From 218eb5055c456a913c28199f435a0b49e468ce92 Mon Sep 17 00:00:00 2001 From: p-arvy <126792538+p-arvy@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:27:25 +0100 Subject: [PATCH] Add version 1.2 of AMPL exporter (#3220) * Add condenser column in generator file of extended ampl exporter * Add target Q for LCC converter stations * Add new version of extended ampl exporter * Remove public attribut to AbstractAmplExporterTest * Add columns to export active set points (targetP/ac emulation) of hvdc converter stations * Add columns for AC emulation and targetP in VSC table * Move AC emulation parameters from VSC table to HVDC lines table * Fix Q0 unit in batteries/lcc columns Signed-off-by: p-arvy --- .../powsybl/ampl/converter/AmplConstants.java | 2 +- .../converter/version/AmplExportVersion.java | 5 +- .../converter/version/BasicAmplExporter.java | 80 ++++++++---- .../version/ExtendedAmplExporterV2.java | 106 +++++++++++++++ .../converter/AbstractAmplExporterTest.java | 46 +++++++ .../ampl/converter/AmplNetworkWriterTest.java | 17 +-- .../converter/ExtendedAmplExporterTest.java | 23 +--- .../converter/ExtendedAmplExporterV2Test.java | 121 ++++++++++++++++++ .../battery-q0-unit-column.txt | 4 + ...orial-example1-generators-is-condenser.txt | 5 + .../inputs/extended_exporter_v2/headers.txt | 1 + .../hvdc-ac-emul-lcc-test-case.txt | 3 + .../hvdc-ac-emul-vsc-test-case.txt | 3 + .../hvdc-vsc-test-case.txt | 3 + .../lcc-load-target-q-test-case.txt | 4 + docs/grid_exchange_formats/ampl/export.md | 12 +- 16 files changed, 367 insertions(+), 68 deletions(-) create mode 100644 ampl-converter/src/main/java/com/powsybl/ampl/converter/version/ExtendedAmplExporterV2.java create mode 100644 ampl-converter/src/test/java/com/powsybl/ampl/converter/AbstractAmplExporterTest.java create mode 100644 ampl-converter/src/test/java/com/powsybl/ampl/converter/ExtendedAmplExporterV2Test.java create mode 100644 ampl-converter/src/test/resources/inputs/extended_exporter_v2/battery-q0-unit-column.txt create mode 100644 ampl-converter/src/test/resources/inputs/extended_exporter_v2/eurostag-tutorial-example1-generators-is-condenser.txt create mode 100644 ampl-converter/src/test/resources/inputs/extended_exporter_v2/headers.txt create mode 100644 ampl-converter/src/test/resources/inputs/extended_exporter_v2/hvdc-ac-emul-lcc-test-case.txt create mode 100644 ampl-converter/src/test/resources/inputs/extended_exporter_v2/hvdc-ac-emul-vsc-test-case.txt create mode 100644 ampl-converter/src/test/resources/inputs/extended_exporter_v2/hvdc-vsc-test-case.txt create mode 100644 ampl-converter/src/test/resources/inputs/extended_exporter_v2/lcc-load-target-q-test-case.txt diff --git a/ampl-converter/src/main/java/com/powsybl/ampl/converter/AmplConstants.java b/ampl-converter/src/main/java/com/powsybl/ampl/converter/AmplConstants.java index 1a8f7646b2a..d54b1b4553b 100644 --- a/ampl-converter/src/main/java/com/powsybl/ampl/converter/AmplConstants.java +++ b/ampl-converter/src/main/java/com/powsybl/ampl/converter/AmplConstants.java @@ -41,7 +41,7 @@ private AmplConstants() { public static final String NUM = "num"; public static final String BUS = "bus"; public static final String P0 = "p0 (MW)"; - public static final String Q0 = "q0 (MW)"; + public static final String Q0 = "q0 (MVar)"; public static final String ID = "id"; // End column headers diff --git a/ampl-converter/src/main/java/com/powsybl/ampl/converter/version/AmplExportVersion.java b/ampl-converter/src/main/java/com/powsybl/ampl/converter/version/AmplExportVersion.java index 17b385463eb..a4e0abc726d 100644 --- a/ampl-converter/src/main/java/com/powsybl/ampl/converter/version/AmplExportVersion.java +++ b/ampl-converter/src/main/java/com/powsybl/ampl/converter/version/AmplExportVersion.java @@ -25,7 +25,8 @@ public enum AmplExportVersion { V1_0("1.0", BasicAmplExporter::new), - V1_1("1.1", ExtendedAmplExporter::new); + V1_1("1.1", ExtendedAmplExporter::new), + V1_2("1.2", ExtendedAmplExporterV2::new); public interface Factory { AmplColumnsExporter create(AmplExportConfig config, Network network, StringToIntMapper mapper, @@ -64,6 +65,6 @@ public static AmplExportVersion fromExporterId(String exporterId) { } public static AmplExportVersion defaultVersion() { - return V1_1; + return V1_2; } } diff --git a/ampl-converter/src/main/java/com/powsybl/ampl/converter/version/BasicAmplExporter.java b/ampl-converter/src/main/java/com/powsybl/ampl/converter/version/BasicAmplExporter.java index 06267f37b52..e7e71ca40c6 100644 --- a/ampl-converter/src/main/java/com/powsybl/ampl/converter/version/BasicAmplExporter.java +++ b/ampl-converter/src/main/java/com/powsybl/ampl/converter/version/BasicAmplExporter.java @@ -279,7 +279,7 @@ public List getBatteriesColumns() { new Column(CON_BUS), new Column(SUBSTATION), new Column(P0), - new Column(Q0), + new Column("q0 (MW)"), // Wrong unit, fixed in v1.2 new Column(MINP), new Column(MAXP), new Column(MIN_Q_MAX_P), @@ -446,20 +446,32 @@ public void writeHvdcToFormatter(TableFormatter formatter, HvdcLine hvdcLine) th HvdcConverterStation.HvdcType type = hvdcLine.getConverterStation1().getHvdcType(); AmplSubset subset = type.equals( HvdcConverterStation.HvdcType.VSC) ? AmplSubset.VSC_CONVERTER_STATION : AmplSubset.LCC_CONVERTER_STATION; - formatter.writeCell(variantIndex) - .writeCell(num) - .writeCell(type.equals(HvdcConverterStation.HvdcType.VSC) ? 1 : 2) - .writeCell(mapper.getInt(subset, hvdcLine.getConverterStation1().getId())) - .writeCell(mapper.getInt(subset, hvdcLine.getConverterStation2().getId())) - .writeCell(hvdcLine.getR()) - .writeCell(hvdcLine.getNominalV()) - .writeCell(hvdcLine.getConvertersMode().name()) - .writeCell(hvdcLine.getActivePowerSetpoint()) - .writeCell(hvdcLine.getMaxP()) - .writeCell(faultNum) - .writeCell(actionNum) - .writeCell(id) - .writeCell(hvdcLine.getNameOrId()); + TableFormatterHelper formatterHelper = new TableFormatterHelper(formatter); + formatterHelper.addCell(variantIndex) + .addCell(num) + .addCell(type.equals(HvdcConverterStation.HvdcType.VSC) ? 1 : 2) + .addCell(mapper.getInt(subset, hvdcLine.getConverterStation1().getId())) + .addCell(mapper.getInt(subset, hvdcLine.getConverterStation2().getId())) + .addCell(hvdcLine.getR()) + .addCell(hvdcLine.getNominalV()) + .addCell(hvdcLine.getConvertersMode().name()) + .addCell(hvdcLine.getActivePowerSetpoint()) + .addCell(hvdcLine.getMaxP()) + .addCell(faultNum) + .addCell(actionNum) + .addCell(id) + .addCell(hvdcLine.getNameOrId()); + + // Add cells if necessary + addAdditionalCellsHvdcLine(formatterHelper, hvdcLine); + + // Write the cells + formatterHelper.write(); + } + + public void addAdditionalCellsHvdcLine(TableFormatterHelper formatterHelper, + HvdcLine hvdcLine) { + // Nothing to do here } @Override @@ -473,19 +485,31 @@ public void writeLccConverterStationToFormatter(TableFormatter formatter, int num = mapper.getInt(AmplSubset.LCC_CONVERTER_STATION, lccStation.getId()); - formatter.writeCell(variantIndex) - .writeCell(num) - .writeCell(busNum) - .writeCell(conBusNum != -1 ? conBusNum : busNum) - .writeCell(vlNum) - .writeCell(lccStation.getLossFactor()) - .writeCell(lccStation.getPowerFactor()) - .writeCell(faultNum) - .writeCell(actionNum) - .writeCell(lccStation.getId()) - .writeCell(lccStation.getNameOrId()) - .writeCell(t.getP()) - .writeCell(t.getQ()); + TableFormatterHelper formatterHelper = new TableFormatterHelper(formatter); + formatterHelper.addCell(variantIndex) + .addCell(num) + .addCell(busNum) + .addCell(conBusNum != -1 ? conBusNum : busNum) + .addCell(vlNum) + .addCell(lccStation.getLossFactor()) + .addCell(lccStation.getPowerFactor()) + .addCell(faultNum) + .addCell(actionNum) + .addCell(lccStation.getId()) + .addCell(lccStation.getNameOrId()) + .addCell(t.getP()) + .addCell(t.getQ()); + + // Add cells if necessary + addAdditionalCellsLccConverterStation(formatterHelper, lccStation); + + // Write the cells + formatterHelper.write(); + } + + public void addAdditionalCellsLccConverterStation(TableFormatterHelper formatterHelper, + LccConverterStation lccStation) { + // Nothing to do here } @Override diff --git a/ampl-converter/src/main/java/com/powsybl/ampl/converter/version/ExtendedAmplExporterV2.java b/ampl-converter/src/main/java/com/powsybl/ampl/converter/version/ExtendedAmplExporterV2.java new file mode 100644 index 00000000000..979bed70a2a --- /dev/null +++ b/ampl-converter/src/main/java/com/powsybl/ampl/converter/version/ExtendedAmplExporterV2.java @@ -0,0 +1,106 @@ +/** + * 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.ampl.converter.version; + +import com.powsybl.ampl.converter.AmplExportConfig; +import com.powsybl.ampl.converter.AmplSubset; +import com.powsybl.commons.io.table.Column; +import com.powsybl.commons.io.table.TableFormatterHelper; +import com.powsybl.commons.util.StringToIntMapper; +import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.extensions.HvdcAngleDroopActivePowerControl; +import com.powsybl.iidm.network.util.HvdcUtils; + +import java.util.ArrayList; +import java.util.List; + +import static com.powsybl.ampl.converter.AmplConstants.*; + +/** + * @author Pierre ARVY {@literal } + */ +public class ExtendedAmplExporterV2 extends ExtendedAmplExporter { + + private static final int BATTERY_Q0_COLUMN_INDEX = 6; + private static final int GENERATOR_IS_CONDENSER_COLUMN_INDEX = 16; + private static final int LCC_TARGET_Q_COLUMN_INDEX = 5; + private static final int HVDC_AC_EMULATION_COLUMN_INDEX = 8; + private static final int HVDC_P_OFFSET_COLUMN_INDEX = 10; + private static final int HVDC_K_COLUMN_INDEX = 11; + + public ExtendedAmplExporterV2(AmplExportConfig config, + Network network, + StringToIntMapper mapper, + int variantIndex, int faultNum, int actionNum) { + super(config, network, mapper, variantIndex, faultNum, actionNum); + } + + @Override + public List getBatteriesColumns() { + List batteriesColumns = new ArrayList<>(super.getBatteriesColumns()); + // fix unit of q0 column + batteriesColumns.set(BATTERY_Q0_COLUMN_INDEX, new Column(Q0)); + return batteriesColumns; + } + + @Override + public List getGeneratorsColumns() { + List generatorsColumns = new ArrayList<>(super.getGeneratorsColumns()); + // add column to indicate if generator is a condenser + generatorsColumns.add(GENERATOR_IS_CONDENSER_COLUMN_INDEX, new Column("condenser")); + return generatorsColumns; + } + + @Override + public List getLccConverterStationsColumns() { + List lccColumns = new ArrayList<>(super.getLccConverterStationsColumns()); + // add columns for load target Q of converter station + lccColumns.add(LCC_TARGET_Q_COLUMN_INDEX, new Column(Q0)); + return lccColumns; + } + + @Override + public List getHvdcLinesColumns() { + List hvdcColumns = new ArrayList<>(super.getHvdcLinesColumns()); + // add columns for AC emulation + hvdcColumns.add(HVDC_AC_EMULATION_COLUMN_INDEX, new Column("ac emul.")); + hvdcColumns.add(HVDC_P_OFFSET_COLUMN_INDEX, new Column("P offset (MW)")); + hvdcColumns.add(HVDC_K_COLUMN_INDEX, new Column("k (MW/rad)")); + return hvdcColumns; + } + + @Override + public void addAdditionalCellsGenerator(TableFormatterHelper formatterHelper, Generator gen) { + super.addAdditionalCellsGenerator(formatterHelper, gen); + formatterHelper.addCell(gen.isCondenser(), GENERATOR_IS_CONDENSER_COLUMN_INDEX); + } + + @Override + public void addAdditionalCellsLccConverterStation(TableFormatterHelper formatterHelper, + LccConverterStation lccStation) { + double loadTargetQ = HvdcUtils.getLccConverterStationLoadTargetQ(lccStation); + formatterHelper.addCell(loadTargetQ, LCC_TARGET_Q_COLUMN_INDEX); + } + + @Override + public void addAdditionalCellsHvdcLine(TableFormatterHelper formatterHelper, + HvdcLine hvdcLine) { + boolean isEnabled = false; + double p0 = Double.NaN; + double k = Double.NaN; + HvdcAngleDroopActivePowerControl droopControl = hvdcLine.getExtension(HvdcAngleDroopActivePowerControl.class); + if (droopControl != null) { + isEnabled = droopControl.isEnabled(); + p0 = droopControl.getP0(); + k = droopControl.getDroop() * 180 / Math.PI; // export MW/rad as voltage angles are exported in rad + } + formatterHelper.addCell(isEnabled, HVDC_AC_EMULATION_COLUMN_INDEX); + formatterHelper.addCell(p0, HVDC_P_OFFSET_COLUMN_INDEX); + formatterHelper.addCell(k, HVDC_K_COLUMN_INDEX); + } +} diff --git a/ampl-converter/src/test/java/com/powsybl/ampl/converter/AbstractAmplExporterTest.java b/ampl-converter/src/test/java/com/powsybl/ampl/converter/AbstractAmplExporterTest.java new file mode 100644 index 00000000000..4200e22569c --- /dev/null +++ b/ampl-converter/src/test/java/com/powsybl/ampl/converter/AbstractAmplExporterTest.java @@ -0,0 +1,46 @@ +/** + * 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.ampl.converter; + +import com.powsybl.commons.datasource.MemDataSource; +import com.powsybl.commons.test.AbstractSerDeTest; +import org.junit.jupiter.api.BeforeEach; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import static com.powsybl.commons.test.ComparisonUtils.assertTxtEquals; + +/** + * @author Geoffroy Jamgotchian {@literal } + * @author Pierre ARVY {@literal } + */ +abstract class AbstractAmplExporterTest extends AbstractSerDeTest { + + MemDataSource dataSource; + AmplExporter exporter; + Properties properties; + + protected void assertEqualsToRef(MemDataSource dataSource, String suffix, String refFileName) throws IOException { + try (InputStream actual = new ByteArrayInputStream(dataSource.getData(suffix, "txt"))) { + assertTxtEquals(getClass().getResourceAsStream("/" + refFileName), actual); + } + } + + @Override + @BeforeEach + public void setUp() throws IOException { + super.setUp(); + dataSource = new MemDataSource(); + exporter = new AmplExporter(); + properties = new Properties(); + } + +} diff --git a/ampl-converter/src/test/java/com/powsybl/ampl/converter/AmplNetworkWriterTest.java b/ampl-converter/src/test/java/com/powsybl/ampl/converter/AmplNetworkWriterTest.java index f2fec589d23..da0b5bfd413 100644 --- a/ampl-converter/src/test/java/com/powsybl/ampl/converter/AmplNetworkWriterTest.java +++ b/ampl-converter/src/test/java/com/powsybl/ampl/converter/AmplNetworkWriterTest.java @@ -7,7 +7,6 @@ */ package com.powsybl.ampl.converter; -import com.powsybl.commons.test.AbstractSerDeTest; import com.powsybl.commons.datasource.DataSource; import com.powsybl.commons.datasource.MemDataSource; import com.powsybl.iidm.network.*; @@ -15,32 +14,20 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; import java.util.Properties; -import static com.powsybl.commons.test.ComparisonUtils.assertTxtEquals; import static org.junit.jupiter.api.Assertions.*; /** * @author Geoffroy Jamgotchian {@literal } */ -class AmplNetworkWriterTest extends AbstractSerDeTest { - - Properties properties; - - private void assertEqualsToRef(MemDataSource dataSource, String suffix, String refFileName) throws IOException { - try (InputStream actual = new ByteArrayInputStream(dataSource.getData(suffix, "txt"))) { - assertTxtEquals(getClass().getResourceAsStream("/" + refFileName), actual); - } - } +class AmplNetworkWriterTest extends AbstractAmplExporterTest { @Override @BeforeEach public void setUp() throws IOException { super.setUp(); - properties = new Properties(); properties.put("iidm.export.ampl.export-version", "1.0"); } @@ -274,7 +261,7 @@ void writeHeadersWithUnknownVersion() { Exception e = assertThrows(IllegalArgumentException.class, () -> export(network, properties, dataSource)); - assertTrue(e.getMessage().contains("Value V1_0 of parameter iidm.export.ampl.export-version is not contained in possible values [1.0, 1.1]")); + assertTrue(e.getMessage().contains("Value V1_0 of parameter iidm.export.ampl.export-version is not contained in possible values [1.0, 1.1, 1.2]")); } @Test diff --git a/ampl-converter/src/test/java/com/powsybl/ampl/converter/ExtendedAmplExporterTest.java b/ampl-converter/src/test/java/com/powsybl/ampl/converter/ExtendedAmplExporterTest.java index 352bc050956..ac9d4f708c9 100644 --- a/ampl-converter/src/test/java/com/powsybl/ampl/converter/ExtendedAmplExporterTest.java +++ b/ampl-converter/src/test/java/com/powsybl/ampl/converter/ExtendedAmplExporterTest.java @@ -7,44 +7,25 @@ */ package com.powsybl.ampl.converter; -import com.powsybl.commons.datasource.MemDataSource; -import com.powsybl.commons.test.AbstractSerDeTest; import com.powsybl.iidm.network.*; import com.powsybl.iidm.network.extensions.SlackTerminalAdder; import com.powsybl.iidm.network.test.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -import static com.powsybl.commons.test.ComparisonUtils.assertTxtEquals; /** * @author Nicolas PIERRE {@literal } * @author Pierre ARVY {@literal } */ -class ExtendedAmplExporterTest extends AbstractSerDeTest { - - MemDataSource dataSource; - AmplExporter exporter; - Properties properties; - - private void assertEqualsToRef(MemDataSource dataSource, String suffix, String refFileName) throws IOException { - try (InputStream actual = new ByteArrayInputStream(dataSource.getData(suffix, "txt"))) { - assertTxtEquals(getClass().getResourceAsStream("/" + refFileName), actual); - } - } +class ExtendedAmplExporterTest extends AbstractAmplExporterTest { @Override @BeforeEach public void setUp() throws IOException { super.setUp(); - dataSource = new MemDataSource(); - exporter = new AmplExporter(); - properties = new Properties(); + properties.put("iidm.export.ampl.export-version", "1.1"); } @Test diff --git a/ampl-converter/src/test/java/com/powsybl/ampl/converter/ExtendedAmplExporterV2Test.java b/ampl-converter/src/test/java/com/powsybl/ampl/converter/ExtendedAmplExporterV2Test.java new file mode 100644 index 00000000000..7d17b632a52 --- /dev/null +++ b/ampl-converter/src/test/java/com/powsybl/ampl/converter/ExtendedAmplExporterV2Test.java @@ -0,0 +1,121 @@ +/** + * 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.ampl.converter; + +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.extensions.HvdcAngleDroopActivePowerControlAdder; +import com.powsybl.iidm.network.test.BatteryNetworkFactory; +import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; +import com.powsybl.iidm.network.test.HvdcTestNetwork; +import org.junit.jupiter.api.Test; + +import java.io.IOException; + +/** + * @author Pierre ARVY {@literal } + */ +class ExtendedAmplExporterV2Test extends AbstractAmplExporterTest { + + @Test + void testNoModifiedExports() throws IOException { + Network network = EurostagTutorialExample1Factory.createWithMoreGenerators(); + + exporter.export(network, properties, dataSource); + + // no modification compared to ampl exporter v1.0 + assertEqualsToRef(dataSource, "_network_substations", "inputs/eurostag-tutorial-example1-substations.txt"); + assertEqualsToRef(dataSource, "_network_rtc", "inputs/eurostag-tutorial-example1-rtc.txt"); + assertEqualsToRef(dataSource, "_network_ptc", "inputs/eurostag-tutorial-example1-ptc.txt"); + assertEqualsToRef(dataSource, "_network_loads", "inputs/eurostag-tutorial-example1-loads.txt"); + assertEqualsToRef(dataSource, "_network_limits", "inputs/eurostag-tutorial-example1-limits.txt"); + } + + @Test + void testQ0UnitColumnBatteries() throws IOException { + Network network = BatteryNetworkFactory.create(); + + exporter.export(network, properties, dataSource); + + assertEqualsToRef(dataSource, "_network_batteries", "inputs/extended_exporter_v2/battery-q0-unit-column.txt"); + } + + @Test + void testIsCondenserExportGenerators() throws IOException { + Network network = EurostagTutorialExample1Factory.createWithMoreGenerators(); + network.getVoltageLevel("VLGEN").newGenerator() + .setId("GEN3") + .setBus("NGEN") + .setConnectableBus("NGEN") + .setMinP(-9999.99) + .setMaxP(9999.99) + .setVoltageRegulatorOn(true) + .setRegulatingTerminal(network.getLoad("LOAD").getTerminal()) + .setTargetV(152.5) + .setTargetP(607.0) + .setTargetQ(301.0) + .setCondenser(true) + .add(); + + exporter.export(network, properties, dataSource); + + assertEqualsToRef(dataSource, "_network_generators", + "inputs/extended_exporter_v2/eurostag-tutorial-example1-generators-is-condenser.txt"); + } + + @Test + void testLccLoadTargetQ() throws IOException { + Network network = HvdcTestNetwork.createLcc(); + + exporter.export(network, properties, dataSource); + + // Check hvdc line has null parameter for ac emulation + assertEqualsToRef(dataSource, "_network_hvdc", "inputs/extended_exporter_v2/hvdc-ac-emul-lcc-test-case.txt"); + + // Check target Q has been added to LCC converter station table + assertEqualsToRef(dataSource, "_network_lcc_converter_stations", "inputs/extended_exporter_v2/lcc-load-target-q-test-case.txt"); + } + + @Test + void testHvdcNoAcEmulation() throws IOException { + Network network = HvdcTestNetwork.createVsc(); + + exporter.export(network, properties, dataSource); + + // Check that export is the same as for basic AMPL exporter + assertEqualsToRef(dataSource, "_network_vsc_converter_stations", "inputs/vsc-test-case.txt"); + + // Check hvdc line has null parameter for ac emulation + assertEqualsToRef(dataSource, "_network_hvdc", "inputs/extended_exporter_v2/hvdc-vsc-test-case.txt"); + } + + @Test + void testHvdcAcEmulation() throws IOException { + Network network = HvdcTestNetwork.createVsc(); + network.getHvdcLine("L").newExtension(HvdcAngleDroopActivePowerControlAdder.class) + .withP0(200.0f) + .withDroop(0.9f) + .withEnabled(true) + .add(); + + exporter.export(network, properties, dataSource); + + // Check that export is the same as for basic AMPL exporter + assertEqualsToRef(dataSource, "_network_vsc_converter_stations", "inputs/vsc-test-case.txt"); + + // Check ac emulation parameters of the hvdc line + assertEqualsToRef(dataSource, "_network_hvdc", "inputs/extended_exporter_v2/hvdc-ac-emul-vsc-test-case.txt"); + } + + @Test + void writeHeadersWithVersion12() throws IOException { + Network network = Network.create("dummy_network", "test"); + exporter.export(network, properties, dataSource); + assertEqualsToRef(dataSource, "_headers", "inputs/extended_exporter_v2/headers.txt"); + } + +} diff --git a/ampl-converter/src/test/resources/inputs/extended_exporter_v2/battery-q0-unit-column.txt b/ampl-converter/src/test/resources/inputs/extended_exporter_v2/battery-q0-unit-column.txt new file mode 100644 index 00000000000..64c1bfc93fb --- /dev/null +++ b/ampl-converter/src/test/resources/inputs/extended_exporter_v2/battery-q0-unit-column.txt @@ -0,0 +1,4 @@ +#Batteries (fictitious/InitialState) +#"variant" "num" "bus" "con. bus" "substation" "p0 (MW)" "q0 (MVar)" "minP (MW)" "maxP (MW)" "minQmaxP (MVar)" "minQ0 (MVar)" "minQminP (MVar)" "maxQmaxP (MVar)" "maxQ0 (MVar)" "maxQminP (MVar)" "fault" "curative" "id" "description" "P (MW)" "Q (MVar)" +1 1 2 2 2 9999.99 9999.99 -9999.99 9999.99 -9999.99 -9999.99 -9999.99 9999.99 9999.99 9999.99 0 0 "BAT" "BAT" -605.000 -225.000 +1 2 2 2 2 100.000 200.000 -200.000 200.000 -54.5500 -59.3000 -59.3000 46.2500 60.0000 60.0000 0 0 "BAT2" "BAT2" -605.000 -225.000 diff --git a/ampl-converter/src/test/resources/inputs/extended_exporter_v2/eurostag-tutorial-example1-generators-is-condenser.txt b/ampl-converter/src/test/resources/inputs/extended_exporter_v2/eurostag-tutorial-example1-generators-is-condenser.txt new file mode 100644 index 00000000000..4f489e6465f --- /dev/null +++ b/ampl-converter/src/test/resources/inputs/extended_exporter_v2/eurostag-tutorial-example1-generators-is-condenser.txt @@ -0,0 +1,5 @@ +#Generators (sim1/InitialState) +#"variant" "num" "bus" "con. bus" "substation" "minP (MW)" "maxP (MW)" "minQmaxP (MVar)" "minQ0 (MVar)" "minQminP (MVar)" "maxQmaxP (MVar)" "maxQ0 (MVar)" "maxQminP (MVar)" "v regul." "v regul. bus" "targetV (pu)" "condenser" "targetP (MW)" "targetQ (MVar)" "fault" "curative" "id" "description" "P (MW)" "Q (MVar)" +1 1 1 1 1 -9999.99 9999.99 -9999.99 -9999.99 -9999.99 9999.99 9999.99 9999.99 true 1 1.02083 false 607.000 301.000 0 0 "GEN" "GEN" -99999.0 -99999.0 +1 2 1 1 1 -9999.99 9999.99 4.00000 6.00000 6.00000 5.00000 7.00000 7.00000 true 1 1.02083 false 607.000 301.000 0 0 "GEN2" "GEN2" -99999.0 -99999.0 +1 3 1 1 1 -9999.99 9999.99 -1.79769e+308 -1.79769e+308 -1.79769e+308 1.79769e+308 1.79769e+308 1.79769e+308 true 4 1.01667 true 607.000 301.000 0 0 "GEN3" "GEN3" -99999.0 -99999.0 diff --git a/ampl-converter/src/test/resources/inputs/extended_exporter_v2/headers.txt b/ampl-converter/src/test/resources/inputs/extended_exporter_v2/headers.txt new file mode 100644 index 00000000000..ef7df68cb0f --- /dev/null +++ b/ampl-converter/src/test/resources/inputs/extended_exporter_v2/headers.txt @@ -0,0 +1 @@ +version 1.2 diff --git a/ampl-converter/src/test/resources/inputs/extended_exporter_v2/hvdc-ac-emul-lcc-test-case.txt b/ampl-converter/src/test/resources/inputs/extended_exporter_v2/hvdc-ac-emul-lcc-test-case.txt new file mode 100644 index 00000000000..ad929ff3a19 --- /dev/null +++ b/ampl-converter/src/test/resources/inputs/extended_exporter_v2/hvdc-ac-emul-lcc-test-case.txt @@ -0,0 +1,3 @@ +#HVDC lines (hvdctest/InitialState) +#"variant" "num" "type" "converterStation1" "converterStation2" "r (ohm)" "nomV (KV)" "convertersMode" "ac emul." "targetP (MW)" "P offset (MW)" "k (MW/rad)" "maxP (MW)" "fault" "curative" "id" "description" +1 1 2 1 2 1.00000 400.000 "SIDE_1_INVERTER_SIDE_2_RECTIFIER" false 280.000 -99999.0 -99999.0 300.000 0 0 "L" "HVDC" diff --git a/ampl-converter/src/test/resources/inputs/extended_exporter_v2/hvdc-ac-emul-vsc-test-case.txt b/ampl-converter/src/test/resources/inputs/extended_exporter_v2/hvdc-ac-emul-vsc-test-case.txt new file mode 100644 index 00000000000..f07d41ef807 --- /dev/null +++ b/ampl-converter/src/test/resources/inputs/extended_exporter_v2/hvdc-ac-emul-vsc-test-case.txt @@ -0,0 +1,3 @@ +#HVDC lines (hvdctest/InitialState) +#"variant" "num" "type" "converterStation1" "converterStation2" "r (ohm)" "nomV (KV)" "convertersMode" "ac emul." "targetP (MW)" "P offset (MW)" "k (MW/rad)" "maxP (MW)" "fault" "curative" "id" "description" +1 1 1 1 2 1.00000 400.000 "SIDE_1_INVERTER_SIDE_2_RECTIFIER" true 280.000 200.000 51.5662 300.000 0 0 "L" "HVDC" diff --git a/ampl-converter/src/test/resources/inputs/extended_exporter_v2/hvdc-vsc-test-case.txt b/ampl-converter/src/test/resources/inputs/extended_exporter_v2/hvdc-vsc-test-case.txt new file mode 100644 index 00000000000..7aed156ff8e --- /dev/null +++ b/ampl-converter/src/test/resources/inputs/extended_exporter_v2/hvdc-vsc-test-case.txt @@ -0,0 +1,3 @@ +#HVDC lines (hvdctest/InitialState) +#"variant" "num" "type" "converterStation1" "converterStation2" "r (ohm)" "nomV (KV)" "convertersMode" "ac emul." "targetP (MW)" "P offset (MW)" "k (MW/rad)" "maxP (MW)" "fault" "curative" "id" "description" +1 1 1 1 2 1.00000 400.000 "SIDE_1_INVERTER_SIDE_2_RECTIFIER" false 280.000 -99999.0 -99999.0 300.000 0 0 "L" "HVDC" diff --git a/ampl-converter/src/test/resources/inputs/extended_exporter_v2/lcc-load-target-q-test-case.txt b/ampl-converter/src/test/resources/inputs/extended_exporter_v2/lcc-load-target-q-test-case.txt new file mode 100644 index 00000000000..e17116f517a --- /dev/null +++ b/ampl-converter/src/test/resources/inputs/extended_exporter_v2/lcc-load-target-q-test-case.txt @@ -0,0 +1,4 @@ +#LCC Converter Stations (hvdctest/InitialState) +#"variant" "num" "bus" "con. bus" "substation" "q0 (MVar)" "lossFactor (%PDC)" "powerFactor" "fault" "curative" "id" "description" "P (MW)" "Q (MVar)" +1 1 1 1 1 473.542 1.10000 0.500000 0 0 "C1" "Converter1" 100.000 50.0000 +1 2 2 2 2 373.333 1.10000 0.600000 0 0 "C2" "Converter2" 75.0000 25.0000 diff --git a/docs/grid_exchange_formats/ampl/export.md b/docs/grid_exchange_formats/ampl/export.md index 6f8bb055daf..9f942862abd 100644 --- a/docs/grid_exchange_formats/ampl/export.md +++ b/docs/grid_exchange_formats/ampl/export.md @@ -8,8 +8,9 @@ At the moment, there are: - The `BasicAmplExporter` (associated with the `AmplExportVersion` `V1_0`); - The `ExtendedAmplExporter` (associated with the `AmplExportVersion` `V1_1`) that inherits from the `BasicAmplExporter`. +- The `ExtendedAmplExporterV2` (associated with the `AmplExportVersion` `V1_2`) that inherits from the `ExtendedAmplExporter`. -The default version is the `V1_1`. +The default version is the `V1_2`. Exporters define the information written in text files and fed to AMPL regarding: @@ -38,6 +39,15 @@ This exporter adds the following information to the `BasicAmplExporter`: - `r`, `g` and `b` in tap tables as it is already done for `x`; - The regulating bus id for generators and static VAR compensators that are in voltage regulation mode. +### The `ExtendedAmplExporterV2` + +This exporter adds the following information to the `ExtendedAmplExporter`: + +- In the generator tables, a boolean indicating if the generator is a condenser; +- In LCC converter station tables, the load target Q of the converter station; +- In HVDC line tables, the AC emulation parameters, along with a boolean to indicate whether AC emulation is active. + +This exporter also corrects the unit of the load target Q (MVar) in the battery tables. (ampl-export-options)= ## Options