From f46a068462cfbf55eec024fbe8817bcbba7cfe12 Mon Sep 17 00:00:00 2001 From: Lisrte Date: Tue, 20 Jun 2023 21:50:58 +0200 Subject: [PATCH] Add dangling HVDC models (#249) Signed-off-by: lisrte --- .../dynawaltz/dsl/EquipmentConfig.groovy | 5 ++ .../models/hvdc/AbstractHvdcBuilder.groovy | 17 ++++- .../models/hvdc/HvdcPvGroovyExtension.groovy | 13 ++-- .../models/hvdc/HvdcVscGroovyExtension.groovy | 12 ++-- dynawaltz-dsl/src/main/resources/models.cfg | 6 ++ .../dsl/DynamicModelsSupplierTest.java | 7 +- .../danglingHvdcException.groovy | 18 +++++ .../resources/dynamicModels/hvdcPv.groovy | 1 - .../dynamicModels/hvdcPvDangling.groovy | 18 +++++ .../resources/dynamicModels/hvdcVsc.groovy | 1 - .../dynamicModels/hvdcVscDangling.groovy | 18 +++++ .../com/powsybl/dynawaltz/models/Side.java | 4 ++ .../dynawaltz/models/hvdc/AbstractHvdc.java | 14 ++-- .../dynawaltz/models/hvdc/DanglingSide.java | 39 +++++++++++ .../dynawaltz/models/hvdc/HvdcPvDangling.java | 44 ++++++++++++ .../models/hvdc/HvdcVscDangling.java | 44 ++++++++++++ .../dynawaltz/models/utils/BusUtils.java | 10 +-- .../dynawaltz/models/utils/SideConverter.java | 12 ++++ .../xml/DisconnectHvdcEventXmlTest.java | 12 +++- .../xml/DisconnectionExceptionXmlTest.java | 70 +++++++++++++++++++ .../powsybl/dynawaltz/xml/EventXmlTest.java | 1 - .../powsybl/dynawaltz/xml/HvdcPvXmlTest.java | 38 ---------- .../powsybl/dynawaltz/xml/HvdcXmlTest.java | 69 ++++++++++++++++++ .../disconnect_hvdc_pv_dangling_dyd.xml | 28 ++++++++ .../disconnect_hvdc_vsc_dangling_dyd.xml | 28 ++++++++ .../test/resources/hvdc_pv_dangling_dyd.xml | 23 ++++++ .../{hvdc_dyd.xml => hvdc_pv_dyd.xml} | 0 .../test/resources/hvdc_vsc_dangling_dyd.xml | 23 ++++++ dynawaltz/src/test/resources/hvdc_vsc_dyd.xml | 24 +++++++ 29 files changed, 535 insertions(+), 64 deletions(-) create mode 100644 dynawaltz-dsl/src/test/resources/dynamicModels/danglingHvdcException.groovy create mode 100644 dynawaltz-dsl/src/test/resources/dynamicModels/hvdcPvDangling.groovy create mode 100644 dynawaltz-dsl/src/test/resources/dynamicModels/hvdcVscDangling.groovy create mode 100644 dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/DanglingSide.java create mode 100644 dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/HvdcPvDangling.java create mode 100644 dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/HvdcVscDangling.java create mode 100644 dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/DisconnectionExceptionXmlTest.java delete mode 100644 dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/HvdcPvXmlTest.java create mode 100644 dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/HvdcXmlTest.java create mode 100644 dynawaltz/src/test/resources/disconnect_hvdc_pv_dangling_dyd.xml create mode 100644 dynawaltz/src/test/resources/disconnect_hvdc_vsc_dangling_dyd.xml create mode 100644 dynawaltz/src/test/resources/hvdc_pv_dangling_dyd.xml rename dynawaltz/src/test/resources/{hvdc_dyd.xml => hvdc_pv_dyd.xml} (100%) create mode 100644 dynawaltz/src/test/resources/hvdc_vsc_dangling_dyd.xml create mode 100644 dynawaltz/src/test/resources/hvdc_vsc_dyd.xml diff --git a/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/EquipmentConfig.groovy b/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/EquipmentConfig.groovy index 2ff6dab8c..b6f22243f 100644 --- a/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/EquipmentConfig.groovy +++ b/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/EquipmentConfig.groovy @@ -4,6 +4,7 @@ package com.powsybl.dynawaltz.dsl class EquipmentConfig { static final String CONTROLLABLE_PROPERTY = "CONTROLLABLE" + static final String DANGLING_PROPERTY = "DANGLING" static final String SYNCHRONIZED_PROPERTY = "SYNCHRONIZED" final String lib @@ -20,6 +21,10 @@ class EquipmentConfig { properties.contains(CONTROLLABLE_PROPERTY) } + boolean isDangling() { + properties.contains(DANGLING_PROPERTY) + } + boolean isSynchronized() { properties.contains(SYNCHRONIZED_PROPERTY) } diff --git a/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/models/hvdc/AbstractHvdcBuilder.groovy b/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/models/hvdc/AbstractHvdcBuilder.groovy index fe801bea9..a2f1d28e8 100644 --- a/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/models/hvdc/AbstractHvdcBuilder.groovy +++ b/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/models/hvdc/AbstractHvdcBuilder.groovy @@ -8,7 +8,11 @@ package com.powsybl.dynawaltz.dsl.models.hvdc import com.powsybl.dsl.DslException +import com.powsybl.dynawaltz.dsl.EquipmentConfig import com.powsybl.dynawaltz.dsl.models.builders.AbstractDynamicModelBuilder +import com.powsybl.dynawaltz.models.Side +import com.powsybl.dynawaltz.models.utils.SideConverter +import com.powsybl.iidm.network.Branch import com.powsybl.iidm.network.HvdcLine import com.powsybl.iidm.network.Network @@ -18,9 +22,20 @@ import com.powsybl.iidm.network.Network abstract class AbstractHvdcBuilder extends AbstractDynamicModelBuilder { HvdcLine hvdc + EquipmentConfig equipmentConfig + Side danglingSide - AbstractHvdcBuilder(Network network) { + AbstractHvdcBuilder(Network network, EquipmentConfig equipmentConfig) { super(network) + this.equipmentConfig = equipmentConfig + } + + void dangling(Branch.Side danglingSide) { + if (equipmentConfig.isDangling()) { + this.danglingSide = SideConverter.convert(danglingSide) + } else { + throw new DslException("'dangling' field is set on a non dangling hvdc : ${equipmentConfig.lib}") + } } void checkData() { diff --git a/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/models/hvdc/HvdcPvGroovyExtension.groovy b/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/models/hvdc/HvdcPvGroovyExtension.groovy index 76f1600b5..7760e8cc8 100644 --- a/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/models/hvdc/HvdcPvGroovyExtension.groovy +++ b/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/models/hvdc/HvdcPvGroovyExtension.groovy @@ -13,7 +13,7 @@ import com.powsybl.dynamicsimulation.groovy.DynamicModelGroovyExtension import com.powsybl.dynawaltz.dsl.AbstractEquipmentGroovyExtension import com.powsybl.dynawaltz.dsl.EquipmentConfig import com.powsybl.dynawaltz.models.hvdc.HvdcPv -import com.powsybl.iidm.network.HvdcLine +import com.powsybl.dynawaltz.models.hvdc.HvdcPvDangling import com.powsybl.iidm.network.Network /** @@ -39,17 +39,18 @@ class HvdcPvGroovyExtension extends AbstractEquipmentGroovyExtension provideEquipmentModelData() { Arguments.of("/dynamicModels/bus.groovy", StandardBus.class, EurostagTutorialExample1Factory.create(), "NGEN", "BBM_NGEN", "SB", "Bus"), Arguments.of("/dynamicModels/hvdcPv.groovy", HvdcPv.class, HvdcTestNetwork.createVsc(), "L", "BBM_HVDC_L", "HVDC", "HvdcPV"), Arguments.of("/dynamicModels/hvdcVsc.groovy", HvdcVsc.class, HvdcTestNetwork.createVsc(), "L", "BBM_HVDC_L", "HVDC", "HvdcVSC"), + Arguments.of("/dynamicModels/hvdcPvDangling.groovy", HvdcPvDangling.class, HvdcTestNetwork.createVsc(), "L", "BBM_HVDC_L", "HVDC", "HvdcPVDanglingDiagramPQ"), + Arguments.of("/dynamicModels/hvdcVscDangling.groovy", HvdcVscDangling.class, HvdcTestNetwork.createVsc(), "L", "BBM_HVDC_L", "HVDC", "HvdcVSCDanglingUdc"), Arguments.of("/dynamicModels/loadAB.groovy", LoadAlphaBeta.class, EurostagTutorialExample1Factory.create(), "LOAD", "LOAD", "LAB", "LoadAlphaBetaRestorative"), Arguments.of("/dynamicModels/loadABControllable.groovy", LoadAlphaBetaControllable.class, EurostagTutorialExample1Factory.create(), "LOAD", "LOAD", "LAB", "LoadAlphaBeta"), Arguments.of("/dynamicModels/loadTransformer.groovy", LoadOneTransformer.class, EurostagTutorialExample1Factory.create(), "LOAD", "LOAD", "LOT", "LoadOneTransformer"), @@ -137,7 +141,8 @@ private static Stream provideExceptionsModel() { Arguments.of("/dynamicModels/phaseShifterTransformerException.groovy", EurostagTutorialExample1Factory.create(), "Transformer static id unknown: NGEN"), Arguments.of("/dynamicModels/tapChangerBusException.groovy", EurostagTutorialExample1Factory.create(), "Bus static id unknown: LOAD"), Arguments.of("/dynamicModels/tapChangerCompatibleException.groovy", EurostagTutorialExample1Factory.create(), "GENERATOR GEN is not compatible"), - Arguments.of("/dynamicModels/underVoltageGeneratorException.groovy", EurostagTutorialExample1Factory.create(), "Generator static id unknown: NGEN") + Arguments.of("/dynamicModels/underVoltageGeneratorException.groovy", EurostagTutorialExample1Factory.create(), "Generator static id unknown: NGEN"), + Arguments.of("/dynamicModels/danglingHvdcException.groovy", HvdcTestNetwork.createVsc(), "'dangling' field is set on a non dangling hvdc : HvdcPV") ); } } diff --git a/dynawaltz-dsl/src/test/resources/dynamicModels/danglingHvdcException.groovy b/dynawaltz-dsl/src/test/resources/dynamicModels/danglingHvdcException.groovy new file mode 100644 index 000000000..2fbfadcaf --- /dev/null +++ b/dynawaltz-dsl/src/test/resources/dynamicModels/danglingHvdcException.groovy @@ -0,0 +1,18 @@ +/** + * 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 + +import com.powsybl.iidm.network.Branch + +HvdcPV { + staticId "L" + dynamicModelId "BBM_HVDC_L" + parameterSetId "HVDC" + dangling Branch.Side.ONE +} diff --git a/dynawaltz-dsl/src/test/resources/dynamicModels/hvdcPv.groovy b/dynawaltz-dsl/src/test/resources/dynamicModels/hvdcPv.groovy index cb8734913..f87186fbf 100644 --- a/dynawaltz-dsl/src/test/resources/dynamicModels/hvdcPv.groovy +++ b/dynawaltz-dsl/src/test/resources/dynamicModels/hvdcPv.groovy @@ -13,4 +13,3 @@ HvdcPV { dynamicModelId "BBM_HVDC_L" parameterSetId "HVDC" } - diff --git a/dynawaltz-dsl/src/test/resources/dynamicModels/hvdcPvDangling.groovy b/dynawaltz-dsl/src/test/resources/dynamicModels/hvdcPvDangling.groovy new file mode 100644 index 000000000..780a0bec4 --- /dev/null +++ b/dynawaltz-dsl/src/test/resources/dynamicModels/hvdcPvDangling.groovy @@ -0,0 +1,18 @@ +/** + * 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 + +import com.powsybl.iidm.network.Branch + +HvdcPVDanglingDiagramPQ { + staticId "L" + dynamicModelId "BBM_HVDC_L" + parameterSetId "HVDC" + dangling Branch.Side.ONE +} diff --git a/dynawaltz-dsl/src/test/resources/dynamicModels/hvdcVsc.groovy b/dynawaltz-dsl/src/test/resources/dynamicModels/hvdcVsc.groovy index 9abbe877f..52c0c5bdf 100644 --- a/dynawaltz-dsl/src/test/resources/dynamicModels/hvdcVsc.groovy +++ b/dynawaltz-dsl/src/test/resources/dynamicModels/hvdcVsc.groovy @@ -13,4 +13,3 @@ HvdcVSC { dynamicModelId "BBM_HVDC_L" parameterSetId "HVDC" } - diff --git a/dynawaltz-dsl/src/test/resources/dynamicModels/hvdcVscDangling.groovy b/dynawaltz-dsl/src/test/resources/dynamicModels/hvdcVscDangling.groovy new file mode 100644 index 000000000..a1290c328 --- /dev/null +++ b/dynawaltz-dsl/src/test/resources/dynamicModels/hvdcVscDangling.groovy @@ -0,0 +1,18 @@ +/** + * 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 + +import com.powsybl.iidm.network.Branch + +HvdcVSCDanglingUdc { + staticId "L" + dynamicModelId "BBM_HVDC_L" + parameterSetId "HVDC" + dangling Branch.Side.TWO +} diff --git a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/Side.java b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/Side.java index 3ee0506f8..4011480bc 100644 --- a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/Side.java +++ b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/Side.java @@ -28,4 +28,8 @@ public String getSideSuffix() { public int getSideNumber() { return ordinal() + 1; } + + public Side getOppositeSide() { + return this == ONE ? TWO : ONE; + } } diff --git a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/AbstractHvdc.java b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/AbstractHvdc.java index 4f181bd15..8dc6a1b62 100644 --- a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/AbstractHvdc.java +++ b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/AbstractHvdc.java @@ -33,14 +33,16 @@ public abstract class AbstractHvdc extends AbstractEquipmentBlackBoxModel getVarsMapping() { return VAR_MAPPING; } - private List getVarConnectionsWithBus(BusModel connected, Side side) { + protected List getVarConnectionsWith(BusModel connected, Side side) { List varConnections = new ArrayList<>(2); - varConnections.add(new VarConnection("hvdc_terminal" + side.getSideNumber(), connected.getTerminalVarName())); + varConnections.add(getSimpleVarConnectionWithBus(connected, side)); connected.getSwitchOffSignalVarName() .map(switchOff -> new VarConnection("hvdc_switchOffSignal1" + side.getSideSuffix(), switchOff)) .ifPresent(varConnections::add); return varConnections; } + + protected final VarConnection getSimpleVarConnectionWithBus(BusModel connected, Side side) { + return new VarConnection(TERMINAL_PREFIX + side.getSideNumber(), connected.getTerminalVarName()); + } } diff --git a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/DanglingSide.java b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/DanglingSide.java new file mode 100644 index 000000000..c6e7998c9 --- /dev/null +++ b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/DanglingSide.java @@ -0,0 +1,39 @@ +package com.powsybl.dynawaltz.models.hvdc; + +import com.powsybl.dynawaltz.models.Side; +import com.powsybl.dynawaltz.models.VarConnection; +import com.powsybl.dynawaltz.models.buses.BusModel; + +import java.util.List; +import java.util.Objects; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; + +public final class DanglingSide { + + private final String prefix; + private final Side side; + + public DanglingSide(String prefix, Side side) { + this.prefix = Objects.requireNonNull(prefix); + this.side = Objects.requireNonNull(side); + } + + boolean isDangling(Side side) { + return this.side == side; + } + + public int getSideNumber() { + return side.getSideNumber(); + } + + public void createMacroConnections(BiFunction> basicVarConnectionsSupplier, + BiConsumer>, Side> connectionCreator) { + connectionCreator.accept(this::getVarConnectionsWith, side); + connectionCreator.accept(basicVarConnectionsSupplier, side.getOppositeSide()); + } + + private List getVarConnectionsWith(BusModel connected, Side side) { + return List.of(new VarConnection(prefix + side.getSideNumber(), connected.getTerminalVarName())); + } +} diff --git a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/HvdcPvDangling.java b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/HvdcPvDangling.java new file mode 100644 index 000000000..33b2e7e8d --- /dev/null +++ b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/HvdcPvDangling.java @@ -0,0 +1,44 @@ +/** + * 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.models.hvdc; + +import com.powsybl.commons.PowsyblException; +import com.powsybl.dynawaltz.DynaWaltzContext; +import com.powsybl.dynawaltz.models.Side; +import com.powsybl.dynawaltz.models.buses.BusModel; +import com.powsybl.dynawaltz.models.utils.BusUtils; +import com.powsybl.iidm.network.HvdcLine; + +/** + * @author Laurent Issertial + */ +public class HvdcPvDangling extends HvdcPv { + + private final DanglingSide danglingSide; + + public HvdcPvDangling(String dynamicModelId, HvdcLine hvdc, String parameterSetId, String hvdcLib, Side danglingSide) { + super(dynamicModelId, hvdc, parameterSetId, hvdcLib); + this.danglingSide = new DanglingSide(TERMINAL_PREFIX, danglingSide); + } + + @Override + public void createMacroConnections(DynaWaltzContext context) { + danglingSide.createMacroConnections( + this::getVarConnectionsWith, + (varCoSupplier, side) -> createMacroConnections(BusUtils.getConnectableBusStaticId(equipment, side), BusModel.class, varCoSupplier, context, side) + ); + } + + @Override + public String getSwitchOffSignalEventVarName(Side side) { + if (danglingSide.isDangling(side)) { + throw new PowsyblException(String.format("Equipment %s side %s is dangling and can't be disconnected with an event", getLib(), danglingSide.getSideNumber())); + } + return super.getSwitchOffSignalEventVarName(side); + } +} diff --git a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/HvdcVscDangling.java b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/HvdcVscDangling.java new file mode 100644 index 000000000..348ee87ef --- /dev/null +++ b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/hvdc/HvdcVscDangling.java @@ -0,0 +1,44 @@ +/** + * 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.models.hvdc; + +import com.powsybl.commons.PowsyblException; +import com.powsybl.dynawaltz.DynaWaltzContext; +import com.powsybl.dynawaltz.models.Side; +import com.powsybl.dynawaltz.models.buses.BusModel; +import com.powsybl.dynawaltz.models.utils.BusUtils; +import com.powsybl.iidm.network.HvdcLine; + +/** + * @author Laurent Issertial + */ +public class HvdcVscDangling extends HvdcVsc { + + private final DanglingSide danglingSide; + + public HvdcVscDangling(String dynamicModelId, HvdcLine hvdc, String parameterSetId, String hvdcLib, Side danglingSide) { + super(dynamicModelId, hvdc, parameterSetId, hvdcLib); + this.danglingSide = new DanglingSide(TERMINAL_PREFIX, danglingSide); + } + + @Override + public void createMacroConnections(DynaWaltzContext context) { + danglingSide.createMacroConnections( + this::getVarConnectionsWith, + (varCoSupplier, side) -> createMacroConnections(BusUtils.getConnectableBusStaticId(equipment, side), BusModel.class, varCoSupplier, context, side) + ); + } + + @Override + public String getSwitchOffSignalEventVarName(Side side) { + if (danglingSide.isDangling(side)) { + throw new PowsyblException(String.format("Equipment %s side %s is dangling and can't be disconnected with an event", getLib(), danglingSide.getSideNumber())); + } + return super.getSwitchOffSignalEventVarName(side); + } +} diff --git a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/utils/BusUtils.java b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/utils/BusUtils.java index 8608aa16e..499a9fad9 100644 --- a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/utils/BusUtils.java +++ b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/utils/BusUtils.java @@ -7,10 +7,8 @@ */ package com.powsybl.dynawaltz.models.utils; -import com.powsybl.iidm.network.Generator; -import com.powsybl.iidm.network.Load; -import com.powsybl.iidm.network.StaticVarCompensator; -import com.powsybl.iidm.network.Terminal; +import com.powsybl.dynawaltz.models.Side; +import com.powsybl.iidm.network.*; /** * @author Laurent Issertial @@ -32,6 +30,10 @@ public static String getConnectableBusStaticId(StaticVarCompensator svc) { return getConnectableBusStaticId(svc.getTerminal()); } + public static String getConnectableBusStaticId(HvdcLine hvdc, Side side) { + return getConnectableBusStaticId(hvdc.getConverterStation(SideConverter.convert(side)).getTerminal()); + } + public static String getConnectableBusStaticId(Load load) { return getConnectableBusStaticId(load.getTerminal()); } diff --git a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/utils/SideConverter.java b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/utils/SideConverter.java index 00483983b..bd5d7331d 100644 --- a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/utils/SideConverter.java +++ b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/utils/SideConverter.java @@ -9,6 +9,7 @@ import com.powsybl.dynawaltz.models.Side; import com.powsybl.iidm.network.Branch; +import com.powsybl.iidm.network.HvdcLine; /** * @author Laurent Issertial @@ -28,4 +29,15 @@ public static Side convert(Branch.Side side) { throw new AssertionError("Unexpected Side value: " + side); } } + + public static HvdcLine.Side convert(Side side) { + switch (side) { + case ONE : + return HvdcLine.Side.ONE; + case TWO : + return HvdcLine.Side.TWO; + default : + throw new IllegalArgumentException("Unexpected Side value: " + side); + } + } } diff --git a/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/DisconnectHvdcEventXmlTest.java b/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/DisconnectHvdcEventXmlTest.java index 9af75b8d7..0c67ade65 100644 --- a/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/DisconnectHvdcEventXmlTest.java +++ b/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/DisconnectHvdcEventXmlTest.java @@ -8,9 +8,12 @@ package com.powsybl.dynawaltz.xml; import com.powsybl.dynawaltz.models.BlackBoxModel; +import com.powsybl.dynawaltz.models.Side; import com.powsybl.dynawaltz.models.events.EventHvdcDisconnection; import com.powsybl.dynawaltz.models.hvdc.HvdcPv; +import com.powsybl.dynawaltz.models.hvdc.HvdcPvDangling; import com.powsybl.dynawaltz.models.hvdc.HvdcVsc; +import com.powsybl.dynawaltz.models.hvdc.HvdcVscDangling; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.test.HvdcTestNetwork; import org.junit.jupiter.api.BeforeEach; @@ -54,7 +57,7 @@ protected void addDynamicModels(Function< Network, BlackBoxModel> hvdcConstructo @ParameterizedTest(name = "{0}") @MethodSource("provideModels") - void writeLoadModel(String dydName, Function< Network, BlackBoxModel> hvdcConstructor, Function< Network, BlackBoxModel> disconnectConstructor) throws SAXException, IOException, XMLStreamException { + void writeModel(String dydName, Function< Network, BlackBoxModel> hvdcConstructor, Function< Network, BlackBoxModel> disconnectConstructor) throws SAXException, IOException, XMLStreamException { DydXml.write(tmpDir, context); ParametersXml.write(tmpDir, context); validate("dyd.xsd", dydName, tmpDir.resolve(DynaWaltzConstants.DYD_FILENAME)); @@ -72,8 +75,13 @@ private static Stream provideModels() { (Function) n -> new EventHvdcDisconnection(n.getHvdcLine(HVDC_NAME), 1, true, false)), Arguments.of("disconnect_hvdc_vsc_dyd.xml", (Function) n -> new HvdcVsc(DYN_HVDC_NAME, n.getHvdcLine(HVDC_NAME), "hvdc", "HvdcVsc"), + (Function) n -> new EventHvdcDisconnection(n.getHvdcLine(HVDC_NAME), 1, false, true)), + Arguments.of("disconnect_hvdc_pv_dangling_dyd.xml", + (Function) n -> new HvdcPvDangling(DYN_HVDC_NAME, n.getHvdcLine(HVDC_NAME), "hvdc", "HvdcPVDangling", Side.TWO), + (Function) n -> new EventHvdcDisconnection(n.getHvdcLine(HVDC_NAME), 1, true, false)), + Arguments.of("disconnect_hvdc_vsc_dangling_dyd.xml", + (Function) n -> new HvdcVscDangling(DYN_HVDC_NAME, n.getHvdcLine(HVDC_NAME), "hvdc", "HvdcVSCDanglingUdc", Side.ONE), (Function) n -> new EventHvdcDisconnection(n.getHvdcLine(HVDC_NAME), 1, false, true)) - ); } } diff --git a/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/DisconnectionExceptionXmlTest.java b/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/DisconnectionExceptionXmlTest.java new file mode 100644 index 000000000..edf4f40d6 --- /dev/null +++ b/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/DisconnectionExceptionXmlTest.java @@ -0,0 +1,70 @@ +/** + * 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.xml; + +import com.powsybl.commons.PowsyblException; +import com.powsybl.dynawaltz.models.BlackBoxModel; +import com.powsybl.dynawaltz.models.Side; +import com.powsybl.dynawaltz.models.events.EventHvdcDisconnection; +import com.powsybl.dynawaltz.models.hvdc.HvdcPvDangling; +import com.powsybl.dynawaltz.models.hvdc.HvdcVscDangling; +import com.powsybl.iidm.network.HvdcLine; +import com.powsybl.iidm.network.test.HvdcTestNetwork; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.function.BiFunction; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * @author Laurent Issertial + */ +@ExtendWith(CustomParameterResolver.class) +class DisconnectionExceptionXmlTest extends AbstractParametrizedDynamicModelXmlTest { + + @BeforeEach + void setup(String exception, Side side, BiFunction constructor) { + setupNetwork(); + addDynamicModels(side, constructor); + } + + protected void setupNetwork() { + network = HvdcTestNetwork.createVsc(); + } + + protected void addDynamicModels(Side side, BiFunction constructor) { + HvdcLine hvdc = network.getHvdcLine("L"); + dynamicModels.add(constructor.apply(hvdc, side)); + boolean disconnectOrigin = Side.ONE == side; + eventModels.add(new EventHvdcDisconnection(hvdc, 1, disconnectOrigin, !disconnectOrigin)); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("provideModels") + void disconnectionOnDanglingSide(String exception, Side side, BiFunction constructor) { + Exception e = assertThrows(PowsyblException.class, this::setupDynawaltzContext); + assertEquals(exception, e.getMessage()); + } + + private static Stream provideModels() { + return Stream.of( + Arguments.of("Equipment HvdcPVDangling side 1 is dangling and can't be disconnected with an event", + Side.ONE, + (BiFunction) (hvdc, side) -> new HvdcPvDangling("BBM_L", hvdc, "hvdc", "HvdcPVDangling", side)), + Arguments.of("Equipment HvdcVSCDanglingUdc side 2 is dangling and can't be disconnected with an event", + Side.TWO, + (BiFunction) (hvdc, side) -> new HvdcVscDangling("BBM_L", hvdc, "hvdc", "HvdcVSCDanglingUdc", side)) + ); + } +} diff --git a/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/EventXmlTest.java b/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/EventXmlTest.java index 4f17c995a..1c270f101 100644 --- a/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/EventXmlTest.java +++ b/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/EventXmlTest.java @@ -51,5 +51,4 @@ void duplicateEventId() { Exception e = assertThrows(PowsyblException.class, () -> new DynaWaltzContext(network, workingVariantId, dynamicModels, eventModels, curves, null, null)); assertEquals("Duplicate dynamicId: [Disconnect_NHV1_NHV2_1, Disconnect_GEN2]", e.getMessage()); } - } diff --git a/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/HvdcPvXmlTest.java b/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/HvdcPvXmlTest.java deleted file mode 100644 index e53ddf278..000000000 --- a/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/HvdcPvXmlTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * 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.xml; - -import com.powsybl.dynawaltz.models.hvdc.HvdcPv; -import com.powsybl.iidm.network.test.HvdcTestNetwork; -import org.junit.jupiter.api.Test; -import org.xml.sax.SAXException; - -import javax.xml.stream.XMLStreamException; -import java.io.IOException; - -/** - * @author Laurent Issertial - */ -class HvdcPvXmlTest extends AbstractDynamicModelXmlTest { - - @Override - protected void setupNetwork() { - network = HvdcTestNetwork.createVsc(); - } - - @Override - protected void addDynamicModels() { - network.getHvdcLineStream().forEach(hvdc -> dynamicModels.add(new HvdcPv("BBM_" + hvdc.getId(), hvdc, "hv", "HvdcPV"))); - } - - @Test - void writeHvdcModel() throws SAXException, IOException, XMLStreamException { - DydXml.write(tmpDir, context); - validate("dyd.xsd", "hvdc_dyd.xml", tmpDir.resolve(DynaWaltzConstants.DYD_FILENAME)); - } -} diff --git a/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/HvdcXmlTest.java b/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/HvdcXmlTest.java new file mode 100644 index 000000000..dd910e0c9 --- /dev/null +++ b/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/HvdcXmlTest.java @@ -0,0 +1,69 @@ +/** + * 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.xml; + +import com.powsybl.dynawaltz.models.BlackBoxModel; +import com.powsybl.dynawaltz.models.Side; +import com.powsybl.dynawaltz.models.hvdc.HvdcPv; +import com.powsybl.dynawaltz.models.hvdc.HvdcPvDangling; +import com.powsybl.dynawaltz.models.hvdc.HvdcVsc; +import com.powsybl.dynawaltz.models.hvdc.HvdcVscDangling; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.test.HvdcTestNetwork; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.xml.sax.SAXException; + +import javax.xml.stream.XMLStreamException; +import java.io.IOException; +import java.util.function.Function; +import java.util.stream.Stream; + +/** + * @author Laurent Issertial + */ +@ExtendWith(CustomParameterResolver.class) +class HvdcXmlTest extends AbstractParametrizedDynamicModelXmlTest { + + private static final String HVDC_NAME = "L"; + private static final String DYN_NAME = "BBM_" + HVDC_NAME; + + @BeforeEach + void setup(String dydName, Function< Network, BlackBoxModel> constructor) { + setupNetwork(); + addDynamicModels(constructor); + setupDynawaltzContext(); + } + + protected void setupNetwork() { + network = HvdcTestNetwork.createVsc(); + } + + protected void addDynamicModels(Function< Network, BlackBoxModel> constructor) { + dynamicModels.add(constructor.apply(network)); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("provideHvdc") + void writeHvdcModel(String dydName, Function< Network, BlackBoxModel> constructor) throws SAXException, IOException, XMLStreamException { + DydXml.write(tmpDir, context); + validate("dyd.xsd", dydName, tmpDir.resolve(DynaWaltzConstants.DYD_FILENAME)); + } + + private static Stream provideHvdc() { + return Stream.of( + Arguments.of("hvdc_pv_dyd.xml", (Function) n -> new HvdcPv(DYN_NAME, n.getHvdcLine(HVDC_NAME), "hv", "HvdcPV")), + Arguments.of("hvdc_vsc_dyd.xml", (Function) n -> new HvdcVsc(DYN_NAME, n.getHvdcLine(HVDC_NAME), "hv", "HvdcVSC")), + Arguments.of("hvdc_pv_dangling_dyd.xml", (Function) n -> new HvdcPvDangling(DYN_NAME, n.getHvdcLine(HVDC_NAME), "hv", "HvdcPVDangling", Side.ONE)), + Arguments.of("hvdc_vsc_dangling_dyd.xml", (Function) n -> new HvdcVscDangling(DYN_NAME, n.getHvdcLine(HVDC_NAME), "hv", "HvdcVSCDanglingP", Side.TWO)) + ); + } +} diff --git a/dynawaltz/src/test/resources/disconnect_hvdc_pv_dangling_dyd.xml b/dynawaltz/src/test/resources/disconnect_hvdc_pv_dangling_dyd.xml new file mode 100644 index 000000000..58009c9b4 --- /dev/null +++ b/dynawaltz/src/test/resources/disconnect_hvdc_pv_dangling_dyd.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dynawaltz/src/test/resources/disconnect_hvdc_vsc_dangling_dyd.xml b/dynawaltz/src/test/resources/disconnect_hvdc_vsc_dangling_dyd.xml new file mode 100644 index 000000000..331081089 --- /dev/null +++ b/dynawaltz/src/test/resources/disconnect_hvdc_vsc_dangling_dyd.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dynawaltz/src/test/resources/hvdc_pv_dangling_dyd.xml b/dynawaltz/src/test/resources/hvdc_pv_dangling_dyd.xml new file mode 100644 index 000000000..f0dda9d5c --- /dev/null +++ b/dynawaltz/src/test/resources/hvdc_pv_dangling_dyd.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dynawaltz/src/test/resources/hvdc_dyd.xml b/dynawaltz/src/test/resources/hvdc_pv_dyd.xml similarity index 100% rename from dynawaltz/src/test/resources/hvdc_dyd.xml rename to dynawaltz/src/test/resources/hvdc_pv_dyd.xml diff --git a/dynawaltz/src/test/resources/hvdc_vsc_dangling_dyd.xml b/dynawaltz/src/test/resources/hvdc_vsc_dangling_dyd.xml new file mode 100644 index 000000000..c85b95bd4 --- /dev/null +++ b/dynawaltz/src/test/resources/hvdc_vsc_dangling_dyd.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dynawaltz/src/test/resources/hvdc_vsc_dyd.xml b/dynawaltz/src/test/resources/hvdc_vsc_dyd.xml new file mode 100644 index 000000000..62cd1fa2d --- /dev/null +++ b/dynawaltz/src/test/resources/hvdc_vsc_dyd.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + +