diff --git a/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/automatons/UnderVoltageAutomatonGroovyExtension.groovy b/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/automatons/UnderVoltageAutomatonGroovyExtension.groovy new file mode 100644 index 000000000..7b5e14fa7 --- /dev/null +++ b/dynawaltz-dsl/src/main/groovy/com/powsybl/dynawaltz/dsl/automatons/UnderVoltageAutomatonGroovyExtension.groovy @@ -0,0 +1,58 @@ +/** + * 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.automatons + +import com.google.auto.service.AutoService +import com.powsybl.dsl.DslException +import com.powsybl.dynamicsimulation.DynamicModel +import com.powsybl.dynamicsimulation.groovy.DynamicModelGroovyExtension +import com.powsybl.dynawaltz.dsl.AbstractPureDynamicGroovyExtension +import com.powsybl.dynawaltz.dsl.models.builders.AbstractPureDynamicModelBuilder +import com.powsybl.dynawaltz.models.automatons.UnderVoltageAutomaton +import com.powsybl.iidm.network.Generator +import com.powsybl.iidm.network.Network + +/** + * @author Laurent Issertial + */ +@AutoService(DynamicModelGroovyExtension.class) +class UnderVoltageAutomatonGroovyExtension extends AbstractPureDynamicGroovyExtension implements DynamicModelGroovyExtension { + + UnderVoltageAutomatonGroovyExtension() { + modelTags = ["UnderVoltage"] + } + + @Override + protected UnderVoltageAutomatonBuilder createBuilder(Network network) { + new UnderVoltageAutomatonBuilder(network) + } + + static class UnderVoltageAutomatonBuilder extends AbstractPureDynamicModelBuilder { + + Network network + + Generator generator + + UnderVoltageAutomatonBuilder(Network network) { + this.network = network + } + + void generator(String staticId) { + this.generator = network.getGenerator(staticId) + if (generator == null) { + throw new DslException("Generator static id unknown: " + staticId) + } + } + + @Override + UnderVoltageAutomaton build() { + checkData() + new UnderVoltageAutomaton(dynamicModelId, parameterSetId, generator) + } + } +} 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 a567a1405..2342577fa 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 @@ -19,6 +19,7 @@ import com.powsybl.dynawaltz.models.automatons.CurrentLimitAutomaton; import com.powsybl.dynawaltz.models.automatons.TapChangerAutomaton; import com.powsybl.dynawaltz.models.automatons.TapChangerBlockingAutomaton; +import com.powsybl.dynawaltz.models.automatons.UnderVoltageAutomaton; import com.powsybl.dynawaltz.models.automatons.phaseshifters.PhaseShifterIAutomaton; import com.powsybl.dynawaltz.models.automatons.phaseshifters.PhaseShifterPAutomaton; import com.powsybl.dynawaltz.models.buses.StandardBus; @@ -34,7 +35,6 @@ import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; import com.powsybl.iidm.network.test.HvdcTestNetwork; import com.powsybl.iidm.network.test.SvcTestCaseFactory; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -72,18 +72,6 @@ void testAutomatonDynamicModels(String groovyScriptName, Class dynamicModels = supplier.get(EurostagTutorialExample1Factory.create()); - assertEquals(1, dynamicModels.size()); - assertTrue(dynamicModels.get(0) instanceof TapChangerBlockingAutomaton); - TapChangerBlockingAutomaton bbm = (TapChangerBlockingAutomaton) dynamicModels.get(0); - assertEquals("ZAB", bbm.getDynamicModelId()); - assertEquals("ZAB", bbm.getParameterSetId()); - assertEquals("TapChangerBlockingAutomaton1", bbm.getLib()); - } - @ParameterizedTest(name = "{0}") @MethodSource("provideExceptionsModel") void testDslExceptions(String groovyScriptName, Network network, String exceptionMessage) { @@ -127,8 +115,10 @@ private static Stream provideAutomatonModelData() { return Stream.of( Arguments.of("currentLimit", CurrentLimitAutomaton.class, EurostagTutorialExample1Factory.create(), "AM_NHV1_NHV2_1", "CLA", "CurrentLimitAutomaton"), Arguments.of("tapChanger", TapChangerAutomaton.class, EurostagTutorialExample1Factory.create(), "TC", "tc", "TapChangerAutomaton"), + Arguments.of("tapChangerBlocking", TapChangerBlockingAutomaton.class, EurostagTutorialExample1Factory.create(), "ZAB", "ZAB", "TapChangerBlockingAutomaton1"), Arguments.of("phaseShifterI", PhaseShifterIAutomaton.class, EurostagTutorialExample1Factory.create(), "PS_NGEN_NHV1", "ps", "PhaseShifterI"), - Arguments.of("phaseShifterP", PhaseShifterPAutomaton.class, EurostagTutorialExample1Factory.create(), "PS_NGEN_NHV1", "ps", "PhaseShifterP") + Arguments.of("phaseShifterP", PhaseShifterPAutomaton.class, EurostagTutorialExample1Factory.create(), "PS_NGEN_NHV1", "ps", "PhaseShifterP"), + Arguments.of("underVoltage", UnderVoltageAutomaton.class, EurostagTutorialExample1Factory.create(), "UV_GEN", "uv", "UnderVoltageAutomaton") ); } @@ -136,7 +126,8 @@ private static Stream provideExceptionsModel() { return Stream.of( Arguments.of("phaseShifterTransformerException", EurostagTutorialExample1Factory.create(), "Transformer static id unknown: NGEN"), Arguments.of("tapChangerBusException", EurostagTutorialExample1Factory.create(), "Bus static id unknown: LOAD"), - Arguments.of("tapChangerCompatibleException", EurostagTutorialExample1Factory.create(), "GENERATOR GEN is not compatible") + Arguments.of("tapChangerCompatibleException", EurostagTutorialExample1Factory.create(), "GENERATOR GEN is not compatible"), + Arguments.of("underVoltageGeneratorException", EurostagTutorialExample1Factory.create(), "Generator static id unknown: NGEN") ); } diff --git a/dynawaltz-dsl/src/test/resources/dynamicModels/underVoltage.groovy b/dynawaltz-dsl/src/test/resources/dynamicModels/underVoltage.groovy new file mode 100644 index 000000000..4b4ad5e0a --- /dev/null +++ b/dynawaltz-dsl/src/test/resources/dynamicModels/underVoltage.groovy @@ -0,0 +1,16 @@ +/** + * 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 + + +UnderVoltage { + dynamicModelId "UV_GEN" + parameterSetId "uv" + generator "GEN" +} diff --git a/dynawaltz-dsl/src/test/resources/dynamicModels/underVoltageGeneratorException.groovy b/dynawaltz-dsl/src/test/resources/dynamicModels/underVoltageGeneratorException.groovy new file mode 100644 index 000000000..7e33aa1de --- /dev/null +++ b/dynawaltz-dsl/src/test/resources/dynamicModels/underVoltageGeneratorException.groovy @@ -0,0 +1,16 @@ +/** + * 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 + + +UnderVoltage { + dynamicModelId "UV_GEN" + parameterSetId "uv" + generator "NGEN" +} diff --git a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/automatons/UnderVoltageAutomaton.java b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/automatons/UnderVoltageAutomaton.java new file mode 100644 index 000000000..20961df35 --- /dev/null +++ b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/automatons/UnderVoltageAutomaton.java @@ -0,0 +1,48 @@ +/** + * 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.automatons; + +import com.powsybl.dynawaltz.DynaWaltzContext; +import com.powsybl.dynawaltz.models.AbstractPureDynamicBlackBoxModel; +import com.powsybl.dynawaltz.models.VarConnection; +import com.powsybl.dynawaltz.models.generators.GeneratorModel; +import com.powsybl.iidm.network.Generator; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +/** + * @author Laurent Issertial + */ +public class UnderVoltageAutomaton extends AbstractPureDynamicBlackBoxModel { + + protected final Generator generator; + + public UnderVoltageAutomaton(String dynamicModelId, String parameterSetId, Generator generator) { + super(dynamicModelId, parameterSetId); + this.generator = Objects.requireNonNull(generator); + } + + @Override + public String getLib() { + return "UnderVoltageAutomaton"; + } + + @Override + public void createMacroConnections(DynaWaltzContext context) { + createMacroConnections(generator, GeneratorModel.class, this::getVarConnectionsWithGenerator, context); + } + + protected List getVarConnectionsWithGenerator(GeneratorModel connected) { + return Arrays.asList( + new VarConnection("underVoltageAutomaton_UMonitoredPu", connected.getUPuVarName()), + new VarConnection("underVoltageAutomaton_switchOffSignal", connected.getSwitchOffSignalAutomatonVarName()) + ); + } +} diff --git a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/generators/AbstractGeneratorModel.java b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/generators/AbstractGeneratorModel.java index fda118a46..5cb6dea27 100644 --- a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/generators/AbstractGeneratorModel.java +++ b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/generators/AbstractGeneratorModel.java @@ -91,6 +91,11 @@ public String getQStatorPuVarName() { return "generator_QStatorPu"; } + @Override + public String getUPuVarName() { + return "generator_UPu"; + } + @Override public String getDisconnectableVarName() { return getSwitchOffSignalEventVarName(); diff --git a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/generators/DefaultGeneratorModel.java b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/generators/DefaultGeneratorModel.java index 627fbf278..464056fb1 100644 --- a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/generators/DefaultGeneratorModel.java +++ b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/generators/DefaultGeneratorModel.java @@ -62,4 +62,8 @@ public String getRunningVarName() { public String getQStatorPuVarName() { return "@NAME@_QStatorPu"; } + + public String getUPuVarName() { + return "@NAME@_UPu"; + } } diff --git a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/generators/GeneratorModel.java b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/generators/GeneratorModel.java index 73c345be0..83aaa1fdc 100644 --- a/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/generators/GeneratorModel.java +++ b/dynawaltz/src/main/java/com/powsybl/dynawaltz/models/generators/GeneratorModel.java @@ -23,4 +23,6 @@ public interface GeneratorModel extends Model { String getRunningVarName(); String getQStatorPuVarName(); + + String getUPuVarName(); } diff --git a/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/UnderVoltageAutomatonXmlTest.java b/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/UnderVoltageAutomatonXmlTest.java new file mode 100644 index 000000000..db7862cf0 --- /dev/null +++ b/dynawaltz/src/test/java/com/powsybl/dynawaltz/xml/UnderVoltageAutomatonXmlTest.java @@ -0,0 +1,39 @@ +/** + * 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.automatons.UnderVoltageAutomaton; +import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; +import org.junit.jupiter.api.Test; +import org.xml.sax.SAXException; + +import javax.xml.stream.XMLStreamException; +import java.io.IOException; + +/** + * @author Laurent Issertial + */ +class UnderVoltageAutomatonXmlTest extends AbstractDynamicModelXmlTest { + + @Override + protected void setupNetwork() { + network = EurostagTutorialExample1Factory.create(); + } + + @Override + protected void addDynamicModels() { + dynamicModels.add(new UnderVoltageAutomaton("BBM_under_voltage", "uv", network.getGenerator("GEN"))); + } + + @Test + void writeModel() throws SAXException, IOException, XMLStreamException { + DydXml.write(tmpDir, context); + ParametersXml.write(tmpDir, context); + validate("dyd.xsd", "under_voltage_dyd.xml", tmpDir.resolve(DynaWaltzConstants.DYD_FILENAME)); + } +} diff --git a/dynawaltz/src/test/resources/under_voltage_dyd.xml b/dynawaltz/src/test/resources/under_voltage_dyd.xml new file mode 100644 index 000000000..356f155e3 --- /dev/null +++ b/dynawaltz/src/test/resources/under_voltage_dyd.xml @@ -0,0 +1,9 @@ + + + + + + + + +