From dcce636d1bddb20381e574a0d5b7fd177f4fdc22 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 16 Oct 2024 08:08:49 +0200 Subject: [PATCH 01/54] update loads. Signed-off-by: marquesja1 --- .../cgmes/completion/CgmesCompletionTest.java | 10 +- .../com/powsybl/cgmes/conversion/Context.java | 19 + .../powsybl/cgmes/conversion/Conversion.java | 77 ++++- .../com/powsybl/cgmes/conversion/Update.java | 102 ++++++ ...AbstractConductingEquipmentConversion.java | 210 ++++++++++-- .../elements/AbstractObjectConversion.java | 5 + .../AsynchronousMachineConversion.java | 33 +- .../elements/EnergyConsumerConversion.java | 80 +++-- .../elements/EnergySourceConversion.java | 36 +- ...gmesConformity1ModifiedConversionTest.java | 20 +- .../cgmes/model/AbstractCgmesModel.java | 2 +- .../com/powsybl/cgmes/model/CgmesModel.java | 8 + .../triplestore/CgmesModelTripleStore.java | 15 +- .../src/main/resources/CIM100-update.sparql | 36 ++ .../src/main/resources/CIM14-update.sparql | 69 ++++ .../src/main/resources/CIM16-update.sparql | 324 ++++++++++++++++++ .../powsybl/iidm/network/ValidationUtil.java | 6 + .../powsybl/triplestore/api/PropertyBag.java | 12 + .../triplestore/api/TripleStoreOptions.java | 10 + .../impl/rdf4j/TripleStoreRDF4J.java | 63 ++-- 20 files changed, 1022 insertions(+), 115 deletions(-) create mode 100644 cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java create mode 100644 cgmes/cgmes-model/src/main/resources/CIM100-update.sparql create mode 100644 cgmes/cgmes-model/src/main/resources/CIM14-update.sparql create mode 100644 cgmes/cgmes-model/src/main/resources/CIM16-update.sparql diff --git a/cgmes/cgmes-completion/src/test/java/com/powsybl/cgmes/completion/CgmesCompletionTest.java b/cgmes/cgmes-completion/src/test/java/com/powsybl/cgmes/completion/CgmesCompletionTest.java index b61319a8186..f0b58fb896c 100644 --- a/cgmes/cgmes-completion/src/test/java/com/powsybl/cgmes/completion/CgmesCompletionTest.java +++ b/cgmes/cgmes-completion/src/test/java/com/powsybl/cgmes/completion/CgmesCompletionTest.java @@ -11,14 +11,13 @@ import com.google.common.jimfs.Jimfs; import com.powsybl.cgmes.conformity.CgmesConformity1ModifiedCatalog; import com.powsybl.cgmes.conversion.CgmesImport; -import com.powsybl.cgmes.conversion.CgmesModelExtension; -import com.powsybl.cgmes.model.CgmesModel; import com.powsybl.commons.config.InMemoryPlatformConfig; import com.powsybl.commons.datasource.ReadOnlyDataSource; import com.powsybl.computation.ComputationManager; import com.powsybl.computation.local.LocalComputationManager; import com.powsybl.iidm.network.Importers; import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.Switch; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -72,11 +71,10 @@ void miniGridNodeBreakerMissingVoltageLevel() throws IOException { } assertNotNull(network); - // Check that a specific terminal has a voltage level, navigating the CGMES model - CgmesModel cgmes = network.getExtension(CgmesModelExtension.class).getCgmesModel(); + // Check that a specific terminal has a voltage level, navigating the switches String terminalId = "4915762d-133e-4209-8545-2822d095d7cd"; - String voltageLevelId = cgmes.voltageLevel(cgmes.terminal(terminalId), cgmes.isNodeBreaker()); - if (voltageLevelId == null || voltageLevelId.isEmpty()) { + Switch sw = network.getSwitch(terminalId); + if (sw == null || sw.getVoltageLevel().getId() == null) { fail("Missing voltage level for terminal " + terminalId); } } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java index df7f1f4acdd..16b33842697 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java @@ -64,6 +64,7 @@ public Context(CgmesModel cgmes, Config config, Network network, ReportNode repo reactiveCapabilityCurveData = new HashMap<>(); powerTransformerRatioTapChangers = new HashMap<>(); powerTransformerPhaseTapChangers = new HashMap<>(); + cgmesTerminals = new HashMap<>(); } public CgmesModel cgmes() { @@ -100,6 +101,11 @@ public void convertedTerminal(String terminalId, Terminal t, int n, PowerFlow f) } } + public void mappingTerminal(String terminalId, Terminal t, int n) { + // Record the mapping between CGMES and IIDM terminals + terminalMapping().add(terminalId, t, n); + } + private boolean setPQAllowed(Terminal t) { return t.getConnectable().getType() != IdentifiableType.BUSBAR_SECTION; } @@ -205,6 +211,18 @@ public PropertyBags phaseTapChangerTable(String tableId) { return phaseTapChangerTables.get(tableId); } + public void loadCgmesTerminals() { + cgmes.terminals().forEach(p -> { + String id = p.getId(CgmesNames.TERMINAL); + cgmesTerminals.put(id, p); + }); + + } + + public PropertyBag cgmesTerminal(String id) { + return cgmesTerminals.get(id); + } + // Handling issues found during conversion public ReportNode getReportNode() { @@ -318,6 +336,7 @@ private static void logIssue(ConversionIssueCategory category, String what, Supp private final Map reactiveCapabilityCurveData; private final Map powerTransformerRatioTapChangers; private final Map powerTransformerPhaseTapChangers; + private final Map cgmesTerminals; private static final Logger LOG = LoggerFactory.getLogger(Context.class); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java index 84b63d2bba4..7e750c4bf2f 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java @@ -37,6 +37,7 @@ import java.util.stream.Stream; import static com.powsybl.cgmes.conversion.Conversion.Config.StateProfile.SSH; +import static com.powsybl.cgmes.conversion.Update.updateLoads; import static java.util.stream.Collectors.groupingBy; /** @@ -158,7 +159,14 @@ public Network convert(ReportNode reportNode) { // Create base network with metadata information Network network = createNetwork(); - Context context = createContext(network, reportNode); + network.setMinimumAcceptableValidationLevel(ValidationLevel.EQUIPMENT); + + // FIXME(Luma) we are not reusing conversion objects, + // so it is safe to store the context as an attribute for later use in update + // to do things right the context should have been created in the constructor, + // together with the empty network + this.context = createContext(network, reportNode); + assignNetworkProperties(context); addMetadataModels(network, context); addCimCharacteristics(network); @@ -276,9 +284,50 @@ public Network convert(ReportNode reportNode) { } CgmesReports.importedCgmesNetworkReport(reportNode, network.getId()); + + // FIXME(Luma) in the first step, the Conversion object has used only info from EQ, + // we call the update method on the same conversion object, + // that has the context created during the convert (first) step + // and all the data already loaded in the triplestore, + // we only need to switch to a different set of queries + updateAfterConvert(network, context, reportNode); + return network; } + private void updateAfterConvert(Network network, Context convertContext, ReportNode reportNode) { + // FIXME(Luma) Before switching to update we must invalidate all caches of the cgmes model + // and change the query catalog to "update" mode + + this.cgmes.invalidateCaches(); + this.cgmes.setQueryCatalog("-update"); + Context context = createUpdateContext(network, reportNode); + + // add processes to create new equipment using update data (ssh and sv data) + + update(network, context); + } + + public void update(Network network, ReportNode reportNode) { + Objects.requireNonNull(network); + Objects.requireNonNull(reportNode); + Context context = createUpdateContext(network, reportNode); + update(network, context); + network.setMinimumAcceptableValidationLevel(ValidationLevel.STEADY_STATE_HYPOTHESIS); + } + + private void update(Network network, Context context) { + // FIXME(Luma) Inspect the contents of the loaded data + if (LOG.isDebugEnabled()) { + PropertyBags nts = cgmes.numObjectsByType(); + LOG.debug("CGMES objects read for the update:"); + nts.forEach(nt -> LOG.debug(String.format(" %5d %s", nt.asInt("numObjects"), nt.getLocal("Type")))); + nts.forEach(nt -> LOG.debug(cgmes.allObjectsOfType(nt.getLocal("Type")).tabulateLocals())); + } + + updateLoads(network, cgmes, context); + } + /** * Retrieve the Collection of OperationalLimitGroups for identifiable that have flow limits * (branch, dangling line, 3w-transformer). @@ -480,6 +529,12 @@ private Context createContext(Network network, ReportNode reportNode) { return context; } + private Context createUpdateContext(Network network, ReportNode reportNode) { + Context context = new Context(cgmes, config, network, reportNode); + context.loadCgmesTerminals(); + return context; + } + private void assignNetworkProperties(Context context) { context.network().setProperty(NETWORK_PS_CGMES_MODEL_DETAIL, context.nodeBreaker() @@ -913,6 +968,13 @@ public enum StateProfile { SV } + public enum DefaultValue { + EQ, + ZERO, + NAN, + PREVIOUS + } + public List substationIdsExcludedFromMapping() { return Collections.emptyList(); } @@ -1107,6 +1169,14 @@ public boolean disconnectNetworkSideOfDanglingLinesIfBoundaryIsDisconnected() { return disconnectNetworkSideOfDanglingLinesIfBoundaryIsDisconnected; } + public boolean updateTerminalConnectionInNodeBreakerVoltageLevel() { + return updateTerminalConnectionInNodeBreakerVoltageLevel; + } + + public List updateDefaultValuesPriority() { + return updateDefaultValuesPriority; + } + private boolean convertBoundary = false; private boolean createBusbarSectionForEveryConnectivityNode = false; @@ -1135,6 +1205,10 @@ public boolean disconnectNetworkSideOfDanglingLinesIfBoundaryIsDisconnected() { private Xfmr3StructuralRatioInterpretationAlternative xfmr3StructuralRatio = Xfmr3StructuralRatioInterpretationAlternative.STAR_BUS_SIDE; private double missingPermanentLimitPercentage = 100; + + private final boolean updateTerminalConnectionInNodeBreakerVoltageLevel = false; + + private final List updateDefaultValuesPriority = List.of(DefaultValue.NAN, DefaultValue.EQ); } private final CgmesModel cgmes; @@ -1142,6 +1216,7 @@ public boolean disconnectNetworkSideOfDanglingLinesIfBoundaryIsDisconnected() { private final List postProcessors; private final List preProcessors; private final NetworkFactory networkFactory; + private Context context; private static final Logger LOG = LoggerFactory.getLogger(Conversion.class); diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java new file mode 100644 index 00000000000..d6a8c407dd8 --- /dev/null +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.cgmes.conversion; + +import com.powsybl.cgmes.conversion.elements.AsynchronousMachineConversion; +import com.powsybl.cgmes.conversion.elements.EnergyConsumerConversion; +import com.powsybl.cgmes.conversion.elements.EnergySourceConversion; +import com.powsybl.cgmes.model.CgmesModel; +import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.iidm.network.Connectable; +import com.powsybl.iidm.network.Identifiable; +import com.powsybl.iidm.network.Load; +import com.powsybl.iidm.network.Network; +import com.powsybl.triplestore.api.PropertyBag; +import com.powsybl.triplestore.api.PropertyBags; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +/** + * @author Luma Zamarreño {@literal } + * @author José Antonio Marqués {@literal } + */ + +public final class Update { + + private Update() { + } + + public static boolean isConvertSeparatedFromUpdate(PropertyBag p) { + return p.propertyNames().contains("EnergyConsumer") + || p.propertyNames().contains("ConformLoad") + || p.propertyNames().contains("NonConformLoad") + || p.propertyNames().contains("ConformLoad") + || p.propertyNames().contains("StationSupply") + || p.propertyNames().contains("AsynchronousMachine"); + } + + static void updateLoads(Network network, CgmesModel cgmes, Context context) { + Map identifiablePropertyBag = new HashMap<>(); + addPropertyBags(network, cgmes.energyConsumers(), CgmesNames.ENERGY_CONSUMER, identifiablePropertyBag); + addPropertyBags(network, cgmes.energySources(), CgmesNames.ENERGY_SOURCE, identifiablePropertyBag); + addPropertyBags(network, cgmes.asynchronousMachines(), CgmesNames.ASYNCHRONOUS_MACHINE, identifiablePropertyBag); + + network.getLoads().forEach(load -> updateLoad(network, load, getPropertyBag(load.getId(), identifiablePropertyBag), context)); + } + + private static void updateLoad(Network network, Load load, PropertyBag propertyBag, Context context) { + if (!load.isFictitious()) { // Loads from SvInjections are fictitious + String originalClass = load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS); + PropertyBag cgmesTerminal = getPropertyBagOfCgmesTerminal(load, context); + + switch (originalClass) { + case CgmesNames.ENERGY_SOURCE -> new EnergySourceConversion(propertyBag, cgmesTerminal, load, context).update(network); + case CgmesNames.ASYNCHRONOUS_MACHINE -> + new AsynchronousMachineConversion(propertyBag, cgmesTerminal, load, context).update(network); + case CgmesNames.CONFORM_LOAD, CgmesNames.NONCONFORM_LOAD, CgmesNames.STATION_SUPPLY, CgmesNames.ENERGY_CONSUMER -> + new EnergyConsumerConversion(propertyBag, cgmesTerminal, load, context).update(network); + default -> + throw new ConversionException("Unexpected originalClass " + originalClass + " for Load: " + load.getId()); + } + } + } + + private static void addPropertyBags(Network network, PropertyBags propertyBags, String idTag, Map identifiablePropertyBag) { + propertyBags.forEach(propertyBag -> { + String propertyBagId = propertyBag.getId(idTag); + Identifiable identifiable = network.getIdentifiable(propertyBagId); + if (identifiable != null) { + identifiablePropertyBag.put(identifiable.getId(), propertyBag); + } + }); + } + + private static PropertyBag getPropertyBag(String identifiableId, Map identifiablePropertyBag) { + return identifiablePropertyBag.containsKey(identifiableId) ? identifiablePropertyBag.get(identifiableId) : emptyPropertyBag(); + } + + private static PropertyBag getPropertyBagOfCgmesTerminal(Connectable connectable, Context context) { + Optional cgmesTerminalId = connectable.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL1); + if (cgmesTerminalId.isPresent()) { + return getPropertyBagOfCgmesTerminal(cgmesTerminalId.get(), context); + } else { + return emptyPropertyBag(); + } + } + + private static PropertyBag getPropertyBagOfCgmesTerminal(String cgmesTerminalId, Context context) { + return context.cgmesTerminal(cgmesTerminalId) != null ? context.cgmesTerminal(cgmesTerminalId) : emptyPropertyBag(); + } + + private static PropertyBag emptyPropertyBag() { + return new PropertyBag(Collections.emptyList(), false); + } +} diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index 85ad9983d1d..1204e52e8a4 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -26,55 +26,69 @@ import java.util.List; import java.util.Optional; +import java.util.OptionalDouble; + +import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.NAN; +import static com.powsybl.cgmes.conversion.Update.isConvertSeparatedFromUpdate; /** * @author Luma Zamarreño {@literal } *

* A ConductingEquipment has at least one Terminal. From the Terminal we - * get either its ConnectivityNode or its TopologicalNode, depending of + * get either its ConnectivityNode or its TopologicalNode, depending on * the conversion context */ public abstract class AbstractConductingEquipmentConversion extends AbstractIdentifiedObjectConversion { protected AbstractConductingEquipmentConversion( - String type, - PropertyBag p, - Context context) { + String type, + PropertyBag p, + Context context) { super(type, p, context); - numTerminals = 1; - terminals = new TerminalData[] {null, null, null}; - terminals[0] = new TerminalData(CgmesNames.TERMINAL, p, context); - steadyStatePowerFlow = new PowerFlow(p, "p", "q"); + if (isConvertSeparatedFromUpdate(p)) { + numTerminals = 1; + terminals = new TerminalData[]{null, null, null}; + terminals[0] = new TerminalData(CgmesNames.TERMINAL, p, context); + steadyStatePowerFlow = null; + updatedTerminals = null; + } else { + numTerminals = 1; + terminals = new TerminalData[]{null, null, null}; + terminals[0] = new TerminalData(CgmesNames.TERMINAL, p, context); + steadyStatePowerFlow = new PowerFlow(p, "p", "q"); + updatedTerminals = null; + } } protected AbstractConductingEquipmentConversion( - String type, - PropertyBag p, - Context context, - int numTerminals) { + String type, + PropertyBag p, + Context context, + int numTerminals) { super(type, p, context); // Information about each terminal is in properties of the unique property bag if (numTerminals > 3) { throw new IllegalArgumentException("Invalid number of terminals at " + id + ": " + numTerminals); } - terminals = new TerminalData[] {null, null, null}; + terminals = new TerminalData[]{null, null, null}; this.numTerminals = numTerminals; for (int k = 1; k <= numTerminals; k++) { int k0 = k - 1; terminals[k0] = new TerminalData(CgmesNames.TERMINAL + k, p, context); } steadyStatePowerFlow = PowerFlow.UNDEFINED; + updatedTerminals = null; } protected AbstractConductingEquipmentConversion( - String type, - PropertyBags ps, - Context context) { + String type, + PropertyBags ps, + Context context) { super(type, ps, context); // Information about each terminal is in each separate property bags // It is assumed the property bags are already sorted this.numTerminals = ps.size(); - terminals = new TerminalData[] {null, null, null}; + terminals = new TerminalData[]{null, null, null}; if (numTerminals > 3) { throw new IllegalStateException("numTerminals should be less or equal to 3 but is " + numTerminals); } @@ -83,6 +97,20 @@ protected AbstractConductingEquipmentConversion( terminals[k0] = new TerminalData(CgmesNames.TERMINAL, ps.get(k0), context); } steadyStatePowerFlow = PowerFlow.UNDEFINED; + updatedTerminals = null; + } + + protected AbstractConductingEquipmentConversion( + String type, + PropertyBag p, + PropertyBag cgmesTerminal, + Context context) { + super(type, p, context); + numTerminals = 1; + terminals = null; + steadyStatePowerFlow = new PowerFlow(p, "p", "q"); + updatedTerminals = new UpdatedTerminalData[]{null, null, null}; + updatedTerminals[0] = new UpdatedTerminalData(cgmesTerminal); } public String findPairingKey(String boundaryNode) { @@ -141,9 +169,9 @@ public boolean valid() { } if (voltageLevel(k).isEmpty()) { missing(String.format("VoltageLevel of terminal %d %s (iidm %s)", - k, - cgmesVoltageLevelId(k), - iidmVoltageLevelId(k))); + k, + cgmesVoltageLevelId(k), + iidmVoltageLevelId(k))); return false; } } @@ -174,14 +202,14 @@ String terminalId(int n) { protected String nodeId() { return context.nodeBreaker() - ? terminals[0].t.connectivityNode() - : terminals[0].t.topologicalNode(); + ? terminals[0].t.connectivityNode() + : terminals[0].t.topologicalNode(); } protected String nodeId(int n) { return context.nodeBreaker() - ? terminals[n - 1].t.connectivityNode() - : terminals[n - 1].t.topologicalNode(); + ? terminals[n - 1].t.connectivityNode() + : terminals[n - 1].t.topologicalNode(); } protected String topologicalNodeId(int n) { @@ -223,8 +251,8 @@ public DanglingLine convertToDanglingLine(String eqInstance, int boundarySide, d // ends in a boundary node where there is no other line, // does not have energy consumer or equivalent injection if (terminalConnected(boundarySide) - && !context.boundary().hasPowerFlow(boundaryNode) - && context.boundary().equivalentInjectionsAtNode(boundaryNode).isEmpty()) { + && !context.boundary().hasPowerFlow(boundaryNode) + && context.boundary().equivalentInjectionsAtNode(boundaryNode).isEmpty()) { missing("Equipment for modeling consumption/injection at boundary node"); } @@ -256,7 +284,7 @@ public DanglingLine convertToDanglingLine(String eqInstance, int boundarySide, d dl.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "Terminal", terminalId(boundarySide == 1 ? 2 : 1)); // TODO: delete when aliases are correctly handled by mergedlines Optional.ofNullable(topologicalNodeId(boundarySide)).ifPresent(tn -> dl.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TOPOLOGICAL_NODE_BOUNDARY, tn)); Optional.ofNullable(connectivityNodeId(boundarySide)).ifPresent(cn -> - dl.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.CONNECTIVITY_NODE_BOUNDARY, cn) + dl.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.CONNECTIVITY_NODE_BOUNDARY, cn) ); setBoundaryNodeInfo(boundaryNode, dl); // In a Dangling Line the CGMES side and the IIDM side may not be the same @@ -264,12 +292,12 @@ public DanglingLine convertToDanglingLine(String eqInstance, int boundarySide, d // We do not have SSH values at the model side, it is a line flow. We take directly SV values context.convertedTerminal(terminalId(modelSide), dl.getTerminal(), 1, powerFlowSV(modelSide)); - // If we do not have power flow at model side and we can compute it, + // If we do not have power flow at model side, and we can compute it, // do it and assign the result at the terminal of the dangling line if (context.config().computeFlowsAtBoundaryDanglingLines() - && terminalConnected(modelSide) - && !powerFlowSV(modelSide).defined() - && context.boundary().hasVoltage(boundaryNode)) { + && terminalConnected(modelSide) + && !powerFlowSV(modelSide).defined() + && context.boundary().hasVoltage(boundaryNode)) { if (isZ0(dl)) { // Flow out must be equal to the consumption seen at boundary @@ -369,7 +397,7 @@ private static Optional getEquivalentInjectionCon } else if (eis.size() == 1) { return Optional.of(new EquivalentInjectionConversion(eis.get(0), context)); } else { - // Select the EI thas is defined in the same EQ instance of the given line + // Select the EI that is defined in the same EQ instance of the given line String eqInstancePropertyName = "graph"; List eisEqInstance = eis.stream().filter(eik -> eik.getId(eqInstancePropertyName).equals(eqInstance)).toList(); @@ -455,6 +483,10 @@ private PowerFlow stateVariablesPowerFlow() { return terminals[0].t.flow(); } + private PowerFlow updatedStateVariablesPowerFlow() { + return new PowerFlow(updatedTerminals[0].cgmesTerminal, "p", "q"); + } + public PowerFlow stateVariablesPowerFlow(int n) { return terminals[n - 1].t.flow(); } @@ -463,6 +495,10 @@ private PowerFlow steadyStateHypothesisPowerFlow() { return steadyStatePowerFlow; } + private PowerFlow updatedSteadyStateHypothesisPowerFlow() { + return steadyStatePowerFlow; + } + PowerFlow powerFlow() { if (steadyStateHypothesisPowerFlow().defined()) { return steadyStateHypothesisPowerFlow(); @@ -473,6 +509,16 @@ PowerFlow powerFlow() { return PowerFlow.UNDEFINED; } + PowerFlow updatedPowerFlow() { + if (updatedSteadyStateHypothesisPowerFlow().defined()) { + return updatedSteadyStateHypothesisPowerFlow(); + } + if (updatedStateVariablesPowerFlow().defined()) { + return updatedStateVariablesPowerFlow(); + } + return PowerFlow.UNDEFINED; + } + PowerFlow powerFlowSV() { if (stateVariablesPowerFlow().defined()) { return stateVariablesPowerFlow(); @@ -500,6 +546,58 @@ protected void convertedTerminals(Terminal... ts) { } } + protected void mappingTerminals(Terminal... ts) { + if (ts.length != numTerminals) { + throw new IllegalStateException(); + } + for (int k = 0; k < ts.length; k++) { + int n = k + 1; + Terminal t = ts[k]; + context.mappingTerminal(terminalId(n), t, n); + } + } + + protected void updateTerminals(Context context, Terminal... ts) { + if (ts.length != numTerminals) { + throw new IllegalStateException(); + } + for (int k = 0; k < ts.length; k++) { + updateTerminal(updatedTerminals[k].cgmesTerminal, ts[k], context); + } + } + + private static void updateTerminal(PropertyBag cgmesTerminal, Terminal terminal, Context context) { + if (updateConnect(terminal, context)) { + boolean connectedInUpdate = cgmesTerminal.asBoolean("connected", true); + if (terminal.isConnected() != connectedInUpdate) { + if (connectedInUpdate) { + terminal.connect(); + } else { + terminal.disconnect(); + } + } + } + if (setPQAllowed(terminal)) { + PowerFlow f = new PowerFlow(cgmesTerminal, "p", "q"); + if (f.defined()) { + terminal.setP(f.p()); + terminal.setQ(f.q()); + } + } + } + + private static boolean updateConnect(Terminal terminal, Context context) { + if (terminal.getVoltageLevel().getTopologyKind().equals(TopologyKind.NODE_BREAKER)) { + return context.config().updateTerminalConnectionInNodeBreakerVoltageLevel(); + } else { + return true; + } + } + + private static boolean setPQAllowed(Terminal t) { + return t.getConnectable().getType() != IdentifiableType.BUSBAR_SECTION; + } + private final int numTerminals; static class TerminalData { @@ -538,7 +636,14 @@ static class TerminalData { } } - // Connections + static class UpdatedTerminalData { + private final PropertyBag cgmesTerminal; + + UpdatedTerminalData(PropertyBag cgmesTerminal) { + this.cgmesTerminal = cgmesTerminal; + } + } + // Connections public void connect(InjectionAdder adder) { if (context.nodeBreaker()) { @@ -548,6 +653,14 @@ public void connect(InjectionAdder adder) { } } + public void connection(InjectionAdder adder) { + if (context.nodeBreaker()) { + adder.setNode(iidmNode()); + } else { + adder.setBus(null).setConnectableBus(busId()); + } + } + public void connect(InjectionAdder adder, int terminal) { if (context.nodeBreaker()) { adder.setNode(iidmNode(terminal)); @@ -682,6 +795,37 @@ protected double q0() { return powerFlow().defined() ? powerFlow().q() : 0.0; } + protected OptionalDouble updatedP0() { + return updatedPowerFlow().defined() ? OptionalDouble.of(updatedPowerFlow().p()) : OptionalDouble.empty(); + } + + protected OptionalDouble qupdatedQ0() { + return updatedPowerFlow().defined() ? OptionalDouble.of(updatedPowerFlow().q()) : OptionalDouble.empty(); + } + + protected static Conversion.Config.DefaultValue selectDefaultValue(List validDefaultValues, Context context) { + return context.config().updateDefaultValuesPriority().stream().filter(validDefaultValues::contains).findFirst().orElse(NAN); + } + + protected static double defaultP(double eqP, double previousP, Conversion.Config.DefaultValue defaultValue) { + return switch (defaultValue) { + case EQ -> eqP; + case PREVIOUS -> previousP; + case ZERO -> 0.0; + case NAN -> Double.NaN; + }; + } + + protected static double defaultQ(double eqQ, double previousQ, Conversion.Config.DefaultValue defaultValue) { + return switch (defaultValue) { + case EQ -> eqQ; + case PREVIOUS -> previousQ; + case ZERO -> 0.0; + case NAN -> Double.NaN; + }; + } + private final TerminalData[] terminals; private final PowerFlow steadyStatePowerFlow; + private final UpdatedTerminalData[] updatedTerminals; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java index 0b6945c1acf..d456212a54f 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java @@ -10,6 +10,7 @@ import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.ConversionException; +import com.powsybl.iidm.network.Network; import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; @@ -47,6 +48,10 @@ public void convertInsideBoundary() { public abstract void convert(); + public void update(Network network) { + throw new ConversionException("Missing implementation: update for " + type); + } + public abstract String what(); protected abstract String complete(String what); diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java index 36a5d2306c2..4c2706a268e 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java @@ -14,8 +14,15 @@ import com.powsybl.iidm.network.Load; import com.powsybl.iidm.network.LoadAdder; import com.powsybl.iidm.network.LoadType; +import com.powsybl.iidm.network.Network; import com.powsybl.triplestore.api.PropertyBag; +import java.util.List; +import java.util.Objects; + +import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; +import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.NAN; + /** * @author Luma Zamarreño {@literal } */ @@ -23,6 +30,12 @@ public class AsynchronousMachineConversion extends AbstractConductingEquipmentCo public AsynchronousMachineConversion(PropertyBag asm, Context context) { super(CgmesNames.ASYNCHRONOUS_MACHINE, asm, context); + this.load = null; + } + + public AsynchronousMachineConversion(PropertyBag es, PropertyBag cgmesTerminal, Load load, Context context) { + super(CgmesNames.ASYNCHRONOUS_MACHINE, es, cgmesTerminal, context); + this.load = load; } @Override @@ -31,21 +44,33 @@ public void convert() { // We make no difference based on the type (motor/generator) LoadType loadType = id.contains("fict") ? LoadType.FICTITIOUS : LoadType.UNDEFINED; LoadAdder adder = voltageLevel().newLoad() - .setP0(p0()) - .setQ0(q0()) .setLoadType(loadType); identify(adder); - connect(adder); + connection(adder); Load load = adder.add(); addAliasesAndProperties(load); - convertedTerminals(load.getTerminal()); + mappingTerminals(load.getTerminal()); addSpecificProperties(load); } + @Override + public void update(Network network) { + Objects.requireNonNull(load); + updateTerminals(context, load.getTerminal()); + load.setP0(updatedP0().orElse(defaultP(Double.NaN, load.getP0(), gettDefaultValue(context)))) + .setQ0(qupdatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), gettDefaultValue(context)))); + } + private static void addSpecificProperties(Load load) { load.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ASYNCHRONOUS_MACHINE); } + + private static Conversion.Config.DefaultValue gettDefaultValue(Context context) { + return selectDefaultValue(List.of(PREVIOUS, ZERO, NAN), context); + } + + private final Load load; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index 099d0a6eb17..34c4a965a89 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -11,13 +11,16 @@ import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.model.CgmesNames; -import com.powsybl.iidm.network.Load; -import com.powsybl.iidm.network.LoadAdder; -import com.powsybl.iidm.network.LoadType; -import com.powsybl.iidm.network.ZipLoadModelAdder; +import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.extensions.LoadDetail; import com.powsybl.iidm.network.extensions.LoadDetailAdder; import com.powsybl.triplestore.api.PropertyBag; +import java.util.List; +import java.util.Objects; + +import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; + /** * @author Luma Zamarreño {@literal } */ @@ -26,6 +29,13 @@ public class EnergyConsumerConversion extends AbstractConductingEquipmentConvers public EnergyConsumerConversion(PropertyBag ec, Context context) { super(CgmesNames.ENERGY_CONSUMER, ec, context); loadKind = ec.getLocal("type"); + this.load = null; + } + + public EnergyConsumerConversion(PropertyBag es, PropertyBag cgmesTerminal, Load load, Context context) { + super(CgmesNames.ENERGY_CONSUMER, es, cgmesTerminal, context); + this.loadKind = null; + this.load = load; } @Override @@ -38,23 +48,25 @@ public void convert() { } else { loadType = LoadType.UNDEFINED; } + double pFixed = p.asDouble("pFixed", 0.0); + double qFixed = p.asDouble("qFixed", 0.0); LoadAdder adder = voltageLevel().newLoad() - .setP0(p0()) - .setQ0(q0()) .setLoadType(loadType); identify(adder); - connect(adder); + connection(adder); model(adder); Load load = adder.add(); addAliasesAndProperties(load); - convertedTerminals(load.getTerminal()); - setLoadDetail(loadKind, load); + mappingTerminals(load.getTerminal()); + setLoadDetail(loadKind, load, pFixed, qFixed); - addSpecificProperties(load, loadKind); + addSpecificProperties(load, loadKind, pFixed, qFixed); } - private static void addSpecificProperties(Load load, String loadKind) { + private static void addSpecificProperties(Load load, String loadKind, double pFixed, double qFixed) { load.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, loadKind); + load.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "pFixed", String.valueOf(pFixed)); + load.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "qFixed", String.valueOf(qFixed)); } private void model(LoadAdder adder) { @@ -115,18 +127,18 @@ private void addZipModel(LoadAdder adder) { } } - private static void setLoadDetail(String type, Load load) { + private static void setLoadDetail(String type, Load load, double pFixed, double qFixed) { if (type.equals("ConformLoad")) { // ConformLoad represent loads that follow a daily load change pattern where the pattern can be used to scale the load with a system load load.newExtension(LoadDetailAdder.class) .withFixedActivePower(0) .withFixedReactivePower(0) - .withVariableActivePower((float) load.getP0()) - .withVariableReactivePower((float) load.getQ0()) + .withVariableActivePower((float) pFixed) + .withVariableReactivePower((float) qFixed) .add(); } else if (type.equals("NonConformLoad")) { // does not participate in scaling load.newExtension(LoadDetailAdder.class) - .withFixedActivePower((float) load.getP0()) - .withFixedReactivePower((float) load.getQ0()) + .withFixedActivePower((float) pFixed) + .withFixedReactivePower((float) qFixed) .withVariableActivePower(0) .withVariableReactivePower(0) .add(); @@ -135,14 +147,40 @@ private static void setLoadDetail(String type, Load load) { } @Override - protected double p0() { - return powerFlow().defined() ? powerFlow().p() : p.asDouble("pFixed", 0.0); + public void update(Network network) { + Objects.requireNonNull(load); + updateTerminals(context, load.getTerminal()); + + double pFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "pFixed")); + double qFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "qFixed")); + load.setP0(updatedP0().orElse(defaultP(pFixed, load.getP0(), getDefaultValue(context)))) + .setQ0(qupdatedQ0().orElse(defaultQ(qFixed, load.getQ0(), getDefaultValue(context)))); + + String loadKind = load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS); + updateLoadDetail(loadKind, load, pFixed, qFixed); } - @Override - protected double q0() { - return powerFlow().defined() ? powerFlow().q() : p.asDouble("qFixed", 0.0); + private static Conversion.Config.DefaultValue getDefaultValue(Context context) { + return selectDefaultValue(List.of(EQ, PREVIOUS, ZERO, NAN), context); + } + + private static void updateLoadDetail(String type, Load load, double pFixed, double qFixed) { + if (type == null) { + return; + } + LoadDetail loadDetail = load.getExtension(LoadDetail.class); + if (loadDetail == null) { + return; + } + if (type.equals("ConformLoad")) { // ConformLoad represent loads that follow a daily load change pattern where the pattern can be used to scale the load with a system load + loadDetail.setVariableActivePower(Double.isFinite(load.getP0()) ? (float) load.getP0() : (float) pFixed) + .setVariableReactivePower(Double.isFinite(load.getQ0()) ? (float) load.getQ0() : (float) qFixed); + } else if (type.equals("NonConformLoad")) { // does not participate in scaling + loadDetail.setFixedActivePower(Double.isFinite(load.getP0()) ? (float) load.getP0() : (float) pFixed) + .setFixedReactivePower(Double.isFinite(load.getQ0()) ? (float) load.getQ0() : (float) qFixed); + } } private final String loadKind; + private final Load load; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java index 24159aa375b..870597978ab 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java @@ -11,18 +11,26 @@ import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.model.CgmesNames; -import com.powsybl.iidm.network.Load; -import com.powsybl.iidm.network.LoadAdder; -import com.powsybl.iidm.network.LoadType; +import com.powsybl.iidm.network.*; import com.powsybl.triplestore.api.PropertyBag; +import java.util.List; +import java.util.Objects; + +import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; + /** * @author Luma Zamarreño {@literal } */ public class EnergySourceConversion extends AbstractConductingEquipmentConversion { - public EnergySourceConversion(PropertyBag es, Context context) { super(CgmesNames.ENERGY_SOURCE, es, context); + this.load = null; + } + + public EnergySourceConversion(PropertyBag es, PropertyBag cgmesTerminal, Load load, Context context) { + super(CgmesNames.ENERGY_SOURCE, es, cgmesTerminal, context); + this.load = load; } @Override @@ -30,14 +38,12 @@ public void convert() { LoadType loadType = id.contains("fict") ? LoadType.FICTITIOUS : LoadType.UNDEFINED; LoadAdder adder = voltageLevel().newLoad() - .setP0(p0()) - .setQ0(q0()) .setLoadType(loadType); identify(adder); - connect(adder); + connection(adder); Load load = adder.add(); addAliasesAndProperties(load); - convertedTerminals(load.getTerminal()); + mappingTerminals(load.getTerminal()); addSpecificProperties(load); } @@ -45,4 +51,18 @@ public void convert() { private static void addSpecificProperties(Load load) { load.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ENERGY_SOURCE); } + + @Override + public void update(Network network) { + Objects.requireNonNull(load); + updateTerminals(context, load.getTerminal()); + load.setP0(updatedP0().orElse(defaultP(Double.NaN, load.getP0(), getDefaultValue(context)))) + .setQ0(qupdatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), getDefaultValue(context)))); + } + + private static Conversion.Config.DefaultValue getDefaultValue(Context context) { + return selectDefaultValue(List.of(PREVIOUS, ZERO, NAN), context); + } + + private final Load load; } diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/conformity/modified/CgmesConformity1ModifiedConversionTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/conformity/modified/CgmesConformity1ModifiedConversionTest.java index ce19719bc92..0e39bc2a69b 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/conformity/modified/CgmesConformity1ModifiedConversionTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/conformity/modified/CgmesConformity1ModifiedConversionTest.java @@ -29,6 +29,7 @@ import com.powsybl.iidm.network.extensions.ReferencePriorities; import com.powsybl.iidm.network.extensions.ReferencePriority; import com.powsybl.triplestore.api.PropertyBags; +import com.powsybl.triplestore.api.TripleStoreFactory; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -990,20 +991,21 @@ void microGridBaseCaseBESingleFile() { @Test void smallNodeBreakerHvdcNoSequenceNumbers() { - Network networkSeq = Importers.importData("CGMES", CgmesConformity1Catalog.smallNodeBreakerHvdc().dataSource(), importParams); - Network networkNoSeq = Importers.importData("CGMES", CgmesConformity1ModifiedCatalog.smallNodeBreakerHvdcNoSequenceNumbers().dataSource(), importParams); - // Make sure we have not lost any line, switch - assertEquals(networkSeq.getLineCount(), networkNoSeq.getLineCount()); - assertEquals(networkSeq.getSwitchCount(), networkNoSeq.getSwitchCount()); - assertEquals(networkSeq.getHvdcLineCount(), networkNoSeq.getHvdcLineCount()); + CgmesModel cgmesSeq = CgmesModelFactory.create(CgmesConformity1Catalog.smallNodeBreakerHvdc().dataSource(), TripleStoreFactory.DEFAULT_IMPLEMENTATION); + CgmesModel cgmesNoSeq = CgmesModelFactory.create(CgmesConformity1ModifiedCatalog.smallNodeBreakerHvdcNoSequenceNumbers().dataSource(), TripleStoreFactory.DEFAULT_IMPLEMENTATION); - // Check terminal ids have been sorted properly - CgmesModel cgmesSeq = networkSeq.getExtension(CgmesModelExtension.class).getCgmesModel(); - CgmesModel cgmesNoSeq = networkNoSeq.getExtension(CgmesModelExtension.class).getCgmesModel(); checkTerminals(cgmesSeq.acLineSegments(), cgmesNoSeq.acLineSegments(), "ACLineSegment", "Terminal1", "Terminal2"); checkTerminals(cgmesSeq.switches(), cgmesNoSeq.switches(), "Switch", "Terminal1", "Terminal2"); checkTerminals(cgmesSeq.seriesCompensators(), cgmesNoSeq.seriesCompensators(), "SeriesCompensator", "Terminal1", "Terminal2"); checkTerminals(cgmesSeq.dcLineSegments(), cgmesNoSeq.dcLineSegments(), "DCLineSegment", "DCTerminal1", "DCTerminal2"); + + // Make sure we have not lost any line, switch + Network networkSeq = Importers.importData("CGMES", CgmesConformity1Catalog.smallNodeBreakerHvdc().dataSource(), importParams); + Network networkNoSeq = Importers.importData("CGMES", CgmesConformity1ModifiedCatalog.smallNodeBreakerHvdcNoSequenceNumbers().dataSource(), importParams); + + assertEquals(networkSeq.getLineCount(), networkNoSeq.getLineCount()); + assertEquals(networkSeq.getSwitchCount(), networkNoSeq.getSwitchCount()); + assertEquals(networkSeq.getHvdcLineCount(), networkNoSeq.getHvdcLineCount()); } @Test diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/AbstractCgmesModel.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/AbstractCgmesModel.java index 1ccbd7dc77b..81d0e76abcb 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/AbstractCgmesModel.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/AbstractCgmesModel.java @@ -269,7 +269,7 @@ public void read(ReadOnlyDataSource ds, ReportNode reportNode) { } } - protected void invalidateCaches() { + public void invalidateCaches() { cachedGroupedTransformerEnds = null; powerTransformerRatioTapChanger = null; powerTransformerPhaseTapChanger = null; diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesModel.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesModel.java index 84057f5c4e1..59db97aab1b 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesModel.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesModel.java @@ -241,4 +241,12 @@ default void write(DataSource ds, CgmesSubset subset) { default PropertyBags modelProfiles() { throw new UnsupportedOperationException(); } + + default void invalidateCaches() { + // Do nothing + } + + default void setQueryCatalog(String s) { + // Do nothing + } } diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/triplestore/CgmesModelTripleStore.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/triplestore/CgmesModelTripleStore.java index 08290fac08e..4bb9a384106 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/triplestore/CgmesModelTripleStore.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/triplestore/CgmesModelTripleStore.java @@ -42,7 +42,7 @@ */ public class CgmesModelTripleStore extends AbstractCgmesModel { - public CgmesModelTripleStore(String cimNamespace, TripleStore tripleStore) { + public CgmesModelTripleStore(String cimNamespace, TripleStore tripleStore, String queryCatalogName) { super(); this.cimNamespace = cimNamespace; this.cimVersion = cimVersionFromCimNamespace(cimNamespace); @@ -50,10 +50,15 @@ public CgmesModelTripleStore(String cimNamespace, TripleStore tripleStore) { tripleStore.defineQueryPrefix("cim", cimNamespace); tripleStore.defineQueryPrefix("entsoe", CgmesNamespace.ENTSOE_NAMESPACE); tripleStore.defineQueryPrefix("eu", CgmesNamespace.EU_NAMESPACE); - queryCatalog = queryCatalogFor(cimVersion); + queryCatalog = queryCatalogFor(cimVersion, queryCatalogName); Objects.requireNonNull(queryCatalog); } + @Override + public void setQueryCatalog(String queryCatalogName) { + this.queryCatalog = queryCatalogFor(this.cimVersion, queryCatalogName); + } + @Override public void read(InputStream is, String baseName, String contextName, ReportNode reportNode) { // Reset cached nodeBreaker value everytime we read new data @@ -768,11 +773,11 @@ private String contextNameFor(CgmesSubset subset) { return modelId() + "_" + subset + ".xml"; } - private QueryCatalog queryCatalogFor(int cimVersion) { + private QueryCatalog queryCatalogFor(int cimVersion, String name) { QueryCatalog qc = null; String resourceName = null; if (cimVersion > 0) { - resourceName = String.format("CIM%d.sparql", cimVersion); + resourceName = String.format("CIM%d%s.sparql", cimVersion, name); } if (resourceName != null) { qc = new QueryCatalog(resourceName); @@ -797,7 +802,7 @@ private String injectParams(String queryText, String... params) { private final String cimNamespace; private final int cimVersion; private final TripleStore tripleStore; - private final QueryCatalog queryCatalog; + private QueryCatalog queryCatalog; private Boolean nodeBreaker = null; private static final String MODEL_PROFILES = "modelProfiles"; diff --git a/cgmes/cgmes-model/src/main/resources/CIM100-update.sparql b/cgmes/cgmes-model/src/main/resources/CIM100-update.sparql new file mode 100644 index 00000000000..29abbfe665a --- /dev/null +++ b/cgmes/cgmes-model/src/main/resources/CIM100-update.sparql @@ -0,0 +1,36 @@ +# +# Copyright (c) 2021, RTE (http://www.rte-france.com) +# 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/. +# SPDX-License-Identifier: MPL-2.0 +# + +# include: CIM16-update.sparql + +# query: boundaryNodes +# All pairs (Connectiviy Node, Topological Node) from a graph that has a modeProfile EquipmentBoundary- +# We expect all Connectivity Nodes have 1 and only one corresponding TopologicalNode +prefix md: +SELECT * +{ +GRAPH ?graphBDEQ { + ?FullModel md:Model.profile ?modelProfile . + FILTER (regex(?modelProfile, "EquipmentBoundary-", "i")) + ?ConnectivityNode + a cim:ConnectivityNode ; + cim:IdentifiedObject.name ?name ; + cim:ConnectivityNode.ConnectivityNodeContainer ?container . + ?BoundaryPoint + a eu:BoundaryPoint ; + eu:BoundaryPoint.ConnectivityNode ?ConnectivityNode . + OPTIONAL { ?BoundaryPoint eu:IdentifiedObject.energyIdentCodeEic ?energyIdentCodeEicFromNode } + OPTIONAL { ?container entsoe:IdentifiedObject.energyIdentCodeEic ?energyIdentCodeEicFromNodeContainer } + OPTIONAL { ?ConnectivityNode cim:IdentifiedObject.description ?description } +} +OPTIONAL { GRAPH ?grapBDTP { + ?ConnectivityNode cim:ConnectivityNode.TopologicalNode ?TopologicalNode . + ?TopologicalNode cim:IdentifiedObject.name ?topologicalNodeName +}} +} + diff --git a/cgmes/cgmes-model/src/main/resources/CIM14-update.sparql b/cgmes/cgmes-model/src/main/resources/CIM14-update.sparql new file mode 100644 index 00000000000..27aec2cc5d3 --- /dev/null +++ b/cgmes/cgmes-model/src/main/resources/CIM14-update.sparql @@ -0,0 +1,69 @@ +# +# Copyright (c) 2017-2018, RTE (http://www.rte-france.com) +# 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/. +# + +# query: graph +SELECT DISTINCT ?graph + WHERE +{ GRAPH ?graph + { ?s ?p ?o } +} + +# query: version +SELECT ?version +{ GRAPH ?graph { + ?versionId cim:IEC61970CIMVersion.version ?version +}} + +# query: numObjectsByType +# Only types in a namespace given as parameter +SELECT ?Type (COUNT (DISTINCT ?object) AS ?numObjects) +{ GRAPH ?graph { + ?object a ?Type . + FILTER (STRSTARTS(STR(?Type), "{0}")) +}} +GROUP BY ?Type + +# query: allObjectsOfType +SELECT * +{ GRAPH ?graph { + ?object a cim:{0} ; + ?attribute ?value . +}} + +# query: terminals +# we cannot access the 'inService' Status +SELECT * +{ + ?Terminal + a cim:Terminal ; + cim:Terminal.connected ?connected + OPTIONAL { + ?SvPowerFlow a cim:SvPowerFlow ; + cim:SvPowerFlow.Terminal ?Terminal ; + cim:SvPowerFlow.p ?p ; + cim:SvPowerFlow.q ?q . + } +} + +# query: topologicalNodes +SELECT * +{ + ?TopologicalNode a cim:TopologicalNode . + OPTIONAL { + ?SvVoltage a cim:SvVoltage ; + cim:SvVoltage.TopologicalNode ?TopologicalNode ; + cim:SvVoltage.v ?v ; + cim:SvVoltage.angle ?angle + } + OPTIONAL { + SELECT ?ConnectivityNode + WHERE { + ?ConnectivityNode cim:ConnectivityNode.TopologicalNode ?TopologicalNode + } + LIMIT 1 + } +} diff --git a/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql b/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql new file mode 100644 index 00000000000..1df6a422d0f --- /dev/null +++ b/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql @@ -0,0 +1,324 @@ +# +# Copyright (c) 2024, RTE (http://www.rte-france.com) +# 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/. +# SPDX-License-Identifier: MPL-2.0 +# + +# query: numObjectsByType +# Only types in a namespace given as parameter +SELECT ?Type (COUNT (DISTINCT ?object) AS ?numObjects) +{ GRAPH ?graph { + ?object a ?Type . + FILTER (STRSTARTS(STR(?Type), "{0}")) +}} +GROUP BY ?Type + +# query: allObjectsOfType +SELECT * +{ GRAPH ?graph { + ?object a cim:{0} ; + ?attribute ?value . +}} + +# query: terminals +# we cannot access the 'inService' Status +SELECT * +{ + ?Terminal + a cim:Terminal ; + cim:ACDCTerminal.connected ?connected + OPTIONAL { + ?SvPowerFlow a cim:SvPowerFlow ; + cim:SvPowerFlow.Terminal ?Terminal ; + cim:SvPowerFlow.p ?p ; + cim:SvPowerFlow.q ?q . + } +} + +# query: topologicalIslands +SELECT * +{ + ?TopologicalIsland a cim:TopologicalIsland ; + cim:IdentifiedObject.name ?name ; + cim:TopologicalIsland.AngleRefTopologicalNode ?AngleRefTopologicalNode ; + cim:TopologicalIsland.TopologicalNodes ?TopologicalNodes . +} + +# query: operationalLimits +SELECT * +{ + ?OperationalLimit a ?type ; + VALUES ?type { cim:CurrentLimit cim:ApparentPowerLimit cim:ActivePowerLimit cim:VoltageLimit } . + OPTIONAL { ?OperationalLimit cim:CurrentLimit.value ?value } + OPTIONAL { ?OperationalLimit cim:ApparentPowerLimit.value ?value } + OPTIONAL { ?OperationalLimit cim:ActivePowerLimit.value ?value } + OPTIONAL { ?OperationalLimit cim:VoltageLimit.value ?value } +} + +# query: topologicalNodes +SELECT * +{ + ?TopologicalNode a cim:TopologicalNode . + OPTIONAL { + ?SvVoltage a cim:SvVoltage ; + cim:SvVoltage.TopologicalNode ?TopologicalNode ; + cim:SvVoltage.v ?v ; + cim:SvVoltage.angle ?angle + } + OPTIONAL { + SELECT ?ConnectivityNode + WHERE { + ?ConnectivityNode cim:ConnectivityNode.TopologicalNode ?TopologicalNode + } + LIMIT 1 + } +} + +# query: switches +SELECT * +{ + ?Switch a ?type ; + cim:Switch.open ?open . + VALUES ?type { cim:Switch cim:Breaker cim:Disconnector cim:LoadBreakSwitch cim:ProtectedSwitch cim:GroundDisconnector } +} + +# query: ratioTapChangers +SELECT * +{ + ?RatioTapChanger a cim:RatioTapChanger ; + # FIXME(Luma) return either data from SSH or from SV, but at least some data has to be present to return a row + OPTIONAL { + ?RatioTapChanger + cim:TapChanger.controlEnabled ?tapChangerControlEnabled ; + cim:TapChanger.step ?step + } + OPTIONAL { + ?SvTapStep a cim:SvTapStep ; + cim:SvTapStep.TapChanger ?RatioTapChanger ; + cim:SvTapStep.position ?SVtapStep + } +} + +# query: phaseTapChangers +SELECT * +{ + ?PhaseTapChanger a ?phaseTapChangerType ; + VALUES ?phaseTapChangerType { cim:PhaseTapChangerLinear cim:PhaseTapChangerAsymmetrical cim:PhaseTapChangerNonLinear cim:PhaseTapChangerTabular } . + OPTIONAL { + ?PhaseTapChanger + cim:TapChanger.controlEnabled ?tapChangerControlEnabled ; + cim:TapChanger.step ?step + } + OPTIONAL { + ?SVTapStep a cim:SvTapStep ; + cim:SvTapStep.TapChanger ?PhaseTapChanger ; + cim:SvTapStep.position ?SVtapStep + } +} + +# query: regulatingControls +SELECT * +{ + { + ?RegulatingControl a cim:RegulatingControl + } + UNION + { + ?RegulatingControl a cim:TapChangerControl + } + OPTIONAL { + ?RegulatingControl + cim:RegulatingControl.enabled ?enabled ; + cim:RegulatingControl.targetValue ?targetValue ; + cim:RegulatingControl.targetValueUnitMultiplier ?targetValueUnitMultiplier ; + cim:RegulatingControl.discrete ?discrete . + OPTIONAL { ?RegulatingControl cim:RegulatingControl.targetDeadband ?targetDeadband } + } +} + +# query: energyConsumers +SELECT * +{ + ?EnergyConsumer a ?type ; + cim:EnergyConsumer.p ?p ; + cim:EnergyConsumer.q ?q . + VALUES ?type { cim:EnergyConsumer cim:ConformLoad cim:NonConformLoad cim:StationSupply } +} + +# query: energySources +SELECT * +{ + ?EnergySource a cim:EnergySource ; + cim:EnergySource.activePower ?p ; + cim:EnergySource.reactivePower ?q +} + +# query: shuntCompensators +SELECT * +{ + { + ?ShuntCompensator a ?type ; + VALUES ?type { cim:LinearShuntCompensator cim:NonlinearShuntCompensator } . + } + OPTIONAL { + ?ShuntCompensator + cim:ShuntCompensator.sections ?SSHsections ; + cim:RegulatingCondEq.controlEnabled ?controlEnabled + } + OPTIONAL { + ?SvShuntCompensatorSections + a cim:SvShuntCompensatorSections ; + cim:SvShuntCompensatorSections.ShuntCompensator ?ShuntCompensator ; + cim:SvShuntCompensatorSections.sections ?SVsections + } +} + +# FIXME(Luma) we do not have access to the type when reading update only files, +# we cannot differentiate between generators and condensers +# this means that we may not deprecate synchronousMachines in the end, +# or we could make the new query "allSynchronousMachines" + +# query: allSynchronousMachines +SELECT * +{ + ?SynchronousMachine a cim:SynchronousMachine + # FIXME(Luma) p in a separate optional block because condersers could not define it + OPTIONAL { ?SynchronousMachine cim:RotatingMachine.p ?p } + OPTIONAL { + ?SynchronousMachine + cim:RotatingMachine.q ?q ; + cim:SynchronousMachine.referencePriority ?referencePriority ; + cim:SynchronousMachine.operatingMode ?operatingMode ; + cim:RegulatingCondEq.controlEnabled ?controlEnabled . + # For condensers givin p is optional, + } +} + +# query: generatingUnits +SELECT * +{ + ?GeneratingUnit + a ?generatingUnitType ; + cim:GeneratingUnit.normalPF ?normalPF +} + +# query: equivalentInjections +SELECT * +{ + ?EquivalentInjection a cim:EquivalentInjection ; + cim:EquivalentInjection.p ?p ; + cim:EquivalentInjection.q ?q . + OPTIONAL { ?EquivalentInjection cim:EquivalentInjection.regulationStatus ?regulationStatus } + OPTIONAL { ?EquivalentInjection cim:EquivalentInjection.regulationTarget ?regulationTarget } +} + +# query: svInjections +SELECT ?SvInjection ?TopologicalNode ?pInjection ?qInjection (MIN(?ConnectivityNode) AS ?ConnectivityNode) +{ + ?SvInjection a cim:SvInjection ; + cim:SvInjection.TopologicalNode ?TopologicalNode ; + cim:SvInjection.pInjection ?pInjection . + OPTIONAL { ?SvInjection cim:SvInjection.qInjection ?qInjection } + OPTIONAL { ?ConnectivityNode cim:ConnectivityNode.TopologicalNode ?TopologicalNode } +}GROUP BY ?SvInjection ?TopologicalNode ?pInjection ?qInjection + +# query: externalNetworkInjections +SELECT * +{ + ?ExternalNetworkInjection a cim:ExternalNetworkInjection ; + cim:ExternalNetworkInjection.p ?p ; + cim:ExternalNetworkInjection.q ?q ; + cim:RegulatingCondEq.controlEnabled ?controlEnabled +} + +# query: staticVarCompensators +SELECT * +{ + ?StaticVarCompensator a cim:StaticVarCompensator ; + cim:StaticVarCompensator.q ?q ; + cim:RegulatingCondEq.controlEnabled ?controlEnabled +} + +# query: asynchronousMachines +SELECT * +{ + ?AsynchronousMachine a cim:AsynchronousMachine ; + cim:AsynchronousMachine.asynchronousMachineType ?type ; + cim:RotatingMachine.p ?p ; + cim:RotatingMachine.q ?q ; + cim:RegulatingCondEq.controlEnabled ?controlEnabled +} + +# query: controlAreas +SELECT * +{ + ?ControlArea a cim:ControlArea ; + cim:ControlArea.netInterchange ?netInterchange . + OPTIONAL { ?ControlArea cim:ControlArea.pTolerance ?pTolerance } +} + +# query: acDcConverters +SELECT * +{ + ?ACDCConverter a ?type . + VALUES ?type { cim:ACDCConverter cim:CsConverter cim:VsConverter } + ?ACDCConverter + cim:ACDCConverter.targetPpcc ?targetPpcc ; + cim:ACDCConverter.p ?p ; + cim:ACDCConverter.q ?q . + # From SV, for all converters + OPTIONAL { + ?ACDCConverter cim:ACDCConverter.poleLossP ?poleLossP + } + # For Current Source Converter + OPTIONAL { + ?ACDCConverter a cim:CsConverter ; + cim:CsConverter.operatingMode ?operatingMode ; + cim:CsConverter.pPccControl ?controlMode . + OPTIONAL { ?ACDCConverter cim:ACDCConverter.targetUdc ?targetUdc } + } + # For Voltage Source Converter + OPTIONAL { + ?ACDCConverter a cim:VsConverter ; + cim:VsConverter.qPccControl ?qPccControl ; + cim:VsConverter.pPccControl ?pPccControl . + OPTIONAL { ?ACDCConverter cim:VsConverter.targetQpcc ?targetQpcc } + OPTIONAL { ?ACDCConverter cim:VsConverter.targetUpcc ?targetUpcc } + } +} + +# query: dcTerminals +SELECT * +{ + ?DCTerminal a cim:DCTerminal ; + cim:ACDCTerminal.connected ?connected + OPTIONAL { + ?DCTerminal cim:DCBaseTerminal.DCTopologicalNode ?DCTopologicalNode . + } +} + +# query: boundaryNodes +# All pairs (Connectiviy Node, Topological Node) from instance files that have boundary profile and attribute boundaryPoint set to true +# We expect all Connectivity Nodes have 1 and only one corresponding TopologicalNode +prefix md: +SELECT * +{ +GRAPH ?graphBDEQ { + ?FullModel md:Model.profile ?modelProfile . + FILTER (regex(?modelProfile, "EquipmentBoundaryOperation", "i")) + ?ConnectivityNode + a cim:ConnectivityNode ; + cim:IdentifiedObject.name ?name ; + cim:ConnectivityNode.ConnectivityNodeContainer ?container ; + entsoe:ConnectivityNode.boundaryPoint "true" . + OPTIONAL { ?ConnectivityNode entsoe:IdentifiedObject.energyIdentCodeEic ?energyIdentCodeEicFromNode } + OPTIONAL { ?container entsoe:IdentifiedObject.energyIdentCodeEic ?energyIdentCodeEicFromNodeContainer } + OPTIONAL { ?ConnectivityNode cim:IdentifiedObject.description ?description } +} +GRAPH ?grapBDTP { + ?ConnectivityNode cim:ConnectivityNode.TopologicalNode ?TopologicalNode . + ?TopologicalNode cim:IdentifiedObject.name ?topologicalNodeName +} +} diff --git a/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/ValidationUtil.java b/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/ValidationUtil.java index c578d297ab3..bce4109f957 100644 --- a/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/ValidationUtil.java +++ b/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/ValidationUtil.java @@ -217,6 +217,9 @@ public static void checkLoadType(Validable validable, LoadType loadType) { } public static ValidationLevel checkP0(Validable validable, double p0, ValidationLevel validationLevel, ReportNode reportNode) { + if (validationLevel.equals(ValidationLevel.EQUIPMENT)) { + return ValidationLevel.EQUIPMENT; + } return checkP0(validable, p0, checkValidationLevel(validationLevel), reportNode); } @@ -229,6 +232,9 @@ private static ValidationLevel checkP0(Validable validable, double p0, boolean t } public static ValidationLevel checkQ0(Validable validable, double q0, ValidationLevel validationLevel, ReportNode reportNode) { + if (validationLevel.equals(ValidationLevel.EQUIPMENT)) { + return ValidationLevel.EQUIPMENT; + } return checkQ0(validable, q0, validationLevel == ValidationLevel.STEADY_STATE_HYPOTHESIS, reportNode); } diff --git a/triple-store/triple-store-api/src/main/java/com/powsybl/triplestore/api/PropertyBag.java b/triple-store/triple-store-api/src/main/java/com/powsybl/triplestore/api/PropertyBag.java index 120f21e29b8..d8d9408ce01 100644 --- a/triple-store/triple-store-api/src/main/java/com/powsybl/triplestore/api/PropertyBag.java +++ b/triple-store/triple-store-api/src/main/java/com/powsybl/triplestore/api/PropertyBag.java @@ -100,6 +100,18 @@ public double asDouble(String property, double defaultValue) { } } + public OptionalDouble getDouble(String property) { + if (!containsKey(property)) { + return OptionalDouble.empty(); + } + try { + return OptionalDouble.of(Double.parseDouble(get(property))); + } catch (NumberFormatException x) { + LOG.warn("Invalid value for property {} : {}", property, get(property)); + return OptionalDouble.of(Double.NaN); + } + } + public Optional asBoolean(String property) { if (!containsKey(property)) { return Optional.empty(); diff --git a/triple-store/triple-store-api/src/main/java/com/powsybl/triplestore/api/TripleStoreOptions.java b/triple-store/triple-store-api/src/main/java/com/powsybl/triplestore/api/TripleStoreOptions.java index 38eb433ca8a..06a47450677 100644 --- a/triple-store/triple-store-api/src/main/java/com/powsybl/triplestore/api/TripleStoreOptions.java +++ b/triple-store/triple-store-api/src/main/java/com/powsybl/triplestore/api/TripleStoreOptions.java @@ -14,6 +14,7 @@ public class TripleStoreOptions { private boolean removeInitialUnderscoreForIdentifiers = true; private boolean unescapeIdentifiers = true; + private String queryCatalog = ""; public TripleStoreOptions() { } @@ -40,4 +41,13 @@ public TripleStoreOptions decodeEscapedIdentifiers(boolean unescapeIdentifiers) this.unescapeIdentifiers = unescapeIdentifiers; return this; } + + public TripleStoreOptions setQueryCatalog(String queryCatalog) { + this.queryCatalog = queryCatalog; + return this; + } + + public String queryCatalog() { + return queryCatalog; + } } diff --git a/triple-store/triple-store-impl-rdf4j/src/main/java/com/powsybl/triplestore/impl/rdf4j/TripleStoreRDF4J.java b/triple-store/triple-store-impl-rdf4j/src/main/java/com/powsybl/triplestore/impl/rdf4j/TripleStoreRDF4J.java index 774abfb5caf..8d8378e09e5 100644 --- a/triple-store/triple-store-impl-rdf4j/src/main/java/com/powsybl/triplestore/impl/rdf4j/TripleStoreRDF4J.java +++ b/triple-store/triple-store-impl-rdf4j/src/main/java/com/powsybl/triplestore/impl/rdf4j/TripleStoreRDF4J.java @@ -169,37 +169,46 @@ public PropertyBags query(String query) { PropertyBags results = new PropertyBags(); try (RepositoryConnection conn = repo.getConnection()) { // Default language is SPARQL - TupleQuery q = conn.prepareTupleQuery(query1); - - // Print the optimization plan for the query - // Explaining queries take some time, so we change the execution timeout - if (EXPLAIN_QUERIES && LOGGER.isDebugEnabled()) { - Explanation explanation = q.explain(Explanation.Level.Timed); - LOGGER.debug("Query explanation:\n{}\n{}", query, explanation); - } + try { + TupleQuery q = conn.prepareTupleQuery(query1); + + // Print the optimization plan for the query + // Explaining queries take some time, so we change the execution timeout + if (EXPLAIN_QUERIES && LOGGER.isDebugEnabled()) { + Explanation explanation = q.explain(Explanation.Level.Timed); + LOGGER.debug("Query explanation:\n{}\n{}", query, explanation); + } - // Duplicated triplets are returned in queries - // when an object is defined in a file and referenced in another (rdf:ID and - // rdf:about) - // and data has been added to repository with contexts - // and we query without using explicit GRAPH clauses - // This means that we have to filter distinct results - try (TupleQueryResult r = QueryResults.distinctResults(q.evaluate())) { - List names = r.getBindingNames(); - while (r.hasNext()) { - BindingSet s = r.next(); - PropertyBag result = new PropertyBag(names, getOptions().isRemoveInitialUnderscoreForIdentifiers(), getOptions().unescapeIdentifiers()); - - names.forEach(name -> { - if (s.hasBinding(name)) { - String value = s.getBinding(name).getValue().stringValue(); - result.put(name, value); + // Duplicated triplets are returned in queries + // when an object is defined in a file and referenced in another (rdf:ID and + // rdf:about) + // and data has been added to repository with contexts + // and we query without using explicit GRAPH clauses + // This means that we have to filter distinct results + try (TupleQueryResult r = QueryResults.distinctResults(q.evaluate())) { + List names = r.getBindingNames(); + while (r.hasNext()) { + BindingSet s = r.next(); + PropertyBag result = new PropertyBag(names, getOptions().isRemoveInitialUnderscoreForIdentifiers(), getOptions().unescapeIdentifiers()); + + names.forEach(name -> { + if (s.hasBinding(name)) { + String value = s.getBinding(name).getValue().stringValue(); + result.put(name, value); + } + }); + if (result.size() > 0) { + results.add(result); } - }); - if (result.size() > 0) { - results.add(result); } } + } catch (MalformedQueryException x) { + int line = 1; + for (String s : query1.split("\n")) { + LOGGER.error(String.format("%3d %s", line, s)); + line++; + } + throw x; } } return results; From 6bc53a83ba02390d87290bc55dd764ea97c812d6 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 16 Oct 2024 08:09:21 +0200 Subject: [PATCH 02/54] Update loads Signed-off-by: marquesja1 --- .../cgmes/model/CgmesModelFactory.java | 31 +------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesModelFactory.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesModelFactory.java index 245aed96f37..e05412246b0 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesModelFactory.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesModelFactory.java @@ -9,7 +9,6 @@ package com.powsybl.cgmes.model; import com.powsybl.cgmes.model.triplestore.CgmesModelTripleStore; -import com.powsybl.commons.PowsyblException; import com.powsybl.commons.datasource.ReadOnlyDataSource; import com.powsybl.commons.report.ReportNode; import com.powsybl.triplestore.api.*; @@ -66,7 +65,7 @@ private static CgmesModel createImplementation(String implementation, TripleStor // Only triple store implementations are available TripleStore tripleStore = TripleStoreFactory.create(implementation, tripleStoreOptions); String cimNamespace = obtainCimNamespace(ds, alternativeDataSourceForBoundary); - return new CgmesModelTripleStore(cimNamespace, tripleStore); + return new CgmesModelTripleStore(cimNamespace, tripleStore, tripleStoreOptions.queryCatalog()); } private static String obtainCimNamespace(ReadOnlyDataSource ds, ReadOnlyDataSource dsBoundary) { @@ -84,32 +83,4 @@ private static String obtainCimNamespace(ReadOnlyDataSource ds, ReadOnlyDataSour } } } - - public static CgmesModel copy(CgmesModel cgmes) { - if (cgmes instanceof CgmesModelTripleStore cgmests) { - TripleStore tripleStore = TripleStoreFactory.copy(cgmests.tripleStore()); - CgmesModel cgmesCopy = new CgmesModelTripleStore(cgmests.getCimNamespace(), tripleStore); - cgmesCopy.setBasename(cgmes.getBasename()); - buildCaches(cgmesCopy); - return cgmesCopy; - } else { - throw new PowsyblException("CGMES model copy not supported, soource is " + cgmes.getClass().getSimpleName()); - } - } - - private static void buildCaches(CgmesModel cgmes) { - // TODO This is rebuilding only some caches - boolean isNodeBreaker = cgmes.isNodeBreaker(); - for (PropertyBags tends : cgmes.groupedTransformerEnds().values()) { - for (PropertyBag end : tends) { - CgmesTerminal t = cgmes.terminal(end.getId(CgmesNames.TERMINAL)); - cgmes.substation(t, isNodeBreaker); - if (isNodeBreaker) { - t.connectivityNode(); - } else { - t.topologicalNode(); - } - } - } - } } From 0241870c4bd6c3791f5c868f011f7af8a96e9ab4 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 16 Oct 2024 13:09:10 +0200 Subject: [PATCH 03/54] Adjust validationUtil Signed-off-by: marquesja1 --- .../powsybl/cgmes/conversion/Conversion.java | 9 +- .../powsybl/iidm/network/ValidationUtil.java | 122 ++++++++++-------- .../iidm/network/impl/NetworkImpl.java | 6 +- 3 files changed, 73 insertions(+), 64 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java index 7e750c4bf2f..999f0d662f6 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java @@ -305,18 +305,17 @@ private void updateAfterConvert(Network network, Context convertContext, ReportN // add processes to create new equipment using update data (ssh and sv data) - update(network, context); + update(network, context, reportNode); } public void update(Network network, ReportNode reportNode) { Objects.requireNonNull(network); Objects.requireNonNull(reportNode); Context context = createUpdateContext(network, reportNode); - update(network, context); - network.setMinimumAcceptableValidationLevel(ValidationLevel.STEADY_STATE_HYPOTHESIS); + update(network, context, reportNode); } - private void update(Network network, Context context) { + private void update(Network network, Context context, ReportNode reportNode) { // FIXME(Luma) Inspect the contents of the loaded data if (LOG.isDebugEnabled()) { PropertyBags nts = cgmes.numObjectsByType(); @@ -326,6 +325,8 @@ private void update(Network network, Context context) { } updateLoads(network, cgmes, context); + network.runValidationChecks(false, reportNode); + network.setMinimumAcceptableValidationLevel(ValidationLevel.STEADY_STATE_HYPOTHESIS); } /** diff --git a/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/ValidationUtil.java b/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/ValidationUtil.java index bce4109f957..259edafe7c3 100644 --- a/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/ValidationUtil.java +++ b/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/ValidationUtil.java @@ -23,6 +23,12 @@ */ public final class ValidationUtil { + public enum LogLevel { + THROW_EXCEPTION, + LOG_ERROR, + NONE, + } + private static final Logger LOGGER = LoggerFactory.getLogger(ValidationUtil.class); private static final String ACTIVE_POWER_SETPOINT = "active power setpoint"; @@ -63,33 +69,37 @@ private static void logError(Validable validable, String message, ReportNode rep LOGGER.error("{}{}", validable.getMessageHeader(), message); } - private static void throwExceptionOrLogError(Validable validable, String message, boolean throwException, ReportNode reportNode) { - if (throwException) { + private static void throwExceptionOrLogError(Validable validable, String message, LogLevel throwException, ReportNode reportNode) { + if (throwException.equals(LogLevel.THROW_EXCEPTION)) { throw new ValidationException(validable, message); } - logError(validable, message, reportNode); + if (throwException.equals(LogLevel.LOG_ERROR)) { + logError(validable, message, reportNode); + } } public static void throwExceptionOrLogError(Validable validable, String message, ValidationLevel validationLevel, ReportNode reportNode) { - throwExceptionOrLogError(validable, message, validationLevel == ValidationLevel.STEADY_STATE_HYPOTHESIS, reportNode); + throwExceptionOrLogError(validable, message, checkValidationLogLevel(validationLevel), reportNode); } - private static void throwExceptionOrLogErrorForInvalidValue(Validable validable, double value, String valueName, boolean throwException, ReportNode reportNode) { + private static void throwExceptionOrLogErrorForInvalidValue(Validable validable, double value, String valueName, LogLevel throwException, ReportNode reportNode) { throwExceptionOrLogErrorForInvalidValue(validable, value, valueName, null, throwException, reportNode); } - private static void throwExceptionOrLogErrorForInvalidValue(Validable validable, double value, String valueName, String reason, boolean throwException, ReportNode reportNode) { - if (throwException) { + private static void throwExceptionOrLogErrorForInvalidValue(Validable validable, double value, String valueName, String reason, LogLevel throwException, ReportNode reportNode) { + if (throwException.equals(LogLevel.THROW_EXCEPTION)) { throw createInvalidValueException(validable, value, valueName, reason); } - logError(validable, createInvalidValueMessage(value, valueName, reason), reportNode); + if (throwException.equals(LogLevel.LOG_ERROR)) { + logError(validable, createInvalidValueMessage(value, valueName, reason), reportNode); + } } public static ValidationLevel checkActivePowerSetpoint(Validable validable, double activePowerSetpoint, ValidationLevel validationLevel, ReportNode reportNode) { - return checkActivePowerSetpoint(validable, activePowerSetpoint, validationLevel == ValidationLevel.STEADY_STATE_HYPOTHESIS, reportNode); + return checkActivePowerSetpoint(validable, activePowerSetpoint, checkValidationLogLevel(validationLevel), reportNode); } - private static ValidationLevel checkActivePowerSetpoint(Validable validable, double activePowerSetpoint, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkActivePowerSetpoint(Validable validable, double activePowerSetpoint, LogLevel throwException, ReportNode reportNode) { if (Double.isNaN(activePowerSetpoint)) { throwExceptionOrLogErrorForInvalidValue(validable, activePowerSetpoint, ACTIVE_POWER_SETPOINT, throwException, reportNode); return ValidationLevel.EQUIPMENT; @@ -98,10 +108,10 @@ private static ValidationLevel checkActivePowerSetpoint(Validable validable, dou } public static ValidationLevel checkHvdcActivePowerSetpoint(Validable validable, double activePowerSetpoint, ValidationLevel validationLevel, ReportNode reportNode) { - return checkHvdcActivePowerSetpoint(validable, activePowerSetpoint, checkValidationLevel(validationLevel), reportNode); + return checkHvdcActivePowerSetpoint(validable, activePowerSetpoint, checkValidationLogLevel(validationLevel), reportNode); } - private static ValidationLevel checkHvdcActivePowerSetpoint(Validable validable, double activePowerSetpoint, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkHvdcActivePowerSetpoint(Validable validable, double activePowerSetpoint, LogLevel throwException, ReportNode reportNode) { if (Double.isNaN(activePowerSetpoint)) { throwExceptionOrLogErrorForInvalidValue(validable, activePowerSetpoint, ACTIVE_POWER_SETPOINT, throwException, reportNode); return ValidationLevel.EQUIPMENT; @@ -118,10 +128,10 @@ public static void checkActivePowerLimits(Validable validable, double minP, doub } public static ValidationLevel checkTargetDeadband(Validable validable, String validableType, boolean regulating, double targetDeadband, ValidationLevel validationLevel, ReportNode reportNode) { - return checkTargetDeadband(validable, validableType, regulating, targetDeadband, checkValidationLevel(validationLevel), reportNode); + return checkTargetDeadband(validable, validableType, regulating, targetDeadband, checkValidationLogLevel(validationLevel), reportNode); } - private static ValidationLevel checkTargetDeadband(Validable validable, String validableType, boolean regulating, double targetDeadband, boolean throwsException, ReportNode reportNode) { + private static ValidationLevel checkTargetDeadband(Validable validable, String validableType, boolean regulating, double targetDeadband, LogLevel throwsException, ReportNode reportNode) { if (regulating && Double.isNaN(targetDeadband)) { throwExceptionOrLogError(validable, "Undefined value for target deadband of regulating " + validableType, throwsException, reportNode); return ValidationLevel.EQUIPMENT; @@ -133,10 +143,10 @@ private static ValidationLevel checkTargetDeadband(Validable validable, String v } public static ValidationLevel checkVoltageControl(Validable validable, boolean voltageRegulatorOn, double voltageSetpoint, ValidationLevel validationLevel, ReportNode reportNode) { - return checkVoltageControl(validable, voltageRegulatorOn, voltageSetpoint, checkValidationLevel(validationLevel), reportNode); + return checkVoltageControl(validable, voltageRegulatorOn, voltageSetpoint, checkValidationLogLevel(validationLevel), reportNode); } - private static ValidationLevel checkVoltageControl(Validable validable, boolean voltageRegulatorOn, double voltageSetpoint, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkVoltageControl(Validable validable, boolean voltageRegulatorOn, double voltageSetpoint, LogLevel throwException, ReportNode reportNode) { if (voltageRegulatorOn) { if (Double.isNaN(voltageSetpoint)) { throwExceptionOrLogErrorForInvalidValue(validable, voltageSetpoint, VOLTAGE_SETPOINT, VOLTAGE_REGULATOR_ON, throwException, reportNode); @@ -150,10 +160,10 @@ private static ValidationLevel checkVoltageControl(Validable validable, boolean } public static ValidationLevel checkVoltageControl(Validable validable, Boolean voltageRegulatorOn, double voltageSetpoint, double reactivePowerSetpoint, ValidationLevel validationLevel, ReportNode reportNode) { - return checkVoltageControl(validable, voltageRegulatorOn, voltageSetpoint, reactivePowerSetpoint, checkValidationLevel(validationLevel), reportNode); + return checkVoltageControl(validable, voltageRegulatorOn, voltageSetpoint, reactivePowerSetpoint, checkValidationLogLevel(validationLevel), reportNode); } - private static ValidationLevel checkVoltageControl(Validable validable, Boolean voltageRegulatorOn, double voltageSetpoint, double reactivePowerSetpoint, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkVoltageControl(Validable validable, Boolean voltageRegulatorOn, double voltageSetpoint, double reactivePowerSetpoint, LogLevel throwException, ReportNode reportNode) { if (voltageRegulatorOn == null) { throw new ValidationException(validable, "voltage regulator status is not set"); } @@ -217,13 +227,10 @@ public static void checkLoadType(Validable validable, LoadType loadType) { } public static ValidationLevel checkP0(Validable validable, double p0, ValidationLevel validationLevel, ReportNode reportNode) { - if (validationLevel.equals(ValidationLevel.EQUIPMENT)) { - return ValidationLevel.EQUIPMENT; - } - return checkP0(validable, p0, checkValidationLevel(validationLevel), reportNode); + return checkP0(validable, p0, checkValidationLogLevel(validationLevel), reportNode); } - private static ValidationLevel checkP0(Validable validable, double p0, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkP0(Validable validable, double p0, LogLevel throwException, ReportNode reportNode) { if (Double.isNaN(p0)) { throwExceptionOrLogError(validable, "p0 is invalid", throwException, reportNode); return ValidationLevel.EQUIPMENT; @@ -232,13 +239,10 @@ private static ValidationLevel checkP0(Validable validable, double p0, boolean t } public static ValidationLevel checkQ0(Validable validable, double q0, ValidationLevel validationLevel, ReportNode reportNode) { - if (validationLevel.equals(ValidationLevel.EQUIPMENT)) { - return ValidationLevel.EQUIPMENT; - } - return checkQ0(validable, q0, validationLevel == ValidationLevel.STEADY_STATE_HYPOTHESIS, reportNode); + return checkQ0(validable, q0, checkValidationLogLevel(validationLevel), reportNode); } - private static ValidationLevel checkQ0(Validable validable, double q0, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkQ0(Validable validable, double q0, LogLevel throwException, ReportNode reportNode) { if (Double.isNaN(q0)) { throwExceptionOrLogError(validable, "q0 is invalid", throwException, reportNode); return ValidationLevel.EQUIPMENT; @@ -345,10 +349,10 @@ public static void checkMaximumSectionCount(Validable validable, int maximumSect } public static ValidationLevel checkSections(Validable validable, Integer currentSectionCount, int maximumSectionCount, ValidationLevel validationLevel, ReportNode reportNode) { - return checkSections(validable, currentSectionCount, maximumSectionCount, checkValidationLevel(validationLevel), reportNode); + return checkSections(validable, currentSectionCount, maximumSectionCount, checkValidationLogLevel(validationLevel), reportNode); } - private static ValidationLevel checkSections(Validable validable, Integer currentSectionCount, int maximumSectionCount, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkSections(Validable validable, Integer currentSectionCount, int maximumSectionCount, LogLevel throwException, ReportNode reportNode) { checkMaximumSectionCount(validable, maximumSectionCount); if (currentSectionCount == null) { throwExceptionOrLogError(validable, "the current number of section is undefined", throwException, reportNode); @@ -383,11 +387,11 @@ public static void checkRatedU2(Validable validable, double ratedU2) { public static ValidationLevel checkSvcRegulator(Validable validable, double voltageSetpoint, double reactivePowerSetpoint, StaticVarCompensator.RegulationMode regulationMode, ValidationLevel validationLevel, ReportNode reportNode) { - return checkSvcRegulator(validable, voltageSetpoint, reactivePowerSetpoint, regulationMode, checkValidationLevel(validationLevel), reportNode); + return checkSvcRegulator(validable, voltageSetpoint, reactivePowerSetpoint, regulationMode, checkValidationLogLevel(validationLevel), reportNode); } private static ValidationLevel checkSvcRegulator(Validable validable, double voltageSetpoint, double reactivePowerSetpoint, - StaticVarCompensator.RegulationMode regulationMode, boolean throwException, ReportNode reportNode) { + StaticVarCompensator.RegulationMode regulationMode, LogLevel throwException, ReportNode reportNode) { if (regulationMode == null) { throwExceptionOrLogError(validable, "Regulation mode is invalid", throwException, reportNode); return ValidationLevel.EQUIPMENT; @@ -424,7 +428,7 @@ public static void checkBmax(Validable validable, double bMax) { } } - private static ValidationLevel errorOrWarningForRtc(Validable validable, boolean loadTapChangingCapabilities, String message, boolean throwException, ReportNode reportNode) { + private static ValidationLevel errorOrWarningForRtc(Validable validable, boolean loadTapChangingCapabilities, String message, LogLevel throwException, ReportNode reportNode) { if (loadTapChangingCapabilities) { throwExceptionOrLogError(validable, message, throwException, reportNode); return ValidationLevel.EQUIPMENT; @@ -440,12 +444,12 @@ private static ValidationLevel errorOrWarningForRtc(Validable validable, boolean public static ValidationLevel checkRatioTapChangerRegulation(Validable validable, boolean regulating, boolean loadTapChangingCapabilities, Terminal regulationTerminal, RatioTapChanger.RegulationMode regulationMode, double regulationValue, Network network, ValidationLevel validationLevel, ReportNode reportNode) { - return checkRatioTapChangerRegulation(validable, regulating, loadTapChangingCapabilities, regulationTerminal, regulationMode, regulationValue, network, checkValidationLevel(validationLevel), reportNode); + return checkRatioTapChangerRegulation(validable, regulating, loadTapChangingCapabilities, regulationTerminal, regulationMode, regulationValue, network, checkValidationLogLevel(validationLevel), reportNode); } private static ValidationLevel checkRatioTapChangerRegulation(Validable validable, boolean regulating, boolean loadTapChangingCapabilities, Terminal regulationTerminal, RatioTapChanger.RegulationMode regulationMode, - double regulationValue, Network network, boolean throwException, + double regulationValue, Network network, LogLevel throwException, ReportNode reportNode) { ValidationLevel validationLevel = ValidationLevel.STEADY_STATE_HYPOTHESIS; if (regulating) { @@ -472,12 +476,12 @@ public static ValidationLevel checkPhaseTapChangerRegulation(Validable validable double regulationValue, boolean regulating, Terminal regulationTerminal, Network network, ValidationLevel validationLevel, ReportNode reportNode) { return checkPhaseTapChangerRegulation(validable, regulationMode, regulationValue, regulating, regulationTerminal, - network, checkValidationLevel(validationLevel), reportNode); + network, checkValidationLogLevel(validationLevel), reportNode); } private static ValidationLevel checkPhaseTapChangerRegulation(Validable validable, PhaseTapChanger.RegulationMode regulationMode, double regulationValue, boolean regulating, Terminal regulationTerminal, - Network network, boolean throwException, ReportNode reportNode) { + Network network, LogLevel throwException, ReportNode reportNode) { ValidationLevel validationLevel = ValidationLevel.STEADY_STATE_HYPOTHESIS; if (regulationMode == null) { throwExceptionOrLogError(validable, "phase regulation mode is not set", throwException, reportNode); @@ -505,11 +509,11 @@ private static ValidationLevel checkPhaseTapChangerRegulation(Validable validabl public static ValidationLevel checkOnlyOneTapChangerRegulatingEnabled(Validable validable, Set> tapChangersNotIncludingTheModified, boolean regulating, ValidationLevel validationLevel, ReportNode reportNode) { - return checkOnlyOneTapChangerRegulatingEnabled(validable, tapChangersNotIncludingTheModified, regulating, checkValidationLevel(validationLevel), reportNode); + return checkOnlyOneTapChangerRegulatingEnabled(validable, tapChangersNotIncludingTheModified, regulating, checkValidationLogLevel(validationLevel), reportNode); } private static ValidationLevel checkOnlyOneTapChangerRegulatingEnabled(Validable validable, Set> tapChangersNotIncludingTheModified, - boolean regulating, boolean throwException, ReportNode reportNode) { + boolean regulating, LogLevel throwException, ReportNode reportNode) { if (regulating && tapChangersNotIncludingTheModified.stream().anyMatch(TapChanger::isRegulating)) { throwExceptionOrLogError(validable, UNIQUE_REGULATING_TAP_CHANGER_MSG, throwException, reportNode); return ValidationLevel.EQUIPMENT; @@ -519,11 +523,11 @@ private static ValidationLevel checkOnlyOneTapChangerRegulatingEnabled(Validable public static ValidationLevel checkConvertersMode(Validable validable, HvdcLine.ConvertersMode converterMode, ValidationLevel validationLevel, ReportNode reportNode) { - return checkConvertersMode(validable, converterMode, checkValidationLevel(validationLevel), reportNode); + return checkConvertersMode(validable, converterMode, checkValidationLogLevel(validationLevel), reportNode); } private static ValidationLevel checkConvertersMode(Validable validable, HvdcLine.ConvertersMode converterMode, - boolean throwException, ReportNode reportNode) { + LogLevel throwException, ReportNode reportNode) { if (converterMode == null) { throwExceptionOrLogError(validable, "converter mode is invalid", throwException, reportNode); return ValidationLevel.EQUIPMENT; @@ -541,11 +545,11 @@ public static void checkPowerFactor(Validable validable, double powerFactor) { public static ValidationLevel checkLoadingLimits(Validable validable, double permanentLimit, Collection temporaryLimits, ValidationLevel validationLevel, ReportNode reportNode) { - return checkLoadingLimits(validable, permanentLimit, temporaryLimits, checkValidationLevel(validationLevel), reportNode); + return checkLoadingLimits(validable, permanentLimit, temporaryLimits, checkValidationLogLevel(validationLevel), reportNode); } private static ValidationLevel checkLoadingLimits(Validable validable, double permanentLimit, Collection temporaryLimits, - boolean throwException, ReportNode reportNode) { + LogLevel throwException, ReportNode reportNode) { ValidationLevel validationLevel = ValidationUtil.checkPermanentLimit(validable, permanentLimit, temporaryLimits, throwException, reportNode); ValidationUtil.checkTemporaryLimits(validable, permanentLimit, temporaryLimits); return validationLevel; @@ -553,11 +557,11 @@ private static ValidationLevel checkLoadingLimits(Validable validable, double pe public static ValidationLevel checkPermanentLimit(Validable validable, double permanentLimit, Collection temporaryLimits, ValidationLevel validationLevel, ReportNode reportNode) { - return checkPermanentLimit(validable, permanentLimit, temporaryLimits, checkValidationLevel(validationLevel), reportNode); + return checkPermanentLimit(validable, permanentLimit, temporaryLimits, checkValidationLogLevel(validationLevel), reportNode); } private static ValidationLevel checkPermanentLimit(Validable validable, double permanentLimit, Collection temporaryLimits, - boolean throwException, ReportNode reportNode) { + LogLevel throwException, ReportNode reportNode) { ValidationLevel validationLevel = ValidationLevel.STEADY_STATE_HYPOTHESIS; if (Double.isNaN(permanentLimit) && !temporaryLimits.isEmpty()) { throwExceptionOrLogError(validable, "permanent limit must be defined if temporary limits are present", throwException, reportNode); @@ -594,10 +598,10 @@ private static void checkTemporaryLimits(Validable validable, double permanentLi } public static ValidationLevel checkLossFactor(Validable validable, float lossFactor, ValidationLevel validationLevel, ReportNode reportNode) { - return checkLossFactor(validable, lossFactor, checkValidationLevel(validationLevel), reportNode); + return checkLossFactor(validable, lossFactor, checkValidationLogLevel(validationLevel), reportNode); } - private static ValidationLevel checkLossFactor(Validable validable, float lossFactor, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkLossFactor(Validable validable, float lossFactor, LogLevel throwException, ReportNode reportNode) { ValidationLevel validationLevel = ValidationLevel.STEADY_STATE_HYPOTHESIS; if (Double.isNaN(lossFactor)) { throwExceptionOrLogError(validable, "loss factor is invalid is undefined", throwException, reportNode); @@ -608,7 +612,7 @@ private static ValidationLevel checkLossFactor(Validable validable, float lossFa return validationLevel; } - private static ValidationLevel checkRtc(Validable validable, RatioTapChanger rtc, Network network, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkRtc(Validable validable, RatioTapChanger rtc, Network network, LogLevel throwException, ReportNode reportNode) { ValidationLevel validationLevel = ValidationLevel.STEADY_STATE_HYPOTHESIS; if (rtc.findTapPosition().isEmpty()) { throwExceptionOrLogError(validable, "tap position is not set", throwException, reportNode); @@ -619,7 +623,7 @@ private static ValidationLevel checkRtc(Validable validable, RatioTapChanger rtc return validationLevel; } - private static ValidationLevel checkPtc(Validable validable, PhaseTapChanger ptc, Network network, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkPtc(Validable validable, PhaseTapChanger ptc, Network network, LogLevel throwException, ReportNode reportNode) { ValidationLevel validationLevel = ValidationLevel.STEADY_STATE_HYPOTHESIS; if (ptc.findTapPosition().isEmpty()) { throwExceptionOrLogError(validable, "tap position is not set", throwException, reportNode); @@ -630,7 +634,7 @@ private static ValidationLevel checkPtc(Validable validable, PhaseTapChanger ptc return validationLevel; } - private static ValidationLevel checkThreeWindingsTransformer(Validable validable, ThreeWindingsTransformer twt, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkThreeWindingsTransformer(Validable validable, ThreeWindingsTransformer twt, LogLevel throwException, ReportNode reportNode) { ValidationLevel validationLevel = ValidationLevel.STEADY_STATE_HYPOTHESIS; for (ThreeWindingsTransformer.Leg leg : twt.getLegs()) { if (leg.hasRatioTapChanger()) { @@ -659,7 +663,7 @@ private static ValidationLevel checkThreeWindingsTransformer(Validable validable return validationLevel; } - private static ValidationLevel checkTwoWindingsTransformer(Validable validable, TwoWindingsTransformer twt, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkTwoWindingsTransformer(Validable validable, TwoWindingsTransformer twt, LogLevel throwException, ReportNode reportNode) { ValidationLevel validationLevel = ValidationLevel.STEADY_STATE_HYPOTHESIS; if (twt.hasRatioTapChanger()) { validationLevel = ValidationLevel.min(validationLevel, checkRtc(validable, twt.getRatioTapChanger(), twt.getNetwork(), throwException, reportNode)); @@ -676,7 +680,7 @@ private static ValidationLevel checkTwoWindingsTransformer(Validable validable, return validationLevel; } - private static ValidationLevel checkIdentifiable(Identifiable identifiable, ValidationLevel previous, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkIdentifiable(Identifiable identifiable, ValidationLevel previous, LogLevel throwException, ReportNode reportNode) { ValidationLevel validationLevel = previous; if (identifiable instanceof Validable validable) { if (identifiable instanceof Battery battery) { @@ -716,7 +720,7 @@ private static ValidationLevel checkIdentifiable(Identifiable identifiable, V return validationLevel; } - private static ValidationLevel checkGenerationOnDanglingLine(ValidationLevel previous, Validable validable, DanglingLine danglingLine, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkGenerationOnDanglingLine(ValidationLevel previous, Validable validable, DanglingLine danglingLine, LogLevel throwException, ReportNode reportNode) { ValidationLevel validationLevel = previous; DanglingLine.Generation generation = danglingLine.getGeneration(); if (generation != null) { @@ -730,7 +734,7 @@ private static Integer getSectionCount(ShuntCompensator shunt) { return shunt.findSectionCount().isPresent() ? shunt.getSectionCount() : null; } - private static ValidationLevel checkOperationalLimitsGroups(Validable validable, Collection operationalLimitsGroupCollection, ValidationLevel previous, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkOperationalLimitsGroups(Validable validable, Collection operationalLimitsGroupCollection, ValidationLevel previous, LogLevel throwException, ReportNode reportNode) { ValidationLevel validationLevel = previous; for (OperationalLimitsGroup group : operationalLimitsGroupCollection) { validationLevel = checkOperationalLimitsGroup(validable, group, validationLevel, throwException, reportNode); @@ -738,7 +742,7 @@ private static ValidationLevel checkOperationalLimitsGroups(Validable validable, return validationLevel; } - private static ValidationLevel checkOperationalLimitsGroup(Validable validable, OperationalLimitsGroup operationalLimitsGroup, ValidationLevel previous, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkOperationalLimitsGroup(Validable validable, OperationalLimitsGroup operationalLimitsGroup, ValidationLevel previous, LogLevel throwException, ReportNode reportNode) { ValidationLevel[] validationLevel = new ValidationLevel[1]; validationLevel[0] = previous; operationalLimitsGroup.getCurrentLimits().ifPresent(l -> validationLevel[0] = checkLoadingLimits(validable, l, validationLevel[0], throwException, reportNode)); @@ -747,11 +751,11 @@ private static ValidationLevel checkOperationalLimitsGroup(Validable validable, return validationLevel[0]; } - private static ValidationLevel checkLoadingLimits(Validable validable, LoadingLimits limits, ValidationLevel validationLevel, boolean throwException, ReportNode reportNode) { + private static ValidationLevel checkLoadingLimits(Validable validable, LoadingLimits limits, ValidationLevel validationLevel, LogLevel throwException, ReportNode reportNode) { return ValidationLevel.min(validationLevel, checkLoadingLimits(validable, limits.getPermanentLimit(), limits.getTemporaryLimits(), throwException, reportNode)); } - public static ValidationLevel validate(Collection> identifiables, boolean allChecks, boolean throwException, ValidationLevel previous, ReportNode reportNode) { + public static ValidationLevel validate(Collection> identifiables, boolean allChecks, LogLevel throwException, ValidationLevel previous, ReportNode reportNode) { Objects.requireNonNull(identifiables); Objects.requireNonNull(previous); Objects.requireNonNull(reportNode); @@ -772,4 +776,8 @@ private static boolean checkValidationLevel(ValidationLevel validationLevel) { return validationLevel.compareTo(ValidationLevel.STEADY_STATE_HYPOTHESIS) >= 0; } + private static LogLevel checkValidationLogLevel(ValidationLevel validationLevel) { + return validationLevel.compareTo(ValidationLevel.STEADY_STATE_HYPOTHESIS) >= 0 ? LogLevel.THROW_EXCEPTION : LogLevel.NONE; + } + } diff --git a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/NetworkImpl.java b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/NetworkImpl.java index de6ddb2c60a..6281e17d924 100644 --- a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/NetworkImpl.java +++ b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/NetworkImpl.java @@ -1246,14 +1246,14 @@ public ValidationLevel runValidationChecks(boolean throwsException, ReportNode r .withUntypedValue("networkId", id) .add(); validationLevel = ValidationUtil.validate(Collections.unmodifiableCollection(index.getAll()), - true, throwsException, validationLevel != null ? validationLevel : minValidationLevel, readReportNode); + true, throwsException ? ValidationUtil.LogLevel.THROW_EXCEPTION : ValidationUtil.LogLevel.LOG_ERROR, validationLevel != null ? validationLevel : minValidationLevel, readReportNode); return validationLevel; } @Override public ValidationLevel getValidationLevel() { if (validationLevel == null) { - validationLevel = ValidationUtil.validate(Collections.unmodifiableCollection(index.getAll()), false, false, minValidationLevel, ReportNode.NO_OP); + validationLevel = ValidationUtil.validate(Collections.unmodifiableCollection(index.getAll()), false, ValidationUtil.LogLevel.NONE, minValidationLevel, ReportNode.NO_OP); } return validationLevel; } @@ -1262,7 +1262,7 @@ public ValidationLevel getValidationLevel() { public Network setMinimumAcceptableValidationLevel(ValidationLevel validationLevel) { Objects.requireNonNull(validationLevel); if (this.validationLevel == null) { - this.validationLevel = ValidationUtil.validate(Collections.unmodifiableCollection(index.getAll()), false, false, this.validationLevel, ReportNode.NO_OP); + this.validationLevel = ValidationUtil.validate(Collections.unmodifiableCollection(index.getAll()), false, ValidationUtil.LogLevel.NONE, minValidationLevel, ReportNode.NO_OP); } if (this.validationLevel.compareTo(validationLevel) < 0) { throw new ValidationException(this, "Network should be corrected in order to correspond to validation level " + validationLevel); From e1e04b2f822c08f267f73619d664b586e09b8086 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 16 Oct 2024 13:31:10 +0200 Subject: [PATCH 04/54] Adjust FunctionalLogsTests Signed-off-by: marquesja1 --- .../functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt | 1 + .../functional-logs/microGridBaseCaseBE-target-deadband.txt | 1 + .../src/test/resources/functional-logs/microGridBaseCaseBE.txt | 1 + .../src/test/resources/functional-logs/miniGridNodeBreaker.txt | 1 + 4 files changed, 4 insertions(+) diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt index ba2c1eafac1..3ba085be984 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt @@ -41,3 +41,4 @@ Setting voltages and angles. Applying postprocessors. CGMES network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 is imported. + Running validation checks on IIDM network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt index d81410a9eda..f5e5e724c6f 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt @@ -41,3 +41,4 @@ Setting voltages and angles. Applying postprocessors. CGMES network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 is imported. + Running validation checks on IIDM network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt index 178ad6e4db5..ce0c42595d8 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt @@ -43,3 +43,4 @@ Setting voltages and angles. Applying postprocessors. CGMES network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 is imported. + Running validation checks on IIDM network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt index 153490be383..d9e431d32f0 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt @@ -40,3 +40,4 @@ Node 49831d24-33e9-4233-8424-3f88186a924e has invalid value for voltage and/or angle. Voltage magnitude is 0.0, angle is 0.0. Applying postprocessors. CGMES network urn:uuid:239ecbd2-9a39-11e0-aa80-0800200c9a66 is imported. + Running validation checks on IIDM network urn:uuid:239ecbd2-9a39-11e0-aa80-0800200c9a66 From 3eafccf6e18b432496fccd5ec29d6e34da7784be Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 16 Oct 2024 16:38:35 +0200 Subject: [PATCH 05/54] Fix all the tests Signed-off-by: marquesja1 --- .../java/com/powsybl/cgmes/conversion/Conversion.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java index 999f0d662f6..6d32530f77c 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java @@ -298,7 +298,9 @@ public Network convert(ReportNode reportNode) { private void updateAfterConvert(Network network, Context convertContext, ReportNode reportNode) { // FIXME(Luma) Before switching to update we must invalidate all caches of the cgmes model // and change the query catalog to "update" mode - + if (!sshIncludedInCgmesModel(this.cgmes)) { + return; + } this.cgmes.invalidateCaches(); this.cgmes.setQueryCatalog("-update"); Context context = createUpdateContext(network, reportNode); @@ -308,6 +310,10 @@ private void updateAfterConvert(Network network, Context convertContext, ReportN update(network, context, reportNode); } + private static boolean sshIncludedInCgmesModel(CgmesModel cgmes) { + return cgmes.version().contains("CIM14") || cgmes.fullModels().stream().anyMatch(fullModel -> fullModel.getId("profileList").contains("SteadyStateHypothesis")); + } + public void update(Network network, ReportNode reportNode) { Objects.requireNonNull(network); Objects.requireNonNull(reportNode); @@ -1209,7 +1215,7 @@ public List updateDefaultValuesPriority() { private final boolean updateTerminalConnectionInNodeBreakerVoltageLevel = false; - private final List updateDefaultValuesPriority = List.of(DefaultValue.NAN, DefaultValue.EQ); + private final List updateDefaultValuesPriority = List.of(DefaultValue.EQ, DefaultValue.NAN); } private final CgmesModel cgmes; From 3884a51b9a08c64983441240ff2d1ffdb15830e6 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 16 Oct 2024 17:09:09 +0200 Subject: [PATCH 06/54] Fix issues Signed-off-by: marquesja1 --- .../powsybl/cgmes/conversion/Conversion.java | 15 +++++------ .../elements/EnergyConsumerConversion.java | 27 ++++++++++--------- .../cgmes/model/AbstractCgmesModel.java | 1 + 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java index 6d32530f77c..ab817aa7e89 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java @@ -165,7 +165,7 @@ public Network convert(ReportNode reportNode) { // so it is safe to store the context as an attribute for later use in update // to do things right the context should have been created in the constructor, // together with the empty network - this.context = createContext(network, reportNode); + Context context = createContext(network, reportNode); assignNetworkProperties(context); addMetadataModels(network, context); @@ -303,11 +303,11 @@ private void updateAfterConvert(Network network, Context convertContext, ReportN } this.cgmes.invalidateCaches(); this.cgmes.setQueryCatalog("-update"); - Context context = createUpdateContext(network, reportNode); + Context updateContext = createUpdateContext(network, reportNode); // add processes to create new equipment using update data (ssh and sv data) - update(network, context, reportNode); + update(network, updateContext, reportNode); } private static boolean sshIncludedInCgmesModel(CgmesModel cgmes) { @@ -317,11 +317,11 @@ private static boolean sshIncludedInCgmesModel(CgmesModel cgmes) { public void update(Network network, ReportNode reportNode) { Objects.requireNonNull(network); Objects.requireNonNull(reportNode); - Context context = createUpdateContext(network, reportNode); - update(network, context, reportNode); + Context updateContext = createUpdateContext(network, reportNode); + update(network, updateContext, reportNode); } - private void update(Network network, Context context, ReportNode reportNode) { + private void update(Network network, Context updateContext, ReportNode reportNode) { // FIXME(Luma) Inspect the contents of the loaded data if (LOG.isDebugEnabled()) { PropertyBags nts = cgmes.numObjectsByType(); @@ -330,7 +330,7 @@ private void update(Network network, Context context, ReportNode reportNode) { nts.forEach(nt -> LOG.debug(cgmes.allObjectsOfType(nt.getLocal("Type")).tabulateLocals())); } - updateLoads(network, cgmes, context); + updateLoads(network, cgmes, updateContext); network.runValidationChecks(false, reportNode); network.setMinimumAcceptableValidationLevel(ValidationLevel.STEADY_STATE_HYPOTHESIS); } @@ -1223,7 +1223,6 @@ public List updateDefaultValuesPriority() { private final List postProcessors; private final List preProcessors; private final NetworkFactory networkFactory; - private Context context; private static final Logger LOG = LoggerFactory.getLogger(Conversion.class); diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index 34c4a965a89..3a21632c803 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -26,6 +26,9 @@ */ public class EnergyConsumerConversion extends AbstractConductingEquipmentConversion { + private static final String P_FIXED = "pFixed"; + private static final String Q_FIXED = "qFixed"; + public EnergyConsumerConversion(PropertyBag ec, Context context) { super(CgmesNames.ENERGY_CONSUMER, ec, context); loadKind = ec.getLocal("type"); @@ -48,8 +51,8 @@ public void convert() { } else { loadType = LoadType.UNDEFINED; } - double pFixed = p.asDouble("pFixed", 0.0); - double qFixed = p.asDouble("qFixed", 0.0); + double pFixed = p.asDouble(P_FIXED, 0.0); + double qFixed = p.asDouble(Q_FIXED, 0.0); LoadAdder adder = voltageLevel().newLoad() .setLoadType(loadType); identify(adder); @@ -65,8 +68,8 @@ public void convert() { private static void addSpecificProperties(Load load, String loadKind, double pFixed, double qFixed) { load.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, loadKind); - load.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "pFixed", String.valueOf(pFixed)); - load.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "qFixed", String.valueOf(qFixed)); + load.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + P_FIXED, String.valueOf(pFixed)); + load.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + Q_FIXED, String.valueOf(qFixed)); } private void model(LoadAdder adder) { @@ -151,8 +154,8 @@ public void update(Network network) { Objects.requireNonNull(load); updateTerminals(context, load.getTerminal()); - double pFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "pFixed")); - double qFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "qFixed")); + double pFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + P_FIXED)); + double qFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + Q_FIXED)); load.setP0(updatedP0().orElse(defaultP(pFixed, load.getP0(), getDefaultValue(context)))) .setQ0(qupdatedQ0().orElse(defaultQ(qFixed, load.getQ0(), getDefaultValue(context)))); @@ -164,20 +167,20 @@ private static Conversion.Config.DefaultValue getDefaultValue(Context context) { return selectDefaultValue(List.of(EQ, PREVIOUS, ZERO, NAN), context); } - private static void updateLoadDetail(String type, Load load, double pFixed, double qFixed) { + private static void updateLoadDetail(String type, Load updatedLoad, double pFixed, double qFixed) { if (type == null) { return; } - LoadDetail loadDetail = load.getExtension(LoadDetail.class); + LoadDetail loadDetail = updatedLoad.getExtension(LoadDetail.class); if (loadDetail == null) { return; } if (type.equals("ConformLoad")) { // ConformLoad represent loads that follow a daily load change pattern where the pattern can be used to scale the load with a system load - loadDetail.setVariableActivePower(Double.isFinite(load.getP0()) ? (float) load.getP0() : (float) pFixed) - .setVariableReactivePower(Double.isFinite(load.getQ0()) ? (float) load.getQ0() : (float) qFixed); + loadDetail.setVariableActivePower(Double.isFinite(updatedLoad.getP0()) ? (float) updatedLoad.getP0() : (float) pFixed) + .setVariableReactivePower(Double.isFinite(updatedLoad.getQ0()) ? (float) updatedLoad.getQ0() : (float) qFixed); } else if (type.equals("NonConformLoad")) { // does not participate in scaling - loadDetail.setFixedActivePower(Double.isFinite(load.getP0()) ? (float) load.getP0() : (float) pFixed) - .setFixedReactivePower(Double.isFinite(load.getQ0()) ? (float) load.getQ0() : (float) qFixed); + loadDetail.setFixedActivePower(Double.isFinite(updatedLoad.getP0()) ? (float) updatedLoad.getP0() : (float) pFixed) + .setFixedReactivePower(Double.isFinite(updatedLoad.getQ0()) ? (float) updatedLoad.getQ0() : (float) qFixed); } } diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/AbstractCgmesModel.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/AbstractCgmesModel.java index 81d0e76abcb..51eaf88a256 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/AbstractCgmesModel.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/AbstractCgmesModel.java @@ -269,6 +269,7 @@ public void read(ReadOnlyDataSource ds, ReportNode reportNode) { } } + @Override public void invalidateCaches() { cachedGroupedTransformerEnds = null; powerTransformerRatioTapChanger = null; From 71bb0f005a7a7771b06fddd6362545addc42f792 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 16 Oct 2024 20:21:36 +0200 Subject: [PATCH 07/54] Pretty code Signed-off-by: marquesja1 --- .../powsybl/cgmes/conversion/Conversion.java | 4 ++-- .../AsynchronousMachineConversion.java | 12 +++++----- .../elements/EnergyConsumerConversion.java | 24 +++++++++---------- .../elements/EnergySourceConversion.java | 12 +++++----- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java index ab817aa7e89..4b92770a6a3 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java @@ -1177,7 +1177,7 @@ public boolean disconnectNetworkSideOfDanglingLinesIfBoundaryIsDisconnected() { } public boolean updateTerminalConnectionInNodeBreakerVoltageLevel() { - return updateTerminalConnectionInNodeBreakerVoltageLevel; + return UPDATE_TERMINAL_CONNECTION_IN_NODE_BREAKER_VOLTAGE_LEVEL; } public List updateDefaultValuesPriority() { @@ -1213,7 +1213,7 @@ public List updateDefaultValuesPriority() { private double missingPermanentLimitPercentage = 100; - private final boolean updateTerminalConnectionInNodeBreakerVoltageLevel = false; + private static final boolean UPDATE_TERMINAL_CONNECTION_IN_NODE_BREAKER_VOLTAGE_LEVEL = false; private final List updateDefaultValuesPriority = List.of(DefaultValue.EQ, DefaultValue.NAN); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java index 4c2706a268e..aa99922658a 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java @@ -47,11 +47,11 @@ public void convert() { .setLoadType(loadType); identify(adder); connection(adder); - Load load = adder.add(); - addAliasesAndProperties(load); - mappingTerminals(load.getTerminal()); + Load newLoad = adder.add(); + addAliasesAndProperties(newLoad); + mappingTerminals(newLoad.getTerminal()); - addSpecificProperties(load); + addSpecificProperties(newLoad); } @Override @@ -62,8 +62,8 @@ public void update(Network network) { .setQ0(qupdatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), gettDefaultValue(context)))); } - private static void addSpecificProperties(Load load) { - load.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ASYNCHRONOUS_MACHINE); + private static void addSpecificProperties(Load newLoad) { + newLoad.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ASYNCHRONOUS_MACHINE); } private static Conversion.Config.DefaultValue gettDefaultValue(Context context) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index 3a21632c803..20487491e88 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -63,13 +63,13 @@ public void convert() { mappingTerminals(load.getTerminal()); setLoadDetail(loadKind, load, pFixed, qFixed); - addSpecificProperties(load, loadKind, pFixed, qFixed); + addSpecificProperties(load, pFixed, qFixed); } - private static void addSpecificProperties(Load load, String loadKind, double pFixed, double qFixed) { - load.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, loadKind); - load.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + P_FIXED, String.valueOf(pFixed)); - load.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + Q_FIXED, String.valueOf(qFixed)); + private void addSpecificProperties(Load newLoad, double pFixed, double qFixed) { + newLoad.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, loadKind); + newLoad.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + P_FIXED, String.valueOf(pFixed)); + newLoad.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + Q_FIXED, String.valueOf(qFixed)); } private void model(LoadAdder adder) { @@ -160,27 +160,27 @@ public void update(Network network) { .setQ0(qupdatedQ0().orElse(defaultQ(qFixed, load.getQ0(), getDefaultValue(context)))); String loadKind = load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS); - updateLoadDetail(loadKind, load, pFixed, qFixed); + updateLoadDetail(loadKind, pFixed, qFixed); } private static Conversion.Config.DefaultValue getDefaultValue(Context context) { return selectDefaultValue(List.of(EQ, PREVIOUS, ZERO, NAN), context); } - private static void updateLoadDetail(String type, Load updatedLoad, double pFixed, double qFixed) { + private void updateLoadDetail(String type, double pFixed, double qFixed) { if (type == null) { return; } - LoadDetail loadDetail = updatedLoad.getExtension(LoadDetail.class); + LoadDetail loadDetail = load.getExtension(LoadDetail.class); if (loadDetail == null) { return; } if (type.equals("ConformLoad")) { // ConformLoad represent loads that follow a daily load change pattern where the pattern can be used to scale the load with a system load - loadDetail.setVariableActivePower(Double.isFinite(updatedLoad.getP0()) ? (float) updatedLoad.getP0() : (float) pFixed) - .setVariableReactivePower(Double.isFinite(updatedLoad.getQ0()) ? (float) updatedLoad.getQ0() : (float) qFixed); + loadDetail.setVariableActivePower(Double.isFinite(load.getP0()) ? (float) load.getP0() : (float) pFixed) + .setVariableReactivePower(Double.isFinite(load.getQ0()) ? (float) load.getQ0() : (float) qFixed); } else if (type.equals("NonConformLoad")) { // does not participate in scaling - loadDetail.setFixedActivePower(Double.isFinite(updatedLoad.getP0()) ? (float) updatedLoad.getP0() : (float) pFixed) - .setFixedReactivePower(Double.isFinite(updatedLoad.getQ0()) ? (float) updatedLoad.getQ0() : (float) qFixed); + loadDetail.setFixedActivePower(Double.isFinite(load.getP0()) ? (float) load.getP0() : (float) pFixed) + .setFixedReactivePower(Double.isFinite(load.getQ0()) ? (float) load.getQ0() : (float) qFixed); } } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java index 870597978ab..7b64d595d05 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java @@ -41,15 +41,15 @@ public void convert() { .setLoadType(loadType); identify(adder); connection(adder); - Load load = adder.add(); - addAliasesAndProperties(load); - mappingTerminals(load.getTerminal()); + Load newLoad = adder.add(); + addAliasesAndProperties(newLoad); + mappingTerminals(newLoad.getTerminal()); - addSpecificProperties(load); + addSpecificProperties(newLoad); } - private static void addSpecificProperties(Load load) { - load.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ENERGY_SOURCE); + private static void addSpecificProperties(Load newLoad) { + newLoad.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ENERGY_SOURCE); } @Override From fafaf11b2a1d2bdaf8a8d46615ab5e7b5229b235 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 16 Oct 2024 20:38:54 +0200 Subject: [PATCH 08/54] Pretty code Signed-off-by: marquesja1 --- .../elements/EnergyConsumerConversion.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index 20487491e88..dc66c6a978e 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -58,12 +58,12 @@ public void convert() { identify(adder); connection(adder); model(adder); - Load load = adder.add(); - addAliasesAndProperties(load); - mappingTerminals(load.getTerminal()); - setLoadDetail(loadKind, load, pFixed, qFixed); + Load newLoad = adder.add(); + addAliasesAndProperties(newLoad); + mappingTerminals(newLoad.getTerminal()); + setLoadDetail(loadKind, newLoad, pFixed, qFixed); - addSpecificProperties(load, pFixed, qFixed); + addSpecificProperties(newLoad, pFixed, qFixed); } private void addSpecificProperties(Load newLoad, double pFixed, double qFixed) { @@ -130,16 +130,16 @@ private void addZipModel(LoadAdder adder) { } } - private static void setLoadDetail(String type, Load load, double pFixed, double qFixed) { + private static void setLoadDetail(String type, Load newLoad, double pFixed, double qFixed) { if (type.equals("ConformLoad")) { // ConformLoad represent loads that follow a daily load change pattern where the pattern can be used to scale the load with a system load - load.newExtension(LoadDetailAdder.class) + newLoad.newExtension(LoadDetailAdder.class) .withFixedActivePower(0) .withFixedReactivePower(0) .withVariableActivePower((float) pFixed) .withVariableReactivePower((float) qFixed) .add(); } else if (type.equals("NonConformLoad")) { // does not participate in scaling - load.newExtension(LoadDetailAdder.class) + newLoad.newExtension(LoadDetailAdder.class) .withFixedActivePower((float) pFixed) .withFixedReactivePower((float) qFixed) .withVariableActivePower(0) @@ -159,8 +159,7 @@ public void update(Network network) { load.setP0(updatedP0().orElse(defaultP(pFixed, load.getP0(), getDefaultValue(context)))) .setQ0(qupdatedQ0().orElse(defaultQ(qFixed, load.getQ0(), getDefaultValue(context)))); - String loadKind = load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS); - updateLoadDetail(loadKind, pFixed, qFixed); + updateLoadDetail(load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS), pFixed, qFixed); } private static Conversion.Config.DefaultValue getDefaultValue(Context context) { From 004b82457518190945750071387848c45565e223 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Fri, 18 Oct 2024 08:25:25 +0200 Subject: [PATCH 09/54] Pretty code Signed-off-by: marquesja1 --- .../com/powsybl/cgmes/conversion/Conversion.java | 6 +++--- .../AbstractConductingEquipmentConversion.java | 12 ++++++------ .../elements/AsynchronousMachineConversion.java | 3 +-- .../elements/EnergyConsumerConversion.java | 2 +- .../conversion/elements/EnergySourceConversion.java | 2 +- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java index 4b92770a6a3..628de8902a4 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java @@ -977,8 +977,8 @@ public enum StateProfile { public enum DefaultValue { EQ, - ZERO, - NAN, + DEFAULT, + EMPTY, PREVIOUS } @@ -1215,7 +1215,7 @@ public List updateDefaultValuesPriority() { private static final boolean UPDATE_TERMINAL_CONNECTION_IN_NODE_BREAKER_VOLTAGE_LEVEL = false; - private final List updateDefaultValuesPriority = List.of(DefaultValue.EQ, DefaultValue.NAN); + private final List updateDefaultValuesPriority = List.of(DefaultValue.EQ, DefaultValue.EMPTY); } private final CgmesModel cgmes; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index 1204e52e8a4..bf1eb699a3d 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -28,7 +28,7 @@ import java.util.Optional; import java.util.OptionalDouble; -import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.NAN; +import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.EMPTY; import static com.powsybl.cgmes.conversion.Update.isConvertSeparatedFromUpdate; /** @@ -804,15 +804,15 @@ protected OptionalDouble qupdatedQ0() { } protected static Conversion.Config.DefaultValue selectDefaultValue(List validDefaultValues, Context context) { - return context.config().updateDefaultValuesPriority().stream().filter(validDefaultValues::contains).findFirst().orElse(NAN); + return context.config().updateDefaultValuesPriority().stream().filter(validDefaultValues::contains).findFirst().orElse(EMPTY); } protected static double defaultP(double eqP, double previousP, Conversion.Config.DefaultValue defaultValue) { return switch (defaultValue) { case EQ -> eqP; case PREVIOUS -> previousP; - case ZERO -> 0.0; - case NAN -> Double.NaN; + case DEFAULT -> 0.0; + case EMPTY -> Double.NaN; }; } @@ -820,8 +820,8 @@ protected static double defaultQ(double eqQ, double previousQ, Conversion.Config return switch (defaultValue) { case EQ -> eqQ; case PREVIOUS -> previousQ; - case ZERO -> 0.0; - case NAN -> Double.NaN; + case DEFAULT -> 0.0; + case EMPTY -> Double.NaN; }; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java index aa99922658a..0d70eb7c72f 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java @@ -21,7 +21,6 @@ import java.util.Objects; import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; -import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.NAN; /** * @author Luma Zamarreño {@literal } @@ -67,7 +66,7 @@ private static void addSpecificProperties(Load newLoad) { } private static Conversion.Config.DefaultValue gettDefaultValue(Context context) { - return selectDefaultValue(List.of(PREVIOUS, ZERO, NAN), context); + return selectDefaultValue(List.of(PREVIOUS, DEFAULT, EMPTY), context); } private final Load load; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index dc66c6a978e..d889fb0b19a 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -163,7 +163,7 @@ public void update(Network network) { } private static Conversion.Config.DefaultValue getDefaultValue(Context context) { - return selectDefaultValue(List.of(EQ, PREVIOUS, ZERO, NAN), context); + return selectDefaultValue(List.of(EQ, PREVIOUS, DEFAULT, EMPTY), context); } private void updateLoadDetail(String type, double pFixed, double qFixed) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java index 7b64d595d05..fbe9af26f88 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java @@ -61,7 +61,7 @@ public void update(Network network) { } private static Conversion.Config.DefaultValue getDefaultValue(Context context) { - return selectDefaultValue(List.of(PREVIOUS, ZERO, NAN), context); + return selectDefaultValue(List.of(PREVIOUS, DEFAULT, EMPTY), context); } private final Load load; From 8dc44cfefdf92aa0cfec3d55b5c4a4014bc8f684 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 6 Nov 2024 12:49:17 +0100 Subject: [PATCH 10/54] update Signed-off-by: marquesja1 --- .../cgmes/conversion/CgmesReports.java | 8 + .../com/powsybl/cgmes/conversion/Context.java | 26 ++ .../powsybl/cgmes/conversion/Conversion.java | 7 + ...gulatingControlMappingForTransformers.java | 154 ++------- .../com/powsybl/cgmes/conversion/Update.java | 54 +++- ...AbstractConductingEquipmentConversion.java | 46 ++- .../AbstractIdentifiedObjectConversion.java | 9 + .../elements/OperationalLimitConversion.java | 219 ++++++++++--- .../AbstractTransformerConversion.java | 294 ++++++++++++++++-- .../ThreeWindingsTransformerConversion.java | 53 +++- .../TwoWindingsTransformerConversion.java | 32 +- .../conversion/export/CgmesExportUtil.java | 35 ++- .../conversion/export/EquipmentExport.java | 16 +- .../export/SteadyStateHypothesisExport.java | 14 +- ...icroGridBaseCaseBE-invalid-voltage-bus.txt | 9 +- .../microGridBaseCaseBE-target-deadband.txt | 13 +- .../functional-logs/microGridBaseCaseBE.txt | 9 +- .../functional-logs/miniGridNodeBreaker.txt | 3 + .../extensions/CgmesTapChangerAdderImpl.java | 6 +- .../extensions/CgmesTapChangersSerDe.java | 4 +- .../extensions/CgmesTapChangersSerDeTest.java | 1 + .../resources/eurostag_cgmes_tap_changers.xml | 2 +- .../com/powsybl/cgmes/model/CgmesNames.java | 1 + 23 files changed, 762 insertions(+), 253 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java index d410c73be34..2a9250372c2 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java @@ -51,6 +51,14 @@ public static ReportNode convertingElementTypeReport(ReportNode reportNode, Stri .add(); } + public static ReportNode updatingElementTypeReport(ReportNode reportNode, String elementType) { + return reportNode.newReportNode() + .withMessageTemplate("updatingElementType", "Updating ${elementType}.") + .withUntypedValue("elementType", elementType) + .withSeverity(TypedValue.INFO_SEVERITY) + .add(); + } + public static ReportNode fixingDanglingLinesIssuesReport(ReportNode reportNode) { return reportNode.newReportNode() .withMessageTemplate("fixingDanglingLinesIssues", "Fixing issues with dangling lines.") diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java index 16b33842697..0fc7e103fa7 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java @@ -65,6 +65,8 @@ public Context(CgmesModel cgmes, Config config, Network network, ReportNode repo powerTransformerRatioTapChangers = new HashMap<>(); powerTransformerPhaseTapChangers = new HashMap<>(); cgmesTerminals = new HashMap<>(); + regulatingControls = new HashMap<>(); + operationalLimits = new HashMap<>(); } public CgmesModel cgmes() { @@ -223,6 +225,28 @@ public PropertyBag cgmesTerminal(String id) { return cgmesTerminals.get(id); } + public void loadRegulatingControls() { + cgmes.regulatingControls().forEach(p -> { + String id = p.getId(CgmesNames.REGULATING_CONTROL); + regulatingControls.put(id, p); + }); + } + + public PropertyBag regulatingControl(String id) { + return regulatingControls.get(id); + } + + public void loadOperationalLimits() { + cgmes.operationalLimits().forEach(op -> { + String id = op.getId(CgmesNames.OPERATIONAL_LIMIT); + operationalLimits.put(id, op); + }); + } + + public PropertyBag operationalLimit(String id) { + return operationalLimits.get(id); + } + // Handling issues found during conversion public ReportNode getReportNode() { @@ -337,6 +361,8 @@ private static void logIssue(ConversionIssueCategory category, String what, Supp private final Map powerTransformerRatioTapChangers; private final Map powerTransformerPhaseTapChangers; private final Map cgmesTerminals; + private final Map regulatingControls; + private final Map operationalLimits; private static final Logger LOG = LoggerFactory.getLogger(Context.class); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java index 628de8902a4..5d81eeb6d50 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java @@ -38,6 +38,7 @@ import static com.powsybl.cgmes.conversion.Conversion.Config.StateProfile.SSH; import static com.powsybl.cgmes.conversion.Update.updateLoads; +import static com.powsybl.cgmes.conversion.Update.updateTwoAndThreeWindingsTransformers; import static java.util.stream.Collectors.groupingBy; /** @@ -331,6 +332,8 @@ private void update(Network network, Context updateContext, ReportNode reportNod } updateLoads(network, cgmes, updateContext); + updateTwoAndThreeWindingsTransformers(network, updateContext); + network.runValidationChecks(false, reportNode); network.setMinimumAcceptableValidationLevel(ValidationLevel.STEADY_STATE_HYPOTHESIS); } @@ -539,6 +542,10 @@ private Context createContext(Network network, ReportNode reportNode) { private Context createUpdateContext(Network network, ReportNode reportNode) { Context context = new Context(cgmes, config, network, reportNode); context.loadCgmesTerminals(); + context.loadRatioTapChangers(); + context.loadPhaseTapChangers(); + context.loadRegulatingControls(); + context.loadOperationalLimits(); return context; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForTransformers.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForTransformers.java index fba4b2c8cf7..15c88a2b489 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForTransformers.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForTransformers.java @@ -18,9 +18,6 @@ import java.util.Map; import java.util.Optional; -import static com.powsybl.cgmes.conversion.CgmesReports.badTargetDeadbandRegulatingControlReport; -import static com.powsybl.cgmes.conversion.CgmesReports.badVoltageTargetValueRegulatingControlReport; - /** * @author José Antonio Marqués {@literal } * @author Marcos de Miguel {@literal } @@ -57,22 +54,18 @@ public void add(String transformerId, CgmesRegulatingControlRatio rcRtc1, CgmesR t3xMapping.put(transformerId, rc); } - public CgmesRegulatingControlRatio buildRegulatingControlRatio(String id, String regulatingControlId, - String tculControlMode, boolean tapChangerControlEnabled) { + public CgmesRegulatingControlRatio buildRegulatingControlRatio(String id, String regulatingControlId, String tculControlMode) { CgmesRegulatingControlRatio rtc = new CgmesRegulatingControlRatio(); rtc.id = id; rtc.regulatingControlId = regulatingControlId; rtc.tculControlMode = tculControlMode; - rtc.tapChangerControlEnabled = tapChangerControlEnabled; return rtc; } - public CgmesRegulatingControlPhase buildRegulatingControlPhase(String id, String regulatingControlId, - boolean tapChangerControlEnabled, boolean ltcFlag) { + public CgmesRegulatingControlPhase buildRegulatingControlPhase(String id, String regulatingControlId, boolean ltcFlag) { CgmesRegulatingControlPhase rtc = new CgmesRegulatingControlPhase(); rtc.id = id; rtc.regulatingControlId = regulatingControlId; - rtc.tapChangerControlEnabled = tapChangerControlEnabled; rtc.ltcFlag = ltcFlag; return rtc; } @@ -87,22 +80,16 @@ private void applyTapChangersRegulatingControl(TwoWindingsTransformer twt) { applyTapChangersRegulatingControl(twt, rc); } - private void applyTapChangersRegulatingControl(TwoWindingsTransformer twt, - CgmesRegulatingControlForTwoWindingsTransformer rc) { + private void applyTapChangersRegulatingControl(TwoWindingsTransformer twt, CgmesRegulatingControlForTwoWindingsTransformer rc) { if (rc == null) { return; } RegulatingControl rtcControl = getTapChangerControl(rc.ratioTapChanger); - boolean rtcRegulating = isTapChangerRegulating(rtcControl, rc.ratioTapChanger); RegulatingControl ptcControl = getTapChangerControl(rc.phaseTapChanger); - boolean ptcRegulating = isTapChangerRegulating(ptcControl, rc.phaseTapChanger); - - setPhaseTapChangerControl(ptcRegulating, rc.phaseTapChanger, ptcControl, twt.getPhaseTapChanger()); - boolean regulatingSet = twt.hasPhaseTapChanger() && twt.getPhaseTapChanger().isRegulating(); - rtcRegulating = checkOnlyOneEnabled(twt.getId(), rtcRegulating, regulatingSet, "ratioTapChanger"); - setRatioTapChangerControl(rtcRegulating, rc.ratioTapChanger, rtcControl, twt.getRatioTapChanger()); + setPhaseTapChangerControl(rc.phaseTapChanger, ptcControl, twt.getPhaseTapChanger(), twt, ""); + setRatioTapChangerControl(rtcControl, twt.getRatioTapChanger()); } private void applyTapChangersRegulatingControl(ThreeWindingsTransformer twt) { @@ -110,151 +97,86 @@ private void applyTapChangersRegulatingControl(ThreeWindingsTransformer twt) { applyTapChangersRegulatingControl(twt, rc); } - private void applyTapChangersRegulatingControl(ThreeWindingsTransformer twt, - CgmesRegulatingControlForThreeWindingsTransformer rc) { + private void applyTapChangersRegulatingControl(ThreeWindingsTransformer twt, CgmesRegulatingControlForThreeWindingsTransformer rc) { if (rc == null) { return; } RegulatingControl rtcControl1 = getTapChangerControl(rc.ratioTapChanger1); - boolean rtcRegulating1 = isTapChangerRegulating(rtcControl1, rc.ratioTapChanger1); RegulatingControl ptcControl1 = getTapChangerControl(rc.phaseTapChanger1); - boolean ptcRegulating1 = isTapChangerRegulating(ptcControl1, rc.phaseTapChanger1); RegulatingControl rtcControl2 = getTapChangerControl(rc.ratioTapChanger2); - boolean rtcRegulating2 = isTapChangerRegulating(rtcControl2, rc.ratioTapChanger2); RegulatingControl ptcControl2 = getTapChangerControl(rc.phaseTapChanger2); - boolean ptcRegulating2 = isTapChangerRegulating(ptcControl2, rc.phaseTapChanger2); RegulatingControl rtcControl3 = getTapChangerControl(rc.ratioTapChanger3); - boolean rtcRegulating3 = isTapChangerRegulating(rtcControl3, rc.ratioTapChanger3); RegulatingControl ptcControl3 = getTapChangerControl(rc.phaseTapChanger3); - boolean ptcRegulating3 = isTapChangerRegulating(ptcControl3, rc.phaseTapChanger3); - - setPhaseTapChangerControl(ptcRegulating1, rc.phaseTapChanger1, ptcControl1, twt.getLeg1().getPhaseTapChanger()); - boolean regulatingSet = twt.getLeg1().hasPhaseTapChanger() && twt.getLeg1().getPhaseTapChanger().isRegulating(); - - rtcRegulating1 = checkOnlyOneEnabled(twt.getId(), rtcRegulating1, regulatingSet, "ratioTapChanger at Leg1"); - setRatioTapChangerControl(rtcRegulating1, rc.ratioTapChanger1, rtcControl1, twt.getLeg1().getRatioTapChanger()); - regulatingSet = regulatingSet - || twt.getLeg1().hasRatioTapChanger() && twt.getLeg1().getRatioTapChanger().isRegulating(); - - ptcRegulating2 = checkOnlyOneEnabled(twt.getId(), ptcRegulating2, regulatingSet, "phaseTapChanger at Leg2"); - setPhaseTapChangerControl(ptcRegulating2, rc.phaseTapChanger2, ptcControl2, twt.getLeg2().getPhaseTapChanger()); - regulatingSet = regulatingSet - || twt.getLeg2().hasPhaseTapChanger() && twt.getLeg2().getPhaseTapChanger().isRegulating(); - - rtcRegulating2 = checkOnlyOneEnabled(twt.getId(), rtcRegulating2, regulatingSet, "ratioTapChanger at Leg2"); - setRatioTapChangerControl(rtcRegulating2, rc.ratioTapChanger2, rtcControl2, twt.getLeg2().getRatioTapChanger()); - regulatingSet = regulatingSet - || twt.getLeg2().hasRatioTapChanger() && twt.getLeg2().getRatioTapChanger().isRegulating(); - ptcRegulating3 = checkOnlyOneEnabled(twt.getId(), ptcRegulating3, regulatingSet, "phaseTapChanger at Leg3"); - setPhaseTapChangerControl(ptcRegulating3, rc.phaseTapChanger3, ptcControl3, twt.getLeg3().getPhaseTapChanger()); - regulatingSet = regulatingSet - || twt.getLeg3().hasPhaseTapChanger() && twt.getLeg3().getPhaseTapChanger().isRegulating(); + setPhaseTapChangerControl(rc.phaseTapChanger1, ptcControl1, twt.getLeg1().getPhaseTapChanger(), twt, "1"); + setRatioTapChangerControl(rtcControl1, twt.getLeg1().getRatioTapChanger()); - rtcRegulating3 = checkOnlyOneEnabled(twt.getId(), rtcRegulating3, regulatingSet, "ratioTapChanger at Leg3"); - setRatioTapChangerControl(rtcRegulating3, rc.ratioTapChanger3, rtcControl3, twt.getLeg3().getRatioTapChanger()); - } - - private static boolean isTapChangerRegulating(RegulatingControl rc, CgmesRegulatingControl tcrc) { - return rc != null && rc.enabled && tcrc.tapChangerControlEnabled; - } + setPhaseTapChangerControl(rc.phaseTapChanger2, ptcControl2, twt.getLeg2().getPhaseTapChanger(), twt, "2"); + setRatioTapChangerControl(rtcControl2, twt.getLeg2().getRatioTapChanger()); - private boolean checkOnlyOneEnabled(String transformerId, boolean regulating, boolean setRegulating, - String disabledTapChanger) { - if (!regulating) { - return false; - } - if (setRegulating) { - context.fixed(transformerId, - "Unsupported more than one regulating control enabled. Disable " + disabledTapChanger); - return false; - } - return true; + setPhaseTapChangerControl(rc.phaseTapChanger3, ptcControl3, twt.getLeg3().getPhaseTapChanger(), twt, "3"); + setRatioTapChangerControl(rtcControl3, twt.getLeg3().getRatioTapChanger()); } - private void setRatioTapChangerControl(boolean regulating, CgmesRegulatingControlRatio rc, - RegulatingControl control, RatioTapChanger rtc) { + private void setRatioTapChangerControl(RegulatingControl control, RatioTapChanger rtc) { if (control == null || rtc == null) { return; } boolean okSet = false; if (RegulatingControlMapping.isControlModeVoltage(control.mode)) { - okSet = setRtcRegulatingControlVoltage(rc.id, regulating, control, rtc, context); + okSet = setRtcRegulatingControlVoltage(control, rtc, context); } else if (!isControlModeFixed(control.mode)) { context.fixed(control.mode, - "Unsupported regulation mode for Ratio tap changer. Considered as a fixed ratio tap changer."); + "Unsupported regulation mode for Ratio tap changer. Considered as a fixed ratio tap changer."); } control.setCorrectlySet(okSet); } - private boolean setRtcRegulatingControlVoltage(String rtcId, boolean regulating, RegulatingControl control, - RatioTapChanger rtc, Context context) { + private boolean setRtcRegulatingControlVoltage(RegulatingControl control, RatioTapChanger rtc, Context context) { Optional regulatingTerminal = RegulatingTerminalMapper.mapForVoltageControl(control.cgmesTerminal, context); if (regulatingTerminal.isEmpty()) { context.missing(String.format(RegulatingControlMapping.MISSING_IIDM_TERMINAL, control.cgmesTerminal)); return false; } - // We always keep the targetValue - // It targetValue is not valid, emit a warning and deactivate regulating control - boolean validTargetValue = control.targetValue > 0; - if (!validTargetValue) { - context.invalid(rtcId, "Regulating control has a bad target voltage " + control.targetValue); - badVoltageTargetValueRegulatingControlReport(context.getReportNode(), rtcId, control.targetValue); - } - - boolean validTargetDeadband = control.targetDeadband >= 0; - if (!validTargetDeadband) { - context.invalid(rtcId, "Regulating control has a bad target deadband " + control.targetDeadband); - badTargetDeadbandRegulatingControlReport(context.getReportNode(), rtcId, control.targetDeadband); - } - - // Order is important rtc.setRegulationTerminal(regulatingTerminal.get()) - .setTargetV(control.targetValue) - .setTargetDeadband(validTargetDeadband ? control.targetDeadband : Double.NaN) - .setRegulating(regulating && validTargetValue && validTargetDeadband); - + .setRegulationMode(RatioTapChanger.RegulationMode.VOLTAGE); return true; } - private void setPhaseTapChangerControl(boolean regulating, CgmesRegulatingControlPhase rc, - RegulatingControl control, PhaseTapChanger ptc) { + private void setPhaseTapChangerControl(CgmesRegulatingControlPhase rc, RegulatingControl control, PhaseTapChanger ptc, Connectable twt, String end) { if (control == null || ptc == null) { return; } boolean okSet = false; if (control.mode.endsWith("currentflow")) { - okSet = setPtcRegulatingControlCurrentFlow(rc.id, regulating, rc.ltcFlag, control, ptc, context); + okSet = setPtcRegulatingControlCurrentFlow(rc.ltcFlag, control, ptc, context, twt, end); } else if (control.mode.endsWith("activepower")) { - okSet = setPtcRegulatingControlActivePower(rc.id, regulating, rc.ltcFlag, control, ptc, context); + okSet = setPtcRegulatingControlActivePower(rc.ltcFlag, control, ptc, context, twt, end); } else if (!control.mode.endsWith("fixed")) { context.fixed(control.mode, "Unsupported regulating mode for Phase tap changer. Considered as FIXED_TAP"); } control.setCorrectlySet(okSet); } - private boolean setPtcRegulatingControlCurrentFlow(String ptcId, boolean regulating, boolean ltcFlag, RegulatingControl control, - PhaseTapChanger ptc, Context context) { + private boolean setPtcRegulatingControlCurrentFlow(boolean ltcFlag, RegulatingControl control, PhaseTapChanger ptc, Context context, Connectable twt, String end) { PhaseTapChanger.RegulationMode regulationMode = getPtcRegulatingMode(ltcFlag, PhaseTapChanger.RegulationMode.CURRENT_LIMITER); - return setPtcRegulatingControl(ptcId, regulating, regulationMode, control, ptc, context); + return setPtcRegulatingControl(regulationMode, control, ptc, context, twt, end); } - private boolean setPtcRegulatingControlActivePower(String ptcId, boolean regulating, boolean ltcFlag, RegulatingControl control, - PhaseTapChanger ptc, Context context) { + private boolean setPtcRegulatingControlActivePower(boolean ltcFlag, RegulatingControl control, PhaseTapChanger ptc, Context context, Connectable twt, String end) { PhaseTapChanger.RegulationMode regulationMode = getPtcRegulatingMode(ltcFlag, PhaseTapChanger.RegulationMode.ACTIVE_POWER_CONTROL); - return setPtcRegulatingControl(ptcId, regulating, regulationMode, control, ptc, context); + return setPtcRegulatingControl(regulationMode, control, ptc, context, twt, end); } - private boolean setPtcRegulatingControl(String ptcId, boolean regulating, PhaseTapChanger.RegulationMode regulationMode, - RegulatingControl control, PhaseTapChanger ptc, Context context) { + private boolean setPtcRegulatingControl(PhaseTapChanger.RegulationMode regulationMode, RegulatingControl control, PhaseTapChanger ptc, Context context, Connectable twt, String end) { TerminalAndSign mappedRegulatingTerminal = RegulatingTerminalMapper .mapForFlowControl(control.cgmesTerminal, context) .orElseGet(() -> new TerminalAndSign(null, 1)); @@ -264,30 +186,15 @@ private boolean setPtcRegulatingControl(String ptcId, boolean regulating, PhaseT return false; } - boolean fixedRegulating = regulating; - if (regulating && regulationMode == PhaseTapChanger.RegulationMode.FIXED_TAP) { - context.fixed(ptcId, "RegulationMode: regulating is set to true whereas regulationMode is set to FIXED_TAP: regulating fixed to false"); - fixedRegulating = false; - } - - boolean validTargetDeadband = control.targetDeadband >= 0; - if (!validTargetDeadband) { - context.invalid(ptcId, "Regulating control has a bad target deadband " + control.targetDeadband); - badTargetDeadbandRegulatingControlReport(context.getReportNode(), ptcId, control.targetDeadband); - } - - // Order is important ptc.setRegulationTerminal(mappedRegulatingTerminal.getTerminal()) - .setRegulationValue(control.targetValue * mappedRegulatingTerminal.getSign()) - .setTargetDeadband(validTargetDeadband ? control.targetDeadband : Double.NaN) - .setRegulationMode(regulationMode) - .setRegulating(fixedRegulating && validTargetDeadband); + .setRegulationMode(regulationMode); + + twt.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "terminalSign" + end, String.valueOf(mappedRegulatingTerminal.getSign())); return true; } - private PhaseTapChanger.RegulationMode getPtcRegulatingMode(boolean ltcFlag, - PhaseTapChanger.RegulationMode regulationMode) { + private PhaseTapChanger.RegulationMode getPtcRegulatingMode(boolean ltcFlag, PhaseTapChanger.RegulationMode regulationMode) { // According to the following CGMES documentation: // IEC TS 61970-600-1, Edition 1.0, 2017-07. // "Energy management system application program interface (EMS-API) @@ -376,7 +283,7 @@ private static final class CgmesRegulatingControlForTwoWindingsTransformer { } public static class CgmesRegulatingControlRatio extends CgmesRegulatingControl { - String tculControlMode; // mode in SSH values of RTC + String tculControlMode; } public static class CgmesRegulatingControlPhase extends CgmesRegulatingControl { @@ -386,7 +293,6 @@ public static class CgmesRegulatingControlPhase extends CgmesRegulatingControl { private static class CgmesRegulatingControl { String id; String regulatingControlId; - boolean tapChangerControlEnabled; // enabled status in SSH values of PTC/RTC } private final RegulatingControlMapping parent; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java index d6a8c407dd8..68b0bb9a2d0 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java @@ -10,19 +10,15 @@ import com.powsybl.cgmes.conversion.elements.AsynchronousMachineConversion; import com.powsybl.cgmes.conversion.elements.EnergyConsumerConversion; import com.powsybl.cgmes.conversion.elements.EnergySourceConversion; +import com.powsybl.cgmes.conversion.elements.transformers.ThreeWindingsTransformerConversion; +import com.powsybl.cgmes.conversion.elements.transformers.TwoWindingsTransformerConversion; import com.powsybl.cgmes.model.CgmesModel; import com.powsybl.cgmes.model.CgmesNames; -import com.powsybl.iidm.network.Connectable; -import com.powsybl.iidm.network.Identifiable; -import com.powsybl.iidm.network.Load; -import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.*; import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; +import java.util.*; /** * @author Luma Zamarreño {@literal } @@ -40,16 +36,19 @@ public static boolean isConvertSeparatedFromUpdate(PropertyBag p) { || p.propertyNames().contains("NonConformLoad") || p.propertyNames().contains("ConformLoad") || p.propertyNames().contains("StationSupply") - || p.propertyNames().contains("AsynchronousMachine"); + || p.propertyNames().contains("TwoWindingsTransformer"); } static void updateLoads(Network network, CgmesModel cgmes, Context context) { + context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.LOAD.name())); + Map identifiablePropertyBag = new HashMap<>(); addPropertyBags(network, cgmes.energyConsumers(), CgmesNames.ENERGY_CONSUMER, identifiablePropertyBag); addPropertyBags(network, cgmes.energySources(), CgmesNames.ENERGY_SOURCE, identifiablePropertyBag); addPropertyBags(network, cgmes.asynchronousMachines(), CgmesNames.ASYNCHRONOUS_MACHINE, identifiablePropertyBag); network.getLoads().forEach(load -> updateLoad(network, load, getPropertyBag(load.getId(), identifiablePropertyBag), context)); + context.popReportNode(); } private static void updateLoad(Network network, Load load, PropertyBag propertyBag, Context context) { @@ -69,6 +68,26 @@ private static void updateLoad(Network network, Load load, PropertyBag propertyB } } + static void updateTwoAndThreeWindingsTransformers(Network network, Context context) { + context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.TWO_WINDINGS_TRANSFORMER.name())); + network.getTwoWindingsTransformers().forEach(t2w -> updateTwoWindingsTransformer(network, t2w, namedPropertyBag("TwoWindingsTransformer", t2w.getId()), context)); + context.popReportNode(); + + context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.THREE_WINDINGS_TRANSFORMER.name())); + network.getThreeWindingsTransformers().forEach(t3w -> updateThreeWindingsTransformer(network, t3w, namedPropertyBag("ThreeWindingsTransformer", t3w.getId()), context)); + context.popReportNode(); + } + + private static void updateTwoWindingsTransformer(Network network, TwoWindingsTransformer t2w, PropertyBag propertyBag, Context context) { + PropertyBags cgmesTerminals = getPropertyBagsOfCgmesTerminals(t2w, context); + new TwoWindingsTransformerConversion(propertyBag, cgmesTerminals, t2w, context).update(network); + } + + private static void updateThreeWindingsTransformer(Network network, ThreeWindingsTransformer t3w, PropertyBag propertyBag, Context context) { + PropertyBags cgmesTerminals = getPropertyBagsOfCgmesTerminals(t3w, context); + new ThreeWindingsTransformerConversion(propertyBag, cgmesTerminals, t3w, context).update(network); + } + private static void addPropertyBags(Network network, PropertyBags propertyBags, String idTag, Map identifiablePropertyBag) { propertyBags.forEach(propertyBag -> { String propertyBagId = propertyBag.getId(idTag); @@ -92,6 +111,17 @@ private static PropertyBag getPropertyBagOfCgmesTerminal(Connectable connecta } } + private static PropertyBags getPropertyBagsOfCgmesTerminals(Connectable connectable, Context context) { + PropertyBags propertyBags = new PropertyBags(); + connectable.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL1) + .ifPresent(cgmesTerminalId -> propertyBags.add(getPropertyBagOfCgmesTerminal(cgmesTerminalId, context))); + connectable.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL2) + .ifPresent(cgmesTerminalId -> propertyBags.add(getPropertyBagOfCgmesTerminal(cgmesTerminalId, context))); + connectable.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL3) + .ifPresent(cgmesTerminalId -> propertyBags.add(getPropertyBagOfCgmesTerminal(cgmesTerminalId, context))); + return propertyBags; + } + private static PropertyBag getPropertyBagOfCgmesTerminal(String cgmesTerminalId, Context context) { return context.cgmesTerminal(cgmesTerminalId) != null ? context.cgmesTerminal(cgmesTerminalId) : emptyPropertyBag(); } @@ -99,4 +129,10 @@ private static PropertyBag getPropertyBagOfCgmesTerminal(String cgmesTerminalId, private static PropertyBag emptyPropertyBag() { return new PropertyBag(Collections.emptyList(), false); } + + private static PropertyBag namedPropertyBag(String propertyName, String id) { + PropertyBag propertyBag = new PropertyBag(Collections.emptyList(), false); + propertyBag.put(propertyName, id); + return propertyBag; + } } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index bf1eb699a3d..60144999fe1 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -49,7 +49,7 @@ protected AbstractConductingEquipmentConversion( numTerminals = 1; terminals = new TerminalData[]{null, null, null}; terminals[0] = new TerminalData(CgmesNames.TERMINAL, p, context); - steadyStatePowerFlow = null; + steadyStatePowerFlow = PowerFlow.UNDEFINED; updatedTerminals = null; } else { numTerminals = 1; @@ -87,6 +87,7 @@ protected AbstractConductingEquipmentConversion( super(type, ps, context); // Information about each terminal is in each separate property bags // It is assumed the property bags are already sorted + // Same code for property bags where convert has been separated from update this.numTerminals = ps.size(); terminals = new TerminalData[]{null, null, null}; if (numTerminals > 3) { @@ -113,6 +114,21 @@ protected AbstractConductingEquipmentConversion( updatedTerminals[0] = new UpdatedTerminalData(cgmesTerminal); } + protected AbstractConductingEquipmentConversion( + String type, + PropertyBag p, + PropertyBags cgmesTerminals, + Context context) { + super(type, p, context); + numTerminals = cgmesTerminals.size(); + terminals = null; + steadyStatePowerFlow = PowerFlow.UNDEFINED; + updatedTerminals = new UpdatedTerminalData[]{null, null, null}; + for (int i = 0; i < cgmesTerminals.size(); i++) { + updatedTerminals[i] = new UpdatedTerminalData(cgmesTerminals.get(i)); + } + } + public String findPairingKey(String boundaryNode) { return findPairingKey(context, boundaryNode); } @@ -689,6 +705,26 @@ public void connect(BranchAdder adder) { } } + public void connection(BranchAdder adder) { + if (context.nodeBreaker()) { + adder + .setVoltageLevel1(iidmVoltageLevelId(1)) + .setVoltageLevel2(iidmVoltageLevelId(2)) + .setNode1(iidmNode(1)) + .setNode2(iidmNode(2)); + } else { + String busId1 = busId(1); + String busId2 = busId(2); + adder + .setVoltageLevel1(iidmVoltageLevelId(1)) + .setVoltageLevel2(iidmVoltageLevelId(2)) + .setBus1(null) + .setBus2(null) + .setConnectableBus1(busId1) + .setConnectableBus2(busId2); + } + } + public static void connect(Context context, InjectionAdder adder, String busId, boolean connected, int node) { if (context.nodeBreaker()) { adder.setNode(node); @@ -763,7 +799,7 @@ public void connect(VoltageLevel.BusBreakerView.SwitchAdder adder, boolean open) .setOpen(open || !terminalConnected(1) || !terminalConnected(2)); } - public void connect(LegAdder adder, int terminal) { + public void connection(LegAdder adder, int terminal) { if (context.nodeBreaker()) { adder .setVoltageLevel(iidmVoltageLevelId(terminal)) @@ -771,7 +807,7 @@ public void connect(LegAdder adder, int terminal) { } else { adder .setVoltageLevel(iidmVoltageLevelId(terminal)) - .setBus(terminalConnected(terminal) ? busId(terminal) : null) + .setBus(null) .setConnectableBus(busId(terminal)); } } @@ -803,10 +839,6 @@ protected OptionalDouble qupdatedQ0() { return updatedPowerFlow().defined() ? OptionalDouble.of(updatedPowerFlow().q()) : OptionalDouble.empty(); } - protected static Conversion.Config.DefaultValue selectDefaultValue(List validDefaultValues, Context context) { - return context.config().updateDefaultValuesPriority().stream().filter(validDefaultValues::contains).findFirst().orElse(EMPTY); - } - protected static double defaultP(double eqP, double previousP, Conversion.Config.DefaultValue defaultValue) { return switch (defaultValue) { case EQ -> eqP; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java index be8b883060c..c07e237bb27 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java @@ -9,10 +9,15 @@ package com.powsybl.cgmes.conversion.elements; import com.powsybl.cgmes.conversion.Context; +import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.iidm.network.IdentifiableAdder; import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; +import java.util.List; + +import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.EMPTY; + /** * @author Luma Zamarreño {@literal } */ @@ -93,6 +98,10 @@ protected String complete(String what) { } } + protected static Conversion.Config.DefaultValue selectDefaultValue(List validDefaultValues, Context context) { + return context.config().updateDefaultValuesPriority().stream().filter(validDefaultValues::contains).findFirst().orElse(EMPTY); + } + protected final String id; protected final String name; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java index 33ea40fccd5..b8893c5269d 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java @@ -14,9 +14,14 @@ import com.powsybl.iidm.network.*; import com.powsybl.triplestore.api.PropertyBag; +import java.util.List; +import java.util.Objects; import java.util.Optional; +import java.util.OptionalDouble; import java.util.function.Supplier; +import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; + /** * @author Luma Zamarreño {@literal } */ @@ -38,26 +43,27 @@ public OperationalLimitConversion(PropertyBag l, Context context) { String limitSetId = p.getId(OPERATIONAL_LIMIT_SET_ID); String limitSetName = p.getLocal(OPERATIONAL_LIMIT_SET_NAME); limitSetName = limitSetName != null ? limitSetName : limitSetId; - // Limit can associated to a Terminal or to an Equipment + // Limit can be associated to a Terminal or to an Equipment terminalId = l.getId("Terminal"); equipmentId = l.getId("Equipment"); + + this.limitSubclass = fixCim14LimitSubclass(limitSubclass); + Terminal terminal = null; - if (limitSubclass == null || limitSubclass.equals(CgmesNames.ACTIVE_POWER_LIMIT) || limitSubclass.equals(CgmesNames.APPARENT_POWER_LIMIT) || limitSubclass.equals(CgmesNames.CURRENT_LIMIT)) { - if (limitSubclass == null) { - // Support for CIM14, all limits are assumed to be current - limitSubclass = CgmesNames.CURRENT_LIMIT; - } + if (isLoadingLimits()) { if (terminalId != null) { terminal = context.terminalMapping().findForFlowLimits(terminalId); } if (terminal != null) { - checkAndCreateLimitsAdder(context.terminalMapping().number(terminalId), limitSubclass, limitSetId, limitSetName, terminal.getConnectable()); + checkAndCreateLimitsAdder(context.terminalMapping().number(terminalId), limitSetId, limitSetName, terminal.getConnectable()); + this.identifiable = terminal.getConnectable(); } else if (equipmentId != null) { // The equipment may be a Branch, a Dangling line, a Switch ... Identifiable identifiable = context.network().getIdentifiable(equipmentId); - checkAndCreateLimitsAdder(-1, limitSubclass, limitSetId, limitSetName, identifiable); + checkAndCreateLimitsAdder(-1, limitSetId, limitSetName, identifiable); + this.identifiable = identifiable; } - } else if (limitSubclass.equals("VoltageLimit")) { + } else if (isVoltageLimits()) { if (terminalId != null) { terminal = context.terminalMapping().findForVoltageLimits(terminalId); } @@ -67,6 +73,23 @@ public OperationalLimitConversion(PropertyBag l, Context context) { } } + // Support for CIM14, all limits are assumed to be current + private static String fixCim14LimitSubclass(String limitSubclass) { + return limitSubclass == null ? CgmesNames.CURRENT_LIMIT : limitSubclass; + } + + private boolean isLoadingLimits() { + Objects.requireNonNull(limitSubclass); + return limitSubclass.equals(CgmesNames.ACTIVE_POWER_LIMIT) + || limitSubclass.equals(CgmesNames.APPARENT_POWER_LIMIT) + || limitSubclass.equals(CgmesNames.CURRENT_LIMIT); + } + + private boolean isVoltageLimits() { + Objects.requireNonNull(limitSubclass); + return limitSubclass.equals("VoltageLimit"); + } + private void setVoltageLevelForVoltageLimit(Terminal terminal) { if (terminal != null) { vl = terminal.getVoltageLevel(); @@ -132,17 +155,17 @@ private void createLimitsAdder(int terminalNumber, String limitSubClass, String OperationalLimitsGroup limitsGroup = twt.getLeg1().getOperationalLimitsGroup(limitSetId).orElseGet(() -> { twt.setProperty(PROPERTY_PREFIX + limitSetId, limitSetName); return twt.getLeg1().newOperationalLimitsGroup(limitSetId); }); - loadingLimitsAdder = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass); + loadingLimitsAdder1 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass); } else if (terminalNumber == 2) { OperationalLimitsGroup limitsGroup = twt.getLeg2().getOperationalLimitsGroup(limitSetId).orElseGet(() -> { twt.setProperty(PROPERTY_PREFIX + limitSetId, limitSetName); return twt.getLeg2().newOperationalLimitsGroup(limitSetId); }); - loadingLimitsAdder = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass); + loadingLimitsAdder2 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass); } else if (terminalNumber == 3) { OperationalLimitsGroup limitsGroup = twt.getLeg3().getOperationalLimitsGroup(limitSetId).orElseGet(() -> { twt.setProperty(PROPERTY_PREFIX + limitSetId, limitSetName); return twt.getLeg3().newOperationalLimitsGroup(limitSetId); }); - loadingLimitsAdder = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass); + loadingLimitsAdder3 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass); } else { throw new IllegalArgumentException(); } @@ -152,41 +175,40 @@ private void createLimitsAdder(int terminalNumber, String limitSubClass, String * Create LoadingLimitsAdder(s) as per the given inputs. * If the inputs are inconsistent, no limit adder is created. * @param terminalNumber The side of the equipment to which the OperationalLimit applies. - * @param limitSubClass The subclass of the OperationalLimit. * @param limitSetId The set containing the OperationalLimit. * @param limitSetName The name of the set containing the OperationalLimit. * @param identifiable The equipment to which the OperationalLimit applies. */ - private void checkAndCreateLimitsAdder(int terminalNumber, String limitSubClass, String limitSetId, String limitSetName, Identifiable identifiable) { + private void checkAndCreateLimitsAdder(int terminalNumber, String limitSetId, String limitSetName, Identifiable identifiable) { if (identifiable instanceof Line) { Branch b = (Branch) identifiable; if (terminalNumber == -1) { - // Limits appliy to the whole equipment == to both sides - createLimitsAdder(1, limitSubClass, limitSetId, limitSetName, b); - createLimitsAdder(2, limitSubClass, limitSetId, limitSetName, b); + // Limits applied to the whole equipment == to both sides + createLimitsAdder(1, limitSubclass, limitSetId, limitSetName, b); + createLimitsAdder(2, limitSubclass, limitSetId, limitSetName, b); } else if (terminalNumber == 1 || terminalNumber == 2) { - createLimitsAdder(terminalNumber, limitSubClass, limitSetId, limitSetName, b); + createLimitsAdder(terminalNumber, limitSubclass, limitSetId, limitSetName, b); } else { notAssigned(b); } } else if (identifiable instanceof TwoWindingsTransformer) { Branch b = (Branch) identifiable; if (terminalNumber == 1 || terminalNumber == 2) { - createLimitsAdder(terminalNumber, limitSubClass, limitSetId, limitSetName, b); + createLimitsAdder(terminalNumber, limitSubclass, limitSetId, limitSetName, b); } else { if (terminalNumber == -1) { - context.ignored(limitSubClass, "Defined for Equipment TwoWindingsTransformer. Should be defined for one Terminal of Two"); + context.ignored(limitSubclass, "Defined for Equipment TwoWindingsTransformer. Should be defined for one Terminal of Two"); } notAssigned(b); } } else if (identifiable instanceof DanglingLine dl) { - createLimitsAdder(limitSubClass, limitSetId, limitSetName, dl); + createLimitsAdder(limitSubclass, limitSetId, limitSetName, dl); } else if (identifiable instanceof ThreeWindingsTransformer twt) { if (terminalNumber == 1 || terminalNumber == 2 || terminalNumber == 3) { - createLimitsAdder(terminalNumber, limitSubClass, limitSetId, limitSetName, twt); + createLimitsAdder(terminalNumber, limitSubclass, limitSetId, limitSetName, twt); } else { if (terminalNumber == -1) { - context.ignored(limitSubClass, "Defined for Equipment ThreeWindingsTransformer. Should be defined for one Terminal of Three"); + context.ignored(limitSubclass, "Defined for Equipment ThreeWindingsTransformer. Should be defined for one Terminal of Three"); } notAssigned(twt); } @@ -200,7 +222,7 @@ private void checkAndCreateLimitsAdder(int terminalNumber, String limitSubClass, @Override public boolean valid() { - if (vl == null && loadingLimitsAdder == null && loadingLimitsAdder1 == null && loadingLimitsAdder2 == null) { + if (vl == null && loadingLimitsAdder == null && loadingLimitsAdder1 == null && loadingLimitsAdder2 == null && loadingLimitsAdder3 == null) { missing(String.format("Terminal %s or Equipment %s", terminalId, equipmentId)); return false; } @@ -209,9 +231,11 @@ public boolean valid() { @Override public void convert() { - double normalValue = p.asDouble("normalValue"); - double value = p.asDouble("value", normalValue); - if (value <= 0) { + double value = getNormalValueFromEQ(p); + if (Double.isNaN(value)) { + context.ignored(OPERATIONAL_LIMIT, "value is not defined"); + return; + } else if (value <= 0) { context.ignored(OPERATIONAL_LIMIT, "value is <= 0"); return; } @@ -226,6 +250,12 @@ public void convert() { } } + // Cgmes 2.6 value is defined in EQ file + // Cgmes 3.0 normalValue is defined in EQ file and value in SSH + private static double getNormalValueFromEQ(PropertyBag p) { + return p.getDouble("normalValue").orElse(p.getDouble("value").orElse(Double.NaN)); + } + private void convertVoltageLimit(double value) { String limitTypeName = p.getLocal(OPERATIONAL_LIMIT_TYPE_NAME); String limitType = p.getLocal(LIMIT_TYPE); @@ -252,9 +282,10 @@ private boolean isPatl() { return limitTypeName.equals("PATL") || "LimitTypeKind.patl".equals(limitType) || "LimitKind.patl".equals(limitType); } - private void addPatl(double value, LoadingLimitsAdder adder) { + private boolean addPatl(double value, LoadingLimitsAdder adder) { if (Double.isNaN(adder.getPermanentLimit())) { adder.setPermanentLimit(value); + return true; } else { if (terminalId != null) { context.fixed(PERMANENT_LIMIT, () -> String.format("Several permanent limits defined for Terminal %s. Only the lowest is kept.", terminalId)); @@ -263,19 +294,30 @@ private void addPatl(double value, LoadingLimitsAdder adder) { } if (adder.getPermanentLimit() > value) { adder.setPermanentLimit(value); + return true; } } + return false; } private void convertPatl(double value) { + String operationalLimitId = p.getId(CgmesNames.OPERATIONAL_LIMIT); + if (loadingLimitsAdder != null) { - addPatl(value, loadingLimitsAdder); + boolean added = addPatl(value, loadingLimitsAdder); + addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "", value); } else { if (loadingLimitsAdder1 != null) { - addPatl(value, loadingLimitsAdder1); + boolean added = addPatl(value, loadingLimitsAdder1); + addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "1", value); } if (loadingLimitsAdder2 != null) { - addPatl(value, loadingLimitsAdder2); + boolean added = addPatl(value, loadingLimitsAdder2); + addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "2", value); + } + if (loadingLimitsAdder3 != null) { + boolean added = addPatl(value, loadingLimitsAdder3); + addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "3", value); } } } @@ -286,10 +328,10 @@ private boolean isTatl() { return limitTypeName.equals("TATL") || "LimitTypeKind.tatl".equals(limitType) || "LimitKind.tatl".equals(limitType); } - private void addTatl(String name, double value, int acceptableDuration, LoadingLimitsAdder adder) { + private boolean addTatl(String name, double value, int acceptableDuration, LoadingLimitsAdder adder) { if (Double.isNaN(value)) { context.ignored(TEMPORARY_LIMIT, "Temporary limit value is undefined"); - return; + return false; } if (Double.isNaN(adder.getTemporaryLimitValue(acceptableDuration))) { @@ -299,6 +341,7 @@ private void addTatl(String name, double value, int acceptableDuration, LoadingL .setValue(value) .ensureNameUnicity() .endTemporaryLimit(); + return true; } else { if (terminalId != null) { context.fixed(TEMPORARY_LIMIT, () -> String.format("Several temporary limits defined for same acceptable duration (%d s) for Terminal %s. Only the lowest is kept.", acceptableDuration, terminalId)); @@ -312,8 +355,10 @@ private void addTatl(String name, double value, int acceptableDuration, LoadingL .setValue(value) .ensureNameUnicity() .endTemporaryLimit(); + return true; } } + return false; } private void convertTatl(double value) { @@ -324,15 +369,23 @@ private void convertTatl(double value) { // if there is no direction, the limit is considered as absoluteValue (cf. CGMES specification) if (direction == null || direction.endsWith("high") || direction.endsWith("absoluteValue")) { + String operationalLimitId = p.getId(CgmesNames.OPERATIONAL_LIMIT); String name = Optional.ofNullable(p.getId("shortName")).orElse(p.getId("name")); if (loadingLimitsAdder != null) { - addTatl(name, value, acceptableDuration, loadingLimitsAdder); + boolean added = addTatl(name, value, acceptableDuration, loadingLimitsAdder); + addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "", acceptableDuration, value); } else { if (loadingLimitsAdder1 != null) { - addTatl(name, value, acceptableDuration, loadingLimitsAdder1); + boolean added = addTatl(name, value, acceptableDuration, loadingLimitsAdder1); + addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "1", acceptableDuration, value); } if (loadingLimitsAdder2 != null) { - addTatl(name, value, acceptableDuration, loadingLimitsAdder2); + boolean added = addTatl(name, value, acceptableDuration, loadingLimitsAdder2); + addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "2", acceptableDuration, value); + } + if (loadingLimitsAdder3 != null) { + boolean added = addTatl(name, value, acceptableDuration, loadingLimitsAdder3); + addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "3", acceptableDuration, value); } } } else if (direction.endsWith("low")) { @@ -342,6 +395,32 @@ private void convertTatl(double value) { } } + private void addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(boolean included, String operationalLimitId, String end, int duration, double value) { + if (included) { + addTemporaryOperationalLimitProperties(operationalLimitId, end, duration, value); + } + } + + private void addTemporaryOperationalLimitProperties(String operationalLimitId, String end, int duration, double value) { + Objects.requireNonNull(limitSubclass); + Objects.requireNonNull(identifiable); + identifiable.setProperty(getPropertyName(end, limitSubclass, duration), operationalLimitId); + identifiable.setProperty(getPropertyName(operationalLimitId), String.valueOf(value)); + } + + private void addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(boolean included, String operationalLimitId, String end, double value) { + if (included) { + addPermanentOperationalLimitProperties(operationalLimitId, end, value); + } + } + + private void addPermanentOperationalLimitProperties(String operationalLimitId, String end, double value) { + Objects.requireNonNull(limitSubclass); + Objects.requireNonNull(identifiable); + identifiable.setProperty(getPropertyName(end, limitSubclass), operationalLimitId); + identifiable.setProperty(getPropertyName(operationalLimitId), String.valueOf(value)); + } + private void notAssigned() { notAssigned(null); } @@ -372,12 +451,80 @@ private static String className(Identifiable o) { return s; } + public static void update(OperationalLimitsGroup operationalLimitsGroup, String end, Identifiable identifiable, Context context) { + operationalLimitsGroup.getActivePowerLimits().ifPresent(activePowerLimits -> updateLoadingLimits(activePowerLimits, end, CgmesNames.ACTIVE_POWER_LIMIT, identifiable, context)); + operationalLimitsGroup.getApparentPowerLimits().ifPresent(apparentPowerLimits -> updateLoadingLimits(apparentPowerLimits, end, CgmesNames.APPARENT_POWER_LIMIT, identifiable, context)); + operationalLimitsGroup.getCurrentLimits().ifPresent(currentLimits -> updateLoadingLimits(currentLimits, end, CgmesNames.CURRENT_LIMIT, identifiable, context)); + } + + private static void updateLoadingLimits(LoadingLimits loadingLimits, String end, String limitSubClass, Identifiable identifiable, Context context) { + loadingLimits.setPermanentLimit(getValue(end, limitSubClass, identifiable, loadingLimits.getPermanentLimit(), context)); + loadingLimits.getTemporaryLimits().forEach(temporaryLimit -> { + int duration = temporaryLimit.getAcceptableDuration(); + loadingLimits.setTemporaryLimitValue(duration, getValue(end, limitSubClass, duration, identifiable, temporaryLimit.getValue(), context)); + }); + } + + private static double getValue(String end, String limitSubClass, Identifiable identifiable, double previousValue, Context context) { + String operationalLimitId = getOperationalLimitId(getPropertyName(end, limitSubClass), identifiable); + return updatedValue(operationalLimitId, context) + .orElse(defaultValue(getNormalValue(getPropertyName(operationalLimitId), identifiable), previousValue, getDefaultValue(context))); + } + + private static double getValue(String end, String limitSubClass, int duration, Identifiable identifiable, double previousValue, Context context) { + String operationalLimitId = getOperationalLimitId(getPropertyName(end, limitSubClass, duration), identifiable); + return updatedValue(operationalLimitId, context) + .orElse(defaultValue(getNormalValue(getPropertyName(operationalLimitId), identifiable), previousValue, getDefaultValue(context))); + } + + private static OptionalDouble updatedValue(String operationalLimitId, Context context) { + PropertyBag p = context.operationalLimit(operationalLimitId); + if (p == null) { + return OptionalDouble.empty(); + } + return p.getDouble("value"); + } + + private static String getOperationalLimitId(String propertyName, Identifiable identifiable) { + return identifiable.getProperty(propertyName); + } + + private static double getNormalValue(String propertyName, Identifiable identifiable) { + return Double.parseDouble(identifiable.getProperty(propertyName)); + } + + private static String getPropertyName(String end, String limitSubClass) { + return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT + "_" + end + "_" + limitSubClass + "_" + "patl"; + } + + private static String getPropertyName(String end, String limitSubClass, int duration) { + return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT + "_" + end + "_" + limitSubClass + "_" + "tatl" + "_" + duration; + } + + private static String getPropertyName(String operationalLimitId) { + return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "normalValue" + "_" + operationalLimitId; + } + + protected static double defaultValue(double normalValue, double previousValue, Conversion.Config.DefaultValue defaultValue) { + return switch (defaultValue) { + case EQ, DEFAULT, EMPTY -> normalValue; + case PREVIOUS -> previousValue; + }; + } + + private static Conversion.Config.DefaultValue getDefaultValue(Context context) { + return selectDefaultValue(List.of(EQ, PREVIOUS), context); + } + private final String terminalId; private final String equipmentId; + private final String limitSubclass; + private Identifiable identifiable; private LoadingLimitsAdder loadingLimitsAdder; private LoadingLimitsAdder loadingLimitsAdder1; private LoadingLimitsAdder loadingLimitsAdder2; + private LoadingLimitsAdder loadingLimitsAdder3; private VoltageLevel vl; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java index a13b5cd1f6a..c0907977c74 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java @@ -10,18 +10,28 @@ import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.Conversion; +import com.powsybl.cgmes.conversion.ConversionException; import com.powsybl.cgmes.conversion.RegulatingControlMappingForTransformers.CgmesRegulatingControlPhase; import com.powsybl.cgmes.conversion.RegulatingControlMappingForTransformers.CgmesRegulatingControlRatio; import com.powsybl.cgmes.conversion.elements.AbstractConductingEquipmentConversion; +import com.powsybl.cgmes.conversion.elements.AbstractObjectConversion; +import com.powsybl.cgmes.extensions.CgmesTapChanger; import com.powsybl.cgmes.extensions.CgmesTapChangers; import com.powsybl.cgmes.extensions.CgmesTapChangersAdder; import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.commons.PowsyblException; import com.powsybl.iidm.network.*; import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; import java.util.List; import java.util.Optional; +import java.util.OptionalInt; + +import static com.powsybl.cgmes.conversion.CgmesReports.badTargetDeadbandRegulatingControlReport; +import static com.powsybl.cgmes.conversion.CgmesReports.badVoltageTargetValueRegulatingControlReport; +import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; +import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.EMPTY; /** * @author Luma Zamarreño {@literal } @@ -33,6 +43,10 @@ abstract class AbstractTransformerConversion extends AbstractConductingEquipment super(type, ends, context); } + AbstractTransformerConversion(String type, PropertyBag transformerPropertyBag, PropertyBags cgmesTerminals, Context context) { + super(type, transformerPropertyBag, cgmesTerminals, context); + } + protected static void setToIidmRatioTapChanger(TapChanger rtc, RatioTapChangerAdder rtca) { boolean isLtcFlag = rtc.isLtcFlag(); int lowStep = rtc.getLowTapPosition(); @@ -91,21 +105,17 @@ protected static void setToIidmPhaseTapChanger(TapChanger ptc, PhaseTapChangerAd } protected CgmesRegulatingControlRatio setContextRegulatingDataRatio(TapChanger tc) { - CgmesRegulatingControlRatio rcRtc = null; if (tc != null) { - rcRtc = context.regulatingControlMapping().forTransformers().buildRegulatingControlRatio(tc.getId(), - tc.getRegulatingControlId(), tc.getTculControlMode(), tc.isTapChangerControlEnabled()); + return context.regulatingControlMapping().forTransformers().buildRegulatingControlRatio(tc.getId(), tc.getRegulatingControlId(), tc.getTculControlMode()); } - return rcRtc; + return null; } protected CgmesRegulatingControlPhase setContextRegulatingDataPhase(TapChanger tc) { - CgmesRegulatingControlPhase rcPtc = null; if (tc != null) { - return context.regulatingControlMapping().forTransformers().buildRegulatingControlPhase( - tc.getId(), tc.getRegulatingControlId(), tc.isTapChangerControlEnabled(), tc.isLtcFlag()); + return context.regulatingControlMapping().forTransformers().buildRegulatingControlPhase(tc.getId(), tc.getRegulatingControlId(), tc.isLtcFlag()); } - return rcPtc; + return null; } @Override @@ -137,28 +147,258 @@ protected static > void addCgmesReferences(C transforme return; } TapChanger tch = tc.getHiddenCombinedTapChanger(); - if (tc.getRegulatingControlId() != null || tc.getType() != null || tch != null) { - CgmesTapChangers tapChangers = transformer.getExtension(CgmesTapChangers.class); - if (tapChangers == null) { - transformer.newExtension(CgmesTapChangersAdder.class).add(); - tapChangers = transformer.getExtension(CgmesTapChangers.class); + + CgmesTapChangers tapChangers = transformer.getExtension(CgmesTapChangers.class); + if (tapChangers == null) { + transformer.newExtension(CgmesTapChangersAdder.class).add(); + tapChangers = transformer.getExtension(CgmesTapChangers.class); + } + // normalStep is always recorded in the step attribute + tapChangers.newTapChanger() + .setId(tc.getId()) + .setType(tc.getType()) + .setStep(tc.getTapPosition()) + .setControlId(tc.getRegulatingControlId()) + .add(); + if (tch != null) { + tapChangers.newTapChanger() + .setId(tch.getId()) + .setCombinedTapChangerId(tc.getId()) + .setHiddenStatus(true) + .setStep(tch.getTapPosition()) + .setType(tch.getType()) + .add(); + } + } + + static > void updateRatioTapChanger(Connectable tw, RatioTapChanger rtc, String end, Context context, boolean isRegulatingAllowed) { + if (regulatingControlIsDefined(rtc.getRegulationTerminal())) { + String ratioTapChangerId = findTapChangerId(tw, Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.RATIO_TAP_CHANGER + end); + PropertyBag ratioTapChangerPropertyBag = findRatioTapChangerPropertyBag(ratioTapChangerId, context); + PropertyBag regulatingControl = findRegulatingControlPropertyBag(tw, ratioTapChangerId, context); + + int tapPosition = findTapPosition(tw, ratioTapChangerPropertyBag, rtc, ratioTapChangerId, context); + rtc.setTapPosition(tapPosition); + + double targetV = findTargetV(regulatingControl, rtc, context); + double targetDeadband = findTargetDeadband(regulatingControl, rtc, context); + + // We always keep the targetValue + // It targetValue is not valid, emit a warning and deactivate regulating control + boolean validTargetV = isValidTargetV(targetV); + if (!validTargetV) { + context.invalid(ratioTapChangerId, "Regulating control has a bad target voltage " + targetV); + badVoltageTargetValueRegulatingControlReport(context.getReportNode(), ratioTapChangerId, targetV); } - if (tc.getRegulatingControlId() != null || tc.getType() != null) { - tapChangers.newTapChanger() - .setId(tc.getId()) - .setType(tc.getType()) - .setControlId(tc.getRegulatingControlId()) - .add(); + boolean validTargetDeadband = isValidTargetDeadband(targetDeadband); + if (!validTargetDeadband) { + context.invalid(ratioTapChangerId, "Regulating control has a bad target deadband " + targetDeadband); + badTargetDeadbandRegulatingControlReport(context.getReportNode(), ratioTapChangerId, targetDeadband); + targetDeadband = Double.NaN; // To avoid an exception from checkTargetDeadband } - if (tch != null) { - tapChangers.newTapChanger() - .setId(tch.getId()) - .setCombinedTapChangerId(tc.getId()) - .setHiddenStatus(true) - .setStep(tch.getTapPosition()) - .setType(tch.getType()) - .add(); + + rtc.setRegulating(findRegulatingOn(regulatingControl, rtc, context) && isRegulatingAllowed && validTargetV && validTargetDeadband) + .setTargetV(targetV) + .setTargetDeadband(targetDeadband); + } + } + + static > void updatePhaseTapChanger(Connectable tw, PhaseTapChanger ptc, String end, Context context, boolean isRegulatingAllowed) { + if (regulatingControlIsDefined(ptc.getRegulationTerminal())) { + String phaseTapChangerId = findTapChangerId(tw, Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.PHASE_TAP_CHANGER + end); + PropertyBag phaseTapChangerPropertyBag = findPhaseTapChangerPropertyBag(phaseTapChangerId, context); + PropertyBag regulatingControl = findRegulatingControlPropertyBag(tw, phaseTapChangerId, context); + + int tapPosition = findTapPosition(tw, phaseTapChangerPropertyBag, ptc, phaseTapChangerId, context); + ptc.setTapPosition(tapPosition); + + double targetValue = findTargetValue(regulatingControl, ptc, findTerminalSign(tw, end), context); + double targetDeadband = findTargetDeadband(regulatingControl, ptc, context); + + boolean regulating = findRegulatingOn(regulatingControl, ptc, context); + boolean fixedRegulating = regulating; + if (regulating && ptc.getRegulationMode() == PhaseTapChanger.RegulationMode.FIXED_TAP) { + context.fixed(phaseTapChangerId, "RegulationMode: regulating is set to true whereas regulationMode is set to FIXED_TAP: regulating fixed to false"); + fixedRegulating = false; + } + boolean validTargetDeadband = isValidTargetDeadband(targetDeadband); + if (!validTargetDeadband) { + context.invalid(phaseTapChangerId, "Regulating control has a bad target deadband " + targetDeadband); + badTargetDeadbandRegulatingControlReport(context.getReportNode(), phaseTapChangerId, targetDeadband); + targetDeadband = Double.NaN; // To avoid an exception from checkTargetDeadband } + + ptc.setRegulating(fixedRegulating && isRegulatingAllowed && isValidTargetValue(targetValue) && validTargetDeadband) + .setRegulationValue(targetValue) + .setTargetDeadband(targetDeadband); } } + + private static boolean regulatingControlIsDefined(Terminal regulatedTerminal) { + return regulatedTerminal != null; + } + + private static PropertyBag findRatioTapChangerPropertyBag(String ratioTapChangerId, Context context) { + return ratioTapChangerId != null ? context.ratioTapChanger(ratioTapChangerId) : null; + } + + private static PropertyBag findPhaseTapChangerPropertyBag(String phaseTapChangerId, Context context) { + return phaseTapChangerId != null ? context.phaseTapChanger(phaseTapChangerId) : null; + } + + private static > PropertyBag findRegulatingControlPropertyBag(Connectable tw, String tapChangerId, Context context) { + CgmesTapChangers cgmesTcs = tw.getExtension(CgmesTapChangers.class); + if (cgmesTcs != null && tapChangerId != null) { + CgmesTapChanger cgmesTc = cgmesTcs.getTapChanger(tapChangerId); + return cgmesTc != null ? context.regulatingControl(cgmesTc.getControlId()) : null; + } + return null; + } + + private static > int findTapPosition(Connectable tw, PropertyBag p, com.powsybl.iidm.network.TapChanger tapChanger, String tapChangerId, Context context) { + OptionalInt tapPosition = findTapPosition(p, context); + return tapPosition.isPresent() && isValidTapPosition(tapChanger, tapPosition.getAsInt()) ? tapPosition.getAsInt() : + getDefaultTapPosition( + getNormalStep(tw, tapChangerId), + tapChanger.getTapPosition(), + tapChanger.getNeutralPosition().orElse(getNormalStep(tw, tapChangerId)), + getDefaultValueForTapPosition(context)); + } + + private static boolean isValidTapPosition(com.powsybl.iidm.network.TapChanger tapChanger, int tapPosition) { + return tapChanger.getLowTapPosition() <= tapPosition && tapPosition <= tapChanger.getHighTapPosition(); + } + + private static OptionalInt findTapPosition(PropertyBag p, Context context) { + if (p != null) { + double tapPosition = findDoubleTapPosition(p, context); + return Double.isFinite(tapPosition) ? OptionalInt.of(AbstractObjectConversion.fromContinuous(tapPosition)) : OptionalInt.empty(); + } else { + return OptionalInt.empty(); + } + } + + private static double findDoubleTapPosition(PropertyBag p, Context context) { + return switch (context.config().getProfileForInitialValuesShuntSectionsTapPositions()) { + case SSH -> p.asDouble(CgmesNames.STEP, p.asDouble(CgmesNames.SV_TAP_STEP)); + case SV -> p.asDouble(CgmesNames.SV_TAP_STEP, p.asDouble(CgmesNames.STEP)); + }; + } + + private static > int getNormalStep(Connectable tw, String tapChangerId) { + CgmesTapChangers cgmesTcs = tw.getExtension(CgmesTapChangers.class); + if (cgmesTcs != null) { + CgmesTapChanger cgmesTc = cgmesTcs.getTapChanger(tapChangerId); + if (cgmesTc != null) { + return cgmesTc.getStep().orElseThrow(); + } + } + throw new ConversionException("normalStep must be defined in transformer: " + tw.getId()); + } + + private static > String findTapChangerId(Connectable tw, String propertyTag) { + List tcIds = tw.getAliases().stream().filter(alias -> isValidTapChangerIdAlias(tw, alias, tw.getAliasType(alias).orElse(null), propertyTag)).toList(); + if (tcIds.size() == 1) { + return tcIds.get(0); + } else { + throw new ConversionException("unexpected tapChangerId for transformer " + tw.getId()); + } + } + + private static boolean isValidTapChangerIdAlias(Connectable connectable, String alias, String aliasType, String propertyTag) { + return alias != null && aliasType != null && aliasType.contains(propertyTag) && !isHiddenTapChanger(connectable, alias); + } + + private static > boolean isHiddenTapChanger(Connectable tw, String tapChangerId) { + CgmesTapChangers cgmesTcs = tw.getExtension(CgmesTapChangers.class); + if (cgmesTcs != null) { + CgmesTapChanger cgmesTc = cgmesTcs.getTapChanger(tapChangerId); + if (cgmesTc != null) { + return cgmesTc.isHidden(); + } + } + return false; + } + + private static > int findTerminalSign(Connectable tw, String end) { + String terminalSign = tw.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "terminalSign" + end); + return terminalSign != null ? Integer.parseInt(terminalSign) : 1; + } + + private static int getDefaultTapPosition(int normalTapPosition, int previousTapPosition, int neutralTapPosition, Conversion.Config.DefaultValue defaultValue) { + return switch (defaultValue) { + case EQ -> normalTapPosition; + case PREVIOUS -> previousTapPosition; + case DEFAULT, EMPTY -> neutralTapPosition; + }; + } + + private static Conversion.Config.DefaultValue getDefaultValueForTapPosition(Context context) { + return selectDefaultValue(List.of(EQ, PREVIOUS, DEFAULT, EMPTY), context); + } + + private static double findTargetV(PropertyBag regulatingControl, com.powsybl.iidm.network.RatioTapChanger ratioTapChanger, Context context) { + return regulatingControl != null + ? regulatingControl.asDouble("targetValue") + : findDefaultTarget(ratioTapChanger.getTargetV(), Double.NaN, Double.NaN, context); + //double nominalV = ratioTapChanger.getRegulationTerminal() != null ? ratioTapChanger.getRegulationTerminal().getVoltageLevel().getNominalV() : Double.NaN; + } + + private static boolean isValidTargetV(double targetV) { + return Double.isFinite(targetV) && targetV > 0.0; + } + + private static double findTargetValue(PropertyBag regulatingControl, com.powsybl.iidm.network.PhaseTapChanger phaseTapChanger, int terminalSign, Context context) { + double targetValue = regulatingControl != null ? regulatingControl.asDouble("targetValue") : Double.NaN; + return isValidTargetValue(targetValue) ? targetValue * terminalSign : findDefaultTarget(phaseTapChanger.getRegulationValue(), Double.NaN, Double.NaN, context); + } + + private static boolean isValidTargetValue(double targetValue) { + return Double.isFinite(targetValue); + } + + // targetDeadBand is optional in Cgmes and mandatory in IIDM then a default value is provided when it is not defined in Cgmes + private static double findTargetDeadband(PropertyBag regulatingControl, com.powsybl.iidm.network.TapChanger tapChanger, Context context) { + return regulatingControl != null + ? regulatingControl.asDouble("targetDeadband") + : findDefaultTarget(tapChanger.getTargetDeadband(), 0.0, 0.0, context); + } + + private static boolean isValidTargetDeadband(double targetDeadband) { + return Double.isFinite(targetDeadband) && targetDeadband >= 0.0; + } + + private static boolean findRegulatingOn(PropertyBag regulatingControl, com.powsybl.iidm.network.TapChanger tapChanger, Context context) { + Boolean regulatingOn = regulatingControl != null ? regulatingControl.asBoolean("enabled").orElse(null) : null; + return isValidRegulatingOn(regulatingOn) ? regulatingOn : findDefaultRegulatingOn(tapChanger.isRegulating(), context); + } + + private static boolean isValidRegulatingOn(Boolean regulatingOn) { + return regulatingOn != null; + } + + private static double findDefaultTarget(double previousTarget, double defaultTarget, double emptyValue, Context context) { + return switch (getDefaultValue(context)) { + case EQ -> throw new PowsyblException("unexpected default type: " + getDefaultValue(context).name()); + case PREVIOUS -> previousTarget; + case DEFAULT -> defaultTarget; + case EMPTY -> emptyValue; + }; + } + + private static boolean findDefaultRegulatingOn(boolean previousRegulatingOn, Context context) { + return switch (getDefaultValue(context)) { + case EQ -> throw new PowsyblException("unexpected default type: " + getDefaultValue(context).name()); + case PREVIOUS -> previousRegulatingOn; + case DEFAULT, EMPTY -> false; + }; + } + + private static Conversion.Config.DefaultValue getDefaultValue(Context context) { + return selectDefaultValue(List.of(PREVIOUS, DEFAULT, EMPTY), context); + } + + static boolean checkOnlyOneEnabled(boolean isAllowedToRegulate, boolean previousTapChangerIsRegulatingOn) { + return isAllowedToRegulate && !previousTapChangerIsRegulatingOn; + } } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java index dd441cbd106..935facef78b 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java @@ -12,14 +12,18 @@ import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.conversion.RegulatingControlMappingForTransformers.CgmesRegulatingControlPhase; import com.powsybl.cgmes.conversion.RegulatingControlMappingForTransformers.CgmesRegulatingControlRatio; +import com.powsybl.cgmes.conversion.elements.OperationalLimitConversion; import com.powsybl.cgmes.model.CgmesNames; import com.powsybl.commons.PowsyblException; import com.powsybl.iidm.network.*; import com.powsybl.iidm.network.ThreeWindingsTransformerAdder.LegAdder; import com.powsybl.iidm.network.extensions.ThreeWindingsTransformerPhaseAngleClock; import com.powsybl.iidm.network.util.TwtData; +import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; +import java.util.Objects; + /** * ThreeWindingsTransformer Cgmes Conversion *

@@ -57,8 +61,16 @@ */ public class ThreeWindingsTransformerConversion extends AbstractTransformerConversion { + private final ThreeWindingsTransformer t3w; + public ThreeWindingsTransformerConversion(PropertyBags ends, Context context) { super(CgmesNames.POWER_TRANSFORMER, ends, context); + this.t3w = null; + } + + public ThreeWindingsTransformerConversion(PropertyBag t3wEmptyBag, PropertyBags cgmesTerminals, ThreeWindingsTransformer t3w, Context context) { + super(CgmesNames.POWER_TRANSFORMER, t3wEmptyBag, cgmesTerminals, context); + this.t3w = t3w; } @Override @@ -99,22 +111,22 @@ private void setToIidm(ConvertedT3xModel convertedT3xModel) { LegAdder l1adder = txadder.newLeg1(); setToIidmWindingAdder(convertedT3xModel.winding1, l1adder); - connect(l1adder, 1); + connection(l1adder, 1); l1adder.add(); LegAdder l2adder = txadder.newLeg2(); setToIidmWindingAdder(convertedT3xModel.winding2, l2adder); - connect(l2adder, 2); + connection(l2adder, 2); l2adder.add(); LegAdder l3adder = txadder.newLeg3(); setToIidmWindingAdder(convertedT3xModel.winding3, l3adder); - connect(l3adder, 3); + connection(l3adder, 3); l3adder.add(); ThreeWindingsTransformer tx = txadder.add(); addAliasesAndProperties(tx); - convertedTerminals( + mappingTerminals( tx.getLeg1().getTerminal(), tx.getLeg2().getTerminal(), tx.getLeg3().getTerminal()); @@ -156,7 +168,9 @@ private static void setToIidmRatioTapChanger(ConvertedT3xModel convertedT3xModel } RatioTapChangerAdder rtca = newRatioTapChanger(convertedT3xModel, tx, convertedWinding.end1.terminal); - setToIidmRatioTapChanger(rtc, rtca); + if (rtca != null) { + setToIidmRatioTapChanger(rtc, rtca); + } } private static void setToIidmPhaseTapChanger(ConvertedT3xModel convertedT3xModel, ConvertedT3xModel.ConvertedWinding convertedWinding, ThreeWindingsTransformer tx, Context context) { @@ -166,7 +180,9 @@ private static void setToIidmPhaseTapChanger(ConvertedT3xModel convertedT3xModel } PhaseTapChangerAdder ptca = newPhaseTapChanger(convertedT3xModel, tx, convertedWinding.end1.terminal); - setToIidmPhaseTapChanger(ptc, ptca, context); + if (ptca != null) { + setToIidmPhaseTapChanger(ptc, ptca, context); + } } private static RatioTapChangerAdder newRatioTapChanger(ConvertedT3xModel convertedT3xModel, ThreeWindingsTransformer tx, @@ -203,4 +219,29 @@ private void setRegulatingControlContext(ConvertedT3xModel convertedT3xModel, Th context.regulatingControlMapping().forTransformers().add(tx.getId(), rcRtc1, rcPtc1, rcRtc2, rcPtc2, rcRtc3, rcPtc3); } + + @Override + public void update(Network network) { + Objects.requireNonNull(t3w); + updateTerminals(context, t3w.getLeg1().getTerminal(), t3w.getLeg2().getTerminal(), t3w.getLeg3().getTerminal()); + + boolean isAllowedToRegulatePtc1 = true; + t3w.getLeg1().getOptionalPhaseTapChanger().ifPresent(ptc -> updatePhaseTapChanger(t3w, ptc, "1", context, isAllowedToRegulatePtc1)); + boolean isAllowedToRegulateRtc1 = checkOnlyOneEnabled(isAllowedToRegulatePtc1, t3w.getLeg1().getOptionalPhaseTapChanger().map(com.powsybl.iidm.network.TapChanger::isRegulating).orElse(false)); + t3w.getLeg1().getOptionalRatioTapChanger().ifPresent(rtc -> updateRatioTapChanger(t3w, rtc, "1", context, isAllowedToRegulateRtc1)); + + boolean isAllowedToRegulatePtc2 = checkOnlyOneEnabled(isAllowedToRegulateRtc1, t3w.getLeg1().getOptionalRatioTapChanger().map(com.powsybl.iidm.network.TapChanger::isRegulating).orElse(false)); + t3w.getLeg2().getOptionalPhaseTapChanger().ifPresent(ptc -> updatePhaseTapChanger(t3w, ptc, "2", context, isAllowedToRegulatePtc2)); + boolean isAllowedToRegulateRtc2 = checkOnlyOneEnabled(isAllowedToRegulatePtc2, t3w.getLeg2().getOptionalPhaseTapChanger().map(com.powsybl.iidm.network.TapChanger::isRegulating).orElse(false)); + t3w.getLeg2().getOptionalRatioTapChanger().ifPresent(rtc -> updateRatioTapChanger(t3w, rtc, "2", context, isAllowedToRegulateRtc2)); + + boolean isAllowedToRegulatePtc3 = checkOnlyOneEnabled(isAllowedToRegulateRtc2, t3w.getLeg2().getOptionalRatioTapChanger().map(com.powsybl.iidm.network.TapChanger::isRegulating).orElse(false)); + t3w.getLeg3().getOptionalPhaseTapChanger().ifPresent(ptc -> updatePhaseTapChanger(t3w, ptc, "3", context, isAllowedToRegulatePtc3)); + boolean isAllowedToRegulateRtc3 = checkOnlyOneEnabled(isAllowedToRegulatePtc3, t3w.getLeg3().getOptionalPhaseTapChanger().map(com.powsybl.iidm.network.TapChanger::isRegulating).orElse(false)); + t3w.getLeg3().getOptionalRatioTapChanger().ifPresent(rtc -> updateRatioTapChanger(t3w, rtc, "3", context, isAllowedToRegulateRtc3)); + + t3w.getLeg1().getOperationalLimitsGroups().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(operationalLimitsGroup, "1", t3w, context)); + t3w.getLeg2().getOperationalLimitsGroups().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(operationalLimitsGroup, "2", t3w, context)); + t3w.getLeg3().getOperationalLimitsGroups().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(operationalLimitsGroup, "3", t3w, context)); + } } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java index 3f28def2c22..137017b58e3 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java @@ -8,9 +8,9 @@ package com.powsybl.cgmes.conversion.elements.transformers; +import com.powsybl.cgmes.conversion.elements.OperationalLimitConversion; import com.powsybl.commons.PowsyblException; import com.powsybl.iidm.network.*; - import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.conversion.ConversionException; @@ -18,8 +18,10 @@ import com.powsybl.cgmes.conversion.RegulatingControlMappingForTransformers.CgmesRegulatingControlRatio; import com.powsybl.cgmes.conversion.elements.EquipmentAtBoundaryConversion; import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; +import java.util.Objects; import java.util.Optional; /** @@ -59,15 +61,22 @@ */ public class TwoWindingsTransformerConversion extends AbstractTransformerConversion implements EquipmentAtBoundaryConversion { + private final TwoWindingsTransformer t2w; private DanglingLine danglingLine; public TwoWindingsTransformerConversion(PropertyBags ends, Context context) { super(CgmesNames.POWER_TRANSFORMER, ends, context); + this.t2w = null; + } + + public TwoWindingsTransformerConversion(PropertyBag t2wEmptyBag, PropertyBags cgmesTerminals, TwoWindingsTransformer t2w, Context context) { + super(CgmesNames.POWER_TRANSFORMER, t2wEmptyBag, cgmesTerminals, context); + this.t2w = t2w; } @Override public boolean valid() { - // An transformer end voltage level may be null + // A transformer end voltage level may be null // (when it is in the boundary and the boundary nodes are not converted) // So we do not use the generic validity check for conducting equipment // or branch. We only ensure we have nodes at both ends @@ -143,10 +152,10 @@ private void setToIidm(ConvertedT2xModel convertedT2xModel) { adder.setRatedS(convertedT2xModel.ratedS); } identify(adder); - connect(adder); + connection(adder); TwoWindingsTransformer tx = adder.add(); addAliasesAndProperties(tx); - convertedTerminals(tx.getTerminal1(), tx.getTerminal2()); + mappingTerminals(tx.getTerminal1(), tx.getTerminal2()); setToIidmRatioTapChanger(convertedT2xModel, tx); setToIidmPhaseTapChanger(convertedT2xModel, tx, context); @@ -242,4 +251,19 @@ private static double getG(ConvertedT2xModel convertedT2xModel) { private static double getB(ConvertedT2xModel convertedT2xModel) { return getValue(convertedT2xModel.end1.b, getStepB1(convertedT2xModel.end1.ratioTapChanger), getStepB1(convertedT2xModel.end1.phaseTapChanger)); } + + @Override + public void update(Network network) { + Objects.requireNonNull(t2w); + updateTerminals(context, t2w.getTerminal1(), t2w.getTerminal2()); + + boolean isAllowedToRegulatePtc = true; + t2w.getOptionalPhaseTapChanger().ifPresent(ptc -> updatePhaseTapChanger(t2w, ptc, "", context, isAllowedToRegulatePtc)); + + boolean isAllowedToRegulateRtc = checkOnlyOneEnabled(isAllowedToRegulatePtc, t2w.getOptionalPhaseTapChanger().map(com.powsybl.iidm.network.TapChanger::isRegulating).orElse(false)); + t2w.getOptionalRatioTapChanger().ifPresent(rtc -> updateRatioTapChanger(t2w, rtc, "", context, isAllowedToRegulateRtc)); + + t2w.getOperationalLimitsGroups1().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(operationalLimitsGroup, "1", t2w, context)); + t2w.getOperationalLimitsGroups2().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(operationalLimitsGroup, "2", t2w, context)); + } } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportUtil.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportUtil.java index e98d8edb1f4..31d7358f039 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportUtil.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportUtil.java @@ -350,19 +350,19 @@ public static > void setCgmesTapChangerType(C eq, Strin // tap changer is exported as it is modelled in IIDM, always at end 1 static void addUpdateCgmesTapChangerExtension(TwoWindingsTransformer twt, CgmesExportContext context) { - twt.getOptionalRatioTapChanger().ifPresent(rtc -> addTapChangerExtension(twt, RATIO_TAP_CHANGER, getTapChangerId(twt, RATIO_TAP_CHANGER, context), regulatingControlIsDefined(rtc), context)); - twt.getOptionalPhaseTapChanger().ifPresent(ptc -> addTapChangerExtension(twt, PHASE_TAP_CHANGER, getTapChangerId(twt, PHASE_TAP_CHANGER, context), regulatingControlIsDefined(ptc), context)); + twt.getOptionalRatioTapChanger().ifPresent(rtc -> addTapChangerExtension(twt, RATIO_TAP_CHANGER, getTapChangerId(twt, RATIO_TAP_CHANGER, context), rtc.getTapPosition(), regulatingControlIsDefined(rtc), context)); + twt.getOptionalPhaseTapChanger().ifPresent(ptc -> addTapChangerExtension(twt, PHASE_TAP_CHANGER, getTapChangerId(twt, PHASE_TAP_CHANGER, context), ptc.getTapPosition(), regulatingControlIsDefined(ptc), context)); } static void addUpdateCgmesTapChangerExtension(ThreeWindingsTransformer twt, CgmesExportContext context) { - twt.getLeg1().getOptionalRatioTapChanger().ifPresent(rtc -> addTapChangerExtension(twt, RATIO_TAP_CHANGER, getTapChangerId(twt, RATIO_TAP_CHANGER, 1, context), regulatingControlIsDefined(rtc), context)); - twt.getLeg1().getOptionalPhaseTapChanger().ifPresent(ptc -> addTapChangerExtension(twt, PHASE_TAP_CHANGER, getTapChangerId(twt, PHASE_TAP_CHANGER, 1, context), regulatingControlIsDefined(ptc), context)); + twt.getLeg1().getOptionalRatioTapChanger().ifPresent(rtc -> addTapChangerExtension(twt, RATIO_TAP_CHANGER, getTapChangerId(twt, RATIO_TAP_CHANGER, 1, context), rtc.getTapPosition(), regulatingControlIsDefined(rtc), context)); + twt.getLeg1().getOptionalPhaseTapChanger().ifPresent(ptc -> addTapChangerExtension(twt, PHASE_TAP_CHANGER, getTapChangerId(twt, PHASE_TAP_CHANGER, 1, context), ptc.getTapPosition(), regulatingControlIsDefined(ptc), context)); - twt.getLeg2().getOptionalRatioTapChanger().ifPresent(rtc -> addTapChangerExtension(twt, RATIO_TAP_CHANGER, getTapChangerId(twt, RATIO_TAP_CHANGER, 2, context), regulatingControlIsDefined(rtc), context)); - twt.getLeg2().getOptionalPhaseTapChanger().ifPresent(ptc -> addTapChangerExtension(twt, PHASE_TAP_CHANGER, getTapChangerId(twt, PHASE_TAP_CHANGER, 2, context), regulatingControlIsDefined(ptc), context)); + twt.getLeg2().getOptionalRatioTapChanger().ifPresent(rtc -> addTapChangerExtension(twt, RATIO_TAP_CHANGER, getTapChangerId(twt, RATIO_TAP_CHANGER, 2, context), rtc.getTapPosition(), regulatingControlIsDefined(rtc), context)); + twt.getLeg2().getOptionalPhaseTapChanger().ifPresent(ptc -> addTapChangerExtension(twt, PHASE_TAP_CHANGER, getTapChangerId(twt, PHASE_TAP_CHANGER, 2, context), ptc.getTapPosition(), regulatingControlIsDefined(ptc), context)); - twt.getLeg3().getOptionalRatioTapChanger().ifPresent(rtc -> addTapChangerExtension(twt, RATIO_TAP_CHANGER, getTapChangerId(twt, RATIO_TAP_CHANGER, 3, context), regulatingControlIsDefined(rtc), context)); - twt.getLeg3().getOptionalPhaseTapChanger().ifPresent(ptc -> addTapChangerExtension(twt, PHASE_TAP_CHANGER, getTapChangerId(twt, PHASE_TAP_CHANGER, 3, context), regulatingControlIsDefined(ptc), context)); + twt.getLeg3().getOptionalRatioTapChanger().ifPresent(rtc -> addTapChangerExtension(twt, RATIO_TAP_CHANGER, getTapChangerId(twt, RATIO_TAP_CHANGER, 3, context), rtc.getTapPosition(), regulatingControlIsDefined(rtc), context)); + twt.getLeg3().getOptionalPhaseTapChanger().ifPresent(ptc -> addTapChangerExtension(twt, PHASE_TAP_CHANGER, getTapChangerId(twt, PHASE_TAP_CHANGER, 3, context), ptc.getTapPosition(), regulatingControlIsDefined(ptc), context)); } // If we had alias only for tc1, it will be at end 1 @@ -403,36 +403,37 @@ private static > String getTapChangerId(C twt, String c static boolean regulatingControlIsDefined(RatioTapChanger rtc) { return !Double.isNaN(rtc.getRegulationValue()) - && !Double.isNaN(rtc.getTargetDeadband()) && rtc.getRegulationTerminal() != null; } static boolean regulatingControlIsDefined(PhaseTapChanger ptc) { return ptc.getRegulationMode() != PhaseTapChanger.RegulationMode.FIXED_TAP && !Double.isNaN(ptc.getRegulationValue()) - && !Double.isNaN(ptc.getTargetDeadband()) && ptc.getRegulationTerminal() != null; } - private static > void addTapChangerExtension(C twt, String cgmesTapChangerTag, String tapChangerId, boolean regulatingControlIsDefined, CgmesExportContext context) { - if (!regulatingControlIsDefined) { - return; - } + static boolean targetDeadbandIsDefined(double targetDeadband) { + return !Double.isNaN(targetDeadband) && targetDeadband >= 0.0; + } + + private static > void addTapChangerExtension(C twt, String cgmesTapChangerTag, String tapChangerId, int tapPosition, boolean regulatingControlIsDefined, CgmesExportContext context) { + CgmesTapChangers cgmesTapChangers = twt.getExtension(CgmesTapChangers.class); if (cgmesTapChangers == null) { twt.newExtension(CgmesTapChangersAdder.class).add(); cgmesTapChangers = twt.getExtension(CgmesTapChangers.class); } - CgmesTapChanger cgmesTapChanger = cgmesTapChangers.getTapChanger(tapChangerId); Part refTapChanger = Objects.equals(cgmesTapChangerTag, RATIO_TAP_CHANGER) ? Part.RATIO_TAP_CHANGER : Part.PHASE_TAP_CHANGER; + + CgmesTapChanger cgmesTapChanger = cgmesTapChangers.getTapChanger(tapChangerId); if (cgmesTapChanger == null) { cgmesTapChanger = cgmesTapChangers.newTapChanger() .setId(tapChangerId) - .setControlId(context.getNamingStrategy().getCgmesId(ref(twt), refTapChanger, Part.REGULATING_CONTROL)) + .setStep(tapPosition) .add(); } - if (cgmesTapChanger.getControlId() == null) { + if (regulatingControlIsDefined && cgmesTapChanger.getControlId() == null) { cgmesTapChanger.setControlId(context.getNamingStrategy().getCgmesId(ref(twt), refTapChanger, Part.REGULATING_CONTROL)); } } 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 c9ec4f180c9..eb1f00bfa53 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 @@ -838,6 +838,7 @@ private static > void writePhaseTapChanger(C eq, PhaseT String cgmesTapChangerId = context.getNamingStrategy().getCgmesIdFromAlias(eq, aliasType); int neutralStep = getPhaseTapChangerNeutralStep(ptc); + int normalStep = getTapChangerNormalStep(eq, tapChangerId).orElseThrow(); Optional regulatingControlId = getTapChangerControlId(eq, tapChangerId); String cgmesRegulatingControlId = null; if (regulatingControlId.isPresent() && CgmesExportUtil.regulatingControlIsDefined(ptc)) { @@ -856,7 +857,7 @@ private static > void writePhaseTapChanger(C eq, PhaseT String typeTabular = CgmesNames.PHASE_TAP_CHANGER_TABULAR; CgmesExportUtil.setCgmesTapChangerType(eq, tapChangerId, typeTabular); boolean ltcFlag = obtainPhaseTapChangerLtcFlag(ptc.getRegulationMode()); - TapChangerEq.writePhase(typeTabular, cgmesTapChangerId, twtName + "_PTC", endId, ptc.getLowTapPosition(), ptc.getHighTapPosition(), neutralStep, ptc.getTapPosition(), neutralU, ltcFlag, phaseTapChangerTableId, cgmesRegulatingControlId, cimNamespace, writer, context); + TapChangerEq.writePhase(typeTabular, cgmesTapChangerId, twtName + "_PTC", endId, ptc.getLowTapPosition(), ptc.getHighTapPosition(), neutralStep, normalStep, neutralU, ltcFlag, phaseTapChangerTableId, cgmesRegulatingControlId, cimNamespace, writer, context); TapChangerEq.writePhaseTable(phaseTapChangerTableId, twtName + "_TABLE", cimNamespace, writer, context); for (Map.Entry step : ptc.getAllSteps().entrySet()) { String stepId = context.getNamingStrategy().getCgmesId(refTyped(eq), ref(endNumber), ref(step.getKey()), PHASE_TAP_CHANGER_STEP); @@ -882,6 +883,16 @@ private static > Optional getTapChangerControlI return Optional.empty(); } + private static > OptionalInt getTapChangerNormalStep(C tw, String tapChangerId) { + CgmesTapChangers cgmesTcs = tw.getExtension(CgmesTapChangers.class); + if (cgmesTcs != null) { + CgmesTapChanger cgmesTc = cgmesTcs.getTapChanger(tapChangerId); + return cgmesTc != null ? cgmesTc.getStep() : OptionalInt.empty(); + } else { + return OptionalInt.empty(); + } + } + private static int getPhaseTapChangerNeutralStep(PhaseTapChanger ptc) { int neutralStep = ptc.getLowTapPosition(); double minAlpha = Math.abs(ptc.getStep(neutralStep).getAlpha()); @@ -902,6 +913,7 @@ private static > void writeRatioTapChanger(C eq, RatioT String cgmesTapChangerId = context.getNamingStrategy().getCgmesIdFromAlias(eq, aliasType); int neutralStep = getRatioTapChangerNeutralStep(rtc); + int normalStep = getTapChangerNormalStep(eq, tapChangerId).orElseThrow(); double stepVoltageIncrement; if (rtc.getHighTapPosition() == rtc.getLowTapPosition()) { stepVoltageIncrement = 100; @@ -925,7 +937,7 @@ private static > void writeRatioTapChanger(C eq, RatioT regulatingControlsWritten.add(cgmesRegulatingControlId); } } - TapChangerEq.writeRatio(cgmesTapChangerId, twtName + "_RTC", endId, rtc.getLowTapPosition(), rtc.getHighTapPosition(), neutralStep, rtc.getTapPosition(), neutralU, rtc.hasLoadTapChangingCapabilities(), stepVoltageIncrement, + TapChangerEq.writeRatio(cgmesTapChangerId, twtName + "_RTC", endId, rtc.getLowTapPosition(), rtc.getHighTapPosition(), neutralStep, normalStep, neutralU, rtc.hasLoadTapChangingCapabilities(), stepVoltageIncrement, ratioTapChangerTableId, cgmesRegulatingControlId, controlMode, cimNamespace, writer, context); TapChangerEq.writeRatioTable(ratioTapChangerTableId, twtName + "_TABLE", cimNamespace, writer, context); for (Map.Entry step : rtc.getAllSteps().entrySet()) { 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..132494e47ad 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 @@ -528,7 +528,11 @@ private static RegulatingControlView combineRegulatingControlViews(List 0) { + if (Double.isNaN(combined.targetDeadband) && !Double.isNaN(current.targetDeadband) && current.targetDeadband >= 0) { + combined.targetDeadband = current.targetDeadband; + } else if (combined.targetDeadband == 0 && !Double.isNaN(current.targetDeadband) && current.targetDeadband > 0) { + combined.targetDeadband = current.targetDeadband; + } else if (combined.targetDeadband > 0 && !Double.isNaN(current.targetDeadband) && current.targetDeadband > 0 && current.targetDeadband < combined.targetDeadband) { combined.targetDeadband = current.targetDeadband; } if (!combined.discrete && current.discrete) { @@ -549,9 +553,11 @@ private static void writeRegulatingControl(RegulatingControlView rc, String cimN writer.writeStartElement(cimNamespace, "RegulatingControl.enabled"); writer.writeCharacters(Boolean.toString(rc.controlEnabled)); writer.writeEndElement(); - writer.writeStartElement(cimNamespace, "RegulatingControl.targetDeadband"); - writer.writeCharacters(CgmesExportUtil.format(rc.targetDeadband)); - writer.writeEndElement(); + if (CgmesExportUtil.targetDeadbandIsDefined(rc.targetDeadband)) { + writer.writeStartElement(cimNamespace, "RegulatingControl.targetDeadband"); + writer.writeCharacters(CgmesExportUtil.format(rc.targetDeadband)); + writer.writeEndElement(); + } writer.writeStartElement(cimNamespace, "RegulatingControl.targetValue"); writer.writeCharacters(CgmesExportUtil.format(rc.targetValue)); writer.writeEndElement(); diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt index 3ba085be984..8e3c6bc636b 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt @@ -34,11 +34,14 @@ Converting OperationalLimit. Converting SvInjection. Converting ControlArea. - + Converting RegulatingControl. - Equipment 955d9cd0-4a10-4031-b008-60c0dc340a07 has a regulating control with bad target value for voltage: 0.0. - Equipment fe25f43a-7341-446e-a71a-8ab7119ba806 has a regulating control with bad target value for voltage: 0.0. + Converting RegulatingControl. Fixing issues with dangling lines. Setting voltages and angles. Applying postprocessors. CGMES network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 is imported. + Updating LOAD. + + Updating TWO_WINDINGS_TRANSFORMER. + Equipment 955d9cd0-4a10-4031-b008-60c0dc340a07 has a regulating control with bad target value for voltage: 0.0. + + Updating THREE_WINDINGS_TRANSFORMER. + Equipment fe25f43a-7341-446e-a71a-8ab7119ba806 has a regulating control with bad target value for voltage: 0.0. Running validation checks on IIDM network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt index f5e5e724c6f..6059b747502 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt @@ -32,13 +32,16 @@ Converting OperationalLimit. Converting SvInjection. Converting ControlArea. - + Converting RegulatingControl. - Equipment 955d9cd0-4a10-4031-b008-60c0dc340a07 has a regulating control with bad target value for voltage: 0.0. - Equipment 955d9cd0-4a10-4031-b008-60c0dc340a07 has a regulating control with bad target deadband: -0.5. - Equipment 6ebbef67-3061-4236-a6fd-6ccc4595f6c3 has a regulating control with bad target deadband: -35.0. - Equipment fe25f43a-7341-446e-a71a-8ab7119ba806 has a regulating control with bad target value for voltage: 0.0. + Converting RegulatingControl. Fixing issues with dangling lines. Setting voltages and angles. Applying postprocessors. CGMES network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 is imported. + Updating LOAD. + + Updating TWO_WINDINGS_TRANSFORMER. + Equipment 955d9cd0-4a10-4031-b008-60c0dc340a07 has a regulating control with bad target value for voltage: 0.0. + Equipment 955d9cd0-4a10-4031-b008-60c0dc340a07 has a regulating control with bad target deadband: -0.5. + Equipment 6ebbef67-3061-4236-a6fd-6ccc4595f6c3 has a regulating control with bad target deadband: -35.0. + + Updating THREE_WINDINGS_TRANSFORMER. + Equipment fe25f43a-7341-446e-a71a-8ab7119ba806 has a regulating control with bad target value for voltage: 0.0. Running validation checks on IIDM network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt index ce0c42595d8..985a4e7ba5f 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt @@ -36,11 +36,14 @@ Converting OperationalLimit. Converting SvInjection. Converting ControlArea. - + Converting RegulatingControl. - Equipment 955d9cd0-4a10-4031-b008-60c0dc340a07 has a regulating control with bad target value for voltage: 0.0. - Equipment fe25f43a-7341-446e-a71a-8ab7119ba806 has a regulating control with bad target value for voltage: 0.0. + Converting RegulatingControl. Fixing issues with dangling lines. Setting voltages and angles. Applying postprocessors. CGMES network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 is imported. + Updating LOAD. + + Updating TWO_WINDINGS_TRANSFORMER. + Equipment 955d9cd0-4a10-4031-b008-60c0dc340a07 has a regulating control with bad target value for voltage: 0.0. + + Updating THREE_WINDINGS_TRANSFORMER. + Equipment fe25f43a-7341-446e-a71a-8ab7119ba806 has a regulating control with bad target value for voltage: 0.0. Running validation checks on IIDM network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt index d9e431d32f0..cebe966fcf3 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt @@ -40,4 +40,7 @@ Node 49831d24-33e9-4233-8424-3f88186a924e has invalid value for voltage and/or angle. Voltage magnitude is 0.0, angle is 0.0. Applying postprocessors. CGMES network urn:uuid:239ecbd2-9a39-11e0-aa80-0800200c9a66 is imported. + Updating LOAD. + Updating TWO_WINDINGS_TRANSFORMER. + Updating THREE_WINDINGS_TRANSFORMER. Running validation checks on IIDM network urn:uuid:239ecbd2-9a39-11e0-aa80-0800200c9a66 diff --git a/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangerAdderImpl.java b/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangerAdderImpl.java index 929259a1747..515aa6b1f65 100644 --- a/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangerAdderImpl.java +++ b/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangerAdderImpl.java @@ -69,9 +69,9 @@ public CgmesTapChanger add() { throw new PowsyblException("Tap changer ID should not be null"); } if (!hidden) { - if (step != null) { - throw new PowsyblException("Non-hidden tap changers step positions can be directly found on the tap changer" + - " and should not be forced"); + // step is used to record the normalStep of the tapChanger when it is not hidden + if (step == null) { + throw new PowsyblException("normal step must be defined for tap changers"); } if (combinedTapChangerId != null) { throw new PowsyblException("Non-hidden tap changers do not have a different ID for the combined tap changer"); diff --git a/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java b/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java index 4b7c1e43935..8dfdb9b3f92 100644 --- a/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java +++ b/cgmes/cgmes-extensions/src/main/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDe.java @@ -52,8 +52,8 @@ public void write(CgmesTapChangers extension, SerializerContext context) { writer.writeStringAttribute("combinedTapChangerId", tapChanger.getCombinedTapChangerId()); writer.writeStringAttribute("type", tapChanger.getType()); writer.writeBooleanAttribute("hidden", tapChanger.isHidden(), false); - writer.writeOptionalIntAttribute("step", - !tapChanger.isHidden() ? null : tapChanger.getStep().orElseThrow(() -> new PowsyblException("Step should be defined"))); + Integer step = tapChanger.getStep().isPresent() ? tapChanger.getStep().getAsInt() : null; + writer.writeOptionalIntAttribute("step", step); writer.writeStringAttribute("controlId", tapChanger.getControlId()); writer.writeEndNode(); } diff --git a/cgmes/cgmes-extensions/src/test/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDeTest.java b/cgmes/cgmes-extensions/src/test/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDeTest.java index 85f1cf3c8e0..ac15209bb22 100644 --- a/cgmes/cgmes-extensions/src/test/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDeTest.java +++ b/cgmes/cgmes-extensions/src/test/java/com/powsybl/cgmes/extensions/CgmesTapChangersSerDeTest.java @@ -30,6 +30,7 @@ void test() throws IOException { ctc2wt.newTapChanger() .setId("tc1") .setControlId("control1") + .setStep(1) .setType("type1") .setHiddenStatus(false) .add(); diff --git a/cgmes/cgmes-extensions/src/test/resources/eurostag_cgmes_tap_changers.xml b/cgmes/cgmes-extensions/src/test/resources/eurostag_cgmes_tap_changers.xml index b3a759bbd20..3e3bbcdb92f 100644 --- a/cgmes/cgmes-extensions/src/test/resources/eurostag_cgmes_tap_changers.xml +++ b/cgmes/cgmes-extensions/src/test/resources/eurostag_cgmes_tap_changers.xml @@ -39,7 +39,7 @@ - + diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java index af5b71cdc0a..3a9a17b79ea 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java @@ -141,6 +141,7 @@ public final class CgmesNames { public static final String OPERATIONAL_LIMIT = "OperationalLimit"; public static final String OPERATIONAL_LIMIT_SET = "OperationalLimitSet"; + public static final String NORMAL_VALUE = "normalValue"; public static final String CURRENT_LIMIT = "CurrentLimit"; public static final String ACTIVE_POWER_LIMIT = "ActivePowerLimit"; public static final String APPARENT_POWER_LIMIT = "ApparentPowerLimit"; From 81954c690bd71f3a140c4bdb0241e2f0e7267eca Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 6 Nov 2024 13:17:20 +0100 Subject: [PATCH 11/54] Typo Signed-off-by: marquesja1 --- .../elements/AbstractConductingEquipmentConversion.java | 3 +-- .../conversion/elements/AsynchronousMachineConversion.java | 2 +- .../cgmes/conversion/elements/EnergyConsumerConversion.java | 2 +- .../cgmes/conversion/elements/EnergySourceConversion.java | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index 60144999fe1..e4933ed9473 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -28,7 +28,6 @@ import java.util.Optional; import java.util.OptionalDouble; -import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.EMPTY; import static com.powsybl.cgmes.conversion.Update.isConvertSeparatedFromUpdate; /** @@ -835,7 +834,7 @@ protected OptionalDouble updatedP0() { return updatedPowerFlow().defined() ? OptionalDouble.of(updatedPowerFlow().p()) : OptionalDouble.empty(); } - protected OptionalDouble qupdatedQ0() { + protected OptionalDouble updatedQ0() { return updatedPowerFlow().defined() ? OptionalDouble.of(updatedPowerFlow().q()) : OptionalDouble.empty(); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java index 0d70eb7c72f..446d5e570cf 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java @@ -58,7 +58,7 @@ public void update(Network network) { Objects.requireNonNull(load); updateTerminals(context, load.getTerminal()); load.setP0(updatedP0().orElse(defaultP(Double.NaN, load.getP0(), gettDefaultValue(context)))) - .setQ0(qupdatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), gettDefaultValue(context)))); + .setQ0(updatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), gettDefaultValue(context)))); } private static void addSpecificProperties(Load newLoad) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index d889fb0b19a..7a65f2ec2f6 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -157,7 +157,7 @@ public void update(Network network) { double pFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + P_FIXED)); double qFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + Q_FIXED)); load.setP0(updatedP0().orElse(defaultP(pFixed, load.getP0(), getDefaultValue(context)))) - .setQ0(qupdatedQ0().orElse(defaultQ(qFixed, load.getQ0(), getDefaultValue(context)))); + .setQ0(updatedQ0().orElse(defaultQ(qFixed, load.getQ0(), getDefaultValue(context)))); updateLoadDetail(load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS), pFixed, qFixed); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java index fbe9af26f88..682cd14ad4a 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java @@ -57,7 +57,7 @@ public void update(Network network) { Objects.requireNonNull(load); updateTerminals(context, load.getTerminal()); load.setP0(updatedP0().orElse(defaultP(Double.NaN, load.getP0(), getDefaultValue(context)))) - .setQ0(qupdatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), getDefaultValue(context)))); + .setQ0(updatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), getDefaultValue(context)))); } private static Conversion.Config.DefaultValue getDefaultValue(Context context) { From 2e6657b31995c3a77c6fc5fa63458860e908f28c Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 6 Nov 2024 13:31:22 +0100 Subject: [PATCH 12/54] Typo Signed-off-by: marquesja1 --- .../elements/AbstractConductingEquipmentConversion.java | 2 +- .../conversion/elements/AsynchronousMachineConversion.java | 2 +- .../cgmes/conversion/elements/EnergyConsumerConversion.java | 2 +- .../cgmes/conversion/elements/EnergySourceConversion.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index bf1eb699a3d..1e5fda7a422 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -799,7 +799,7 @@ protected OptionalDouble updatedP0() { return updatedPowerFlow().defined() ? OptionalDouble.of(updatedPowerFlow().p()) : OptionalDouble.empty(); } - protected OptionalDouble qupdatedQ0() { + protected OptionalDouble updatedQ0() { return updatedPowerFlow().defined() ? OptionalDouble.of(updatedPowerFlow().q()) : OptionalDouble.empty(); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java index 0d70eb7c72f..446d5e570cf 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java @@ -58,7 +58,7 @@ public void update(Network network) { Objects.requireNonNull(load); updateTerminals(context, load.getTerminal()); load.setP0(updatedP0().orElse(defaultP(Double.NaN, load.getP0(), gettDefaultValue(context)))) - .setQ0(qupdatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), gettDefaultValue(context)))); + .setQ0(updatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), gettDefaultValue(context)))); } private static void addSpecificProperties(Load newLoad) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index d889fb0b19a..7a65f2ec2f6 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -157,7 +157,7 @@ public void update(Network network) { double pFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + P_FIXED)); double qFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + Q_FIXED)); load.setP0(updatedP0().orElse(defaultP(pFixed, load.getP0(), getDefaultValue(context)))) - .setQ0(qupdatedQ0().orElse(defaultQ(qFixed, load.getQ0(), getDefaultValue(context)))); + .setQ0(updatedQ0().orElse(defaultQ(qFixed, load.getQ0(), getDefaultValue(context)))); updateLoadDetail(load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS), pFixed, qFixed); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java index fbe9af26f88..682cd14ad4a 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java @@ -57,7 +57,7 @@ public void update(Network network) { Objects.requireNonNull(load); updateTerminals(context, load.getTerminal()); load.setP0(updatedP0().orElse(defaultP(Double.NaN, load.getP0(), getDefaultValue(context)))) - .setQ0(qupdatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), getDefaultValue(context)))); + .setQ0(updatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), getDefaultValue(context)))); } private static Conversion.Config.DefaultValue getDefaultValue(Context context) { From cbb0f54f91ded8d68aea1ecbe8cb1c206e30f4d4 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 6 Nov 2024 13:41:36 +0100 Subject: [PATCH 13/54] Updating report Signed-off-by: marquesja1 --- .../java/com/powsybl/cgmes/conversion/CgmesReports.java | 8 ++++++++ .../main/java/com/powsybl/cgmes/conversion/Update.java | 8 ++++---- .../microGridBaseCaseBE-invalid-voltage-bus.txt | 1 + .../microGridBaseCaseBE-target-deadband.txt | 1 + .../resources/functional-logs/microGridBaseCaseBE.txt | 1 + .../resources/functional-logs/miniGridNodeBreaker.txt | 1 + 6 files changed, 16 insertions(+), 4 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java index d410c73be34..2a9250372c2 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java @@ -51,6 +51,14 @@ public static ReportNode convertingElementTypeReport(ReportNode reportNode, Stri .add(); } + public static ReportNode updatingElementTypeReport(ReportNode reportNode, String elementType) { + return reportNode.newReportNode() + .withMessageTemplate("updatingElementType", "Updating ${elementType}.") + .withUntypedValue("elementType", elementType) + .withSeverity(TypedValue.INFO_SEVERITY) + .add(); + } + public static ReportNode fixingDanglingLinesIssuesReport(ReportNode reportNode) { return reportNode.newReportNode() .withMessageTemplate("fixingDanglingLinesIssues", "Fixing issues with dangling lines.") diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java index d6a8c407dd8..21e3e917b50 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java @@ -12,10 +12,7 @@ import com.powsybl.cgmes.conversion.elements.EnergySourceConversion; import com.powsybl.cgmes.model.CgmesModel; import com.powsybl.cgmes.model.CgmesNames; -import com.powsybl.iidm.network.Connectable; -import com.powsybl.iidm.network.Identifiable; -import com.powsybl.iidm.network.Load; -import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.*; import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; @@ -44,12 +41,15 @@ public static boolean isConvertSeparatedFromUpdate(PropertyBag p) { } static void updateLoads(Network network, CgmesModel cgmes, Context context) { + context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.LOAD.name())); + Map identifiablePropertyBag = new HashMap<>(); addPropertyBags(network, cgmes.energyConsumers(), CgmesNames.ENERGY_CONSUMER, identifiablePropertyBag); addPropertyBags(network, cgmes.energySources(), CgmesNames.ENERGY_SOURCE, identifiablePropertyBag); addPropertyBags(network, cgmes.asynchronousMachines(), CgmesNames.ASYNCHRONOUS_MACHINE, identifiablePropertyBag); network.getLoads().forEach(load -> updateLoad(network, load, getPropertyBag(load.getId(), identifiablePropertyBag), context)); + context.popReportNode(); } private static void updateLoad(Network network, Load load, PropertyBag propertyBag, Context context) { diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt index 3ba085be984..69a62c9c367 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt @@ -41,4 +41,5 @@ Setting voltages and angles. Applying postprocessors. CGMES network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 is imported. + Updating LOAD. Running validation checks on IIDM network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt index f5e5e724c6f..5519377d349 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt @@ -41,4 +41,5 @@ Setting voltages and angles. Applying postprocessors. CGMES network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 is imported. + Updating LOAD. Running validation checks on IIDM network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt index ce0c42595d8..0681b96a704 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt @@ -43,4 +43,5 @@ Setting voltages and angles. Applying postprocessors. CGMES network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 is imported. + Updating LOAD. Running validation checks on IIDM network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt index d9e431d32f0..7e4a775b374 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt @@ -40,4 +40,5 @@ Node 49831d24-33e9-4233-8424-3f88186a924e has invalid value for voltage and/or angle. Voltage magnitude is 0.0, angle is 0.0. Applying postprocessors. CGMES network urn:uuid:239ecbd2-9a39-11e0-aa80-0800200c9a66 is imported. + Updating LOAD. Running validation checks on IIDM network urn:uuid:239ecbd2-9a39-11e0-aa80-0800200c9a66 From b3d094550bf581e28fb8b34bf8b1be458a6630d0 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 6 Nov 2024 17:12:57 +0100 Subject: [PATCH 14/54] update voltage and angles after the update Signed-off-by: marquesja1 --- .../com/powsybl/cgmes/conversion/Conversion.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java index 85f3f0e4127..45ddf35fcb8 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java @@ -334,6 +334,8 @@ private void update(Network network, Context updateContext, ReportNode reportNod updateLoads(network, cgmes, updateContext); updateTwoAndThreeWindingsTransformers(network, updateContext); + completeVoltagesAndAnglesAfterUpdate(network); + network.runValidationChecks(false, reportNode); network.setMinimumAcceptableValidationLevel(ValidationLevel.STEADY_STATE_HYPOTHESIS); } @@ -450,16 +452,19 @@ private Source isBoundaryBaseVoltage(String graph) { private static void completeVoltagesAndAngles(Network network) { - // Voltage and angle in starBus as properties - network.getThreeWindingsTransformers() - .forEach(ThreeWindingsTransformerConversion::calculateVoltageAndAngleInStarBus); - // Voltage and angle in boundary buses network.getDanglingLineStream(DanglingLineFilter.UNPAIRED) .forEach(AbstractConductingEquipmentConversion::calculateVoltageAndAngleInBoundaryBus); network.getTieLines().forEach(tieLine -> AbstractConductingEquipmentConversion.calculateVoltageAndAngleInBoundaryBus(tieLine.getDanglingLine1(), tieLine.getDanglingLine2())); } + private static void completeVoltagesAndAnglesAfterUpdate(Network network) { + + // Voltage and angle in starBus as properties + network.getThreeWindingsTransformers() + .forEach(ThreeWindingsTransformerConversion::calculateVoltageAndAngleInStarBus); + } + private static void createControlArea(CgmesControlAreas cgmesControlAreas, PropertyBag ca) { String controlAreaId = ca.getId("ControlArea"); cgmesControlAreas.newCgmesControlArea() From 7e3766a8d645315ecf90e28a392aff3d6362a6cd Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 7 Nov 2024 09:20:30 +0100 Subject: [PATCH 15/54] Fix code smells Signed-off-by: marquesja1 --- .../cgmes/conversion/CgmesReports.java | 11 +- .../elements/OperationalLimitConversion.java | 100 +++++++------- .../AbstractTransformerConversion.java | 129 +++++++++--------- 3 files changed, 128 insertions(+), 112 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java index 2a9250372c2..5e5ea742ad4 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java @@ -98,11 +98,20 @@ public static void badVoltageTargetValueRegulatingControlReport(ReportNode repor .add(); } + public static void badTargetValueRegulatingControlReport(ReportNode reportNode, String eqId, double targetValue) { + reportNode.newReportNode() + .withMessageTemplate("badTargetValueRegulatingControl", "Equipment ${equipmentId} has a regulating control with bad target value: ${targetValue}.") + .withUntypedValue("equipmentId", eqId) + .withUntypedValue("targetValue", targetValue) + .withSeverity(TypedValue.WARN_SEVERITY) + .add(); + } + public static void badTargetDeadbandRegulatingControlReport(ReportNode reportNode, String eqId, double targetDeadband) { reportNode.newReportNode() .withMessageTemplate("badTargetDeadbandRegulatingControl", "Equipment ${equipmentId} has a regulating control with bad target deadband: ${targetDeadband}.") .withUntypedValue("equipmentId", eqId) - .withTypedValue("targetDeadband", targetDeadband, TypedValue.VOLTAGE) + .withUntypedValue("targetDeadband", targetDeadband) .withSeverity(TypedValue.WARN_SEVERITY) .add(); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java index b8893c5269d..e3fc2ce3f91 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java @@ -47,7 +47,7 @@ public OperationalLimitConversion(PropertyBag l, Context context) { terminalId = l.getId("Terminal"); equipmentId = l.getId("Equipment"); - this.limitSubclass = fixCim14LimitSubclass(limitSubclass); + this.limitSubclassType = fixCim14LimitSubclass(limitSubclass); Terminal terminal = null; if (isLoadingLimits()) { @@ -56,12 +56,12 @@ public OperationalLimitConversion(PropertyBag l, Context context) { } if (terminal != null) { checkAndCreateLimitsAdder(context.terminalMapping().number(terminalId), limitSetId, limitSetName, terminal.getConnectable()); - this.identifiable = terminal.getConnectable(); + this.loadingLimitsIdentifiable = terminal.getConnectable(); } else if (equipmentId != null) { // The equipment may be a Branch, a Dangling line, a Switch ... Identifiable identifiable = context.network().getIdentifiable(equipmentId); checkAndCreateLimitsAdder(-1, limitSetId, limitSetName, identifiable); - this.identifiable = identifiable; + this.loadingLimitsIdentifiable = identifiable; } } else if (isVoltageLimits()) { if (terminalId != null) { @@ -79,15 +79,15 @@ private static String fixCim14LimitSubclass(String limitSubclass) { } private boolean isLoadingLimits() { - Objects.requireNonNull(limitSubclass); - return limitSubclass.equals(CgmesNames.ACTIVE_POWER_LIMIT) - || limitSubclass.equals(CgmesNames.APPARENT_POWER_LIMIT) - || limitSubclass.equals(CgmesNames.CURRENT_LIMIT); + Objects.requireNonNull(limitSubclassType); + return limitSubclassType.equals(CgmesNames.ACTIVE_POWER_LIMIT) + || limitSubclassType.equals(CgmesNames.APPARENT_POWER_LIMIT) + || limitSubclassType.equals(CgmesNames.CURRENT_LIMIT); } private boolean isVoltageLimits() { - Objects.requireNonNull(limitSubclass); - return limitSubclass.equals("VoltageLimit"); + Objects.requireNonNull(limitSubclassType); + return limitSubclassType.equals("VoltageLimit"); } private void setVoltageLevelForVoltageLimit(Terminal terminal) { @@ -107,22 +107,22 @@ private void setVoltageLevelForVoltageLimit(Terminal terminal) { /** * 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. - * @param limitSubClass The subclass of the OperationalLimit. + * @param limitSubclass The subclass of the OperationalLimit. * @param limitSetId The id of the set containing the OperationalLimit. * @param limitSetName The name of the set containing the OperationalLimit. * @param b The branch to which the OperationalLimit applies. */ - private void createLimitsAdder(int terminalNumber, String limitSubClass, String limitSetId, String limitSetName, Branch b) { + 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); return b.newOperationalLimitsGroup1(limitSetId); }); - loadingLimitsAdder1 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass); + loadingLimitsAdder1 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubclass); } else if (terminalNumber == 2) { OperationalLimitsGroup limitsGroup = b.getOperationalLimitsGroup2(limitSetId).orElseGet(() -> { b.setProperty(PROPERTY_PREFIX + limitSetId, limitSetName); return b.newOperationalLimitsGroup2(limitSetId); }); - loadingLimitsAdder2 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass); + loadingLimitsAdder2 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubclass); } else { throw new IllegalArgumentException(); } @@ -130,42 +130,42 @@ private void createLimitsAdder(int terminalNumber, String limitSubClass, String /** * Create the LoadingLimitsAdder for the given dangling line and the given limit set + subclass. - * @param limitSubClass The subclass of the OperationalLimit. + * @param limitSubclass The subclass of the OperationalLimit. * @param limitSetId The set containing the OperationalLimit. * @param limitSetName The name of the set containing the OperationalLimit. * @param dl The branch to which the OperationalLimit applies. */ - private void createLimitsAdder(String limitSubClass, String limitSetId, String limitSetName, DanglingLine dl) { + private void createLimitsAdder(String limitSubclass, String limitSetId, String limitSetName, DanglingLine dl) { OperationalLimitsGroup limitsGroup = dl.getOperationalLimitsGroup(limitSetId).orElseGet(() -> { dl.setProperty(PROPERTY_PREFIX + limitSetId, limitSetName); return dl.newOperationalLimitsGroup(limitSetId); }); - loadingLimitsAdder = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass); + loadingLimitsAdder = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubclass); } /** * Create the LoadingLimitsAdder for the given 3w-transformer + side and the given limit set + subclass. * @param terminalNumber The side of the transformer to which the OperationalLimit applies. - * @param limitSubClass The subclass of the OperationalLimit. + * @param limitSubclass The subclass of the OperationalLimit. * @param limitSetId The set containing the OperationalLimit. * @param limitSetName The name of the set containing the OperationalLimit. * @param twt The 3w-transformer to which the OperationalLimit applies. */ - private void createLimitsAdder(int terminalNumber, String limitSubClass, String limitSetId, String limitSetName, ThreeWindingsTransformer twt) { + 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); return twt.getLeg1().newOperationalLimitsGroup(limitSetId); }); - loadingLimitsAdder1 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass); + loadingLimitsAdder1 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubclass); } else if (terminalNumber == 2) { OperationalLimitsGroup limitsGroup = twt.getLeg2().getOperationalLimitsGroup(limitSetId).orElseGet(() -> { twt.setProperty(PROPERTY_PREFIX + limitSetId, limitSetName); return twt.getLeg2().newOperationalLimitsGroup(limitSetId); }); - loadingLimitsAdder2 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass); + loadingLimitsAdder2 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubclass); } else if (terminalNumber == 3) { OperationalLimitsGroup limitsGroup = twt.getLeg3().getOperationalLimitsGroup(limitSetId).orElseGet(() -> { twt.setProperty(PROPERTY_PREFIX + limitSetId, limitSetName); return twt.getLeg3().newOperationalLimitsGroup(limitSetId); }); - loadingLimitsAdder3 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass); + loadingLimitsAdder3 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubclass); } else { throw new IllegalArgumentException(); } @@ -184,31 +184,31 @@ private void checkAndCreateLimitsAdder(int terminalNumber, String limitSetId, St Branch b = (Branch) identifiable; if (terminalNumber == -1) { // Limits applied to the whole equipment == to both sides - createLimitsAdder(1, limitSubclass, limitSetId, limitSetName, b); - createLimitsAdder(2, limitSubclass, limitSetId, limitSetName, b); + createLimitsAdder(1, limitSubclassType, limitSetId, limitSetName, b); + createLimitsAdder(2, limitSubclassType, limitSetId, limitSetName, b); } else if (terminalNumber == 1 || terminalNumber == 2) { - createLimitsAdder(terminalNumber, limitSubclass, limitSetId, limitSetName, b); + createLimitsAdder(terminalNumber, limitSubclassType, limitSetId, limitSetName, b); } else { notAssigned(b); } } else if (identifiable instanceof TwoWindingsTransformer) { Branch b = (Branch) identifiable; if (terminalNumber == 1 || terminalNumber == 2) { - createLimitsAdder(terminalNumber, limitSubclass, limitSetId, limitSetName, b); + createLimitsAdder(terminalNumber, limitSubclassType, limitSetId, limitSetName, b); } else { if (terminalNumber == -1) { - context.ignored(limitSubclass, "Defined for Equipment TwoWindingsTransformer. Should be defined for one Terminal of Two"); + context.ignored(limitSubclassType, "Defined for Equipment TwoWindingsTransformer. Should be defined for one Terminal of Two"); } notAssigned(b); } } else if (identifiable instanceof DanglingLine dl) { - createLimitsAdder(limitSubclass, limitSetId, limitSetName, dl); + createLimitsAdder(limitSubclassType, limitSetId, limitSetName, dl); } else if (identifiable instanceof ThreeWindingsTransformer twt) { if (terminalNumber == 1 || terminalNumber == 2 || terminalNumber == 3) { - createLimitsAdder(terminalNumber, limitSubclass, limitSetId, limitSetName, twt); + createLimitsAdder(terminalNumber, limitSubclassType, limitSetId, limitSetName, twt); } else { if (terminalNumber == -1) { - context.ignored(limitSubclass, "Defined for Equipment ThreeWindingsTransformer. Should be defined for one Terminal of Three"); + context.ignored(limitSubclassType, "Defined for Equipment ThreeWindingsTransformer. Should be defined for one Terminal of Three"); } notAssigned(twt); } @@ -402,10 +402,10 @@ private void addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(bool } private void addTemporaryOperationalLimitProperties(String operationalLimitId, String end, int duration, double value) { - Objects.requireNonNull(limitSubclass); - Objects.requireNonNull(identifiable); - identifiable.setProperty(getPropertyName(end, limitSubclass, duration), operationalLimitId); - identifiable.setProperty(getPropertyName(operationalLimitId), String.valueOf(value)); + Objects.requireNonNull(limitSubclassType); + Objects.requireNonNull(loadingLimitsIdentifiable); + loadingLimitsIdentifiable.setProperty(getPropertyName(end, limitSubclassType, duration), operationalLimitId); + loadingLimitsIdentifiable.setProperty(getPropertyName(operationalLimitId), String.valueOf(value)); } private void addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(boolean included, String operationalLimitId, String end, double value) { @@ -415,10 +415,10 @@ private void addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(bool } private void addPermanentOperationalLimitProperties(String operationalLimitId, String end, double value) { - Objects.requireNonNull(limitSubclass); - Objects.requireNonNull(identifiable); - identifiable.setProperty(getPropertyName(end, limitSubclass), operationalLimitId); - identifiable.setProperty(getPropertyName(operationalLimitId), String.valueOf(value)); + Objects.requireNonNull(limitSubclassType); + Objects.requireNonNull(loadingLimitsIdentifiable); + loadingLimitsIdentifiable.setProperty(getPropertyName(end, limitSubclassType), operationalLimitId); + loadingLimitsIdentifiable.setProperty(getPropertyName(operationalLimitId), String.valueOf(value)); } private void notAssigned() { @@ -457,22 +457,22 @@ public static void update(OperationalLimitsGroup operationalLimitsGroup, String operationalLimitsGroup.getCurrentLimits().ifPresent(currentLimits -> updateLoadingLimits(currentLimits, end, CgmesNames.CURRENT_LIMIT, identifiable, context)); } - private static void updateLoadingLimits(LoadingLimits loadingLimits, String end, String limitSubClass, Identifiable identifiable, Context context) { - loadingLimits.setPermanentLimit(getValue(end, limitSubClass, identifiable, loadingLimits.getPermanentLimit(), context)); + private static void updateLoadingLimits(LoadingLimits loadingLimits, String end, String limitSubclass, Identifiable identifiable, Context context) { + loadingLimits.setPermanentLimit(getValue(end, limitSubclass, identifiable, loadingLimits.getPermanentLimit(), context)); loadingLimits.getTemporaryLimits().forEach(temporaryLimit -> { int duration = temporaryLimit.getAcceptableDuration(); - loadingLimits.setTemporaryLimitValue(duration, getValue(end, limitSubClass, duration, identifiable, temporaryLimit.getValue(), context)); + loadingLimits.setTemporaryLimitValue(duration, getValue(end, limitSubclass, duration, identifiable, temporaryLimit.getValue(), context)); }); } - private static double getValue(String end, String limitSubClass, Identifiable identifiable, double previousValue, Context context) { - String operationalLimitId = getOperationalLimitId(getPropertyName(end, limitSubClass), identifiable); + private static double getValue(String end, String limitSubclass, Identifiable identifiable, double previousValue, Context context) { + String operationalLimitId = getOperationalLimitId(getPropertyName(end, limitSubclass), identifiable); return updatedValue(operationalLimitId, context) .orElse(defaultValue(getNormalValue(getPropertyName(operationalLimitId), identifiable), previousValue, getDefaultValue(context))); } - private static double getValue(String end, String limitSubClass, int duration, Identifiable identifiable, double previousValue, Context context) { - String operationalLimitId = getOperationalLimitId(getPropertyName(end, limitSubClass, duration), identifiable); + private static double getValue(String end, String limitSubclass, int duration, Identifiable identifiable, double previousValue, Context context) { + String operationalLimitId = getOperationalLimitId(getPropertyName(end, limitSubclass, duration), identifiable); return updatedValue(operationalLimitId, context) .orElse(defaultValue(getNormalValue(getPropertyName(operationalLimitId), identifiable), previousValue, getDefaultValue(context))); } @@ -493,12 +493,12 @@ private static double getNormalValue(String propertyName, Identifiable identi return Double.parseDouble(identifiable.getProperty(propertyName)); } - private static String getPropertyName(String end, String limitSubClass) { - return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT + "_" + end + "_" + limitSubClass + "_" + "patl"; + private static String getPropertyName(String end, String limitSubclass) { + return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT + "_" + end + "_" + limitSubclass + "_" + "patl"; } - private static String getPropertyName(String end, String limitSubClass, int duration) { - return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT + "_" + end + "_" + limitSubClass + "_" + "tatl" + "_" + duration; + private static String getPropertyName(String end, String limitSubclass, int duration) { + return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT + "_" + end + "_" + limitSubclass + "_" + "tatl" + "_" + duration; } private static String getPropertyName(String operationalLimitId) { @@ -518,8 +518,8 @@ private static Conversion.Config.DefaultValue getDefaultValue(Context context) { private final String terminalId; private final String equipmentId; - private final String limitSubclass; - private Identifiable identifiable; + private final String limitSubclassType; + private Identifiable loadingLimitsIdentifiable; private LoadingLimitsAdder loadingLimitsAdder; private LoadingLimitsAdder loadingLimitsAdder1; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java index c0907977c74..2056b08a074 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java @@ -28,8 +28,7 @@ import java.util.Optional; import java.util.OptionalInt; -import static com.powsybl.cgmes.conversion.CgmesReports.badTargetDeadbandRegulatingControlReport; -import static com.powsybl.cgmes.conversion.CgmesReports.badVoltageTargetValueRegulatingControlReport; +import static com.powsybl.cgmes.conversion.CgmesReports.*; import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.EMPTY; @@ -174,14 +173,17 @@ protected static > void addCgmesReferences(C transforme static > void updateRatioTapChanger(Connectable tw, RatioTapChanger rtc, String end, Context context, boolean isRegulatingAllowed) { if (regulatingControlIsDefined(rtc.getRegulationTerminal())) { String ratioTapChangerId = findTapChangerId(tw, Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.RATIO_TAP_CHANGER + end); - PropertyBag ratioTapChangerPropertyBag = findRatioTapChangerPropertyBag(ratioTapChangerId, context); - PropertyBag regulatingControl = findRegulatingControlPropertyBag(tw, ratioTapChangerId, context); - int tapPosition = findTapPosition(tw, ratioTapChangerPropertyBag, rtc, ratioTapChangerId, context); - rtc.setTapPosition(tapPosition); + int tapPosition = findRatioTapChangerPropertyBag(ratioTapChangerId, context) + .map(propertyBag -> findTapPosition(tw, propertyBag, rtc, ratioTapChangerId, context)) + .orElseGet(() -> findDefaultTapPosition(tw, rtc, ratioTapChangerId, context)); + int validTapPosition = isValidTapPosition(rtc, tapPosition) ? tapPosition : findDefaultTapPosition(tw, rtc, ratioTapChangerId, context); + rtc.setTapPosition(validTapPosition); - double targetV = findTargetV(regulatingControl, rtc, context); - double targetDeadband = findTargetDeadband(regulatingControl, rtc, context); + Optional regulatingControlPropertyBag = findRegulatingControlPropertyBag(tw, ratioTapChangerId, context); + double targetV = regulatingControlPropertyBag.map(AbstractTransformerConversion::findTargetV).orElseGet(() -> findDefaultTargetV(rtc, context)); + double targetDeadband = regulatingControlPropertyBag.map(AbstractTransformerConversion::findTargetDeadband).orElseGet(() -> findDefaultTargetDeadband(rtc, context)); + boolean regulatingOn = regulatingControlPropertyBag.map(propertyBag -> findRegulatingOn(propertyBag, rtc, context)).orElseGet(() -> findDefaultRegulatingOn(rtc, context)); // We always keep the targetValue // It targetValue is not valid, emit a warning and deactivate regulating control @@ -197,7 +199,7 @@ static > void updateRatioTapChanger(Connectable tw, targetDeadband = Double.NaN; // To avoid an exception from checkTargetDeadband } - rtc.setRegulating(findRegulatingOn(regulatingControl, rtc, context) && isRegulatingAllowed && validTargetV && validTargetDeadband) + rtc.setRegulating(regulatingOn && isRegulatingAllowed && validTargetV && validTargetDeadband) .setTargetV(targetV) .setTargetDeadband(targetDeadband); } @@ -206,21 +208,30 @@ static > void updateRatioTapChanger(Connectable tw, static > void updatePhaseTapChanger(Connectable tw, PhaseTapChanger ptc, String end, Context context, boolean isRegulatingAllowed) { if (regulatingControlIsDefined(ptc.getRegulationTerminal())) { String phaseTapChangerId = findTapChangerId(tw, Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.PHASE_TAP_CHANGER + end); - PropertyBag phaseTapChangerPropertyBag = findPhaseTapChangerPropertyBag(phaseTapChangerId, context); - PropertyBag regulatingControl = findRegulatingControlPropertyBag(tw, phaseTapChangerId, context); - int tapPosition = findTapPosition(tw, phaseTapChangerPropertyBag, ptc, phaseTapChangerId, context); - ptc.setTapPosition(tapPosition); + int tapPosition = findPhaseTapChangerPropertyBag(phaseTapChangerId, context) + .map(propertyBag -> findTapPosition(tw, propertyBag, ptc, phaseTapChangerId, context)) + .orElseGet(() -> findDefaultTapPosition(tw, ptc, phaseTapChangerId, context)); + int validTapPosition = isValidTapPosition(ptc, tapPosition) ? tapPosition : findDefaultTapPosition(tw, ptc, phaseTapChangerId, context); + ptc.setTapPosition(validTapPosition); - double targetValue = findTargetValue(regulatingControl, ptc, findTerminalSign(tw, end), context); - double targetDeadband = findTargetDeadband(regulatingControl, ptc, context); + Optional regulatingControlPropertyBag = findRegulatingControlPropertyBag(tw, phaseTapChangerId, context); + double targetValue = regulatingControlPropertyBag.map(propertyBag -> findTargetValue(propertyBag, findTerminalSign(tw, end))).orElseGet(() -> findDefaultTargetValue(ptc, context)); + double targetDeadband = regulatingControlPropertyBag.map(AbstractTransformerConversion::findTargetDeadband).orElseGet(() -> findDefaultTargetDeadband(ptc, context)); + boolean regulatingOn = regulatingControlPropertyBag.map(propertyBag -> findRegulatingOn(propertyBag, ptc, context)).orElseGet(() -> findDefaultRegulatingOn(ptc, context)); - boolean regulating = findRegulatingOn(regulatingControl, ptc, context); - boolean fixedRegulating = regulating; - if (regulating && ptc.getRegulationMode() == PhaseTapChanger.RegulationMode.FIXED_TAP) { + boolean fixedRegulating = regulatingOn; + if (regulatingOn && ptc.getRegulationMode() == PhaseTapChanger.RegulationMode.FIXED_TAP) { context.fixed(phaseTapChangerId, "RegulationMode: regulating is set to true whereas regulationMode is set to FIXED_TAP: regulating fixed to false"); fixedRegulating = false; } + + boolean validTargetValue = isValidTargetValue(targetValue); + if (!validTargetValue) { + context.invalid(phaseTapChangerId, "Regulating control has a bad target value " + targetValue); + badTargetValueRegulatingControlReport(context.getReportNode(), phaseTapChangerId, targetValue); + } + boolean validTargetDeadband = isValidTargetDeadband(targetDeadband); if (!validTargetDeadband) { context.invalid(phaseTapChangerId, "Regulating control has a bad target deadband " + targetDeadband); @@ -238,31 +249,34 @@ private static boolean regulatingControlIsDefined(Terminal regulatedTerminal) { return regulatedTerminal != null; } - private static PropertyBag findRatioTapChangerPropertyBag(String ratioTapChangerId, Context context) { - return ratioTapChangerId != null ? context.ratioTapChanger(ratioTapChangerId) : null; + private static Optional findRatioTapChangerPropertyBag(String ratioTapChangerId, Context context) { + return ratioTapChangerId != null ? Optional.ofNullable(context.ratioTapChanger(ratioTapChangerId)) : Optional.empty(); } - private static PropertyBag findPhaseTapChangerPropertyBag(String phaseTapChangerId, Context context) { - return phaseTapChangerId != null ? context.phaseTapChanger(phaseTapChangerId) : null; + private static Optional findPhaseTapChangerPropertyBag(String phaseTapChangerId, Context context) { + return phaseTapChangerId != null ? Optional.ofNullable(context.phaseTapChanger(phaseTapChangerId)) : Optional.empty(); } - private static > PropertyBag findRegulatingControlPropertyBag(Connectable tw, String tapChangerId, Context context) { + private static > Optional findRegulatingControlPropertyBag(Connectable tw, String tapChangerId, Context context) { CgmesTapChangers cgmesTcs = tw.getExtension(CgmesTapChangers.class); if (cgmesTcs != null && tapChangerId != null) { CgmesTapChanger cgmesTc = cgmesTcs.getTapChanger(tapChangerId); - return cgmesTc != null ? context.regulatingControl(cgmesTc.getControlId()) : null; + return cgmesTc != null ? Optional.ofNullable(context.regulatingControl(cgmesTc.getControlId())) : Optional.empty(); } - return null; + return Optional.empty(); } private static > int findTapPosition(Connectable tw, PropertyBag p, com.powsybl.iidm.network.TapChanger tapChanger, String tapChangerId, Context context) { OptionalInt tapPosition = findTapPosition(p, context); - return tapPosition.isPresent() && isValidTapPosition(tapChanger, tapPosition.getAsInt()) ? tapPosition.getAsInt() : - getDefaultTapPosition( - getNormalStep(tw, tapChangerId), - tapChanger.getTapPosition(), - tapChanger.getNeutralPosition().orElse(getNormalStep(tw, tapChangerId)), - getDefaultValueForTapPosition(context)); + return tapPosition.isPresent() ? tapPosition.getAsInt() : findDefaultTapPosition(tw, tapChanger, tapChangerId, context); + } + + private static > int findDefaultTapPosition(Connectable tw, com.powsybl.iidm.network.TapChanger tapChanger, String tapChangerId, Context context) { + return switch (getDefaultValueTypeForTapPosition(context)) { + case EQ -> getNormalStep(tw, tapChangerId); + case PREVIOUS -> tapChanger.getTapPosition(); + case DEFAULT, EMPTY -> tapChanger.getNeutralPosition().orElse(getNormalStep(tw, tapChangerId)); + }; } private static boolean isValidTapPosition(com.powsybl.iidm.network.TapChanger tapChanger, int tapPosition) { @@ -270,12 +284,8 @@ private static boolean isValidTapPosition(com.powsybl.iidm.network.TapChanger> int findTerminalSign(Connectable tw return terminalSign != null ? Integer.parseInt(terminalSign) : 1; } - private static int getDefaultTapPosition(int normalTapPosition, int previousTapPosition, int neutralTapPosition, Conversion.Config.DefaultValue defaultValue) { - return switch (defaultValue) { - case EQ -> normalTapPosition; - case PREVIOUS -> previousTapPosition; - case DEFAULT, EMPTY -> neutralTapPosition; - }; + private static Conversion.Config.DefaultValue getDefaultValueTypeForTapPosition(Context context) { + return selectDefaultValue(List.of(EQ, PREVIOUS, DEFAULT, EMPTY), context); } - private static Conversion.Config.DefaultValue getDefaultValueForTapPosition(Context context) { - return selectDefaultValue(List.of(EQ, PREVIOUS, DEFAULT, EMPTY), context); + private static double findTargetV(PropertyBag regulatingControl) { + return regulatingControl.asDouble("targetValue"); } - private static double findTargetV(PropertyBag regulatingControl, com.powsybl.iidm.network.RatioTapChanger ratioTapChanger, Context context) { - return regulatingControl != null - ? regulatingControl.asDouble("targetValue") - : findDefaultTarget(ratioTapChanger.getTargetV(), Double.NaN, Double.NaN, context); - //double nominalV = ratioTapChanger.getRegulationTerminal() != null ? ratioTapChanger.getRegulationTerminal().getVoltageLevel().getNominalV() : Double.NaN; + private static double findDefaultTargetV(com.powsybl.iidm.network.RatioTapChanger ratioTapChanger, Context context) { + return findDefaultTarget(ratioTapChanger.getTargetV(), Double.NaN, Double.NaN, context); } private static boolean isValidTargetV(double targetV) { return Double.isFinite(targetV) && targetV > 0.0; } - private static double findTargetValue(PropertyBag regulatingControl, com.powsybl.iidm.network.PhaseTapChanger phaseTapChanger, int terminalSign, Context context) { - double targetValue = regulatingControl != null ? regulatingControl.asDouble("targetValue") : Double.NaN; - return isValidTargetValue(targetValue) ? targetValue * terminalSign : findDefaultTarget(phaseTapChanger.getRegulationValue(), Double.NaN, Double.NaN, context); + private static double findTargetValue(PropertyBag regulatingControl, int terminalSign) { + return regulatingControl.asDouble("targetValue") * terminalSign; + } + + private static double findDefaultTargetValue(com.powsybl.iidm.network.PhaseTapChanger phaseTapChanger, Context context) { + return findDefaultTarget(phaseTapChanger.getRegulationValue(), Double.NaN, Double.NaN, context); } private static boolean isValidTargetValue(double targetValue) { @@ -358,10 +364,12 @@ private static boolean isValidTargetValue(double targetValue) { } // targetDeadBand is optional in Cgmes and mandatory in IIDM then a default value is provided when it is not defined in Cgmes - private static double findTargetDeadband(PropertyBag regulatingControl, com.powsybl.iidm.network.TapChanger tapChanger, Context context) { - return regulatingControl != null - ? regulatingControl.asDouble("targetDeadband") - : findDefaultTarget(tapChanger.getTargetDeadband(), 0.0, 0.0, context); + private static double findTargetDeadband(PropertyBag regulatingControl) { + return regulatingControl.asDouble("targetDeadband"); + } + + private static double findDefaultTargetDeadband(com.powsybl.iidm.network.TapChanger tapChanger, Context context) { + return findDefaultTarget(tapChanger.getTargetDeadband(), 0.0, 0.0, context); } private static boolean isValidTargetDeadband(double targetDeadband) { @@ -369,12 +377,11 @@ private static boolean isValidTargetDeadband(double targetDeadband) { } private static boolean findRegulatingOn(PropertyBag regulatingControl, com.powsybl.iidm.network.TapChanger tapChanger, Context context) { - Boolean regulatingOn = regulatingControl != null ? regulatingControl.asBoolean("enabled").orElse(null) : null; - return isValidRegulatingOn(regulatingOn) ? regulatingOn : findDefaultRegulatingOn(tapChanger.isRegulating(), context); + return regulatingControl.asBoolean("enabled").orElse(findDefaultRegulatingOn(tapChanger, context)); } - private static boolean isValidRegulatingOn(Boolean regulatingOn) { - return regulatingOn != null; + private static boolean findDefaultRegulatingOn(com.powsybl.iidm.network.TapChanger tapChanger, Context context) { + return findDefaultRegulatingOn(tapChanger.isRegulating(), context); } private static double findDefaultTarget(double previousTarget, double defaultTarget, double emptyValue, Context context) { From df10d15956910dc6050b51659599f60416e46d0e Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 7 Nov 2024 09:30:03 +0100 Subject: [PATCH 16/54] Minor changes Signed-off-by: marquesja1 --- .../main/java/com/powsybl/cgmes/conversion/CgmesReports.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java index 5e5ea742ad4..0fceb7222f9 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java @@ -102,7 +102,7 @@ public static void badTargetValueRegulatingControlReport(ReportNode reportNode, reportNode.newReportNode() .withMessageTemplate("badTargetValueRegulatingControl", "Equipment ${equipmentId} has a regulating control with bad target value: ${targetValue}.") .withUntypedValue("equipmentId", eqId) - .withUntypedValue("targetValue", targetValue) + .withTypedValue("targetValue", targetValue, TypedValue.VOLTAGE) .withSeverity(TypedValue.WARN_SEVERITY) .add(); } @@ -111,7 +111,7 @@ public static void badTargetDeadbandRegulatingControlReport(ReportNode reportNod reportNode.newReportNode() .withMessageTemplate("badTargetDeadbandRegulatingControl", "Equipment ${equipmentId} has a regulating control with bad target deadband: ${targetDeadband}.") .withUntypedValue("equipmentId", eqId) - .withUntypedValue("targetDeadband", targetDeadband) + .withTypedValue("targetDeadband", targetDeadband, TypedValue.VOLTAGE) .withSeverity(TypedValue.WARN_SEVERITY) .add(); } From 5114bde29b78e5508ff7430db49d20863001861e Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 7 Nov 2024 10:00:52 +0100 Subject: [PATCH 17/54] Pretty code Signed-off-by: marquesja1 --- .../export/SteadyStateHypothesisExport.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) 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 132494e47ad..46841f59a2c 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 @@ -528,12 +528,14 @@ private static RegulatingControlView combineRegulatingControlViews(List= 0) { - combined.targetDeadband = current.targetDeadband; - } else if (combined.targetDeadband == 0 && !Double.isNaN(current.targetDeadband) && current.targetDeadband > 0) { - combined.targetDeadband = current.targetDeadband; - } else if (combined.targetDeadband > 0 && !Double.isNaN(current.targetDeadband) && current.targetDeadband > 0 && current.targetDeadband < combined.targetDeadband) { - combined.targetDeadband = current.targetDeadband; + if (!Double.isNaN(current.targetDeadband) && current.targetDeadband >= 0) { + if (Double.isNaN(combined.targetDeadband) || combined.targetDeadband < 0) { + combined.targetDeadband = current.targetDeadband; + } else if (current.targetDeadband > 0 && combined.targetDeadband == 0) { + combined.targetDeadband = current.targetDeadband; + } else if (current.targetDeadband > 0 && current.targetDeadband < combined.targetDeadband) { + combined.targetDeadband = current.targetDeadband; + } } if (!combined.discrete && current.discrete) { combined.discrete = true; From 69ade84a40b50729b0f967016c42cf2dfa1c8f0d Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 7 Nov 2024 12:35:15 +0100 Subject: [PATCH 18/54] Reduce complexity Signed-off-by: marquesja1 --- .../elements/OperationalLimitConversion.java | 17 +++++++++-------- .../com/powsybl/iidm/network/util/LinkData.java | 17 +++++++++++++---- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java index e3fc2ce3f91..34cf31046c0 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java @@ -372,20 +372,16 @@ private void convertTatl(double value) { String operationalLimitId = p.getId(CgmesNames.OPERATIONAL_LIMIT); String name = Optional.ofNullable(p.getId("shortName")).orElse(p.getId("name")); if (loadingLimitsAdder != null) { - boolean added = addTatl(name, value, acceptableDuration, loadingLimitsAdder); - addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "", acceptableDuration, value); + addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder, operationalLimitId, ""); } else { if (loadingLimitsAdder1 != null) { - boolean added = addTatl(name, value, acceptableDuration, loadingLimitsAdder1); - addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "1", acceptableDuration, value); + addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder1, operationalLimitId, "1"); } if (loadingLimitsAdder2 != null) { - boolean added = addTatl(name, value, acceptableDuration, loadingLimitsAdder2); - addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "2", acceptableDuration, value); + addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder2, operationalLimitId, "2"); } if (loadingLimitsAdder3 != null) { - boolean added = addTatl(name, value, acceptableDuration, loadingLimitsAdder3); - addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "3", acceptableDuration, value); + addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder3, operationalLimitId, "3"); } } } else if (direction.endsWith("low")) { @@ -395,6 +391,11 @@ private void convertTatl(double value) { } } + private void addTatlAndTemporaryProperties(String name, double value, int acceptableDuration, LoadingLimitsAdder loadingLimitsAdder, String operationalLimitId, String end) { + boolean added = addTatl(name, value, acceptableDuration, loadingLimitsAdder); + addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, end, acceptableDuration, value); + } + private void addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(boolean included, String operationalLimitId, String end, int duration, double value) { if (included) { addTemporaryOperationalLimitProperties(operationalLimitId, end, duration, value); diff --git a/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/util/LinkData.java b/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/util/LinkData.java index 002463d76ef..d04a27ae235 100644 --- a/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/util/LinkData.java +++ b/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/util/LinkData.java @@ -114,7 +114,7 @@ static Complex flowYshunt(Complex ysh, double u, double theta) { return ysh.conjugate().multiply(v.conjugate().multiply(v)); } - static Flow flowBothEnds(Complex y11, Complex y12, Complex y21, Complex y22, + public static Flow flowBothEnds(Complex y11, Complex y12, Complex y21, Complex y22, double u1, double theta1, double u2, double theta2) { Complex v1 = ComplexUtils.polar2Complex(u1, theta1); @@ -181,8 +181,17 @@ public Complex y22() { } } - static class Flow { - Complex fromTo = Complex.ZERO; - Complex toFrom = Complex.ZERO; + public static class Flow { + public Complex fromTo = Complex.ZERO; + public Complex toFrom = Complex.ZERO; + + public Complex getFromTo() { + return fromTo; + } + + public Complex getToFrom() { + return toFrom; + } + } } From e4b95b3873654be35e0a5854014666463d95c5b4 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 7 Nov 2024 13:03:07 +0100 Subject: [PATCH 19/54] Reduce complexity Signed-off-by: marquesja1 --- .../elements/OperationalLimitConversion.java | 97 +++++++++++-------- .../export/SteadyStateHypothesisExport.java | 8 +- 2 files changed, 60 insertions(+), 45 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java index 34cf31046c0..3e1c6f19aa5 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java @@ -181,37 +181,13 @@ private void createLimitsAdder(int terminalNumber, String limitSubclass, String */ private void checkAndCreateLimitsAdder(int terminalNumber, String limitSetId, String limitSetName, Identifiable identifiable) { if (identifiable instanceof Line) { - Branch b = (Branch) identifiable; - if (terminalNumber == -1) { - // Limits applied to the whole equipment == to both sides - createLimitsAdder(1, limitSubclassType, limitSetId, limitSetName, b); - createLimitsAdder(2, limitSubclassType, limitSetId, limitSetName, b); - } else if (terminalNumber == 1 || terminalNumber == 2) { - createLimitsAdder(terminalNumber, limitSubclassType, limitSetId, limitSetName, b); - } else { - notAssigned(b); - } + checkAndCreateLimitsAdderBranch((Branch) identifiable, terminalNumber, limitSetId, limitSetName); } else if (identifiable instanceof TwoWindingsTransformer) { - Branch b = (Branch) identifiable; - if (terminalNumber == 1 || terminalNumber == 2) { - createLimitsAdder(terminalNumber, limitSubclassType, limitSetId, limitSetName, b); - } else { - if (terminalNumber == -1) { - context.ignored(limitSubclassType, "Defined for Equipment TwoWindingsTransformer. Should be defined for one Terminal of Two"); - } - notAssigned(b); - } + checkAndCreateLimitsAdderTwoWindingsTransformers((Branch) identifiable, terminalNumber, limitSetId, limitSetName); } else if (identifiable instanceof DanglingLine dl) { createLimitsAdder(limitSubclassType, limitSetId, limitSetName, dl); - } else if (identifiable instanceof ThreeWindingsTransformer twt) { - if (terminalNumber == 1 || terminalNumber == 2 || terminalNumber == 3) { - createLimitsAdder(terminalNumber, limitSubclassType, limitSetId, limitSetName, twt); - } else { - if (terminalNumber == -1) { - context.ignored(limitSubclassType, "Defined for Equipment ThreeWindingsTransformer. Should be defined for one Terminal of Three"); - } - notAssigned(twt); - } + } else if (identifiable instanceof ThreeWindingsTransformer t3w) { + checkAndCreateLimitsAdderThreeWindingsTransformers(t3w, terminalNumber, limitSetId, limitSetName); } else if (identifiable instanceof Switch) { Switch aswitch = context.network().getSwitch(equipmentId); notAssigned(aswitch); @@ -220,6 +196,40 @@ private void checkAndCreateLimitsAdder(int terminalNumber, String limitSetId, St } } + private void checkAndCreateLimitsAdderBranch(Branch b, int terminalNumber, String limitSetId, String limitSetName) { + if (terminalNumber == -1) { + // Limits applied to the whole equipment == to both sides + createLimitsAdder(1, limitSubclassType, limitSetId, limitSetName, b); + createLimitsAdder(2, limitSubclassType, limitSetId, limitSetName, b); + } else if (terminalNumber == 1 || terminalNumber == 2) { + createLimitsAdder(terminalNumber, limitSubclassType, limitSetId, limitSetName, b); + } else { + notAssigned(b); + } + } + + private void checkAndCreateLimitsAdderTwoWindingsTransformers(Branch b, int terminalNumber, String limitSetId, String limitSetName) { + if (terminalNumber == 1 || terminalNumber == 2) { + createLimitsAdder(terminalNumber, limitSubclassType, limitSetId, limitSetName, b); + } else { + if (terminalNumber == -1) { + context.ignored(limitSubclassType, "Defined for Equipment TwoWindingsTransformer. Should be defined for one Terminal of Two"); + } + notAssigned(b); + } + } + + private void checkAndCreateLimitsAdderThreeWindingsTransformers(ThreeWindingsTransformer t3w, int terminalNumber, String limitSetId, String limitSetName) { + if (terminalNumber == 1 || terminalNumber == 2 || terminalNumber == 3) { + createLimitsAdder(terminalNumber, limitSubclassType, limitSetId, limitSetName, t3w); + } else { + if (terminalNumber == -1) { + context.ignored(limitSubclassType, "Defined for Equipment ThreeWindingsTransformer. Should be defined for one Terminal of Three"); + } + notAssigned(t3w); + } + } + @Override public boolean valid() { if (vl == null && loadingLimitsAdder == null && loadingLimitsAdder1 == null && loadingLimitsAdder2 == null && loadingLimitsAdder3 == null) { @@ -371,19 +381,8 @@ private void convertTatl(double value) { if (direction == null || direction.endsWith("high") || direction.endsWith("absoluteValue")) { String operationalLimitId = p.getId(CgmesNames.OPERATIONAL_LIMIT); String name = Optional.ofNullable(p.getId("shortName")).orElse(p.getId("name")); - if (loadingLimitsAdder != null) { - addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder, operationalLimitId, ""); - } else { - if (loadingLimitsAdder1 != null) { - addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder1, operationalLimitId, "1"); - } - if (loadingLimitsAdder2 != null) { - addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder2, operationalLimitId, "2"); - } - if (loadingLimitsAdder3 != null) { - addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder3, operationalLimitId, "3"); - } - } + + addTemporayLoadingLimits(name, value, acceptableDuration, operationalLimitId); } else if (direction.endsWith("low")) { context.invalid(TEMPORARY_LIMIT, () -> String.format("TATL %s is a low limit", id)); } else { @@ -391,6 +390,22 @@ private void convertTatl(double value) { } } + private void addTemporayLoadingLimits(String name, double value, int acceptableDuration, String operationalLimitId) { + if (loadingLimitsAdder != null) { + addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder, operationalLimitId, ""); + } else { + if (loadingLimitsAdder1 != null) { + addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder1, operationalLimitId, "1"); + } + if (loadingLimitsAdder2 != null) { + addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder2, operationalLimitId, "2"); + } + if (loadingLimitsAdder3 != null) { + addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder3, operationalLimitId, "3"); + } + } + } + private void addTatlAndTemporaryProperties(String name, double value, int acceptableDuration, LoadingLimitsAdder loadingLimitsAdder, String operationalLimitId, String end) { boolean added = addTatl(name, value, acceptableDuration, loadingLimitsAdder); addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, end, acceptableDuration, value); 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 46841f59a2c..01c643c4059 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 @@ -528,12 +528,12 @@ private static RegulatingControlView combineRegulatingControlViews(List= 0) { + if (current.targetDeadband == 0) { if (Double.isNaN(combined.targetDeadband) || combined.targetDeadband < 0) { combined.targetDeadband = current.targetDeadband; - } else if (current.targetDeadband > 0 && combined.targetDeadband == 0) { - combined.targetDeadband = current.targetDeadband; - } else if (current.targetDeadband > 0 && current.targetDeadband < combined.targetDeadband) { + } + } else if (current.targetDeadband > 0) { + if (combined.targetDeadband == 0 || current.targetDeadband < combined.targetDeadband) { combined.targetDeadband = current.targetDeadband; } } From 81376bde3977180b1d37b5059e37f09a9a17ce0b Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 7 Nov 2024 13:14:15 +0100 Subject: [PATCH 20/54] Undo mistake made before Signed-off-by: marquesja1 --- .../com/powsybl/iidm/network/util/LinkData.java | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/util/LinkData.java b/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/util/LinkData.java index d04a27ae235..002463d76ef 100644 --- a/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/util/LinkData.java +++ b/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/util/LinkData.java @@ -114,7 +114,7 @@ static Complex flowYshunt(Complex ysh, double u, double theta) { return ysh.conjugate().multiply(v.conjugate().multiply(v)); } - public static Flow flowBothEnds(Complex y11, Complex y12, Complex y21, Complex y22, + static Flow flowBothEnds(Complex y11, Complex y12, Complex y21, Complex y22, double u1, double theta1, double u2, double theta2) { Complex v1 = ComplexUtils.polar2Complex(u1, theta1); @@ -181,17 +181,8 @@ public Complex y22() { } } - public static class Flow { - public Complex fromTo = Complex.ZERO; - public Complex toFrom = Complex.ZERO; - - public Complex getFromTo() { - return fromTo; - } - - public Complex getToFrom() { - return toFrom; - } - + static class Flow { + Complex fromTo = Complex.ZERO; + Complex toFrom = Complex.ZERO; } } From e7da075a13032a6ceb4f240191cbabdc204e4a66 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 7 Nov 2024 13:32:55 +0100 Subject: [PATCH 21/54] pretty code Signed-off-by: marquesja1 --- .../export/SteadyStateHypothesisExport.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) 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 01c643c4059..9986ab09994 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 @@ -528,14 +528,8 @@ private static RegulatingControlView combineRegulatingControlViews(List 0) { - if (combined.targetDeadband == 0 || current.targetDeadband < combined.targetDeadband) { - combined.targetDeadband = current.targetDeadband; - } + if (combinedTargetDeadbandMustBeUpdated(current.targetDeadband, combined.targetDeadband)) { + combined.targetDeadband = current.targetDeadband; } if (!combined.discrete && current.discrete) { combined.discrete = true; @@ -547,6 +541,11 @@ private static RegulatingControlView combineRegulatingControlViews(List 0 && (combinedTargetDeadband == 0 || currentTargetDeadband < combinedTargetDeadband); + } + private static void writeRegulatingControl(RegulatingControlView rc, String cimNamespace, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException { CgmesExportUtil.writeStartAbout(regulatingControlClassname(rc.type), rc.id, cimNamespace, writer, context); writer.writeStartElement(cimNamespace, "RegulatingControl.discrete"); From 4884abb7c7809b14cde8620af838d9f936c5b950 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 13 Nov 2024 11:32:28 +0100 Subject: [PATCH 22/54] Some improvements Signed-off-by: marquesja1 --- .../cgmes/conversion/CgmesReports.java | 4 +- .../com/powsybl/cgmes/conversion/Context.java | 2 +- .../powsybl/cgmes/conversion/Conversion.java | 12 +++--- .../com/powsybl/cgmes/conversion/Update.java | 41 ++++++++----------- ...AbstractConductingEquipmentConversion.java | 37 +++++++---------- .../AbstractIdentifiedObjectConversion.java | 2 +- .../elements/AbstractObjectConversion.java | 3 +- .../AsynchronousMachineConversion.java | 15 ++++--- .../elements/EnergyConsumerConversion.java | 14 +++---- .../elements/EnergySourceConversion.java | 17 ++++---- .../elements/OperationalLimitConversion.java | 2 +- .../AbstractTransformerConversion.java | 4 +- .../ThreeWindingsTransformerConversion.java | 10 ++--- .../TwoWindingsTransformerConversion.java | 6 +-- 14 files changed, 76 insertions(+), 93 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java index 0fceb7222f9..5e5ea742ad4 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java @@ -102,7 +102,7 @@ public static void badTargetValueRegulatingControlReport(ReportNode reportNode, reportNode.newReportNode() .withMessageTemplate("badTargetValueRegulatingControl", "Equipment ${equipmentId} has a regulating control with bad target value: ${targetValue}.") .withUntypedValue("equipmentId", eqId) - .withTypedValue("targetValue", targetValue, TypedValue.VOLTAGE) + .withUntypedValue("targetValue", targetValue) .withSeverity(TypedValue.WARN_SEVERITY) .add(); } @@ -111,7 +111,7 @@ public static void badTargetDeadbandRegulatingControlReport(ReportNode reportNod reportNode.newReportNode() .withMessageTemplate("badTargetDeadbandRegulatingControl", "Equipment ${equipmentId} has a regulating control with bad target deadband: ${targetDeadband}.") .withUntypedValue("equipmentId", eqId) - .withTypedValue("targetDeadband", targetDeadband, TypedValue.VOLTAGE) + .withUntypedValue("targetDeadband", targetDeadband) .withSeverity(TypedValue.WARN_SEVERITY) .add(); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java index 416e82603ec..e62b387e00c 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java @@ -103,7 +103,7 @@ public void convertedTerminal(String terminalId, Terminal t, int n, PowerFlow f) } } - public void mappingTerminal(String terminalId, Terminal t, int n) { + public void convertedTerminalWithOnlyEq(String terminalId, Terminal t, int n) { // Record the mapping between CGMES and IIDM terminals terminalMapping().add(terminalId, t, n); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java index 45ddf35fcb8..d2bb0a326f7 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java @@ -262,7 +262,7 @@ public Network convert(ReportNode reportNode) { // Set voltages and angles context.pushReportNode(CgmesReports.settingVoltagesAndAnglesReport(reportNode)); voltageAngles(nodes, context); - completeVoltagesAndAngles(network); + completeVoltagesAndAnglesLegacy(network); context.popReportNode(); // Save/store data for debug or external validation @@ -291,12 +291,12 @@ public Network convert(ReportNode reportNode) { // that has the context created during the convert (first) step // and all the data already loaded in the triplestore, // we only need to switch to a different set of queries - updateAfterConvert(network, context, reportNode); + updateWithAllInputs(network, context, reportNode); return network; } - private void updateAfterConvert(Network network, Context convertContext, ReportNode reportNode) { + private void updateWithAllInputs(Network network, Context convertContext, ReportNode reportNode) { // FIXME(Luma) Before switching to update we must invalidate all caches of the cgmes model // and change the query catalog to "update" mode if (!sshIncludedInCgmesModel(this.cgmes)) { @@ -334,7 +334,7 @@ private void update(Network network, Context updateContext, ReportNode reportNod updateLoads(network, cgmes, updateContext); updateTwoAndThreeWindingsTransformers(network, updateContext); - completeVoltagesAndAnglesAfterUpdate(network); + completeVoltagesAndAngles(network); network.runValidationChecks(false, reportNode); network.setMinimumAcceptableValidationLevel(ValidationLevel.STEADY_STATE_HYPOTHESIS); @@ -450,7 +450,7 @@ private Source isBoundaryBaseVoltage(String graph) { return graph.contains("EQ") && graph.contains("BD") ? Source.BOUNDARY : Source.IGM; } - private static void completeVoltagesAndAngles(Network network) { + private static void completeVoltagesAndAnglesLegacy(Network network) { // Voltage and angle in boundary buses network.getDanglingLineStream(DanglingLineFilter.UNPAIRED) @@ -458,7 +458,7 @@ private static void completeVoltagesAndAngles(Network network) { network.getTieLines().forEach(tieLine -> AbstractConductingEquipmentConversion.calculateVoltageAndAngleInBoundaryBus(tieLine.getDanglingLine1(), tieLine.getDanglingLine2())); } - private static void completeVoltagesAndAnglesAfterUpdate(Network network) { + private static void completeVoltagesAndAngles(Network network) { // Voltage and angle in starBus as properties network.getThreeWindingsTransformers() diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java index 68b0bb9a2d0..e48c909f60c 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java @@ -36,32 +36,33 @@ public static boolean isConvertSeparatedFromUpdate(PropertyBag p) { || p.propertyNames().contains("NonConformLoad") || p.propertyNames().contains("ConformLoad") || p.propertyNames().contains("StationSupply") - || p.propertyNames().contains("TwoWindingsTransformer"); + || p.propertyNames().contains("TwoWindingsTransformer") + || p.propertyNames().contains("ThreeWindingsTransformer"); } static void updateLoads(Network network, CgmesModel cgmes, Context context) { context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.LOAD.name())); Map identifiablePropertyBag = new HashMap<>(); - addPropertyBags(network, cgmes.energyConsumers(), CgmesNames.ENERGY_CONSUMER, identifiablePropertyBag); - addPropertyBags(network, cgmes.energySources(), CgmesNames.ENERGY_SOURCE, identifiablePropertyBag); - addPropertyBags(network, cgmes.asynchronousMachines(), CgmesNames.ASYNCHRONOUS_MACHINE, identifiablePropertyBag); + addPropertyBags(cgmes.energyConsumers(), CgmesNames.ENERGY_CONSUMER, identifiablePropertyBag); + addPropertyBags(cgmes.energySources(), CgmesNames.ENERGY_SOURCE, identifiablePropertyBag); + addPropertyBags(cgmes.asynchronousMachines(), CgmesNames.ASYNCHRONOUS_MACHINE, identifiablePropertyBag); - network.getLoads().forEach(load -> updateLoad(network, load, getPropertyBag(load.getId(), identifiablePropertyBag), context)); + network.getLoads().forEach(load -> updateLoad(load, getPropertyBag(load.getId(), identifiablePropertyBag), context)); context.popReportNode(); } - private static void updateLoad(Network network, Load load, PropertyBag propertyBag, Context context) { + private static void updateLoad(Load load, PropertyBag cgmesData, Context context) { if (!load.isFictitious()) { // Loads from SvInjections are fictitious String originalClass = load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS); PropertyBag cgmesTerminal = getPropertyBagOfCgmesTerminal(load, context); switch (originalClass) { - case CgmesNames.ENERGY_SOURCE -> new EnergySourceConversion(propertyBag, cgmesTerminal, load, context).update(network); + case CgmesNames.ENERGY_SOURCE -> new EnergySourceConversion(cgmesData, cgmesTerminal, load, context).update(); case CgmesNames.ASYNCHRONOUS_MACHINE -> - new AsynchronousMachineConversion(propertyBag, cgmesTerminal, load, context).update(network); + new AsynchronousMachineConversion(cgmesData, cgmesTerminal, load, context).update(); case CgmesNames.CONFORM_LOAD, CgmesNames.NONCONFORM_LOAD, CgmesNames.STATION_SUPPLY, CgmesNames.ENERGY_CONSUMER -> - new EnergyConsumerConversion(propertyBag, cgmesTerminal, load, context).update(network); + new EnergyConsumerConversion(cgmesData, cgmesTerminal, load, context).update(); default -> throw new ConversionException("Unexpected originalClass " + originalClass + " for Load: " + load.getId()); } @@ -70,32 +71,26 @@ private static void updateLoad(Network network, Load load, PropertyBag propertyB static void updateTwoAndThreeWindingsTransformers(Network network, Context context) { context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.TWO_WINDINGS_TRANSFORMER.name())); - network.getTwoWindingsTransformers().forEach(t2w -> updateTwoWindingsTransformer(network, t2w, namedPropertyBag("TwoWindingsTransformer", t2w.getId()), context)); + network.getTwoWindingsTransformers().forEach(t2w -> updateTwoWindingsTransformer(t2w, namedPropertyBag("TwoWindingsTransformer", t2w.getId()), context)); context.popReportNode(); context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.THREE_WINDINGS_TRANSFORMER.name())); - network.getThreeWindingsTransformers().forEach(t3w -> updateThreeWindingsTransformer(network, t3w, namedPropertyBag("ThreeWindingsTransformer", t3w.getId()), context)); + network.getThreeWindingsTransformers().forEach(t3w -> updateThreeWindingsTransformer(t3w, namedPropertyBag("ThreeWindingsTransformer", t3w.getId()), context)); context.popReportNode(); } - private static void updateTwoWindingsTransformer(Network network, TwoWindingsTransformer t2w, PropertyBag propertyBag, Context context) { + private static void updateTwoWindingsTransformer(TwoWindingsTransformer t2w, PropertyBag propertyBag, Context context) { PropertyBags cgmesTerminals = getPropertyBagsOfCgmesTerminals(t2w, context); - new TwoWindingsTransformerConversion(propertyBag, cgmesTerminals, t2w, context).update(network); + new TwoWindingsTransformerConversion(propertyBag, cgmesTerminals, t2w, context).update(); } - private static void updateThreeWindingsTransformer(Network network, ThreeWindingsTransformer t3w, PropertyBag propertyBag, Context context) { + private static void updateThreeWindingsTransformer(ThreeWindingsTransformer t3w, PropertyBag propertyBag, Context context) { PropertyBags cgmesTerminals = getPropertyBagsOfCgmesTerminals(t3w, context); - new ThreeWindingsTransformerConversion(propertyBag, cgmesTerminals, t3w, context).update(network); + new ThreeWindingsTransformerConversion(propertyBag, cgmesTerminals, t3w, context).update(); } - private static void addPropertyBags(Network network, PropertyBags propertyBags, String idTag, Map identifiablePropertyBag) { - propertyBags.forEach(propertyBag -> { - String propertyBagId = propertyBag.getId(idTag); - Identifiable identifiable = network.getIdentifiable(propertyBagId); - if (identifiable != null) { - identifiablePropertyBag.put(identifiable.getId(), propertyBag); - } - }); + private static void addPropertyBags(PropertyBags propertyBags, String idTag, Map identifiablePropertyBag) { + propertyBags.forEach(propertyBag -> identifiablePropertyBag.put(propertyBag.getId(idTag), propertyBag)); } private static PropertyBag getPropertyBag(String identifiableId, Map identifiablePropertyBag) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index faf3f204e71..1a84f317caa 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -549,7 +549,7 @@ PowerFlow powerFlowSV(int n) { protected void convertedTerminals(Terminal... ts) { if (ts.length != numTerminals) { - throw new IllegalStateException(); + throw new IllegalArgumentException(); } for (int k = 0; k < ts.length; k++) { int n = k + 1; @@ -558,20 +558,20 @@ protected void convertedTerminals(Terminal... ts) { } } - protected void mappingTerminals(Terminal... ts) { + protected void convertedTerminalsWithOnlyEq(Terminal... ts) { if (ts.length != numTerminals) { - throw new IllegalStateException(); + throw new IllegalArgumentException(); } for (int k = 0; k < ts.length; k++) { int n = k + 1; Terminal t = ts[k]; - context.mappingTerminal(terminalId(n), t, n); + context.convertedTerminalWithOnlyEq(terminalId(n), t, n); } } protected void updateTerminals(Context context, Terminal... ts) { if (ts.length != numTerminals) { - throw new IllegalStateException(); + throw new IllegalArgumentException(); } for (int k = 0; k < ts.length; k++) { updateTerminal(updatedTerminals[k].cgmesTerminal, ts[k], context); @@ -671,7 +671,7 @@ public void connect(InjectionAdder adder) { } } - public void connection(InjectionAdder adder) { + public void connectWithOnlyEq(InjectionAdder adder) { if (context.nodeBreaker()) { adder.setNode(iidmNode()); } else { @@ -707,7 +707,7 @@ public void connect(BranchAdder adder) { } } - public void connection(BranchAdder adder) { + public void connectWithOnlyEq(BranchAdder adder) { if (context.nodeBreaker()) { adder .setVoltageLevel1(iidmVoltageLevelId(1)) @@ -801,7 +801,7 @@ public void connect(VoltageLevel.BusBreakerView.SwitchAdder adder, boolean open) .setOpen(open || !terminalConnected(1) || !terminalConnected(2)); } - public void connection(LegAdder adder, int terminal) { + public void connectWithOnlyEq(LegAdder adder, int terminal) { if (context.nodeBreaker()) { adder .setVoltageLevel(iidmVoltageLevelId(terminal)) @@ -841,21 +841,12 @@ protected OptionalDouble updatedQ0() { return updatedPowerFlow().defined() ? OptionalDouble.of(updatedPowerFlow().q()) : OptionalDouble.empty(); } - protected static double defaultP(double eqP, double previousP, Conversion.Config.DefaultValue defaultValue) { - return switch (defaultValue) { - case EQ -> eqP; - case PREVIOUS -> previousP; - case DEFAULT -> 0.0; - case EMPTY -> Double.NaN; - }; - } - - protected static double defaultQ(double eqQ, double previousQ, Conversion.Config.DefaultValue defaultValue) { - return switch (defaultValue) { - case EQ -> eqQ; - case PREVIOUS -> previousQ; - case DEFAULT -> 0.0; - case EMPTY -> Double.NaN; + protected static double defaultValue(double eq, double previous, double defaultValue, double emptyValue, Conversion.Config.DefaultValue defaultValueSelector) { + return switch (defaultValueSelector) { + case EQ -> eq; + case PREVIOUS -> previous; + case DEFAULT -> defaultValue; + case EMPTY -> emptyValue; }; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java index c07e237bb27..56d0b011afc 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java @@ -98,7 +98,7 @@ protected String complete(String what) { } } - protected static Conversion.Config.DefaultValue selectDefaultValue(List validDefaultValues, Context context) { + protected static Conversion.Config.DefaultValue getDefaultValueSelector(List validDefaultValues, Context context) { return context.config().updateDefaultValuesPriority().stream().filter(validDefaultValues::contains).findFirst().orElse(EMPTY); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java index d456212a54f..55c3ae881b7 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java @@ -10,7 +10,6 @@ import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.ConversionException; -import com.powsybl.iidm.network.Network; import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; @@ -48,7 +47,7 @@ public void convertInsideBoundary() { public abstract void convert(); - public void update(Network network) { + public void update() { throw new ConversionException("Missing implementation: update for " + type); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java index 446d5e570cf..8230c1c8d39 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java @@ -14,7 +14,6 @@ import com.powsybl.iidm.network.Load; import com.powsybl.iidm.network.LoadAdder; import com.powsybl.iidm.network.LoadType; -import com.powsybl.iidm.network.Network; import com.powsybl.triplestore.api.PropertyBag; import java.util.List; @@ -45,28 +44,28 @@ public void convert() { LoadAdder adder = voltageLevel().newLoad() .setLoadType(loadType); identify(adder); - connection(adder); + connectWithOnlyEq(adder); Load newLoad = adder.add(); addAliasesAndProperties(newLoad); - mappingTerminals(newLoad.getTerminal()); + convertedTerminalsWithOnlyEq(newLoad.getTerminal()); addSpecificProperties(newLoad); } @Override - public void update(Network network) { + public void update() { Objects.requireNonNull(load); updateTerminals(context, load.getTerminal()); - load.setP0(updatedP0().orElse(defaultP(Double.NaN, load.getP0(), gettDefaultValue(context)))) - .setQ0(updatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), gettDefaultValue(context)))); + load.setP0(updatedP0().orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))) + .setQ0(updatedQ0().orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))); } private static void addSpecificProperties(Load newLoad) { newLoad.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ASYNCHRONOUS_MACHINE); } - private static Conversion.Config.DefaultValue gettDefaultValue(Context context) { - return selectDefaultValue(List.of(PREVIOUS, DEFAULT, EMPTY), context); + private static Conversion.Config.DefaultValue gettDefaultValueSelector(Context context) { + return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); } private final Load load; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index 7a65f2ec2f6..8f50b7fc259 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -56,11 +56,11 @@ public void convert() { LoadAdder adder = voltageLevel().newLoad() .setLoadType(loadType); identify(adder); - connection(adder); + connectWithOnlyEq(adder); model(adder); Load newLoad = adder.add(); addAliasesAndProperties(newLoad); - mappingTerminals(newLoad.getTerminal()); + convertedTerminalsWithOnlyEq(newLoad.getTerminal()); setLoadDetail(loadKind, newLoad, pFixed, qFixed); addSpecificProperties(newLoad, pFixed, qFixed); @@ -150,20 +150,20 @@ private static void setLoadDetail(String type, Load newLoad, double pFixed, doub } @Override - public void update(Network network) { + public void update() { Objects.requireNonNull(load); updateTerminals(context, load.getTerminal()); double pFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + P_FIXED)); double qFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + Q_FIXED)); - load.setP0(updatedP0().orElse(defaultP(pFixed, load.getP0(), getDefaultValue(context)))) - .setQ0(updatedQ0().orElse(defaultQ(qFixed, load.getQ0(), getDefaultValue(context)))); + load.setP0(updatedP0().orElse(defaultValue(pFixed, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))) + .setQ0(updatedQ0().orElse(defaultValue(qFixed, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); updateLoadDetail(load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS), pFixed, qFixed); } - private static Conversion.Config.DefaultValue getDefaultValue(Context context) { - return selectDefaultValue(List.of(EQ, PREVIOUS, DEFAULT, EMPTY), context); + private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { + return getDefaultValueSelector(List.of(EQ, PREVIOUS, DEFAULT, EMPTY), context); } private void updateLoadDetail(String type, double pFixed, double qFixed) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java index 682cd14ad4a..69031ecebf5 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java @@ -30,7 +30,7 @@ public EnergySourceConversion(PropertyBag es, Context context) { public EnergySourceConversion(PropertyBag es, PropertyBag cgmesTerminal, Load load, Context context) { super(CgmesNames.ENERGY_SOURCE, es, cgmesTerminal, context); - this.load = load; + this.load = Objects.requireNonNull(load); } @Override @@ -40,10 +40,10 @@ public void convert() { LoadAdder adder = voltageLevel().newLoad() .setLoadType(loadType); identify(adder); - connection(adder); + connectWithOnlyEq(adder); Load newLoad = adder.add(); addAliasesAndProperties(newLoad); - mappingTerminals(newLoad.getTerminal()); + convertedTerminalsWithOnlyEq(newLoad.getTerminal()); addSpecificProperties(newLoad); } @@ -53,15 +53,14 @@ private static void addSpecificProperties(Load newLoad) { } @Override - public void update(Network network) { - Objects.requireNonNull(load); + public void update() { updateTerminals(context, load.getTerminal()); - load.setP0(updatedP0().orElse(defaultP(Double.NaN, load.getP0(), getDefaultValue(context)))) - .setQ0(updatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), getDefaultValue(context)))); + load.setP0(updatedP0().orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))) + .setQ0(updatedQ0().orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); } - private static Conversion.Config.DefaultValue getDefaultValue(Context context) { - return selectDefaultValue(List.of(PREVIOUS, DEFAULT, EMPTY), context); + private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { + return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); } private final Load load; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java index 3e1c6f19aa5..4fc7b85fa6b 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java @@ -529,7 +529,7 @@ protected static double defaultValue(double normalValue, double previousValue, C } private static Conversion.Config.DefaultValue getDefaultValue(Context context) { - return selectDefaultValue(List.of(EQ, PREVIOUS), context); + return getDefaultValueSelector(List.of(EQ, PREVIOUS), context); } private final String terminalId; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java index 2056b08a074..4aa79dfc38f 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java @@ -336,7 +336,7 @@ private static > int findTerminalSign(Connectable tw } private static Conversion.Config.DefaultValue getDefaultValueTypeForTapPosition(Context context) { - return selectDefaultValue(List.of(EQ, PREVIOUS, DEFAULT, EMPTY), context); + return getDefaultValueSelector(List.of(EQ, PREVIOUS, DEFAULT, EMPTY), context); } private static double findTargetV(PropertyBag regulatingControl) { @@ -402,7 +402,7 @@ private static boolean findDefaultRegulatingOn(boolean previousRegulatingOn, Con } private static Conversion.Config.DefaultValue getDefaultValue(Context context) { - return selectDefaultValue(List.of(PREVIOUS, DEFAULT, EMPTY), context); + return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); } static boolean checkOnlyOneEnabled(boolean isAllowedToRegulate, boolean previousTapChangerIsRegulatingOn) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java index 935facef78b..d7cb74b206e 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java @@ -111,22 +111,22 @@ private void setToIidm(ConvertedT3xModel convertedT3xModel) { LegAdder l1adder = txadder.newLeg1(); setToIidmWindingAdder(convertedT3xModel.winding1, l1adder); - connection(l1adder, 1); + connectWithOnlyEq(l1adder, 1); l1adder.add(); LegAdder l2adder = txadder.newLeg2(); setToIidmWindingAdder(convertedT3xModel.winding2, l2adder); - connection(l2adder, 2); + connectWithOnlyEq(l2adder, 2); l2adder.add(); LegAdder l3adder = txadder.newLeg3(); setToIidmWindingAdder(convertedT3xModel.winding3, l3adder); - connection(l3adder, 3); + connectWithOnlyEq(l3adder, 3); l3adder.add(); ThreeWindingsTransformer tx = txadder.add(); addAliasesAndProperties(tx); - mappingTerminals( + convertedTerminalsWithOnlyEq( tx.getLeg1().getTerminal(), tx.getLeg2().getTerminal(), tx.getLeg3().getTerminal()); @@ -221,7 +221,7 @@ private void setRegulatingControlContext(ConvertedT3xModel convertedT3xModel, Th } @Override - public void update(Network network) { + public void update() { Objects.requireNonNull(t3w); updateTerminals(context, t3w.getLeg1().getTerminal(), t3w.getLeg2().getTerminal(), t3w.getLeg3().getTerminal()); diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java index 137017b58e3..a882bdcec9d 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java @@ -152,10 +152,10 @@ private void setToIidm(ConvertedT2xModel convertedT2xModel) { adder.setRatedS(convertedT2xModel.ratedS); } identify(adder); - connection(adder); + connectWithOnlyEq(adder); TwoWindingsTransformer tx = adder.add(); addAliasesAndProperties(tx); - mappingTerminals(tx.getTerminal1(), tx.getTerminal2()); + convertedTerminalsWithOnlyEq(tx.getTerminal1(), tx.getTerminal2()); setToIidmRatioTapChanger(convertedT2xModel, tx); setToIidmPhaseTapChanger(convertedT2xModel, tx, context); @@ -253,7 +253,7 @@ private static double getB(ConvertedT2xModel convertedT2xModel) { } @Override - public void update(Network network) { + public void update() { Objects.requireNonNull(t2w); updateTerminals(context, t2w.getTerminal1(), t2w.getTerminal2()); From 779d77807d470af7aae63db97d0044b9876a7dd4 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 13 Nov 2024 11:59:22 +0100 Subject: [PATCH 23/54] Some improvements Signed-off-by: marquesja1 --- .../com/powsybl/cgmes/conversion/Context.java | 2 +- .../powsybl/cgmes/conversion/Conversion.java | 4 +-- .../com/powsybl/cgmes/conversion/Update.java | 26 ++++++-------- ...AbstractConductingEquipmentConversion.java | 35 +++++++------------ .../elements/AbstractObjectConversion.java | 3 +- .../AsynchronousMachineConversion.java | 15 ++++---- .../elements/EnergyConsumerConversion.java | 14 ++++---- .../elements/EnergySourceConversion.java | 14 ++++---- 8 files changed, 48 insertions(+), 65 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java index 98c0b096501..0287534099f 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java @@ -101,7 +101,7 @@ public void convertedTerminal(String terminalId, Terminal t, int n, PowerFlow f) } } - public void mappingTerminal(String terminalId, Terminal t, int n) { + public void convertedTerminalWithOnlyEq(String terminalId, Terminal t, int n) { // Record the mapping between CGMES and IIDM terminals terminalMapping().add(terminalId, t, n); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java index b68b1082dd2..d898d4fd571 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java @@ -290,12 +290,12 @@ public Network convert(ReportNode reportNode) { // that has the context created during the convert (first) step // and all the data already loaded in the triplestore, // we only need to switch to a different set of queries - updateAfterConvert(network, context, reportNode); + updateWithAllInputs(network, context, reportNode); return network; } - private void updateAfterConvert(Network network, Context convertContext, ReportNode reportNode) { + private void updateWithAllInputs(Network network, Context convertContext, ReportNode reportNode) { // FIXME(Luma) Before switching to update we must invalidate all caches of the cgmes model // and change the query catalog to "update" mode if (!sshIncludedInCgmesModel(this.cgmes)) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java index 21e3e917b50..812b24d27af 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java @@ -44,39 +44,33 @@ static void updateLoads(Network network, CgmesModel cgmes, Context context) { context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.LOAD.name())); Map identifiablePropertyBag = new HashMap<>(); - addPropertyBags(network, cgmes.energyConsumers(), CgmesNames.ENERGY_CONSUMER, identifiablePropertyBag); - addPropertyBags(network, cgmes.energySources(), CgmesNames.ENERGY_SOURCE, identifiablePropertyBag); - addPropertyBags(network, cgmes.asynchronousMachines(), CgmesNames.ASYNCHRONOUS_MACHINE, identifiablePropertyBag); + addPropertyBags(cgmes.energyConsumers(), CgmesNames.ENERGY_CONSUMER, identifiablePropertyBag); + addPropertyBags(cgmes.energySources(), CgmesNames.ENERGY_SOURCE, identifiablePropertyBag); + addPropertyBags(cgmes.asynchronousMachines(), CgmesNames.ASYNCHRONOUS_MACHINE, identifiablePropertyBag); - network.getLoads().forEach(load -> updateLoad(network, load, getPropertyBag(load.getId(), identifiablePropertyBag), context)); + network.getLoads().forEach(load -> updateLoad(load, getPropertyBag(load.getId(), identifiablePropertyBag), context)); context.popReportNode(); } - private static void updateLoad(Network network, Load load, PropertyBag propertyBag, Context context) { + private static void updateLoad(Load load, PropertyBag cgmesData, Context context) { if (!load.isFictitious()) { // Loads from SvInjections are fictitious String originalClass = load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS); PropertyBag cgmesTerminal = getPropertyBagOfCgmesTerminal(load, context); switch (originalClass) { - case CgmesNames.ENERGY_SOURCE -> new EnergySourceConversion(propertyBag, cgmesTerminal, load, context).update(network); + case CgmesNames.ENERGY_SOURCE -> new EnergySourceConversion(cgmesData, cgmesTerminal, load, context).update(); case CgmesNames.ASYNCHRONOUS_MACHINE -> - new AsynchronousMachineConversion(propertyBag, cgmesTerminal, load, context).update(network); + new AsynchronousMachineConversion(cgmesData, cgmesTerminal, load, context).update(); case CgmesNames.CONFORM_LOAD, CgmesNames.NONCONFORM_LOAD, CgmesNames.STATION_SUPPLY, CgmesNames.ENERGY_CONSUMER -> - new EnergyConsumerConversion(propertyBag, cgmesTerminal, load, context).update(network); + new EnergyConsumerConversion(cgmesData, cgmesTerminal, load, context).update(); default -> throw new ConversionException("Unexpected originalClass " + originalClass + " for Load: " + load.getId()); } } } - private static void addPropertyBags(Network network, PropertyBags propertyBags, String idTag, Map identifiablePropertyBag) { - propertyBags.forEach(propertyBag -> { - String propertyBagId = propertyBag.getId(idTag); - Identifiable identifiable = network.getIdentifiable(propertyBagId); - if (identifiable != null) { - identifiablePropertyBag.put(identifiable.getId(), propertyBag); - } - }); + private static void addPropertyBags(PropertyBags propertyBags, String idTag, Map identifiablePropertyBag) { + propertyBags.forEach(propertyBag -> identifiablePropertyBag.put(propertyBag.getId(idTag), propertyBag)); } private static PropertyBag getPropertyBag(String identifiableId, Map identifiablePropertyBag) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index a6c7833392a..df48182b883 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -534,7 +534,7 @@ PowerFlow powerFlowSV(int n) { protected void convertedTerminals(Terminal... ts) { if (ts.length != numTerminals) { - throw new IllegalStateException(); + throw new IllegalArgumentException(); } for (int k = 0; k < ts.length; k++) { int n = k + 1; @@ -543,20 +543,20 @@ protected void convertedTerminals(Terminal... ts) { } } - protected void mappingTerminals(Terminal... ts) { + protected void convertedTerminalsWithOnlyEq(Terminal... ts) { if (ts.length != numTerminals) { - throw new IllegalStateException(); + throw new IllegalArgumentException(); } for (int k = 0; k < ts.length; k++) { int n = k + 1; Terminal t = ts[k]; - context.mappingTerminal(terminalId(n), t, n); + context.convertedTerminalWithOnlyEq(terminalId(n), t, n); } } protected void updateTerminals(Context context, Terminal... ts) { if (ts.length != numTerminals) { - throw new IllegalStateException(); + throw new IllegalArgumentException(); } for (int k = 0; k < ts.length; k++) { updateTerminal(updatedTerminals[k].cgmesTerminal, ts[k], context); @@ -656,7 +656,7 @@ public void connect(InjectionAdder adder) { } } - public void connection(InjectionAdder adder) { + public void connectWithOnlyEq(InjectionAdder adder) { if (context.nodeBreaker()) { adder.setNode(iidmNode()); } else { @@ -806,25 +806,16 @@ protected OptionalDouble updatedQ0() { return updatedPowerFlow().defined() ? OptionalDouble.of(updatedPowerFlow().q()) : OptionalDouble.empty(); } - protected static Conversion.Config.DefaultValue selectDefaultValue(List validDefaultValues, Context context) { + protected static Conversion.Config.DefaultValue getDefaultValueSelector(List validDefaultValues, Context context) { return context.config().updateDefaultValuesPriority().stream().filter(validDefaultValues::contains).findFirst().orElse(EMPTY); } - protected static double defaultP(double eqP, double previousP, Conversion.Config.DefaultValue defaultValue) { - return switch (defaultValue) { - case EQ -> eqP; - case PREVIOUS -> previousP; - case DEFAULT -> 0.0; - case EMPTY -> Double.NaN; - }; - } - - protected static double defaultQ(double eqQ, double previousQ, Conversion.Config.DefaultValue defaultValue) { - return switch (defaultValue) { - case EQ -> eqQ; - case PREVIOUS -> previousQ; - case DEFAULT -> 0.0; - case EMPTY -> Double.NaN; + protected static double defaultValue(double eq, double previous, double defaultValue, double emptyValue, Conversion.Config.DefaultValue defaultValueSelector) { + return switch (defaultValueSelector) { + case EQ -> eq; + case PREVIOUS -> previous; + case DEFAULT -> defaultValue; + case EMPTY -> emptyValue; }; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java index d456212a54f..55c3ae881b7 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java @@ -10,7 +10,6 @@ import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.ConversionException; -import com.powsybl.iidm.network.Network; import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; @@ -48,7 +47,7 @@ public void convertInsideBoundary() { public abstract void convert(); - public void update(Network network) { + public void update() { throw new ConversionException("Missing implementation: update for " + type); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java index 446d5e570cf..8230c1c8d39 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java @@ -14,7 +14,6 @@ import com.powsybl.iidm.network.Load; import com.powsybl.iidm.network.LoadAdder; import com.powsybl.iidm.network.LoadType; -import com.powsybl.iidm.network.Network; import com.powsybl.triplestore.api.PropertyBag; import java.util.List; @@ -45,28 +44,28 @@ public void convert() { LoadAdder adder = voltageLevel().newLoad() .setLoadType(loadType); identify(adder); - connection(adder); + connectWithOnlyEq(adder); Load newLoad = adder.add(); addAliasesAndProperties(newLoad); - mappingTerminals(newLoad.getTerminal()); + convertedTerminalsWithOnlyEq(newLoad.getTerminal()); addSpecificProperties(newLoad); } @Override - public void update(Network network) { + public void update() { Objects.requireNonNull(load); updateTerminals(context, load.getTerminal()); - load.setP0(updatedP0().orElse(defaultP(Double.NaN, load.getP0(), gettDefaultValue(context)))) - .setQ0(updatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), gettDefaultValue(context)))); + load.setP0(updatedP0().orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))) + .setQ0(updatedQ0().orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))); } private static void addSpecificProperties(Load newLoad) { newLoad.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ASYNCHRONOUS_MACHINE); } - private static Conversion.Config.DefaultValue gettDefaultValue(Context context) { - return selectDefaultValue(List.of(PREVIOUS, DEFAULT, EMPTY), context); + private static Conversion.Config.DefaultValue gettDefaultValueSelector(Context context) { + return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); } private final Load load; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index 7a65f2ec2f6..8f50b7fc259 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -56,11 +56,11 @@ public void convert() { LoadAdder adder = voltageLevel().newLoad() .setLoadType(loadType); identify(adder); - connection(adder); + connectWithOnlyEq(adder); model(adder); Load newLoad = adder.add(); addAliasesAndProperties(newLoad); - mappingTerminals(newLoad.getTerminal()); + convertedTerminalsWithOnlyEq(newLoad.getTerminal()); setLoadDetail(loadKind, newLoad, pFixed, qFixed); addSpecificProperties(newLoad, pFixed, qFixed); @@ -150,20 +150,20 @@ private static void setLoadDetail(String type, Load newLoad, double pFixed, doub } @Override - public void update(Network network) { + public void update() { Objects.requireNonNull(load); updateTerminals(context, load.getTerminal()); double pFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + P_FIXED)); double qFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + Q_FIXED)); - load.setP0(updatedP0().orElse(defaultP(pFixed, load.getP0(), getDefaultValue(context)))) - .setQ0(updatedQ0().orElse(defaultQ(qFixed, load.getQ0(), getDefaultValue(context)))); + load.setP0(updatedP0().orElse(defaultValue(pFixed, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))) + .setQ0(updatedQ0().orElse(defaultValue(qFixed, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); updateLoadDetail(load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS), pFixed, qFixed); } - private static Conversion.Config.DefaultValue getDefaultValue(Context context) { - return selectDefaultValue(List.of(EQ, PREVIOUS, DEFAULT, EMPTY), context); + private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { + return getDefaultValueSelector(List.of(EQ, PREVIOUS, DEFAULT, EMPTY), context); } private void updateLoadDetail(String type, double pFixed, double qFixed) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java index 682cd14ad4a..5a0bea33127 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java @@ -40,10 +40,10 @@ public void convert() { LoadAdder adder = voltageLevel().newLoad() .setLoadType(loadType); identify(adder); - connection(adder); + connectWithOnlyEq(adder); Load newLoad = adder.add(); addAliasesAndProperties(newLoad); - mappingTerminals(newLoad.getTerminal()); + convertedTerminalsWithOnlyEq(newLoad.getTerminal()); addSpecificProperties(newLoad); } @@ -53,15 +53,15 @@ private static void addSpecificProperties(Load newLoad) { } @Override - public void update(Network network) { + public void update() { Objects.requireNonNull(load); updateTerminals(context, load.getTerminal()); - load.setP0(updatedP0().orElse(defaultP(Double.NaN, load.getP0(), getDefaultValue(context)))) - .setQ0(updatedQ0().orElse(defaultQ(Double.NaN, load.getQ0(), getDefaultValue(context)))); + load.setP0(updatedP0().orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))) + .setQ0(updatedQ0().orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); } - private static Conversion.Config.DefaultValue getDefaultValue(Context context) { - return selectDefaultValue(List.of(PREVIOUS, DEFAULT, EMPTY), context); + private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { + return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); } private final Load load; From cdc18f7134dfa293089d25b1a874bf56abedadcb Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 13 Nov 2024 12:41:13 +0100 Subject: [PATCH 24/54] More improvements Signed-off-by: marquesja1 --- .../com/powsybl/cgmes/conversion/Update.java | 8 ++-- ...AbstractConductingEquipmentConversion.java | 18 ++++++++ .../AbstractTransformerConversion.java | 46 ++++++------------- .../ThreeWindingsTransformerConversion.java | 3 +- .../TwoWindingsTransformerConversion.java | 3 +- 5 files changed, 38 insertions(+), 40 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java index e48c909f60c..808cbc27b00 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java @@ -79,14 +79,14 @@ static void updateTwoAndThreeWindingsTransformers(Network network, Context conte context.popReportNode(); } - private static void updateTwoWindingsTransformer(TwoWindingsTransformer t2w, PropertyBag propertyBag, Context context) { + private static void updateTwoWindingsTransformer(TwoWindingsTransformer t2w, PropertyBag cgmesData, Context context) { PropertyBags cgmesTerminals = getPropertyBagsOfCgmesTerminals(t2w, context); - new TwoWindingsTransformerConversion(propertyBag, cgmesTerminals, t2w, context).update(); + new TwoWindingsTransformerConversion(cgmesData, cgmesTerminals, t2w, context).update(); } - private static void updateThreeWindingsTransformer(ThreeWindingsTransformer t3w, PropertyBag propertyBag, Context context) { + private static void updateThreeWindingsTransformer(ThreeWindingsTransformer t3w, PropertyBag cgmesData, Context context) { PropertyBags cgmesTerminals = getPropertyBagsOfCgmesTerminals(t3w, context); - new ThreeWindingsTransformerConversion(propertyBag, cgmesTerminals, t3w, context).update(); + new ThreeWindingsTransformerConversion(cgmesData, cgmesTerminals, t3w, context).update(); } private static void addPropertyBags(PropertyBags propertyBags, String idTag, Map identifiablePropertyBag) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index 1a84f317caa..a52f7312fc5 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -841,6 +841,24 @@ protected OptionalDouble updatedQ0() { return updatedPowerFlow().defined() ? OptionalDouble.of(updatedPowerFlow().q()) : OptionalDouble.empty(); } + protected static int defaultValue(int eq, int previous, int defaultValue, int emptyValue, Conversion.Config.DefaultValue defaultValueSelector) { + return switch (defaultValueSelector) { + case EQ -> eq; + case PREVIOUS -> previous; + case DEFAULT -> defaultValue; + case EMPTY -> emptyValue; + }; + } + + protected static boolean defaultValue(boolean eq, boolean previous, boolean defaultValue, boolean emptyValue, Conversion.Config.DefaultValue defaultValueSelector) { + return switch (defaultValueSelector) { + case EQ -> eq; + case PREVIOUS -> previous; + case DEFAULT -> defaultValue; + case EMPTY -> emptyValue; + }; + } + protected static double defaultValue(double eq, double previous, double defaultValue, double emptyValue, Conversion.Config.DefaultValue defaultValueSelector) { return switch (defaultValueSelector) { case EQ -> eq; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java index 4aa79dfc38f..089c6c16402 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java @@ -19,7 +19,6 @@ import com.powsybl.cgmes.extensions.CgmesTapChangers; import com.powsybl.cgmes.extensions.CgmesTapChangersAdder; import com.powsybl.cgmes.model.CgmesNames; -import com.powsybl.commons.PowsyblException; import com.powsybl.iidm.network.*; import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; @@ -272,11 +271,15 @@ private static > int findTapPosition(Connectable tw, } private static > int findDefaultTapPosition(Connectable tw, com.powsybl.iidm.network.TapChanger tapChanger, String tapChangerId, Context context) { - return switch (getDefaultValueTypeForTapPosition(context)) { - case EQ -> getNormalStep(tw, tapChangerId); - case PREVIOUS -> tapChanger.getTapPosition(); - case DEFAULT, EMPTY -> tapChanger.getNeutralPosition().orElse(getNormalStep(tw, tapChangerId)); - }; + return defaultValue(getNormalStep(tw, tapChangerId), + tapChanger.getTapPosition(), + tapChanger.getNeutralPosition().orElse(getNormalStep(tw, tapChangerId)), + tapChanger.getNeutralPosition().orElse(getNormalStep(tw, tapChangerId)), + getDefaultValueSelectorForTapPosition(context)); + } + + private static Conversion.Config.DefaultValue getDefaultValueSelectorForTapPosition(Context context) { + return getDefaultValueSelector(List.of(EQ, PREVIOUS, DEFAULT), context); } private static boolean isValidTapPosition(com.powsybl.iidm.network.TapChanger tapChanger, int tapPosition) { @@ -335,16 +338,12 @@ private static > int findTerminalSign(Connectable tw return terminalSign != null ? Integer.parseInt(terminalSign) : 1; } - private static Conversion.Config.DefaultValue getDefaultValueTypeForTapPosition(Context context) { - return getDefaultValueSelector(List.of(EQ, PREVIOUS, DEFAULT, EMPTY), context); - } - private static double findTargetV(PropertyBag regulatingControl) { return regulatingControl.asDouble("targetValue"); } private static double findDefaultTargetV(com.powsybl.iidm.network.RatioTapChanger ratioTapChanger, Context context) { - return findDefaultTarget(ratioTapChanger.getTargetV(), Double.NaN, Double.NaN, context); + return defaultValue(Double.NaN, ratioTapChanger.getTargetV(), Double.NaN, Double.NaN, getDefaultValueSelector(context)); } private static boolean isValidTargetV(double targetV) { @@ -356,7 +355,7 @@ private static double findTargetValue(PropertyBag regulatingControl, int termina } private static double findDefaultTargetValue(com.powsybl.iidm.network.PhaseTapChanger phaseTapChanger, Context context) { - return findDefaultTarget(phaseTapChanger.getRegulationValue(), Double.NaN, Double.NaN, context); + return defaultValue(Double.NaN, phaseTapChanger.getRegulationValue(), Double.NaN, Double.NaN, getDefaultValueSelector(context)); } private static boolean isValidTargetValue(double targetValue) { @@ -369,7 +368,7 @@ private static double findTargetDeadband(PropertyBag regulatingControl) { } private static double findDefaultTargetDeadband(com.powsybl.iidm.network.TapChanger tapChanger, Context context) { - return findDefaultTarget(tapChanger.getTargetDeadband(), 0.0, 0.0, context); + return defaultValue(Double.NaN, tapChanger.getTargetDeadband(), 0.0, 0.0, getDefaultValueSelector(context)); } private static boolean isValidTargetDeadband(double targetDeadband) { @@ -381,27 +380,10 @@ private static boolean findRegulatingOn(PropertyBag regulatingControl, com.powsy } private static boolean findDefaultRegulatingOn(com.powsybl.iidm.network.TapChanger tapChanger, Context context) { - return findDefaultRegulatingOn(tapChanger.isRegulating(), context); - } - - private static double findDefaultTarget(double previousTarget, double defaultTarget, double emptyValue, Context context) { - return switch (getDefaultValue(context)) { - case EQ -> throw new PowsyblException("unexpected default type: " + getDefaultValue(context).name()); - case PREVIOUS -> previousTarget; - case DEFAULT -> defaultTarget; - case EMPTY -> emptyValue; - }; - } - - private static boolean findDefaultRegulatingOn(boolean previousRegulatingOn, Context context) { - return switch (getDefaultValue(context)) { - case EQ -> throw new PowsyblException("unexpected default type: " + getDefaultValue(context).name()); - case PREVIOUS -> previousRegulatingOn; - case DEFAULT, EMPTY -> false; - }; + return defaultValue(false, tapChanger.isRegulating(), false, false, getDefaultValueSelector(context)); } - private static Conversion.Config.DefaultValue getDefaultValue(Context context) { + private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java index d7cb74b206e..255343bb6a5 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java @@ -70,7 +70,7 @@ public ThreeWindingsTransformerConversion(PropertyBags ends, Context context) { public ThreeWindingsTransformerConversion(PropertyBag t3wEmptyBag, PropertyBags cgmesTerminals, ThreeWindingsTransformer t3w, Context context) { super(CgmesNames.POWER_TRANSFORMER, t3wEmptyBag, cgmesTerminals, context); - this.t3w = t3w; + this.t3w = Objects.requireNonNull(t3w); } @Override @@ -222,7 +222,6 @@ private void setRegulatingControlContext(ConvertedT3xModel convertedT3xModel, Th @Override public void update() { - Objects.requireNonNull(t3w); updateTerminals(context, t3w.getLeg1().getTerminal(), t3w.getLeg2().getTerminal(), t3w.getLeg3().getTerminal()); boolean isAllowedToRegulatePtc1 = true; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java index a882bdcec9d..29a463b027a 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java @@ -71,7 +71,7 @@ public TwoWindingsTransformerConversion(PropertyBags ends, Context context) { public TwoWindingsTransformerConversion(PropertyBag t2wEmptyBag, PropertyBags cgmesTerminals, TwoWindingsTransformer t2w, Context context) { super(CgmesNames.POWER_TRANSFORMER, t2wEmptyBag, cgmesTerminals, context); - this.t2w = t2w; + this.t2w = Objects.requireNonNull(t2w); } @Override @@ -254,7 +254,6 @@ private static double getB(ConvertedT2xModel convertedT2xModel) { @Override public void update() { - Objects.requireNonNull(t2w); updateTerminals(context, t2w.getTerminal1(), t2w.getTerminal2()); boolean isAllowedToRegulatePtc = true; From 5b2796c30acd921a4b3896781af2ad5f38b1e768 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 14 Nov 2024 09:40:58 +0100 Subject: [PATCH 25/54] update by using static classes Signed-off-by: marquesja1 --- .../com/powsybl/cgmes/conversion/Update.java | 57 ++------ ...AbstractConductingEquipmentConversion.java | 136 +++++++----------- .../elements/AbstractObjectConversion.java | 4 - .../AsynchronousMachineConversion.java | 24 +--- .../elements/EnergyConsumerConversion.java | 24 +--- .../elements/EnergySourceConversion.java | 19 +-- .../AbstractTransformerConversion.java | 4 - .../ThreeWindingsTransformerConversion.java | 16 +-- .../TwoWindingsTransformerConversion.java | 14 +- 9 files changed, 92 insertions(+), 206 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java index 808cbc27b00..5f1a7937cb0 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java @@ -30,39 +30,26 @@ public final class Update { private Update() { } - public static boolean isConvertSeparatedFromUpdate(PropertyBag p) { - return p.propertyNames().contains("EnergyConsumer") - || p.propertyNames().contains("ConformLoad") - || p.propertyNames().contains("NonConformLoad") - || p.propertyNames().contains("ConformLoad") - || p.propertyNames().contains("StationSupply") - || p.propertyNames().contains("TwoWindingsTransformer") - || p.propertyNames().contains("ThreeWindingsTransformer"); - } - static void updateLoads(Network network, CgmesModel cgmes, Context context) { context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.LOAD.name())); - Map identifiablePropertyBag = new HashMap<>(); - addPropertyBags(cgmes.energyConsumers(), CgmesNames.ENERGY_CONSUMER, identifiablePropertyBag); - addPropertyBags(cgmes.energySources(), CgmesNames.ENERGY_SOURCE, identifiablePropertyBag); - addPropertyBags(cgmes.asynchronousMachines(), CgmesNames.ASYNCHRONOUS_MACHINE, identifiablePropertyBag); + Map equipmentIdPropertyBag = new HashMap<>(); + addPropertyBags(cgmes.energyConsumers(), CgmesNames.ENERGY_CONSUMER, equipmentIdPropertyBag); + addPropertyBags(cgmes.energySources(), CgmesNames.ENERGY_SOURCE, equipmentIdPropertyBag); + addPropertyBags(cgmes.asynchronousMachines(), CgmesNames.ASYNCHRONOUS_MACHINE, equipmentIdPropertyBag); - network.getLoads().forEach(load -> updateLoad(load, getPropertyBag(load.getId(), identifiablePropertyBag), context)); + network.getLoads().forEach(load -> updateLoad(load, getPropertyBag(load.getId(), equipmentIdPropertyBag), context)); context.popReportNode(); } private static void updateLoad(Load load, PropertyBag cgmesData, Context context) { if (!load.isFictitious()) { // Loads from SvInjections are fictitious String originalClass = load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS); - PropertyBag cgmesTerminal = getPropertyBagOfCgmesTerminal(load, context); switch (originalClass) { - case CgmesNames.ENERGY_SOURCE -> new EnergySourceConversion(cgmesData, cgmesTerminal, load, context).update(); - case CgmesNames.ASYNCHRONOUS_MACHINE -> - new AsynchronousMachineConversion(cgmesData, cgmesTerminal, load, context).update(); - case CgmesNames.CONFORM_LOAD, CgmesNames.NONCONFORM_LOAD, CgmesNames.STATION_SUPPLY, CgmesNames.ENERGY_CONSUMER -> - new EnergyConsumerConversion(cgmesData, cgmesTerminal, load, context).update(); + case CgmesNames.ENERGY_SOURCE -> EnergySourceConversion.update(cgmesData, load, context); + case CgmesNames.ASYNCHRONOUS_MACHINE -> AsynchronousMachineConversion.update(cgmesData, load, context); + case CgmesNames.CONFORM_LOAD, CgmesNames.NONCONFORM_LOAD, CgmesNames.STATION_SUPPLY, CgmesNames.ENERGY_CONSUMER -> EnergyConsumerConversion.update(cgmesData, load, context); default -> throw new ConversionException("Unexpected originalClass " + originalClass + " for Load: " + load.getId()); } @@ -71,30 +58,20 @@ private static void updateLoad(Load load, PropertyBag cgmesData, Context context static void updateTwoAndThreeWindingsTransformers(Network network, Context context) { context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.TWO_WINDINGS_TRANSFORMER.name())); - network.getTwoWindingsTransformers().forEach(t2w -> updateTwoWindingsTransformer(t2w, namedPropertyBag("TwoWindingsTransformer", t2w.getId()), context)); + network.getTwoWindingsTransformers().forEach(t2w -> TwoWindingsTransformerConversion.update(t2w, context)); context.popReportNode(); context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.THREE_WINDINGS_TRANSFORMER.name())); - network.getThreeWindingsTransformers().forEach(t3w -> updateThreeWindingsTransformer(t3w, namedPropertyBag("ThreeWindingsTransformer", t3w.getId()), context)); + network.getThreeWindingsTransformers().forEach(t3w -> ThreeWindingsTransformerConversion.update(t3w, context)); context.popReportNode(); } - private static void updateTwoWindingsTransformer(TwoWindingsTransformer t2w, PropertyBag cgmesData, Context context) { - PropertyBags cgmesTerminals = getPropertyBagsOfCgmesTerminals(t2w, context); - new TwoWindingsTransformerConversion(cgmesData, cgmesTerminals, t2w, context).update(); - } - - private static void updateThreeWindingsTransformer(ThreeWindingsTransformer t3w, PropertyBag cgmesData, Context context) { - PropertyBags cgmesTerminals = getPropertyBagsOfCgmesTerminals(t3w, context); - new ThreeWindingsTransformerConversion(cgmesData, cgmesTerminals, t3w, context).update(); + private static void addPropertyBags(PropertyBags propertyBags, String idTag, Map equipmentIdPropertyBag) { + propertyBags.forEach(propertyBag -> equipmentIdPropertyBag.put(propertyBag.getId(idTag), propertyBag)); } - private static void addPropertyBags(PropertyBags propertyBags, String idTag, Map identifiablePropertyBag) { - propertyBags.forEach(propertyBag -> identifiablePropertyBag.put(propertyBag.getId(idTag), propertyBag)); - } - - private static PropertyBag getPropertyBag(String identifiableId, Map identifiablePropertyBag) { - return identifiablePropertyBag.containsKey(identifiableId) ? identifiablePropertyBag.get(identifiableId) : emptyPropertyBag(); + private static PropertyBag getPropertyBag(String identifiableId, Map equipmentIdPropertyBag) { + return equipmentIdPropertyBag.containsKey(identifiableId) ? equipmentIdPropertyBag.get(identifiableId) : emptyPropertyBag(); } private static PropertyBag getPropertyBagOfCgmesTerminal(Connectable connectable, Context context) { @@ -124,10 +101,4 @@ private static PropertyBag getPropertyBagOfCgmesTerminal(String cgmesTerminalId, private static PropertyBag emptyPropertyBag() { return new PropertyBag(Collections.emptyList(), false); } - - private static PropertyBag namedPropertyBag(String propertyName, String id) { - PropertyBag propertyBag = new PropertyBag(Collections.emptyList(), false); - propertyBag.put(propertyName, id); - return propertyBag; - } } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index a52f7312fc5..49e97d4e0f6 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -21,12 +21,11 @@ import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.OptionalDouble; -import static com.powsybl.cgmes.conversion.Update.isConvertSeparatedFromUpdate; - /** * @author Luma Zamarreño {@literal } *

@@ -41,19 +40,11 @@ protected AbstractConductingEquipmentConversion( PropertyBag p, Context context) { super(type, p, context); - if (isConvertSeparatedFromUpdate(p)) { - numTerminals = 1; - terminals = new TerminalData[]{null, null, null}; - terminals[0] = new TerminalData(CgmesNames.TERMINAL, p, context); - steadyStatePowerFlow = PowerFlow.UNDEFINED; - updatedTerminals = null; - } else { - numTerminals = 1; - terminals = new TerminalData[]{null, null, null}; - terminals[0] = new TerminalData(CgmesNames.TERMINAL, p, context); - steadyStatePowerFlow = new PowerFlow(p, "p", "q"); - updatedTerminals = null; - } + numTerminals = 1; + terminals = new TerminalData[]{null, null, null}; + terminals[0] = new TerminalData(CgmesNames.TERMINAL, p, context); + steadyStatePowerFlow = new PowerFlow(p, "p", "q"); + } protected AbstractConductingEquipmentConversion( @@ -73,7 +64,6 @@ protected AbstractConductingEquipmentConversion( terminals[k0] = new TerminalData(CgmesNames.TERMINAL + k, p, context); } steadyStatePowerFlow = PowerFlow.UNDEFINED; - updatedTerminals = null; } protected AbstractConductingEquipmentConversion( @@ -94,35 +84,6 @@ protected AbstractConductingEquipmentConversion( terminals[k0] = new TerminalData(CgmesNames.TERMINAL, ps.get(k0), context); } steadyStatePowerFlow = PowerFlow.UNDEFINED; - updatedTerminals = null; - } - - protected AbstractConductingEquipmentConversion( - String type, - PropertyBag p, - PropertyBag cgmesTerminal, - Context context) { - super(type, p, context); - numTerminals = 1; - terminals = null; - steadyStatePowerFlow = new PowerFlow(p, "p", "q"); - updatedTerminals = new UpdatedTerminalData[]{null, null, null}; - updatedTerminals[0] = new UpdatedTerminalData(cgmesTerminal); - } - - protected AbstractConductingEquipmentConversion( - String type, - PropertyBag p, - PropertyBags cgmesTerminals, - Context context) { - super(type, p, context); - numTerminals = cgmesTerminals.size(); - terminals = null; - steadyStatePowerFlow = PowerFlow.UNDEFINED; - updatedTerminals = new UpdatedTerminalData[]{null, null, null}; - for (int i = 0; i < cgmesTerminals.size(); i++) { - updatedTerminals[i] = new UpdatedTerminalData(cgmesTerminals.get(i)); - } } public String findPairingKey(String boundaryNode) { @@ -495,10 +456,6 @@ private PowerFlow stateVariablesPowerFlow() { return terminals[0].t.flow(); } - private PowerFlow updatedStateVariablesPowerFlow() { - return new PowerFlow(updatedTerminals[0].cgmesTerminal, "p", "q"); - } - public PowerFlow stateVariablesPowerFlow(int n) { return terminals[n - 1].t.flow(); } @@ -507,10 +464,6 @@ private PowerFlow steadyStateHypothesisPowerFlow() { return steadyStatePowerFlow; } - private PowerFlow updatedSteadyStateHypothesisPowerFlow() { - return steadyStatePowerFlow; - } - PowerFlow powerFlow() { if (steadyStateHypothesisPowerFlow().defined()) { return steadyStateHypothesisPowerFlow(); @@ -521,16 +474,6 @@ PowerFlow powerFlow() { return PowerFlow.UNDEFINED; } - PowerFlow updatedPowerFlow() { - if (updatedSteadyStateHypothesisPowerFlow().defined()) { - return updatedSteadyStateHypothesisPowerFlow(); - } - if (updatedStateVariablesPowerFlow().defined()) { - return updatedStateVariablesPowerFlow(); - } - return PowerFlow.UNDEFINED; - } - PowerFlow powerFlowSV() { if (stateVariablesPowerFlow().defined()) { return stateVariablesPowerFlow(); @@ -569,12 +512,10 @@ protected void convertedTerminalsWithOnlyEq(Terminal... ts) { } } - protected void updateTerminals(Context context, Terminal... ts) { - if (ts.length != numTerminals) { - throw new IllegalArgumentException(); - } + protected static void updateTerminals(Connectable connectable, Context context, Terminal... ts) { + PropertyBags cgmesTerminals = getPropertyBagsOfTerminals(connectable, context, ts.length); for (int k = 0; k < ts.length; k++) { - updateTerminal(updatedTerminals[k].cgmesTerminal, ts[k], context); + updateTerminal(cgmesTerminals.get(k), ts[k], context); } } @@ -610,6 +551,33 @@ private static boolean setPQAllowed(Terminal t) { return t.getConnectable().getType() != IdentifiableType.BUSBAR_SECTION; } + private static PropertyBag getPropertyBagsOfTerminal(Connectable connectable, Context context) { + return getPropertyBagsOfTerminals(connectable, context, 1).get(0); + } + + private static PropertyBags getPropertyBagsOfTerminals(Connectable connectable, Context context, int numTerminals) { + PropertyBags propertyBags = new PropertyBags(); + getTerminalTags(numTerminals).forEach(terminalTag -> connectable.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + terminalTag) + .ifPresent(cgmesTerminalId -> propertyBags.add(getPropertyBagOfTerminal(cgmesTerminalId, context)))); + return propertyBags; + } + + private static List getTerminalTags(int numTerminals) { + return switch (numTerminals) { + case 1 -> List.of(CgmesNames.TERMINAL1); + case 2 -> List.of(CgmesNames.TERMINAL1, CgmesNames.TERMINAL2); + case 3 -> List.of(CgmesNames.TERMINAL1, CgmesNames.TERMINAL2, CgmesNames.TERMINAL3); + default -> throw new PowsyblException("unexpected number of terminals " + numTerminals); + }; + } + + // If the propertyBag is not received, an empty one is returned. + private static PropertyBag getPropertyBagOfTerminal(String cgmesTerminalId, Context context) { + return context.cgmesTerminal(cgmesTerminalId) != null + ? context.cgmesTerminal(cgmesTerminalId) + : new PropertyBag(Collections.emptyList(), false); + } + private final int numTerminals; static class TerminalData { @@ -654,14 +622,7 @@ private static String findCgmesVoltageLevelIdForContainer(String nodeId, Context } } - static class UpdatedTerminalData { - private final PropertyBag cgmesTerminal; - - UpdatedTerminalData(PropertyBag cgmesTerminal) { - this.cgmesTerminal = cgmesTerminal; - } - } - // Connections + // Connect public void connect(InjectionAdder adder) { if (context.nodeBreaker()) { @@ -833,12 +794,26 @@ protected double q0() { return powerFlow().defined() ? powerFlow().q() : 0.0; } - protected OptionalDouble updatedP0() { - return updatedPowerFlow().defined() ? OptionalDouble.of(updatedPowerFlow().p()) : OptionalDouble.empty(); + protected static OptionalDouble updatedP0(Connectable connectable, PropertyBag cgmesData, Context context) { + PowerFlow powerFlow = getPowerFlow(cgmesData, getPropertyBagsOfTerminal(connectable, context)); + return powerFlow.defined() ? OptionalDouble.of(powerFlow.p()) : OptionalDouble.empty(); + } + + protected static OptionalDouble updatedQ0(Connectable connectable, PropertyBag cgmesData, Context context) { + PowerFlow powerFlow = getPowerFlow(cgmesData, getPropertyBagsOfTerminal(connectable, context)); + return powerFlow.defined() ? OptionalDouble.of(powerFlow.q()) : OptionalDouble.empty(); } - protected OptionalDouble updatedQ0() { - return updatedPowerFlow().defined() ? OptionalDouble.of(updatedPowerFlow().q()) : OptionalDouble.empty(); + private static PowerFlow getPowerFlow(PropertyBag cgmesData, PropertyBag cgmesTerminal) { + PowerFlow steadyStateHypothesisPowerFlow = new PowerFlow(cgmesData, "p", "q"); + if (steadyStateHypothesisPowerFlow.defined()) { + return steadyStateHypothesisPowerFlow; + } + PowerFlow stateVariablesPowerFlow = new PowerFlow(cgmesTerminal, "p", "q"); + if (stateVariablesPowerFlow.defined()) { + return stateVariablesPowerFlow; + } + return PowerFlow.UNDEFINED; } protected static int defaultValue(int eq, int previous, int defaultValue, int emptyValue, Conversion.Config.DefaultValue defaultValueSelector) { @@ -870,5 +845,4 @@ protected static double defaultValue(double eq, double previous, double defaultV private final TerminalData[] terminals; private final PowerFlow steadyStatePowerFlow; - private final UpdatedTerminalData[] updatedTerminals; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java index 55c3ae881b7..0b6945c1acf 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java @@ -47,10 +47,6 @@ public void convertInsideBoundary() { public abstract void convert(); - public void update() { - throw new ConversionException("Missing implementation: update for " + type); - } - public abstract String what(); protected abstract String complete(String what); diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java index 8230c1c8d39..bb306488689 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java @@ -17,7 +17,6 @@ import com.powsybl.triplestore.api.PropertyBag; import java.util.List; -import java.util.Objects; import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; @@ -28,12 +27,6 @@ public class AsynchronousMachineConversion extends AbstractConductingEquipmentCo public AsynchronousMachineConversion(PropertyBag asm, Context context) { super(CgmesNames.ASYNCHRONOUS_MACHINE, asm, context); - this.load = null; - } - - public AsynchronousMachineConversion(PropertyBag es, PropertyBag cgmesTerminal, Load load, Context context) { - super(CgmesNames.ASYNCHRONOUS_MACHINE, es, cgmesTerminal, context); - this.load = load; } @Override @@ -52,23 +45,20 @@ public void convert() { addSpecificProperties(newLoad); } - @Override - public void update() { - Objects.requireNonNull(load); - updateTerminals(context, load.getTerminal()); - load.setP0(updatedP0().orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))) - .setQ0(updatedQ0().orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))); - } - private static void addSpecificProperties(Load newLoad) { newLoad.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ASYNCHRONOUS_MACHINE); } + public static void update(PropertyBag cgmesData, Load load, Context context) { + updateTerminals(load, context, load.getTerminal()); + + load.setP0(updatedP0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))); + load.setQ0(updatedQ0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))); + } + private static Conversion.Config.DefaultValue gettDefaultValueSelector(Context context) { return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); } - - private final Load load; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index 8f50b7fc259..92c6ae62437 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -17,7 +17,6 @@ import com.powsybl.triplestore.api.PropertyBag; import java.util.List; -import java.util.Objects; import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; @@ -32,13 +31,6 @@ public class EnergyConsumerConversion extends AbstractConductingEquipmentConvers public EnergyConsumerConversion(PropertyBag ec, Context context) { super(CgmesNames.ENERGY_CONSUMER, ec, context); loadKind = ec.getLocal("type"); - this.load = null; - } - - public EnergyConsumerConversion(PropertyBag es, PropertyBag cgmesTerminal, Load load, Context context) { - super(CgmesNames.ENERGY_CONSUMER, es, cgmesTerminal, context); - this.loadKind = null; - this.load = load; } @Override @@ -149,24 +141,23 @@ private static void setLoadDetail(String type, Load newLoad, double pFixed, doub // else: EnergyConsumer - undefined } - @Override - public void update() { - Objects.requireNonNull(load); - updateTerminals(context, load.getTerminal()); + public static void update(PropertyBag cgmesData, Load load, Context context) { + updateTerminals(load, context, load.getTerminal()); double pFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + P_FIXED)); double qFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + Q_FIXED)); - load.setP0(updatedP0().orElse(defaultValue(pFixed, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))) - .setQ0(updatedQ0().orElse(defaultValue(qFixed, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); - updateLoadDetail(load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS), pFixed, qFixed); + load.setP0(updatedP0(load, cgmesData, context).orElse(defaultValue(pFixed, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); + load.setQ0(updatedQ0(load, cgmesData, context).orElse(defaultValue(qFixed, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); + + updateLoadDetail(load, load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS), pFixed, qFixed); } private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { return getDefaultValueSelector(List.of(EQ, PREVIOUS, DEFAULT, EMPTY), context); } - private void updateLoadDetail(String type, double pFixed, double qFixed) { + private static void updateLoadDetail(Load load, String type, double pFixed, double qFixed) { if (type == null) { return; } @@ -184,5 +175,4 @@ private void updateLoadDetail(String type, double pFixed, double qFixed) { } private final String loadKind; - private final Load load; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java index 69031ecebf5..f169ee2c4a2 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java @@ -15,7 +15,6 @@ import com.powsybl.triplestore.api.PropertyBag; import java.util.List; -import java.util.Objects; import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; @@ -25,12 +24,6 @@ public class EnergySourceConversion extends AbstractConductingEquipmentConversion { public EnergySourceConversion(PropertyBag es, Context context) { super(CgmesNames.ENERGY_SOURCE, es, context); - this.load = null; - } - - public EnergySourceConversion(PropertyBag es, PropertyBag cgmesTerminal, Load load, Context context) { - super(CgmesNames.ENERGY_SOURCE, es, cgmesTerminal, context); - this.load = Objects.requireNonNull(load); } @Override @@ -52,16 +45,14 @@ private static void addSpecificProperties(Load newLoad) { newLoad.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ENERGY_SOURCE); } - @Override - public void update() { - updateTerminals(context, load.getTerminal()); - load.setP0(updatedP0().orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))) - .setQ0(updatedQ0().orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); + public static void update(PropertyBag cgmesData, Load load, Context context) { + updateTerminals(load, context, load.getTerminal()); + + load.setP0(updatedP0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); + load.setQ0(updatedQ0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); } private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); } - - private final Load load; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java index 089c6c16402..c10f91f99f1 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java @@ -41,10 +41,6 @@ abstract class AbstractTransformerConversion extends AbstractConductingEquipment super(type, ends, context); } - AbstractTransformerConversion(String type, PropertyBag transformerPropertyBag, PropertyBags cgmesTerminals, Context context) { - super(type, transformerPropertyBag, cgmesTerminals, context); - } - protected static void setToIidmRatioTapChanger(TapChanger rtc, RatioTapChangerAdder rtca) { boolean isLtcFlag = rtc.isLtcFlag(); int lowStep = rtc.getLowTapPosition(); diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java index 255343bb6a5..7279aa0469a 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java @@ -19,11 +19,8 @@ import com.powsybl.iidm.network.ThreeWindingsTransformerAdder.LegAdder; import com.powsybl.iidm.network.extensions.ThreeWindingsTransformerPhaseAngleClock; import com.powsybl.iidm.network.util.TwtData; -import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; -import java.util.Objects; - /** * ThreeWindingsTransformer Cgmes Conversion *

@@ -61,16 +58,8 @@ */ public class ThreeWindingsTransformerConversion extends AbstractTransformerConversion { - private final ThreeWindingsTransformer t3w; - public ThreeWindingsTransformerConversion(PropertyBags ends, Context context) { super(CgmesNames.POWER_TRANSFORMER, ends, context); - this.t3w = null; - } - - public ThreeWindingsTransformerConversion(PropertyBag t3wEmptyBag, PropertyBags cgmesTerminals, ThreeWindingsTransformer t3w, Context context) { - super(CgmesNames.POWER_TRANSFORMER, t3wEmptyBag, cgmesTerminals, context); - this.t3w = Objects.requireNonNull(t3w); } @Override @@ -220,9 +209,8 @@ private void setRegulatingControlContext(ConvertedT3xModel convertedT3xModel, Th context.regulatingControlMapping().forTransformers().add(tx.getId(), rcRtc1, rcPtc1, rcRtc2, rcPtc2, rcRtc3, rcPtc3); } - @Override - public void update() { - updateTerminals(context, t3w.getLeg1().getTerminal(), t3w.getLeg2().getTerminal(), t3w.getLeg3().getTerminal()); + public static void update(ThreeWindingsTransformer t3w, Context context) { + updateTerminals(t3w, context, t3w.getLeg1().getTerminal(), t3w.getLeg2().getTerminal(), t3w.getLeg3().getTerminal()); boolean isAllowedToRegulatePtc1 = true; t3w.getLeg1().getOptionalPhaseTapChanger().ifPresent(ptc -> updatePhaseTapChanger(t3w, ptc, "1", context, isAllowedToRegulatePtc1)); diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java index 29a463b027a..65ab4b49dd2 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java @@ -18,10 +18,8 @@ import com.powsybl.cgmes.conversion.RegulatingControlMappingForTransformers.CgmesRegulatingControlRatio; import com.powsybl.cgmes.conversion.elements.EquipmentAtBoundaryConversion; import com.powsybl.cgmes.model.CgmesNames; -import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; -import java.util.Objects; import java.util.Optional; /** @@ -61,17 +59,10 @@ */ public class TwoWindingsTransformerConversion extends AbstractTransformerConversion implements EquipmentAtBoundaryConversion { - private final TwoWindingsTransformer t2w; private DanglingLine danglingLine; public TwoWindingsTransformerConversion(PropertyBags ends, Context context) { super(CgmesNames.POWER_TRANSFORMER, ends, context); - this.t2w = null; - } - - public TwoWindingsTransformerConversion(PropertyBag t2wEmptyBag, PropertyBags cgmesTerminals, TwoWindingsTransformer t2w, Context context) { - super(CgmesNames.POWER_TRANSFORMER, t2wEmptyBag, cgmesTerminals, context); - this.t2w = Objects.requireNonNull(t2w); } @Override @@ -252,9 +243,8 @@ private static double getB(ConvertedT2xModel convertedT2xModel) { return getValue(convertedT2xModel.end1.b, getStepB1(convertedT2xModel.end1.ratioTapChanger), getStepB1(convertedT2xModel.end1.phaseTapChanger)); } - @Override - public void update() { - updateTerminals(context, t2w.getTerminal1(), t2w.getTerminal2()); + public static void update(TwoWindingsTransformer t2w, Context context) { + updateTerminals(t2w, context, t2w.getTerminal1(), t2w.getTerminal2()); boolean isAllowedToRegulatePtc = true; t2w.getOptionalPhaseTapChanger().ifPresent(ptc -> updatePhaseTapChanger(t2w, ptc, "", context, isAllowedToRegulatePtc)); From 324c805a2fcfd12249932b8ec2427faa301d5fc0 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 14 Nov 2024 09:56:44 +0100 Subject: [PATCH 26/54] Remove unused methods Signed-off-by: marquesja1 --- .../com/powsybl/cgmes/conversion/Update.java | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java index 5f1a7937cb0..cd424fae906 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java @@ -74,30 +74,6 @@ private static PropertyBag getPropertyBag(String identifiableId, Map connectable, Context context) { - Optional cgmesTerminalId = connectable.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL1); - if (cgmesTerminalId.isPresent()) { - return getPropertyBagOfCgmesTerminal(cgmesTerminalId.get(), context); - } else { - return emptyPropertyBag(); - } - } - - private static PropertyBags getPropertyBagsOfCgmesTerminals(Connectable connectable, Context context) { - PropertyBags propertyBags = new PropertyBags(); - connectable.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL1) - .ifPresent(cgmesTerminalId -> propertyBags.add(getPropertyBagOfCgmesTerminal(cgmesTerminalId, context))); - connectable.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL2) - .ifPresent(cgmesTerminalId -> propertyBags.add(getPropertyBagOfCgmesTerminal(cgmesTerminalId, context))); - connectable.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL3) - .ifPresent(cgmesTerminalId -> propertyBags.add(getPropertyBagOfCgmesTerminal(cgmesTerminalId, context))); - return propertyBags; - } - - private static PropertyBag getPropertyBagOfCgmesTerminal(String cgmesTerminalId, Context context) { - return context.cgmesTerminal(cgmesTerminalId) != null ? context.cgmesTerminal(cgmesTerminalId) : emptyPropertyBag(); - } - private static PropertyBag emptyPropertyBag() { return new PropertyBag(Collections.emptyList(), false); } From 160edf1fc3585521de0a5b779e4ff10d79b3ffd3 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 14 Nov 2024 10:32:41 +0100 Subject: [PATCH 27/54] update by using static classes Signed-off-by: marquesja1 --- .../com/powsybl/cgmes/conversion/Update.java | 54 ++------ ...AbstractConductingEquipmentConversion.java | 124 ++++++++---------- .../elements/AbstractObjectConversion.java | 4 - .../AsynchronousMachineConversion.java | 24 +--- .../elements/EnergyConsumerConversion.java | 24 +--- .../elements/EnergySourceConversion.java | 20 +-- 6 files changed, 89 insertions(+), 161 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java index 812b24d27af..b5c3d7c683b 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java @@ -16,10 +16,7 @@ import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; +import java.util.*; /** * @author Luma Zamarreño {@literal } @@ -31,63 +28,38 @@ public final class Update { private Update() { } - public static boolean isConvertSeparatedFromUpdate(PropertyBag p) { - return p.propertyNames().contains("EnergyConsumer") - || p.propertyNames().contains("ConformLoad") - || p.propertyNames().contains("NonConformLoad") - || p.propertyNames().contains("ConformLoad") - || p.propertyNames().contains("StationSupply") - || p.propertyNames().contains("AsynchronousMachine"); - } - static void updateLoads(Network network, CgmesModel cgmes, Context context) { context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.LOAD.name())); - Map identifiablePropertyBag = new HashMap<>(); - addPropertyBags(cgmes.energyConsumers(), CgmesNames.ENERGY_CONSUMER, identifiablePropertyBag); - addPropertyBags(cgmes.energySources(), CgmesNames.ENERGY_SOURCE, identifiablePropertyBag); - addPropertyBags(cgmes.asynchronousMachines(), CgmesNames.ASYNCHRONOUS_MACHINE, identifiablePropertyBag); + Map equipmentIdPropertyBag = new HashMap<>(); + addPropertyBags(cgmes.energyConsumers(), CgmesNames.ENERGY_CONSUMER, equipmentIdPropertyBag); + addPropertyBags(cgmes.energySources(), CgmesNames.ENERGY_SOURCE, equipmentIdPropertyBag); + addPropertyBags(cgmes.asynchronousMachines(), CgmesNames.ASYNCHRONOUS_MACHINE, equipmentIdPropertyBag); - network.getLoads().forEach(load -> updateLoad(load, getPropertyBag(load.getId(), identifiablePropertyBag), context)); + network.getLoads().forEach(load -> updateLoad(load, getPropertyBag(load.getId(), equipmentIdPropertyBag), context)); context.popReportNode(); } private static void updateLoad(Load load, PropertyBag cgmesData, Context context) { if (!load.isFictitious()) { // Loads from SvInjections are fictitious String originalClass = load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS); - PropertyBag cgmesTerminal = getPropertyBagOfCgmesTerminal(load, context); switch (originalClass) { - case CgmesNames.ENERGY_SOURCE -> new EnergySourceConversion(cgmesData, cgmesTerminal, load, context).update(); - case CgmesNames.ASYNCHRONOUS_MACHINE -> - new AsynchronousMachineConversion(cgmesData, cgmesTerminal, load, context).update(); - case CgmesNames.CONFORM_LOAD, CgmesNames.NONCONFORM_LOAD, CgmesNames.STATION_SUPPLY, CgmesNames.ENERGY_CONSUMER -> - new EnergyConsumerConversion(cgmesData, cgmesTerminal, load, context).update(); + case CgmesNames.ENERGY_SOURCE -> EnergySourceConversion.update(cgmesData, load, context); + case CgmesNames.ASYNCHRONOUS_MACHINE -> AsynchronousMachineConversion.update(cgmesData, load, context); + case CgmesNames.CONFORM_LOAD, CgmesNames.NONCONFORM_LOAD, CgmesNames.STATION_SUPPLY, CgmesNames.ENERGY_CONSUMER -> EnergyConsumerConversion.update(cgmesData, load, context); default -> throw new ConversionException("Unexpected originalClass " + originalClass + " for Load: " + load.getId()); } } } - private static void addPropertyBags(PropertyBags propertyBags, String idTag, Map identifiablePropertyBag) { - propertyBags.forEach(propertyBag -> identifiablePropertyBag.put(propertyBag.getId(idTag), propertyBag)); - } - - private static PropertyBag getPropertyBag(String identifiableId, Map identifiablePropertyBag) { - return identifiablePropertyBag.containsKey(identifiableId) ? identifiablePropertyBag.get(identifiableId) : emptyPropertyBag(); - } - - private static PropertyBag getPropertyBagOfCgmesTerminal(Connectable connectable, Context context) { - Optional cgmesTerminalId = connectable.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL1); - if (cgmesTerminalId.isPresent()) { - return getPropertyBagOfCgmesTerminal(cgmesTerminalId.get(), context); - } else { - return emptyPropertyBag(); - } + private static void addPropertyBags(PropertyBags propertyBags, String idTag, Map equipmentIdPropertyBag) { + propertyBags.forEach(propertyBag -> equipmentIdPropertyBag.put(propertyBag.getId(idTag), propertyBag)); } - private static PropertyBag getPropertyBagOfCgmesTerminal(String cgmesTerminalId, Context context) { - return context.cgmesTerminal(cgmesTerminalId) != null ? context.cgmesTerminal(cgmesTerminalId) : emptyPropertyBag(); + private static PropertyBag getPropertyBag(String identifiableId, Map equipmentIdPropertyBag) { + return equipmentIdPropertyBag.containsKey(identifiableId) ? equipmentIdPropertyBag.get(identifiableId) : emptyPropertyBag(); } private static PropertyBag emptyPropertyBag() { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index df48182b883..391c6bb4117 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -21,12 +21,12 @@ import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.OptionalDouble; import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.EMPTY; -import static com.powsybl.cgmes.conversion.Update.isConvertSeparatedFromUpdate; /** * @author Luma Zamarreño {@literal } @@ -42,19 +42,11 @@ protected AbstractConductingEquipmentConversion( PropertyBag p, Context context) { super(type, p, context); - if (isConvertSeparatedFromUpdate(p)) { - numTerminals = 1; - terminals = new TerminalData[]{null, null, null}; - terminals[0] = new TerminalData(CgmesNames.TERMINAL, p, context); - steadyStatePowerFlow = null; - updatedTerminals = null; - } else { - numTerminals = 1; - terminals = new TerminalData[]{null, null, null}; - terminals[0] = new TerminalData(CgmesNames.TERMINAL, p, context); - steadyStatePowerFlow = new PowerFlow(p, "p", "q"); - updatedTerminals = null; - } + numTerminals = 1; + terminals = new TerminalData[]{null, null, null}; + terminals[0] = new TerminalData(CgmesNames.TERMINAL, p, context); + steadyStatePowerFlow = new PowerFlow(p, "p", "q"); + } protected AbstractConductingEquipmentConversion( @@ -74,7 +66,6 @@ protected AbstractConductingEquipmentConversion( terminals[k0] = new TerminalData(CgmesNames.TERMINAL + k, p, context); } steadyStatePowerFlow = PowerFlow.UNDEFINED; - updatedTerminals = null; } protected AbstractConductingEquipmentConversion( @@ -94,20 +85,6 @@ protected AbstractConductingEquipmentConversion( terminals[k0] = new TerminalData(CgmesNames.TERMINAL, ps.get(k0), context); } steadyStatePowerFlow = PowerFlow.UNDEFINED; - updatedTerminals = null; - } - - protected AbstractConductingEquipmentConversion( - String type, - PropertyBag p, - PropertyBag cgmesTerminal, - Context context) { - super(type, p, context); - numTerminals = 1; - terminals = null; - steadyStatePowerFlow = new PowerFlow(p, "p", "q"); - updatedTerminals = new UpdatedTerminalData[]{null, null, null}; - updatedTerminals[0] = new UpdatedTerminalData(cgmesTerminal); } public String findPairingKey(String boundaryNode) { @@ -480,10 +457,6 @@ private PowerFlow stateVariablesPowerFlow() { return terminals[0].t.flow(); } - private PowerFlow updatedStateVariablesPowerFlow() { - return new PowerFlow(updatedTerminals[0].cgmesTerminal, "p", "q"); - } - public PowerFlow stateVariablesPowerFlow(int n) { return terminals[n - 1].t.flow(); } @@ -492,10 +465,6 @@ private PowerFlow steadyStateHypothesisPowerFlow() { return steadyStatePowerFlow; } - private PowerFlow updatedSteadyStateHypothesisPowerFlow() { - return steadyStatePowerFlow; - } - PowerFlow powerFlow() { if (steadyStateHypothesisPowerFlow().defined()) { return steadyStateHypothesisPowerFlow(); @@ -506,16 +475,6 @@ PowerFlow powerFlow() { return PowerFlow.UNDEFINED; } - PowerFlow updatedPowerFlow() { - if (updatedSteadyStateHypothesisPowerFlow().defined()) { - return updatedSteadyStateHypothesisPowerFlow(); - } - if (updatedStateVariablesPowerFlow().defined()) { - return updatedStateVariablesPowerFlow(); - } - return PowerFlow.UNDEFINED; - } - PowerFlow powerFlowSV() { if (stateVariablesPowerFlow().defined()) { return stateVariablesPowerFlow(); @@ -554,12 +513,10 @@ protected void convertedTerminalsWithOnlyEq(Terminal... ts) { } } - protected void updateTerminals(Context context, Terminal... ts) { - if (ts.length != numTerminals) { - throw new IllegalArgumentException(); - } + protected static void updateTerminals(Connectable connectable, Context context, Terminal... ts) { + PropertyBags cgmesTerminals = getPropertyBagsOfTerminals(connectable, context, ts.length); for (int k = 0; k < ts.length; k++) { - updateTerminal(updatedTerminals[k].cgmesTerminal, ts[k], context); + updateTerminal(cgmesTerminals.get(k), ts[k], context); } } @@ -595,6 +552,33 @@ private static boolean setPQAllowed(Terminal t) { return t.getConnectable().getType() != IdentifiableType.BUSBAR_SECTION; } + private static PropertyBag getPropertyBagsOfTerminal(Connectable connectable, Context context) { + return getPropertyBagsOfTerminals(connectable, context, 1).get(0); + } + + private static PropertyBags getPropertyBagsOfTerminals(Connectable connectable, Context context, int numTerminals) { + PropertyBags propertyBags = new PropertyBags(); + getTerminalTags(numTerminals).forEach(terminalTag -> connectable.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + terminalTag) + .ifPresent(cgmesTerminalId -> propertyBags.add(getPropertyBagOfTerminal(cgmesTerminalId, context)))); + return propertyBags; + } + + private static List getTerminalTags(int numTerminals) { + return switch (numTerminals) { + case 1 -> List.of(CgmesNames.TERMINAL1); + case 2 -> List.of(CgmesNames.TERMINAL1, CgmesNames.TERMINAL2); + case 3 -> List.of(CgmesNames.TERMINAL1, CgmesNames.TERMINAL2, CgmesNames.TERMINAL3); + default -> throw new PowsyblException("unexpected number of terminals " + numTerminals); + }; + } + + // If the propertyBag is not received, an empty one is returned. + private static PropertyBag getPropertyBagOfTerminal(String cgmesTerminalId, Context context) { + return context.cgmesTerminal(cgmesTerminalId) != null + ? context.cgmesTerminal(cgmesTerminalId) + : new PropertyBag(Collections.emptyList(), false); + } + private final int numTerminals; static class TerminalData { @@ -639,14 +623,7 @@ private static String findCgmesVoltageLevelIdForContainer(String nodeId, Context } } - static class UpdatedTerminalData { - private final PropertyBag cgmesTerminal; - - UpdatedTerminalData(PropertyBag cgmesTerminal) { - this.cgmesTerminal = cgmesTerminal; - } - } - // Connections + // Connect public void connect(InjectionAdder adder) { if (context.nodeBreaker()) { @@ -798,16 +775,26 @@ protected double q0() { return powerFlow().defined() ? powerFlow().q() : 0.0; } - protected OptionalDouble updatedP0() { - return updatedPowerFlow().defined() ? OptionalDouble.of(updatedPowerFlow().p()) : OptionalDouble.empty(); + protected static OptionalDouble updatedP0(Connectable connectable, PropertyBag cgmesData, Context context) { + PowerFlow powerFlow = getPowerFlow(cgmesData, getPropertyBagsOfTerminal(connectable, context)); + return powerFlow.defined() ? OptionalDouble.of(powerFlow.p()) : OptionalDouble.empty(); } - protected OptionalDouble updatedQ0() { - return updatedPowerFlow().defined() ? OptionalDouble.of(updatedPowerFlow().q()) : OptionalDouble.empty(); + protected static OptionalDouble updatedQ0(Connectable connectable, PropertyBag cgmesData, Context context) { + PowerFlow powerFlow = getPowerFlow(cgmesData, getPropertyBagsOfTerminal(connectable, context)); + return powerFlow.defined() ? OptionalDouble.of(powerFlow.q()) : OptionalDouble.empty(); } - protected static Conversion.Config.DefaultValue getDefaultValueSelector(List validDefaultValues, Context context) { - return context.config().updateDefaultValuesPriority().stream().filter(validDefaultValues::contains).findFirst().orElse(EMPTY); + private static PowerFlow getPowerFlow(PropertyBag cgmesData, PropertyBag cgmesTerminal) { + PowerFlow steadyStateHypothesisPowerFlow = new PowerFlow(cgmesData, "p", "q"); + if (steadyStateHypothesisPowerFlow.defined()) { + return steadyStateHypothesisPowerFlow; + } + PowerFlow stateVariablesPowerFlow = new PowerFlow(cgmesTerminal, "p", "q"); + if (stateVariablesPowerFlow.defined()) { + return stateVariablesPowerFlow; + } + return PowerFlow.UNDEFINED; } protected static double defaultValue(double eq, double previous, double defaultValue, double emptyValue, Conversion.Config.DefaultValue defaultValueSelector) { @@ -819,7 +806,10 @@ protected static double defaultValue(double eq, double previous, double defaultV }; } + protected static Conversion.Config.DefaultValue getDefaultValueSelector(List validDefaultValues, Context context) { + return context.config().updateDefaultValuesPriority().stream().filter(validDefaultValues::contains).findFirst().orElse(EMPTY); + } + private final TerminalData[] terminals; private final PowerFlow steadyStatePowerFlow; - private final UpdatedTerminalData[] updatedTerminals; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java index 55c3ae881b7..0b6945c1acf 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractObjectConversion.java @@ -47,10 +47,6 @@ public void convertInsideBoundary() { public abstract void convert(); - public void update() { - throw new ConversionException("Missing implementation: update for " + type); - } - public abstract String what(); protected abstract String complete(String what); diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java index 8230c1c8d39..bb306488689 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java @@ -17,7 +17,6 @@ import com.powsybl.triplestore.api.PropertyBag; import java.util.List; -import java.util.Objects; import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; @@ -28,12 +27,6 @@ public class AsynchronousMachineConversion extends AbstractConductingEquipmentCo public AsynchronousMachineConversion(PropertyBag asm, Context context) { super(CgmesNames.ASYNCHRONOUS_MACHINE, asm, context); - this.load = null; - } - - public AsynchronousMachineConversion(PropertyBag es, PropertyBag cgmesTerminal, Load load, Context context) { - super(CgmesNames.ASYNCHRONOUS_MACHINE, es, cgmesTerminal, context); - this.load = load; } @Override @@ -52,23 +45,20 @@ public void convert() { addSpecificProperties(newLoad); } - @Override - public void update() { - Objects.requireNonNull(load); - updateTerminals(context, load.getTerminal()); - load.setP0(updatedP0().orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))) - .setQ0(updatedQ0().orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))); - } - private static void addSpecificProperties(Load newLoad) { newLoad.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ASYNCHRONOUS_MACHINE); } + public static void update(PropertyBag cgmesData, Load load, Context context) { + updateTerminals(load, context, load.getTerminal()); + + load.setP0(updatedP0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))); + load.setQ0(updatedQ0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))); + } + private static Conversion.Config.DefaultValue gettDefaultValueSelector(Context context) { return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); } - - private final Load load; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index 8f50b7fc259..92c6ae62437 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -17,7 +17,6 @@ import com.powsybl.triplestore.api.PropertyBag; import java.util.List; -import java.util.Objects; import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; @@ -32,13 +31,6 @@ public class EnergyConsumerConversion extends AbstractConductingEquipmentConvers public EnergyConsumerConversion(PropertyBag ec, Context context) { super(CgmesNames.ENERGY_CONSUMER, ec, context); loadKind = ec.getLocal("type"); - this.load = null; - } - - public EnergyConsumerConversion(PropertyBag es, PropertyBag cgmesTerminal, Load load, Context context) { - super(CgmesNames.ENERGY_CONSUMER, es, cgmesTerminal, context); - this.loadKind = null; - this.load = load; } @Override @@ -149,24 +141,23 @@ private static void setLoadDetail(String type, Load newLoad, double pFixed, doub // else: EnergyConsumer - undefined } - @Override - public void update() { - Objects.requireNonNull(load); - updateTerminals(context, load.getTerminal()); + public static void update(PropertyBag cgmesData, Load load, Context context) { + updateTerminals(load, context, load.getTerminal()); double pFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + P_FIXED)); double qFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + Q_FIXED)); - load.setP0(updatedP0().orElse(defaultValue(pFixed, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))) - .setQ0(updatedQ0().orElse(defaultValue(qFixed, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); - updateLoadDetail(load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS), pFixed, qFixed); + load.setP0(updatedP0(load, cgmesData, context).orElse(defaultValue(pFixed, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); + load.setQ0(updatedQ0(load, cgmesData, context).orElse(defaultValue(qFixed, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); + + updateLoadDetail(load, load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS), pFixed, qFixed); } private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { return getDefaultValueSelector(List.of(EQ, PREVIOUS, DEFAULT, EMPTY), context); } - private void updateLoadDetail(String type, double pFixed, double qFixed) { + private static void updateLoadDetail(Load load, String type, double pFixed, double qFixed) { if (type == null) { return; } @@ -184,5 +175,4 @@ private void updateLoadDetail(String type, double pFixed, double qFixed) { } private final String loadKind; - private final Load load; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java index 5a0bea33127..f169ee2c4a2 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java @@ -15,7 +15,6 @@ import com.powsybl.triplestore.api.PropertyBag; import java.util.List; -import java.util.Objects; import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; @@ -25,12 +24,6 @@ public class EnergySourceConversion extends AbstractConductingEquipmentConversion { public EnergySourceConversion(PropertyBag es, Context context) { super(CgmesNames.ENERGY_SOURCE, es, context); - this.load = null; - } - - public EnergySourceConversion(PropertyBag es, PropertyBag cgmesTerminal, Load load, Context context) { - super(CgmesNames.ENERGY_SOURCE, es, cgmesTerminal, context); - this.load = load; } @Override @@ -52,17 +45,14 @@ private static void addSpecificProperties(Load newLoad) { newLoad.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ENERGY_SOURCE); } - @Override - public void update() { - Objects.requireNonNull(load); - updateTerminals(context, load.getTerminal()); - load.setP0(updatedP0().orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))) - .setQ0(updatedQ0().orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); + public static void update(PropertyBag cgmesData, Load load, Context context) { + updateTerminals(load, context, load.getTerminal()); + + load.setP0(updatedP0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); + load.setQ0(updatedQ0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); } private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); } - - private final Load load; } From c9075ca0385442112497678d87623118f5becd4f Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 14 Nov 2024 10:36:34 +0100 Subject: [PATCH 28/54] Update comment Signed-off-by: marquesja1 --- .../elements/AbstractConductingEquipmentConversion.java | 1 - 1 file changed, 1 deletion(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index 49e97d4e0f6..4079c5ea69d 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -73,7 +73,6 @@ protected AbstractConductingEquipmentConversion( super(type, ps, context); // Information about each terminal is in each separate property bags // It is assumed the property bags are already sorted - // Same code for property bags where convert has been separated from update this.numTerminals = ps.size(); terminals = new TerminalData[]{null, null, null}; if (numTerminals > 3) { From 79e54ae3fa168c457a4209afa14d4729bb96b1f5 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 14 Nov 2024 16:15:09 +0100 Subject: [PATCH 29/54] Fix operational limits and pretty code Signed-off-by: marquesja1 --- .../powsybl/cgmes/conversion/Conversion.java | 4 +- .../com/powsybl/cgmes/conversion/Update.java | 9 +- ...AbstractConductingEquipmentConversion.java | 25 ++--- .../AsynchronousMachineConversion.java | 8 +- .../elements/EnergyConsumerConversion.java | 8 +- .../elements/EnergySourceConversion.java | 8 +- .../elements/OperationalLimitConversion.java | 104 +++++++++++------- .../AbstractTransformerConversion.java | 70 +++++++----- .../ThreeWindingsTransformerConversion.java | 18 +-- .../TwoWindingsTransformerConversion.java | 8 +- 10 files changed, 153 insertions(+), 109 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java index d2bb0a326f7..3f9af645d6d 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java @@ -38,7 +38,7 @@ import static com.powsybl.cgmes.conversion.Conversion.Config.StateProfile.SSH; import static com.powsybl.cgmes.conversion.Update.updateLoads; -import static com.powsybl.cgmes.conversion.Update.updateTwoAndThreeWindingsTransformers; +import static com.powsybl.cgmes.conversion.Update.updateTransformers; import static java.util.stream.Collectors.groupingBy; /** @@ -332,7 +332,7 @@ private void update(Network network, Context updateContext, ReportNode reportNod } updateLoads(network, cgmes, updateContext); - updateTwoAndThreeWindingsTransformers(network, updateContext); + updateTransformers(network, updateContext); completeVoltagesAndAngles(network); diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java index cd424fae906..ddd279ed313 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java @@ -47,16 +47,17 @@ private static void updateLoad(Load load, PropertyBag cgmesData, Context context String originalClass = load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS); switch (originalClass) { - case CgmesNames.ENERGY_SOURCE -> EnergySourceConversion.update(cgmesData, load, context); - case CgmesNames.ASYNCHRONOUS_MACHINE -> AsynchronousMachineConversion.update(cgmesData, load, context); - case CgmesNames.CONFORM_LOAD, CgmesNames.NONCONFORM_LOAD, CgmesNames.STATION_SUPPLY, CgmesNames.ENERGY_CONSUMER -> EnergyConsumerConversion.update(cgmesData, load, context); + case CgmesNames.ENERGY_SOURCE -> EnergySourceConversion.update(load, cgmesData, context); + case CgmesNames.ASYNCHRONOUS_MACHINE -> AsynchronousMachineConversion.update(load, cgmesData, context); + case CgmesNames.CONFORM_LOAD, CgmesNames.NONCONFORM_LOAD, CgmesNames.STATION_SUPPLY, CgmesNames.ENERGY_CONSUMER -> + EnergyConsumerConversion.update(load, cgmesData, context); default -> throw new ConversionException("Unexpected originalClass " + originalClass + " for Load: " + load.getId()); } } } - static void updateTwoAndThreeWindingsTransformers(Network network, Context context) { + static void updateTransformers(Network network, Context context) { context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.TWO_WINDINGS_TRANSFORMER.name())); network.getTwoWindingsTransformers().forEach(t2w -> TwoWindingsTransformerConversion.update(t2w, context)); context.popReportNode(); diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index 4079c5ea69d..181218d8359 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -24,7 +24,6 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.OptionalDouble; /** * @author Luma Zamarreño {@literal } @@ -512,7 +511,7 @@ protected void convertedTerminalsWithOnlyEq(Terminal... ts) { } protected static void updateTerminals(Connectable connectable, Context context, Terminal... ts) { - PropertyBags cgmesTerminals = getPropertyBagsOfTerminals(connectable, context, ts.length); + PropertyBags cgmesTerminals = getCgmesTerminals(connectable, context, ts.length); for (int k = 0; k < ts.length; k++) { updateTerminal(cgmesTerminals.get(k), ts[k], context); } @@ -550,14 +549,14 @@ private static boolean setPQAllowed(Terminal t) { return t.getConnectable().getType() != IdentifiableType.BUSBAR_SECTION; } - private static PropertyBag getPropertyBagsOfTerminal(Connectable connectable, Context context) { - return getPropertyBagsOfTerminals(connectable, context, 1).get(0); + private static PropertyBag getCgmesTerminal(Connectable connectable, Context context) { + return getCgmesTerminals(connectable, context, 1).get(0); } - private static PropertyBags getPropertyBagsOfTerminals(Connectable connectable, Context context, int numTerminals) { + private static PropertyBags getCgmesTerminals(Connectable connectable, Context context, int numTerminals) { PropertyBags propertyBags = new PropertyBags(); getTerminalTags(numTerminals).forEach(terminalTag -> connectable.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + terminalTag) - .ifPresent(cgmesTerminalId -> propertyBags.add(getPropertyBagOfTerminal(cgmesTerminalId, context)))); + .ifPresent(cgmesTerminalId -> propertyBags.add(getCgmesTerminal(cgmesTerminalId, context)))); return propertyBags; } @@ -571,7 +570,7 @@ private static List getTerminalTags(int numTerminals) { } // If the propertyBag is not received, an empty one is returned. - private static PropertyBag getPropertyBagOfTerminal(String cgmesTerminalId, Context context) { + private static PropertyBag getCgmesTerminal(String cgmesTerminalId, Context context) { return context.cgmesTerminal(cgmesTerminalId) != null ? context.cgmesTerminal(cgmesTerminalId) : new PropertyBag(Collections.emptyList(), false); @@ -793,17 +792,9 @@ protected double q0() { return powerFlow().defined() ? powerFlow().q() : 0.0; } - protected static OptionalDouble updatedP0(Connectable connectable, PropertyBag cgmesData, Context context) { - PowerFlow powerFlow = getPowerFlow(cgmesData, getPropertyBagsOfTerminal(connectable, context)); - return powerFlow.defined() ? OptionalDouble.of(powerFlow.p()) : OptionalDouble.empty(); - } - - protected static OptionalDouble updatedQ0(Connectable connectable, PropertyBag cgmesData, Context context) { - PowerFlow powerFlow = getPowerFlow(cgmesData, getPropertyBagsOfTerminal(connectable, context)); - return powerFlow.defined() ? OptionalDouble.of(powerFlow.q()) : OptionalDouble.empty(); - } + protected static PowerFlow updatedPowerFlow(Connectable connectable, PropertyBag cgmesData, Context context) { + PropertyBag cgmesTerminal = getCgmesTerminal(connectable, context); - private static PowerFlow getPowerFlow(PropertyBag cgmesData, PropertyBag cgmesTerminal) { PowerFlow steadyStateHypothesisPowerFlow = new PowerFlow(cgmesData, "p", "q"); if (steadyStateHypothesisPowerFlow.defined()) { return steadyStateHypothesisPowerFlow; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java index bb306488689..a476e60747f 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java @@ -11,6 +11,7 @@ import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.cgmes.model.PowerFlow; import com.powsybl.iidm.network.Load; import com.powsybl.iidm.network.LoadAdder; import com.powsybl.iidm.network.LoadType; @@ -49,11 +50,12 @@ private static void addSpecificProperties(Load newLoad) { newLoad.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ASYNCHRONOUS_MACHINE); } - public static void update(PropertyBag cgmesData, Load load, Context context) { + public static void update(Load load, PropertyBag cgmesData, Context context) { updateTerminals(load, context, load.getTerminal()); - load.setP0(updatedP0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))); - load.setQ0(updatedQ0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))); + PowerFlow updatedPowerFlow = updatedPowerFlow(load, cgmesData, context); + load.setP0(updatedPowerFlow.defined() ? updatedPowerFlow.p() : defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, gettDefaultValueSelector(context))); + load.setQ0(updatedPowerFlow.defined() ? updatedPowerFlow.q() : defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, gettDefaultValueSelector(context))); } private static Conversion.Config.DefaultValue gettDefaultValueSelector(Context context) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index 92c6ae62437..72c656963ff 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -11,6 +11,7 @@ import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.cgmes.model.PowerFlow; import com.powsybl.iidm.network.*; import com.powsybl.iidm.network.extensions.LoadDetail; import com.powsybl.iidm.network.extensions.LoadDetailAdder; @@ -141,14 +142,15 @@ private static void setLoadDetail(String type, Load newLoad, double pFixed, doub // else: EnergyConsumer - undefined } - public static void update(PropertyBag cgmesData, Load load, Context context) { + public static void update(Load load, PropertyBag cgmesData, Context context) { updateTerminals(load, context, load.getTerminal()); double pFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + P_FIXED)); double qFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + Q_FIXED)); - load.setP0(updatedP0(load, cgmesData, context).orElse(defaultValue(pFixed, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); - load.setQ0(updatedQ0(load, cgmesData, context).orElse(defaultValue(qFixed, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); + PowerFlow updatedPowerFlow = updatedPowerFlow(load, cgmesData, context); + load.setP0(updatedPowerFlow.defined() ? updatedPowerFlow.p() : defaultValue(pFixed, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context))); + load.setQ0(updatedPowerFlow.defined() ? updatedPowerFlow.q() : defaultValue(qFixed, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context))); updateLoadDetail(load, load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS), pFixed, qFixed); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java index f169ee2c4a2..6572a7ec779 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java @@ -11,6 +11,7 @@ import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.cgmes.model.PowerFlow; import com.powsybl.iidm.network.*; import com.powsybl.triplestore.api.PropertyBag; @@ -45,11 +46,12 @@ private static void addSpecificProperties(Load newLoad) { newLoad.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ENERGY_SOURCE); } - public static void update(PropertyBag cgmesData, Load load, Context context) { + public static void update(Load load, PropertyBag cgmesData, Context context) { updateTerminals(load, context, load.getTerminal()); - load.setP0(updatedP0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); - load.setQ0(updatedQ0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); + PowerFlow updatedPowerFlow = updatedPowerFlow(load, cgmesData, context); + load.setP0(updatedPowerFlow.defined() ? updatedPowerFlow.p() : defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context))); + load.setQ0(updatedPowerFlow.defined() ? updatedPowerFlow.q() : defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context))); } private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java index 4fc7b85fa6b..2a6e91208a2 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java @@ -311,23 +311,24 @@ private boolean addPatl(double value, LoadingLimitsAdder adder) { } private void convertPatl(double value) { + String operationalLimitSetId = p.getId(OPERATIONAL_LIMIT_SET_ID); String operationalLimitId = p.getId(CgmesNames.OPERATIONAL_LIMIT); if (loadingLimitsAdder != null) { boolean added = addPatl(value, loadingLimitsAdder); - addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "", value); + addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(added, new PR(operationalLimitSetId, limitSubclassType, ""), operationalLimitId, value); } else { if (loadingLimitsAdder1 != null) { boolean added = addPatl(value, loadingLimitsAdder1); - addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "1", value); + addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(added, new PR(operationalLimitSetId, limitSubclassType, "1"), operationalLimitId, value); } if (loadingLimitsAdder2 != null) { boolean added = addPatl(value, loadingLimitsAdder2); - addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "2", value); + addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(added, new PR(operationalLimitSetId, limitSubclassType, "2"), operationalLimitId, value); } if (loadingLimitsAdder3 != null) { boolean added = addPatl(value, loadingLimitsAdder3); - addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, "3", value); + addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(added, new PR(operationalLimitSetId, limitSubclassType, "3"), operationalLimitId, value); } } } @@ -379,10 +380,11 @@ private void convertTatl(double value) { // if there is no direction, the limit is considered as absoluteValue (cf. CGMES specification) if (direction == null || direction.endsWith("high") || direction.endsWith("absoluteValue")) { + String operationalLimitSetId = p.getId(OPERATIONAL_LIMIT_SET_ID); String operationalLimitId = p.getId(CgmesNames.OPERATIONAL_LIMIT); String name = Optional.ofNullable(p.getId("shortName")).orElse(p.getId("name")); - addTemporayLoadingLimits(name, value, acceptableDuration, operationalLimitId); + addTemporayLoadingLimits(name, value, acceptableDuration, operationalLimitSetId, operationalLimitId); } else if (direction.endsWith("low")) { context.invalid(TEMPORARY_LIMIT, () -> String.format("TATL %s is a low limit", id)); } else { @@ -390,50 +392,48 @@ private void convertTatl(double value) { } } - private void addTemporayLoadingLimits(String name, double value, int acceptableDuration, String operationalLimitId) { + private void addTemporayLoadingLimits(String name, double value, int acceptableDuration, String operationalLimitSetId, String operationalLimitId) { if (loadingLimitsAdder != null) { - addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder, operationalLimitId, ""); + addTatlAndTemporaryProperties(name, new PR(operationalLimitSetId, limitSubclassType, ""), value, acceptableDuration, loadingLimitsAdder, operationalLimitId); } else { if (loadingLimitsAdder1 != null) { - addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder1, operationalLimitId, "1"); + addTatlAndTemporaryProperties(name, new PR(operationalLimitSetId, limitSubclassType, "1"), value, acceptableDuration, loadingLimitsAdder1, operationalLimitId); } if (loadingLimitsAdder2 != null) { - addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder2, operationalLimitId, "2"); + addTatlAndTemporaryProperties(name, new PR(operationalLimitSetId, limitSubclassType, "2"), value, acceptableDuration, loadingLimitsAdder2, operationalLimitId); } if (loadingLimitsAdder3 != null) { - addTatlAndTemporaryProperties(name, value, acceptableDuration, loadingLimitsAdder3, operationalLimitId, "3"); + addTatlAndTemporaryProperties(name, new PR(operationalLimitSetId, limitSubclassType, "3"), value, acceptableDuration, loadingLimitsAdder3, operationalLimitId); } } } - private void addTatlAndTemporaryProperties(String name, double value, int acceptableDuration, LoadingLimitsAdder loadingLimitsAdder, String operationalLimitId, String end) { + private void addTatlAndTemporaryProperties(String name, PR propertyNameData, double value, int acceptableDuration, LoadingLimitsAdder loadingLimitsAdder, String operationalLimitId) { boolean added = addTatl(name, value, acceptableDuration, loadingLimitsAdder); - addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(added, operationalLimitId, end, acceptableDuration, value); + addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(added, propertyNameData.toTR(acceptableDuration), operationalLimitId, value); } - private void addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(boolean included, String operationalLimitId, String end, int duration, double value) { + private void addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(boolean included, TPR temporaryPropertyNameData, String operationalLimitId, double value) { if (included) { - addTemporaryOperationalLimitProperties(operationalLimitId, end, duration, value); + addTemporaryOperationalLimitProperties(temporaryPropertyNameData, operationalLimitId, value); } } - private void addTemporaryOperationalLimitProperties(String operationalLimitId, String end, int duration, double value) { - Objects.requireNonNull(limitSubclassType); + private void addTemporaryOperationalLimitProperties(TPR temporaryPropertyNameData, String operationalLimitId, double value) { Objects.requireNonNull(loadingLimitsIdentifiable); - loadingLimitsIdentifiable.setProperty(getPropertyName(end, limitSubclassType, duration), operationalLimitId); + loadingLimitsIdentifiable.setProperty(getPropertyName(temporaryPropertyNameData), operationalLimitId); loadingLimitsIdentifiable.setProperty(getPropertyName(operationalLimitId), String.valueOf(value)); } - private void addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(boolean included, String operationalLimitId, String end, double value) { + private void addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(boolean included, PR propertyNameData, String operationalLimitId, double value) { if (included) { - addPermanentOperationalLimitProperties(operationalLimitId, end, value); + addPermanentOperationalLimitProperties(propertyNameData, operationalLimitId, value); } } - private void addPermanentOperationalLimitProperties(String operationalLimitId, String end, double value) { - Objects.requireNonNull(limitSubclassType); + private void addPermanentOperationalLimitProperties(PR propertyNameData, String operationalLimitId, double value) { Objects.requireNonNull(loadingLimitsIdentifiable); - loadingLimitsIdentifiable.setProperty(getPropertyName(end, limitSubclassType), operationalLimitId); + loadingLimitsIdentifiable.setProperty(getPropertyName(propertyNameData), operationalLimitId); loadingLimitsIdentifiable.setProperty(getPropertyName(operationalLimitId), String.valueOf(value)); } @@ -467,28 +467,39 @@ private static String className(Identifiable o) { return s; } - public static void update(OperationalLimitsGroup operationalLimitsGroup, String end, Identifiable identifiable, Context context) { - operationalLimitsGroup.getActivePowerLimits().ifPresent(activePowerLimits -> updateLoadingLimits(activePowerLimits, end, CgmesNames.ACTIVE_POWER_LIMIT, identifiable, context)); - operationalLimitsGroup.getApparentPowerLimits().ifPresent(apparentPowerLimits -> updateLoadingLimits(apparentPowerLimits, end, CgmesNames.APPARENT_POWER_LIMIT, identifiable, context)); - operationalLimitsGroup.getCurrentLimits().ifPresent(currentLimits -> updateLoadingLimits(currentLimits, end, CgmesNames.CURRENT_LIMIT, identifiable, context)); + public static void update(Identifiable identifiable, OperationalLimitsGroup operationalLimitsGroup, TwoSides side, Context context) { + update(identifiable, operationalLimitsGroup, String.valueOf(side.getNum()), context); + } + + public static void update(Identifiable identifiable, OperationalLimitsGroup operationalLimitsGroup, ThreeSides side, Context context) { + update(identifiable, operationalLimitsGroup, String.valueOf(side.getNum()), context); + } + + private static void update(Identifiable identifiable, OperationalLimitsGroup operationalLimitsGroup, String end, Context context) { + operationalLimitsGroup.getActivePowerLimits().ifPresent(activePowerLimits + -> updateLoadingLimits(new PR(operationalLimitsGroup.getId(), CgmesNames.ACTIVE_POWER_LIMIT, end), activePowerLimits, identifiable, context)); + operationalLimitsGroup.getApparentPowerLimits().ifPresent(apparentPowerLimits + -> updateLoadingLimits(new PR(operationalLimitsGroup.getId(), CgmesNames.APPARENT_POWER_LIMIT, end), apparentPowerLimits, identifiable, context)); + operationalLimitsGroup.getCurrentLimits().ifPresent(currentLimits + -> updateLoadingLimits(new PR(operationalLimitsGroup.getId(), CgmesNames.CURRENT_LIMIT, end), currentLimits, identifiable, context)); } - private static void updateLoadingLimits(LoadingLimits loadingLimits, String end, String limitSubclass, Identifiable identifiable, Context context) { - loadingLimits.setPermanentLimit(getValue(end, limitSubclass, identifiable, loadingLimits.getPermanentLimit(), context)); + private static void updateLoadingLimits(PR propertyNameData, LoadingLimits loadingLimits, Identifiable identifiable, Context context) { + loadingLimits.setPermanentLimit(getValue(propertyNameData, identifiable, loadingLimits.getPermanentLimit(), context)); loadingLimits.getTemporaryLimits().forEach(temporaryLimit -> { int duration = temporaryLimit.getAcceptableDuration(); - loadingLimits.setTemporaryLimitValue(duration, getValue(end, limitSubclass, duration, identifiable, temporaryLimit.getValue(), context)); + loadingLimits.setTemporaryLimitValue(duration, getValue(propertyNameData.toTR(duration), identifiable, temporaryLimit.getValue(), context)); }); } - private static double getValue(String end, String limitSubclass, Identifiable identifiable, double previousValue, Context context) { - String operationalLimitId = getOperationalLimitId(getPropertyName(end, limitSubclass), identifiable); + private static double getValue(PR propertyNameData, Identifiable identifiable, double previousValue, Context context) { + String operationalLimitId = getOperationalLimitId(getPropertyName(propertyNameData), identifiable); return updatedValue(operationalLimitId, context) .orElse(defaultValue(getNormalValue(getPropertyName(operationalLimitId), identifiable), previousValue, getDefaultValue(context))); } - private static double getValue(String end, String limitSubclass, int duration, Identifiable identifiable, double previousValue, Context context) { - String operationalLimitId = getOperationalLimitId(getPropertyName(end, limitSubclass, duration), identifiable); + private static double getValue(TPR temporaryPropertyNameData, Identifiable identifiable, double previousValue, Context context) { + String operationalLimitId = getOperationalLimitId(getPropertyName(temporaryPropertyNameData), identifiable); return updatedValue(operationalLimitId, context) .orElse(defaultValue(getNormalValue(getPropertyName(operationalLimitId), identifiable), previousValue, getDefaultValue(context))); } @@ -509,12 +520,21 @@ private static double getNormalValue(String propertyName, Identifiable identi return Double.parseDouble(identifiable.getProperty(propertyName)); } - private static String getPropertyName(String end, String limitSubclass) { - return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT + "_" + end + "_" + limitSubclass + "_" + "patl"; + private static String getPropertyName(PR pr) { + return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT + "_" + + pr.operationalLimitSetId + "_" + + pr.end + "_" + + pr.limitSubclass + "_" + + "patl"; } - private static String getPropertyName(String end, String limitSubclass, int duration) { - return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT + "_" + end + "_" + limitSubclass + "_" + "tatl" + "_" + duration; + private static String getPropertyName(TPR tpr) { + return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT + "_" + + tpr.operationalLimitSetId + "_" + + tpr.end + "_" + + tpr.limitSubclass + "_" + + "tatl" + "_" + + tpr.duration; } private static String getPropertyName(String operationalLimitId) { @@ -532,6 +552,16 @@ private static Conversion.Config.DefaultValue getDefaultValue(Context context) { return getDefaultValueSelector(List.of(EQ, PREVIOUS), context); } + private record PR(String operationalLimitSetId, String limitSubclass, String end) { + + private TPR toTR(int duration) { + return new TPR(this.operationalLimitSetId, this.limitSubclass, this.end, duration); + } + } + + private record TPR(String operationalLimitSetId, String limitSubclass, String end, int duration) { + } + private final String terminalId; private final String equipmentId; private final String limitSubclassType; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java index c10f91f99f1..70c30ff3f29 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java @@ -165,20 +165,36 @@ protected static > void addCgmesReferences(C transforme } } - static > void updateRatioTapChanger(Connectable tw, RatioTapChanger rtc, String end, Context context, boolean isRegulatingAllowed) { - if (regulatingControlIsDefined(rtc.getRegulationTerminal())) { - String ratioTapChangerId = findTapChangerId(tw, Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.RATIO_TAP_CHANGER + end); + static > void updateRatioTapChanger(Connectable tw, RatioTapChanger rtc, Context context, boolean isRegulatingAllowed) { + updateRatioTapChanger(tw, rtc, "", context, isRegulatingAllowed); + } + + static > void updateRatioTapChanger(Connectable tw, RatioTapChanger rtc, ThreeSides side, Context context, boolean isRegulatingAllowed) { + updateRatioTapChanger(tw, rtc, String.valueOf(side.getNum()), context, isRegulatingAllowed); + } + + static > void updatePhaseTapChanger(Connectable tw, PhaseTapChanger ptc, Context context, boolean isRegulatingAllowed) { + updatePhaseTapChanger(tw, ptc, "", context, isRegulatingAllowed); + } - int tapPosition = findRatioTapChangerPropertyBag(ratioTapChangerId, context) - .map(propertyBag -> findTapPosition(tw, propertyBag, rtc, ratioTapChangerId, context)) - .orElseGet(() -> findDefaultTapPosition(tw, rtc, ratioTapChangerId, context)); - int validTapPosition = isValidTapPosition(rtc, tapPosition) ? tapPosition : findDefaultTapPosition(tw, rtc, ratioTapChangerId, context); - rtc.setTapPosition(validTapPosition); + static > void updatePhaseTapChanger(Connectable tw, PhaseTapChanger ptc, ThreeSides side, Context context, boolean isRegulatingAllowed) { + updatePhaseTapChanger(tw, ptc, String.valueOf(side.getNum()), context, isRegulatingAllowed); + } + + private static > void updateRatioTapChanger(Connectable tw, RatioTapChanger rtc, String end, Context context, boolean isRegulatingAllowed) { + String ratioTapChangerId = findTapChangerId(tw, Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.RATIO_TAP_CHANGER + end); + + int tapPosition = findCgmesRatioTapChanger(ratioTapChangerId, context) + .map(propertyBag -> findTapPosition(tw, propertyBag, rtc, ratioTapChangerId, context)) + .orElseGet(() -> findDefaultTapPosition(tw, rtc, ratioTapChangerId, context)); + int validTapPosition = isValidTapPosition(rtc, tapPosition) ? tapPosition : findDefaultTapPosition(tw, rtc, ratioTapChangerId, context); + rtc.setTapPosition(validTapPosition); - Optional regulatingControlPropertyBag = findRegulatingControlPropertyBag(tw, ratioTapChangerId, context); - double targetV = regulatingControlPropertyBag.map(AbstractTransformerConversion::findTargetV).orElseGet(() -> findDefaultTargetV(rtc, context)); - double targetDeadband = regulatingControlPropertyBag.map(AbstractTransformerConversion::findTargetDeadband).orElseGet(() -> findDefaultTargetDeadband(rtc, context)); - boolean regulatingOn = regulatingControlPropertyBag.map(propertyBag -> findRegulatingOn(propertyBag, rtc, context)).orElseGet(() -> findDefaultRegulatingOn(rtc, context)); + if (regulatingControlIsDefined(rtc.getRegulationTerminal())) { + Optional cgmesRegulatingControl = findCgmesRegulatingControl(tw, ratioTapChangerId, context); + double targetV = cgmesRegulatingControl.map(AbstractTransformerConversion::findTargetV).orElseGet(() -> findDefaultTargetV(rtc, context)); + double targetDeadband = cgmesRegulatingControl.map(AbstractTransformerConversion::findTargetDeadband).orElseGet(() -> findDefaultTargetDeadband(rtc, context)); + boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, rtc, context)).orElseGet(() -> findDefaultRegulatingOn(rtc, context)); // We always keep the targetValue // It targetValue is not valid, emit a warning and deactivate regulating control @@ -200,20 +216,20 @@ static > void updateRatioTapChanger(Connectable tw, } } - static > void updatePhaseTapChanger(Connectable tw, PhaseTapChanger ptc, String end, Context context, boolean isRegulatingAllowed) { - if (regulatingControlIsDefined(ptc.getRegulationTerminal())) { - String phaseTapChangerId = findTapChangerId(tw, Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.PHASE_TAP_CHANGER + end); + private static > void updatePhaseTapChanger(Connectable tw, PhaseTapChanger ptc, String end, Context context, boolean isRegulatingAllowed) { + String phaseTapChangerId = findTapChangerId(tw, Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.PHASE_TAP_CHANGER + end); - int tapPosition = findPhaseTapChangerPropertyBag(phaseTapChangerId, context) - .map(propertyBag -> findTapPosition(tw, propertyBag, ptc, phaseTapChangerId, context)) - .orElseGet(() -> findDefaultTapPosition(tw, ptc, phaseTapChangerId, context)); - int validTapPosition = isValidTapPosition(ptc, tapPosition) ? tapPosition : findDefaultTapPosition(tw, ptc, phaseTapChangerId, context); - ptc.setTapPosition(validTapPosition); + int tapPosition = findCgmesPhaseTapChanger(phaseTapChangerId, context) + .map(propertyBag -> findTapPosition(tw, propertyBag, ptc, phaseTapChangerId, context)) + .orElseGet(() -> findDefaultTapPosition(tw, ptc, phaseTapChangerId, context)); + int validTapPosition = isValidTapPosition(ptc, tapPosition) ? tapPosition : findDefaultTapPosition(tw, ptc, phaseTapChangerId, context); + ptc.setTapPosition(validTapPosition); - Optional regulatingControlPropertyBag = findRegulatingControlPropertyBag(tw, phaseTapChangerId, context); - double targetValue = regulatingControlPropertyBag.map(propertyBag -> findTargetValue(propertyBag, findTerminalSign(tw, end))).orElseGet(() -> findDefaultTargetValue(ptc, context)); - double targetDeadband = regulatingControlPropertyBag.map(AbstractTransformerConversion::findTargetDeadband).orElseGet(() -> findDefaultTargetDeadband(ptc, context)); - boolean regulatingOn = regulatingControlPropertyBag.map(propertyBag -> findRegulatingOn(propertyBag, ptc, context)).orElseGet(() -> findDefaultRegulatingOn(ptc, context)); + if (regulatingControlIsDefined(ptc.getRegulationTerminal())) { + Optional cgmesRegulatingControl = findCgmesRegulatingControl(tw, phaseTapChangerId, context); + double targetValue = cgmesRegulatingControl.map(propertyBag -> findTargetValue(propertyBag, findTerminalSign(tw, end))).orElseGet(() -> findDefaultTargetValue(ptc, context)); + double targetDeadband = cgmesRegulatingControl.map(AbstractTransformerConversion::findTargetDeadband).orElseGet(() -> findDefaultTargetDeadband(ptc, context)); + boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, ptc, context)).orElseGet(() -> findDefaultRegulatingOn(ptc, context)); boolean fixedRegulating = regulatingOn; if (regulatingOn && ptc.getRegulationMode() == PhaseTapChanger.RegulationMode.FIXED_TAP) { @@ -244,15 +260,15 @@ private static boolean regulatingControlIsDefined(Terminal regulatedTerminal) { return regulatedTerminal != null; } - private static Optional findRatioTapChangerPropertyBag(String ratioTapChangerId, Context context) { + private static Optional findCgmesRatioTapChanger(String ratioTapChangerId, Context context) { return ratioTapChangerId != null ? Optional.ofNullable(context.ratioTapChanger(ratioTapChangerId)) : Optional.empty(); } - private static Optional findPhaseTapChangerPropertyBag(String phaseTapChangerId, Context context) { + private static Optional findCgmesPhaseTapChanger(String phaseTapChangerId, Context context) { return phaseTapChangerId != null ? Optional.ofNullable(context.phaseTapChanger(phaseTapChangerId)) : Optional.empty(); } - private static > Optional findRegulatingControlPropertyBag(Connectable tw, String tapChangerId, Context context) { + private static > Optional findCgmesRegulatingControl(Connectable tw, String tapChangerId, Context context) { CgmesTapChangers cgmesTcs = tw.getExtension(CgmesTapChangers.class); if (cgmesTcs != null && tapChangerId != null) { CgmesTapChanger cgmesTc = cgmesTcs.getTapChanger(tapChangerId); diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java index 7279aa0469a..fbe51d1c2db 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/ThreeWindingsTransformerConversion.java @@ -213,22 +213,22 @@ public static void update(ThreeWindingsTransformer t3w, Context context) { updateTerminals(t3w, context, t3w.getLeg1().getTerminal(), t3w.getLeg2().getTerminal(), t3w.getLeg3().getTerminal()); boolean isAllowedToRegulatePtc1 = true; - t3w.getLeg1().getOptionalPhaseTapChanger().ifPresent(ptc -> updatePhaseTapChanger(t3w, ptc, "1", context, isAllowedToRegulatePtc1)); + t3w.getLeg1().getOptionalPhaseTapChanger().ifPresent(ptc -> updatePhaseTapChanger(t3w, ptc, ThreeSides.ONE, context, isAllowedToRegulatePtc1)); boolean isAllowedToRegulateRtc1 = checkOnlyOneEnabled(isAllowedToRegulatePtc1, t3w.getLeg1().getOptionalPhaseTapChanger().map(com.powsybl.iidm.network.TapChanger::isRegulating).orElse(false)); - t3w.getLeg1().getOptionalRatioTapChanger().ifPresent(rtc -> updateRatioTapChanger(t3w, rtc, "1", context, isAllowedToRegulateRtc1)); + t3w.getLeg1().getOptionalRatioTapChanger().ifPresent(rtc -> updateRatioTapChanger(t3w, rtc, ThreeSides.ONE, context, isAllowedToRegulateRtc1)); boolean isAllowedToRegulatePtc2 = checkOnlyOneEnabled(isAllowedToRegulateRtc1, t3w.getLeg1().getOptionalRatioTapChanger().map(com.powsybl.iidm.network.TapChanger::isRegulating).orElse(false)); - t3w.getLeg2().getOptionalPhaseTapChanger().ifPresent(ptc -> updatePhaseTapChanger(t3w, ptc, "2", context, isAllowedToRegulatePtc2)); + t3w.getLeg2().getOptionalPhaseTapChanger().ifPresent(ptc -> updatePhaseTapChanger(t3w, ptc, ThreeSides.TWO, context, isAllowedToRegulatePtc2)); boolean isAllowedToRegulateRtc2 = checkOnlyOneEnabled(isAllowedToRegulatePtc2, t3w.getLeg2().getOptionalPhaseTapChanger().map(com.powsybl.iidm.network.TapChanger::isRegulating).orElse(false)); - t3w.getLeg2().getOptionalRatioTapChanger().ifPresent(rtc -> updateRatioTapChanger(t3w, rtc, "2", context, isAllowedToRegulateRtc2)); + t3w.getLeg2().getOptionalRatioTapChanger().ifPresent(rtc -> updateRatioTapChanger(t3w, rtc, ThreeSides.TWO, context, isAllowedToRegulateRtc2)); boolean isAllowedToRegulatePtc3 = checkOnlyOneEnabled(isAllowedToRegulateRtc2, t3w.getLeg2().getOptionalRatioTapChanger().map(com.powsybl.iidm.network.TapChanger::isRegulating).orElse(false)); - t3w.getLeg3().getOptionalPhaseTapChanger().ifPresent(ptc -> updatePhaseTapChanger(t3w, ptc, "3", context, isAllowedToRegulatePtc3)); + t3w.getLeg3().getOptionalPhaseTapChanger().ifPresent(ptc -> updatePhaseTapChanger(t3w, ptc, ThreeSides.THREE, context, isAllowedToRegulatePtc3)); boolean isAllowedToRegulateRtc3 = checkOnlyOneEnabled(isAllowedToRegulatePtc3, t3w.getLeg3().getOptionalPhaseTapChanger().map(com.powsybl.iidm.network.TapChanger::isRegulating).orElse(false)); - t3w.getLeg3().getOptionalRatioTapChanger().ifPresent(rtc -> updateRatioTapChanger(t3w, rtc, "3", context, isAllowedToRegulateRtc3)); + t3w.getLeg3().getOptionalRatioTapChanger().ifPresent(rtc -> updateRatioTapChanger(t3w, rtc, ThreeSides.THREE, context, isAllowedToRegulateRtc3)); - t3w.getLeg1().getOperationalLimitsGroups().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(operationalLimitsGroup, "1", t3w, context)); - t3w.getLeg2().getOperationalLimitsGroups().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(operationalLimitsGroup, "2", t3w, context)); - t3w.getLeg3().getOperationalLimitsGroups().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(operationalLimitsGroup, "3", t3w, context)); + t3w.getLeg1().getOperationalLimitsGroups().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(t3w, operationalLimitsGroup, ThreeSides.ONE, context)); + t3w.getLeg2().getOperationalLimitsGroups().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(t3w, operationalLimitsGroup, ThreeSides.TWO, context)); + t3w.getLeg3().getOperationalLimitsGroups().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(t3w, operationalLimitsGroup, ThreeSides.THREE, context)); } } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java index 65ab4b49dd2..308b7dbe3a7 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/TwoWindingsTransformerConversion.java @@ -247,12 +247,12 @@ public static void update(TwoWindingsTransformer t2w, Context context) { updateTerminals(t2w, context, t2w.getTerminal1(), t2w.getTerminal2()); boolean isAllowedToRegulatePtc = true; - t2w.getOptionalPhaseTapChanger().ifPresent(ptc -> updatePhaseTapChanger(t2w, ptc, "", context, isAllowedToRegulatePtc)); + t2w.getOptionalPhaseTapChanger().ifPresent(ptc -> updatePhaseTapChanger(t2w, ptc, context, isAllowedToRegulatePtc)); boolean isAllowedToRegulateRtc = checkOnlyOneEnabled(isAllowedToRegulatePtc, t2w.getOptionalPhaseTapChanger().map(com.powsybl.iidm.network.TapChanger::isRegulating).orElse(false)); - t2w.getOptionalRatioTapChanger().ifPresent(rtc -> updateRatioTapChanger(t2w, rtc, "", context, isAllowedToRegulateRtc)); + t2w.getOptionalRatioTapChanger().ifPresent(rtc -> updateRatioTapChanger(t2w, rtc, context, isAllowedToRegulateRtc)); - t2w.getOperationalLimitsGroups1().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(operationalLimitsGroup, "1", t2w, context)); - t2w.getOperationalLimitsGroups2().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(operationalLimitsGroup, "2", t2w, context)); + t2w.getOperationalLimitsGroups1().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(t2w, operationalLimitsGroup, TwoSides.ONE, context)); + t2w.getOperationalLimitsGroups2().forEach(operationalLimitsGroup -> OperationalLimitConversion.update(t2w, operationalLimitsGroup, TwoSides.TWO, context)); } } From 42e4a14ac26ad42a49a37b5762353c3bb6b7bb4d Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 14 Nov 2024 16:41:48 +0100 Subject: [PATCH 30/54] pretty code Signed-off-by: marquesja1 --- .../com/powsybl/cgmes/conversion/Update.java | 7 ++--- ...AbstractConductingEquipmentConversion.java | 26 ++++++------------- .../AsynchronousMachineConversion.java | 8 +++--- .../elements/EnergyConsumerConversion.java | 8 +++--- .../elements/EnergySourceConversion.java | 8 +++--- 5 files changed, 27 insertions(+), 30 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java index b5c3d7c683b..db821bafd50 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java @@ -45,9 +45,10 @@ private static void updateLoad(Load load, PropertyBag cgmesData, Context context String originalClass = load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS); switch (originalClass) { - case CgmesNames.ENERGY_SOURCE -> EnergySourceConversion.update(cgmesData, load, context); - case CgmesNames.ASYNCHRONOUS_MACHINE -> AsynchronousMachineConversion.update(cgmesData, load, context); - case CgmesNames.CONFORM_LOAD, CgmesNames.NONCONFORM_LOAD, CgmesNames.STATION_SUPPLY, CgmesNames.ENERGY_CONSUMER -> EnergyConsumerConversion.update(cgmesData, load, context); + case CgmesNames.ENERGY_SOURCE -> EnergySourceConversion.update(load, cgmesData, context); + case CgmesNames.ASYNCHRONOUS_MACHINE -> AsynchronousMachineConversion.update(load, cgmesData, context); + case CgmesNames.CONFORM_LOAD, CgmesNames.NONCONFORM_LOAD, CgmesNames.STATION_SUPPLY, CgmesNames.ENERGY_CONSUMER -> + EnergyConsumerConversion.update(load, cgmesData, context); default -> throw new ConversionException("Unexpected originalClass " + originalClass + " for Load: " + load.getId()); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index 391c6bb4117..258c9319514 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -24,8 +24,6 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.OptionalDouble; - import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.EMPTY; /** @@ -514,7 +512,7 @@ protected void convertedTerminalsWithOnlyEq(Terminal... ts) { } protected static void updateTerminals(Connectable connectable, Context context, Terminal... ts) { - PropertyBags cgmesTerminals = getPropertyBagsOfTerminals(connectable, context, ts.length); + PropertyBags cgmesTerminals = getCgmesTerminals(connectable, context, ts.length); for (int k = 0; k < ts.length; k++) { updateTerminal(cgmesTerminals.get(k), ts[k], context); } @@ -552,14 +550,14 @@ private static boolean setPQAllowed(Terminal t) { return t.getConnectable().getType() != IdentifiableType.BUSBAR_SECTION; } - private static PropertyBag getPropertyBagsOfTerminal(Connectable connectable, Context context) { - return getPropertyBagsOfTerminals(connectable, context, 1).get(0); + private static PropertyBag getCgmesTerminal(Connectable connectable, Context context) { + return getCgmesTerminals(connectable, context, 1).get(0); } - private static PropertyBags getPropertyBagsOfTerminals(Connectable connectable, Context context, int numTerminals) { + private static PropertyBags getCgmesTerminals(Connectable connectable, Context context, int numTerminals) { PropertyBags propertyBags = new PropertyBags(); getTerminalTags(numTerminals).forEach(terminalTag -> connectable.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + terminalTag) - .ifPresent(cgmesTerminalId -> propertyBags.add(getPropertyBagOfTerminal(cgmesTerminalId, context)))); + .ifPresent(cgmesTerminalId -> propertyBags.add(getCgmesTerminal(cgmesTerminalId, context)))); return propertyBags; } @@ -573,7 +571,7 @@ private static List getTerminalTags(int numTerminals) { } // If the propertyBag is not received, an empty one is returned. - private static PropertyBag getPropertyBagOfTerminal(String cgmesTerminalId, Context context) { + private static PropertyBag getCgmesTerminal(String cgmesTerminalId, Context context) { return context.cgmesTerminal(cgmesTerminalId) != null ? context.cgmesTerminal(cgmesTerminalId) : new PropertyBag(Collections.emptyList(), false); @@ -775,17 +773,9 @@ protected double q0() { return powerFlow().defined() ? powerFlow().q() : 0.0; } - protected static OptionalDouble updatedP0(Connectable connectable, PropertyBag cgmesData, Context context) { - PowerFlow powerFlow = getPowerFlow(cgmesData, getPropertyBagsOfTerminal(connectable, context)); - return powerFlow.defined() ? OptionalDouble.of(powerFlow.p()) : OptionalDouble.empty(); - } - - protected static OptionalDouble updatedQ0(Connectable connectable, PropertyBag cgmesData, Context context) { - PowerFlow powerFlow = getPowerFlow(cgmesData, getPropertyBagsOfTerminal(connectable, context)); - return powerFlow.defined() ? OptionalDouble.of(powerFlow.q()) : OptionalDouble.empty(); - } + protected static PowerFlow updatedPowerFlow(Connectable connectable, PropertyBag cgmesData, Context context) { + PropertyBag cgmesTerminal = getCgmesTerminal(connectable, context); - private static PowerFlow getPowerFlow(PropertyBag cgmesData, PropertyBag cgmesTerminal) { PowerFlow steadyStateHypothesisPowerFlow = new PowerFlow(cgmesData, "p", "q"); if (steadyStateHypothesisPowerFlow.defined()) { return steadyStateHypothesisPowerFlow; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java index bb306488689..a476e60747f 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java @@ -11,6 +11,7 @@ import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.cgmes.model.PowerFlow; import com.powsybl.iidm.network.Load; import com.powsybl.iidm.network.LoadAdder; import com.powsybl.iidm.network.LoadType; @@ -49,11 +50,12 @@ private static void addSpecificProperties(Load newLoad) { newLoad.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ASYNCHRONOUS_MACHINE); } - public static void update(PropertyBag cgmesData, Load load, Context context) { + public static void update(Load load, PropertyBag cgmesData, Context context) { updateTerminals(load, context, load.getTerminal()); - load.setP0(updatedP0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))); - load.setQ0(updatedQ0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, gettDefaultValueSelector(context)))); + PowerFlow updatedPowerFlow = updatedPowerFlow(load, cgmesData, context); + load.setP0(updatedPowerFlow.defined() ? updatedPowerFlow.p() : defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, gettDefaultValueSelector(context))); + load.setQ0(updatedPowerFlow.defined() ? updatedPowerFlow.q() : defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, gettDefaultValueSelector(context))); } private static Conversion.Config.DefaultValue gettDefaultValueSelector(Context context) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index 92c6ae62437..72c656963ff 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -11,6 +11,7 @@ import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.cgmes.model.PowerFlow; import com.powsybl.iidm.network.*; import com.powsybl.iidm.network.extensions.LoadDetail; import com.powsybl.iidm.network.extensions.LoadDetailAdder; @@ -141,14 +142,15 @@ private static void setLoadDetail(String type, Load newLoad, double pFixed, doub // else: EnergyConsumer - undefined } - public static void update(PropertyBag cgmesData, Load load, Context context) { + public static void update(Load load, PropertyBag cgmesData, Context context) { updateTerminals(load, context, load.getTerminal()); double pFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + P_FIXED)); double qFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + Q_FIXED)); - load.setP0(updatedP0(load, cgmesData, context).orElse(defaultValue(pFixed, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); - load.setQ0(updatedQ0(load, cgmesData, context).orElse(defaultValue(qFixed, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); + PowerFlow updatedPowerFlow = updatedPowerFlow(load, cgmesData, context); + load.setP0(updatedPowerFlow.defined() ? updatedPowerFlow.p() : defaultValue(pFixed, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context))); + load.setQ0(updatedPowerFlow.defined() ? updatedPowerFlow.q() : defaultValue(qFixed, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context))); updateLoadDetail(load, load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS), pFixed, qFixed); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java index f169ee2c4a2..6572a7ec779 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java @@ -11,6 +11,7 @@ import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.cgmes.model.PowerFlow; import com.powsybl.iidm.network.*; import com.powsybl.triplestore.api.PropertyBag; @@ -45,11 +46,12 @@ private static void addSpecificProperties(Load newLoad) { newLoad.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.ENERGY_SOURCE); } - public static void update(PropertyBag cgmesData, Load load, Context context) { + public static void update(Load load, PropertyBag cgmesData, Context context) { updateTerminals(load, context, load.getTerminal()); - load.setP0(updatedP0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); - load.setQ0(updatedQ0(load, cgmesData, context).orElse(defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context)))); + PowerFlow updatedPowerFlow = updatedPowerFlow(load, cgmesData, context); + load.setP0(updatedPowerFlow.defined() ? updatedPowerFlow.p() : defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context))); + load.setQ0(updatedPowerFlow.defined() ? updatedPowerFlow.q() : defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context))); } private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { From cfbcdde19e1e7f11a9b62de2e0a9680e6c4cc541 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 11 Dec 2024 15:08:56 +0100 Subject: [PATCH 31/54] unitary tests Signed-off-by: marquesja1 --- .../powsybl/cgmes/conversion/CgmesImport.java | 14 +++ .../cgmes/conversion/test/ConversionUtil.java | 7 ++ .../cgmes/conversion/test/LoadUpdateTest.java | 112 ++++++++++++++++++ .../test/resources/update/load/load_EQ.xml | 93 +++++++++++++++ .../test/resources/update/load/load_SSH.xml | 35 ++++++ .../test/resources/update/load/load_SSH_1.xml | 35 ++++++ 6 files changed, 296 insertions(+) create mode 100644 cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH.xml create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH_1.xml diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java index d4cfb94cf0e..f118fbd4d27 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java @@ -176,6 +176,20 @@ private Network importData1(ReadOnlyDataSource ds, NetworkFactory networkFactory return new Conversion(cgmes, config(p), activatedPreProcessors(p), activatedPostProcessors(p), networkFactory).convert(conversionReportNode); } + public void updateData(Network network, ReadOnlyDataSource ds, Properties p, ReportNode reportNode) { + TripleStoreOptions tripleStoreOptions = new TripleStoreOptions(); + tripleStoreOptions.setQueryCatalog("-update"); + ReadOnlyDataSource alternativeDataSourceForBoundary = null; + CgmesModel cgmes = CgmesModelFactory.create( + ds, + alternativeDataSourceForBoundary, + TripleStoreFactory.DEFAULT_IMPLEMENTATION, + reportNode, + tripleStoreOptions); + Conversion conversion = new Conversion(cgmes, config(p)); + conversion.update(network, reportNode); + } + static class FilteredReadOnlyDataSource implements ReadOnlyDataSource { private final ReadOnlyDataSource ds; private final Predicate filter; diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java index 449e7f76f20..6feea04ca8e 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java @@ -8,6 +8,7 @@ package com.powsybl.cgmes.conversion.test; import com.powsybl.cgmes.conversion.CgmesExport; +import com.powsybl.cgmes.conversion.CgmesImport; import com.powsybl.cgmes.conversion.CgmesImportPostProcessor; import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.model.CgmesModel; @@ -16,6 +17,7 @@ import com.powsybl.commons.datasource.ReadOnlyDataSource; import com.powsybl.commons.datasource.ResourceDataSource; import com.powsybl.commons.datasource.ResourceSet; +import com.powsybl.commons.report.ReportNode; import com.powsybl.iidm.network.Network; import com.powsybl.triplestore.api.TripleStoreFactory; @@ -98,6 +100,11 @@ public static Network readCgmesResources(Properties properties, String dir, Stri return Network.read(ds, properties); } + public static void readCgmesResources(Network network, String dir, String... files) { + ReadOnlyDataSource ds = new ResourceDataSource("CGMES input file(s)", new ResourceSet(dir, files)); + new CgmesImport().updateData(network, ds, new Properties(), ReportNode.NO_OP); + } + public static String writeCgmesProfile(Network network, String profile, Path outDir) throws IOException { return writeCgmesProfile(network, profile, outDir, new Properties()); } diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java new file mode 100644 index 00000000000..4dfcec64ea2 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.cgmes.conversion.test; + +import com.powsybl.iidm.network.Load; +import com.powsybl.iidm.network.Network; +import org.junit.jupiter.api.Test; + +import static com.powsybl.cgmes.conversion.test.ConversionUtil.readCgmesResources; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Luma Zamarreño {@literal } + * @author José Antonio Marqués {@literal } + */ +class LoadUpdateTest { + + private static final String DIR = "/update/load/"; + + @Test + void importEqTest() { + Network network = readCgmesResources(DIR, "load_EQ.xml"); + assertEquals(3, network.getLoadCount()); + + Load loadEnergyConsumer = network.getLoad("EnergyConsumer"); + assertTrue(checkNaNLoad(loadEnergyConsumer)); + + Load loadEnergySource = network.getLoad("EnergySource"); + assertTrue(checkNaNLoad(loadEnergySource)); + + Load loadAsynchronousMachine = network.getLoad("AsynchronousMachine"); + assertTrue(checkNaNLoad(loadAsynchronousMachine)); + } + + @Test + void importEqAndSshTogetherTest() { + Network network = readCgmesResources(DIR, "load_EQ.xml", "load_SSH.xml"); + assertEquals(3, network.getLoadCount()); + + Load loadEnergyConsumer = network.getLoad("EnergyConsumer"); + assertTrue(checkLoad(loadEnergyConsumer, 10.0, 5.0)); + + Load loadEnergySource = network.getLoad("EnergySource"); + assertTrue(checkLoad(loadEnergySource, -200.0, -90.0)); + + Load loadAsynchronousMachine = network.getLoad("AsynchronousMachine"); + assertTrue(checkLoad(loadAsynchronousMachine, 200.0, 50.0)); + } + + @Test + void importEAndSshSeparatelyTest() { + Network network = readCgmesResources(DIR, "load_EQ.xml"); + assertEquals(3, network.getLoadCount()); + + Load loadEnergyConsumer = network.getLoad("EnergyConsumer"); + assertTrue(checkNaNLoad(loadEnergyConsumer)); + Load loadEnergySource = network.getLoad("EnergySource"); + assertTrue(checkNaNLoad(loadEnergySource)); + Load loadAsynchronousMachine = network.getLoad("AsynchronousMachine"); + assertTrue(checkNaNLoad(loadAsynchronousMachine)); + + readCgmesResources(network, DIR, "load_SSH.xml"); + + assertTrue(checkLoad(loadEnergyConsumer, 10.0, 5.0)); + assertTrue(checkLoad(loadEnergySource, -200.0, -90.0)); + assertTrue(checkLoad(loadAsynchronousMachine, 200.0, 50.0)); + } + + @Test + void importEAndTwoSshsTest() { + Network network = readCgmesResources(DIR, "load_EQ.xml"); + assertEquals(3, network.getLoadCount()); + + Load loadEnergyConsumer = network.getLoad("EnergyConsumer"); + assertTrue(checkNaNLoad(loadEnergyConsumer)); + Load loadEnergySource = network.getLoad("EnergySource"); + assertTrue(checkNaNLoad(loadEnergySource)); + Load loadAsynchronousMachine = network.getLoad("AsynchronousMachine"); + assertTrue(checkNaNLoad(loadAsynchronousMachine)); + + readCgmesResources(network, DIR, "load_SSH.xml"); + + assertTrue(checkLoad(loadEnergyConsumer, 10.0, 5.0)); + assertTrue(checkLoad(loadEnergySource, -200.0, -90.0)); + assertTrue(checkLoad(loadAsynchronousMachine, 200.0, 50.0)); + + readCgmesResources(network, DIR, "load_SSH_1.xml"); + + assertTrue(checkLoad(loadEnergyConsumer, 10.5, 5.5)); + assertTrue(checkLoad(loadEnergySource, -200.5, -90.5)); + assertTrue(checkLoad(loadAsynchronousMachine, 200.5, 50.5)); + } + + private static boolean checkNaNLoad(Load load) { + assertNotNull(load); + assertTrue(Double.isNaN(load.getP0())); + assertTrue(Double.isNaN(load.getQ0())); + return true; + } + + private static boolean checkLoad(Load load, double p0, double q0) { + assertNotNull(load); + assertEquals(p0, load.getP0()); + assertEquals(q0, load.getQ0()); + return true; + } +} diff --git a/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml new file mode 100644 index 00000000000..f7e2d205117 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml @@ -0,0 +1,93 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + All type of Loads + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/CoreEquipment-EU/3.0 + + + + GeographicalRegionTest + GeographicalRegionTest + + + SubGeographicalRegionTest + SubGeographicalRegionTest + + + + Substation1 + Substation1 + + + + BaseVoltage400 + Base Voltage Level 400kV + 400.0 kV + 400.0 + + + VoltageLevel1 + VoltageLevel1 + 420 + 380 + + + + + ConnectivityNode1 + Connectivity Node 1 + + + + + EnergyConsumer + + + + EnergyConsumer_T + Terminal + 1 + + + + + + EnergySource + + + + EnergySource_T + Terminal + 1 + + + + + + AsynchronousMachine + false + + 0.89 + 2.321 + 10 + false + 96.8 + 5.2 + 2 + 2 + false + 0.1 + AsynchronousMachine + + + synchronousMachine_T + Terminal + 1 + + + + + diff --git a/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH.xml b/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH.xml new file mode 100644 index 00000000000..9ded0a48bbe --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH.xml @@ -0,0 +1,35 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + All type of Loads + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 + + + + 10.0 + 5.0 + + + true + + + -200.0 + -90.0 + + + true + + + true + false + 200 + 50 + + + + true + + diff --git a/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH_1.xml b/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH_1.xml new file mode 100644 index 00000000000..efa3b861b10 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH_1.xml @@ -0,0 +1,35 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + All type of Loads + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 + + + + 10.5 + 5.5 + + + true + + + -200.5 + -90.5 + + + true + + + true + false + 200.5 + 50.5 + + + + true + + From a23bad256b64a549202eb9bb49e2dffa199ec161 Mon Sep 17 00:00:00 2001 From: Luma Date: Wed, 11 Dec 2024 16:54:29 +0100 Subject: [PATCH 32/54] use proposed API for network updates Signed-off-by: Luma --- .../powsybl/cgmes/conversion/CgmesImport.java | 3 ++- .../cgmes/conversion/test/ConversionUtil.java | 4 +--- .../com/powsybl/iidm/network/Importer.java | 23 +++++++++++++++++++ .../com/powsybl/iidm/network/Network.java | 23 +++++++++++++++++++ 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java index f118fbd4d27..6dffe400655 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java @@ -176,7 +176,8 @@ private Network importData1(ReadOnlyDataSource ds, NetworkFactory networkFactory return new Conversion(cgmes, config(p), activatedPreProcessors(p), activatedPostProcessors(p), networkFactory).convert(conversionReportNode); } - public void updateData(Network network, ReadOnlyDataSource ds, Properties p, ReportNode reportNode) { + @Override + public void update(Network network, ReadOnlyDataSource ds, Properties p, ReportNode reportNode) { TripleStoreOptions tripleStoreOptions = new TripleStoreOptions(); tripleStoreOptions.setQueryCatalog("-update"); ReadOnlyDataSource alternativeDataSourceForBoundary = null; diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java index 6feea04ca8e..831706c9d42 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java @@ -8,7 +8,6 @@ package com.powsybl.cgmes.conversion.test; import com.powsybl.cgmes.conversion.CgmesExport; -import com.powsybl.cgmes.conversion.CgmesImport; import com.powsybl.cgmes.conversion.CgmesImportPostProcessor; import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.model.CgmesModel; @@ -17,7 +16,6 @@ import com.powsybl.commons.datasource.ReadOnlyDataSource; import com.powsybl.commons.datasource.ResourceDataSource; import com.powsybl.commons.datasource.ResourceSet; -import com.powsybl.commons.report.ReportNode; import com.powsybl.iidm.network.Network; import com.powsybl.triplestore.api.TripleStoreFactory; @@ -102,7 +100,7 @@ public static Network readCgmesResources(Properties properties, String dir, Stri public static void readCgmesResources(Network network, String dir, String... files) { ReadOnlyDataSource ds = new ResourceDataSource("CGMES input file(s)", new ResourceSet(dir, files)); - new CgmesImport().updateData(network, ds, new Properties(), ReportNode.NO_OP); + network.update(ds); } public static String writeCgmesProfile(Network network, String profile, Path outDir) throws IOException { diff --git a/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/Importer.java b/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/Importer.java index bf18803ba0c..5828fc5dcfa 100644 --- a/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/Importer.java +++ b/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/Importer.java @@ -346,4 +346,27 @@ default Network importData(ReadOnlyDataSource dataSource, NetworkFactory network default void copy(ReadOnlyDataSource fromDataSource, DataSource toDataSource) { throw new UnsupportedOperationException("Copy not implemented"); } + + /** + * Update a given network with contents coming from a data source. + * + * @param network network + * @param dataSource data source + * @param parameters some properties to configure the import + * @param reportNode the reportNode used for functional logs + */ + default void update(Network network, ReadOnlyDataSource dataSource, Properties parameters, ReportNode reportNode) { + update(network, dataSource, parameters); + } + + /** + * Update a given network with contents coming from a data source. + * + * @param network network + * @param dataSource data source + * @param parameters some properties to configure the import + */ + default void update(Network network, ReadOnlyDataSource dataSource, Properties parameters) { + throw new UnsupportedOperationException("Importer do not implement updates"); + } } diff --git a/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/Network.java b/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/Network.java index 8197882ca70..764c862e2a3 100644 --- a/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/Network.java +++ b/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/Network.java @@ -401,6 +401,29 @@ static void readAll(Path dir, Consumer consumer) throws IOException, In readAll(dir, false, LocalComputationManager.getDefault(), ImportConfig.CACHE.get(), consumer); } + default void update(ReadOnlyDataSource dataSource) { + update(dataSource, null); + } + + default void update(ReadOnlyDataSource dataSource, Properties properties) { + update(dataSource, properties, ReportNode.NO_OP); + } + + default void update(ReadOnlyDataSource dataSource, Properties parameters, ReportNode reportNode) { + update(dataSource, LocalComputationManager.getDefault(), ImportConfig.load(), parameters, + new ImportersServiceLoader(), reportNode); + } + + default void update(ReadOnlyDataSource dataSource, ComputationManager computationManager, ImportConfig config, Properties parameters, + ImportersLoader loader, ReportNode reportNode) { + Importer importer = Importer.find(dataSource, loader, computationManager, config); + if (importer != null) { + importer.update(this, dataSource, parameters, reportNode); + } else { + throw new PowsyblException(Importers.UNSUPPORTED_FILE_FORMAT_OR_INVALID_FILE); + } + } + /** * A global bus/breaker view of the network. *

From 52a6c8fc5ab6a8f12ec213460325a5829cca5baf Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 12 Dec 2024 07:57:21 +0100 Subject: [PATCH 33/54] Add unitary tests Signed-off-by: marquesja1 --- .../powsybl/cgmes/conversion/CgmesImport.java | 14 + .../cgmes/conversion/test/ConversionUtil.java | 7 + .../cgmes/conversion/test/LoadUpdateTest.java | 112 ++++++++ .../test/TransformerUpdateTest.java | 146 +++++++++++ .../test/resources/update/load/load_EQ.xml | 93 +++++++ .../test/resources/update/load/load_SSH.xml | 35 +++ .../test/resources/update/load/load_SSH_1.xml | 35 +++ .../update/transformer/transformer_EQ.xml | 244 ++++++++++++++++++ .../update/transformer/transformer_SSH.xml | 54 ++++ .../update/transformer/transformer_SSH_1.xml | 54 ++++ 10 files changed, 794 insertions(+) create mode 100644 cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java create mode 100644 cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/TransformerUpdateTest.java create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH.xml create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH_1.xml create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_EQ.xml create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH.xml create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH_1.xml diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java index d4cfb94cf0e..f118fbd4d27 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java @@ -176,6 +176,20 @@ private Network importData1(ReadOnlyDataSource ds, NetworkFactory networkFactory return new Conversion(cgmes, config(p), activatedPreProcessors(p), activatedPostProcessors(p), networkFactory).convert(conversionReportNode); } + public void updateData(Network network, ReadOnlyDataSource ds, Properties p, ReportNode reportNode) { + TripleStoreOptions tripleStoreOptions = new TripleStoreOptions(); + tripleStoreOptions.setQueryCatalog("-update"); + ReadOnlyDataSource alternativeDataSourceForBoundary = null; + CgmesModel cgmes = CgmesModelFactory.create( + ds, + alternativeDataSourceForBoundary, + TripleStoreFactory.DEFAULT_IMPLEMENTATION, + reportNode, + tripleStoreOptions); + Conversion conversion = new Conversion(cgmes, config(p)); + conversion.update(network, reportNode); + } + static class FilteredReadOnlyDataSource implements ReadOnlyDataSource { private final ReadOnlyDataSource ds; private final Predicate filter; diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java index 449e7f76f20..6feea04ca8e 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/ConversionUtil.java @@ -8,6 +8,7 @@ package com.powsybl.cgmes.conversion.test; import com.powsybl.cgmes.conversion.CgmesExport; +import com.powsybl.cgmes.conversion.CgmesImport; import com.powsybl.cgmes.conversion.CgmesImportPostProcessor; import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.model.CgmesModel; @@ -16,6 +17,7 @@ import com.powsybl.commons.datasource.ReadOnlyDataSource; import com.powsybl.commons.datasource.ResourceDataSource; import com.powsybl.commons.datasource.ResourceSet; +import com.powsybl.commons.report.ReportNode; import com.powsybl.iidm.network.Network; import com.powsybl.triplestore.api.TripleStoreFactory; @@ -98,6 +100,11 @@ public static Network readCgmesResources(Properties properties, String dir, Stri return Network.read(ds, properties); } + public static void readCgmesResources(Network network, String dir, String... files) { + ReadOnlyDataSource ds = new ResourceDataSource("CGMES input file(s)", new ResourceSet(dir, files)); + new CgmesImport().updateData(network, ds, new Properties(), ReportNode.NO_OP); + } + public static String writeCgmesProfile(Network network, String profile, Path outDir) throws IOException { return writeCgmesProfile(network, profile, outDir, new Properties()); } diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java new file mode 100644 index 00000000000..4dfcec64ea2 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.cgmes.conversion.test; + +import com.powsybl.iidm.network.Load; +import com.powsybl.iidm.network.Network; +import org.junit.jupiter.api.Test; + +import static com.powsybl.cgmes.conversion.test.ConversionUtil.readCgmesResources; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Luma Zamarreño {@literal } + * @author José Antonio Marqués {@literal } + */ +class LoadUpdateTest { + + private static final String DIR = "/update/load/"; + + @Test + void importEqTest() { + Network network = readCgmesResources(DIR, "load_EQ.xml"); + assertEquals(3, network.getLoadCount()); + + Load loadEnergyConsumer = network.getLoad("EnergyConsumer"); + assertTrue(checkNaNLoad(loadEnergyConsumer)); + + Load loadEnergySource = network.getLoad("EnergySource"); + assertTrue(checkNaNLoad(loadEnergySource)); + + Load loadAsynchronousMachine = network.getLoad("AsynchronousMachine"); + assertTrue(checkNaNLoad(loadAsynchronousMachine)); + } + + @Test + void importEqAndSshTogetherTest() { + Network network = readCgmesResources(DIR, "load_EQ.xml", "load_SSH.xml"); + assertEquals(3, network.getLoadCount()); + + Load loadEnergyConsumer = network.getLoad("EnergyConsumer"); + assertTrue(checkLoad(loadEnergyConsumer, 10.0, 5.0)); + + Load loadEnergySource = network.getLoad("EnergySource"); + assertTrue(checkLoad(loadEnergySource, -200.0, -90.0)); + + Load loadAsynchronousMachine = network.getLoad("AsynchronousMachine"); + assertTrue(checkLoad(loadAsynchronousMachine, 200.0, 50.0)); + } + + @Test + void importEAndSshSeparatelyTest() { + Network network = readCgmesResources(DIR, "load_EQ.xml"); + assertEquals(3, network.getLoadCount()); + + Load loadEnergyConsumer = network.getLoad("EnergyConsumer"); + assertTrue(checkNaNLoad(loadEnergyConsumer)); + Load loadEnergySource = network.getLoad("EnergySource"); + assertTrue(checkNaNLoad(loadEnergySource)); + Load loadAsynchronousMachine = network.getLoad("AsynchronousMachine"); + assertTrue(checkNaNLoad(loadAsynchronousMachine)); + + readCgmesResources(network, DIR, "load_SSH.xml"); + + assertTrue(checkLoad(loadEnergyConsumer, 10.0, 5.0)); + assertTrue(checkLoad(loadEnergySource, -200.0, -90.0)); + assertTrue(checkLoad(loadAsynchronousMachine, 200.0, 50.0)); + } + + @Test + void importEAndTwoSshsTest() { + Network network = readCgmesResources(DIR, "load_EQ.xml"); + assertEquals(3, network.getLoadCount()); + + Load loadEnergyConsumer = network.getLoad("EnergyConsumer"); + assertTrue(checkNaNLoad(loadEnergyConsumer)); + Load loadEnergySource = network.getLoad("EnergySource"); + assertTrue(checkNaNLoad(loadEnergySource)); + Load loadAsynchronousMachine = network.getLoad("AsynchronousMachine"); + assertTrue(checkNaNLoad(loadAsynchronousMachine)); + + readCgmesResources(network, DIR, "load_SSH.xml"); + + assertTrue(checkLoad(loadEnergyConsumer, 10.0, 5.0)); + assertTrue(checkLoad(loadEnergySource, -200.0, -90.0)); + assertTrue(checkLoad(loadAsynchronousMachine, 200.0, 50.0)); + + readCgmesResources(network, DIR, "load_SSH_1.xml"); + + assertTrue(checkLoad(loadEnergyConsumer, 10.5, 5.5)); + assertTrue(checkLoad(loadEnergySource, -200.5, -90.5)); + assertTrue(checkLoad(loadAsynchronousMachine, 200.5, 50.5)); + } + + private static boolean checkNaNLoad(Load load) { + assertNotNull(load); + assertTrue(Double.isNaN(load.getP0())); + assertTrue(Double.isNaN(load.getQ0())); + return true; + } + + private static boolean checkLoad(Load load, double p0, double q0) { + assertNotNull(load); + assertEquals(p0, load.getP0()); + assertEquals(q0, load.getQ0()); + return true; + } +} diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/TransformerUpdateTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/TransformerUpdateTest.java new file mode 100644 index 00000000000..1e8154790e8 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/TransformerUpdateTest.java @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.cgmes.conversion.test; + +import com.powsybl.cgmes.conversion.Conversion; +import com.powsybl.cgmes.extensions.CgmesTapChanger; +import com.powsybl.cgmes.extensions.CgmesTapChangers; +import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.iidm.network.*; +import org.junit.jupiter.api.Test; + +import static com.powsybl.cgmes.conversion.test.ConversionUtil.readCgmesResources; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Luma Zamarreño {@literal } + * @author José Antonio Marqués {@literal } + */ +class TransformerUpdateTest { + + private static final String DIR = "/update/transformer/"; + + @Test + void importEqTest() { + Network network = readCgmesResources(DIR, "transformer_EQ.xml"); + assertEquals(1, network.getTwoWindingsTransformerCount()); + assertEquals(1, network.getThreeWindingsTransformerCount()); + + TwoWindingsTransformer t2w = network.getTwoWindingsTransformer("T2W"); + assertTrue(checkEq(t2w)); + ThreeWindingsTransformer t3w = network.getThreeWindingsTransformer("T3W"); + assertTrue(checkEq(t3w)); + } + + @Test + void importEqAndSshTogetherTest() { + Network network = readCgmesResources(DIR, "transformer_EQ.xml", "transformer_SSH.xml"); + assertEquals(1, network.getTwoWindingsTransformerCount()); + assertEquals(1, network.getThreeWindingsTransformerCount()); + + TwoWindingsTransformer t2w = network.getTwoWindingsTransformer("T2W"); + assertTrue(checkSsh(t2w, -2, 100.0, 0.2, true)); + + ThreeWindingsTransformer t3w = network.getThreeWindingsTransformer("T3W"); + assertTrue(checkSsh(t3w, 8, 225.0, 2.0, true)); + } + + @Test + void importEqAndSshSeparatelyTest() { + Network network = readCgmesResources(DIR, "transformer_EQ.xml"); + assertEquals(1, network.getTwoWindingsTransformerCount()); + assertEquals(1, network.getThreeWindingsTransformerCount()); + + TwoWindingsTransformer t2w = network.getTwoWindingsTransformer("T2W"); + assertTrue(checkEq(t2w)); + ThreeWindingsTransformer t3w = network.getThreeWindingsTransformer("T3W"); + assertTrue(checkEq(t3w)); + + readCgmesResources(network, DIR, "transformer_SSH.xml"); + + assertTrue(checkSsh(t2w, -2, 100.0, 0.2, true)); + assertTrue(checkSsh(t3w, 8, 225.0, 2.0, true)); + } + + @Test + void importEqAndTwoSshsTest() { + Network network = readCgmesResources(DIR, "transformer_EQ.xml"); + assertEquals(1, network.getTwoWindingsTransformerCount()); + assertEquals(1, network.getThreeWindingsTransformerCount()); + + TwoWindingsTransformer t2w = network.getTwoWindingsTransformer("T2W"); + assertTrue(checkEq(t2w)); + ThreeWindingsTransformer t3w = network.getThreeWindingsTransformer("T3W"); + assertTrue(checkEq(t3w)); + + readCgmesResources(network, DIR, "transformer_SSH.xml"); + assertTrue(checkSsh(t2w, -2, 100.0, 0.2, true)); + assertTrue(checkSsh(t3w, 8, 225.0, 2.0, true)); + + readCgmesResources(network, DIR, "transformer_SSH_1.xml"); + assertTrue(checkSsh(t2w, -1, 110.0, 0.3, false)); + assertTrue(checkSsh(t3w, 7, 220.0, 2.2, false)); + } + + private static boolean checkEq(TwoWindingsTransformer t2w) { + assertNotNull(t2w); + String tapChangerId = t2w.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.PHASE_TAP_CHANGER + 1).orElseThrow(); + int normalStep = getNormalStep(t2w, tapChangerId); + assertNotNull(t2w.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "terminalSign")); + assertEquals(normalStep, t2w.getPhaseTapChanger().getTapPosition()); + + assertTrue(Double.isNaN(t2w.getPhaseTapChanger().getRegulationValue())); + assertTrue(Double.isNaN(t2w.getPhaseTapChanger().getTargetDeadband())); + assertSame(t2w.getPhaseTapChanger().getRegulationMode(), PhaseTapChanger.RegulationMode.ACTIVE_POWER_CONTROL); + assertNotNull(t2w.getPhaseTapChanger().getRegulationTerminal()); + assertFalse(t2w.getPhaseTapChanger().isRegulating()); + return true; + } + + private static boolean checkEq(ThreeWindingsTransformer t3w) { + assertNotNull(t3w); + String tapChangerId = t3w.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.RATIO_TAP_CHANGER + 2).orElseThrow(); + int normalStep = getNormalStep(t3w, tapChangerId); + assertEquals(normalStep, t3w.getLeg2().getRatioTapChanger().getTapPosition()); + + assertTrue(Double.isNaN(t3w.getLeg2().getRatioTapChanger().getRegulationValue())); + assertTrue(Double.isNaN(t3w.getLeg2().getRatioTapChanger().getTargetDeadband())); + assertSame(t3w.getLeg2().getRatioTapChanger().getRegulationMode(), RatioTapChanger.RegulationMode.VOLTAGE); + assertNotNull(t3w.getLeg2().getRatioTapChanger().getRegulationTerminal()); + assertFalse(t3w.getLeg2().getRatioTapChanger().isRegulating()); + return true; + } + + private static boolean checkSsh(TwoWindingsTransformer t2w, int tapPosition, double regulationValue, double targetDeadband, boolean isRegulating) { + assertNotNull(t2w); + assertEquals(tapPosition, t2w.getPhaseTapChanger().getTapPosition()); + + assertEquals(regulationValue, t2w.getPhaseTapChanger().getRegulationValue()); + assertEquals(targetDeadband, t2w.getPhaseTapChanger().getTargetDeadband()); + assertEquals(isRegulating, t2w.getPhaseTapChanger().isRegulating()); + return true; + } + + private static boolean checkSsh(ThreeWindingsTransformer t3w, int tapPosition, double regulationValue, double targetDeadband, boolean isRegulating) { + assertNotNull(t3w); + assertEquals(tapPosition, t3w.getLeg2().getRatioTapChanger().getTapPosition()); + + assertEquals(regulationValue, t3w.getLeg2().getRatioTapChanger().getRegulationValue()); + assertEquals(targetDeadband, t3w.getLeg2().getRatioTapChanger().getTargetDeadband()); + assertEquals(isRegulating, t3w.getLeg2().getRatioTapChanger().isRegulating()); + return true; + } + + private static > int getNormalStep(Connectable tw, String tapChangerId) { + CgmesTapChangers cgmesTcs = tw.getExtension(CgmesTapChangers.class); + assertNotNull(cgmesTcs); + CgmesTapChanger cgmesTc = cgmesTcs.getTapChanger(tapChangerId); + assertNotNull(cgmesTcs); + return cgmesTc.getStep().orElseThrow(); + } +} diff --git a/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml new file mode 100644 index 00000000000..f7e2d205117 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml @@ -0,0 +1,93 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + All type of Loads + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/CoreEquipment-EU/3.0 + + + + GeographicalRegionTest + GeographicalRegionTest + + + SubGeographicalRegionTest + SubGeographicalRegionTest + + + + Substation1 + Substation1 + + + + BaseVoltage400 + Base Voltage Level 400kV + 400.0 kV + 400.0 + + + VoltageLevel1 + VoltageLevel1 + 420 + 380 + + + + + ConnectivityNode1 + Connectivity Node 1 + + + + + EnergyConsumer + + + + EnergyConsumer_T + Terminal + 1 + + + + + + EnergySource + + + + EnergySource_T + Terminal + 1 + + + + + + AsynchronousMachine + false + + 0.89 + 2.321 + 10 + false + 96.8 + 5.2 + 2 + 2 + false + 0.1 + AsynchronousMachine + + + synchronousMachine_T + Terminal + 1 + + + + + diff --git a/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH.xml b/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH.xml new file mode 100644 index 00000000000..9ded0a48bbe --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH.xml @@ -0,0 +1,35 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + All type of Loads + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 + + + + 10.0 + 5.0 + + + true + + + -200.0 + -90.0 + + + true + + + true + false + 200 + 50 + + + + true + + diff --git a/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH_1.xml b/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH_1.xml new file mode 100644 index 00000000000..efa3b861b10 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH_1.xml @@ -0,0 +1,35 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + All type of Loads + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 + + + + 10.5 + 5.5 + + + true + + + -200.5 + -90.5 + + + true + + + true + false + 200.5 + 50.5 + + + + true + + diff --git a/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_EQ.xml new file mode 100644 index 00000000000..2293c44384a --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_EQ.xml @@ -0,0 +1,244 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + All type of Loads + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/CoreEquipment-EU/3.0 + + + + GeographicalRegionTest + GeographicalRegionTest + + + SubGeographicalRegionTest + SubGeographicalRegionTest + + + + Substation1 + Substation1 + + + + BaseVoltage400 + Base Voltage Level 400kV + 400.0 kV + 400.0 + + + BaseVoltage220 + Base Voltage Level 220kV + 220.0 kV + 220.0 + + + BaseVoltage110 + Base Voltage Level 110kV + 110.0 kV + 110.0 + + + VoltageLevel1 + VoltageLevel1 + 420 + 380 + + + + + ConnectivityNode1 + Connectivity Node 1 + + + + VoltageLevel2 + VoltageLevel2 + 235 + 205 + + + + + ConnectivityNode2 + Connectivity Node 2 + + + + VoltageLevel3 + VoltageLevel3 + 120 + 100 + + + + + ConnectivityNode3 + Connectivity Node 3 + + + + + T2W + + + + + 0.0 + 1 + 0.0 + T2W-End1 + 0.10 + 999 + 400 + 5.44 + + + + + + + T2W-Terminal1 + 1 + + + + + + + 0 + 2 + 0 + T2W-End2 + 0 + 999 + 220 + 0 + + + + + + + T2W-Terminal2 + 2 + + + + + + + 8 + -8 + true + T2W-PhaseTapChanger + 0 + 400 + 4 + -1.25 + 5.45 + 5.45 + + + + + + + TT2W-PhaseTapChanger-Control + + + + + T3W + + + + + 0.0 + 1 + 0.0 + T3W-End1 + 0.10 + 999 + 400 + 5.44 + + + + + + + T3W-Terminal1 + 1 + + + + + + + 0 + 2 + 0 + T3W-End2 + 0.018 + 999 + 220 + 0.44 + + + + + + + T3W-Terminal2 + 2 + + + + + + + 0 + 3 + 0 + T3W-End3 + 0.018 + 999 + 110 + 0.44 + + + + + + + T3W-Terminal3 + 3 + + + + + + + 15 + 1 + true + T3W-Winding2-RatioTapChanger + 8 + 220 + 8 + -2 + + + + + + + + T3W-winding2-ratioTapChanger-control + + + + diff --git a/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH.xml b/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH.xml new file mode 100644 index 00000000000..a8beb622703 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH.xml @@ -0,0 +1,54 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + All type of Loads + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 + + + + false + -2 + + + + true + true + 0.2 + 100 + + + + + false + 8 + + + + true + true + 2.0 + 225.0 + + + + + true + + + true + + + + true + + + true + + + true + + + diff --git a/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH_1.xml b/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH_1.xml new file mode 100644 index 00000000000..81e4bb574de --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH_1.xml @@ -0,0 +1,54 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + All type of Loads + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 + + + + false + -1 + + + + true + false + 0.3 + 110 + + + + + false + 7 + + + + true + false + 2.2 + 220.0 + + + + + true + + + true + + + + true + + + true + + + true + + + From eee776ce3aaad4749dbdb1cc897efed7bba2fe84 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 12 Dec 2024 08:26:32 +0100 Subject: [PATCH 34/54] Pretty code Signed-off-by: marquesja1 --- .../elements/EnergyConsumerConversion.java | 15 ++--- .../cgmes/conversion/test/LoadUpdateTest.java | 58 +++++++++++-------- .../com/powsybl/cgmes/model/CgmesNames.java | 2 + 3 files changed, 41 insertions(+), 34 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index 72c656963ff..dcb265f057b 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -26,9 +26,6 @@ */ public class EnergyConsumerConversion extends AbstractConductingEquipmentConversion { - private static final String P_FIXED = "pFixed"; - private static final String Q_FIXED = "qFixed"; - public EnergyConsumerConversion(PropertyBag ec, Context context) { super(CgmesNames.ENERGY_CONSUMER, ec, context); loadKind = ec.getLocal("type"); @@ -44,8 +41,8 @@ public void convert() { } else { loadType = LoadType.UNDEFINED; } - double pFixed = p.asDouble(P_FIXED, 0.0); - double qFixed = p.asDouble(Q_FIXED, 0.0); + double pFixed = p.asDouble(CgmesNames.P_FIXED, 0.0); + double qFixed = p.asDouble(CgmesNames.Q_FIXED, 0.0); LoadAdder adder = voltageLevel().newLoad() .setLoadType(loadType); identify(adder); @@ -61,8 +58,8 @@ public void convert() { private void addSpecificProperties(Load newLoad, double pFixed, double qFixed) { newLoad.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, loadKind); - newLoad.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + P_FIXED, String.valueOf(pFixed)); - newLoad.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + Q_FIXED, String.valueOf(qFixed)); + newLoad.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.P_FIXED, String.valueOf(pFixed)); + newLoad.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.Q_FIXED, String.valueOf(qFixed)); } private void model(LoadAdder adder) { @@ -145,8 +142,8 @@ private static void setLoadDetail(String type, Load newLoad, double pFixed, doub public static void update(Load load, PropertyBag cgmesData, Context context) { updateTerminals(load, context, load.getTerminal()); - double pFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + P_FIXED)); - double qFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + Q_FIXED)); + double pFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.P_FIXED)); + double qFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.Q_FIXED)); PowerFlow updatedPowerFlow = updatedPowerFlow(load, cgmesData, context); load.setP0(updatedPowerFlow.defined() ? updatedPowerFlow.p() : defaultValue(pFixed, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context))); diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java index 4dfcec64ea2..8764cff19dd 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java @@ -7,6 +7,8 @@ */ package com.powsybl.cgmes.conversion.test; +import com.powsybl.cgmes.conversion.Conversion; +import com.powsybl.cgmes.model.CgmesNames; import com.powsybl.iidm.network.Load; import com.powsybl.iidm.network.Network; import org.junit.jupiter.api.Test; @@ -28,13 +30,13 @@ void importEqTest() { assertEquals(3, network.getLoadCount()); Load loadEnergyConsumer = network.getLoad("EnergyConsumer"); - assertTrue(checkNaNLoad(loadEnergyConsumer)); + assertTrue(checkEq(loadEnergyConsumer)); Load loadEnergySource = network.getLoad("EnergySource"); - assertTrue(checkNaNLoad(loadEnergySource)); + assertTrue(checkEq(loadEnergySource)); Load loadAsynchronousMachine = network.getLoad("AsynchronousMachine"); - assertTrue(checkNaNLoad(loadAsynchronousMachine)); + assertTrue(checkEq(loadAsynchronousMachine)); } @Test @@ -43,67 +45,73 @@ void importEqAndSshTogetherTest() { assertEquals(3, network.getLoadCount()); Load loadEnergyConsumer = network.getLoad("EnergyConsumer"); - assertTrue(checkLoad(loadEnergyConsumer, 10.0, 5.0)); + assertTrue(checkSsh(loadEnergyConsumer, 10.0, 5.0)); Load loadEnergySource = network.getLoad("EnergySource"); - assertTrue(checkLoad(loadEnergySource, -200.0, -90.0)); + assertTrue(checkSsh(loadEnergySource, -200.0, -90.0)); Load loadAsynchronousMachine = network.getLoad("AsynchronousMachine"); - assertTrue(checkLoad(loadAsynchronousMachine, 200.0, 50.0)); + assertTrue(checkSsh(loadAsynchronousMachine, 200.0, 50.0)); } @Test - void importEAndSshSeparatelyTest() { + void importEqAndSshSeparatelyTest() { Network network = readCgmesResources(DIR, "load_EQ.xml"); assertEquals(3, network.getLoadCount()); Load loadEnergyConsumer = network.getLoad("EnergyConsumer"); - assertTrue(checkNaNLoad(loadEnergyConsumer)); + assertTrue(checkEq(loadEnergyConsumer)); Load loadEnergySource = network.getLoad("EnergySource"); - assertTrue(checkNaNLoad(loadEnergySource)); + assertTrue(checkEq(loadEnergySource)); Load loadAsynchronousMachine = network.getLoad("AsynchronousMachine"); - assertTrue(checkNaNLoad(loadAsynchronousMachine)); + assertTrue(checkEq(loadAsynchronousMachine)); readCgmesResources(network, DIR, "load_SSH.xml"); - assertTrue(checkLoad(loadEnergyConsumer, 10.0, 5.0)); - assertTrue(checkLoad(loadEnergySource, -200.0, -90.0)); - assertTrue(checkLoad(loadAsynchronousMachine, 200.0, 50.0)); + assertTrue(checkSsh(loadEnergyConsumer, 10.0, 5.0)); + assertTrue(checkSsh(loadEnergySource, -200.0, -90.0)); + assertTrue(checkSsh(loadAsynchronousMachine, 200.0, 50.0)); } @Test - void importEAndTwoSshsTest() { + void importEqAndTwoSshsTest() { Network network = readCgmesResources(DIR, "load_EQ.xml"); assertEquals(3, network.getLoadCount()); Load loadEnergyConsumer = network.getLoad("EnergyConsumer"); - assertTrue(checkNaNLoad(loadEnergyConsumer)); + assertTrue(checkEq(loadEnergyConsumer)); Load loadEnergySource = network.getLoad("EnergySource"); - assertTrue(checkNaNLoad(loadEnergySource)); + assertTrue(checkEq(loadEnergySource)); Load loadAsynchronousMachine = network.getLoad("AsynchronousMachine"); - assertTrue(checkNaNLoad(loadAsynchronousMachine)); + assertTrue(checkEq(loadAsynchronousMachine)); readCgmesResources(network, DIR, "load_SSH.xml"); - assertTrue(checkLoad(loadEnergyConsumer, 10.0, 5.0)); - assertTrue(checkLoad(loadEnergySource, -200.0, -90.0)); - assertTrue(checkLoad(loadAsynchronousMachine, 200.0, 50.0)); + assertTrue(checkSsh(loadEnergyConsumer, 10.0, 5.0)); + assertTrue(checkSsh(loadEnergySource, -200.0, -90.0)); + assertTrue(checkSsh(loadAsynchronousMachine, 200.0, 50.0)); readCgmesResources(network, DIR, "load_SSH_1.xml"); - assertTrue(checkLoad(loadEnergyConsumer, 10.5, 5.5)); - assertTrue(checkLoad(loadEnergySource, -200.5, -90.5)); - assertTrue(checkLoad(loadAsynchronousMachine, 200.5, 50.5)); + assertTrue(checkSsh(loadEnergyConsumer, 10.5, 5.5)); + assertTrue(checkSsh(loadEnergySource, -200.5, -90.5)); + assertTrue(checkSsh(loadAsynchronousMachine, 200.5, 50.5)); } - private static boolean checkNaNLoad(Load load) { + private static boolean checkEq(Load load) { assertNotNull(load); assertTrue(Double.isNaN(load.getP0())); assertTrue(Double.isNaN(load.getQ0())); + String originalClass = load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS); + if (originalClass.equals(CgmesNames.ENERGY_CONSUMER)) { + assertNotNull(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.P_FIXED)); + assertNotNull(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.Q_FIXED)); + } + load.getPropertyNames().forEach(pn -> System.err.printf("Property %s %s %n", pn, load.getProperty(pn))); return true; } - private static boolean checkLoad(Load load, double p0, double q0) { + private static boolean checkSsh(Load load, double p0, double q0) { assertNotNull(load); assertEquals(p0, load.getP0()); assertEquals(q0, load.getQ0()); diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java index af5b71cdc0a..6c2bc975b70 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java @@ -144,6 +144,8 @@ public final class CgmesNames { public static final String CURRENT_LIMIT = "CurrentLimit"; public static final String ACTIVE_POWER_LIMIT = "ActivePowerLimit"; public static final String APPARENT_POWER_LIMIT = "ApparentPowerLimit"; + public static final String P_FIXED = "pFixed"; + public static final String Q_FIXED = "qFixed"; private CgmesNames() { } From 3a5a3ae9a0d5304bb97c3ed35dbb1777d004335b Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 12 Dec 2024 09:45:46 +0100 Subject: [PATCH 35/54] Minor changes. Signed-off-by: marquesja1 --- .../conversion/RegulatingControlMappingForTransformers.java | 3 ++- .../elements/AbstractConductingEquipmentConversion.java | 1 - .../transformers/AbstractTransformerConversion.java | 2 +- .../cgmes/conversion/test/TransformerUpdateTest.java | 6 +++--- .../src/main/java/com/powsybl/cgmes/model/CgmesNames.java | 1 + 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForTransformers.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForTransformers.java index 15c88a2b489..b229b350af9 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForTransformers.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForTransformers.java @@ -9,6 +9,7 @@ import com.powsybl.cgmes.conversion.RegulatingControlMapping.RegulatingControl; import com.powsybl.cgmes.conversion.RegulatingTerminalMapper.TerminalAndSign; +import com.powsybl.cgmes.model.CgmesNames; import com.powsybl.iidm.network.*; import com.powsybl.triplestore.api.PropertyBag; import org.slf4j.Logger; @@ -189,7 +190,7 @@ private boolean setPtcRegulatingControl(PhaseTapChanger.RegulationMode regulatio ptc.setRegulationTerminal(mappedRegulatingTerminal.getTerminal()) .setRegulationMode(regulationMode); - twt.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "terminalSign" + end, String.valueOf(mappedRegulatingTerminal.getSign())); + twt.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL_SIGN + end, String.valueOf(mappedRegulatingTerminal.getSign())); return true; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index 979027d1f0e..12a3e666006 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -24,7 +24,6 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.EMPTY; /** * @author Luma Zamarreño {@literal } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java index 70c30ff3f29..ebf3ddd47bb 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java @@ -346,7 +346,7 @@ private static > boolean isHiddenTapChanger(Connectable } private static > int findTerminalSign(Connectable tw, String end) { - String terminalSign = tw.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "terminalSign" + end); + String terminalSign = tw.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL_SIGN + end); return terminalSign != null ? Integer.parseInt(terminalSign) : 1; } diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/TransformerUpdateTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/TransformerUpdateTest.java index 1e8154790e8..7866bf5ad7a 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/TransformerUpdateTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/TransformerUpdateTest.java @@ -91,12 +91,12 @@ private static boolean checkEq(TwoWindingsTransformer t2w) { assertNotNull(t2w); String tapChangerId = t2w.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.PHASE_TAP_CHANGER + 1).orElseThrow(); int normalStep = getNormalStep(t2w, tapChangerId); - assertNotNull(t2w.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "terminalSign")); + assertNotNull(t2w.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL_SIGN)); assertEquals(normalStep, t2w.getPhaseTapChanger().getTapPosition()); assertTrue(Double.isNaN(t2w.getPhaseTapChanger().getRegulationValue())); assertTrue(Double.isNaN(t2w.getPhaseTapChanger().getTargetDeadband())); - assertSame(t2w.getPhaseTapChanger().getRegulationMode(), PhaseTapChanger.RegulationMode.ACTIVE_POWER_CONTROL); + assertSame(PhaseTapChanger.RegulationMode.ACTIVE_POWER_CONTROL, t2w.getPhaseTapChanger().getRegulationMode()); assertNotNull(t2w.getPhaseTapChanger().getRegulationTerminal()); assertFalse(t2w.getPhaseTapChanger().isRegulating()); return true; @@ -110,7 +110,7 @@ private static boolean checkEq(ThreeWindingsTransformer t3w) { assertTrue(Double.isNaN(t3w.getLeg2().getRatioTapChanger().getRegulationValue())); assertTrue(Double.isNaN(t3w.getLeg2().getRatioTapChanger().getTargetDeadband())); - assertSame(t3w.getLeg2().getRatioTapChanger().getRegulationMode(), RatioTapChanger.RegulationMode.VOLTAGE); + assertSame(RatioTapChanger.RegulationMode.VOLTAGE, t3w.getLeg2().getRatioTapChanger().getRegulationMode()); assertNotNull(t3w.getLeg2().getRatioTapChanger().getRegulationTerminal()); assertFalse(t3w.getLeg2().getRatioTapChanger().isRegulating()); return true; diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java index 69ad77aeb44..223bbf7d0c4 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java @@ -147,6 +147,7 @@ public final class CgmesNames { public static final String APPARENT_POWER_LIMIT = "ApparentPowerLimit"; public static final String P_FIXED = "pFixed"; public static final String Q_FIXED = "qFixed"; + public static final String TERMINAL_SIGN = "terminalSign"; private CgmesNames() { } From 4485ba1fbc7e4ace8dbaa4fd2960ff416267bb39 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 12 Dec 2024 10:33:14 +0100 Subject: [PATCH 36/54] Fix code smell Signed-off-by: marquesja1 --- .../java/com/powsybl/cgmes/conversion/CgmesReports.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java index 5e5ea742ad4..32d7776e699 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java @@ -17,6 +17,8 @@ */ public final class CgmesReports { + private static final String EQUIPMENT_ID = "equipmentId"; + private CgmesReports() { } @@ -92,7 +94,7 @@ public static void importedCgmesNetworkReport(ReportNode reportNode, String netw public static void badVoltageTargetValueRegulatingControlReport(ReportNode reportNode, String eqId, double targetValue) { reportNode.newReportNode() .withMessageTemplate("badVoltageTargetValueRegulatingControl", "Equipment ${equipmentId} has a regulating control with bad target value for voltage: ${targetValue}.") - .withUntypedValue("equipmentId", eqId) + .withUntypedValue(EQUIPMENT_ID, eqId) .withTypedValue("targetValue", targetValue, TypedValue.VOLTAGE) .withSeverity(TypedValue.WARN_SEVERITY) .add(); @@ -101,7 +103,7 @@ public static void badVoltageTargetValueRegulatingControlReport(ReportNode repor public static void badTargetValueRegulatingControlReport(ReportNode reportNode, String eqId, double targetValue) { reportNode.newReportNode() .withMessageTemplate("badTargetValueRegulatingControl", "Equipment ${equipmentId} has a regulating control with bad target value: ${targetValue}.") - .withUntypedValue("equipmentId", eqId) + .withUntypedValue(EQUIPMENT_ID, eqId) .withUntypedValue("targetValue", targetValue) .withSeverity(TypedValue.WARN_SEVERITY) .add(); @@ -110,7 +112,7 @@ public static void badTargetValueRegulatingControlReport(ReportNode reportNode, public static void badTargetDeadbandRegulatingControlReport(ReportNode reportNode, String eqId, double targetDeadband) { reportNode.newReportNode() .withMessageTemplate("badTargetDeadbandRegulatingControl", "Equipment ${equipmentId} has a regulating control with bad target deadband: ${targetDeadband}.") - .withUntypedValue("equipmentId", eqId) + .withUntypedValue(EQUIPMENT_ID, eqId) .withUntypedValue("targetDeadband", targetDeadband) .withSeverity(TypedValue.WARN_SEVERITY) .add(); From b63bbcd3fc3b0276a3ca20beb067a56df45c8d37 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 12 Dec 2024 12:26:27 +0100 Subject: [PATCH 37/54] Clean load queries Signed-off-by: marquesja1 (cherry picked from commit 5bb3d08dfd8eda8c87ade5bf839bc2ffab343b5f) --- .../cgmes-model/src/main/resources/CIM16.sparql | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/cgmes/cgmes-model/src/main/resources/CIM16.sparql b/cgmes/cgmes-model/src/main/resources/CIM16.sparql index bae7ca1b6db..e81bcb2a774 100644 --- a/cgmes/cgmes-model/src/main/resources/CIM16.sparql +++ b/cgmes/cgmes-model/src/main/resources/CIM16.sparql @@ -766,11 +766,6 @@ WHERE { OPTIONAL { ?EnergyConsumer cim:EnergyConsumer.pfixed ?pfixed } OPTIONAL { ?EnergyConsumer cim:EnergyConsumer.qfixed ?qfixed } }} -OPTIONAL { GRAPH ?graphSSH { - ?EnergyConsumer - cim:EnergyConsumer.p ?p ; - cim:EnergyConsumer.q ?q -}} } # query: energySources @@ -782,11 +777,6 @@ WHERE { cim:IdentifiedObject.name ?name . ?Terminal cim:Terminal.ConductingEquipment ?EnergySource }} -OPTIONAL { GRAPH ?graphSSH { - ?EnergySource - cim:EnergySource.activePower ?p ; - cim:EnergySource.reactivePower ?q -}} } # query: shuntCompensators @@ -1039,13 +1029,6 @@ WHERE { cim:IdentifiedObject.name ?name . ?Terminal cim:Terminal.ConductingEquipment ?AsynchronousMachine . }} -OPTIONAL { GRAPH ?graphSSH { - ?AsynchronousMachine - cim:AsynchronousMachine.asynchronousMachineType ?type ; - cim:RotatingMachine.p ?p ; - cim:RotatingMachine.q ?q ; - cim:RegulatingCondEq.controlEnabled ?controlEnabled -}} } # query: controlAreas From c3a3893bf325163098bfc72097ea155b478e6661 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 12 Dec 2024 15:59:10 +0100 Subject: [PATCH 38/54] Clean transformer queries Signed-off-by: marquesja1 --- ...icroGridTestConfiguration_BC_BE_SSH_V2.xml | 4 ++-- .../test/export/ExportXmlCompare.java | 2 ++ .../src/main/resources/CIM16.sparql | 24 ------------------- 3 files changed, 4 insertions(+), 26 deletions(-) diff --git a/cgmes/cgmes-conformity/src/main/resources/conformity-modified/cas-1.1.3-data-4.0.3/MicroGrid/BaseCase/BC_BE_v2_hidden_tc/MicroGridTestConfiguration_BC_BE_SSH_V2.xml b/cgmes/cgmes-conformity/src/main/resources/conformity-modified/cas-1.1.3-data-4.0.3/MicroGrid/BaseCase/BC_BE_v2_hidden_tc/MicroGridTestConfiguration_BC_BE_SSH_V2.xml index 3fc79cee1ee..3a000a823d4 100644 --- a/cgmes/cgmes-conformity/src/main/resources/conformity-modified/cas-1.1.3-data-4.0.3/MicroGrid/BaseCase/BC_BE_v2_hidden_tc/MicroGridTestConfiguration_BC_BE_SSH_V2.xml +++ b/cgmes/cgmes-conformity/src/main/resources/conformity-modified/cas-1.1.3-data-4.0.3/MicroGrid/BaseCase/BC_BE_v2_hidden_tc/MicroGridTestConfiguration_BC_BE_SSH_V2.xml @@ -178,7 +178,7 @@ true - 3 + 9 false @@ -186,7 +186,7 @@ false - 5 + 12 false diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java index dca16ba77ba..99ce0f673ba 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java @@ -363,6 +363,8 @@ static ComparisonResult ignoringNonEQ(Comparison comparison, ComparisonResult re return ComparisonResult.EQUAL; } else if (control != null && control.getLocalName().equals("targetQ")) { return ComparisonResult.EQUAL; + } else if (control != null && control.getLocalName().equals("tapPosition")) { + return ComparisonResult.EQUAL; } else if (comparison.getControlDetails().getXPath().contains("temporaryLimit")) { // If the control node is a temporary limit, the order depends on the name attribute, // this attribute is generated as a unique identifier in the EQ export to avoid duplicates in CGMES diff --git a/cgmes/cgmes-model/src/main/resources/CIM16.sparql b/cgmes/cgmes-model/src/main/resources/CIM16.sparql index e81bcb2a774..7df40e3b997 100644 --- a/cgmes/cgmes-model/src/main/resources/CIM16.sparql +++ b/cgmes/cgmes-model/src/main/resources/CIM16.sparql @@ -589,17 +589,6 @@ WHERE { ?RatioTapChanger cim:RatioTapChanger.RatioTapChangerTable ?RatioTapChangerTable } }} -OPTIONAL { GRAPH ?graphSSH { - ?RatioTapChanger - cim:TapChanger.controlEnabled ?tapChangerControlEnabled ; - cim:TapChanger.step ?step -}} -OPTIONAL { GRAPH ?graphSV { - ?SvTapStep - a cim:SvTapStep ; - cim:SvTapStep.TapChanger ?RatioTapChanger ; - cim:SvTapStep.position ?SVtapStep -}} } # query: ratioTapChangerTable @@ -671,19 +660,6 @@ WHERE { cim:TapChanger.TapChangerControl ?TapChangerControl } }} -OPTIONAL { GRAPH ?graphSSH { - # ??? FIXME Difference between TapChanger.controlEnabled and TapChangerControl.enabled ??? - # When controlEnabled is set to false there is no additional data - ?PhaseTapChanger - cim:TapChanger.controlEnabled ?tapChangerControlEnabled ; - cim:TapChanger.step ?step -}} -OPTIONAL { GRAPH ?graphSV { - ?SVTapStep - a cim:SvTapStep ; - cim:SvTapStep.TapChanger ?PhaseTapChanger ; - cim:SvTapStep.position ?SVtapStep -}} } # query: phaseTapChangerTable From 94099547819000f617e95b1cb6aca12920a99ed6 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 12 Dec 2024 16:26:00 +0100 Subject: [PATCH 39/54] Improve the management of properties associated with operational limits used in the update process Signed-off-by: marquesja1 --- .../elements/OperationalLimitConversion.java | 28 ++++++++----------- .../test/export/ExportXmlCompare.java | 2 +- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java index 720c5513b40..e40a87760fc 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java @@ -451,8 +451,8 @@ private void addTemporaryOperationalLimitPropertiesIfLimitHasBeenConsidered(bool private void addTemporaryOperationalLimitProperties(TPR temporaryPropertyNameData, String operationalLimitId, double value) { Objects.requireNonNull(loadingLimitsIdentifiable); - loadingLimitsIdentifiable.setProperty(getPropertyName(temporaryPropertyNameData), operationalLimitId); - loadingLimitsIdentifiable.setProperty(getPropertyName(operationalLimitId), String.valueOf(value)); + loadingLimitsIdentifiable.setProperty(getPropertyName(temporaryPropertyNameData, CgmesNames.OPERATIONAL_LIMIT), operationalLimitId); + loadingLimitsIdentifiable.setProperty(getPropertyName(temporaryPropertyNameData, CgmesNames.NORMAL_VALUE), String.valueOf(value)); } private void addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(boolean included, PR propertyNameData, String operationalLimitId, double value) { @@ -463,8 +463,8 @@ private void addPermanentOperationalLimitPropertiesIfLimitHasBeenConsidered(bool private void addPermanentOperationalLimitProperties(PR propertyNameData, String operationalLimitId, double value) { Objects.requireNonNull(loadingLimitsIdentifiable); - loadingLimitsIdentifiable.setProperty(getPropertyName(propertyNameData), operationalLimitId); - loadingLimitsIdentifiable.setProperty(getPropertyName(operationalLimitId), String.valueOf(value)); + loadingLimitsIdentifiable.setProperty(getPropertyName(propertyNameData, CgmesNames.OPERATIONAL_LIMIT), operationalLimitId); + loadingLimitsIdentifiable.setProperty(getPropertyName(propertyNameData, CgmesNames.NORMAL_VALUE), String.valueOf(value)); } private void notAssigned() { @@ -523,15 +523,15 @@ private static void updateLoadingLimits(PR propertyNameData, LoadingLimits loadi } private static double getValue(PR propertyNameData, Identifiable identifiable, double previousValue, Context context) { - String operationalLimitId = getOperationalLimitId(getPropertyName(propertyNameData), identifiable); + String operationalLimitId = getOperationalLimitId(getPropertyName(propertyNameData, CgmesNames.OPERATIONAL_LIMIT_SET), identifiable); return updatedValue(operationalLimitId, context) - .orElse(defaultValue(getNormalValue(getPropertyName(operationalLimitId), identifiable), previousValue, getDefaultValue(context))); + .orElse(defaultValue(getNormalValue(getPropertyName(propertyNameData, CgmesNames.NORMAL_VALUE), identifiable), previousValue, getDefaultValue(context))); } private static double getValue(TPR temporaryPropertyNameData, Identifiable identifiable, double previousValue, Context context) { - String operationalLimitId = getOperationalLimitId(getPropertyName(temporaryPropertyNameData), identifiable); + String operationalLimitId = getOperationalLimitId(getPropertyName(temporaryPropertyNameData, CgmesNames.OPERATIONAL_LIMIT_SET), identifiable); return updatedValue(operationalLimitId, context) - .orElse(defaultValue(getNormalValue(getPropertyName(operationalLimitId), identifiable), previousValue, getDefaultValue(context))); + .orElse(defaultValue(getNormalValue(getPropertyName(temporaryPropertyNameData, CgmesNames.NORMAL_VALUE), identifiable), previousValue, getDefaultValue(context))); } private static OptionalDouble updatedValue(String operationalLimitId, Context context) { @@ -550,16 +550,16 @@ private static double getNormalValue(String propertyName, Identifiable identi return Double.parseDouble(identifiable.getProperty(propertyName)); } - private static String getPropertyName(PR pr) { - return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT + "_" + private static String getPropertyName(PR pr, String tagProperty) { + return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + tagProperty + "_" + pr.operationalLimitSetId + "_" + pr.end + "_" + pr.limitSubclass + "_" + "patl"; } - private static String getPropertyName(TPR tpr) { - return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT + "_" + private static String getPropertyName(TPR tpr, String tagProperty) { + return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + tagProperty + "_" + tpr.operationalLimitSetId + "_" + tpr.end + "_" + tpr.limitSubclass + "_" @@ -567,10 +567,6 @@ private static String getPropertyName(TPR tpr) { + tpr.duration; } - private static String getPropertyName(String operationalLimitId) { - return Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "normalValue" + "_" + operationalLimitId; - } - protected static double defaultValue(double normalValue, double previousValue, Conversion.Config.DefaultValue defaultValue) { return switch (defaultValue) { case EQ, DEFAULT, EMPTY -> normalValue; diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java index 99ce0f673ba..c6f9432794e 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java @@ -364,7 +364,7 @@ static ComparisonResult ignoringNonEQ(Comparison comparison, ComparisonResult re } else if (control != null && control.getLocalName().equals("targetQ")) { return ComparisonResult.EQUAL; } else if (control != null && control.getLocalName().equals("tapPosition")) { - return ComparisonResult.EQUAL; + return ComparisonResult.EQUAL; } else if (comparison.getControlDetails().getXPath().contains("temporaryLimit")) { // If the control node is a temporary limit, the order depends on the name attribute, // this attribute is generated as a unique identifier in the EQ export to avoid duplicates in CGMES From 7d6b4bea4a572938b109b9ebb63e9afef9943941 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 2 Jan 2025 17:56:30 +0100 Subject: [PATCH 40/54] remove unused update queries Signed-off-by: marquesja1 --- .../src/main/resources/CIM16-update.sparql | 134 ------------------ 1 file changed, 134 deletions(-) diff --git a/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql b/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql index 1df6a422d0f..2e17f27c15f 100644 --- a/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql +++ b/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql @@ -155,92 +155,6 @@ SELECT * cim:EnergySource.reactivePower ?q } -# query: shuntCompensators -SELECT * -{ - { - ?ShuntCompensator a ?type ; - VALUES ?type { cim:LinearShuntCompensator cim:NonlinearShuntCompensator } . - } - OPTIONAL { - ?ShuntCompensator - cim:ShuntCompensator.sections ?SSHsections ; - cim:RegulatingCondEq.controlEnabled ?controlEnabled - } - OPTIONAL { - ?SvShuntCompensatorSections - a cim:SvShuntCompensatorSections ; - cim:SvShuntCompensatorSections.ShuntCompensator ?ShuntCompensator ; - cim:SvShuntCompensatorSections.sections ?SVsections - } -} - -# FIXME(Luma) we do not have access to the type when reading update only files, -# we cannot differentiate between generators and condensers -# this means that we may not deprecate synchronousMachines in the end, -# or we could make the new query "allSynchronousMachines" - -# query: allSynchronousMachines -SELECT * -{ - ?SynchronousMachine a cim:SynchronousMachine - # FIXME(Luma) p in a separate optional block because condersers could not define it - OPTIONAL { ?SynchronousMachine cim:RotatingMachine.p ?p } - OPTIONAL { - ?SynchronousMachine - cim:RotatingMachine.q ?q ; - cim:SynchronousMachine.referencePriority ?referencePriority ; - cim:SynchronousMachine.operatingMode ?operatingMode ; - cim:RegulatingCondEq.controlEnabled ?controlEnabled . - # For condensers givin p is optional, - } -} - -# query: generatingUnits -SELECT * -{ - ?GeneratingUnit - a ?generatingUnitType ; - cim:GeneratingUnit.normalPF ?normalPF -} - -# query: equivalentInjections -SELECT * -{ - ?EquivalentInjection a cim:EquivalentInjection ; - cim:EquivalentInjection.p ?p ; - cim:EquivalentInjection.q ?q . - OPTIONAL { ?EquivalentInjection cim:EquivalentInjection.regulationStatus ?regulationStatus } - OPTIONAL { ?EquivalentInjection cim:EquivalentInjection.regulationTarget ?regulationTarget } -} - -# query: svInjections -SELECT ?SvInjection ?TopologicalNode ?pInjection ?qInjection (MIN(?ConnectivityNode) AS ?ConnectivityNode) -{ - ?SvInjection a cim:SvInjection ; - cim:SvInjection.TopologicalNode ?TopologicalNode ; - cim:SvInjection.pInjection ?pInjection . - OPTIONAL { ?SvInjection cim:SvInjection.qInjection ?qInjection } - OPTIONAL { ?ConnectivityNode cim:ConnectivityNode.TopologicalNode ?TopologicalNode } -}GROUP BY ?SvInjection ?TopologicalNode ?pInjection ?qInjection - -# query: externalNetworkInjections -SELECT * -{ - ?ExternalNetworkInjection a cim:ExternalNetworkInjection ; - cim:ExternalNetworkInjection.p ?p ; - cim:ExternalNetworkInjection.q ?q ; - cim:RegulatingCondEq.controlEnabled ?controlEnabled -} - -# query: staticVarCompensators -SELECT * -{ - ?StaticVarCompensator a cim:StaticVarCompensator ; - cim:StaticVarCompensator.q ?q ; - cim:RegulatingCondEq.controlEnabled ?controlEnabled -} - # query: asynchronousMachines SELECT * { @@ -251,54 +165,6 @@ SELECT * cim:RegulatingCondEq.controlEnabled ?controlEnabled } -# query: controlAreas -SELECT * -{ - ?ControlArea a cim:ControlArea ; - cim:ControlArea.netInterchange ?netInterchange . - OPTIONAL { ?ControlArea cim:ControlArea.pTolerance ?pTolerance } -} - -# query: acDcConverters -SELECT * -{ - ?ACDCConverter a ?type . - VALUES ?type { cim:ACDCConverter cim:CsConverter cim:VsConverter } - ?ACDCConverter - cim:ACDCConverter.targetPpcc ?targetPpcc ; - cim:ACDCConverter.p ?p ; - cim:ACDCConverter.q ?q . - # From SV, for all converters - OPTIONAL { - ?ACDCConverter cim:ACDCConverter.poleLossP ?poleLossP - } - # For Current Source Converter - OPTIONAL { - ?ACDCConverter a cim:CsConverter ; - cim:CsConverter.operatingMode ?operatingMode ; - cim:CsConverter.pPccControl ?controlMode . - OPTIONAL { ?ACDCConverter cim:ACDCConverter.targetUdc ?targetUdc } - } - # For Voltage Source Converter - OPTIONAL { - ?ACDCConverter a cim:VsConverter ; - cim:VsConverter.qPccControl ?qPccControl ; - cim:VsConverter.pPccControl ?pPccControl . - OPTIONAL { ?ACDCConverter cim:VsConverter.targetQpcc ?targetQpcc } - OPTIONAL { ?ACDCConverter cim:VsConverter.targetUpcc ?targetUpcc } - } -} - -# query: dcTerminals -SELECT * -{ - ?DCTerminal a cim:DCTerminal ; - cim:ACDCTerminal.connected ?connected - OPTIONAL { - ?DCTerminal cim:DCBaseTerminal.DCTopologicalNode ?DCTopologicalNode . - } -} - # query: boundaryNodes # All pairs (Connectiviy Node, Topological Node) from instance files that have boundary profile and attribute boundaryPoint set to true # We expect all Connectivity Nodes have 1 and only one corresponding TopologicalNode From 84655ebe8af471b04f1985a41e6bb44e5704fee6 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 9 Jan 2025 15:31:27 +0100 Subject: [PATCH 41/54] Update generators Signed-off-by: marquesja1 --- .../com/powsybl/cgmes/conversion/Context.java | 13 ++ .../powsybl/cgmes/conversion/Conversion.java | 7 +- .../conversion/RegulatingControlMapping.java | 4 +- ...RegulatingControlMappingForGenerators.java | 44 ++---- .../com/powsybl/cgmes/conversion/Update.java | 27 +++- ...AbstractReactiveLimitsOwnerConversion.java | 120 +++++++++++++++- .../EquivalentInjectionConversion.java | 78 +++++++--- .../ExternalNetworkInjectionConversion.java | 31 ++-- .../SynchronousMachineConversion.java | 110 ++++++++++----- .../conversion/test/GeneratorUpdateTest.java | 133 ++++++++++++++++++ .../cgmes/conversion/test/LoadUpdateTest.java | 1 - .../test/export/EquipmentExportTest.java | 4 + .../test/export/ExportXmlCompare.java | 2 +- ...icroGridBaseCaseBE-invalid-voltage-bus.txt | 1 + .../microGridBaseCaseBE-target-deadband.txt | 1 + .../functional-logs/microGridBaseCaseBE.txt | 1 + .../functional-logs/miniGridNodeBreaker.txt | 1 + .../update/generator/generator_EQ.xml | 130 +++++++++++++++++ .../update/generator/generator_SSH.xml | 52 +++++++ .../update/generator/generator_SSH_1.xml | 52 +++++++ .../com/powsybl/cgmes/model/CgmesModel.java | 7 + .../com/powsybl/cgmes/model/CgmesNames.java | 7 + .../cgmes/model/InMemoryCgmesModel.java | 7 + .../triplestore/CgmesModelTripleStore.java | 10 ++ .../src/main/resources/CIM14-update.sparql | 27 ++++ .../src/main/resources/CIM16-update.sparql | 50 ++++++- .../src/main/resources/CIM16.sparql | 25 ---- .../RemoteReactivePowerControlAdderImpl.java | 2 +- 28 files changed, 811 insertions(+), 136 deletions(-) create mode 100644 cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/GeneratorUpdateTest.java create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH.xml create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH_1.xml diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java index e62b387e00c..b180f12011d 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java @@ -67,6 +67,7 @@ public Context(CgmesModel cgmes, Config config, Network network, ReportNode repo cgmesTerminals = new HashMap<>(); regulatingControls = new HashMap<>(); operationalLimits = new HashMap<>(); + generatingUnits = new HashMap<>(); } public CgmesModel cgmes() { @@ -247,6 +248,17 @@ public PropertyBag operationalLimit(String id) { return operationalLimits.get(id); } + public void loadGeneratingUnits() { + cgmes.generatingUnits().forEach(generatingUnit -> { + String id = generatingUnit.getId(CgmesNames.GENERATING_UNIT); + generatingUnits.put(id, generatingUnit); + }); + } + + public PropertyBag generatingUnit(String id) { + return generatingUnits.get(id); + } + // Handling issues found during conversion public ReportNode getReportNode() { @@ -363,6 +375,7 @@ private static void logIssue(ConversionIssueCategory category, String what, Supp private final Map cgmesTerminals; private final Map regulatingControls; private final Map operationalLimits; + private final Map generatingUnits; private static final Logger LOG = LoggerFactory.getLogger(Context.class); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java index 31ebe1bd853..df2257c3d87 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java @@ -37,8 +37,7 @@ import java.util.stream.Stream; import static com.powsybl.cgmes.conversion.Conversion.Config.StateProfile.SSH; -import static com.powsybl.cgmes.conversion.Update.updateLoads; -import static com.powsybl.cgmes.conversion.Update.updateTransformers; +import static com.powsybl.cgmes.conversion.Update.*; import static java.util.stream.Collectors.groupingBy; /** @@ -332,6 +331,7 @@ private void update(Network network, Context updateContext, ReportNode reportNod } updateLoads(network, cgmes, updateContext); + updateGenerators(network, cgmes, updateContext); updateTransformers(network, updateContext); completeVoltagesAndAngles(network); @@ -551,6 +551,7 @@ private Context createUpdateContext(Network network, ReportNode reportNode) { context.loadPhaseTapChangers(); context.loadRegulatingControls(); context.loadOperationalLimits(); + context.loadGeneratingUnits(); return context; } @@ -1171,7 +1172,7 @@ public Config setCreateFictitiousVoltageLevelsForEveryNode(boolean b) { private double missingPermanentLimitPercentage = 100; private boolean createFictitiousVoltageLevelsForEveryNode = true; private static final boolean UPDATE_TERMINAL_CONNECTION_IN_NODE_BREAKER_VOLTAGE_LEVEL = false; - private final List updateDefaultValuesPriority = List.of(DefaultValue.EQ, DefaultValue.EMPTY); + private final List updateDefaultValuesPriority = List.of(DefaultValue.EQ, DefaultValue.DEFAULT, DefaultValue.EMPTY); } private final CgmesModel cgmes; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMapping.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMapping.java index fb84422ce75..e681534893a 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMapping.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMapping.java @@ -126,11 +126,11 @@ void setAllRegulatingControls(Network network) { cachedRegulatingControls.clear(); } - static boolean isControlModeVoltage(String controlMode) { + public static boolean isControlModeVoltage(String controlMode) { return controlMode != null && controlMode.endsWith(VOLTAGE); } - static boolean isControlModeReactivePower(String controlMode) { + public static boolean isControlModeReactivePower(String controlMode) { return controlMode != null && controlMode.toLowerCase().endsWith("reactivepower"); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForGenerators.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForGenerators.java index da03e69c7ea..92c5d9d8d9f 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForGenerators.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForGenerators.java @@ -10,6 +10,7 @@ import com.powsybl.cgmes.conversion.RegulatingControlMapping.RegulatingControl; import com.powsybl.cgmes.conversion.RegulatingTerminalMapper.TerminalAndSign; import com.powsybl.cgmes.model.CgmesModelException; +import com.powsybl.cgmes.model.CgmesNames; import com.powsybl.iidm.network.Generator; import com.powsybl.iidm.network.GeneratorAdder; import com.powsybl.iidm.network.Network; @@ -53,7 +54,6 @@ public void add(String generatorId, PropertyBag sm) { CgmesRegulatingControlForGenerator rd = new CgmesRegulatingControlForGenerator(); rd.regulatingControlId = cgmesRegulatingControlId; rd.qPercent = qPercent; - rd.controlEnabled = sm.asBoolean("controlEnabled", false); mapping.put(generatorId, rd); } @@ -85,38 +85,23 @@ private void apply(Generator gen, CgmesRegulatingControlForGenerator rc) { boolean okSet = false; if (RegulatingControlMapping.isControlModeVoltage(control.mode)) { - okSet = setRegulatingControlVoltage(controlId, control, rc.qPercent, rc.controlEnabled, gen); + okSet = setRegulatingControlVoltage(controlId, control, rc.qPercent, gen); } else if (RegulatingControlMapping.isControlModeReactivePower(control.mode)) { - okSet = setRegulatingControlReactivePower(controlId, control, rc.qPercent, rc.controlEnabled, gen); + okSet = setRegulatingControlReactivePower(controlId, control, rc.qPercent, gen); } else { context.ignored(control.mode, "Unsupported regulation mode for generator " + gen.getId()); } control.setCorrectlySet(okSet); } - private boolean setRegulatingControlVoltage(String controlId, - RegulatingControl control, double qPercent, boolean eqControlEnabled, Generator gen) { + private boolean setRegulatingControlVoltage(String controlId, RegulatingControl control, double qPercent, Generator gen) { // Take default terminal if it has not been defined in CGMES file (it is never null) Terminal regulatingTerminal = RegulatingTerminalMapper .mapForVoltageControl(control.cgmesTerminal, context) .orElse(gen.getTerminal()); - double targetV; - if (control.targetValue <= 0.0 || Double.isNaN(control.targetValue)) { - targetV = regulatingTerminal.getVoltageLevel().getNominalV(); - regulatingTerminal = gen.getTerminal(); - context.fixed(controlId, "Invalid value for regulating target value. Regulation considered as local.", control.targetValue, targetV); - } else { - targetV = control.targetValue; - } - - // Regulating control is enabled AND this equipment participates in regulating control - boolean voltageRegulatorOn = control.enabled && eqControlEnabled; - - gen.setRegulatingTerminal(regulatingTerminal) - .setTargetV(targetV) - .setVoltageRegulatorOn(voltageRegulatorOn); + gen.setRegulatingTerminal(regulatingTerminal); // add qPercent as an extension if (!Double.isNaN(qPercent)) { @@ -125,11 +110,12 @@ private boolean setRegulatingControlVoltage(String controlId, .add(); } gen.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "RegulatingControl", controlId); + gen.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "mode", control.mode); return true; } - private boolean setRegulatingControlReactivePower(String controlId, RegulatingControl control, double qPercent, boolean eqControlEnabled, Generator gen) { + private boolean setRegulatingControlReactivePower(String controlId, RegulatingControl control, double qPercent, Generator gen) { // Ignore control if the terminal is not mapped. TerminalAndSign mappedRegulatingTerminal = RegulatingTerminalMapper .mapForFlowControl(control.cgmesTerminal, context) @@ -140,18 +126,9 @@ private boolean setRegulatingControlReactivePower(String controlId, RegulatingCo return false; } - double targetQ; - if (Double.isNaN(control.targetValue)) { - context.fixed(controlId, "Invalid value for regulating target value. Real flows are considered targets."); - return false; - } else { - targetQ = control.targetValue; - } - gen.newExtension(RemoteReactivePowerControlAdder.class) - .withTargetQ(targetQ * mappedRegulatingTerminal.getSign()) .withRegulatingTerminal(mappedRegulatingTerminal.getTerminal()) - .withEnabled(control.enabled && eqControlEnabled) + .withEnabled(false) .add(); // add qPercent as an extension @@ -161,7 +138,9 @@ private boolean setRegulatingControlReactivePower(String controlId, RegulatingCo .add(); } - gen.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "RegulatingControl", controlId); + gen.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.REGULATING_CONTROL, controlId); + gen.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.MODE, control.mode); + gen.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL_SIGN, String.valueOf(mappedRegulatingTerminal.getSign())); return true; } @@ -169,7 +148,6 @@ private boolean setRegulatingControlReactivePower(String controlId, RegulatingCo private static final class CgmesRegulatingControlForGenerator { String regulatingControlId; double qPercent; - boolean controlEnabled; } private final RegulatingControlMapping parent; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java index ddd279ed313..38c744ce2be 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java @@ -7,9 +7,7 @@ */ package com.powsybl.cgmes.conversion; -import com.powsybl.cgmes.conversion.elements.AsynchronousMachineConversion; -import com.powsybl.cgmes.conversion.elements.EnergyConsumerConversion; -import com.powsybl.cgmes.conversion.elements.EnergySourceConversion; +import com.powsybl.cgmes.conversion.elements.*; import com.powsybl.cgmes.conversion.elements.transformers.ThreeWindingsTransformerConversion; import com.powsybl.cgmes.conversion.elements.transformers.TwoWindingsTransformerConversion; import com.powsybl.cgmes.model.CgmesModel; @@ -57,6 +55,29 @@ private static void updateLoad(Load load, PropertyBag cgmesData, Context context } } + static void updateGenerators(Network network, CgmesModel cgmes, Context context) { + context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.GENERATOR.name())); + + Map equipmentIdPropertyBag = new HashMap<>(); + addPropertyBags(cgmes.synchronousMachinesForUpdate(), CgmesNames.SYNCHRONOUS_MACHINE, equipmentIdPropertyBag); + addPropertyBags(cgmes.equivalentInjections(), CgmesNames.EQUIVALENT_INJECTION, equipmentIdPropertyBag); + addPropertyBags(cgmes.externalNetworkInjections(), CgmesNames.EXTERNAL_NETWORK_INJECTION, equipmentIdPropertyBag); + + network.getGenerators().forEach(generator -> updateGenerator(generator, getPropertyBag(generator.getId(), equipmentIdPropertyBag), context)); + context.popReportNode(); + } + + private static void updateGenerator(Generator generator, PropertyBag cgmesData, Context context) { + String originalClass = generator.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS); + + switch (originalClass) { + case CgmesNames.SYNCHRONOUS_MACHINE -> SynchronousMachineConversion.update(generator, cgmesData, context); + case CgmesNames.EQUIVALENT_INJECTION -> EquivalentInjectionConversion.update(generator, cgmesData, context); + case CgmesNames.EXTERNAL_NETWORK_INJECTION -> ExternalNetworkInjectionConversion.update(generator, cgmesData, context); + default -> throw new ConversionException("Unexpected originalClass " + originalClass + " for Generator: " + generator.getId()); + } + } + static void updateTransformers(Network network, Context context) { context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.TWO_WINDINGS_TRANSFORMER.name())); network.getTwoWindingsTransformers().forEach(t2w -> TwoWindingsTransformerConversion.update(t2w, context)); diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractReactiveLimitsOwnerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractReactiveLimitsOwnerConversion.java index cc942b4e0fc..bdd41fcf3bc 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractReactiveLimitsOwnerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractReactiveLimitsOwnerConversion.java @@ -10,16 +10,25 @@ import com.google.common.collect.Range; import com.powsybl.cgmes.conversion.Context; -import com.powsybl.iidm.network.GeneratorAdder; -import com.powsybl.iidm.network.ReactiveCapabilityCurveAdder; -import com.powsybl.iidm.network.ReactiveLimitsHolder; +import com.powsybl.cgmes.conversion.Conversion; +import com.powsybl.cgmes.conversion.RegulatingControlMapping; +import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.extensions.RemoteReactivePowerControl; import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Supplier; +import static com.powsybl.cgmes.conversion.CgmesReports.badVoltageTargetValueRegulatingControlReport; +import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; + /** * @author Luma Zamarreño {@literal } */ @@ -139,4 +148,109 @@ protected void setMinPMaxP(GeneratorAdder adder, double minP, double maxP) { } adder.setMinP(minP).setMaxP(maxP); } + + protected static void updateRegulatingControl(Generator generator, boolean controlEnabled, Context context) { + String controlId = generator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.REGULATING_CONTROL); + String mode = generator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.MODE); + int terminalSign = findTerminalSign(generator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL_SIGN)); + + updateRegulatingControl(generator, new RC(controlEnabled, mode, terminalSign), controlId, context); + } + + private static int findTerminalSign(String terminalSign) { + return terminalSign != null ? Integer.parseInt(terminalSign) : 1; + } + + private static void updateRegulatingControl(Generator generator, RC rc, String regulatingControlId, Context context) { + if (regulatingControlId == null) { + LOG.trace("Regulating control Id not present for generator {}", generator.getId()); + return; + } + + if (RegulatingControlMapping.isControlModeVoltage(rc.mode)) { + updateRegulatingControlVoltage(regulatingControlId, rc, generator, context); + } else if (RegulatingControlMapping.isControlModeReactivePower(rc.mode)) { + updateRegulatingControlReactivePower(regulatingControlId, rc, generator, context); + } else { + context.ignored(rc.mode, "Unsupported regulation mode for generator " + generator.getId()); + } + } + + private static void updateRegulatingControlVoltage(String regulatingControlId, RC rc, Generator generator, Context context) { + Optional cgmesRegulatingControl = findCgmesRegulatingControl(regulatingControlId, context); + + double targetV = cgmesRegulatingControl.map(propertyBag -> findTargetV(propertyBag, generator, context)).orElseGet(() -> findDefaultTargetV(generator, context)); + boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, generator, context)).orElseGet(() -> findDefaultRegulatingOn(generator, context)); + + boolean validTargetV = isValidTargetV(targetV); + if (!validTargetV) { + context.invalid(regulatingControlId, "Regulating control has a bad target voltage " + targetV); + badVoltageTargetValueRegulatingControlReport(context.getReportNode(), regulatingControlId, targetV); + } + + // Regulating control is enabled AND this equipment participates in regulating control + generator.setTargetV(targetV).setVoltageRegulatorOn(regulatingOn && rc.controlEnabled && validTargetV); + } + + private static void updateRegulatingControlReactivePower(String regulatingControlId, RC rc, Generator generator, Context context) { + RemoteReactivePowerControl remoteReactivePowerControl = generator.getExtension(RemoteReactivePowerControl.class); + if (remoteReactivePowerControl == null || remoteReactivePowerControl.getRegulatingTerminal() == null) { + return; + } + Optional cgmesRegulatingControl = findCgmesRegulatingControl(regulatingControlId, context); + + double targetQ = cgmesRegulatingControl.map(propertyBag -> findTargetQ(propertyBag, rc.terminalSign)).orElseGet(() -> findDefaultTargetQ(remoteReactivePowerControl, context)); + boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, generator, context)).orElseGet(() -> findDefaultRegulatingOn(generator, context)); + + remoteReactivePowerControl.setTargetQ(targetQ).setEnabled(regulatingOn && rc.controlEnabled && isValidTargetQ(targetQ)); + } + + private static double findTargetV(PropertyBag regulatingControl, Generator generator, Context context) { + double targetV = regulatingControl.asDouble("targetValue"); + return isValidTargetV(targetV) ? targetV : findDefaultTargetV(generator, context); + } + + private static double findDefaultTargetV(Generator generator, Context context) { + double defaultTargetV = generator.getRegulatingTerminal() != null + ? generator.getRegulatingTerminal().getVoltageLevel().getNominalV() + : generator.getTerminal().getVoltageLevel().getNominalV(); + return defaultValue(Double.NaN, generator.getTargetV(), defaultTargetV, Double.NaN, getDefaultValueSelector(context)); + } + + private static boolean findRegulatingOn(PropertyBag regulatingControl, Generator generator, Context context) { + return regulatingControl.asBoolean("enabled").orElse(findDefaultRegulatingOn(generator, context)); + } + + private static boolean findDefaultRegulatingOn(Generator generator, Context context) { + return defaultValue(false, generator.isVoltageRegulatorOn(), false, false, getDefaultValueSelector(context)); + } + + private static boolean isValidTargetV(double targetV) { + return Double.isFinite(targetV) && targetV > 0.0; + } + + private static double findTargetQ(PropertyBag regulatingControl, int terminalSign) { + return regulatingControl.asDouble("targetValue") * terminalSign; + } + + private static double findDefaultTargetQ(RemoteReactivePowerControl remoteReactivePowerControl, Context context) { + return defaultValue(Double.NaN, remoteReactivePowerControl.getTargetQ(), Double.NaN, Double.NaN, getDefaultValueSelector(context)); + } + + private static boolean isValidTargetQ(double targetValue) { + return Double.isFinite(targetValue); + } + + private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { + return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); + } + + private static Optional findCgmesRegulatingControl(String regulatingControlId, Context context) { + return regulatingControlId != null ? Optional.ofNullable(context.regulatingControl(regulatingControlId)) : Optional.empty(); + } + + private record RC(boolean controlEnabled, String mode, int terminalSign) { + } + + private static final Logger LOG = LoggerFactory.getLogger(AbstractReactiveLimitsOwnerConversion.class); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EquivalentInjectionConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EquivalentInjectionConversion.java index 1b23aeec791..385555180d6 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EquivalentInjectionConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EquivalentInjectionConversion.java @@ -18,13 +18,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; + +import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; + /** * @author Luma Zamarreño {@literal } */ public class EquivalentInjectionConversion extends AbstractReactiveLimitsOwnerConversion { - private static final String REGULATION_TARGET = "regulationTarget"; - public EquivalentInjectionConversion(PropertyBag ei, Context context) { super(CgmesNames.EQUIVALENT_INJECTION, ei, context); } @@ -99,28 +101,24 @@ public DanglingLine convertOverDanglingLine(DanglingLineAdder adder, PowerFlow f private void convertToGenerator() { double minP = p.asDouble("minP", -Double.MAX_VALUE); double maxP = p.asDouble("maxP", Double.MAX_VALUE); - EnergySource energySource = EnergySource.OTHER; - Regulation regulation = getRegulation(); GeneratorAdder adder = voltageLevel().newGenerator(); setMinPMaxP(adder, minP, maxP); - adder.setVoltageRegulatorOn(regulation.status) - .setTargetP(regulation.targetP) - .setTargetQ(regulation.targetQ) - .setTargetV(regulation.targetV) - .setEnergySource(energySource); + adder.setEnergySource(EnergySource.OTHER); identify(adder); - connect(adder); + connectWithOnlyEq(adder); Generator g = adder.add(); addAliasesAndProperties(g); - convertedTerminals(g.getTerminal()); + convertedTerminalsWithOnlyEq(g.getTerminal()); convertReactiveLimits(g); - addSpecificProperties(g); + addSpecificProperties(g, p); } - private static void addSpecificProperties(Generator generator) { + private static void addSpecificProperties(Generator generator, PropertyBag propertyBag) { generator.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.EQUIVALENT_INJECTION); + generator.setProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS + CgmesNames.REGULATION_CAPABILITY, + String.valueOf(propertyBag.asBoolean(CgmesNames.REGULATION_CAPABILITY, false))); } static class Regulation { @@ -133,16 +131,16 @@ static class Regulation { private Regulation getRegulation() { Regulation regulation = new Regulation(); - boolean regulationCapability = p.asBoolean("regulationCapability", false); - regulation.status = p.asBoolean("regulationStatus", false) && regulationCapability; - if (!p.containsKey("regulationStatus") || !p.containsKey(REGULATION_TARGET)) { + boolean regulationCapability = p.asBoolean(CgmesNames.REGULATION_CAPABILITY, false); + regulation.status = p.asBoolean(CgmesNames.REGULATION_STATUS, false) && regulationCapability; + if (!p.containsKey(CgmesNames.REGULATION_STATUS) || !p.containsKey(CgmesNames.REGULATION_TARGET)) { LOG.trace("Attributes regulationStatus or regulationTarget not present for equivalent injection {}. Voltage regulation is considered as off.", id); } regulation.status = regulation.status && terminalConnected(); regulation.targetV = Double.NaN; if (regulation.status) { - regulation.targetV = p.asDouble(REGULATION_TARGET); + regulation.targetV = p.asDouble(CgmesNames.REGULATION_TARGET); if (Double.isNaN(regulation.targetV) || regulation.targetV == 0) { missing("Valid target voltage value (voltage regulation is considered as off)"); regulation.status = false; @@ -160,5 +158,51 @@ private Regulation getRegulation() { return regulation; } + public static void update(Generator generator, PropertyBag cgmesData, Context context) { + updateTerminals(generator, context, generator.getTerminal()); + + boolean regulationCapability = Boolean.parseBoolean(generator.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS + CgmesNames.REGULATION_CAPABILITY)); + + double targetP = 0.0; + double targetQ = 0.0; + PowerFlow updatedPowerFlow = updatedPowerFlow(generator, cgmesData, context); + if (updatedPowerFlow.defined()) { + targetP = -updatedPowerFlow.p(); + targetQ = -updatedPowerFlow.q(); + } + + double targetV = findTargetV(cgmesData, generator, context); + boolean regulatingOn = findRegulatingOn(cgmesData, generator, context); + + generator.setTargetP(targetP) + .setTargetQ(targetQ) + .setTargetV(targetV) + .setVoltageRegulatorOn(regulatingOn && regulationCapability && isValidTargetV(targetV)); + } + + private static double findTargetV(PropertyBag cgmesData, Generator generator, Context context) { + return cgmesData.containsKey(CgmesNames.REGULATION_TARGET) ? cgmesData.asDouble(CgmesNames.REGULATION_TARGET) : findDefaultTargetV(generator, context); + } + + private static double findDefaultTargetV(Generator generator, Context context) { + return defaultValue(Double.NaN, generator.getTargetV(), Double.NaN, Double.NaN, getDefaultValueSelector(context)); + } + + private static boolean findRegulatingOn(PropertyBag cgmesData, Generator generator, Context context) { + return cgmesData.asBoolean(CgmesNames.REGULATION_STATUS).orElse(findDefaultRegulatingOn(generator, context)); + } + + private static boolean findDefaultRegulatingOn(Generator generator, Context context) { + return defaultValue(false, generator.isVoltageRegulatorOn(), false, false, getDefaultValueSelector(context)); + } + + private static boolean isValidTargetV(double targetV) { + return Double.isFinite(targetV) && targetV > 0.0; + } + + private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { + return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); + } + private static final Logger LOG = LoggerFactory.getLogger(EquivalentInjectionConversion.class); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/ExternalNetworkInjectionConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/ExternalNetworkInjectionConversion.java index 50f0507f676..866643fd83a 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/ExternalNetworkInjectionConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/ExternalNetworkInjectionConversion.java @@ -31,25 +31,16 @@ public ExternalNetworkInjectionConversion(PropertyBag sm, Context context) { public void convert() { double minP = p.asDouble("minP", -Double.MAX_VALUE); double maxP = p.asDouble("maxP", Double.MAX_VALUE); - double targetP = 0; - double targetQ = 0; - PowerFlow f = powerFlow(); - if (f.defined()) { - targetP = -f.p(); - targetQ = -f.q(); - } GeneratorAdder adder = voltageLevel().newGenerator(); RegulatingControlMappingForGenerators.initialize(adder); setMinPMaxP(adder, minP, maxP); - adder.setTargetP(targetP) - .setTargetQ(targetQ) - .setEnergySource(EnergySource.OTHER); + adder.setEnergySource(EnergySource.OTHER); identify(adder); - connect(adder); + connectWithOnlyEq(adder); Generator g = adder.add(); addAliasesAndProperties(g); - convertedTerminals(g.getTerminal()); + convertedTerminalsWithOnlyEq(g.getTerminal()); convertReactiveLimits(g); context.regulatingControlMapping().forGenerators().add(g.getId(), p); @@ -64,4 +55,20 @@ private static void addSpecificProperties(Generator generator, PropertyBag p) { generator.setProperty(Conversion.PROPERTY_CGMES_GOVERNOR_SCD, String.valueOf(governorSCD)); } } + + public static void update(Generator generator, PropertyBag cgmesData, Context context) { + updateTerminals(generator, context, generator.getTerminal()); + + double targetP = 0.0; + double targetQ = 0.0; + PowerFlow updatedPowerFlow = updatedPowerFlow(generator, cgmesData, context); + if (updatedPowerFlow.defined()) { + targetP = -updatedPowerFlow.p(); + targetQ = -updatedPowerFlow.q(); + } + generator.setTargetP(targetP).setTargetQ(targetQ); + + boolean controlEnabled = cgmesData.asBoolean("controlEnabled", false); + updateRegulatingControl(generator, controlEnabled, context); + } } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/SynchronousMachineConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/SynchronousMachineConversion.java index f161afed3e2..fee0176139a 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/SynchronousMachineConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/SynchronousMachineConversion.java @@ -14,11 +14,13 @@ import com.powsybl.cgmes.model.CgmesNames; import com.powsybl.cgmes.model.PowerFlow; import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.extensions.ActivePowerControl; import com.powsybl.iidm.network.extensions.ActivePowerControlAdder; -import com.powsybl.iidm.network.extensions.ReferencePriority; +import com.powsybl.iidm.network.extensions.ReferencePriority; import com.powsybl.triplestore.api.PropertyBag; import java.util.Arrays; +import java.util.Optional; /** * @author Luma Zamarreño {@literal } @@ -42,35 +44,20 @@ public void convert() { double maxP = p.asDouble("maxP", isCondenser ? 0 : Double.MAX_VALUE); double ratedS = p.asDouble("ratedS"); ratedS = ratedS > 0 ? ratedS : Double.NaN; - PowerFlow f = powerFlow(); - - // Default targetP from initial P defined in EQ GeneratingUnit. Removed since CGMES 3.0 - double targetP = p.asDouble("initialP", 0); - double targetQ = 0; - // Flow values may come from Terminal or Equipment (SSH RotatingMachine) - if (f.defined()) { - targetP = -f.p(); - targetQ = -f.q(); - } GeneratorAdder adder = voltageLevel().newGenerator(); RegulatingControlMappingForGenerators.initialize(adder); setMinPMaxP(adder, minP, maxP); - adder.setTargetP(targetP) - .setTargetQ(targetQ) - .setEnergySource(energySourceFromGeneratingUnitType()) + adder.setEnergySource(energySourceFromGeneratingUnitType()) .setRatedS(ratedS); identify(adder); - connect(adder); + connectWithOnlyEq(adder); adder.setCondenser(isCondenser); Generator g = adder.add(); addAliasesAndProperties(g); - convertedTerminals(g.getTerminal()); + convertedTerminalsWithOnlyEq(g.getTerminal()); convertReactiveLimits(g); - int referencePriority = p.asInt("referencePriority", 0); - if (referencePriority > 0) { - ReferencePriority.set(g, referencePriority); - } + if (!isCondenser) { convertGenerator(g); } @@ -92,26 +79,19 @@ private static void addSpecificProperties(Generator generator, PropertyBag p) { } private void convertGenerator(Generator g) { - double normalPF = p.asDouble("normalPF"); - if (!Double.isNaN(normalPF)) { - if (context.config().createActivePowerControlExtension()) { - g.newExtension(ActivePowerControlAdder.class) - .withParticipate(true) - .withParticipationFactor(normalPF) - .add(); - } else { - g.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "normalPF", String.valueOf(normalPF)); - } - } - String generatingUnit = p.getId("GeneratingUnit"); + String generatingUnit = p.getId(CgmesNames.GENERATING_UNIT); if (generatingUnit != null) { - g.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "GeneratingUnit", generatingUnit); + g.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.GENERATING_UNIT, generatingUnit); } - addSpecificGeneratingUnitProperties(g, p); } private static void addSpecificGeneratingUnitProperties(Generator generator, PropertyBag p) { + // Default targetP from initial P defined in EQ GeneratingUnit. Removed since CGMES 3.0 + String initialP = p.getLocal(CgmesNames.INITIAL_P); + if (initialP != null) { + generator.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.INITIAL_P, initialP); + } String hydroPlantStorageType = p.getLocal("hydroPlantStorageType"); if (hydroPlantStorageType != null) { generator.setProperty(Conversion.PROPERTY_HYDRO_PLANT_STORAGE_TYPE, hydroPlantStorageType.replace("HydroPlantStorageKind.", "")); @@ -147,4 +127,66 @@ private EnergySource energySourceFromGeneratingUnitType() { } return es; } + + public static void update(Generator generator, PropertyBag cgmesData, Context context) { + updateTerminals(generator, context, generator.getTerminal()); + + int referencePriority = cgmesData.asInt("referencePriority", 0); + if (referencePriority > 0) { + ReferencePriority.set(generator, referencePriority); + } + + double targetP = getInitialP(generator, 0.0); + double targetQ = 0.0; + PowerFlow updatedPowerFlow = updatedPowerFlow(generator, cgmesData, context); + if (updatedPowerFlow.defined()) { + targetP = -updatedPowerFlow.p(); + targetQ = -updatedPowerFlow.q(); + } + generator.setTargetP(targetP).setTargetQ(targetQ); + + String generatingUnitId = generator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.GENERATING_UNIT); + if (generatingUnitId != null) { + updateGeneratingUnit(generator, generatingUnitId, context); + } + + String operatingMode = cgmesData.getLocal("operatingMode"); + if (operatingMode != null) { + generator.setProperty(Conversion.PROPERTY_CGMES_SYNCHRONOUS_MACHINE_OPERATING_MODE, operatingMode.replace("SynchronousMachineOperatingMode.", "")); + } + boolean controlEnabled = cgmesData.asBoolean("controlEnabled", false); + updateRegulatingControl(generator, controlEnabled, context); + } + + private static double getInitialP(Generator generator, double defaultValue) { + String initialP = generator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.INITIAL_P); + return initialP != null ? Double.parseDouble(initialP) : defaultValue; + } + + private static void updateGeneratingUnit(Generator generator, String generatingUnitId, Context context) { + findCgmesGeneratingUnit(generatingUnitId, context).ifPresent(generatingUnit -> { + double normalPF = generatingUnit.asDouble(CgmesNames.NORMAL_PF); + if (!Double.isNaN(normalPF)) { + updateNormalPF(generator, normalPF, context); + } + }); + } + + private static Optional findCgmesGeneratingUnit(String generatingUnitId, Context context) { + return generatingUnitId != null ? Optional.ofNullable(context.generatingUnit(generatingUnitId)) : Optional.empty(); + } + + private static void updateNormalPF(Generator generator, double normalPF, Context context) { + ActivePowerControl activePowerControl = generator.getExtension(ActivePowerControl.class); + if (activePowerControl != null) { + activePowerControl.setParticipationFactor(normalPF); + } else if (context.config().createActivePowerControlExtension()) { + generator.newExtension(ActivePowerControlAdder.class) + .withParticipate(true) + .withParticipationFactor(normalPF) + .add(); + } else { + generator.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.NORMAL_PF, String.valueOf(normalPF)); + } + } } diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/GeneratorUpdateTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/GeneratorUpdateTest.java new file mode 100644 index 00000000000..30e20aa8e30 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/GeneratorUpdateTest.java @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.cgmes.conversion.test; + +import com.powsybl.cgmes.conversion.Conversion; +import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.iidm.network.Generator; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.extensions.ActivePowerControl; +import com.powsybl.iidm.network.extensions.ReferencePriority; +import org.junit.jupiter.api.Test; + +import static com.powsybl.cgmes.conversion.test.ConversionUtil.readCgmesResources; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Luma Zamarreño {@literal } + * @author José Antonio Marqués {@literal } + */ +class GeneratorUpdateTest { + + private static final String DIR = "/update/generator/"; + + @Test + void importEqTest() { + Network network = readCgmesResources(DIR, "generator_EQ.xml"); + assertEquals(3, network.getGeneratorCount()); + + Generator synchronousMachine = network.getGenerator("SynchronousMachine"); + assertTrue(checkEq(synchronousMachine)); + + Generator externalNetworkInjection = network.getGenerator("ExternalNetworkInjection"); + assertTrue(checkEq(externalNetworkInjection)); + + Generator equivalentInjection = network.getGenerator("EquivalentInjection"); + assertTrue(checkEq(equivalentInjection)); + } + + @Test + void importEqAndSshTogetherTest() { + Network network = readCgmesResources(DIR, "generator_EQ.xml", "generator_SSH.xml"); + assertEquals(3, network.getGeneratorCount()); + + Generator synchronousMachine = network.getGenerator("SynchronousMachine"); + assertTrue(checkSsh(synchronousMachine, 160.0, 0.0, 131.34, true, 0.0, 0)); + + Generator externalNetworkInjection = network.getGenerator("ExternalNetworkInjection"); + assertTrue(checkSsh(externalNetworkInjection, -0.0, -0.0, Double.NaN, false, 0.0, 0)); + + Generator equivalentInjection = network.getGenerator("EquivalentInjection"); + assertTrue(checkSsh(equivalentInjection, -184.0, 0.0, Double.NaN, false, 0.0, 0)); + } + + @Test + void importEqAndSshSeparatelyTest() { + Network network = readCgmesResources(DIR, "generator_EQ.xml"); + assertEquals(3, network.getGeneratorCount()); + + Generator synchronousMachine = network.getGenerator("SynchronousMachine"); + assertTrue(checkEq(synchronousMachine)); + Generator externalNetworkInjection = network.getGenerator("ExternalNetworkInjection"); + assertTrue(checkEq(externalNetworkInjection)); + Generator equivalentInjection = network.getGenerator("EquivalentInjection"); + assertTrue(checkEq(equivalentInjection)); + + readCgmesResources(network, DIR, "generator_SSH.xml"); + + assertTrue(checkSsh(synchronousMachine, 160.0, 0.0, 131.34, true, 0.0, 0)); + assertTrue(checkSsh(externalNetworkInjection, -0.0, -0.0, Double.NaN, false, 0.0, 0)); + assertTrue(checkSsh(equivalentInjection, -184.0, 0.0, Double.NaN, false, 0.0, 0)); + } + + @Test + void importEqAndTwoSshsTest() { + Network network = readCgmesResources(DIR, "generator_EQ.xml"); + assertEquals(3, network.getGeneratorCount()); + + Generator synchronousMachine = network.getGenerator("SynchronousMachine"); + assertTrue(checkEq(synchronousMachine)); + Generator externalNetworkInjection = network.getGenerator("ExternalNetworkInjection"); + assertTrue(checkEq(externalNetworkInjection)); + Generator equivalentInjection = network.getGenerator("EquivalentInjection"); + assertTrue(checkEq(equivalentInjection)); + + readCgmesResources(network, DIR, "generator_SSH.xml"); + + assertTrue(checkSsh(synchronousMachine, 160.0, 0.0, 131.34, true, 0.0, 0)); + assertTrue(checkSsh(externalNetworkInjection, -0.0, -0.0, Double.NaN, false, 0.0, 0)); + assertTrue(checkSsh(equivalentInjection, -184.0, 0.0, Double.NaN, false, 0.0, 0)); + + readCgmesResources(network, DIR, "generator_SSH_1.xml"); + + assertTrue(checkSsh(synchronousMachine, 165.0, -5.0, 130.34, true, 0.9, 1)); + assertTrue(checkSsh(externalNetworkInjection, -10.0, -5.0, Double.NaN, false, 0.0, 0)); + assertTrue(checkSsh(equivalentInjection, -174.0, -5.0, Double.NaN, false, 0.0, 0)); + } + + private static boolean checkEq(Generator generator) { + assertNotNull(generator); + assertTrue(Double.isNaN(generator.getTargetP())); + assertTrue(Double.isNaN(generator.getTargetQ())); + assertTrue(Double.isNaN(generator.getTargetV())); + assertNotNull(generator.getRegulatingTerminal()); + assertFalse(generator.isVoltageRegulatorOn()); + + String originalClass = generator.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS); + if (originalClass.equals(CgmesNames.SYNCHRONOUS_MACHINE)) { + assertNotNull(generator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.MODE)); + } + return true; + } + + private static boolean checkSsh(Generator generator, double targetP, double targetQ, double targetV, boolean isRegulatingOn, double normalPF, int referencePriority) { + assertNotNull(generator); + double tol = 0.0000001; + assertEquals(targetP, generator.getTargetP(), tol); + assertEquals(targetQ, generator.getTargetQ(), tol); + assertEquals(targetV, generator.getTargetV(), tol); + assertEquals(isRegulatingOn, generator.isVoltageRegulatorOn()); + + ActivePowerControl activePowerControl = generator.getExtension(ActivePowerControl.class); + if (activePowerControl != null) { + assertEquals(normalPF, activePowerControl.getParticipationFactor()); + } + assertEquals(referencePriority, ReferencePriority.get(generator)); + return true; + } +} diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java index 8764cff19dd..9f41f68417e 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java @@ -107,7 +107,6 @@ private static boolean checkEq(Load load) { assertNotNull(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.P_FIXED)); assertNotNull(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.Q_FIXED)); } - load.getPropertyNames().forEach(pn -> System.err.printf("Property %s %s %n", pn, load.getProperty(pn))); return true; } diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/EquipmentExportTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/EquipmentExportTest.java index 5a9977b2829..4844a319766 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/EquipmentExportTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/EquipmentExportTest.java @@ -1771,6 +1771,8 @@ private void compareLoadingLimits(LoadingLimits expected, LoadingLimits actual) } private Network prepareNetworkForEQComparison(Network network) { + network.setMinimumAcceptableValidationLevel(ValidationLevel.EQUIPMENT); + network.getAliases().forEach(network::removeAlias); network.getIdentifiables().forEach(identifiable -> identifiable.getAliases().forEach(identifiable::removeAlias)); @@ -1796,6 +1798,8 @@ private Network prepareNetworkForEQComparison(Network network) { Generator generator = (Generator) identifiable; generator.setVoltageRegulatorOn(false); generator.setTargetV(Double.NaN); + generator.setTargetP(Double.NaN); + generator.setTargetQ(Double.NaN); generator.getTerminal().setP(0.0).setQ(0.0); } else if (identifiable instanceof StaticVarCompensator) { StaticVarCompensator staticVarCompensator = (StaticVarCompensator) identifiable; diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java index c6f9432794e..b5218e181a9 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java @@ -143,7 +143,7 @@ private static boolean isConsideredForEQNetwork(Attr attr) { // ratedS is optional for generators, // but we always export it to keep up with the quality of datasets rules. // So we do not enforce this attribute to be equal in the original and exported network - ignored = attr.getLocalName().equals("ratedS"); + ignored = attr.getLocalName().equals("ratedS") || attr.getLocalName().equals("bus"); } else { ignored = attr.getLocalName().contains("node") || attr.getLocalName().contains("bus") || attr.getLocalName().contains("Bus"); } diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt index 8e3c6bc636b..0217b9c21f8 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt @@ -40,6 +40,7 @@ Applying postprocessors. CGMES network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 is imported. Updating LOAD. + Updating GENERATOR. + Updating TWO_WINDINGS_TRANSFORMER. Equipment 955d9cd0-4a10-4031-b008-60c0dc340a07 has a regulating control with bad target value for voltage: 0.0. + Updating THREE_WINDINGS_TRANSFORMER. diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt index 6059b747502..1b8c5963728 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt @@ -38,6 +38,7 @@ Applying postprocessors. CGMES network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 is imported. Updating LOAD. + Updating GENERATOR. + Updating TWO_WINDINGS_TRANSFORMER. Equipment 955d9cd0-4a10-4031-b008-60c0dc340a07 has a regulating control with bad target value for voltage: 0.0. Equipment 955d9cd0-4a10-4031-b008-60c0dc340a07 has a regulating control with bad target deadband: -0.5. diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt index 985a4e7ba5f..64c371b7d3e 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt @@ -42,6 +42,7 @@ Applying postprocessors. CGMES network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 is imported. Updating LOAD. + Updating GENERATOR. + Updating TWO_WINDINGS_TRANSFORMER. Equipment 955d9cd0-4a10-4031-b008-60c0dc340a07 has a regulating control with bad target value for voltage: 0.0. + Updating THREE_WINDINGS_TRANSFORMER. diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt index cebe966fcf3..0686056653e 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt @@ -41,6 +41,7 @@ Applying postprocessors. CGMES network urn:uuid:239ecbd2-9a39-11e0-aa80-0800200c9a66 is imported. Updating LOAD. + Updating GENERATOR. Updating TWO_WINDINGS_TRANSFORMER. Updating THREE_WINDINGS_TRANSFORMER. Running validation checks on IIDM network urn:uuid:239ecbd2-9a39-11e0-aa80-0800200c9a66 diff --git a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml new file mode 100644 index 00000000000..110e49109d0 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml @@ -0,0 +1,130 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + All type of Generators + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/CoreEquipment-EU/3.0 + + + + GeographicalRegionTest + GeographicalRegionTest + + + SubGeographicalRegionTest + SubGeographicalRegionTest + + + + Substation1 + Substation1 + + + + BaseVoltage400 + Base Voltage Level 400kV + 400.0 kV + 400.0 + + + VoltageLevel1 + VoltageLevel1 + 420 + 380 + + + + + ConnectivityNode1 + Connectivity Node 1 + + + + + SynchronousMachine + + + 0 + 0 + 0 + 0 + + 0 + 0 + + + + SynchronousMachine_T + Terminal + 1 + + + + + + SynchronousMachine-RegulatingControl + + + + + SynchronousMachine-GeneratingUnit + + + 240 + 120 + 240 + + + SynchronousMachine-GeneratingUnit-FossilFuel + + + + + + EquivalentInjection + + 0 + 0 + 0 + false + 0 + 0 + 0 + + + EquivalentInjection_T + Terminal + 1 + + + + + + + ExternalNetworkInjection + + 0 + 16000 + 0.2 + 0.1 + 3.34865 + 0 + 0 + 0 + 0 + 88 + 66 + -88 + -66 + + + ExternalNetworkInjection_T + Terminal + 1 + + + + + diff --git a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH.xml b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH.xml new file mode 100644 index 00000000000..a1674bf4b7d --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH.xml @@ -0,0 +1,52 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + All type of Generators + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 + + + + true + true + -160 + 0 + + 0 + + + true + + + false + true + 131.34 + + + + true + 0 + + + + true + 184 + 0 + + + true + + + + true + true + 0 + 0 + 0 + + + true + + diff --git a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH_1.xml b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH_1.xml new file mode 100644 index 00000000000..91d2b426ed4 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH_1.xml @@ -0,0 +1,52 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + All type of Generators + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 + + + + true + true + -165 + 5 + + 1 + + + true + + + false + true + 130.34 + + + + true + 0.9 + + + + true + 174 + 5 + + + true + + + + true + true + 10 + 5 + 2 + + + true + + diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesModel.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesModel.java index 18db6ec5e96..6462355ae08 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesModel.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesModel.java @@ -74,6 +74,8 @@ default PropertyBags fullModels() { PropertyBags operationalLimits(); + PropertyBags generatingUnits(); + PropertyBags connectivityNodes(); PropertyBags topologicalNodes(); @@ -133,6 +135,11 @@ default PropertyBags synchronousMachines() { return synchronousMachinesGenerators(); } + // we need to query all sync machines to perform updates + default PropertyBags synchronousMachinesForUpdate() { + return new PropertyBags(); + } + default PropertyBags synchronousMachinesGenerators() { return new PropertyBags(); } diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java index 223bbf7d0c4..88ac9af13db 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java @@ -148,6 +148,13 @@ public final class CgmesNames { public static final String P_FIXED = "pFixed"; public static final String Q_FIXED = "qFixed"; public static final String TERMINAL_SIGN = "terminalSign"; + public static final String GENERATING_UNIT = "GeneratingUnit"; + public static final String NORMAL_PF = "normalPF"; + public static final String REGULATION_CAPABILITY = "regulationCapability"; + public static final String REGULATION_TARGET = "regulationTarget"; + public static final String REGULATION_STATUS = "regulationStatus"; + public static final String MODE = "mode"; + public static final String INITIAL_P = "initialP"; private CgmesNames() { } diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/InMemoryCgmesModel.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/InMemoryCgmesModel.java index 17f9d4844ec..31c4c5a16f1 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/InMemoryCgmesModel.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/InMemoryCgmesModel.java @@ -64,6 +64,7 @@ public final class InMemoryCgmesModel implements CgmesModel { private PropertyBags tieFlows; private PropertyBags numObjectsByType; private PropertyBags modelProfiles; + private PropertyBags generatingUnits; public InMemoryCgmesModel() { properties = new Properties(); @@ -106,6 +107,7 @@ public InMemoryCgmesModel() { tieFlows = new PropertyBags(); numObjectsByType = new PropertyBags(); modelProfiles = new PropertyBags(); + generatingUnits = new PropertyBags(); } @Override @@ -366,6 +368,11 @@ public PropertyBags operationalLimits() { return operationalLimits; } + @Override + public PropertyBags generatingUnits() { + return generatingUnits; + } + @Override public PropertyBags connectivityNodes() { return connectivityNodes; diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/triplestore/CgmesModelTripleStore.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/triplestore/CgmesModelTripleStore.java index bce21562b39..390bcd386cd 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/triplestore/CgmesModelTripleStore.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/triplestore/CgmesModelTripleStore.java @@ -432,6 +432,11 @@ public PropertyBags operationalLimits() { return namedQuery("operationalLimits"); } + @Override + public PropertyBags generatingUnits() { + return namedQuery("generatingUnits"); + } + @Override public PropertyBags busBarSections() { return namedQuery("busbarSections"); @@ -512,6 +517,11 @@ public PropertyBags staticVarCompensators() { return namedQuery("staticVarCompensators"); } + @Override + public PropertyBags synchronousMachinesForUpdate() { + return namedQuery("synchronousMachinesForUpdate"); + } + @Override public PropertyBags synchronousMachinesGenerators() { return namedQuery("synchronousMachinesGenerators"); diff --git a/cgmes/cgmes-model/src/main/resources/CIM14-update.sparql b/cgmes/cgmes-model/src/main/resources/CIM14-update.sparql index 27aec2cc5d3..e93f6f1ae1a 100644 --- a/cgmes/cgmes-model/src/main/resources/CIM14-update.sparql +++ b/cgmes/cgmes-model/src/main/resources/CIM14-update.sparql @@ -67,3 +67,30 @@ SELECT * LIMIT 1 } } + +# query: synchronousMachinesForUpdate +SELECT * +WHERE { +{ GRAPH ?graph { + ?SynchronousMachine + a cim:SynchronousMachine . + BIND ( "true" AS ?controlEnabled ) +}} +} + +# query: regulatingControls +SELECT * +WHERE { +{ GRAPH ?graph { + { + ?RegulatingControl a cim:RegulatingControl + } + UNION + { + ?RegulatingControl a cim:TapChangerControl + } + ?RegulatingControl + cim:RegulatingControl.targetValue ?targetValue . + BIND ( "true" AS ?enabled ) +}} +} diff --git a/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql b/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql index 2e17f27c15f..af1fd3d0a50 100644 --- a/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql +++ b/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql @@ -155,6 +155,54 @@ SELECT * cim:EnergySource.reactivePower ?q } +# FIXME(Luma) we do not have access to the type when reading update only files, +# we cannot differentiate between generators and condensers +# this means that we may not deprecate synchronousMachines in the end, +# or we could make the new query "synchronousMachinesForUpdate" + +# query: synchronousMachinesForUpdate +SELECT * +{ + ?SynchronousMachine a cim:SynchronousMachine + # FIXME(Luma) p in a separate optional block because condensers could not define it + OPTIONAL { ?SynchronousMachine cim:RotatingMachine.p ?p } + OPTIONAL { + ?SynchronousMachine + cim:RotatingMachine.q ?q ; + cim:SynchronousMachine.referencePriority ?referencePriority ; + cim:SynchronousMachine.operatingMode ?operatingMode ; + cim:RegulatingCondEq.controlEnabled ?controlEnabled . + # For condensers giving p is optional, + } +} + +# query: generatingUnits +SELECT * +{ + ?GeneratingUnit + a ?generatingUnitType ; + cim:GeneratingUnit.normalPF ?normalPF +} + +# query: equivalentInjections +SELECT * +{ + ?EquivalentInjection a cim:EquivalentInjection ; + cim:EquivalentInjection.p ?p ; + cim:EquivalentInjection.q ?q . + OPTIONAL { ?EquivalentInjection cim:EquivalentInjection.regulationStatus ?regulationStatus } + OPTIONAL { ?EquivalentInjection cim:EquivalentInjection.regulationTarget ?regulationTarget } +} + +# query: externalNetworkInjections +SELECT * +{ + ?ExternalNetworkInjection a cim:ExternalNetworkInjection ; + cim:ExternalNetworkInjection.p ?p ; + cim:ExternalNetworkInjection.q ?q ; + cim:RegulatingCondEq.controlEnabled ?controlEnabled +} + # query: asynchronousMachines SELECT * { @@ -166,7 +214,7 @@ SELECT * } # query: boundaryNodes -# All pairs (Connectiviy Node, Topological Node) from instance files that have boundary profile and attribute boundaryPoint set to true +# All pairs (Connectivity Node, Topological Node) from instance files that have boundary profile and attribute boundaryPoint set to true # We expect all Connectivity Nodes have 1 and only one corresponding TopologicalNode prefix md: SELECT * diff --git a/cgmes/cgmes-model/src/main/resources/CIM16.sparql b/cgmes/cgmes-model/src/main/resources/CIM16.sparql index 99698ef4abb..9fe0f3df039 100644 --- a/cgmes/cgmes-model/src/main/resources/CIM16.sparql +++ b/cgmes/cgmes-model/src/main/resources/CIM16.sparql @@ -845,17 +845,6 @@ WHERE { OPTIONAL { ?SynchronousMachine cim:RegulatingCondEq.RegulatingControl ?RegulatingControl } OPTIONAL { ?SynchronousMachine cim:SynchronousMachine.qPercent ?qPercent } }} -OPTIONAL { GRAPH ?graphSSH { - ?SynchronousMachine - cim:RotatingMachine.p ?p ; - cim:RotatingMachine.q ?q ; - cim:SynchronousMachine.referencePriority ?referencePriority ; - cim:SynchronousMachine.operatingMode ?operatingMode ; - cim:RegulatingCondEq.controlEnabled ?controlEnabled . -}} -OPTIONAL { GRAPH ?graphSSH2 { - ?GeneratingUnit cim:GeneratingUnit.normalPF ?normalPF -}} } # query: synchronousMachinesCondensers @@ -879,14 +868,6 @@ WHERE { OPTIONAL { ?SynchronousMachine cim:RegulatingCondEq.RegulatingControl ?RegulatingControl } OPTIONAL { ?SynchronousMachine cim:SynchronousMachine.qPercent ?qPercent } }} -OPTIONAL { GRAPH ?graphSSH { - ?SynchronousMachine - cim:RotatingMachine.q ?q ; - cim:SynchronousMachine.referencePriority ?referencePriority ; - cim:RegulatingCondEq.controlEnabled ?controlEnabled . - # For condensers, the p value is always 0 - BIND ( "0" AS ?p ) -}} } # query: equivalentInjections @@ -964,12 +945,6 @@ WHERE { OPTIONAL { ?ExternalNetworkInjection cim:ExternalNetworkInjection.maxQ ?maxQ } OPTIONAL { ?ExternalNetworkInjection cim:RegulatingCondEq.RegulatingControl ?RegulatingControl } }} -OPTIONAL { GRAPH ?graphSSH { - ?ExternalNetworkInjection - cim:ExternalNetworkInjection.p ?p ; - cim:ExternalNetworkInjection.q ?q ; - cim:RegulatingCondEq.controlEnabled ?controlEnabled -}} } # query: staticVarCompensators diff --git a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/RemoteReactivePowerControlAdderImpl.java b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/RemoteReactivePowerControlAdderImpl.java index cb840592d9a..07b0e3f9d04 100644 --- a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/RemoteReactivePowerControlAdderImpl.java +++ b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/RemoteReactivePowerControlAdderImpl.java @@ -31,7 +31,7 @@ protected RemoteReactivePowerControlAdderImpl(final Generator extendable) { @Override protected RemoteReactivePowerControl createExtension(final Generator extendable) { - if (Double.isNaN(targetQ)) { + if (Double.isNaN(targetQ) && enabled) { throw new PowsyblException("Reactive power target must be set"); } if (regulatingTerminal == null) { From 67af19c4af331c55c698fd3c2d04ca92862fa521 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Fri, 10 Jan 2025 07:50:25 +0100 Subject: [PATCH 42/54] targetV adjustment Signed-off-by: marquesja1 --- .../cgmes/conversion/test/GeneratorUpdateTest.java | 8 ++++---- .../src/test/resources/update/generator/generator_SSH.xml | 2 +- .../test/resources/update/generator/generator_SSH_1.xml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/GeneratorUpdateTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/GeneratorUpdateTest.java index 30e20aa8e30..21ad7a4d07f 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/GeneratorUpdateTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/GeneratorUpdateTest.java @@ -47,7 +47,7 @@ void importEqAndSshTogetherTest() { assertEquals(3, network.getGeneratorCount()); Generator synchronousMachine = network.getGenerator("SynchronousMachine"); - assertTrue(checkSsh(synchronousMachine, 160.0, 0.0, 131.34, true, 0.0, 0)); + assertTrue(checkSsh(synchronousMachine, 160.0, 0.0, 405.0, true, 0.0, 0)); Generator externalNetworkInjection = network.getGenerator("ExternalNetworkInjection"); assertTrue(checkSsh(externalNetworkInjection, -0.0, -0.0, Double.NaN, false, 0.0, 0)); @@ -70,7 +70,7 @@ void importEqAndSshSeparatelyTest() { readCgmesResources(network, DIR, "generator_SSH.xml"); - assertTrue(checkSsh(synchronousMachine, 160.0, 0.0, 131.34, true, 0.0, 0)); + assertTrue(checkSsh(synchronousMachine, 160.0, 0.0, 405.0, true, 0.0, 0)); assertTrue(checkSsh(externalNetworkInjection, -0.0, -0.0, Double.NaN, false, 0.0, 0)); assertTrue(checkSsh(equivalentInjection, -184.0, 0.0, Double.NaN, false, 0.0, 0)); } @@ -89,13 +89,13 @@ void importEqAndTwoSshsTest() { readCgmesResources(network, DIR, "generator_SSH.xml"); - assertTrue(checkSsh(synchronousMachine, 160.0, 0.0, 131.34, true, 0.0, 0)); + assertTrue(checkSsh(synchronousMachine, 160.0, 0.0, 405.0, true, 0.0, 0)); assertTrue(checkSsh(externalNetworkInjection, -0.0, -0.0, Double.NaN, false, 0.0, 0)); assertTrue(checkSsh(equivalentInjection, -184.0, 0.0, Double.NaN, false, 0.0, 0)); readCgmesResources(network, DIR, "generator_SSH_1.xml"); - assertTrue(checkSsh(synchronousMachine, 165.0, -5.0, 130.34, true, 0.9, 1)); + assertTrue(checkSsh(synchronousMachine, 165.0, -5.0, 410.0, true, 0.9, 1)); assertTrue(checkSsh(externalNetworkInjection, -10.0, -5.0, Double.NaN, false, 0.0, 0)); assertTrue(checkSsh(equivalentInjection, -174.0, -5.0, Double.NaN, false, 0.0, 0)); } diff --git a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH.xml b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH.xml index a1674bf4b7d..2f10c4ce23a 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH.xml @@ -22,7 +22,7 @@ false true - 131.34 + 405.0 diff --git a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH_1.xml b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH_1.xml index 91d2b426ed4..1b7fea01163 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH_1.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH_1.xml @@ -22,7 +22,7 @@ false true - 130.34 + 410.0 From 876d15bc227d1afb5d3c068df2a53608111b7c76 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Mon, 13 Jan 2025 07:48:46 +0100 Subject: [PATCH 43/54] Clean query Signed-off-by: marquesja1 --- cgmes/cgmes-model/src/main/resources/CIM100.sparql | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/cgmes/cgmes-model/src/main/resources/CIM100.sparql b/cgmes/cgmes-model/src/main/resources/CIM100.sparql index ba668498e7a..38e2e3dfb0f 100644 --- a/cgmes/cgmes-model/src/main/resources/CIM100.sparql +++ b/cgmes/cgmes-model/src/main/resources/CIM100.sparql @@ -96,17 +96,6 @@ WHERE { OPTIONAL { ?SynchronousMachine cim:RegulatingCondEq.RegulatingControl ?RegulatingControl } OPTIONAL { ?SynchronousMachine cim:SynchronousMachine.qPercent ?qPercent } }} -OPTIONAL { GRAPH ?graphSSH { - ?SynchronousMachine - cim:RotatingMachine.p ?p ; - cim:RotatingMachine.q ?q ; - cim:SynchronousMachine.referencePriority ?referencePriority ; - cim:SynchronousMachine.operatingMode ?operatingMode ; - cim:RegulatingCondEq.controlEnabled ?controlEnabled . -}} -OPTIONAL { GRAPH ?graphSSH2 { - ?GeneratingUnit cim:GeneratingUnit.normalPF ?normalPF -}} } # query: operationalLimits From 9c4add2b39e12db729344e6cc9778554c84957d9 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Mon, 13 Jan 2025 12:32:18 +0100 Subject: [PATCH 44/54] update staticVarCompensator Signed-off-by: marquesja1 --- .../powsybl/cgmes/conversion/Conversion.java | 1 + ...ontrolMappingForStaticVarCompensators.java | 98 +++------------- .../com/powsybl/cgmes/conversion/Update.java | 10 ++ .../StaticVarCompensatorConversion.java | 105 +++++++++++++++++- .../test/StaticVarCompensatorUpdateTest.java | 92 +++++++++++++++ .../test/export/ExportXmlCompare.java | 7 +- ...icroGridBaseCaseBE-invalid-voltage-bus.txt | 1 + .../microGridBaseCaseBE-target-deadband.txt | 1 + .../functional-logs/microGridBaseCaseBE.txt | 1 + .../functional-logs/miniGridNodeBreaker.txt | 1 + .../staticVarCompensator_EQ.xml | 66 +++++++++++ .../staticVarCompensator_SSH.xml | 25 +++++ .../staticVarCompensator_SSH_1.xml | 25 +++++ .../src/main/resources/CIM100.sparql | 18 +++ .../src/main/resources/CIM16-update.sparql | 8 ++ .../src/main/resources/CIM16.sparql | 5 - 16 files changed, 375 insertions(+), 89 deletions(-) create mode 100644 cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/StaticVarCompensatorUpdateTest.java create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_EQ.xml create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_SSH.xml create mode 100644 cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_SSH_1.xml diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java index df2257c3d87..692e6ae34a8 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java @@ -333,6 +333,7 @@ private void update(Network network, Context updateContext, ReportNode reportNod updateLoads(network, cgmes, updateContext); updateGenerators(network, cgmes, updateContext); updateTransformers(network, updateContext); + updateStaticVarCompensators(network, cgmes, updateContext); completeVoltagesAndAngles(network); diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForStaticVarCompensators.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForStaticVarCompensators.java index a5dba5a75b6..92f44fc022e 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForStaticVarCompensators.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMappingForStaticVarCompensators.java @@ -9,6 +9,7 @@ import com.powsybl.cgmes.conversion.RegulatingControlMapping.RegulatingControl; import com.powsybl.cgmes.model.CgmesModelException; +import com.powsybl.cgmes.model.CgmesNames; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.StaticVarCompensator; import com.powsybl.iidm.network.StaticVarCompensatorAdder; @@ -39,9 +40,7 @@ public static void initialize(StaticVarCompensatorAdder adder) { public void add(String iidmId, PropertyBag sm) { String rcId = RegulatingControlMapping.getRegulatingControlId(sm); - boolean controlEnabled = sm.asBoolean("controlEnabled", false); double defaultTargetVoltage = sm.asDouble("voltageSetPoint"); - double defaultTargetReactivePower = sm.asDouble("q"); String defaultRegulationMode = sm.getId("controlMode"); if (mapping.containsKey(iidmId)) { @@ -51,9 +50,7 @@ public void add(String iidmId, PropertyBag sm) { CgmesRegulatingControlForStaticVarCompensator rc = new CgmesRegulatingControlForStaticVarCompensator(); rc.regulatingControlId = rcId; - rc.controlEnabled = controlEnabled; rc.defaultTargetVoltage = defaultTargetVoltage; - rc.defaultTargetReactivePower = defaultTargetReactivePower; rc.defaultRegulationMode = defaultRegulationMode; mapping.put(iidmId, rc); @@ -76,113 +73,52 @@ private void apply(StaticVarCompensator svc, CgmesRegulatingControlForStaticVarC String controlId = rc.regulatingControlId; if (controlId == null) { LOG.trace("Regulating control Id not present for static var compensator {}", svc.getId()); - setDefaultRegulatingControl(rc, svc, false, null); + setDefaultRegulatingControl(rc, svc); return; } RegulatingControl control = parent.cachedRegulatingControls().get(controlId); if (control == null) { context.missing(String.format("Regulating control %s", controlId)); - setDefaultRegulatingControl(rc, svc, false, null); + setDefaultRegulatingControl(rc, svc); return; } control.setCorrectlySet(setRegulatingControl(rc, control, svc)); } + private void setDefaultRegulatingControl(CgmesRegulatingControlForStaticVarCompensator rc, StaticVarCompensator svc) { + setDefaultRegulatingControlData(rc, svc); + svc.setRegulatingTerminal(svc.getTerminal()); + } + private boolean setRegulatingControl(CgmesRegulatingControlForStaticVarCompensator rc, RegulatingControl control, StaticVarCompensator svc) { - // Always save the original RC id, - // even if we can not complete setting all the regulation data - svc.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "RegulatingControl", rc.regulatingControlId); + setDefaultRegulatingControlData(rc, svc); + svc.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.REGULATING_CONTROL, rc.regulatingControlId); + svc.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.MODE, control.mode); // Take default terminal if it has not been defined in CGMES files (it is never null) Terminal regulatingTerminal = RegulatingTerminalMapper .mapForVoltageControl(control.cgmesTerminal, context) .orElse(svc.getTerminal()); - double targetVoltage = Double.NaN; - double targetReactivePower = Double.NaN; - StaticVarCompensator.RegulationMode regulationMode; - - boolean okSet = false; - if (!control.enabled && rc.controlEnabled) { - context.fixed("SVCControlEnabledStatus", () -> String.format("Regulating control of %s is disabled but controlEnabled property is set to true." + - "Equipment and regulating control properties are used to set local default regulation if local default regulation is reactive power. Else, regulation is disabled.", svc.getId())); - setDefaultRegulatingControl(rc, svc, true, control); - return false; - } - if (RegulatingControlMapping.isControlModeVoltage(control.mode.toLowerCase())) { - regulationMode = StaticVarCompensator.RegulationMode.VOLTAGE; - targetVoltage = control.targetValue; - okSet = true; - } else if (isControlModeReactivePower(control.mode.toLowerCase())) { - regulationMode = StaticVarCompensator.RegulationMode.REACTIVE_POWER; - targetReactivePower = control.targetValue; - okSet = true; - } else { - context.fixed("SVCControlMode", () -> String.format("Invalid control mode for static var compensator %s. Regulating control is disabled", svc.getId())); - regulationMode = StaticVarCompensator.RegulationMode.OFF; - } - - svc.setVoltageSetpoint(targetVoltage); - svc.setReactivePowerSetpoint(targetReactivePower); - if (control.enabled && rc.controlEnabled) { - svc.setRegulationMode(regulationMode); - } svc.setRegulatingTerminal(regulatingTerminal); - return okSet; + return true; } - private boolean isValidVoltageFromRegulatingControl(RegulatingControl control) { - return control != null - && RegulatingControlMapping.isControlModeVoltage(control.mode) - && Double.isFinite(control.targetValue) - && control.targetValue > 0; - } - - private boolean isValidReactivePowerFromRegulatingControl(RegulatingControl control) { - return control != null - && RegulatingControlMapping.isControlModeReactivePower(control.mode) - && Double.isFinite(control.targetValue); - } - - private void setDefaultRegulatingControl(CgmesRegulatingControlForStaticVarCompensator rc, StaticVarCompensator svc, boolean onlyReactivePowerReg, RegulatingControl control) { - - double targetVoltage = Double.NaN; - double targetReactivePower = Double.NaN; - StaticVarCompensator.RegulationMode regulationMode; - - // Before using the default target value, - // We try to keep data from original regulating control if available. - // Even if the regulating control was disabled it may have defined a valid target value - if (RegulatingControlMapping.isControlModeVoltage(rc.defaultRegulationMode.toLowerCase())) { - regulationMode = onlyReactivePowerReg ? StaticVarCompensator.RegulationMode.OFF : StaticVarCompensator.RegulationMode.VOLTAGE; - targetVoltage = isValidVoltageFromRegulatingControl(control) ? control.targetValue : rc.defaultTargetVoltage; - } else if (isControlModeReactivePower(rc.defaultRegulationMode.toLowerCase())) { - regulationMode = StaticVarCompensator.RegulationMode.REACTIVE_POWER; - targetReactivePower = isValidReactivePowerFromRegulatingControl(control) ? control.targetValue : rc.defaultTargetReactivePower; - } else { - context.fixed("SVCControlMode", () -> String.format("Invalid control mode for static var compensator %s. Regulating control is disabled", svc.getId())); - regulationMode = StaticVarCompensator.RegulationMode.OFF; + private void setDefaultRegulatingControlData(CgmesRegulatingControlForStaticVarCompensator rc, StaticVarCompensator svc) { + if (rc.defaultRegulationMode != null) { + svc.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "defaultRegulationMode", rc.defaultRegulationMode); } - - svc.setVoltageSetpoint(targetVoltage); - svc.setReactivePowerSetpoint(targetReactivePower); - if (rc.controlEnabled) { - svc.setRegulationMode(regulationMode); + if (!Double.isNaN(rc.defaultTargetVoltage)) { + svc.setProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "defaultTargetVoltage", String.valueOf(rc.defaultTargetVoltage)); } } - private static boolean isControlModeReactivePower(String controlMode) { - return controlMode != null && controlMode.endsWith("reactivepower"); - } - private static final class CgmesRegulatingControlForStaticVarCompensator { String regulatingControlId; - boolean controlEnabled; double defaultTargetVoltage; - double defaultTargetReactivePower; String defaultRegulationMode; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java index 38c744ce2be..7c0f053fec9 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Update.java @@ -88,6 +88,16 @@ static void updateTransformers(Network network, Context context) { context.popReportNode(); } + static void updateStaticVarCompensators(Network network, CgmesModel cgmes, Context context) { + context.pushReportNode(CgmesReports.updatingElementTypeReport(context.getReportNode(), IdentifiableType.STATIC_VAR_COMPENSATOR.name())); + + Map equipmentIdPropertyBag = new HashMap<>(); + addPropertyBags(cgmes.staticVarCompensators(), CgmesNames.STATIC_VAR_COMPENSATOR, equipmentIdPropertyBag); + + network.getStaticVarCompensators().forEach(staticVarCompensator -> StaticVarCompensatorConversion.update(staticVarCompensator, getPropertyBag(staticVarCompensator.getId(), equipmentIdPropertyBag), context)); + context.popReportNode(); + } + private static void addPropertyBags(PropertyBags propertyBags, String idTag, Map equipmentIdPropertyBag) { propertyBags.forEach(propertyBag -> equipmentIdPropertyBag.put(propertyBag.getId(idTag), propertyBag)); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java index 3640007c29d..dd1983c0682 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java @@ -9,6 +9,8 @@ package com.powsybl.cgmes.conversion.elements; import com.powsybl.cgmes.conversion.Context; +import com.powsybl.cgmes.conversion.Conversion; +import com.powsybl.cgmes.conversion.RegulatingControlMapping; import com.powsybl.cgmes.conversion.RegulatingControlMappingForStaticVarCompensators; import com.powsybl.cgmes.model.CgmesNames; import com.powsybl.iidm.network.StaticVarCompensator; @@ -16,6 +18,11 @@ import com.powsybl.iidm.network.extensions.VoltagePerReactivePowerControlAdder; import com.powsybl.triplestore.api.PropertyBag; +import java.util.List; +import java.util.Optional; + +import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; + /** * @author Luma Zamarreño {@literal } */ @@ -35,12 +42,12 @@ public void convert() { .setBmin(getB(inductiveRating, "inductive")) .setBmax(getB(capacitiveRating, "capacitive")); identify(adder); - connect(adder); + connectWithOnlyEq(adder); RegulatingControlMappingForStaticVarCompensators.initialize(adder); StaticVarCompensator svc = adder.add(); addAliasesAndProperties(svc); - convertedTerminals(svc.getTerminal()); + convertedTerminalsWithOnlyEq(svc.getTerminal()); if (slope >= 0) { svc.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(slope).add(); } @@ -65,4 +72,98 @@ private double checkSlope(double slope) { } return slope; } + + public static void update(StaticVarCompensator staticVarCompensator, PropertyBag cgmesData, Context context) { + updateTerminals(staticVarCompensator, context, staticVarCompensator.getTerminal()); + + double defaultTargetQ = cgmesData.asDouble("q"); + boolean controlEnabled = cgmesData.asBoolean("controlEnabled", false); + updateRegulatingControl(staticVarCompensator, defaultTargetQ, controlEnabled, context); + } + + private static void updateRegulatingControl(StaticVarCompensator staticVarCompensator, double defaultTargetQ, boolean controlEnabled, Context context) { + String defaultRegulationMode = staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "defaultRegulationMode"); + String mode = staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.MODE); + String selectedMode = mode != null ? mode : defaultRegulationMode; + + String regulatingControlId = staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.REGULATING_CONTROL); + Optional cgmesRegulatingControl = findCgmesRegulatingControl(regulatingControlId, context); + + double defaultTargetV = findDefaultTargetV(staticVarCompensator); + + if (cgmesRegulatingControl.isEmpty() && controlEnabled && defaultRegulationMode != null && RegulatingControlMapping.isControlModeVoltage(defaultRegulationMode.toLowerCase()) && isValidTargetV(defaultTargetV)) { + context.fixed("SVCControlEnabledStatus", () -> String.format("Regulating control of %s is disabled but controlEnabled property is set to true." + + "Equipment and regulating control properties are used to set local default regulation if local default regulation is voltage.", staticVarCompensator.getId())); + staticVarCompensator.setVoltageSetpoint(defaultTargetV).setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE); + return; + } + + boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, staticVarCompensator, context)).orElseGet(() -> findDefaultRegulatingOn(staticVarCompensator, context)); + + if (!regulatingOn && controlEnabled && defaultRegulationMode != null && RegulatingControlMapping.isControlModeReactivePower(defaultRegulationMode.toLowerCase()) && isValidTargetQ(defaultTargetQ)) { + context.fixed("SVCControlEnabledStatus", () -> String.format("Regulating control of %s is disabled but controlEnabled property is set to true." + + "Equipment and regulating control properties are used to set local default regulation if local default regulation is reactive power.", staticVarCompensator.getId())); + staticVarCompensator.setReactivePowerSetpoint(defaultTargetQ).setRegulationMode(StaticVarCompensator.RegulationMode.REACTIVE_POWER); + return; + } + + if (selectedMode != null && RegulatingControlMapping.isControlModeVoltage(selectedMode.toLowerCase())) { + double targetV = cgmesRegulatingControl.map(StaticVarCompensatorConversion::findTargetV).orElseGet(() -> findDefaultTargetV(staticVarCompensator, defaultTargetV, context)); + StaticVarCompensator.RegulationMode regulationMode = controlEnabled && regulatingOn && isValidTargetV(targetV) ? StaticVarCompensator.RegulationMode.VOLTAGE : StaticVarCompensator.RegulationMode.OFF; + staticVarCompensator.setVoltageSetpoint(targetV).setRegulationMode(regulationMode); + } else if (selectedMode != null && RegulatingControlMapping.isControlModeReactivePower(selectedMode.toLowerCase())) { + double targetQ = cgmesRegulatingControl.map(StaticVarCompensatorConversion::findTargetQ).orElseGet(() -> findDefaultTargetQ(staticVarCompensator, defaultTargetQ, context)); + StaticVarCompensator.RegulationMode regulationMode = controlEnabled && regulatingOn && isValidTargetQ(targetQ) ? StaticVarCompensator.RegulationMode.REACTIVE_POWER : StaticVarCompensator.RegulationMode.OFF; + staticVarCompensator.setReactivePowerSetpoint(targetQ).setRegulationMode(regulationMode); + } else { + context.ignored(mode, "Unsupported regulation mode for staticVarCompensator " + staticVarCompensator.getId()); + } + } + + private static Optional findCgmesRegulatingControl(String regulatingControlId, Context context) { + return regulatingControlId != null ? Optional.ofNullable(context.regulatingControl(regulatingControlId)) : Optional.empty(); + } + + private static double findDefaultTargetV(StaticVarCompensator staticVarCompensator) { + String defaultTargetVoltage = staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "defaultTargetVoltage"); + return defaultTargetVoltage != null ? Double.parseDouble(defaultTargetVoltage) : Double.NaN; + } + + private static double findTargetV(PropertyBag regulatingControl) { + return regulatingControl.asDouble("targetValue"); + } + + private static double findDefaultTargetV(StaticVarCompensator staticVarCompensator, double defaultTargetV, Context context) { + return defaultValue(Double.NaN, staticVarCompensator.getVoltageSetpoint(), defaultTargetV, Double.NaN, getDefaultValueSelector(context)); + } + + private static boolean isValidTargetV(double targetV) { + return Double.isFinite(targetV) && targetV > 0.0; + } + + private static double findTargetQ(PropertyBag regulatingControl) { + return regulatingControl.asDouble("targetValue"); + } + + private static double findDefaultTargetQ(StaticVarCompensator staticVarCompensator, double defaultTargetQ, Context context) { + return defaultValue(Double.NaN, staticVarCompensator.getReactivePowerSetpoint(), defaultTargetQ, Double.NaN, getDefaultValueSelector(context)); + } + + private static boolean isValidTargetQ(double targetValue) { + return Double.isFinite(targetValue); + } + + private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { + return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); + } + + private static boolean findRegulatingOn(PropertyBag regulatingControl, StaticVarCompensator staticVarCompensator, Context context) { + return regulatingControl.asBoolean("enabled").orElse(findDefaultRegulatingOn(staticVarCompensator, context)); + } + + private static boolean findDefaultRegulatingOn(StaticVarCompensator staticVarCompensator, Context context) { + return defaultValue(false, staticVarCompensator.getRegulationMode() == StaticVarCompensator.RegulationMode.VOLTAGE || + staticVarCompensator.getRegulationMode() == StaticVarCompensator.RegulationMode.REACTIVE_POWER, + false, false, getDefaultValueSelector(context)); + } } diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/StaticVarCompensatorUpdateTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/StaticVarCompensatorUpdateTest.java new file mode 100644 index 00000000000..b6a25e57d76 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/StaticVarCompensatorUpdateTest.java @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.cgmes.conversion.test; + +import com.powsybl.cgmes.conversion.Conversion; +import com.powsybl.cgmes.model.CgmesNames; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.StaticVarCompensator; +import org.junit.jupiter.api.Test; + +import static com.powsybl.cgmes.conversion.test.ConversionUtil.readCgmesResources; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Luma Zamarreño {@literal } + * @author José Antonio Marqués {@literal } + */ +class StaticVarCompensatorUpdateTest { + + private static final String DIR = "/update/staticVarCompensator/"; + + @Test + void importEqTest() { + Network network = readCgmesResources(DIR, "staticVarCompensator_EQ.xml"); + assertEquals(1, network.getStaticVarCompensatorCount()); + + StaticVarCompensator staticVarCompensator = network.getStaticVarCompensator("StaticVarCompensator"); + assertTrue(checkEq(staticVarCompensator)); + } + + @Test + void importEqAndSshTogetherTest() { + Network network = readCgmesResources(DIR, "staticVarCompensator_EQ.xml", "staticVarCompensator_SSH.xml"); + assertEquals(1, network.getStaticVarCompensatorCount()); + + StaticVarCompensator staticVarCompensator = network.getStaticVarCompensator("StaticVarCompensator"); + assertTrue(checkSsh(staticVarCompensator, Double.NaN, 405.0, StaticVarCompensator.RegulationMode.VOLTAGE)); + } + + @Test + void importEqAndSshSeparatelyTest() { + Network network = readCgmesResources(DIR, "staticVarCompensator_EQ.xml"); + assertEquals(1, network.getStaticVarCompensatorCount()); + + StaticVarCompensator staticVarCompensator = network.getStaticVarCompensator("StaticVarCompensator"); + assertTrue(checkEq(staticVarCompensator)); + + readCgmesResources(network, DIR, "staticVarCompensator_SSH.xml"); + assertTrue(checkSsh(staticVarCompensator, Double.NaN, 405.0, StaticVarCompensator.RegulationMode.VOLTAGE)); + } + + @Test + void importEqAndTwoSshsTest() { + Network network = readCgmesResources(DIR, "staticVarCompensator_EQ.xml"); + assertEquals(1, network.getStaticVarCompensatorCount()); + + StaticVarCompensator staticVarCompensator = network.getStaticVarCompensator("StaticVarCompensator"); + assertTrue(checkEq(staticVarCompensator)); + + readCgmesResources(network, DIR, "staticVarCompensator_SSH.xml"); + assertTrue(checkSsh(staticVarCompensator, Double.NaN, 405.0, StaticVarCompensator.RegulationMode.VOLTAGE)); + + readCgmesResources(network, DIR, "staticVarCompensator_SSH_1.xml"); + assertTrue(checkSsh(staticVarCompensator, Double.NaN, 400.0, StaticVarCompensator.RegulationMode.OFF)); + } + + private static boolean checkEq(StaticVarCompensator staticVarCompensator) { + assertNotNull(staticVarCompensator); + assertTrue(Double.isNaN(staticVarCompensator.getReactivePowerSetpoint())); + assertTrue(Double.isNaN(staticVarCompensator.getVoltageSetpoint())); + assertNotNull(staticVarCompensator.getRegulatingTerminal()); + assertEquals(StaticVarCompensator.RegulationMode.OFF, staticVarCompensator.getRegulationMode()); + + assertNotNull(staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.MODE)); + assertNotNull(staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.REGULATING_CONTROL)); + return true; + } + + private static boolean checkSsh(StaticVarCompensator staticVarCompensator, double targetQ, double targetV, StaticVarCompensator.RegulationMode regulationMode) { + assertNotNull(staticVarCompensator); + double tol = 0.0000001; + assertEquals(targetQ, staticVarCompensator.getReactivePowerSetpoint(), tol); + assertEquals(targetV, staticVarCompensator.getVoltageSetpoint(), tol); + assertEquals(regulationMode, staticVarCompensator.getRegulationMode()); + return true; + } +} diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java index b5218e181a9..eb03a045ab1 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java @@ -607,7 +607,12 @@ static ComparisonResult ignoringRdfChildLookupEquivalentInjection(Comparison com } static ComparisonResult ignoringRdfChildLookupStaticVarCompensator(Comparison comparison, ComparisonResult result) { - if (result == ComparisonResult.DIFFERENT && comparison.getType() == ComparisonType.CHILD_LOOKUP) { + if (result == ComparisonResult.DIFFERENT && comparison.getType() == ComparisonType.TEXT_VALUE) { + String cxpath = comparison.getControlDetails().getXPath(); + if (cxpath != null && cxpath.contains("RDF") && cxpath.contains("StaticVarCompensator")) { + return ComparisonResult.EQUAL; + } + } else if (result == ComparisonResult.DIFFERENT && comparison.getType() == ComparisonType.CHILD_LOOKUP) { String cxpath = comparison.getControlDetails().getXPath(); if (cxpath != null && cxpath.contains("RDF") && cxpath.contains("StaticVarCompensator")) { return ComparisonResult.EQUAL; diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt index 0217b9c21f8..352c4fd3147 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-invalid-voltage-bus.txt @@ -45,4 +45,5 @@ Equipment 955d9cd0-4a10-4031-b008-60c0dc340a07 has a regulating control with bad target value for voltage: 0.0. + Updating THREE_WINDINGS_TRANSFORMER. Equipment fe25f43a-7341-446e-a71a-8ab7119ba806 has a regulating control with bad target value for voltage: 0.0. + Updating STATIC_VAR_COMPENSATOR. Running validation checks on IIDM network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt index 1b8c5963728..de026ce188d 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE-target-deadband.txt @@ -45,4 +45,5 @@ Equipment 6ebbef67-3061-4236-a6fd-6ccc4595f6c3 has a regulating control with bad target deadband: -35.0. + Updating THREE_WINDINGS_TRANSFORMER. Equipment fe25f43a-7341-446e-a71a-8ab7119ba806 has a regulating control with bad target value for voltage: 0.0. + Updating STATIC_VAR_COMPENSATOR. Running validation checks on IIDM network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt index 64c371b7d3e..8696dc1f08f 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/microGridBaseCaseBE.txt @@ -47,4 +47,5 @@ Equipment 955d9cd0-4a10-4031-b008-60c0dc340a07 has a regulating control with bad target value for voltage: 0.0. + Updating THREE_WINDINGS_TRANSFORMER. Equipment fe25f43a-7341-446e-a71a-8ab7119ba806 has a regulating control with bad target value for voltage: 0.0. + Updating STATIC_VAR_COMPENSATOR. Running validation checks on IIDM network urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73 diff --git a/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt b/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt index 0686056653e..1b0ea594990 100644 --- a/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt +++ b/cgmes/cgmes-conversion/src/test/resources/functional-logs/miniGridNodeBreaker.txt @@ -44,4 +44,5 @@ Updating GENERATOR. Updating TWO_WINDINGS_TRANSFORMER. Updating THREE_WINDINGS_TRANSFORMER. + Updating STATIC_VAR_COMPENSATOR. Running validation checks on IIDM network urn:uuid:239ecbd2-9a39-11e0-aa80-0800200c9a66 diff --git a/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_EQ.xml new file mode 100644 index 00000000000..356e7df1b15 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_EQ.xml @@ -0,0 +1,66 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + StaticVarCompensator + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/CoreEquipment-EU/3.0 + + + + GeographicalRegionTest + GeographicalRegionTest + + + SubGeographicalRegionTest + SubGeographicalRegionTest + + + + Substation1 + Substation1 + + + + BaseVoltage400 + Base Voltage Level 400kV + 400.0 kV + 400.0 + + + VoltageLevel1 + VoltageLevel1 + 420 + 380 + + + + + ConnectivityNode1 + Connectivity Node 1 + + + + + StaticVarCompensator + + + 5062.5 + -5062.5 + 0.102 + + + StaticVarCompensator_T + Terminal + 1 + + + + + + SynchronousMachine-RegulatingControl + + + + diff --git a/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_SSH.xml b/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_SSH.xml new file mode 100644 index 00000000000..1a9ffdc4b89 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_SSH.xml @@ -0,0 +1,25 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + StaticVarCompensator + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 + + + + true + true + 0 + + + true + + + false + true + 405.0 + + + diff --git a/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_SSH_1.xml b/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_SSH_1.xml new file mode 100644 index 00000000000..7a2abe75003 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_SSH_1.xml @@ -0,0 +1,25 @@ + + + 2024-02-21T11:00:00Z + 2024-02-21T11:00:00Z + 1 + StaticVarCompensator + https://www.powsybl.org/ + http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 + + + + true + true + 0 + + + true + + + false + false + 400.0 + + + diff --git a/cgmes/cgmes-model/src/main/resources/CIM100.sparql b/cgmes/cgmes-model/src/main/resources/CIM100.sparql index 38e2e3dfb0f..8da755a63f4 100644 --- a/cgmes/cgmes-model/src/main/resources/CIM100.sparql +++ b/cgmes/cgmes-model/src/main/resources/CIM100.sparql @@ -98,6 +98,24 @@ WHERE { }} } +# query: staticVarCompensators +SELECT * +WHERE { +{ GRAPH ?graph { + ?StaticVarCompensator + a cim:StaticVarCompensator ; + cim:IdentifiedObject.name ?name ; + cim:StaticVarCompensator.capacitiveRating ?capacitiveRating ; + cim:StaticVarCompensator.inductiveRating ?inductiveRating ; + cim:StaticVarCompensator.slope ?slope . + ?Terminal cim:Terminal.ConductingEquipment ?StaticVarCompensator . + + OPTIONAL { ?StaticVarCompensator cim:StaticVarCompensator.sVCControlMode ?controlMode } + OPTIONAL { ?StaticVarCompensator cim:StaticVarCompensator.voltageSetPoint ?voltageSetPoint } + OPTIONAL { ?StaticVarCompensator cim:RegulatingCondEq.RegulatingControl ?RegulatingControl } +}} +} + # query: operationalLimits SELECT * WHERE { diff --git a/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql b/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql index af1fd3d0a50..bab3c23b301 100644 --- a/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql +++ b/cgmes/cgmes-model/src/main/resources/CIM16-update.sparql @@ -213,6 +213,14 @@ SELECT * cim:RegulatingCondEq.controlEnabled ?controlEnabled } +# query: staticVarCompensators +SELECT * +{ + ?StaticVarCompensator a cim:StaticVarCompensator ; + cim:StaticVarCompensator.q ?q ; + cim:RegulatingCondEq.controlEnabled ?controlEnabled +} + # query: boundaryNodes # All pairs (Connectivity Node, Topological Node) from instance files that have boundary profile and attribute boundaryPoint set to true # We expect all Connectivity Nodes have 1 and only one corresponding TopologicalNode diff --git a/cgmes/cgmes-model/src/main/resources/CIM16.sparql b/cgmes/cgmes-model/src/main/resources/CIM16.sparql index 9fe0f3df039..3ebaece417f 100644 --- a/cgmes/cgmes-model/src/main/resources/CIM16.sparql +++ b/cgmes/cgmes-model/src/main/resources/CIM16.sparql @@ -964,11 +964,6 @@ WHERE { ?StaticVarCompensator cim:RegulatingCondEq.RegulatingControl ?RegulatingControl } }} -OPTIONAL { GRAPH ?graphSSH { - ?StaticVarCompensator - cim:StaticVarCompensator.q ?q ; - cim:RegulatingCondEq.controlEnabled ?controlEnabled -}} } # query: asynchronousMachines From 4aa9045625e199c2ceb0fdee190ef9f6110ef1fb Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Mon, 13 Jan 2025 13:21:44 +0100 Subject: [PATCH 45/54] pretty code Signed-off-by: marquesja1 --- .../elements/StaticVarCompensatorConversion.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java index dd1983c0682..a8bd912c1be 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java @@ -84,11 +84,8 @@ public static void update(StaticVarCompensator staticVarCompensator, PropertyBag private static void updateRegulatingControl(StaticVarCompensator staticVarCompensator, double defaultTargetQ, boolean controlEnabled, Context context) { String defaultRegulationMode = staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "defaultRegulationMode"); String mode = staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.MODE); - String selectedMode = mode != null ? mode : defaultRegulationMode; - - String regulatingControlId = staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.REGULATING_CONTROL); - Optional cgmesRegulatingControl = findCgmesRegulatingControl(regulatingControlId, context); + Optional cgmesRegulatingControl = findCgmesRegulatingControl(staticVarCompensator, context); double defaultTargetV = findDefaultTargetV(staticVarCompensator); if (cgmesRegulatingControl.isEmpty() && controlEnabled && defaultRegulationMode != null && RegulatingControlMapping.isControlModeVoltage(defaultRegulationMode.toLowerCase()) && isValidTargetV(defaultTargetV)) { @@ -107,6 +104,7 @@ private static void updateRegulatingControl(StaticVarCompensator staticVarCompen return; } + String selectedMode = mode != null ? mode : defaultRegulationMode; if (selectedMode != null && RegulatingControlMapping.isControlModeVoltage(selectedMode.toLowerCase())) { double targetV = cgmesRegulatingControl.map(StaticVarCompensatorConversion::findTargetV).orElseGet(() -> findDefaultTargetV(staticVarCompensator, defaultTargetV, context)); StaticVarCompensator.RegulationMode regulationMode = controlEnabled && regulatingOn && isValidTargetV(targetV) ? StaticVarCompensator.RegulationMode.VOLTAGE : StaticVarCompensator.RegulationMode.OFF; @@ -120,7 +118,8 @@ private static void updateRegulatingControl(StaticVarCompensator staticVarCompen } } - private static Optional findCgmesRegulatingControl(String regulatingControlId, Context context) { + private static Optional findCgmesRegulatingControl(StaticVarCompensator staticVarCompensator, Context context) { + String regulatingControlId = staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.REGULATING_CONTROL); return regulatingControlId != null ? Optional.ofNullable(context.regulatingControl(regulatingControlId)) : Optional.empty(); } From 6c41d4907f54a5a01695facd8f89e4f08ae50b64 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Tue, 14 Jan 2025 08:35:25 +0100 Subject: [PATCH 46/54] Extend previous change to regulating controls Signed-off-by: marquesja1 --- .../cgmes/conversion/test/export/ExportXmlCompare.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java index eb03a045ab1..bcc044a6169 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java @@ -622,7 +622,12 @@ static ComparisonResult ignoringRdfChildLookupStaticVarCompensator(Comparison co } static ComparisonResult ignoringRdfChildLookupRegulatingControl(Comparison comparison, ComparisonResult result) { - if (result == ComparisonResult.DIFFERENT && comparison.getType() == ComparisonType.CHILD_LOOKUP) { + if (result == ComparisonResult.DIFFERENT && comparison.getType() == ComparisonType.TEXT_VALUE) { + String cxpath = comparison.getControlDetails().getXPath(); + if (cxpath != null && cxpath.contains("RDF") && cxpath.contains("RegulatingControl")) { + return ComparisonResult.EQUAL; + } + } else if (result == ComparisonResult.DIFFERENT && comparison.getType() == ComparisonType.CHILD_LOOKUP) { String cxpath = comparison.getControlDetails().getXPath(); if (cxpath != null && cxpath.contains("RDF") && cxpath.contains("RegulatingControl")) { return ComparisonResult.EQUAL; From 3861d2a29ce267a492afb2fc44222ca9244d4db6 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Tue, 14 Jan 2025 15:01:32 +0100 Subject: [PATCH 47/54] Reduce complexity and additional minor changes Signed-off-by: marquesja1 --- .../StaticVarCompensatorConversion.java | 40 ++++++++++++++----- .../test/export/ExportXmlCompare.java | 15 ++++--- .../SteadyStateHypothesisExportTest.java | 5 ++- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java index a8bd912c1be..29bfad5693f 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java @@ -88,19 +88,13 @@ private static void updateRegulatingControl(StaticVarCompensator staticVarCompen Optional cgmesRegulatingControl = findCgmesRegulatingControl(staticVarCompensator, context); double defaultTargetV = findDefaultTargetV(staticVarCompensator); - if (cgmesRegulatingControl.isEmpty() && controlEnabled && defaultRegulationMode != null && RegulatingControlMapping.isControlModeVoltage(defaultRegulationMode.toLowerCase()) && isValidTargetV(defaultTargetV)) { - context.fixed("SVCControlEnabledStatus", () -> String.format("Regulating control of %s is disabled but controlEnabled property is set to true." + - "Equipment and regulating control properties are used to set local default regulation if local default regulation is voltage.", staticVarCompensator.getId())); - staticVarCompensator.setVoltageSetpoint(defaultTargetV).setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE); + if (isDefaultVoltageControl(cgmesRegulatingControl.isEmpty(), controlEnabled, defaultRegulationMode, defaultTargetV)) { + setDefaultVoltageControl(staticVarCompensator, defaultTargetV, context); return; } - boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, staticVarCompensator, context)).orElseGet(() -> findDefaultRegulatingOn(staticVarCompensator, context)); - - if (!regulatingOn && controlEnabled && defaultRegulationMode != null && RegulatingControlMapping.isControlModeReactivePower(defaultRegulationMode.toLowerCase()) && isValidTargetQ(defaultTargetQ)) { - context.fixed("SVCControlEnabledStatus", () -> String.format("Regulating control of %s is disabled but controlEnabled property is set to true." + - "Equipment and regulating control properties are used to set local default regulation if local default regulation is reactive power.", staticVarCompensator.getId())); - staticVarCompensator.setReactivePowerSetpoint(defaultTargetQ).setRegulationMode(StaticVarCompensator.RegulationMode.REACTIVE_POWER); + if (isDefaultReactivePowerControl(regulatingOn, controlEnabled, defaultRegulationMode, defaultTargetQ)) { + setDefaultReactivePowerControl(staticVarCompensator, defaultTargetQ, context); return; } @@ -118,6 +112,32 @@ private static void updateRegulatingControl(StaticVarCompensator staticVarCompen } } + private static boolean isDefaultVoltageControl(boolean cgmesRegulatingControlIsNotDefined, boolean controlEnabled, String defaultRegulationMode, double defaultTargetV) { + return cgmesRegulatingControlIsNotDefined + && controlEnabled + && defaultRegulationMode != null && RegulatingControlMapping.isControlModeVoltage(defaultRegulationMode.toLowerCase()) + && isValidTargetV(defaultTargetV); + } + + private static void setDefaultVoltageControl(StaticVarCompensator staticVarCompensator, double defaultTargetV, Context context) { + context.fixed("SVCControlEnabledStatus", () -> String.format("Regulating control of %s is disabled but controlEnabled property is set to true." + + "Equipment and regulating control properties are used to set local default regulation if local default regulation is voltage.", staticVarCompensator.getId())); + staticVarCompensator.setVoltageSetpoint(defaultTargetV).setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE); + } + + private static boolean isDefaultReactivePowerControl(boolean regulatingOn, boolean controlEnabled, String defaultRegulationMode, double defaultTargetQ) { + return !regulatingOn + && controlEnabled + && defaultRegulationMode != null && RegulatingControlMapping.isControlModeReactivePower(defaultRegulationMode.toLowerCase()) + && isValidTargetQ(defaultTargetQ); + } + + private static void setDefaultReactivePowerControl(StaticVarCompensator staticVarCompensator, double defaultTargetQ, Context context) { + context.fixed("SVCControlEnabledStatus", () -> String.format("Regulating control of %s is disabled but controlEnabled property is set to true." + + "Equipment and regulating control properties are used to set local default regulation if local default regulation is reactive power.", staticVarCompensator.getId())); + staticVarCompensator.setReactivePowerSetpoint(defaultTargetQ).setRegulationMode(StaticVarCompensator.RegulationMode.REACTIVE_POWER); + } + private static Optional findCgmesRegulatingControl(StaticVarCompensator staticVarCompensator, Context context) { String regulatingControlId = staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.REGULATING_CONTROL); return regulatingControlId != null ? Optional.ofNullable(context.regulatingControl(regulatingControlId)) : Optional.empty(); diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java index bcc044a6169..2177cba9f56 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/ExportXmlCompare.java @@ -606,22 +606,27 @@ static ComparisonResult ignoringRdfChildLookupEquivalentInjection(Comparison com return result; } - static ComparisonResult ignoringRdfChildLookupStaticVarCompensator(Comparison comparison, ComparisonResult result) { + static ComparisonResult ignoringStaticVarCompensatorControlEnabled(Comparison comparison, ComparisonResult result) { if (result == ComparisonResult.DIFFERENT && comparison.getType() == ComparisonType.TEXT_VALUE) { String cxpath = comparison.getControlDetails().getXPath(); - if (cxpath != null && cxpath.contains("RDF") && cxpath.contains("StaticVarCompensator")) { + if (cxpath != null && cxpath.contains("StaticVarCompensator") && cxpath.contains(".controlEnabled")) { return ComparisonResult.EQUAL; } - } else if (result == ComparisonResult.DIFFERENT && comparison.getType() == ComparisonType.CHILD_LOOKUP) { + } + return result; + } + + static ComparisonResult ignoringStaticVarCompensatorQ(Comparison comparison, ComparisonResult result) { + if (result == ComparisonResult.DIFFERENT && comparison.getType() == ComparisonType.TEXT_VALUE) { String cxpath = comparison.getControlDetails().getXPath(); - if (cxpath != null && cxpath.contains("RDF") && cxpath.contains("StaticVarCompensator")) { + if (cxpath != null && cxpath.contains("StaticVarCompensator.q")) { return ComparisonResult.EQUAL; } } return result; } - static ComparisonResult ignoringRdfChildLookupRegulatingControl(Comparison comparison, ComparisonResult result) { + static ComparisonResult ignoringRegulatingControl(Comparison comparison, ComparisonResult result) { if (result == ComparisonResult.DIFFERENT && comparison.getType() == ComparisonType.TEXT_VALUE) { String cxpath = comparison.getControlDetails().getXPath(); if (cxpath != null && cxpath.contains("RDF") && cxpath.contains("RegulatingControl")) { diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/SteadyStateHypothesisExportTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/SteadyStateHypothesisExportTest.java index 43102c5c030..057af0834fe 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/SteadyStateHypothesisExportTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/SteadyStateHypothesisExportTest.java @@ -354,8 +354,9 @@ void microGridCgmesExportPreservingOriginalClassesOfLoads() throws IOException, ExportXmlCompare::ignoringTextValueTapChangerControlEnabled, ExportXmlCompare::ignoringRdfChildLookupTerminal, ExportXmlCompare::ignoringRdfChildLookupEquivalentInjection, - ExportXmlCompare::ignoringRdfChildLookupStaticVarCompensator, - ExportXmlCompare::ignoringRdfChildLookupRegulatingControl, + ExportXmlCompare::ignoringStaticVarCompensatorControlEnabled, + ExportXmlCompare::ignoringStaticVarCompensatorQ, + ExportXmlCompare::ignoringRegulatingControl, ExportXmlCompare::ignoringTextValueEquivalentInjection); assertTrue(ExportXmlCompare.compareSSH(expectedSsh, new ByteArrayInputStream(actualSsh.getBytes(StandardCharsets.UTF_8)), knownDiffsSsh)); } From 0cf9161518a51a27b321f20e0521fab431119ced Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 15 Jan 2025 07:40:43 +0100 Subject: [PATCH 48/54] Enhance the EQ files used in unit tests Signed-off-by: marquesja1 --- .../src/test/resources/update/generator/generator_EQ.xml | 9 +++------ .../src/test/resources/update/load/load_EQ.xml | 9 +++------ .../staticVarCompensator/staticVarCompensator_EQ.xml | 3 +-- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml index 110e49109d0..1b624abcaca 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml @@ -56,8 +56,7 @@ - SynchronousMachine_T - Terminal + SynchronousMachine_T 1 @@ -94,8 +93,7 @@ 0 - EquivalentInjection_T - Terminal + EquivalentInjection_T 1 @@ -120,8 +118,7 @@ -66 - ExternalNetworkInjection_T - Terminal + ExternalNetworkInjection_T 1 diff --git a/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml index f7e2d205117..bce605162e7 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml @@ -47,8 +47,7 @@ - EnergyConsumer_T - Terminal + EnergyConsumer_T 1 @@ -59,8 +58,7 @@ - EnergySource_T - Terminal + EnergySource_T 1 @@ -83,8 +81,7 @@ AsynchronousMachine - synchronousMachine_T - Terminal + AsynchronousMachine_T 1 diff --git a/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_EQ.xml index 356e7df1b15..18b43ee5197 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_EQ.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_EQ.xml @@ -51,8 +51,7 @@ 0.102 - StaticVarCompensator_T - Terminal + StaticVarCompensator_T 1 From 7451e8f1271157f3025a7dfc0606853b0ffdd4ca Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Fri, 17 Jan 2025 12:54:44 +0100 Subject: [PATCH 49/54] Improve EQ files used in unit tests Signed-off-by: marquesja1 --- .../test/StaticVarCompensatorUpdateTest.java | 2 +- .../update/generator/generator_EQ.xml | 15 ----------- .../test/resources/update/load/load_EQ.xml | 17 ------------ .../staticVarCompensator_EQ.xml | 11 -------- .../staticVarCompensator_SSH.xml | 0 .../staticVarCompensator_SSH_1.xml | 0 .../update/transformer/transformer_EQ.xml | 26 ------------------- 7 files changed, 1 insertion(+), 70 deletions(-) rename cgmes/cgmes-conversion/src/test/resources/update/{staticVarCompensator => static-var-compensator}/staticVarCompensator_EQ.xml (79%) rename cgmes/cgmes-conversion/src/test/resources/update/{staticVarCompensator => static-var-compensator}/staticVarCompensator_SSH.xml (100%) rename cgmes/cgmes-conversion/src/test/resources/update/{staticVarCompensator => static-var-compensator}/staticVarCompensator_SSH_1.xml (100%) diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/StaticVarCompensatorUpdateTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/StaticVarCompensatorUpdateTest.java index b6a25e57d76..90552b8b2cd 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/StaticVarCompensatorUpdateTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/StaticVarCompensatorUpdateTest.java @@ -22,7 +22,7 @@ */ class StaticVarCompensatorUpdateTest { - private static final String DIR = "/update/staticVarCompensator/"; + private static final String DIR = "/update/static-var-compensator/"; @Test void importEqTest() { diff --git a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml index 1b624abcaca..23b957b72aa 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml @@ -9,35 +9,26 @@ - GeographicalRegionTest GeographicalRegionTest - SubGeographicalRegionTest SubGeographicalRegionTest - Substation1 Substation1 - BaseVoltage400 - Base Voltage Level 400kV 400.0 kV 400.0 - VoltageLevel1 VoltageLevel1 - 420 - 380 - ConnectivityNode1 Connectivity Node 1 @@ -57,8 +48,6 @@ SynchronousMachine_T - 1 - @@ -94,8 +83,6 @@ EquivalentInjection_T - 1 - @@ -119,8 +106,6 @@ ExternalNetworkInjection_T - 1 - diff --git a/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml index bce605162e7..ca46a03a559 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml @@ -9,35 +9,26 @@ - GeographicalRegionTest GeographicalRegionTest - SubGeographicalRegionTest SubGeographicalRegionTest - Substation1 Substation1 - BaseVoltage400 - Base Voltage Level 400kV 400.0 kV 400.0 - VoltageLevel1 VoltageLevel1 - 420 - 380 - ConnectivityNode1 Connectivity Node 1 @@ -48,8 +39,6 @@ EnergyConsumer_T - 1 - @@ -59,14 +48,11 @@ EnergySource_T - 1 - AsynchronousMachine - false 0.89 2.321 @@ -78,12 +64,9 @@ 2 false 0.1 - AsynchronousMachine AsynchronousMachine_T - 1 - diff --git a/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/static-var-compensator/staticVarCompensator_EQ.xml similarity index 79% rename from cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_EQ.xml rename to cgmes/cgmes-conversion/src/test/resources/update/static-var-compensator/staticVarCompensator_EQ.xml index 18b43ee5197..0e0e03f87ea 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_EQ.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/static-var-compensator/staticVarCompensator_EQ.xml @@ -9,35 +9,26 @@ - GeographicalRegionTest GeographicalRegionTest - SubGeographicalRegionTest SubGeographicalRegionTest - Substation1 Substation1 - BaseVoltage400 - Base Voltage Level 400kV 400.0 kV 400.0 - VoltageLevel1 VoltageLevel1 - 420 - 380 - ConnectivityNode1 Connectivity Node 1 @@ -52,8 +43,6 @@ StaticVarCompensator_T - 1 - diff --git a/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_SSH.xml b/cgmes/cgmes-conversion/src/test/resources/update/static-var-compensator/staticVarCompensator_SSH.xml similarity index 100% rename from cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_SSH.xml rename to cgmes/cgmes-conversion/src/test/resources/update/static-var-compensator/staticVarCompensator_SSH.xml diff --git a/cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_SSH_1.xml b/cgmes/cgmes-conversion/src/test/resources/update/static-var-compensator/staticVarCompensator_SSH_1.xml similarity index 100% rename from cgmes/cgmes-conversion/src/test/resources/update/staticVarCompensator/staticVarCompensator_SSH_1.xml rename to cgmes/cgmes-conversion/src/test/resources/update/static-var-compensator/staticVarCompensator_SSH_1.xml diff --git a/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_EQ.xml index 2293c44384a..c2640b4e91b 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_EQ.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_EQ.xml @@ -9,73 +9,52 @@ - GeographicalRegionTest GeographicalRegionTest - SubGeographicalRegionTest SubGeographicalRegionTest - Substation1 Substation1 - BaseVoltage400 - Base Voltage Level 400kV 400.0 kV 400.0 - BaseVoltage220 - Base Voltage Level 220kV 220.0 kV 220.0 - BaseVoltage110 - Base Voltage Level 110kV 110.0 kV 110.0 - VoltageLevel1 VoltageLevel1 - 420 - 380 - ConnectivityNode1 Connectivity Node 1 - VoltageLevel2 VoltageLevel2 - 235 - 205 - ConnectivityNode2 Connectivity Node 2 - VoltageLevel3 VoltageLevel3 - 120 - 100 - ConnectivityNode3 Connectivity Node 3 @@ -102,7 +81,6 @@ T2W-Terminal1 1 - @@ -124,7 +102,6 @@ T2W-Terminal2 2 - @@ -172,7 +149,6 @@ T3W-Terminal1 1 - @@ -194,7 +170,6 @@ T3W-Terminal2 2 - @@ -216,7 +191,6 @@ T3W-Terminal3 3 - From b8b4897d6cd73efc2dca7fa5c5a078523916b362 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 22 Jan 2025 07:53:18 +0100 Subject: [PATCH 50/54] Improvements to previous PRs Signed-off-by: marquesja1 --- .../conversion/test/GeneratorUpdateTest.java | 19 ------------------- .../cgmes/conversion/test/LoadUpdateTest.java | 19 ------------------- .../test/StaticVarCompensatorUpdateTest.java | 12 ------------ .../test/TransformerUpdateTest.java | 17 ----------------- .../update/generator/generator_EQ.xml | 2 +- .../update/generator/generator_SSH.xml | 2 +- .../update/generator/generator_SSH_1.xml | 2 +- .../test/resources/update/load/load_EQ.xml | 2 +- .../test/resources/update/load/load_SSH.xml | 2 +- .../test/resources/update/load/load_SSH_1.xml | 2 +- .../update/transformer/transformer_EQ.xml | 2 +- .../update/transformer/transformer_SSH.xml | 2 +- .../update/transformer/transformer_SSH_1.xml | 2 +- 13 files changed, 9 insertions(+), 76 deletions(-) diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/GeneratorUpdateTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/GeneratorUpdateTest.java index 21ad7a4d07f..7103afb8270 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/GeneratorUpdateTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/GeneratorUpdateTest.java @@ -56,25 +56,6 @@ void importEqAndSshTogetherTest() { assertTrue(checkSsh(equivalentInjection, -184.0, 0.0, Double.NaN, false, 0.0, 0)); } - @Test - void importEqAndSshSeparatelyTest() { - Network network = readCgmesResources(DIR, "generator_EQ.xml"); - assertEquals(3, network.getGeneratorCount()); - - Generator synchronousMachine = network.getGenerator("SynchronousMachine"); - assertTrue(checkEq(synchronousMachine)); - Generator externalNetworkInjection = network.getGenerator("ExternalNetworkInjection"); - assertTrue(checkEq(externalNetworkInjection)); - Generator equivalentInjection = network.getGenerator("EquivalentInjection"); - assertTrue(checkEq(equivalentInjection)); - - readCgmesResources(network, DIR, "generator_SSH.xml"); - - assertTrue(checkSsh(synchronousMachine, 160.0, 0.0, 405.0, true, 0.0, 0)); - assertTrue(checkSsh(externalNetworkInjection, -0.0, -0.0, Double.NaN, false, 0.0, 0)); - assertTrue(checkSsh(equivalentInjection, -184.0, 0.0, Double.NaN, false, 0.0, 0)); - } - @Test void importEqAndTwoSshsTest() { Network network = readCgmesResources(DIR, "generator_EQ.xml"); diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java index 9f41f68417e..2c3ece482b4 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/LoadUpdateTest.java @@ -54,25 +54,6 @@ void importEqAndSshTogetherTest() { assertTrue(checkSsh(loadAsynchronousMachine, 200.0, 50.0)); } - @Test - void importEqAndSshSeparatelyTest() { - Network network = readCgmesResources(DIR, "load_EQ.xml"); - assertEquals(3, network.getLoadCount()); - - Load loadEnergyConsumer = network.getLoad("EnergyConsumer"); - assertTrue(checkEq(loadEnergyConsumer)); - Load loadEnergySource = network.getLoad("EnergySource"); - assertTrue(checkEq(loadEnergySource)); - Load loadAsynchronousMachine = network.getLoad("AsynchronousMachine"); - assertTrue(checkEq(loadAsynchronousMachine)); - - readCgmesResources(network, DIR, "load_SSH.xml"); - - assertTrue(checkSsh(loadEnergyConsumer, 10.0, 5.0)); - assertTrue(checkSsh(loadEnergySource, -200.0, -90.0)); - assertTrue(checkSsh(loadAsynchronousMachine, 200.0, 50.0)); - } - @Test void importEqAndTwoSshsTest() { Network network = readCgmesResources(DIR, "load_EQ.xml"); diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/StaticVarCompensatorUpdateTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/StaticVarCompensatorUpdateTest.java index 90552b8b2cd..59019ba29df 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/StaticVarCompensatorUpdateTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/StaticVarCompensatorUpdateTest.java @@ -42,18 +42,6 @@ void importEqAndSshTogetherTest() { assertTrue(checkSsh(staticVarCompensator, Double.NaN, 405.0, StaticVarCompensator.RegulationMode.VOLTAGE)); } - @Test - void importEqAndSshSeparatelyTest() { - Network network = readCgmesResources(DIR, "staticVarCompensator_EQ.xml"); - assertEquals(1, network.getStaticVarCompensatorCount()); - - StaticVarCompensator staticVarCompensator = network.getStaticVarCompensator("StaticVarCompensator"); - assertTrue(checkEq(staticVarCompensator)); - - readCgmesResources(network, DIR, "staticVarCompensator_SSH.xml"); - assertTrue(checkSsh(staticVarCompensator, Double.NaN, 405.0, StaticVarCompensator.RegulationMode.VOLTAGE)); - } - @Test void importEqAndTwoSshsTest() { Network network = readCgmesResources(DIR, "staticVarCompensator_EQ.xml"); diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/TransformerUpdateTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/TransformerUpdateTest.java index 7866bf5ad7a..fc96276af68 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/TransformerUpdateTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/TransformerUpdateTest.java @@ -50,23 +50,6 @@ void importEqAndSshTogetherTest() { assertTrue(checkSsh(t3w, 8, 225.0, 2.0, true)); } - @Test - void importEqAndSshSeparatelyTest() { - Network network = readCgmesResources(DIR, "transformer_EQ.xml"); - assertEquals(1, network.getTwoWindingsTransformerCount()); - assertEquals(1, network.getThreeWindingsTransformerCount()); - - TwoWindingsTransformer t2w = network.getTwoWindingsTransformer("T2W"); - assertTrue(checkEq(t2w)); - ThreeWindingsTransformer t3w = network.getThreeWindingsTransformer("T3W"); - assertTrue(checkEq(t3w)); - - readCgmesResources(network, DIR, "transformer_SSH.xml"); - - assertTrue(checkSsh(t2w, -2, 100.0, 0.2, true)); - assertTrue(checkSsh(t3w, 8, 225.0, 2.0, true)); - } - @Test void importEqAndTwoSshsTest() { Network network = readCgmesResources(DIR, "transformer_EQ.xml"); diff --git a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml index 23b957b72aa..5046c7dd5dd 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_EQ.xml @@ -3,7 +3,7 @@ 2024-02-21T11:00:00Z 2024-02-21T11:00:00Z 1 - All type of Generators + All types of Generators https://www.powsybl.org/ http://iec.ch/TC57/ns/CIM/CoreEquipment-EU/3.0 diff --git a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH.xml b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH.xml index 2f10c4ce23a..d0ef7a165ba 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH.xml @@ -3,7 +3,7 @@ 2024-02-21T11:00:00Z 2024-02-21T11:00:00Z 1 - All type of Generators + All types of Generators https://www.powsybl.org/ http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 diff --git a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH_1.xml b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH_1.xml index 1b7fea01163..a8e1ac11ca9 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH_1.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/generator/generator_SSH_1.xml @@ -3,7 +3,7 @@ 2024-02-21T11:00:00Z 2024-02-21T11:00:00Z 1 - All type of Generators + All types of Generators https://www.powsybl.org/ http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 diff --git a/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml index ca46a03a559..f702bebc074 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/load/load_EQ.xml @@ -3,7 +3,7 @@ 2024-02-21T11:00:00Z 2024-02-21T11:00:00Z 1 - All type of Loads + All types of Loads https://www.powsybl.org/ http://iec.ch/TC57/ns/CIM/CoreEquipment-EU/3.0 diff --git a/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH.xml b/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH.xml index 9ded0a48bbe..58d3585621a 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH.xml @@ -3,7 +3,7 @@ 2024-02-21T11:00:00Z 2024-02-21T11:00:00Z 1 - All type of Loads + All types of Loads https://www.powsybl.org/ http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 diff --git a/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH_1.xml b/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH_1.xml index efa3b861b10..9776820cacc 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH_1.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/load/load_SSH_1.xml @@ -3,7 +3,7 @@ 2024-02-21T11:00:00Z 2024-02-21T11:00:00Z 1 - All type of Loads + All types of Loads https://www.powsybl.org/ http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 diff --git a/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_EQ.xml index c2640b4e91b..090065fd336 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_EQ.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_EQ.xml @@ -3,7 +3,7 @@ 2024-02-21T11:00:00Z 2024-02-21T11:00:00Z 1 - All type of Loads + All types of Transformers https://www.powsybl.org/ http://iec.ch/TC57/ns/CIM/CoreEquipment-EU/3.0 diff --git a/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH.xml b/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH.xml index a8beb622703..1a68b3214eb 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH.xml @@ -3,7 +3,7 @@ 2024-02-21T11:00:00Z 2024-02-21T11:00:00Z 1 - All type of Loads + All types of Transformers https://www.powsybl.org/ http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 diff --git a/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH_1.xml b/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH_1.xml index 81e4bb574de..8121dac5959 100644 --- a/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH_1.xml +++ b/cgmes/cgmes-conversion/src/test/resources/update/transformer/transformer_SSH_1.xml @@ -3,7 +3,7 @@ 2024-02-21T11:00:00Z 2024-02-21T11:00:00Z 1 - All type of Loads + All types of Transformers https://www.powsybl.org/ http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0 From 23a4270bb5f41bf52b6e8fb25d4093500795fc9a Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Wed, 29 Jan 2025 16:04:46 +0100 Subject: [PATCH 51/54] Review regulatingControls and defaultValues Signed-off-by: marquesja1 --- .../conversion/RegulatingControlMapping.java | 16 +-- ...AbstractConductingEquipmentConversion.java | 124 ++++++++++++++---- .../AbstractIdentifiedObjectConversion.java | 85 +++++++++++- ...AbstractReactiveLimitsOwnerConversion.java | 107 +++++---------- .../AsynchronousMachineConversion.java | 16 +-- .../elements/EnergyConsumerConversion.java | 16 +-- .../elements/EnergySourceConversion.java | 16 +-- .../EquivalentInjectionConversion.java | 34 ++--- .../ExternalNetworkInjectionConversion.java | 2 +- .../elements/OperationalLimitConversion.java | 22 +--- .../StaticVarCompensatorConversion.java | 88 +++++-------- .../SynchronousMachineConversion.java | 2 +- .../AbstractTransformerConversion.java | 115 ++++++---------- .../com/powsybl/cgmes/model/CgmesNames.java | 5 + 14 files changed, 337 insertions(+), 311 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMapping.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMapping.java index e681534893a..186f07708aa 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMapping.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMapping.java @@ -7,6 +7,7 @@ */ package com.powsybl.cgmes.conversion; +import com.powsybl.cgmes.model.CgmesNames; import com.powsybl.iidm.network.Network; import com.powsybl.triplestore.api.PropertyBag; @@ -19,10 +20,7 @@ public class RegulatingControlMapping { static final String MISSING_IIDM_TERMINAL = "IIDM terminal for this CGMES terminal: %s"; - private static final String REGULATING_TERMINAL = "Regulating Terminal"; - private static final String REGULATING_CONTROL = "RegulatingControl"; - private static final String TERMINAL = "Terminal"; private static final String VOLTAGE = "voltage"; private final Context context; @@ -71,7 +69,7 @@ public static class RegulatingControl { RegulatingControl(PropertyBag p) { this.mode = p.get("mode").toLowerCase(); - this.cgmesTerminal = p.getId(TERMINAL); + this.cgmesTerminal = p.getId(CgmesNames.TERMINAL); this.enabled = p.asBoolean("enabled", true); this.targetValue = p.asDouble("targetValue"); // targetDeadband is optional in CGMES, @@ -106,7 +104,7 @@ public Map cachedRegulatingControls() { } void cacheRegulatingControls(PropertyBag p) { - cachedRegulatingControls.put(p.getId(REGULATING_CONTROL), new RegulatingControl(p)); + cachedRegulatingControls.put(p.getId(CgmesNames.REGULATING_CONTROL), new RegulatingControl(p)); } void setAllRegulatingControls(Network network) { @@ -126,15 +124,15 @@ void setAllRegulatingControls(Network network) { cachedRegulatingControls.clear(); } - public static boolean isControlModeVoltage(String controlMode) { + protected static boolean isControlModeVoltage(String controlMode) { return controlMode != null && controlMode.endsWith(VOLTAGE); } - public static boolean isControlModeReactivePower(String controlMode) { + protected static boolean isControlModeReactivePower(String controlMode) { return controlMode != null && controlMode.toLowerCase().endsWith("reactivepower"); } - static String getRegulatingControlId(PropertyBag p) { - return p.getId(REGULATING_CONTROL); + protected static String getRegulatingControlId(PropertyBag p) { + return p.getId(CgmesNames.REGULATING_CONTROL); } } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index 12a3e666006..060d221bed3 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -12,6 +12,8 @@ import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.conversion.ConversionException; import com.powsybl.cgmes.extensions.CgmesDanglingLineBoundaryNodeAdder; +import com.powsybl.cgmes.extensions.CgmesTapChanger; +import com.powsybl.cgmes.extensions.CgmesTapChangers; import com.powsybl.cgmes.model.*; import com.powsybl.commons.PowsyblException; import com.powsybl.iidm.network.*; @@ -510,7 +512,7 @@ protected void convertedTerminalsWithOnlyEq(Terminal... ts) { } } - protected static void updateTerminals(Connectable connectable, Context context, Terminal... ts) { + public static void updateTerminals(Connectable connectable, Context context, Terminal... ts) { PropertyBags cgmesTerminals = getCgmesTerminals(connectable, context, ts.length); for (int k = 0; k < ts.length; k++) { updateTerminal(cgmesTerminals.get(k), ts[k], context); @@ -806,31 +808,109 @@ protected static PowerFlow updatedPowerFlow(Connectable connectable, Property return PowerFlow.UNDEFINED; } - protected static double defaultValue(double eq, double previous, double defaultValue, double emptyValue, Conversion.Config.DefaultValue defaultValueSelector) { - return switch (defaultValueSelector) { - case EQ -> eq; - case PREVIOUS -> previous; - case DEFAULT -> defaultValue; - case EMPTY -> emptyValue; - }; + protected static boolean isControlModeVoltage(String controlMode) { + return controlMode != null && controlMode.endsWith("voltage"); } - protected static int defaultValue(int eq, int previous, int defaultValue, int emptyValue, Conversion.Config.DefaultValue defaultValueSelector) { - return switch (defaultValueSelector) { - case EQ -> eq; - case PREVIOUS -> previous; - case DEFAULT -> defaultValue; - case EMPTY -> emptyValue; - }; + protected static boolean isControlModeReactivePower(String controlMode) { + return controlMode != null && controlMode.toLowerCase().endsWith("reactivepower"); } - protected static boolean defaultValue(boolean eq, boolean previous, boolean defaultValue, boolean emptyValue, Conversion.Config.DefaultValue defaultValueSelector) { - return switch (defaultValueSelector) { - case EQ -> eq; - case PREVIOUS -> previous; - case DEFAULT -> defaultValue; - case EMPTY -> emptyValue; - }; + protected static String getRegulatingControlId(PropertyBag p) { + return p.getId(CgmesNames.REGULATING_CONTROL); + } + + protected static Optional findCgmesRegulatingControl(Connectable connectable, Context context) { + String regulatingControlId = connectable.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.REGULATING_CONTROL); + return regulatingControlId != null ? Optional.ofNullable(context.regulatingControl(regulatingControlId)) : Optional.empty(); + } + + protected static > Optional findCgmesRegulatingControl(Connectable tw, String tapChangerId, Context context) { + CgmesTapChangers cgmesTcs = tw.getExtension(CgmesTapChangers.class); + if (cgmesTcs != null && tapChangerId != null) { + CgmesTapChanger cgmesTc = cgmesTcs.getTapChanger(tapChangerId); + return cgmesTc != null ? Optional.ofNullable(context.regulatingControl(cgmesTc.getControlId())) : Optional.empty(); + } + return Optional.empty(); + } + + protected static int findTerminalSign(Connectable connectable) { + String terminalSign = connectable.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL_SIGN); + return terminalSign != null ? Integer.parseInt(terminalSign) : 1; + } + + protected static int findTerminalSign(Connectable connectable, String end) { + String terminalSign = connectable.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL_SIGN + end); + return terminalSign != null ? Integer.parseInt(terminalSign) : 1; + } + + protected static double findTargetV(PropertyBag regulatingControl, DefaultValueDouble defaultValue, DefaultValueUse use, Context context) { + return findTargetV(regulatingControl, CgmesNames.TARGET_VALUE, defaultValue, use, context); + } + + protected static double findTargetV(PropertyBag regulatingControl, String propertyTag, DefaultValueDouble defaultValue, DefaultValueUse use, Context context) { + double targetV = regulatingControl.asDouble(propertyTag); + return useDefaultValue(regulatingControl.containsKey(propertyTag), isValidTargetV(targetV), use) ? defaultValue(defaultValue, context) : targetV; + } + + protected static double findTargetQ(PropertyBag regulatingControl, int terminalSign, DefaultValueDouble defaultValue, DefaultValueUse use, Context context) { + return findTargetValue(regulatingControl, terminalSign, defaultValue, use, context); + } + + protected static double findTargetQ(PropertyBag regulatingControl, String propertyTag, int terminalSign, DefaultValueDouble defaultValue, DefaultValueUse use, Context context) { + return findTargetValue(regulatingControl, propertyTag, terminalSign, defaultValue, use, context); + } + + protected static double findTargetValue(PropertyBag regulatingControl, int terminalSign, DefaultValueDouble defaultValue, DefaultValueUse use, Context context) { + return findTargetValue(regulatingControl, CgmesNames.TARGET_VALUE, terminalSign, defaultValue, use, context); + } + + protected static double findTargetValue(PropertyBag regulatingControl, String propertyTag, int terminalSign, DefaultValueDouble defaultValue, DefaultValueUse use, Context context) { + double targetValue = regulatingControl.asDouble(propertyTag); + return useDefaultValue(regulatingControl.containsKey(propertyTag), isValidTargetValue(targetValue), use) ? defaultValue(defaultValue, context) : targetValue * terminalSign; + } + + protected static double findTargetDeadband(PropertyBag regulatingControl, DefaultValueDouble defaultValue, DefaultValueUse use, Context context) { + double targetDeadband = regulatingControl.asDouble(CgmesNames.TARGET_DEADBAND); + return useDefaultValue(regulatingControl.containsKey(CgmesNames.TARGET_DEADBAND), isValidTargetDeadband(targetDeadband), use) ? defaultValue(defaultValue, context) : targetDeadband; + } + + protected static boolean findRegulatingOn(PropertyBag regulatingControl, DefaultValueBoolean defaultValue, DefaultValueUse use, Context context) { + return findRegulatingOn(regulatingControl, CgmesNames.ENABLED, defaultValue, use, context); + } + + protected static boolean findRegulatingOn(PropertyBag regulatingControl, String propertyTag, DefaultValueBoolean defaultValue, DefaultValueUse use, Context context) { + Optional isRegulatingOn = regulatingControl.asBoolean(propertyTag); + return useDefaultValue(isRegulatingOn.isPresent(), true, use) ? defaultValue(defaultValue, context) : isRegulatingOn.orElse(false); + } + + private static boolean useDefaultValue(boolean isDefined, boolean isValid, DefaultValueUse use) { + return use == DefaultValueUse.ALWAYS + || use == DefaultValueUse.NOT_DEFINED && !isDefined + || use == DefaultValueUse.NOT_VALID && !isValid; + } + + protected static boolean isValidTargetV(double targetV) { + return targetV > 0.0; + } + + protected static boolean isValidTargetQ(double targetQ) { + return isValidTargetValue(targetQ); + } + + protected static boolean isValidTargetValue(double targetValue) { + return Double.isFinite(targetValue); + } + + protected static boolean isValidTargetDeadband(double targetDeadband) { + return targetDeadband >= 0.0; + } + + protected enum DefaultValueUse { + NEVER, + NOT_DEFINED, + NOT_VALID, + ALWAYS } private final TerminalData[] terminals; diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java index 56d0b011afc..4ec92e618a8 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java @@ -14,8 +14,10 @@ import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; +import java.util.ArrayList; import java.util.List; +import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.EMPTY; /** @@ -98,10 +100,91 @@ protected String complete(String what) { } } - protected static Conversion.Config.DefaultValue getDefaultValueSelector(List validDefaultValues, Context context) { + protected static double defaultValue(DefaultValueDouble defaultValue, Context context) { + List validDefaultValues = new ArrayList<>(); + if (defaultValue.equipmentValue != null) { + validDefaultValues.add(EQ); + } + if (defaultValue.previousValue != null) { + validDefaultValues.add(PREVIOUS); + } + if (defaultValue.defaultValue != null) { + validDefaultValues.add(DEFAULT); + } + validDefaultValues.add(EMPTY); + return defaultValue(defaultValue, getDefaultValueSelector(validDefaultValues, context)); + } + + private static double defaultValue(DefaultValueDouble defaultValue, Conversion.Config.DefaultValue defaultValueSelector) { + return switch (defaultValueSelector) { + case EQ -> defaultValue.equipmentValue; + case PREVIOUS -> defaultValue.previousValue; + case DEFAULT -> defaultValue.defaultValue; + case EMPTY -> defaultValue.emptyValue; + }; + } + + protected static int defaultValue(DefaultValueInteger defaultValue, Context context) { + List validDefaultValues = new ArrayList<>(); + if (defaultValue.equipmentValue != null) { + validDefaultValues.add(EQ); + } + if (defaultValue.previousValue != null) { + validDefaultValues.add(PREVIOUS); + } + if (defaultValue.defaultValue != null) { + validDefaultValues.add(DEFAULT); + } + validDefaultValues.add(EMPTY); + return defaultValue(defaultValue, getDefaultValueSelector(validDefaultValues, context)); + } + + private static int defaultValue(DefaultValueInteger defaultValue, Conversion.Config.DefaultValue defaultValueSelector) { + return switch (defaultValueSelector) { + case EQ -> defaultValue.equipmentValue; + case PREVIOUS -> defaultValue.previousValue; + case DEFAULT -> defaultValue.defaultValue; + case EMPTY -> defaultValue.emptyValue; + }; + } + + protected static boolean defaultValue(DefaultValueBoolean defaultValue, Context context) { + List validDefaultValues = new ArrayList<>(); + if (defaultValue.equipmentValue != null) { + validDefaultValues.add(EQ); + } + if (defaultValue.previousValue != null) { + validDefaultValues.add(PREVIOUS); + } + if (defaultValue.defaultValue != null) { + validDefaultValues.add(DEFAULT); + } + validDefaultValues.add(EMPTY); + return defaultValue(defaultValue, getDefaultValueSelector(validDefaultValues, context)); + } + + private static boolean defaultValue(DefaultValueBoolean defaultValue, Conversion.Config.DefaultValue defaultValueSelector) { + return switch (defaultValueSelector) { + case EQ -> defaultValue.equipmentValue; + case PREVIOUS -> defaultValue.previousValue; + case DEFAULT -> defaultValue.defaultValue; + case EMPTY -> defaultValue.emptyValue; + }; + } + + private static Conversion.Config.DefaultValue getDefaultValueSelector(List validDefaultValues, Context context) { return context.config().updateDefaultValuesPriority().stream().filter(validDefaultValues::contains).findFirst().orElse(EMPTY); } + public record DefaultValueDouble(Double equipmentValue, Double previousValue, Double defaultValue, double emptyValue) { + } + + public record DefaultValueInteger(Integer equipmentValue, Integer previousValue, Integer defaultValue, int emptyValue) { + } + + public record DefaultValueBoolean(Boolean equipmentValue, Boolean previousValue, Boolean defaultValue, boolean emptyValue) { + } + protected final String id; protected final String name; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractReactiveLimitsOwnerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractReactiveLimitsOwnerConversion.java index bdd41fcf3bc..82422e93ebd 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractReactiveLimitsOwnerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractReactiveLimitsOwnerConversion.java @@ -11,23 +11,18 @@ import com.google.common.collect.Range; import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.Conversion; -import com.powsybl.cgmes.conversion.RegulatingControlMapping; import com.powsybl.cgmes.model.CgmesNames; import com.powsybl.iidm.network.*; import com.powsybl.iidm.network.extensions.RemoteReactivePowerControl; import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.function.Supplier; import static com.powsybl.cgmes.conversion.CgmesReports.badVoltageTargetValueRegulatingControlReport; -import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; /** * @author Luma Zamarreño {@literal } @@ -150,107 +145,69 @@ protected void setMinPMaxP(GeneratorAdder adder, double minP, double maxP) { } protected static void updateRegulatingControl(Generator generator, boolean controlEnabled, Context context) { - String controlId = generator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.REGULATING_CONTROL); + //String controlId = generator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.REGULATING_CONTROL); String mode = generator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.MODE); - int terminalSign = findTerminalSign(generator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL_SIGN)); + //int terminalSign = findTerminalSign(generator); - updateRegulatingControl(generator, new RC(controlEnabled, mode, terminalSign), controlId, context); - } - - private static int findTerminalSign(String terminalSign) { - return terminalSign != null ? Integer.parseInt(terminalSign) : 1; - } - - private static void updateRegulatingControl(Generator generator, RC rc, String regulatingControlId, Context context) { - if (regulatingControlId == null) { - LOG.trace("Regulating control Id not present for generator {}", generator.getId()); - return; - } - - if (RegulatingControlMapping.isControlModeVoltage(rc.mode)) { - updateRegulatingControlVoltage(regulatingControlId, rc, generator, context); - } else if (RegulatingControlMapping.isControlModeReactivePower(rc.mode)) { - updateRegulatingControlReactivePower(regulatingControlId, rc, generator, context); + if (isControlModeVoltage(mode)) { + updateRegulatingControlVoltage(generator, controlEnabled, context); + } else if (isControlModeReactivePower(mode)) { + updateRegulatingControlReactivePower(generator, controlEnabled, context); } else { - context.ignored(rc.mode, "Unsupported regulation mode for generator " + generator.getId()); + context.ignored(mode, "Unsupported regulation mode for generator " + generator.getId()); } } - private static void updateRegulatingControlVoltage(String regulatingControlId, RC rc, Generator generator, Context context) { - Optional cgmesRegulatingControl = findCgmesRegulatingControl(regulatingControlId, context); + private static void updateRegulatingControlVoltage(Generator generator, boolean controlEnabled, Context context) { + Optional cgmesRegulatingControl = findCgmesRegulatingControl(generator, context); - double targetV = cgmesRegulatingControl.map(propertyBag -> findTargetV(propertyBag, generator, context)).orElseGet(() -> findDefaultTargetV(generator, context)); - boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, generator, context)).orElseGet(() -> findDefaultRegulatingOn(generator, context)); + DefaultValueDouble defaultTargetV = getDefaultTargetV(generator); + double targetV = cgmesRegulatingControl.map(propertyBag -> findTargetV(propertyBag, defaultTargetV, DefaultValueUse.NOT_VALID, context)).orElse(defaultValue(defaultTargetV, context)); + DefaultValueBoolean defaultRegulatingOn = getDefaultRegulatingOn(generator); + boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, defaultRegulatingOn, DefaultValueUse.NOT_DEFINED, context)).orElse(defaultValue(defaultRegulatingOn, context)); boolean validTargetV = isValidTargetV(targetV); if (!validTargetV) { - context.invalid(regulatingControlId, "Regulating control has a bad target voltage " + targetV); - badVoltageTargetValueRegulatingControlReport(context.getReportNode(), regulatingControlId, targetV); + context.invalid(generator.getId(), "Regulating control has a bad target voltage " + targetV); + badVoltageTargetValueRegulatingControlReport(context.getReportNode(), generator.getId(), targetV); } // Regulating control is enabled AND this equipment participates in regulating control - generator.setTargetV(targetV).setVoltageRegulatorOn(regulatingOn && rc.controlEnabled && validTargetV); + generator.setTargetV(targetV).setVoltageRegulatorOn(regulatingOn && controlEnabled && validTargetV); } - private static void updateRegulatingControlReactivePower(String regulatingControlId, RC rc, Generator generator, Context context) { + private static void updateRegulatingControlReactivePower(Generator generator, boolean controlEnabled, Context context) { RemoteReactivePowerControl remoteReactivePowerControl = generator.getExtension(RemoteReactivePowerControl.class); if (remoteReactivePowerControl == null || remoteReactivePowerControl.getRegulatingTerminal() == null) { return; } - Optional cgmesRegulatingControl = findCgmesRegulatingControl(regulatingControlId, context); - - double targetQ = cgmesRegulatingControl.map(propertyBag -> findTargetQ(propertyBag, rc.terminalSign)).orElseGet(() -> findDefaultTargetQ(remoteReactivePowerControl, context)); - boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, generator, context)).orElseGet(() -> findDefaultRegulatingOn(generator, context)); + Optional cgmesRegulatingControl = findCgmesRegulatingControl(generator, context); + int terminalSign = findTerminalSign(generator); + DefaultValueDouble defaultTargetQ = getDefaultTargetQ(remoteReactivePowerControl); + DefaultValueBoolean defaultRegulatingOn = getDefaultRegulatingOn(remoteReactivePowerControl); - remoteReactivePowerControl.setTargetQ(targetQ).setEnabled(regulatingOn && rc.controlEnabled && isValidTargetQ(targetQ)); - } + double targetQ = cgmesRegulatingControl.map(propertyBag -> findTargetQ(propertyBag, terminalSign, defaultTargetQ, DefaultValueUse.NOT_DEFINED, context)).orElse(defaultValue(defaultTargetQ, context)); + boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, defaultRegulatingOn, DefaultValueUse.NOT_DEFINED, context)).orElse(defaultValue(defaultRegulatingOn, context)); - private static double findTargetV(PropertyBag regulatingControl, Generator generator, Context context) { - double targetV = regulatingControl.asDouble("targetValue"); - return isValidTargetV(targetV) ? targetV : findDefaultTargetV(generator, context); + remoteReactivePowerControl.setTargetQ(targetQ).setEnabled(regulatingOn && controlEnabled && isValidTargetQ(targetQ)); } - private static double findDefaultTargetV(Generator generator, Context context) { + private static DefaultValueDouble getDefaultTargetV(Generator generator) { double defaultTargetV = generator.getRegulatingTerminal() != null ? generator.getRegulatingTerminal().getVoltageLevel().getNominalV() : generator.getTerminal().getVoltageLevel().getNominalV(); - return defaultValue(Double.NaN, generator.getTargetV(), defaultTargetV, Double.NaN, getDefaultValueSelector(context)); - } - - private static boolean findRegulatingOn(PropertyBag regulatingControl, Generator generator, Context context) { - return regulatingControl.asBoolean("enabled").orElse(findDefaultRegulatingOn(generator, context)); + return new DefaultValueDouble(null, generator.getTargetV(), defaultTargetV, Double.NaN); } - private static boolean findDefaultRegulatingOn(Generator generator, Context context) { - return defaultValue(false, generator.isVoltageRegulatorOn(), false, false, getDefaultValueSelector(context)); + private static DefaultValueBoolean getDefaultRegulatingOn(Generator generator) { + return new DefaultValueBoolean(false, generator.isVoltageRegulatorOn(), false, false); } - private static boolean isValidTargetV(double targetV) { - return Double.isFinite(targetV) && targetV > 0.0; + private static DefaultValueDouble getDefaultTargetQ(RemoteReactivePowerControl remoteReactivePowerControl) { + return new DefaultValueDouble(null, remoteReactivePowerControl.getTargetQ(), Double.NaN, Double.NaN); } - private static double findTargetQ(PropertyBag regulatingControl, int terminalSign) { - return regulatingControl.asDouble("targetValue") * terminalSign; + private static DefaultValueBoolean getDefaultRegulatingOn(RemoteReactivePowerControl remoteReactivePowerControl) { + return new DefaultValueBoolean(false, remoteReactivePowerControl.isEnabled(), false, false); } - - private static double findDefaultTargetQ(RemoteReactivePowerControl remoteReactivePowerControl, Context context) { - return defaultValue(Double.NaN, remoteReactivePowerControl.getTargetQ(), Double.NaN, Double.NaN, getDefaultValueSelector(context)); - } - - private static boolean isValidTargetQ(double targetValue) { - return Double.isFinite(targetValue); - } - - private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { - return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); - } - - private static Optional findCgmesRegulatingControl(String regulatingControlId, Context context) { - return regulatingControlId != null ? Optional.ofNullable(context.regulatingControl(regulatingControlId)) : Optional.empty(); - } - - private record RC(boolean controlEnabled, String mode, int terminalSign) { - } - - private static final Logger LOG = LoggerFactory.getLogger(AbstractReactiveLimitsOwnerConversion.class); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java index a476e60747f..f073fb20698 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AsynchronousMachineConversion.java @@ -17,10 +17,6 @@ import com.powsybl.iidm.network.LoadType; import com.powsybl.triplestore.api.PropertyBag; -import java.util.List; - -import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; - /** * @author Luma Zamarreño {@literal } */ @@ -54,12 +50,16 @@ public static void update(Load load, PropertyBag cgmesData, Context context) { updateTerminals(load, context, load.getTerminal()); PowerFlow updatedPowerFlow = updatedPowerFlow(load, cgmesData, context); - load.setP0(updatedPowerFlow.defined() ? updatedPowerFlow.p() : defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, gettDefaultValueSelector(context))); - load.setQ0(updatedPowerFlow.defined() ? updatedPowerFlow.q() : defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, gettDefaultValueSelector(context))); + load.setP0(updatedPowerFlow.defined() ? updatedPowerFlow.p() : defaultValue(getDefaultP(load), context)); + load.setQ0(updatedPowerFlow.defined() ? updatedPowerFlow.q() : defaultValue(getDefaultQ(load), context)); + } + + private static DefaultValueDouble getDefaultP(Load load) { + return new DefaultValueDouble(null, load.getP0(), 0.0, Double.NaN); } - private static Conversion.Config.DefaultValue gettDefaultValueSelector(Context context) { - return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); + private static DefaultValueDouble getDefaultQ(Load load) { + return new DefaultValueDouble(null, load.getQ0(), 0.0, Double.NaN); } } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java index dcb265f057b..92896b76f18 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergyConsumerConversion.java @@ -17,10 +17,6 @@ import com.powsybl.iidm.network.extensions.LoadDetailAdder; import com.powsybl.triplestore.api.PropertyBag; -import java.util.List; - -import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; - /** * @author Luma Zamarreño {@literal } */ @@ -146,14 +142,18 @@ public static void update(Load load, PropertyBag cgmesData, Context context) { double qFixed = Double.parseDouble(load.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.Q_FIXED)); PowerFlow updatedPowerFlow = updatedPowerFlow(load, cgmesData, context); - load.setP0(updatedPowerFlow.defined() ? updatedPowerFlow.p() : defaultValue(pFixed, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context))); - load.setQ0(updatedPowerFlow.defined() ? updatedPowerFlow.q() : defaultValue(qFixed, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context))); + load.setP0(updatedPowerFlow.defined() ? updatedPowerFlow.p() : defaultValue(getDefaultP(load, pFixed), context)); + load.setQ0(updatedPowerFlow.defined() ? updatedPowerFlow.q() : defaultValue(getDefaultQ(load, qFixed), context)); updateLoadDetail(load, load.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS), pFixed, qFixed); } - private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { - return getDefaultValueSelector(List.of(EQ, PREVIOUS, DEFAULT, EMPTY), context); + private static DefaultValueDouble getDefaultP(Load load, double pFixed) { + return new DefaultValueDouble(pFixed, load.getP0(), 0.0, Double.NaN); + } + + private static DefaultValueDouble getDefaultQ(Load load, double qFixed) { + return new DefaultValueDouble(qFixed, load.getQ0(), 0.0, Double.NaN); } private static void updateLoadDetail(Load load, String type, double pFixed, double qFixed) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java index 6572a7ec779..b8a083ba2ce 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EnergySourceConversion.java @@ -15,10 +15,6 @@ import com.powsybl.iidm.network.*; import com.powsybl.triplestore.api.PropertyBag; -import java.util.List; - -import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; - /** * @author Luma Zamarreño {@literal } */ @@ -50,11 +46,15 @@ public static void update(Load load, PropertyBag cgmesData, Context context) { updateTerminals(load, context, load.getTerminal()); PowerFlow updatedPowerFlow = updatedPowerFlow(load, cgmesData, context); - load.setP0(updatedPowerFlow.defined() ? updatedPowerFlow.p() : defaultValue(Double.NaN, load.getP0(), 0.0, Double.NaN, getDefaultValueSelector(context))); - load.setQ0(updatedPowerFlow.defined() ? updatedPowerFlow.q() : defaultValue(Double.NaN, load.getQ0(), 0.0, Double.NaN, getDefaultValueSelector(context))); + load.setP0(updatedPowerFlow.defined() ? updatedPowerFlow.p() : defaultValue(getDefaultP(load), context)); + load.setQ0(updatedPowerFlow.defined() ? updatedPowerFlow.q() : defaultValue(getDefaultQ(load), context)); + } + + private static DefaultValueDouble getDefaultP(Load load) { + return new DefaultValueDouble(null, load.getP0(), 0.0, Double.NaN); } - private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { - return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); + private static DefaultValueDouble getDefaultQ(Load load) { + return new DefaultValueDouble(null, load.getQ0(), 0.0, Double.NaN); } } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EquivalentInjectionConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EquivalentInjectionConversion.java index 385555180d6..1e7073b495a 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EquivalentInjectionConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/EquivalentInjectionConversion.java @@ -18,10 +18,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.List; - -import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; - /** * @author Luma Zamarreño {@literal } */ @@ -171,8 +167,10 @@ public static void update(Generator generator, PropertyBag cgmesData, Context co targetQ = -updatedPowerFlow.q(); } - double targetV = findTargetV(cgmesData, generator, context); - boolean regulatingOn = findRegulatingOn(cgmesData, generator, context); + DefaultValueDouble defaultTargetV = getDefaultTargetV(generator); + double targetV = findTargetV(cgmesData, CgmesNames.REGULATION_TARGET, defaultTargetV, DefaultValueUse.NOT_DEFINED, context); + DefaultValueBoolean defaultRegulatingOn = getDefaultRegulatingOn(generator); + boolean regulatingOn = findRegulatingOn(cgmesData, CgmesNames.REGULATION_STATUS, defaultRegulatingOn, DefaultValueUse.NOT_DEFINED, context); generator.setTargetP(targetP) .setTargetQ(targetQ) @@ -180,28 +178,12 @@ public static void update(Generator generator, PropertyBag cgmesData, Context co .setVoltageRegulatorOn(regulatingOn && regulationCapability && isValidTargetV(targetV)); } - private static double findTargetV(PropertyBag cgmesData, Generator generator, Context context) { - return cgmesData.containsKey(CgmesNames.REGULATION_TARGET) ? cgmesData.asDouble(CgmesNames.REGULATION_TARGET) : findDefaultTargetV(generator, context); - } - - private static double findDefaultTargetV(Generator generator, Context context) { - return defaultValue(Double.NaN, generator.getTargetV(), Double.NaN, Double.NaN, getDefaultValueSelector(context)); - } - - private static boolean findRegulatingOn(PropertyBag cgmesData, Generator generator, Context context) { - return cgmesData.asBoolean(CgmesNames.REGULATION_STATUS).orElse(findDefaultRegulatingOn(generator, context)); - } - - private static boolean findDefaultRegulatingOn(Generator generator, Context context) { - return defaultValue(false, generator.isVoltageRegulatorOn(), false, false, getDefaultValueSelector(context)); - } - - private static boolean isValidTargetV(double targetV) { - return Double.isFinite(targetV) && targetV > 0.0; + private static DefaultValueDouble getDefaultTargetV(Generator generator) { + return new DefaultValueDouble(null, generator.getTargetV(), Double.NaN, Double.NaN); } - private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { - return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); + private static DefaultValueBoolean getDefaultRegulatingOn(Generator generator) { + return new DefaultValueBoolean(false, generator.isVoltageRegulatorOn(), false, false); } private static final Logger LOG = LoggerFactory.getLogger(EquivalentInjectionConversion.class); diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/ExternalNetworkInjectionConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/ExternalNetworkInjectionConversion.java index 866643fd83a..921a95e8eaf 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/ExternalNetworkInjectionConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/ExternalNetworkInjectionConversion.java @@ -68,7 +68,7 @@ public static void update(Generator generator, PropertyBag cgmesData, Context co } generator.setTargetP(targetP).setTargetQ(targetQ); - boolean controlEnabled = cgmesData.asBoolean("controlEnabled", false); + boolean controlEnabled = cgmesData.asBoolean(CgmesNames.CONTROL_ENABLED, false); updateRegulatingControl(generator, controlEnabled, context); } } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java index e40a87760fc..cc240cd6614 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java @@ -19,14 +19,11 @@ import com.powsybl.iidm.network.*; import com.powsybl.triplestore.api.PropertyBag; -import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.OptionalDouble; import java.util.function.Supplier; -import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.EQ; -import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.PREVIOUS; import static com.powsybl.cgmes.conversion.Conversion.PROPERTY_OPERATIONAL_LIMIT_SET_IDENTIFIERS; /** @@ -524,14 +521,14 @@ private static void updateLoadingLimits(PR propertyNameData, LoadingLimits loadi private static double getValue(PR propertyNameData, Identifiable identifiable, double previousValue, Context context) { String operationalLimitId = getOperationalLimitId(getPropertyName(propertyNameData, CgmesNames.OPERATIONAL_LIMIT_SET), identifiable); - return updatedValue(operationalLimitId, context) - .orElse(defaultValue(getNormalValue(getPropertyName(propertyNameData, CgmesNames.NORMAL_VALUE), identifiable), previousValue, getDefaultValue(context))); + DefaultValueDouble defaultLimitValue = getDefaultValue(getNormalValue(getPropertyName(propertyNameData, CgmesNames.NORMAL_VALUE), identifiable), previousValue); + return updatedValue(operationalLimitId, context).orElse(defaultValue(defaultLimitValue, context)); } private static double getValue(TPR temporaryPropertyNameData, Identifiable identifiable, double previousValue, Context context) { String operationalLimitId = getOperationalLimitId(getPropertyName(temporaryPropertyNameData, CgmesNames.OPERATIONAL_LIMIT_SET), identifiable); - return updatedValue(operationalLimitId, context) - .orElse(defaultValue(getNormalValue(getPropertyName(temporaryPropertyNameData, CgmesNames.NORMAL_VALUE), identifiable), previousValue, getDefaultValue(context))); + DefaultValueDouble defaultLimitValue = getDefaultValue(getNormalValue(getPropertyName(temporaryPropertyNameData, CgmesNames.NORMAL_VALUE), identifiable), previousValue); + return updatedValue(operationalLimitId, context).orElse(defaultValue(defaultLimitValue, context)); } private static OptionalDouble updatedValue(String operationalLimitId, Context context) { @@ -567,15 +564,8 @@ private static String getPropertyName(TPR tpr, String tagProperty) { + tpr.duration; } - protected static double defaultValue(double normalValue, double previousValue, Conversion.Config.DefaultValue defaultValue) { - return switch (defaultValue) { - case EQ, DEFAULT, EMPTY -> normalValue; - case PREVIOUS -> previousValue; - }; - } - - private static Conversion.Config.DefaultValue getDefaultValue(Context context) { - return getDefaultValueSelector(List.of(EQ, PREVIOUS), context); + private static DefaultValueDouble getDefaultValue(double normalValue, double previousValue) { + return new DefaultValueDouble(normalValue, previousValue, normalValue, normalValue); } private record PR(String operationalLimitSetId, String limitSubclass, String end) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java index 29bfad5693f..5880c3ea1de 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/StaticVarCompensatorConversion.java @@ -10,7 +10,6 @@ import com.powsybl.cgmes.conversion.Context; import com.powsybl.cgmes.conversion.Conversion; -import com.powsybl.cgmes.conversion.RegulatingControlMapping; import com.powsybl.cgmes.conversion.RegulatingControlMappingForStaticVarCompensators; import com.powsybl.cgmes.model.CgmesNames; import com.powsybl.iidm.network.StaticVarCompensator; @@ -18,11 +17,8 @@ import com.powsybl.iidm.network.extensions.VoltagePerReactivePowerControlAdder; import com.powsybl.triplestore.api.PropertyBag; -import java.util.List; import java.util.Optional; -import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; - /** * @author Luma Zamarreño {@literal } */ @@ -76,36 +72,41 @@ private double checkSlope(double slope) { public static void update(StaticVarCompensator staticVarCompensator, PropertyBag cgmesData, Context context) { updateTerminals(staticVarCompensator, context, staticVarCompensator.getTerminal()); - double defaultTargetQ = cgmesData.asDouble("q"); - boolean controlEnabled = cgmesData.asBoolean("controlEnabled", false); - updateRegulatingControl(staticVarCompensator, defaultTargetQ, controlEnabled, context); + double defaultQ = cgmesData.asDouble("q"); + boolean controlEnabled = cgmesData.asBoolean(CgmesNames.CONTROL_ENABLED, false); + updateRegulatingControl(staticVarCompensator, defaultQ, controlEnabled, context); } - private static void updateRegulatingControl(StaticVarCompensator staticVarCompensator, double defaultTargetQ, boolean controlEnabled, Context context) { + private static void updateRegulatingControl(StaticVarCompensator staticVarCompensator, double defaultQ, boolean controlEnabled, Context context) { String defaultRegulationMode = staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "defaultRegulationMode"); String mode = staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.MODE); Optional cgmesRegulatingControl = findCgmesRegulatingControl(staticVarCompensator, context); - double defaultTargetV = findDefaultTargetV(staticVarCompensator); + double defaultEquipmentTargetV = findDefaultEquipmentTargetV(staticVarCompensator); - if (isDefaultVoltageControl(cgmesRegulatingControl.isEmpty(), controlEnabled, defaultRegulationMode, defaultTargetV)) { - setDefaultVoltageControl(staticVarCompensator, defaultTargetV, context); + if (isDefaultVoltageControl(cgmesRegulatingControl.isEmpty(), controlEnabled, defaultRegulationMode, defaultEquipmentTargetV)) { + setDefaultVoltageControl(staticVarCompensator, defaultEquipmentTargetV, context); return; } - boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, staticVarCompensator, context)).orElseGet(() -> findDefaultRegulatingOn(staticVarCompensator, context)); - if (isDefaultReactivePowerControl(regulatingOn, controlEnabled, defaultRegulationMode, defaultTargetQ)) { - setDefaultReactivePowerControl(staticVarCompensator, defaultTargetQ, context); + DefaultValueBoolean defaultRegulatingOn = getDefaultRegulatingOn(staticVarCompensator); + boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, defaultRegulatingOn, DefaultValueUse.NOT_DEFINED, context)).orElse(defaultValue(defaultRegulatingOn, context)); + if (isDefaultReactivePowerControl(regulatingOn, controlEnabled, defaultRegulationMode, defaultQ)) { + setDefaultReactivePowerControl(staticVarCompensator, defaultQ, context); return; } String selectedMode = mode != null ? mode : defaultRegulationMode; - if (selectedMode != null && RegulatingControlMapping.isControlModeVoltage(selectedMode.toLowerCase())) { - double targetV = cgmesRegulatingControl.map(StaticVarCompensatorConversion::findTargetV).orElseGet(() -> findDefaultTargetV(staticVarCompensator, defaultTargetV, context)); + if (selectedMode != null && isControlModeVoltage(selectedMode.toLowerCase())) { + DefaultValueDouble defaultTargetV = getDefaultTargetV(staticVarCompensator, defaultEquipmentTargetV); + double targetV = cgmesRegulatingControl.map(propertyBag -> findTargetV(propertyBag, defaultTargetV, DefaultValueUse.NOT_DEFINED, context)).orElse(defaultValue(defaultTargetV, context)); StaticVarCompensator.RegulationMode regulationMode = controlEnabled && regulatingOn && isValidTargetV(targetV) ? StaticVarCompensator.RegulationMode.VOLTAGE : StaticVarCompensator.RegulationMode.OFF; + staticVarCompensator.setVoltageSetpoint(targetV).setRegulationMode(regulationMode); - } else if (selectedMode != null && RegulatingControlMapping.isControlModeReactivePower(selectedMode.toLowerCase())) { - double targetQ = cgmesRegulatingControl.map(StaticVarCompensatorConversion::findTargetQ).orElseGet(() -> findDefaultTargetQ(staticVarCompensator, defaultTargetQ, context)); + } else if (selectedMode != null && isControlModeReactivePower(selectedMode.toLowerCase())) { + DefaultValueDouble defaultTargetQ = getDefaultTargetQ(staticVarCompensator, defaultQ); + double targetQ = cgmesRegulatingControl.map(propertyBag -> findTargetQ(propertyBag, 1, defaultTargetQ, DefaultValueUse.NOT_DEFINED, context)).orElse(defaultValue(defaultTargetQ, context)); StaticVarCompensator.RegulationMode regulationMode = controlEnabled && regulatingOn && isValidTargetQ(targetQ) ? StaticVarCompensator.RegulationMode.REACTIVE_POWER : StaticVarCompensator.RegulationMode.OFF; + staticVarCompensator.setReactivePowerSetpoint(targetQ).setRegulationMode(regulationMode); } else { context.ignored(mode, "Unsupported regulation mode for staticVarCompensator " + staticVarCompensator.getId()); @@ -115,7 +116,7 @@ private static void updateRegulatingControl(StaticVarCompensator staticVarCompen private static boolean isDefaultVoltageControl(boolean cgmesRegulatingControlIsNotDefined, boolean controlEnabled, String defaultRegulationMode, double defaultTargetV) { return cgmesRegulatingControlIsNotDefined && controlEnabled - && defaultRegulationMode != null && RegulatingControlMapping.isControlModeVoltage(defaultRegulationMode.toLowerCase()) + && defaultRegulationMode != null && isControlModeVoltage(defaultRegulationMode.toLowerCase()) && isValidTargetV(defaultTargetV); } @@ -128,7 +129,7 @@ private static void setDefaultVoltageControl(StaticVarCompensator staticVarCompe private static boolean isDefaultReactivePowerControl(boolean regulatingOn, boolean controlEnabled, String defaultRegulationMode, double defaultTargetQ) { return !regulatingOn && controlEnabled - && defaultRegulationMode != null && RegulatingControlMapping.isControlModeReactivePower(defaultRegulationMode.toLowerCase()) + && defaultRegulationMode != null && isControlModeReactivePower(defaultRegulationMode.toLowerCase()) && isValidTargetQ(defaultTargetQ); } @@ -138,51 +139,22 @@ private static void setDefaultReactivePowerControl(StaticVarCompensator staticVa staticVarCompensator.setReactivePowerSetpoint(defaultTargetQ).setRegulationMode(StaticVarCompensator.RegulationMode.REACTIVE_POWER); } - private static Optional findCgmesRegulatingControl(StaticVarCompensator staticVarCompensator, Context context) { - String regulatingControlId = staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.REGULATING_CONTROL); - return regulatingControlId != null ? Optional.ofNullable(context.regulatingControl(regulatingControlId)) : Optional.empty(); - } - - private static double findDefaultTargetV(StaticVarCompensator staticVarCompensator) { + private static double findDefaultEquipmentTargetV(StaticVarCompensator staticVarCompensator) { String defaultTargetVoltage = staticVarCompensator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "defaultTargetVoltage"); return defaultTargetVoltage != null ? Double.parseDouble(defaultTargetVoltage) : Double.NaN; } - private static double findTargetV(PropertyBag regulatingControl) { - return regulatingControl.asDouble("targetValue"); - } - - private static double findDefaultTargetV(StaticVarCompensator staticVarCompensator, double defaultTargetV, Context context) { - return defaultValue(Double.NaN, staticVarCompensator.getVoltageSetpoint(), defaultTargetV, Double.NaN, getDefaultValueSelector(context)); - } - - private static boolean isValidTargetV(double targetV) { - return Double.isFinite(targetV) && targetV > 0.0; - } - - private static double findTargetQ(PropertyBag regulatingControl) { - return regulatingControl.asDouble("targetValue"); - } - - private static double findDefaultTargetQ(StaticVarCompensator staticVarCompensator, double defaultTargetQ, Context context) { - return defaultValue(Double.NaN, staticVarCompensator.getReactivePowerSetpoint(), defaultTargetQ, Double.NaN, getDefaultValueSelector(context)); - } - - private static boolean isValidTargetQ(double targetValue) { - return Double.isFinite(targetValue); - } - - private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { - return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); + private static DefaultValueDouble getDefaultTargetV(StaticVarCompensator staticVarCompensator, double defaultEquipmentTargetV) { + return new DefaultValueDouble(defaultEquipmentTargetV, staticVarCompensator.getVoltageSetpoint(), Double.NaN, Double.NaN); } - private static boolean findRegulatingOn(PropertyBag regulatingControl, StaticVarCompensator staticVarCompensator, Context context) { - return regulatingControl.asBoolean("enabled").orElse(findDefaultRegulatingOn(staticVarCompensator, context)); + private static DefaultValueDouble getDefaultTargetQ(StaticVarCompensator staticVarCompensator, double defaultTargetQ) { + return new DefaultValueDouble(null, staticVarCompensator.getReactivePowerSetpoint(), defaultTargetQ, Double.NaN); } - private static boolean findDefaultRegulatingOn(StaticVarCompensator staticVarCompensator, Context context) { - return defaultValue(false, staticVarCompensator.getRegulationMode() == StaticVarCompensator.RegulationMode.VOLTAGE || - staticVarCompensator.getRegulationMode() == StaticVarCompensator.RegulationMode.REACTIVE_POWER, - false, false, getDefaultValueSelector(context)); + private static DefaultValueBoolean getDefaultRegulatingOn(StaticVarCompensator staticVarCompensator) { + return new DefaultValueBoolean(null, + staticVarCompensator.getRegulationMode() != StaticVarCompensator.RegulationMode.OFF, + false, false); } } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/SynchronousMachineConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/SynchronousMachineConversion.java index fee0176139a..3e7c060e662 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/SynchronousMachineConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/SynchronousMachineConversion.java @@ -154,7 +154,7 @@ public static void update(Generator generator, PropertyBag cgmesData, Context co if (operatingMode != null) { generator.setProperty(Conversion.PROPERTY_CGMES_SYNCHRONOUS_MACHINE_OPERATING_MODE, operatingMode.replace("SynchronousMachineOperatingMode.", "")); } - boolean controlEnabled = cgmesData.asBoolean("controlEnabled", false); + boolean controlEnabled = cgmesData.asBoolean(CgmesNames.CONTROL_ENABLED, false); updateRegulatingControl(generator, controlEnabled, context); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java index 2a87333f21e..5f99eaa1032 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/transformers/AbstractTransformerConversion.java @@ -29,8 +29,6 @@ import java.util.OptionalInt; import static com.powsybl.cgmes.conversion.CgmesReports.*; -import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; -import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.EMPTY; /** * @author Luma Zamarreño {@literal } @@ -183,17 +181,23 @@ static > void updatePhaseTapChanger(Connectable tw, private static > void updateRatioTapChanger(Connectable tw, RatioTapChanger rtc, String end, Context context, boolean isRegulatingAllowed) { String ratioTapChangerId = findTapChangerId(tw, Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.RATIO_TAP_CHANGER + end); + DefaultValueInteger defaultTapPosition = getDefaultTapPosition(tw, rtc, ratioTapChangerId); int tapPosition = findCgmesRatioTapChanger(ratioTapChangerId, context) - .map(propertyBag -> findTapPosition(tw, propertyBag, rtc, ratioTapChangerId, context)) - .orElseGet(() -> findDefaultTapPosition(tw, rtc, ratioTapChangerId, context)); - int validTapPosition = isValidTapPosition(rtc, tapPosition) ? tapPosition : findDefaultTapPosition(tw, rtc, ratioTapChangerId, context); + .map(propertyBag -> findTapPosition(propertyBag, defaultTapPosition, context)) + .orElse(defaultValue(defaultTapPosition, context)); + int validTapPosition = isValidTapPosition(rtc, tapPosition) ? tapPosition : defaultValue(defaultTapPosition, context); rtc.setTapPosition(validTapPosition); if (regulatingControlIsDefined(rtc.getRegulationTerminal())) { Optional cgmesRegulatingControl = findCgmesRegulatingControl(tw, ratioTapChangerId, context); - double targetV = cgmesRegulatingControl.map(AbstractTransformerConversion::findTargetV).orElseGet(() -> findDefaultTargetV(rtc, context)); - double targetDeadband = cgmesRegulatingControl.map(AbstractTransformerConversion::findTargetDeadband).orElseGet(() -> findDefaultTargetDeadband(rtc, context)); - boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, rtc, context)).orElseGet(() -> findDefaultRegulatingOn(rtc, context)); + DefaultValueDouble defaultTargetV = getDefaultTargetV(rtc); + double targetV = cgmesRegulatingControl.map(propertyBag -> findTargetV(propertyBag, defaultTargetV, DefaultValueUse.NOT_DEFINED, context)).orElse(defaultValue(defaultTargetV, context)); + + DefaultValueDouble defaultTargetDeadband = getDefaultTargetDeadband(rtc); + double targetDeadband = cgmesRegulatingControl.map(propertyBag -> findTargetDeadband(propertyBag, defaultTargetDeadband, DefaultValueUse.NOT_DEFINED, context)).orElse(defaultValue(defaultTargetDeadband, context)); + + DefaultValueBoolean defaultRegulatingOn = getDefaultRegulatingOn(rtc); + boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, defaultRegulatingOn, DefaultValueUse.NOT_DEFINED, context)).orElse(defaultValue(defaultRegulatingOn, context)); // We always keep the targetValue // It targetValue is not valid, emit a warning and deactivate regulating control @@ -218,17 +222,23 @@ private static > void updateRatioTapChanger(Connectable private static > void updatePhaseTapChanger(Connectable tw, PhaseTapChanger ptc, String end, Context context, boolean isRegulatingAllowed) { String phaseTapChangerId = findTapChangerId(tw, Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.PHASE_TAP_CHANGER + end); + DefaultValueInteger defaultTapPosition = getDefaultTapPosition(tw, ptc, phaseTapChangerId); int tapPosition = findCgmesPhaseTapChanger(phaseTapChangerId, context) - .map(propertyBag -> findTapPosition(tw, propertyBag, ptc, phaseTapChangerId, context)) - .orElseGet(() -> findDefaultTapPosition(tw, ptc, phaseTapChangerId, context)); - int validTapPosition = isValidTapPosition(ptc, tapPosition) ? tapPosition : findDefaultTapPosition(tw, ptc, phaseTapChangerId, context); + .map(propertyBag -> findTapPosition(propertyBag, defaultTapPosition, context)) + .orElse(defaultValue(defaultTapPosition, context)); + int validTapPosition = isValidTapPosition(ptc, tapPosition) ? tapPosition : defaultValue(defaultTapPosition, context); ptc.setTapPosition(validTapPosition); if (regulatingControlIsDefined(ptc.getRegulationTerminal())) { Optional cgmesRegulatingControl = findCgmesRegulatingControl(tw, phaseTapChangerId, context); - double targetValue = cgmesRegulatingControl.map(propertyBag -> findTargetValue(propertyBag, findTerminalSign(tw, end))).orElseGet(() -> findDefaultTargetValue(ptc, context)); - double targetDeadband = cgmesRegulatingControl.map(AbstractTransformerConversion::findTargetDeadband).orElseGet(() -> findDefaultTargetDeadband(ptc, context)); - boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, ptc, context)).orElseGet(() -> findDefaultRegulatingOn(ptc, context)); + DefaultValueDouble defaultTargetValue = getDefaultTargetValue(ptc); + double targetValue = cgmesRegulatingControl.map(propertyBag -> findTargetValue(propertyBag, findTerminalSign(tw, end), defaultTargetValue, DefaultValueUse.NOT_DEFINED, context)).orElse(defaultValue(defaultTargetValue, context)); + + DefaultValueDouble defaultTargetDeadband = getDefaultTargetDeadband(ptc); + double targetDeadband = cgmesRegulatingControl.map(propertyBag -> findTargetDeadband(propertyBag, defaultTargetDeadband, DefaultValueUse.NOT_DEFINED, context)).orElse(defaultValue(defaultTargetDeadband, context)); + + DefaultValueBoolean defaultRegulatingOn = getDefaultRegulatingOn(ptc); + boolean regulatingOn = cgmesRegulatingControl.map(propertyBag -> findRegulatingOn(propertyBag, defaultRegulatingOn, DefaultValueUse.NOT_DEFINED, context)).orElse(defaultValue(defaultRegulatingOn, context)); boolean fixedRegulating = regulatingOn; if (regulatingOn && ptc.getRegulationMode() == PhaseTapChanger.RegulationMode.FIXED_TAP) { @@ -267,30 +277,16 @@ private static Optional findCgmesPhaseTapChanger(String phaseTapCha return phaseTapChangerId != null ? Optional.ofNullable(context.phaseTapChanger(phaseTapChangerId)) : Optional.empty(); } - private static > Optional findCgmesRegulatingControl(Connectable tw, String tapChangerId, Context context) { - CgmesTapChangers cgmesTcs = tw.getExtension(CgmesTapChangers.class); - if (cgmesTcs != null && tapChangerId != null) { - CgmesTapChanger cgmesTc = cgmesTcs.getTapChanger(tapChangerId); - return cgmesTc != null ? Optional.ofNullable(context.regulatingControl(cgmesTc.getControlId())) : Optional.empty(); - } - return Optional.empty(); - } - - private static > int findTapPosition(Connectable tw, PropertyBag p, com.powsybl.iidm.network.TapChanger tapChanger, String tapChangerId, Context context) { + private static int findTapPosition(PropertyBag p, DefaultValueInteger defaultTapPosition, Context context) { OptionalInt tapPosition = findTapPosition(p, context); - return tapPosition.isPresent() ? tapPosition.getAsInt() : findDefaultTapPosition(tw, tapChanger, tapChangerId, context); + return tapPosition.isPresent() ? tapPosition.getAsInt() : defaultValue(defaultTapPosition, context); } - private static > int findDefaultTapPosition(Connectable tw, com.powsybl.iidm.network.TapChanger tapChanger, String tapChangerId, Context context) { - return defaultValue(getNormalStep(tw, tapChangerId), + private static > DefaultValueInteger getDefaultTapPosition(Connectable tw, com.powsybl.iidm.network.TapChanger tapChanger, String tapChangerId) { + return new DefaultValueInteger(getNormalStep(tw, tapChangerId), tapChanger.getTapPosition(), tapChanger.getNeutralPosition().orElse(getNormalStep(tw, tapChangerId)), - tapChanger.getNeutralPosition().orElse(getNormalStep(tw, tapChangerId)), - getDefaultValueSelectorForTapPosition(context)); - } - - private static Conversion.Config.DefaultValue getDefaultValueSelectorForTapPosition(Context context) { - return getDefaultValueSelector(List.of(EQ, PREVIOUS, DEFAULT), context); + tapChanger.getNeutralPosition().orElse(getNormalStep(tw, tapChangerId))); } private static boolean isValidTapPosition(com.powsybl.iidm.network.TapChanger tapChanger, int tapPosition) { @@ -344,58 +340,21 @@ private static > boolean isHiddenTapChanger(Connectable return false; } - private static > int findTerminalSign(Connectable tw, String end) { - String terminalSign = tw.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TERMINAL_SIGN + end); - return terminalSign != null ? Integer.parseInt(terminalSign) : 1; - } - - private static double findTargetV(PropertyBag regulatingControl) { - return regulatingControl.asDouble("targetValue"); - } - - private static double findDefaultTargetV(com.powsybl.iidm.network.RatioTapChanger ratioTapChanger, Context context) { - return defaultValue(Double.NaN, ratioTapChanger.getTargetV(), Double.NaN, Double.NaN, getDefaultValueSelector(context)); - } - - private static boolean isValidTargetV(double targetV) { - return Double.isFinite(targetV) && targetV > 0.0; - } - - private static double findTargetValue(PropertyBag regulatingControl, int terminalSign) { - return regulatingControl.asDouble("targetValue") * terminalSign; - } - - private static double findDefaultTargetValue(com.powsybl.iidm.network.PhaseTapChanger phaseTapChanger, Context context) { - return defaultValue(Double.NaN, phaseTapChanger.getRegulationValue(), Double.NaN, Double.NaN, getDefaultValueSelector(context)); + private static DefaultValueDouble getDefaultTargetV(com.powsybl.iidm.network.RatioTapChanger ratioTapChanger) { + return new DefaultValueDouble(null, ratioTapChanger.getTargetV(), Double.NaN, Double.NaN); } - private static boolean isValidTargetValue(double targetValue) { - return Double.isFinite(targetValue); + private static DefaultValueDouble getDefaultTargetValue(com.powsybl.iidm.network.PhaseTapChanger phaseTapChanger) { + return new DefaultValueDouble(null, phaseTapChanger.getRegulationValue(), Double.NaN, Double.NaN); } // targetDeadBand is optional in Cgmes and mandatory in IIDM then a default value is provided when it is not defined in Cgmes - private static double findTargetDeadband(PropertyBag regulatingControl) { - return regulatingControl.asDouble("targetDeadband"); - } - - private static double findDefaultTargetDeadband(com.powsybl.iidm.network.TapChanger tapChanger, Context context) { - return defaultValue(Double.NaN, tapChanger.getTargetDeadband(), 0.0, 0.0, getDefaultValueSelector(context)); - } - - private static boolean isValidTargetDeadband(double targetDeadband) { - return Double.isFinite(targetDeadband) && targetDeadband >= 0.0; - } - - private static boolean findRegulatingOn(PropertyBag regulatingControl, com.powsybl.iidm.network.TapChanger tapChanger, Context context) { - return regulatingControl.asBoolean("enabled").orElse(findDefaultRegulatingOn(tapChanger, context)); - } - - private static boolean findDefaultRegulatingOn(com.powsybl.iidm.network.TapChanger tapChanger, Context context) { - return defaultValue(false, tapChanger.isRegulating(), false, false, getDefaultValueSelector(context)); + private static DefaultValueDouble getDefaultTargetDeadband(com.powsybl.iidm.network.TapChanger tapChanger) { + return new DefaultValueDouble(0.0, tapChanger.getTargetDeadband(), 0.0, 0.0); } - private static Conversion.Config.DefaultValue getDefaultValueSelector(Context context) { - return getDefaultValueSelector(List.of(PREVIOUS, DEFAULT, EMPTY), context); + private static DefaultValueBoolean getDefaultRegulatingOn(com.powsybl.iidm.network.TapChanger tapChanger) { + return new DefaultValueBoolean(false, tapChanger.isRegulating(), false, false); } static boolean checkOnlyOneEnabled(boolean isAllowedToRegulate, boolean previousTapChangerIsRegulatingOn) { diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java index 88ac9af13db..ee45e942fdd 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java @@ -155,6 +155,11 @@ public final class CgmesNames { public static final String REGULATION_STATUS = "regulationStatus"; public static final String MODE = "mode"; public static final String INITIAL_P = "initialP"; + public static final String NORMAL_SECTIONS = "normalSections"; + public static final String TARGET_VALUE = "targetValue"; + public static final String TARGET_DEADBAND = "targetDeadband"; + public static final String ENABLED = "enabled"; + public static final String CONTROL_ENABLED = "controlEnabled"; private CgmesNames() { } From e74ff92afd3c51b0ef14bc360e2777aafe2bb8f3 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 30 Jan 2025 08:43:12 +0100 Subject: [PATCH 52/54] Minor changes Signed-off-by: marquesja1 --- .../cgmes/conversion/RegulatingControlMapping.java | 5 ++--- .../elements/AbstractConductingEquipmentConversion.java | 8 ++------ .../elements/AbstractReactiveLimitsOwnerConversion.java | 2 -- .../src/main/java/com/powsybl/cgmes/model/CgmesNames.java | 2 ++ 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMapping.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMapping.java index 186f07708aa..d80bc4e19ad 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMapping.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingControlMapping.java @@ -21,7 +21,6 @@ public class RegulatingControlMapping { static final String MISSING_IIDM_TERMINAL = "IIDM terminal for this CGMES terminal: %s"; private static final String REGULATING_TERMINAL = "Regulating Terminal"; - private static final String VOLTAGE = "voltage"; private final Context context; private final RegulatingControlMappingForGenerators regulatingControlMappingForGenerators; @@ -125,11 +124,11 @@ void setAllRegulatingControls(Network network) { } protected static boolean isControlModeVoltage(String controlMode) { - return controlMode != null && controlMode.endsWith(VOLTAGE); + return controlMode != null && controlMode.endsWith(CgmesNames.VOLTAGE_TAG); } protected static boolean isControlModeReactivePower(String controlMode) { - return controlMode != null && controlMode.toLowerCase().endsWith("reactivepower"); + return controlMode != null && controlMode.toLowerCase().endsWith(CgmesNames.REACTIVE_POWER); } protected static String getRegulatingControlId(PropertyBag p) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java index 060d221bed3..6b6397e39aa 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractConductingEquipmentConversion.java @@ -809,15 +809,11 @@ protected static PowerFlow updatedPowerFlow(Connectable connectable, Property } protected static boolean isControlModeVoltage(String controlMode) { - return controlMode != null && controlMode.endsWith("voltage"); + return controlMode != null && controlMode.endsWith(CgmesNames.VOLTAGE_TAG); } protected static boolean isControlModeReactivePower(String controlMode) { - return controlMode != null && controlMode.toLowerCase().endsWith("reactivepower"); - } - - protected static String getRegulatingControlId(PropertyBag p) { - return p.getId(CgmesNames.REGULATING_CONTROL); + return controlMode != null && controlMode.toLowerCase().endsWith(CgmesNames.REACTIVE_POWER); } protected static Optional findCgmesRegulatingControl(Connectable connectable, Context context) { diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractReactiveLimitsOwnerConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractReactiveLimitsOwnerConversion.java index 82422e93ebd..313cdd1feaa 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractReactiveLimitsOwnerConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractReactiveLimitsOwnerConversion.java @@ -145,9 +145,7 @@ protected void setMinPMaxP(GeneratorAdder adder, double minP, double maxP) { } protected static void updateRegulatingControl(Generator generator, boolean controlEnabled, Context context) { - //String controlId = generator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.REGULATING_CONTROL); String mode = generator.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.MODE); - //int terminalSign = findTerminalSign(generator); if (isControlModeVoltage(mode)) { updateRegulatingControlVoltage(generator, controlEnabled, context); diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java index ee45e942fdd..40019f88382 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java @@ -160,6 +160,8 @@ public final class CgmesNames { public static final String TARGET_DEADBAND = "targetDeadband"; public static final String ENABLED = "enabled"; public static final String CONTROL_ENABLED = "controlEnabled"; + public static final String REACTIVE_POWER = "reactivepower"; + public static final String VOLTAGE_TAG = "voltage"; private CgmesNames() { } From f052643091ff362924c8ad8c7f1e2cc203bb592f Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 30 Jan 2025 15:10:40 +0100 Subject: [PATCH 53/54] Improve context and remove unused code Signed-off-by: marquesja1 --- .../com/powsybl/cgmes/conversion/Context.java | 53 +++------- .../powsybl/cgmes/conversion/Conversion.java | 7 +- .../AbstractIdentifiedObjectConversion.java | 100 ++++++------------ .../com/powsybl/cgmes/model/CgmesNames.java | 1 - 4 files changed, 47 insertions(+), 114 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java index 71a66ecd321..9138064e86f 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Context.java @@ -199,69 +199,42 @@ public PropertyBags reactiveCapabilityCurveData(String curveId) { return cachedGroupedReactiveCapabilityCurveData.getOrDefault(curveId, new PropertyBags()); } - public void loadCgmesTerminals() { - cgmes.terminals().forEach(p -> { - String id = p.getId(CgmesNames.TERMINAL); - cgmesTerminals.put(id, p); + public void buildUpdateCache() { + buildUpdateCache(cgmesTerminals, cgmes.terminals(), CgmesNames.TERMINAL); + buildUpdateCache(ratioTapChangers, cgmes.ratioTapChangers(), CgmesNames.RATIO_TAP_CHANGER); + buildUpdateCache(phaseTapChangers, cgmes.phaseTapChangers(), CgmesNames.PHASE_TAP_CHANGER); + buildUpdateCache(regulatingControls, cgmes.regulatingControls(), CgmesNames.REGULATING_CONTROL); + buildUpdateCache(operationalLimits, cgmes.operationalLimits(), CgmesNames.OPERATIONAL_LIMIT); + buildUpdateCache(generatingUnits, cgmes.generatingUnits(), CgmesNames.GENERATING_UNIT); + } + + private static void buildUpdateCache(Map cache, PropertyBags cgmesPropertyBags, String tagId) { + cgmesPropertyBags.forEach(p -> { + String id = p.getId(tagId); + cache.put(id, p); }); - } public PropertyBag cgmesTerminal(String id) { return cgmesTerminals.get(id); } - public void loadRatioTapChangers() { - cgmes.ratioTapChangers().forEach(p -> { - String id = p.getId(CgmesNames.RATIO_TAP_CHANGER); - ratioTapChangers.put(id, p); - }); - } - public PropertyBag ratioTapChanger(String id) { return ratioTapChangers.get(id); } - public void loadPhaseTapChangers() { - cgmes.phaseTapChangers().forEach(p -> { - String id = p.getId(CgmesNames.PHASE_TAP_CHANGER); - phaseTapChangers.put(id, p); - }); - } - public PropertyBag phaseTapChanger(String id) { return phaseTapChangers.get(id); } - public void loadRegulatingControls() { - cgmes.regulatingControls().forEach(p -> { - String id = p.getId(CgmesNames.REGULATING_CONTROL); - regulatingControls.put(id, p); - }); - } - public PropertyBag regulatingControl(String id) { return regulatingControls.get(id); } - public void loadOperationalLimits() { - cgmes.operationalLimits().forEach(op -> { - String id = op.getId(CgmesNames.OPERATIONAL_LIMIT); - operationalLimits.put(id, op); - }); - } - public PropertyBag operationalLimit(String id) { return operationalLimits.get(id); } - public void loadGeneratingUnits() { - cgmes.generatingUnits().forEach(generatingUnit -> { - String id = generatingUnit.getId(CgmesNames.GENERATING_UNIT); - generatingUnits.put(id, generatingUnit); - }); - } - public PropertyBag generatingUnit(String id) { return generatingUnits.get(id); } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java index f1ad5310397..3f5d4b71875 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java @@ -542,12 +542,7 @@ private Context createContext(Network network, ReportNode reportNode) { private Context createUpdateContext(Network network, ReportNode reportNode) { Context context = new Context(cgmes, config, network, reportNode); - context.loadCgmesTerminals(); - context.loadRatioTapChangers(); - context.loadPhaseTapChangers(); - context.loadRegulatingControls(); - context.loadOperationalLimits(); - context.loadGeneratingUnits(); + context.buildUpdateCache(); return context; } diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java index 4ec92e618a8..6b9e08404b4 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java @@ -14,9 +14,6 @@ import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; -import java.util.ArrayList; -import java.util.List; - import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.*; import static com.powsybl.cgmes.conversion.Conversion.Config.DefaultValue.EMPTY; @@ -101,79 +98,48 @@ protected String complete(String what) { } protected static double defaultValue(DefaultValueDouble defaultValue, Context context) { - List validDefaultValues = new ArrayList<>(); - if (defaultValue.equipmentValue != null) { - validDefaultValues.add(EQ); - } - if (defaultValue.previousValue != null) { - validDefaultValues.add(PREVIOUS); + for (Conversion.Config.DefaultValue defaultValueSelector : context.config().updateDefaultValuesPriority()) { + if (defaultValueSelector == EQ && defaultValue.equipmentValue != null) { + return defaultValue.equipmentValue; + } else if (defaultValueSelector == PREVIOUS && defaultValue.previousValue != null) { + return defaultValue.previousValue; + } else if (defaultValueSelector == DEFAULT && defaultValue.defaultValue != null) { + return defaultValue.defaultValue; + } else if (defaultValueSelector == EMPTY) { + return defaultValue.emptyValue; + } } - if (defaultValue.defaultValue != null) { - validDefaultValues.add(DEFAULT); - } - validDefaultValues.add(EMPTY); - return defaultValue(defaultValue, getDefaultValueSelector(validDefaultValues, context)); - } - - private static double defaultValue(DefaultValueDouble defaultValue, Conversion.Config.DefaultValue defaultValueSelector) { - return switch (defaultValueSelector) { - case EQ -> defaultValue.equipmentValue; - case PREVIOUS -> defaultValue.previousValue; - case DEFAULT -> defaultValue.defaultValue; - case EMPTY -> defaultValue.emptyValue; - }; + return defaultValue.emptyValue; } protected static int defaultValue(DefaultValueInteger defaultValue, Context context) { - List validDefaultValues = new ArrayList<>(); - if (defaultValue.equipmentValue != null) { - validDefaultValues.add(EQ); - } - if (defaultValue.previousValue != null) { - validDefaultValues.add(PREVIOUS); + for (Conversion.Config.DefaultValue defaultValueSelector : context.config().updateDefaultValuesPriority()) { + if (defaultValueSelector == EQ && defaultValue.equipmentValue != null) { + return defaultValue.equipmentValue; + } else if (defaultValueSelector == PREVIOUS && defaultValue.previousValue != null) { + return defaultValue.previousValue; + } else if (defaultValueSelector == DEFAULT && defaultValue.defaultValue != null) { + return defaultValue.defaultValue; + } else if (defaultValueSelector == EMPTY) { + return defaultValue.emptyValue; + } } - if (defaultValue.defaultValue != null) { - validDefaultValues.add(DEFAULT); - } - validDefaultValues.add(EMPTY); - return defaultValue(defaultValue, getDefaultValueSelector(validDefaultValues, context)); - } - - private static int defaultValue(DefaultValueInteger defaultValue, Conversion.Config.DefaultValue defaultValueSelector) { - return switch (defaultValueSelector) { - case EQ -> defaultValue.equipmentValue; - case PREVIOUS -> defaultValue.previousValue; - case DEFAULT -> defaultValue.defaultValue; - case EMPTY -> defaultValue.emptyValue; - }; + return defaultValue.emptyValue; } protected static boolean defaultValue(DefaultValueBoolean defaultValue, Context context) { - List validDefaultValues = new ArrayList<>(); - if (defaultValue.equipmentValue != null) { - validDefaultValues.add(EQ); - } - if (defaultValue.previousValue != null) { - validDefaultValues.add(PREVIOUS); + for (Conversion.Config.DefaultValue defaultValueSelector : context.config().updateDefaultValuesPriority()) { + if (defaultValueSelector == EQ && defaultValue.equipmentValue != null) { + return defaultValue.equipmentValue; + } else if (defaultValueSelector == PREVIOUS && defaultValue.previousValue != null) { + return defaultValue.previousValue; + } else if (defaultValueSelector == DEFAULT && defaultValue.defaultValue != null) { + return defaultValue.defaultValue; + } else if (defaultValueSelector == EMPTY) { + return defaultValue.emptyValue; + } } - if (defaultValue.defaultValue != null) { - validDefaultValues.add(DEFAULT); - } - validDefaultValues.add(EMPTY); - return defaultValue(defaultValue, getDefaultValueSelector(validDefaultValues, context)); - } - - private static boolean defaultValue(DefaultValueBoolean defaultValue, Conversion.Config.DefaultValue defaultValueSelector) { - return switch (defaultValueSelector) { - case EQ -> defaultValue.equipmentValue; - case PREVIOUS -> defaultValue.previousValue; - case DEFAULT -> defaultValue.defaultValue; - case EMPTY -> defaultValue.emptyValue; - }; - } - - private static Conversion.Config.DefaultValue getDefaultValueSelector(List validDefaultValues, Context context) { - return context.config().updateDefaultValuesPriority().stream().filter(validDefaultValues::contains).findFirst().orElse(EMPTY); + return defaultValue.emptyValue; } public record DefaultValueDouble(Double equipmentValue, Double previousValue, Double defaultValue, double emptyValue) { diff --git a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java index 40019f88382..ea7b6e772ec 100644 --- a/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java +++ b/cgmes/cgmes-model/src/main/java/com/powsybl/cgmes/model/CgmesNames.java @@ -155,7 +155,6 @@ public final class CgmesNames { public static final String REGULATION_STATUS = "regulationStatus"; public static final String MODE = "mode"; public static final String INITIAL_P = "initialP"; - public static final String NORMAL_SECTIONS = "normalSections"; public static final String TARGET_VALUE = "targetValue"; public static final String TARGET_DEADBAND = "targetDeadband"; public static final String ENABLED = "enabled"; From b1dcad88df1b0c2ac7954a88562db278d7157295 Mon Sep 17 00:00:00 2001 From: marquesja1 Date: Thu, 30 Jan 2025 15:48:26 +0100 Subject: [PATCH 54/54] Remove duplicated code Signed-off-by: marquesja1 --- .../AbstractIdentifiedObjectConversion.java | 51 +++++++------------ 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java index 6b9e08404b4..6ed733a4d1c 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/AbstractIdentifiedObjectConversion.java @@ -98,48 +98,33 @@ protected String complete(String what) { } protected static double defaultValue(DefaultValueDouble defaultValue, Context context) { - for (Conversion.Config.DefaultValue defaultValueSelector : context.config().updateDefaultValuesPriority()) { - if (defaultValueSelector == EQ && defaultValue.equipmentValue != null) { - return defaultValue.equipmentValue; - } else if (defaultValueSelector == PREVIOUS && defaultValue.previousValue != null) { - return defaultValue.previousValue; - } else if (defaultValueSelector == DEFAULT && defaultValue.defaultValue != null) { - return defaultValue.defaultValue; - } else if (defaultValueSelector == EMPTY) { - return defaultValue.emptyValue; - } - } - return defaultValue.emptyValue; + Double result = defaultValue(defaultValue.equipmentValue, defaultValue.previousValue, defaultValue.defaultValue, defaultValue.emptyValue, context); + return result != null ? result : defaultValue.emptyValue; } protected static int defaultValue(DefaultValueInteger defaultValue, Context context) { - for (Conversion.Config.DefaultValue defaultValueSelector : context.config().updateDefaultValuesPriority()) { - if (defaultValueSelector == EQ && defaultValue.equipmentValue != null) { - return defaultValue.equipmentValue; - } else if (defaultValueSelector == PREVIOUS && defaultValue.previousValue != null) { - return defaultValue.previousValue; - } else if (defaultValueSelector == DEFAULT && defaultValue.defaultValue != null) { - return defaultValue.defaultValue; - } else if (defaultValueSelector == EMPTY) { - return defaultValue.emptyValue; - } - } - return defaultValue.emptyValue; + Integer result = defaultValue(defaultValue.equipmentValue, defaultValue.previousValue, defaultValue.defaultValue, defaultValue.emptyValue, context); + return result != null ? result : defaultValue.emptyValue; } protected static boolean defaultValue(DefaultValueBoolean defaultValue, Context context) { + Boolean result = defaultValue(defaultValue.equipmentValue, defaultValue.previousValue, defaultValue.defaultValue, defaultValue.emptyValue, context); + return result != null ? result : defaultValue.emptyValue; + } + + private static T defaultValue(T equipmentValue, T previousValue, T defaultValue, T emptyValue, Context context) { for (Conversion.Config.DefaultValue defaultValueSelector : context.config().updateDefaultValuesPriority()) { - if (defaultValueSelector == EQ && defaultValue.equipmentValue != null) { - return defaultValue.equipmentValue; - } else if (defaultValueSelector == PREVIOUS && defaultValue.previousValue != null) { - return defaultValue.previousValue; - } else if (defaultValueSelector == DEFAULT && defaultValue.defaultValue != null) { - return defaultValue.defaultValue; - } else if (defaultValueSelector == EMPTY) { - return defaultValue.emptyValue; + if (defaultValueSelector == EQ && equipmentValue != null) { + return equipmentValue; + } else if (defaultValueSelector == PREVIOUS && previousValue != null) { + return previousValue; + } else if (defaultValueSelector == DEFAULT && defaultValue != null) { + return defaultValue; + } else if (defaultValueSelector == EMPTY && emptyValue != null) { + return emptyValue; } } - return defaultValue.emptyValue; + return emptyValue; } public record DefaultValueDouble(Double equipmentValue, Double previousValue, Double defaultValue, double emptyValue) {