diff --git a/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/DslFilteredEquipment.groovy b/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/DslFilteredEquipment.groovy index 35664efa0..873479b23 100644 --- a/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/DslFilteredEquipment.groovy +++ b/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/DslFilteredEquipment.groovy @@ -20,13 +20,18 @@ import java.util.function.Predicate */ class DslFilteredEquipment extends DslEquipment { - private final Predicate typePredicate + protected final Predicate typePredicate DslFilteredEquipment(String equipmentType, Predicate typePredicate) { super(equipmentType) this.typePredicate = typePredicate } + DslFilteredEquipment(String equipmentType, String fieldName, Predicate typePredicate) { + super(equipmentType, fieldName) + this.typePredicate = typePredicate + } + @Override void addEquipment(String equipmentId, Function equipmentSupplier) { staticId = equipmentId diff --git a/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/automatons/TapChangerBlockingAutomatonGroovyExtension.groovy b/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/automatons/TapChangerBlockingAutomatonGroovyExtension.groovy index 376f81cf4..d859f9b01 100644 --- a/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/automatons/TapChangerBlockingAutomatonGroovyExtension.groovy +++ b/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/automatons/TapChangerBlockingAutomatonGroovyExtension.groovy @@ -14,13 +14,9 @@ import com.powsybl.dynamicsimulation.groovy.DynamicModelGroovyExtension import com.powsybl.dynawaltz.dsl.AbstractPureDynamicGroovyExtension import com.powsybl.dynawaltz.dsl.Reporters import com.powsybl.dynawaltz.dsl.builders.AbstractPureDynamicModelBuilder +import com.powsybl.dynawaltz.dsl.builders.BuildersUtil import com.powsybl.dynawaltz.models.automatons.TapChangerBlockingAutomaton -import com.powsybl.iidm.network.Bus -import com.powsybl.iidm.network.Identifiable -import com.powsybl.iidm.network.IdentifiableType -import com.powsybl.iidm.network.Load -import com.powsybl.iidm.network.Network -import com.powsybl.iidm.network.TwoWindingsTransformer +import com.powsybl.iidm.network.* /** * @author Laurent Issertial {@literal } @@ -43,7 +39,7 @@ class TapChangerBlockingAutomatonGroovyExtension extends AbstractPureDynamicGroo List loads = [] List transformers = [] - List uMeasurements = [] + List uMeasurements = [] List tapChangerAutomatonIds = [] TCBAutomatonBuilder(Network network, String lib, Reporter reporter) { @@ -77,12 +73,27 @@ class TapChangerBlockingAutomatonGroovyExtension extends AbstractPureDynamicGroo } void uMeasurements(String[] staticIds) { - uMeasurements = staticIds.collect { - def bus = network.busBreakerView.getBus(it) - if (!bus) { - Reporters.reportStaticIdUnknown(reporter, "uMeasurements", it, IdentifiableType.BUS.toString()) + for (staticId in staticIds) { + def measurementPoint = network.getIdentifiable(staticId) + if (!measurementPoint || !BuildersUtil.isActionConnectionPoint(measurementPoint.type)) { + Reporters.reportStaticIdUnknown(reporter, "uMeasurements", staticId, "BUS/BUSBAR_SECTION") + } else { + uMeasurements << measurementPoint + } + } + } + + void uMeasurements(List[] staticIdsArray) { + for (staticIds in staticIdsArray) { + for (staticId in staticIds) { + def measurementPoint = network.getIdentifiable(staticId) + if (!measurementPoint || !BuildersUtil.isActionConnectionPoint(measurementPoint.type)) { + Reporters.reportStaticIdUnknown(reporter, "uMeasurements", staticId, "BUS/BUSBAR_SECTION") + } else { + uMeasurements << measurementPoint + break + } } - bus } } @@ -91,12 +102,6 @@ class TapChangerBlockingAutomatonGroovyExtension extends AbstractPureDynamicGroo if (!uMeasurements) { Reporters.reportFieldNotSet(reporter, "uMeasurements") isInstantiable = false - } else { - uMeasurements -= null - if (!uMeasurements) { - Reporters.reportEmptyList(reporter, "uMeasurements") - isInstantiable = false - } } if(!loads && !transformers && !tapChangerAutomatonIds) { Reporters.reportEmptyList(reporter, "transformers") diff --git a/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/builders/BuildersUtil.groovy b/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/builders/BuildersUtil.groovy new file mode 100644 index 000000000..cd349a425 --- /dev/null +++ b/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/builders/BuildersUtil.groovy @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2023, 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.dynawaltz.dsl.builders + + +import com.powsybl.iidm.network.IdentifiableType + +/** + * @author Laurent Issertial {@literal } + */ +final class BuildersUtil { + + private BuildersUtil() { + } + + private static final EnumSet ACTION_CONNECTION_POINTS = EnumSet.of(IdentifiableType.BUS, IdentifiableType.BUSBAR_SECTION) + + static boolean isActionConnectionPoint(IdentifiableType type) { + return ACTION_CONNECTION_POINTS.contains(type) + } +} diff --git a/dynawaltz-dsl/src/test/java/com/powsybl/dynawaltz/dsl/DynamicModelsSupplierTest.java b/dynawaltz-dsl/src/test/java/com/powsybl/dynawaltz/dsl/DynamicModelsSupplierTest.java index 063ce9a59..fd7a16a2f 100644 --- a/dynawaltz-dsl/src/test/java/com/powsybl/dynawaltz/dsl/DynamicModelsSupplierTest.java +++ b/dynawaltz-dsl/src/test/java/com/powsybl/dynawaltz/dsl/DynamicModelsSupplierTest.java @@ -34,6 +34,7 @@ import com.powsybl.dynawaltz.models.generators.WeccGen; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; +import com.powsybl.iidm.network.test.FourSubstationsNodeBreakerFactory; import com.powsybl.iidm.network.test.HvdcTestNetwork; import com.powsybl.iidm.network.test.SvcTestCaseFactory; import org.junit.jupiter.params.ParameterizedTest; @@ -138,7 +139,8 @@ private static Stream provideAutomatonModelData() { Arguments.of("/dynamicModels/currentLimit.groovy", CurrentLimitAutomaton.class, EurostagTutorialExample1Factory.create(), "AM_NHV1_NHV2_1", "CLA", "CurrentLimitAutomaton"), Arguments.of("/dynamicModels/currentLimitTwoLevels.groovy", CurrentLimitTwoLevelsAutomaton.class, EurostagTutorialExample1Factory.create(), "AM_NHV1_NHV2_1", "CLA", "CurrentLimitAutomatonTwoLevels"), Arguments.of("/dynamicModels/tapChanger.groovy", TapChangerAutomaton.class, EurostagTutorialExample1Factory.create(), "TC", "tc", "TapChangerAutomaton"), - Arguments.of("/dynamicModels/tapChangerBlocking.groovy", TapChangerBlockingAutomaton.class, EurostagTutorialExample1Factory.create(), "ZAB", "ZAB", "TapChangerBlockingAutomaton1"), + Arguments.of("/dynamicModels/tapChangerBlockingBusBar.groovy", TapChangerBlockingAutomaton.class, FourSubstationsNodeBreakerFactory.create(), "ZAB", "ZAB", "TapChangerBlockingAutomaton2"), + Arguments.of("/dynamicModels/tapChangerBlocking.groovy", TapChangerBlockingAutomaton.class, EurostagTutorialExample1Factory.create(), "ZAB", "ZAB", "TapChangerBlockingAutomaton3"), Arguments.of("/dynamicModels/phaseShifterI.groovy", PhaseShifterIAutomaton.class, EurostagTutorialExample1Factory.create(), "PS_NGEN_NHV1", "ps", "PhaseShifterI"), Arguments.of("/dynamicModels/phaseShifterP.groovy", PhaseShifterPAutomaton.class, EurostagTutorialExample1Factory.create(), "PS_NGEN_NHV1", "ps", "PhaseShifterP"), Arguments.of("/dynamicModels/underVoltage.groovy", UnderVoltageAutomaton.class, EurostagTutorialExample1Factory.create(), "UV_GEN", "uv", "UnderVoltageAutomaton") @@ -251,8 +253,20 @@ private static Stream provideWarningsModel() { + DSL tests + Groovy Dynamic Models Supplier + DSL model builder for TapChangerBlockingAutomaton - 'uMeasurements' field value 'LOAD' not found for equipment type(s) BUS - 'uMeasurements' list is empty + 'uMeasurements' field value 'LOAD' not found for equipment type(s) BUS/BUSBAR_SECTION + 'uMeasurements' field value 'Wrong_ID' not found for equipment type(s) BUS/BUSBAR_SECTION + 'uMeasurements' field is not set + Model ZAB cannot be instantiated + """), + Arguments.of("/warnings/tapChangerMissingBusList.groovy", EurostagTutorialExample1Factory.create(), + """ + + DSL tests + + Groovy Dynamic Models Supplier + + DSL model builder for TapChangerBlockingAutomaton + 'uMeasurements' field value 'LOAD' not found for equipment type(s) BUS/BUSBAR_SECTION + 'uMeasurements' field value 'Wrong_ID' not found for equipment type(s) BUS/BUSBAR_SECTION + 'uMeasurements' field value 'NGEN_NHV1' not found for equipment type(s) BUS/BUSBAR_SECTION + 'uMeasurements' field is not set Model ZAB cannot be instantiated """), Arguments.of("/warnings/tapChangerCompatible.groovy", EurostagTutorialExample1Factory.create(), diff --git a/dynawaltz-dsl/src/test/resources/dynamicModels/tapChangerBlocking.groovy b/dynawaltz-dsl/src/test/resources/dynamicModels/tapChangerBlocking.groovy index e6e9d7d88..d11424d4b 100644 --- a/dynawaltz-dsl/src/test/resources/dynamicModels/tapChangerBlocking.groovy +++ b/dynawaltz-dsl/src/test/resources/dynamicModels/tapChangerBlocking.groovy @@ -8,10 +8,9 @@ package dynamicModels - TapChangerBlockingAutomaton { dynamicModelId "ZAB" parameterSetId "ZAB" - uMeasurements "NGEN" + uMeasurements ["OldId", "NGEN", "NHV1"], ["NHV1", "OldId"], ["NHV2"] transformers "NGEN_NHV1", "NHV2_NLOAD", "LOAD" } diff --git a/dynawaltz-dsl/src/test/resources/dynamicModels/tapChangerBlockingBusBar.groovy b/dynawaltz-dsl/src/test/resources/dynamicModels/tapChangerBlockingBusBar.groovy new file mode 100644 index 000000000..3372d8f88 --- /dev/null +++ b/dynawaltz-dsl/src/test/resources/dynamicModels/tapChangerBlockingBusBar.groovy @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2023, 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 dynamicModels + + +TapChangerBlockingAutomaton { + dynamicModelId "ZAB" + parameterSetId "ZAB" + uMeasurements "S1VL2_BBS1", "OldId", "S3VL1_BBS" + transformers "TWT", "LD1" +} diff --git a/dynawaltz-dsl/src/test/resources/warnings/tapChangerMissingBus.groovy b/dynawaltz-dsl/src/test/resources/warnings/tapChangerMissingBus.groovy index 0d7763638..b205fe9e0 100644 --- a/dynawaltz-dsl/src/test/resources/warnings/tapChangerMissingBus.groovy +++ b/dynawaltz-dsl/src/test/resources/warnings/tapChangerMissingBus.groovy @@ -12,6 +12,6 @@ package warnings TapChangerBlockingAutomaton { dynamicModelId "ZAB" parameterSetId "ZAB" - uMeasurements "LOAD" + uMeasurements "LOAD", "Wrong_ID" transformers "NGEN_NHV1", "NHV2_NLOAD", "LOAD" } diff --git a/dynawaltz-dsl/src/test/resources/warnings/tapChangerMissingBusList.groovy b/dynawaltz-dsl/src/test/resources/warnings/tapChangerMissingBusList.groovy new file mode 100644 index 000000000..036e8aa03 --- /dev/null +++ b/dynawaltz-dsl/src/test/resources/warnings/tapChangerMissingBusList.groovy @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2023, 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 warnings + + +TapChangerBlockingAutomaton { + dynamicModelId "ZAB" + parameterSetId "ZAB" + uMeasurements ["LOAD", "Wrong_ID"], ["NGEN_NHV1"] + transformers "NGEN_NHV1", "NHV2_NLOAD", "LOAD" +} diff --git a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/automatons/TapChangerBlockingAutomaton.java b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/automatons/TapChangerBlockingAutomaton.java index 8fcabd3c3..9d14fca14 100644 --- a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/automatons/TapChangerBlockingAutomaton.java +++ b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/automatons/TapChangerBlockingAutomaton.java @@ -16,7 +16,7 @@ import com.powsybl.dynawaltz.models.buses.ActionConnectionPoint; import com.powsybl.dynawaltz.models.macroconnections.MacroConnectionsAdder; import com.powsybl.dynawaltz.models.transformers.TapChangerModel; -import com.powsybl.iidm.network.Bus; +import com.powsybl.iidm.network.Identifiable; import com.powsybl.iidm.network.IdentifiableType; import com.powsybl.iidm.network.Load; import com.powsybl.iidm.network.TwoWindingsTransformer; @@ -36,10 +36,10 @@ public class TapChangerBlockingAutomaton extends AbstractPureDynamicBlackBoxMode private final List transformers; private final List loadsWithTransformer; private final List tapChangerAutomatonIds; - private final List uMeasurements; + private final List> uMeasurements; private boolean isConnected = true; - public TapChangerBlockingAutomaton(String dynamicModelId, String parameterSetId, List transformers, List loadsWithTransformer, List tapChangerAutomatonIds, List uMeasurements) { + public TapChangerBlockingAutomaton(String dynamicModelId, String parameterSetId, List transformers, List loadsWithTransformer, List tapChangerAutomatonIds, List> uMeasurements) { super(dynamicModelId, parameterSetId); this.transformers = Objects.requireNonNull(transformers); this.loadsWithTransformer = Objects.requireNonNull(loadsWithTransformer); @@ -56,11 +56,11 @@ public TapChangerBlockingAutomaton(String dynamicModelId, String parameterSetId, } } - public TapChangerBlockingAutomaton(String dynamicModelId, String parameterSetId, List transformers, List loadsWithTransformer, List uMeasurements) { + public TapChangerBlockingAutomaton(String dynamicModelId, String parameterSetId, List transformers, List loadsWithTransformer, List> uMeasurements) { this(dynamicModelId, parameterSetId, transformers, loadsWithTransformer, Collections.emptyList(), uMeasurements); } - public TapChangerBlockingAutomaton(String dynamicModelId, String parameterSetId, List transformers, List uMeasurements) { + public TapChangerBlockingAutomaton(String dynamicModelId, String parameterSetId, List transformers, List> uMeasurements) { this(dynamicModelId, parameterSetId, transformers, Collections.emptyList(), Collections.emptyList(), uMeasurements); } @@ -97,8 +97,8 @@ public void createMacroConnections(MacroConnectionsAdder adder) { } if (!transformers.isEmpty() || skippedTapChangers < (loadsWithTransformer.size() + tapChangerAutomatonIds.size())) { int i = 1; - for (Bus bus : uMeasurements) { - adder.createMacroConnections(this, bus, ActionConnectionPoint.class, this::getVarConnectionsWith, MeasurementPointSuffix.of(i)); + for (Identifiable measurement : uMeasurements) { + adder.createMacroConnections(this, measurement, ActionConnectionPoint.class, this::getVarConnectionsWith, MeasurementPointSuffix.of(i)); i++; } } else { diff --git a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/defaultmodels/DefaultModelConfiguration.java b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/defaultmodels/DefaultModelConfiguration.java index 40e61b648..6e7acc7c3 100644 --- a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/defaultmodels/DefaultModelConfiguration.java +++ b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/defaultmodels/DefaultModelConfiguration.java @@ -30,6 +30,9 @@ */ public enum DefaultModelConfiguration { + ACTION_CONNECTION_POINT_BBS(IdentifiableType.BUSBAR_SECTION, + ActionConnectionPoint.class, + new DefaultModelFactory<>(DefaultActionConnectionPoint::new)), ACTION_CONNECTION_POINT(IdentifiableType.BUS, ActionConnectionPoint.class, new DefaultModelFactory<>(DefaultActionConnectionPoint::new)), diff --git a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/defaultmodels/DefaultModelsHandler.java b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/defaultmodels/DefaultModelsHandler.java index bf06f38ff..e7c4deba8 100644 --- a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/defaultmodels/DefaultModelsHandler.java +++ b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/defaultmodels/DefaultModelsHandler.java @@ -13,7 +13,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.*; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; import static java.util.stream.Collectors.groupingBy; diff --git a/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/TapChangerBlockingAutomatonXmlTest.java b/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/TapChangerBlockingAutomatonXmlTest.java index 4ecfc2dc2..14d00b826 100644 --- a/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/TapChangerBlockingAutomatonXmlTest.java +++ b/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/TapChangerBlockingAutomatonXmlTest.java @@ -13,6 +13,7 @@ import com.powsybl.dynawaltz.models.loads.LoadTwoTransformersTapChangers; import com.powsybl.dynawaltz.models.transformers.TransformerFixedRatio; import com.powsybl.iidm.network.Bus; +import com.powsybl.iidm.network.Identifiable; import com.powsybl.iidm.network.TwoWindingsTransformer; import com.powsybl.iidm.network.VoltageLevel; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; @@ -61,9 +62,9 @@ void writeModel() throws SAXException, IOException, XMLStreamException { @Test void testMonitoredEquipmentsLimit() { - List buses = List.of(network.getBusBreakerView().getBus("NHV1")); + List> buses = List.of(network.getBusBreakerView().getBus("NHV1")); List transformers = List.of(network.getTwoWindingsTransformer("NGEN_NHV1")); - List tooManyBuses = List.of(network.getBusBreakerView().getBus("NHV1"), + List> tooManyBuses = List.of(network.getBusBreakerView().getBus("NHV1"), network.getBusBreakerView().getBus("NHV1"), network.getBusBreakerView().getBus("NHV1"), network.getBusBreakerView().getBus("NHV1"),