From a4cea8dc5976ca57c2ab569ba145d34aeedb1b01 Mon Sep 17 00:00:00 2001 From: Lisrte Date: Thu, 18 Jul 2024 15:58:37 +0200 Subject: [PATCH] Signal n models (#373) * Add Signal N and signal N generators * Add integration tests * Add documentation Signed-off-by: lisrte --- docs/dynamic_simulation/dynamic-models-dsl.md | 1 + .../dynawo/it/DynawoSimulationTest.java | 30 +++++ .../ieee14/disconnectline/eventModels.groovy | 1 + .../test/resources/ieee14/signal_n/IEEE14.par | 118 ++++++++++++++++++ .../ieee14/signal_n/dynamicModels.groovy | 40 ++++++ .../dynawo/DynawoSimulationContext.java | 31 +++-- .../builders/ModelConfigLoaderImpl.java | 3 +- .../models/buses/BusOfSignalNModel.java | 20 +++ .../models/buses/DefaultBusOfSignalN.java | 43 +++++++ .../frequencysynchronizers/SignalN.java | 62 +++++++++ .../frequencysynchronizers/SignalNModel.java | 23 ++++ .../models/generators/SignalNGenerator.java | 33 +++++ .../generators/SignalNGeneratorBuilder.java | 62 +++++++++ .../src/main/resources/models.json | 32 +++++ .../builders/DefaultLibBuilderTest.java | 2 + .../xml/MixedFreqSynchSignalNXmlTest.java | 53 ++++++++ .../powsybl/dynawo/xml/SignalNXmlTest.java | 47 +++++++ .../src/test/resources/signal_n_dyd.xml | 30 +++++ 18 files changed, 620 insertions(+), 11 deletions(-) create mode 100644 dynawo-integration-tests/src/test/resources/ieee14/signal_n/IEEE14.par create mode 100644 dynawo-integration-tests/src/test/resources/ieee14/signal_n/dynamicModels.groovy create mode 100644 dynawo-simulation/src/main/java/com/powsybl/dynawo/models/buses/BusOfSignalNModel.java create mode 100644 dynawo-simulation/src/main/java/com/powsybl/dynawo/models/buses/DefaultBusOfSignalN.java create mode 100644 dynawo-simulation/src/main/java/com/powsybl/dynawo/models/frequencysynchronizers/SignalN.java create mode 100644 dynawo-simulation/src/main/java/com/powsybl/dynawo/models/frequencysynchronizers/SignalNModel.java create mode 100644 dynawo-simulation/src/main/java/com/powsybl/dynawo/models/generators/SignalNGenerator.java create mode 100644 dynawo-simulation/src/main/java/com/powsybl/dynawo/models/generators/SignalNGeneratorBuilder.java create mode 100644 dynawo-simulation/src/test/java/com/powsybl/dynawo/xml/MixedFreqSynchSignalNXmlTest.java create mode 100644 dynawo-simulation/src/test/java/com/powsybl/dynawo/xml/SignalNXmlTest.java create mode 100644 dynawo-simulation/src/test/resources/signal_n_dyd.xml diff --git a/docs/dynamic_simulation/dynamic-models-dsl.md b/docs/dynamic_simulation/dynamic-models-dsl.md index 7ff17ca1d..fdeb3cb0c 100644 --- a/docs/dynamic_simulation/dynamic-models-dsl.md +++ b/docs/dynamic_simulation/dynamic-models-dsl.md @@ -72,6 +72,7 @@ Ultimately, all groovy scripts call dedicated builders that can be used directly * HvdcPBuilder * HvdcVscBuilder * GeneratorFictitiousBuilder +* SignalNGeneratorBuilder * SynchronizedGeneratorBuilder * SynchronousGeneratorBuilder * WeccBuilder diff --git a/dynawo-integration-tests/src/test/java/com/powsybl/dynawo/it/DynawoSimulationTest.java b/dynawo-integration-tests/src/test/java/com/powsybl/dynawo/it/DynawoSimulationTest.java index e8ddcb85d..d35d33f1b 100644 --- a/dynawo-integration-tests/src/test/java/com/powsybl/dynawo/it/DynawoSimulationTest.java +++ b/dynawo-integration-tests/src/test/java/com/powsybl/dynawo/it/DynawoSimulationTest.java @@ -308,4 +308,34 @@ private void checkFirstTimeLineEvent(TimelineEvent event, double time, String mo assertEquals(modelName, event.modelName()); assertEquals(message, event.message()); } + + @Test + void testIEEE14SignalN() { + Network network = Network.read(new ResourceDataSource("IEEE14", new ResourceSet("/ieee14", "IEEE14.iidm"))); + + GroovyDynamicModelsSupplier dynamicModelsSupplier = new GroovyDynamicModelsSupplier( + getResourceAsStream("/ieee14/signal_n/dynamicModels.groovy"), + GroovyExtension.find(DynamicModelGroovyExtension.class, DynawoSimulationProvider.NAME)); + GroovyEventModelsSupplier eventModelsSupplier = new GroovyEventModelsSupplier( + getResourceAsStream("/ieee14/disconnectline/eventModels.groovy"), + GroovyExtension.find(EventModelGroovyExtension.class, DynawoSimulationProvider.NAME)); + + dynawoSimulationParameters.setModelsParameters(ParametersXml.load(getResourceAsStream("/ieee14/signal_n/IEEE14.par"))) + .setNetworkParameters(ParametersXml.load(getResourceAsStream("/ieee14/signal_n/IEEE14.par"), "Network")) + .setSolverParameters(ParametersXml.load(getResourceAsStream("/ieee14/signal_n/IEEE14.par"), "SimplifiedSolver")) + .setLogLevelFilter(DynawoSimulationParameters.LogLevel.DEBUG) + .setSolverType(DynawoSimulationParameters.SolverType.SIM) + .setTimelineExportMode(DynawoSimulationParameters.ExportMode.XML); + + DynamicSimulationResult result = provider.run(network, dynamicModelsSupplier, eventModelsSupplier, CurvesSupplier.empty(), + VariantManagerConstants.INITIAL_VARIANT_ID, computationManager, parameters, NO_OP) + .join(); + + assertEquals(DynamicSimulationResult.Status.SUCCESS, result.getStatus()); + assertTrue(result.getStatusText().isEmpty()); + assertEquals(0, result.getCurves().size()); + List timeLine = result.getTimeLine(); + assertEquals(1, timeLine.size()); + checkFirstTimeLineEvent(timeLine.get(0), 10, "_BUS____1-BUS____5-1_AC", "LINE : opening on side 2"); + } } diff --git a/dynawo-integration-tests/src/test/resources/ieee14/disconnectline/eventModels.groovy b/dynawo-integration-tests/src/test/resources/ieee14/disconnectline/eventModels.groovy index f15f829a7..3dc82969f 100644 --- a/dynawo-integration-tests/src/test/resources/ieee14/disconnectline/eventModels.groovy +++ b/dynawo-integration-tests/src/test/resources/ieee14/disconnectline/eventModels.groovy @@ -4,6 +4,7 @@ * 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/. */ +package ieee14.disconnectline import com.powsybl.iidm.network.TwoSides diff --git a/dynawo-integration-tests/src/test/resources/ieee14/signal_n/IEEE14.par b/dynawo-integration-tests/src/test/resources/ieee14/signal_n/IEEE14.par new file mode 100644 index 000000000..b0056d93a --- /dev/null +++ b/dynawo-integration-tests/src/test/resources/ieee14/signal_n/IEEE14.par @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dynawo-integration-tests/src/test/resources/ieee14/signal_n/dynamicModels.groovy b/dynawo-integration-tests/src/test/resources/ieee14/signal_n/dynamicModels.groovy new file mode 100644 index 000000000..d7ade18c7 --- /dev/null +++ b/dynawo-integration-tests/src/test/resources/ieee14/signal_n/dynamicModels.groovy @@ -0,0 +1,40 @@ +/** + * 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 ieee14.signal_n + +GeneratorPVSignalN { + staticId "_GEN____1_SM" + parameterSetId "Generator1" +} + +GeneratorPVSignalN { + staticId "_GEN____2_SM" + parameterSetId "Generator2" +} + +GeneratorPVSignalN { + staticId "_GEN____3_SM" + parameterSetId "Generator3" +} + +GeneratorPVSignalN { + staticId "_GEN____6_SM" + parameterSetId "Generator6" +} + +GeneratorPVSignalN { + staticId "_GEN____8_SM" + parameterSetId "Generator8" +} + +for (load in network.loads) { + LoadAlphaBetaRestorative { + staticId load.id + parameterSetId "GenericRestorativeLoad" + } +} \ No newline at end of file diff --git a/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoSimulationContext.java b/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoSimulationContext.java index 3eda357c6..fa2ac14b9 100644 --- a/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoSimulationContext.java +++ b/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoSimulationContext.java @@ -18,10 +18,7 @@ import com.powsybl.dynawo.models.buses.AbstractBus; import com.powsybl.dynawo.models.defaultmodels.DefaultModelsHandler; import com.powsybl.dynawo.models.events.ContextDependentEvent; -import com.powsybl.dynawo.models.frequencysynchronizers.FrequencySynchronizedModel; -import com.powsybl.dynawo.models.frequencysynchronizers.FrequencySynchronizerModel; -import com.powsybl.dynawo.models.frequencysynchronizers.OmegaRef; -import com.powsybl.dynawo.models.frequencysynchronizers.SetPoint; +import com.powsybl.dynawo.models.frequencysynchronizers.*; import com.powsybl.dynawo.models.macroconnections.MacroConnect; import com.powsybl.dynawo.models.macroconnections.MacroConnectionsAdder; import com.powsybl.dynawo.models.macroconnections.MacroConnector; @@ -102,7 +99,7 @@ public DynawoSimulationContext(Network network, String workingVariantId, List simplifyModels(Stream inputBbm, Rep return outputBbm; } - private FrequencySynchronizerModel setupFrequencySynchronizer(Function, FrequencySynchronizerModel> fsConstructor) { - return fsConstructor.apply(dynamicModels.stream() - .filter(FrequencySynchronizedModel.class::isInstance) - .map(FrequencySynchronizedModel.class::cast) - .toList()); + private FrequencySynchronizerModel setupFrequencySynchronizer() { + List signalNModels = filterDynamicModels(SignalNModel.class); + List frequencySynchronizedModels = filterDynamicModels(FrequencySynchronizedModel.class); + boolean hasSpecificBuses = dynamicModels.stream().anyMatch(AbstractBus.class::isInstance); + boolean hasSignalNModel = !signalNModels.isEmpty(); + if (!frequencySynchronizedModels.isEmpty() && hasSignalNModel) { + throw new PowsyblException("Signal N and frequency synchronized generators cannot be used with one another"); + } + if (hasSignalNModel) { + return new SignalN(signalNModels); + } + return hasSpecificBuses ? new SetPoint(frequencySynchronizedModels) : new OmegaRef(frequencySynchronizedModels); + } + + private List filterDynamicModels(Class modelClass) { + return dynamicModels.stream() + .filter(modelClass::isInstance) + .map(modelClass::cast) + .toList(); } public Network getNetwork() { diff --git a/dynawo-simulation/src/main/java/com/powsybl/dynawo/builders/ModelConfigLoaderImpl.java b/dynawo-simulation/src/main/java/com/powsybl/dynawo/builders/ModelConfigLoaderImpl.java index 789910cae..9d589b4a2 100644 --- a/dynawo-simulation/src/main/java/com/powsybl/dynawo/builders/ModelConfigLoaderImpl.java +++ b/dynawo-simulation/src/main/java/com/powsybl/dynawo/builders/ModelConfigLoaderImpl.java @@ -66,7 +66,8 @@ public final class ModelConfigLoaderImpl implements ModelConfigLoader { new BuilderConfig(SynchronizedGeneratorBuilder.CATEGORY, SynchronizedGeneratorBuilder::of, SynchronizedGeneratorBuilder::getSupportedModelInfos), new BuilderConfig(SynchronousGeneratorBuilder.CATEGORY, SynchronousGeneratorBuilder::of, SynchronousGeneratorBuilder::getSupportedModelInfos), new BuilderConfig(WeccBuilder.CATEGORY, WeccBuilder::of, WeccBuilder::getSupportedModelInfos), - new BuilderConfig(GridFormingConverterBuilder.CATEGORY, GridFormingConverterBuilder::of, GridFormingConverterBuilder::getSupportedModelInfos)); + new BuilderConfig(GridFormingConverterBuilder.CATEGORY, GridFormingConverterBuilder::of, GridFormingConverterBuilder::getSupportedModelInfos), + new BuilderConfig(SignalNGeneratorBuilder.CATEGORY, SignalNGeneratorBuilder::of, SignalNGeneratorBuilder::getSupportedModelInfos)); private static final Stream EVENT_BUILDER_CONFIGS = Stream.of( new EventBuilderConfig(EventActivePowerVariationBuilder::of, EventActivePowerVariationBuilder.getEventModelInfo()), diff --git a/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/buses/BusOfSignalNModel.java b/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/buses/BusOfSignalNModel.java new file mode 100644 index 000000000..e6ddd27b2 --- /dev/null +++ b/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/buses/BusOfSignalNModel.java @@ -0,0 +1,20 @@ +/** + * 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.dynawo.models.buses; + +import com.powsybl.dynawo.models.Model; + +/** + * View of signal N equipment from the bus to which it is connected + * Used by Signal N in order to get phi var name + * @author Laurent Issertial {@literal } + */ +public interface BusOfSignalNModel extends Model { + + String getPhiVarName(); +} diff --git a/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/buses/DefaultBusOfSignalN.java b/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/buses/DefaultBusOfSignalN.java new file mode 100644 index 000000000..6dc8c627d --- /dev/null +++ b/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/buses/DefaultBusOfSignalN.java @@ -0,0 +1,43 @@ +/** + * 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.dynawo.models.buses; + +import java.util.List; +import com.powsybl.dynawo.models.defaultmodels.AbstractDefaultModel; +import com.powsybl.dynawo.models.macroconnections.MacroConnectAttribute; +import com.powsybl.dynawo.xml.DynawoSimulationXmlConstants; + +/** + * @author Laurent Issertial {@literal } + */ +public class DefaultBusOfSignalN extends AbstractDefaultModel implements BusOfSignalNModel { + + private final String signalNEquipmentStaticId; + + public DefaultBusOfSignalN(String staticId, String signalNEquipmentStaticId) { + super(staticId); + this.signalNEquipmentStaticId = signalNEquipmentStaticId; + } + + @Override + public String getName() { + return "DefaultBusOfSignalN"; + } + + public String getPhiVarName() { + return "@@NAME@@@NODE@_phi_value"; + } + + @Override + public List getMacroConnectToAttributes() { + return List.of( + MacroConnectAttribute.of("id2", DynawoSimulationXmlConstants.NETWORK), + MacroConnectAttribute.of("name2", signalNEquipmentStaticId) + ); + } +} diff --git a/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/frequencysynchronizers/SignalN.java b/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/frequencysynchronizers/SignalN.java new file mode 100644 index 000000000..222da3df3 --- /dev/null +++ b/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/frequencysynchronizers/SignalN.java @@ -0,0 +1,62 @@ +/** + * 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.dynawo.models.frequencysynchronizers; + +import com.powsybl.dynawo.models.AbstractPureDynamicBlackBoxModel; +import com.powsybl.dynawo.models.VarConnection; +import com.powsybl.dynawo.models.buses.BusOfSignalNModel; +import com.powsybl.dynawo.models.buses.DefaultBusOfSignalN; +import com.powsybl.dynawo.models.macroconnections.MacroConnectionsAdder; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import java.util.List; + +/** + * @author Laurent Issertial {@literal } + */ +public class SignalN extends AbstractPureDynamicBlackBoxModel implements FrequencySynchronizerModel { + + private static final String SIGNAL_N_ID = "Signal_N"; + private static final String LIB = "SignalN"; + private final List signalNEquipments; + + public SignalN(List signalNEquipments) { + super(SIGNAL_N_ID, "", LIB); + this.signalNEquipments = signalNEquipments; + } + + @Override + public void createMacroConnections(MacroConnectionsAdder adder) { + for (SignalNModel eq : signalNEquipments) { + adder.createMacroConnections(this, eq, getVarConnectionsWith(eq)); + } + SignalNModel firstModel = signalNEquipments.get(0); + BusOfSignalNModel busOf = new DefaultBusOfSignalN(firstModel.getConnectableBus().getId(), firstModel.getStaticId()); + adder.createMacroConnections(this, busOf, getVarConnectionsWithBus(busOf)); + } + + private List getVarConnectionsWith(SignalNModel connected) { + return List.of(new VarConnection("signalN_N", connected.getNVarName())); + } + + private List getVarConnectionsWithBus(BusOfSignalNModel connected) { + return List.of(new VarConnection("signalN_thetaRef", connected.getPhiVarName())); + } + + @Override + public boolean isEmpty() { + return signalNEquipments.isEmpty(); + } + + @Override + protected void writeDynamicAttributes(XMLStreamWriter writer, String parFileName) throws XMLStreamException { + writer.writeAttribute("id", getDynamicModelId()); + writer.writeAttribute("lib", getLib()); + } +} diff --git a/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/frequencysynchronizers/SignalNModel.java b/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/frequencysynchronizers/SignalNModel.java new file mode 100644 index 000000000..0edf3c5a4 --- /dev/null +++ b/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/frequencysynchronizers/SignalNModel.java @@ -0,0 +1,23 @@ +/** + * 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.dynawo.models.frequencysynchronizers; + +import com.powsybl.dynawo.models.Model; +import com.powsybl.iidm.network.Bus; + +/** + * @author Laurent Issertial {@literal } + */ +public interface SignalNModel extends Model { + + String getNVarName(); + + String getStaticId(); + + Bus getConnectableBus(); +} diff --git a/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/generators/SignalNGenerator.java b/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/generators/SignalNGenerator.java new file mode 100644 index 000000000..4ca5c2b07 --- /dev/null +++ b/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/generators/SignalNGenerator.java @@ -0,0 +1,33 @@ +/** + * 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.dynawo.models.generators; + +import com.powsybl.dynawo.models.frequencysynchronizers.SignalNModel; +import com.powsybl.dynawo.models.utils.BusUtils; +import com.powsybl.iidm.network.Bus; +import com.powsybl.iidm.network.Generator; + +/** + * @author Laurent Issertial {@literal } + */ +public class SignalNGenerator extends AbstractGenerator implements SignalNModel { + + protected SignalNGenerator(String dynamicModelId, Generator generator, String parameterSetId, String lib) { + super(dynamicModelId, generator, parameterSetId, lib); + } + + @Override + public String getNVarName() { + return "generator_N"; + } + + @Override + public Bus getConnectableBus() { + return BusUtils.getConnectableBus(equipment); + } +} diff --git a/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/generators/SignalNGeneratorBuilder.java b/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/generators/SignalNGeneratorBuilder.java new file mode 100644 index 000000000..dff900787 --- /dev/null +++ b/dynawo-simulation/src/main/java/com/powsybl/dynawo/models/generators/SignalNGeneratorBuilder.java @@ -0,0 +1,62 @@ +/** + * 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.dynawo.models.generators; + +import com.powsybl.commons.report.ReportNode; +import com.powsybl.dynawo.builders.*; +import com.powsybl.iidm.network.Network; + +import java.util.Collection; + +/** + * @author Laurent Issertial {@literal } + */ +public class SignalNGeneratorBuilder extends AbstractGeneratorBuilder { + + public static final String CATEGORY = "SIGNAL_N_GENERATOR"; + private static final ModelConfigs MODEL_CONFIGS = ModelConfigsHandler.getInstance().getModelConfigs(CATEGORY); + + public static SignalNGeneratorBuilder of(Network network) { + return of(network, ReportNode.NO_OP); + } + + public static SignalNGeneratorBuilder of(Network network, ReportNode reportNode) { + return new SignalNGeneratorBuilder(network, MODEL_CONFIGS.getDefaultModelConfig(), reportNode); + } + + public static SignalNGeneratorBuilder of(Network network, String modelName) { + return of(network, modelName, ReportNode.NO_OP); + } + + public static SignalNGeneratorBuilder of(Network network, String modelName, ReportNode reportNode) { + ModelConfig modelConfig = MODEL_CONFIGS.getModelConfig(modelName); + if (modelConfig == null) { + BuilderReports.reportModelNotFound(reportNode, SignalNGeneratorBuilder.class.getSimpleName(), modelName); + return null; + } + return new SignalNGeneratorBuilder(network, modelConfig, reportNode); + } + + public static Collection getSupportedModelInfos() { + return MODEL_CONFIGS.getModelInfos(); + } + + protected SignalNGeneratorBuilder(Network network, ModelConfig modelConfig, ReportNode reportNode) { + super(network, modelConfig, reportNode); + } + + @Override + public SignalNGenerator build() { + return isInstantiable() ? new SignalNGenerator(dynamicModelId, getEquipment(), parameterSetId, modelConfig.lib()) : null; + } + + @Override + protected SignalNGeneratorBuilder self() { + return this; + } +} diff --git a/dynawo-simulation/src/main/resources/models.json b/dynawo-simulation/src/main/resources/models.json index 32d672e8d..7eec40665 100644 --- a/dynawo-simulation/src/main/resources/models.json +++ b/dynawo-simulation/src/main/resources/models.json @@ -208,6 +208,38 @@ } ] }, + "SIGNAL_N_GENERATOR": { + "defaultLib": "GeneratorPVSignalN", + "libs": [ + { + "lib": "GeneratorPVSignalN" + }, + { + "lib": "GeneratorPQPropSignalN" + }, + { + "lib": "GeneratorPQPropDiagramPQSignalN" + }, + { + "lib": "GeneratorPVPropSignalN" + }, + { + "lib": "GeneratorPVDiagramPQSignalN" + }, + { + "lib": "GeneratorPVRemoteDiagramPQSignalN" + }, + { + "lib": "GeneratorPVTfoDiagramPQSignalN" + }, + { + "lib": "GeneratorPVTfoSignalN" + }, + { + "lib": "GeneratorPVRemoteSignalN" + } + ] + }, "HVDC_P": { "defaultLib": "HvdcPV", "libs": [ diff --git a/dynawo-simulation/src/test/java/com/powsybl/dynawo/builders/DefaultLibBuilderTest.java b/dynawo-simulation/src/test/java/com/powsybl/dynawo/builders/DefaultLibBuilderTest.java index 3f5bdc6c4..7b154b39d 100644 --- a/dynawo-simulation/src/test/java/com/powsybl/dynawo/builders/DefaultLibBuilderTest.java +++ b/dynawo-simulation/src/test/java/com/powsybl/dynawo/builders/DefaultLibBuilderTest.java @@ -73,6 +73,7 @@ void testDefaultLibEquipments() { assertNotNull(SynchronousGeneratorBuilder.of(NETWORK)); assertNotNull(WeccBuilder.of(NETWORK)); assertNotNull(GridFormingConverterBuilder.of(NETWORK)); + assertNotNull(SignalNGeneratorBuilder.of(NETWORK)); // HVDC assertNotNull(HvdcPBuilder.of(NETWORK)); assertNotNull(HvdcVscBuilder.of(NETWORK)); @@ -114,6 +115,7 @@ void testWrongLibEquipments() { assertNull(SynchronousGeneratorBuilder.of(NETWORK, WRONG_LIB)); assertNull(WeccBuilder.of(NETWORK, WRONG_LIB)); assertNull(GridFormingConverterBuilder.of(NETWORK, WRONG_LIB)); + assertNull(SignalNGeneratorBuilder.of(NETWORK, WRONG_LIB)); // HVDC assertNull(HvdcPBuilder.of(NETWORK, WRONG_LIB)); assertNull(HvdcVscBuilder.of(NETWORK, WRONG_LIB)); diff --git a/dynawo-simulation/src/test/java/com/powsybl/dynawo/xml/MixedFreqSynchSignalNXmlTest.java b/dynawo-simulation/src/test/java/com/powsybl/dynawo/xml/MixedFreqSynchSignalNXmlTest.java new file mode 100644 index 000000000..d7f02b1fc --- /dev/null +++ b/dynawo-simulation/src/test/java/com/powsybl/dynawo/xml/MixedFreqSynchSignalNXmlTest.java @@ -0,0 +1,53 @@ +/** + * 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.dynawo.xml; + +import com.powsybl.commons.PowsyblException; +import com.powsybl.dynawo.models.generators.SignalNGeneratorBuilder; +import com.powsybl.dynawo.models.generators.SynchronizedGeneratorBuilder; +import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * @author Laurent Issertial {@literal } + */ +class MixedFreqSynchSignalNXmlTest extends AbstractDynamicModelXmlTest { + + @Override + protected void setupNetwork() { + network = EurostagTutorialExample1Factory.createWithMoreGenerators(); + } + + @Override + protected void addDynamicModels() { + dynamicModels.add(SignalNGeneratorBuilder.of(network, "GeneratorPQPropSignalN") + .dynamicModelId("BBM_GEN") + .staticId("GEN") + .parameterSetId("n") + .build()); + dynamicModels.add(SynchronizedGeneratorBuilder.of(network, "GeneratorPQ") + .dynamicModelId("BBM_GEN2") + .staticId("GEN2") + .parameterSetId("n") + .build()); + } + + @Override + void setupDynawoContext() { + // empty to call super in test + } + + @Test + void testExceptions() { + Exception e = assertThrows(PowsyblException.class, super::setupDynawoContext); + assertEquals("Signal N and frequency synchronized generators cannot be used with one another", e.getMessage()); + } +} diff --git a/dynawo-simulation/src/test/java/com/powsybl/dynawo/xml/SignalNXmlTest.java b/dynawo-simulation/src/test/java/com/powsybl/dynawo/xml/SignalNXmlTest.java new file mode 100644 index 000000000..a51e0864e --- /dev/null +++ b/dynawo-simulation/src/test/java/com/powsybl/dynawo/xml/SignalNXmlTest.java @@ -0,0 +1,47 @@ +/** + * 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.dynawo.xml; + +import com.powsybl.dynawo.models.generators.SignalNGeneratorBuilder; +import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; +import org.junit.jupiter.api.Test; +import org.xml.sax.SAXException; + +import java.io.IOException; + +/** + * @author Laurent Issertial {@literal } + */ +class SignalNXmlTest extends AbstractDynamicModelXmlTest { + + @Override + protected void setupNetwork() { + network = EurostagTutorialExample1Factory.createWithMoreGenerators(); + } + + @Override + protected void addDynamicModels() { + dynamicModels.add(SignalNGeneratorBuilder.of(network, "GeneratorPVRemoteDiagramPQSignalN") + .dynamicModelId("BBM_GEN") + .staticId("GEN") + .parameterSetId("n") + .build()); + dynamicModels.add(SignalNGeneratorBuilder.of(network, "GeneratorPVRemoteDiagramPQSignalN") + .dynamicModelId("BBM_GEN2") + .staticId("GEN2") + .parameterSetId("n") + .build()); + } + + @Test + void writeModel() throws SAXException, IOException { + DydXml.write(tmpDir, context); + ParametersXml.write(tmpDir, context); + validate("dyd.xsd", "signal_n_dyd.xml", tmpDir.resolve(DynawoSimulationConstants.DYD_FILENAME)); + } +} diff --git a/dynawo-simulation/src/test/resources/signal_n_dyd.xml b/dynawo-simulation/src/test/resources/signal_n_dyd.xml new file mode 100644 index 000000000..0e8bda026 --- /dev/null +++ b/dynawo-simulation/src/test/resources/signal_n_dyd.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +