From 390cbcde79c554c0e83f0ef8f74ae45e072c4050 Mon Sep 17 00:00:00 2001 From: parvy Date: Fri, 12 Jan 2024 17:07:50 +0100 Subject: [PATCH 01/28] Refactor output classes. Signed-off-by: parvy --- .../output/AbstractNoThrowOutput.java | 48 +++++++++++++++++++ .../output/ReactiveSlackOutput.java | 44 ++++++----------- .../output/network/AbstractNetworkOutput.java | 39 +++------------ .../network/GeneratorNetworkOutput.java | 17 ++++--- .../ShuntCompensatorNetworkOutput.java | 16 ++++--- .../output/network/SvcNetworkOutput.java | 18 ++++--- .../network/TapPositionNetworkOutput.java | 13 +++-- .../output/network/VscNetworkOutput.java | 19 ++++---- 8 files changed, 121 insertions(+), 93 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/AbstractNoThrowOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/AbstractNoThrowOutput.java index 95786012..6a6dd931 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/AbstractNoThrowOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/AbstractNoThrowOutput.java @@ -6,11 +6,24 @@ */ package com.powsybl.openreac.parameters.output; +import com.powsybl.ampl.converter.AmplConstants; +import com.powsybl.ampl.converter.AmplSubset; +import com.powsybl.commons.util.StringToIntMapper; +import com.powsybl.openreac.OpenReacModel; +import com.powsybl.openreac.exceptions.IncompatibleModelException; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.function.Predicate; +import java.util.regex.Pattern; + /** * @author Nicolas Pierre */ public abstract class AbstractNoThrowOutput implements NoThrowAmplOutput { + private static final Predicate COMMENTED_LINE_TEST = Pattern.compile("\\s*#.*").asMatchPredicate(); + private boolean errorState = false; @Override @@ -18,7 +31,42 @@ public boolean isErrorState() { return errorState; } + @Override + public String getFileName() { + return OpenReacModel.OUTPUT_FILE_PREFIX + "_" + getElement() + "." + OpenReacModel.OUTPUT_FILE_FORMAT.getFileExtension(); + } + + /** + * @return the name of the element that will be read. + */ + public abstract String getElement(); + + public abstract int getExpectedColumns(); + + @Override + public void read(BufferedReader reader, StringToIntMapper stringToIntMapper) throws IOException { + String headers = reader.readLine(); + int readCols = headers.split(OpenReacModel.OUTPUT_FILE_FORMAT.getTokenSeparator()).length; + if (readCols != getExpectedColumns()) { + triggerErrorState(); + throw new IncompatibleModelException("Error reading " + getFileName() + ", wrong number of columns. Expected: " + getExpectedColumns() + ", found:" + readCols); + } + reader.lines().forEach(line -> { + if (!COMMENTED_LINE_TEST.test(line)) { + String[] tokens = line.split(OpenReacModel.OUTPUT_FILE_FORMAT.getTokenSeparator()); + doReadLine(tokens, stringToIntMapper); + } + }); + } + + protected abstract void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper); + + protected double readDouble(String d) { + return Float.parseFloat(d) != AmplConstants.INVALID_FLOAT_VALUE ? Double.parseDouble(d) : Double.NaN; + } + protected void triggerErrorState() { errorState = true; } + } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutput.java index 961c055c..818151a7 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutput.java @@ -6,14 +6,10 @@ */ package com.powsybl.openreac.parameters.output; -import com.powsybl.ampl.converter.AmplConstants; import com.powsybl.ampl.converter.AmplSubset; import com.powsybl.commons.util.StringToIntMapper; -import com.powsybl.openreac.exceptions.IncompatibleModelException; import com.powsybl.openreac.parameters.AmplIOUtils; -import java.io.BufferedReader; -import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -23,9 +19,12 @@ * Reactive slacks in load convention. */ public class ReactiveSlackOutput extends AbstractNoThrowOutput { - + private static final String ELEMENT = "reactive_slacks"; public static final int EXPECTED_COLS = 6; - private static final String SEP = ";"; + private static final int BUS_ID_COLUMN_INDEX = 4; + private static final int VOLTAGE_LEVEL_ID_COLUMN_INDEX = 5; + private static final int REACTIVE_SLACK_GENERATION_COLUMN_INDEX = 2; + private static final int REACTIVE_SLACK_LOAD_COLUMN_INDEX = 3; public static class ReactiveSlack { public final String busId; @@ -58,24 +57,13 @@ public List getSlacks() { } @Override - public String getFileName() { - return "reactiveopf_results_reactive_slacks.csv"; + public String getElement() { + return ELEMENT; } @Override - public void read(BufferedReader reader, StringToIntMapper stringToIntMapper) throws IOException { - String headers = reader.readLine(); - int readCols = headers.split(SEP).length; - if (readCols != EXPECTED_COLS) { - triggerErrorState(); - throw new IncompatibleModelException("Error reading " + getFileName() + ", wrong number of columns. Expected: " + EXPECTED_COLS + ", found:" + readCols); - } else { - String line = reader.readLine(); - while (line != null) { - readLine(line.split(SEP)); - line = reader.readLine(); - } - } + public int getExpectedColumns() { + return EXPECTED_COLS; } @Override @@ -84,19 +72,15 @@ public boolean throwOnMissingFile() { return false; } - private void readLine(String[] tokens) { + protected void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { // slack capacitor is a generation of reactive power. // slack self is a reactive load. - double slackCapacitor = -readDouble(tokens[2]); - double slackSelf = readDouble(tokens[3]); - String id = AmplIOUtils.removeQuotes(tokens[4]); - String voltageLevelId = AmplIOUtils.removeQuotes(tokens[5]); + double slackCapacitor = -readDouble(tokens[REACTIVE_SLACK_GENERATION_COLUMN_INDEX]); + double slackSelf = readDouble(tokens[REACTIVE_SLACK_LOAD_COLUMN_INDEX]); + String id = AmplIOUtils.removeQuotes(tokens[BUS_ID_COLUMN_INDEX]); + String voltageLevelId = AmplIOUtils.removeQuotes(tokens[VOLTAGE_LEVEL_ID_COLUMN_INDEX]); double slack = slackCapacitor + slackSelf; slacks.add(new ReactiveSlack(id, voltageLevelId, slack)); } - private double readDouble(String d) { - return Float.parseFloat(d) != AmplConstants.INVALID_FLOAT_VALUE ? Double.parseDouble(d) : Double.NaN; - } - } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/AbstractNetworkOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/AbstractNetworkOutput.java index ef95a874..77f2b63e 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/AbstractNetworkOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/AbstractNetworkOutput.java @@ -6,18 +6,12 @@ */ package com.powsybl.openreac.parameters.output.network; -import com.powsybl.ampl.converter.AmplSubset; -import com.powsybl.commons.util.StringToIntMapper; import com.powsybl.iidm.modification.NetworkModification; -import com.powsybl.openreac.OpenReacModel; +import com.powsybl.iidm.network.Network; import com.powsybl.openreac.parameters.output.AbstractNoThrowOutput; -import java.io.BufferedReader; -import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.function.Predicate; -import java.util.regex.Pattern; /** * Abstract class that reads output from ampl and generates network modifications @@ -27,39 +21,20 @@ */ public abstract class AbstractNetworkOutput extends AbstractNoThrowOutput { - private static final Predicate COMMENTED_LINE_TEST = Pattern.compile("\\s*#.*").asMatchPredicate(); + protected final Network network; + protected final List modifications = new ArrayList<>(); - private final List modifications = new ArrayList<>(); - - /** - * @return the name of the element that will be read. - */ - public abstract String getElement(); - - @Override - public String getFileName() { - return OpenReacModel.OUTPUT_FILE_PREFIX + "_" + getElement() + "." + OpenReacModel.OUTPUT_FILE_FORMAT.getFileExtension(); + protected AbstractNetworkOutput(Network network) { + this.network = network; } - @Override - public void read(BufferedReader bufferedReader, StringToIntMapper stringToIntMapper) throws IOException { - bufferedReader.lines().forEach(line -> { - if (!COMMENTED_LINE_TEST.test(line)) { - String[] tokens = line.split(OpenReacModel.OUTPUT_FILE_FORMAT.getTokenSeparator()); - modifications.add(doReadLine(tokens, stringToIntMapper)); - } - }); + public List getModifications() { + return modifications; } - protected abstract T doReadLine(String[] tokens, StringToIntMapper stringToIntMapper); - @Override public boolean throwOnMissingFile() { triggerErrorState(); return false; } - - public List getModifications() { - return modifications; - } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/GeneratorNetworkOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/GeneratorNetworkOutput.java index 7a8f72ea..28c620f0 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/GeneratorNetworkOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/GeneratorNetworkOutput.java @@ -16,13 +16,13 @@ */ public class GeneratorNetworkOutput extends AbstractNetworkOutput { private static final String ELEMENT = "generators"; + public static final int EXPECTED_COLS = 9; private static final int ID_COLUMN_INDEX = 1; private static final int TARGET_V_COLUMN_INDEX = 4; private static final int TARGET_Q_COLUMN_INDEX = 6; - private final Network network; public GeneratorNetworkOutput(Network network) { - this.network = network; + super(network); } @Override @@ -31,10 +31,15 @@ public String getElement() { } @Override - protected GeneratorModification doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { + public int getExpectedColumns() { + return EXPECTED_COLS; + } + + @Override + protected void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { String id = stringToIntMapper.getId(AmplSubset.GENERATOR, Integer.parseInt(tokens[ID_COLUMN_INDEX])); - double targetV = Double.parseDouble(tokens[TARGET_V_COLUMN_INDEX]) * network.getGenerator(id).getRegulatingTerminal().getVoltageLevel().getNominalV(); - double targetQ = Double.parseDouble(tokens[TARGET_Q_COLUMN_INDEX]); + double targetV = readDouble(tokens[TARGET_V_COLUMN_INDEX]) * network.getGenerator(id).getRegulatingTerminal().getVoltageLevel().getNominalV(); + double targetQ = readDouble(tokens[TARGET_Q_COLUMN_INDEX]); GeneratorModification.Modifs modifs = new GeneratorModification.Modifs(); if (targetQ != network.getGenerator(id).getTargetQ()) { @@ -43,6 +48,6 @@ protected GeneratorModification doReadLine(String[] tokens, StringToIntMapper { private static final String ELEMENT = "shunts"; + public static final int EXPECTED_COLS = 6; private static final int ID_COLUMN_INDEX = 1; private static final int B_COLUMN_INDEX = 3; private static final int BUS_COLUMN_INDEX = 2; - private final Network network; public ShuntCompensatorNetworkOutput(Network network) { - this.network = network; + super(network); } @Override @@ -32,10 +32,14 @@ public String getElement() { } @Override - protected ShuntCompensatorModification doReadLine(String[] tokens, - StringToIntMapper stringToIntMapper) { + public int getExpectedColumns() { + return EXPECTED_COLS; + } + + @Override + protected void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { String id = stringToIntMapper.getId(AmplSubset.SHUNT, Integer.parseInt(tokens[ID_COLUMN_INDEX])); - double b = Double.parseDouble(tokens[B_COLUMN_INDEX]); + double b = readDouble(tokens[B_COLUMN_INDEX]); String busId = stringToIntMapper.getId(AmplSubset.BUS, Integer.parseInt(tokens[BUS_COLUMN_INDEX])); Boolean reconnect = null; ShuntCompensator shuntCompensator = network.getShuntCompensator(id); @@ -43,7 +47,7 @@ protected ShuntCompensatorModification doReadLine(String[] tokens, shuntCompensator.getTerminal().getBusView().getConnectableBus().getId())) { reconnect = true; } - return new ShuntCompensatorModification(id, reconnect, shuntCompensator == null ? null : findSectionCount(shuntCompensator, b)); + modifications.add(new ShuntCompensatorModification(id, reconnect, shuntCompensator == null ? null : findSectionCount(shuntCompensator, b))); } /** diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/SvcNetworkOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/SvcNetworkOutput.java index 9d1fa4ad..3dbd1203 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/SvcNetworkOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/SvcNetworkOutput.java @@ -17,13 +17,13 @@ */ public class SvcNetworkOutput extends AbstractNetworkOutput { private static final String ELEMENT = "static_var_compensators"; + public static final int EXPECTED_COLS = 6; private static final int ID_COLUMN_INDEX = 1; private static final int SET_POINT_V_COLUMN_INDEX = 4; private static final int SET_POINT_Q_COLUMN_INDEX = 5; - private final Network network; public SvcNetworkOutput(Network network) { - this.network = network; + super(network); } @Override @@ -32,16 +32,20 @@ public String getElement() { } @Override - protected StaticVarCompensatorModification doReadLine(String[] tokens, - StringToIntMapper stringToIntMapper) { + public int getExpectedColumns() { + return EXPECTED_COLS; + } + + @Override + protected void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { String id = stringToIntMapper.getId(AmplSubset.STATIC_VAR_COMPENSATOR, Integer.parseInt(tokens[ID_COLUMN_INDEX])); StaticVarCompensator staticVarCompensator = network.getStaticVarCompensator(id); - Double targetV = Double.parseDouble(tokens[SET_POINT_V_COLUMN_INDEX]) * staticVarCompensator + Double targetV = readDouble(tokens[SET_POINT_V_COLUMN_INDEX]) * staticVarCompensator .getRegulatingTerminal() .getVoltageLevel() .getNominalV(); - Double targetQ = Double.parseDouble(tokens[SET_POINT_Q_COLUMN_INDEX]); + Double targetQ = readDouble(tokens[SET_POINT_Q_COLUMN_INDEX]); if (targetQ == staticVarCompensator.getReactivePowerSetpoint()) { targetQ = null; @@ -49,6 +53,6 @@ protected StaticVarCompensatorModification doReadLine(String[] tokens, if (targetV == staticVarCompensator.getVoltageSetpoint()) { targetV = null; } - return new StaticVarCompensatorModification(id, targetV, targetQ); + modifications.add(new StaticVarCompensatorModification(id, targetV, targetQ)); } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/TapPositionNetworkOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/TapPositionNetworkOutput.java index 0a8fffce..1fc1151e 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/TapPositionNetworkOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/TapPositionNetworkOutput.java @@ -18,12 +18,12 @@ */ public class TapPositionNetworkOutput extends AbstractNetworkOutput { private static final String ELEMENT = "rtc"; + public static final int EXPECTED_COLS = 3; private static final int TRANSFO_ID_COLUMN_INDEX = 1; private static final int TAP_POS_COLUMN_INDEX = 2; - private final Network network; public TapPositionNetworkOutput(Network network) { - this.network = network; + super(network); } @Override @@ -32,7 +32,12 @@ public String getElement() { } @Override - protected RatioTapPositionModification doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { + public int getExpectedColumns() { + return EXPECTED_COLS; + } + + @Override + protected void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { String transfoId = stringToIntMapper.getId(AmplSubset.BRANCH, Integer.parseInt(tokens[TRANSFO_ID_COLUMN_INDEX])); TwoWindingsTransformer twt = network.getTwoWindingsTransformer(transfoId); if (twt == null || !twt.hasRatioTapChanger()) { @@ -40,6 +45,6 @@ protected RatioTapPositionModification doReadLine(String[] tokens, StringToIntMa } int tapPosition = -1 + twt.getRatioTapChanger().getLowTapPosition() + Integer.parseInt(tokens[TAP_POS_COLUMN_INDEX]); - return new RatioTapPositionModification(transfoId, tapPosition); + modifications.add(new RatioTapPositionModification(transfoId, tapPosition)); } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/VscNetworkOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/VscNetworkOutput.java index 79044d22..c67543dc 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/VscNetworkOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/VscNetworkOutput.java @@ -17,16 +17,14 @@ */ public class VscNetworkOutput extends AbstractNetworkOutput { private static final String ELEMENT = "vsc_converter_stations"; + public static final int EXPECTED_COLS = 8; private static final int ID_COLUMN_INDEX = 1; - - /** - * FIXME Which columns are columns in the ampl should be used Target V or V ? - */ private static final int SET_POINT_V_COLUMN_INDEX = 4; private static final int SET_POINT_Q_COLUMN_INDEX = 5; private final Network network; public VscNetworkOutput(Network network) { + super(network); this.network = network; } @@ -36,14 +34,19 @@ public String getElement() { } @Override - protected VscConverterStationModification doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { + public int getExpectedColumns() { + return EXPECTED_COLS; + } + + @Override + protected void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { String id = stringToIntMapper.getId(AmplSubset.VSC_CONVERTER_STATION, Integer.parseInt(tokens[ID_COLUMN_INDEX])); VscConverterStation vscConverterStation = network.getVscConverterStation(id); - Double targetV = Double.parseDouble(tokens[SET_POINT_V_COLUMN_INDEX]) * vscConverterStation + Double targetV = readDouble(tokens[SET_POINT_V_COLUMN_INDEX]) * vscConverterStation .getRegulatingTerminal() .getVoltageLevel() .getNominalV(); - Double targetQ = Double.parseDouble(tokens[SET_POINT_Q_COLUMN_INDEX]); + Double targetQ = readDouble(tokens[SET_POINT_Q_COLUMN_INDEX]); if (targetQ == vscConverterStation.getReactivePowerSetpoint()) { targetQ = null; @@ -51,6 +54,6 @@ protected VscConverterStationModification doReadLine(String[] tokens, StringToIn if (targetV == vscConverterStation.getVoltageSetpoint()) { targetV = null; } - return new VscConverterStationModification(id, targetV, targetQ); + modifications.add(new VscConverterStationModification(id, targetV, targetQ)); } } From 45f790dd634aea64410425fb7857a7eeb37b7106 Mon Sep 17 00:00:00 2001 From: parvy Date: Fri, 12 Jan 2024 17:54:05 +0100 Subject: [PATCH 02/28] refactor. Signed-off-by: parvy --- .../parameters/output/AbstractNoThrowOutput.java | 12 +++++++----- .../parameters/output/network/VscNetworkOutput.java | 2 -- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/AbstractNoThrowOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/AbstractNoThrowOutput.java index 6a6dd931..61f0d599 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/AbstractNoThrowOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/AbstractNoThrowOutput.java @@ -31,6 +31,10 @@ public boolean isErrorState() { return errorState; } + protected void triggerErrorState() { + errorState = true; + } + @Override public String getFileName() { return OpenReacModel.OUTPUT_FILE_PREFIX + "_" + getElement() + "." + OpenReacModel.OUTPUT_FILE_FORMAT.getFileExtension(); @@ -41,6 +45,9 @@ public String getFileName() { */ public abstract String getElement(); + /** + * @return the number of columns expected in the output file. + */ public abstract int getExpectedColumns(); @Override @@ -64,9 +71,4 @@ public void read(BufferedReader reader, StringToIntMapper stringToIn protected double readDouble(String d) { return Float.parseFloat(d) != AmplConstants.INVALID_FLOAT_VALUE ? Double.parseDouble(d) : Double.NaN; } - - protected void triggerErrorState() { - errorState = true; - } - } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/VscNetworkOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/VscNetworkOutput.java index c67543dc..19387860 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/VscNetworkOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/VscNetworkOutput.java @@ -21,11 +21,9 @@ public class VscNetworkOutput extends AbstractNetworkOutput Date: Fri, 12 Jan 2024 17:59:29 +0100 Subject: [PATCH 03/28] refactor. Signed-off-by: parvy --- .../openreac/parameters/output/ReactiveSlackOutput.java | 4 ++-- .../parameters/output/ReactiveSlackOutputTest.java | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutput.java index 818151a7..d431db82 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutput.java @@ -75,10 +75,10 @@ public boolean throwOnMissingFile() { protected void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { // slack capacitor is a generation of reactive power. // slack self is a reactive load. - double slackCapacitor = -readDouble(tokens[REACTIVE_SLACK_GENERATION_COLUMN_INDEX]); - double slackSelf = readDouble(tokens[REACTIVE_SLACK_LOAD_COLUMN_INDEX]); String id = AmplIOUtils.removeQuotes(tokens[BUS_ID_COLUMN_INDEX]); String voltageLevelId = AmplIOUtils.removeQuotes(tokens[VOLTAGE_LEVEL_ID_COLUMN_INDEX]); + double slackCapacitor = -readDouble(tokens[REACTIVE_SLACK_GENERATION_COLUMN_INDEX]); + double slackSelf = readDouble(tokens[REACTIVE_SLACK_LOAD_COLUMN_INDEX]); double slack = slackCapacitor + slackSelf; slacks.add(new ReactiveSlack(id, voltageLevelId, slack)); } diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutputTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutputTest.java index 9ddf7b22..b0134b30 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutputTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutputTest.java @@ -22,6 +22,14 @@ */ class ReactiveSlackOutputTest { + @Test + void testReactiveSlack() { + ReactiveSlackOutput.ReactiveSlack reactiveSlack = new ReactiveSlackOutput.ReactiveSlack("busId", "vlId", 10); + assertEquals("busId", reactiveSlack.getBusId()); + assertEquals("vlId", reactiveSlack.getVoltageLevelId()); + assertEquals(10, reactiveSlack.getSlack()); + } + @Test void readTest() throws IOException { ReactiveSlackOutput output = new ReactiveSlackOutput(); From bdf9067ea58eca02109f49b98a1dbc47083cb781 Mon Sep 17 00:00:00 2001 From: parvy Date: Fri, 12 Jan 2024 18:21:45 +0100 Subject: [PATCH 04/28] Add TU for wrong number of columns. Signed-off-by: parvy --- .../output/OpenReacNetworkOutputTest.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 open-reac/src/test/java/com/powsybl/openreac/parameters/output/OpenReacNetworkOutputTest.java diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/output/OpenReacNetworkOutputTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/OpenReacNetworkOutputTest.java new file mode 100644 index 00000000..1f974996 --- /dev/null +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/OpenReacNetworkOutputTest.java @@ -0,0 +1,27 @@ +package com.powsybl.openreac.parameters.output; + +import com.powsybl.openreac.exceptions.IncompatibleModelException; +import com.powsybl.openreac.parameters.output.network.GeneratorNetworkOutput; +import org.junit.jupiter.api.Test; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class OpenReacNetworkOutputTest { + @Test + void wrongNumberOfColumnsTest() throws IOException { + GeneratorNetworkOutput output = new GeneratorNetworkOutput(null); + try (InputStream input = getClass().getResourceAsStream("/mock_outputs/reactiveopf_results_shunts.csv"); + InputStreamReader in = new InputStreamReader(input); + BufferedReader reader = new BufferedReader(in)) { + IncompatibleModelException e = assertThrows(IncompatibleModelException.class, () -> output.read(reader, null)); + assertEquals("Error of compatibility between the ampl model and the interface, this is a OpenReac issue.\n" + + "Error reading reactiveopf_results_generators.csv, wrong number of columns. Expected: 9, found:6", e.getMessage()); + } + } +} From e494e7b734e5d4ecdf79293d7df6f05e496d4e22 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 17 Jan 2024 16:11:19 +0100 Subject: [PATCH 05/28] Small renaming. Signed-off-by: Anne Tilloy --- .../openreac/parameters/output/AbstractNoThrowOutput.java | 4 ++-- .../openreac/parameters/output/ReactiveSlackOutput.java | 3 +-- .../parameters/output/network/GeneratorNetworkOutput.java | 2 +- .../output/network/ShuntCompensatorNetworkOutput.java | 2 +- .../openreac/parameters/output/network/SvcNetworkOutput.java | 2 +- .../parameters/output/network/TapPositionNetworkOutput.java | 2 +- .../openreac/parameters/output/network/VscNetworkOutput.java | 2 +- 7 files changed, 8 insertions(+), 9 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/AbstractNoThrowOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/AbstractNoThrowOutput.java index 61f0d599..01b2b5dc 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/AbstractNoThrowOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/AbstractNoThrowOutput.java @@ -61,12 +61,12 @@ public void read(BufferedReader reader, StringToIntMapper stringToIn reader.lines().forEach(line -> { if (!COMMENTED_LINE_TEST.test(line)) { String[] tokens = line.split(OpenReacModel.OUTPUT_FILE_FORMAT.getTokenSeparator()); - doReadLine(tokens, stringToIntMapper); + readLine(tokens, stringToIntMapper); } }); } - protected abstract void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper); + protected abstract void readLine(String[] tokens, StringToIntMapper stringToIntMapper); protected double readDouble(String d) { return Float.parseFloat(d) != AmplConstants.INVALID_FLOAT_VALUE ? Double.parseDouble(d) : Double.NaN; diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutput.java index d431db82..ed85767a 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutput.java @@ -72,7 +72,7 @@ public boolean throwOnMissingFile() { return false; } - protected void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { + protected void readLine(String[] tokens, StringToIntMapper stringToIntMapper) { // slack capacitor is a generation of reactive power. // slack self is a reactive load. String id = AmplIOUtils.removeQuotes(tokens[BUS_ID_COLUMN_INDEX]); @@ -82,5 +82,4 @@ protected void doReadLine(String[] tokens, StringToIntMapper stringT double slack = slackCapacitor + slackSelf; slacks.add(new ReactiveSlack(id, voltageLevelId, slack)); } - } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/GeneratorNetworkOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/GeneratorNetworkOutput.java index 28c620f0..4e28d996 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/GeneratorNetworkOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/GeneratorNetworkOutput.java @@ -36,7 +36,7 @@ public int getExpectedColumns() { } @Override - protected void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { + protected void readLine(String[] tokens, StringToIntMapper stringToIntMapper) { String id = stringToIntMapper.getId(AmplSubset.GENERATOR, Integer.parseInt(tokens[ID_COLUMN_INDEX])); double targetV = readDouble(tokens[TARGET_V_COLUMN_INDEX]) * network.getGenerator(id).getRegulatingTerminal().getVoltageLevel().getNominalV(); double targetQ = readDouble(tokens[TARGET_Q_COLUMN_INDEX]); diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/ShuntCompensatorNetworkOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/ShuntCompensatorNetworkOutput.java index 4f795913..c3d81891 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/ShuntCompensatorNetworkOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/ShuntCompensatorNetworkOutput.java @@ -37,7 +37,7 @@ public int getExpectedColumns() { } @Override - protected void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { + protected void readLine(String[] tokens, StringToIntMapper stringToIntMapper) { String id = stringToIntMapper.getId(AmplSubset.SHUNT, Integer.parseInt(tokens[ID_COLUMN_INDEX])); double b = readDouble(tokens[B_COLUMN_INDEX]); String busId = stringToIntMapper.getId(AmplSubset.BUS, Integer.parseInt(tokens[BUS_COLUMN_INDEX])); diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/SvcNetworkOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/SvcNetworkOutput.java index 3dbd1203..51690886 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/SvcNetworkOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/SvcNetworkOutput.java @@ -37,7 +37,7 @@ public int getExpectedColumns() { } @Override - protected void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { + protected void readLine(String[] tokens, StringToIntMapper stringToIntMapper) { String id = stringToIntMapper.getId(AmplSubset.STATIC_VAR_COMPENSATOR, Integer.parseInt(tokens[ID_COLUMN_INDEX])); StaticVarCompensator staticVarCompensator = network.getStaticVarCompensator(id); diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/TapPositionNetworkOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/TapPositionNetworkOutput.java index 1fc1151e..58724147 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/TapPositionNetworkOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/TapPositionNetworkOutput.java @@ -37,7 +37,7 @@ public int getExpectedColumns() { } @Override - protected void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { + protected void readLine(String[] tokens, StringToIntMapper stringToIntMapper) { String transfoId = stringToIntMapper.getId(AmplSubset.BRANCH, Integer.parseInt(tokens[TRANSFO_ID_COLUMN_INDEX])); TwoWindingsTransformer twt = network.getTwoWindingsTransformer(transfoId); if (twt == null || !twt.hasRatioTapChanger()) { diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/VscNetworkOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/VscNetworkOutput.java index 19387860..d4f4358e 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/VscNetworkOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/network/VscNetworkOutput.java @@ -37,7 +37,7 @@ public int getExpectedColumns() { } @Override - protected void doReadLine(String[] tokens, StringToIntMapper stringToIntMapper) { + protected void readLine(String[] tokens, StringToIntMapper stringToIntMapper) { String id = stringToIntMapper.getId(AmplSubset.VSC_CONVERTER_STATION, Integer.parseInt(tokens[ID_COLUMN_INDEX])); VscConverterStation vscConverterStation = network.getVscConverterStation(id); Double targetV = readDouble(tokens[SET_POINT_V_COLUMN_INDEX]) * vscConverterStation From 9ba7d6a95738e290165b935f4571993de844c40b Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 10 Jan 2024 10:52:10 +0100 Subject: [PATCH 06/28] Add export of voltage plan. Signed-off-by: parvy --- .../parameters/OpenReacAmplIOFiles.java | 10 +- .../parameters/output/OpenReacResult.java | 32 +++++- .../parameters/output/VoltagePlanOutput.java | 97 +++++++++++++++++++ .../resources/openreac/reactiveopfoutput.run | 18 ++++ 4 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/OpenReacAmplIOFiles.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/OpenReacAmplIOFiles.java index ee3aace5..2697d5a2 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/OpenReacAmplIOFiles.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/OpenReacAmplIOFiles.java @@ -14,6 +14,7 @@ import com.powsybl.openreac.parameters.input.algo.AlgorithmInput; import com.powsybl.openreac.parameters.output.OpenReacResult; import com.powsybl.openreac.parameters.output.ReactiveSlackOutput; +import com.powsybl.openreac.parameters.output.VoltagePlanOutput; import com.powsybl.openreac.parameters.output.network.NetworkModifications; import java.util.ArrayList; @@ -40,6 +41,7 @@ public class OpenReacAmplIOFiles implements AmplParameters { private final VoltageLevelLimitsOverrideInput voltageLimitsOverride; private final ConfiguredBusesWithReactiveSlack configuredReactiveSlackBuses; private final NetworkModifications networkModifications; + private final VoltagePlanOutput voltagePlanOutput; private final boolean debug; public OpenReacAmplIOFiles(OpenReacParameters params, Network network, boolean debug) { @@ -54,6 +56,7 @@ public OpenReacAmplIOFiles(OpenReacParameters params, Network network, boolean d //outputs this.reactiveSlackOutput = new ReactiveSlackOutput(); this.networkModifications = new NetworkModifications(network); + this.voltagePlanOutput = new VoltagePlanOutput(); this.debug = debug; } @@ -66,6 +69,10 @@ public NetworkModifications getNetworkModifications() { return networkModifications; } + public VoltagePlanOutput getVoltagePlanOutput() { + return voltagePlanOutput; + } + @Override public Collection getInputParameters() { return List.of(constantQGenerators, variableShuntCompensators, variableTwoWindingsTransformers, @@ -76,9 +83,10 @@ public Collection getInputParameters() { public Collection getOutputParameters(boolean isConvergenceOk) { if (isConvergenceOk) { List networkModificationsOutputFiles = networkModifications.getOutputFiles(); - List list = new ArrayList<>(networkModificationsOutputFiles.size() + 1); + List list = new ArrayList<>(networkModificationsOutputFiles.size() + 2); list.addAll(networkModificationsOutputFiles); list.add(reactiveSlackOutput); + list.add(voltagePlanOutput); return list; } return List.of(); diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index a7ea265a..09234147 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -8,9 +8,10 @@ import com.powsybl.iidm.modification.*; import com.powsybl.iidm.modification.tapchanger.RatioTapPositionModification; -import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.*; import com.powsybl.openreac.parameters.OpenReacAmplIOFiles; import com.powsybl.openreac.parameters.output.ReactiveSlackOutput.ReactiveSlack; +import com.powsybl.openreac.parameters.output.VoltagePlanOutput.BusResult; import java.util.ArrayList; import java.util.List; @@ -32,6 +33,7 @@ public class OpenReacResult { private final List vscModifications; private final List svcModifications; private final List tapPositionModifications; + private final List voltagePlan; /** * @param status the final status of the OpenReac run. @@ -48,6 +50,7 @@ public OpenReacResult(OpenReacStatus status, OpenReacAmplIOFiles amplIOFiles, Ma this.vscModifications = List.copyOf(amplIOFiles.getNetworkModifications().getVscModifications()); this.svcModifications = List.copyOf(amplIOFiles.getNetworkModifications().getSvcModifications()); this.tapPositionModifications = List.copyOf(amplIOFiles.getNetworkModifications().getTapPositionModifications()); + this.voltagePlan = List.copyOf(amplIOFiles.getVoltagePlanOutput().getVoltagePlan()); } public OpenReacStatus getStatus() { @@ -82,7 +85,11 @@ public List getVscModifications() { return vscModifications; } - public List getAllModifs() { + public List getVoltagePlan() { + return voltagePlan; + } + + public List getAllNetworkModifications() { List modifs = new ArrayList<>(getGeneratorModifications().size() + getShuntsModifications().size() + getSvcModifications().size() + @@ -97,8 +104,27 @@ public List getAllModifs() { } public void applyAllModifications(Network network) { - for (NetworkModification modif : getAllModifs()) { + for (NetworkModification modif : getAllNetworkModifications()) { modif.apply(network); } + + for (BusResult busResult : getVoltagePlan()) { + Bus b = network.getBusView().getBus(busResult.getBusId()); + + // TODO : update voltage values of b ? + + // Update target of ratio tap changers regulating voltage + network.getTwoWindingsTransformerStream() + .map(RatioTapChangerHolder::getRatioTapChanger) + .filter(TapChanger::isRegulating) + .filter(ratioTapChanger -> ratioTapChanger.getRegulationTerminal().getBusView().getBus() == b) + .forEach(ratioTapChanger -> ratioTapChanger.setTargetV(busResult.getV())); + + // Update target of shunts regulating voltage + network.getShuntCompensatorStream() + .filter(ShuntCompensator::isVoltageRegulatorOn) + .filter(shuntCompensator -> shuntCompensator.getRegulatingTerminal().getBusView().getBus() == b) + .forEach(shuntCompensator -> shuntCompensator.setTargetV(busResult.getV())); + } } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java new file mode 100644 index 00000000..b2253603 --- /dev/null +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java @@ -0,0 +1,97 @@ +/** + * 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/. + */ +package com.powsybl.openreac.parameters.output; + +import com.powsybl.ampl.converter.AmplConstants; +import com.powsybl.ampl.converter.AmplSubset; +import com.powsybl.commons.util.StringToIntMapper; +import com.powsybl.openreac.exceptions.IncompatibleModelException; +import com.powsybl.openreac.parameters.AmplIOUtils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * @author Pierre Arvy + */ +public class VoltagePlanOutput extends AbstractNoThrowOutput { + + public static final int EXPECTED_COLS = 4; + private static final String SEP = ";"; + + public static class BusResult { + private final String busId; + private final double v; + private final double angle; + + public BusResult(String busId, double v, double angle) { + this.busId = Objects.requireNonNull(busId); + this.v = v; + this.angle = angle; + } + + public String getBusId() { + return busId; + } + + public double getV() { + return v; + } + + public double getAngle() { + return angle; + } + } + + private final List voltagePlan = new ArrayList<>(); + + public List getVoltagePlan() { + return voltagePlan; + } + + @Override + public String getFileName() { + return "reactiveopf_results_voltages.csv"; + } + + @Override + public void read(BufferedReader reader, StringToIntMapper stringToIntMapper) throws IOException { + String headers = reader.readLine(); + int readCols = headers.split(SEP).length; + if (readCols != EXPECTED_COLS) { + triggerErrorState(); + throw new IncompatibleModelException("Error reading " + getFileName() + ", wrong number of columns. Expected: " + EXPECTED_COLS + ", found:" + readCols); + } else { + String line = reader.readLine(); + while (line != null) { + readLine(line.split(SEP)); + line = reader.readLine(); + } + } + } + + @Override + public boolean throwOnMissingFile() { + triggerErrorState(); + return false; + } + + private void readLine(String[] tokens) { + double v = readDouble(tokens[2]); + double angle = readDouble(tokens[3]); + String id = AmplIOUtils.removeQuotes(tokens[4]); + voltagePlan.add(new BusResult(id, v, angle)); + } + + private double readDouble(String d) { + return Float.parseFloat(d) != AmplConstants.INVALID_FLOAT_VALUE ? Double.parseDouble(d) : Double.NaN; + } + +} diff --git a/open-reac/src/main/resources/openreac/reactiveopfoutput.run b/open-reac/src/main/resources/openreac/reactiveopfoutput.run index cd87a102..57e3269d 100644 --- a/open-reac/src/main/resources/openreac/reactiveopfoutput.run +++ b/open-reac/src/main/resources/openreac/reactiveopfoutput.run @@ -190,6 +190,24 @@ close (fileOut); +############################################################################### +# +# Writing results for buses states +# +############################################################################### +if final_status == "OK" then { + + let fileOut := "reactiveopf_results_voltages.csv"; + printf "#variant;bus;V;theta;id;\n" > (fileOut); + printf {n in BUSCC} "%i;%i;%.3f;%.3f;%s;\n", + 1, n, V[n], teta[n], '"' & bus_id[1,n] & '"' + > (fileOut); + close (fileOut); + +} + + + ############################################################################### # # Writing results for LCC converters From b289f5ad30e2bba74fc86a377eecdc42f08a707c Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 10 Jan 2024 11:00:26 +0100 Subject: [PATCH 07/28] remove useless id. Signed-off-by: parvy --- .../openreac/parameters/output/VoltagePlanOutput.java | 7 +++---- .../src/main/resources/openreac/reactiveopfoutput.run | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java index b2253603..ef20d822 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java @@ -10,7 +10,6 @@ import com.powsybl.ampl.converter.AmplSubset; import com.powsybl.commons.util.StringToIntMapper; import com.powsybl.openreac.exceptions.IncompatibleModelException; -import com.powsybl.openreac.parameters.AmplIOUtils; import java.io.BufferedReader; import java.io.IOException; @@ -71,7 +70,7 @@ public void read(BufferedReader reader, StringToIntMapper stringToIn } else { String line = reader.readLine(); while (line != null) { - readLine(line.split(SEP)); + readLine(line.split(SEP), stringToIntMapper); line = reader.readLine(); } } @@ -83,10 +82,10 @@ public boolean throwOnMissingFile() { return false; } - private void readLine(String[] tokens) { + private void readLine(String[] tokens, StringToIntMapper stringToIntMapper) { + String id = stringToIntMapper.getId(AmplSubset.BUS, Integer.parseInt(tokens[1])); double v = readDouble(tokens[2]); double angle = readDouble(tokens[3]); - String id = AmplIOUtils.removeQuotes(tokens[4]); voltagePlan.add(new BusResult(id, v, angle)); } diff --git a/open-reac/src/main/resources/openreac/reactiveopfoutput.run b/open-reac/src/main/resources/openreac/reactiveopfoutput.run index 57e3269d..9d5d563a 100644 --- a/open-reac/src/main/resources/openreac/reactiveopfoutput.run +++ b/open-reac/src/main/resources/openreac/reactiveopfoutput.run @@ -198,9 +198,9 @@ close (fileOut); if final_status == "OK" then { let fileOut := "reactiveopf_results_voltages.csv"; - printf "#variant;bus;V;theta;id;\n" > (fileOut); + printf "#variant;bus;V;theta;\n" > (fileOut); printf {n in BUSCC} "%i;%i;%.3f;%.3f;%s;\n", - 1, n, V[n], teta[n], '"' & bus_id[1,n] & '"' + 1, n, V[n], teta[n] > (fileOut); close (fileOut); From 6b1210515d63d4f1cebac27d46b50fe110ffbe3b Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 10 Jan 2024 11:51:51 +0100 Subject: [PATCH 08/28] Add TU for VoltagePlanOutput. Signed-off-by: parvy --- .../parameters/output/VoltagePlanOutput.java | 16 ++++--- .../resources/openreac/reactiveopfoutput.run | 4 +- .../output/VoltagePlanOutputTest.java | 48 +++++++++++++++++++ .../reactiveopf_results_voltages.csv | 4 ++ 4 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java create mode 100644 open-reac/src/test/resources/mock_outputs/reactiveopf_results_voltages.csv diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java index ef20d822..4a6e1667 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java @@ -10,6 +10,7 @@ import com.powsybl.ampl.converter.AmplSubset; import com.powsybl.commons.util.StringToIntMapper; import com.powsybl.openreac.exceptions.IncompatibleModelException; +import com.powsybl.openreac.parameters.AmplIOUtils; import java.io.BufferedReader; import java.io.IOException; @@ -22,7 +23,10 @@ */ public class VoltagePlanOutput extends AbstractNoThrowOutput { - public static final int EXPECTED_COLS = 4; + public static final int EXPECTED_COLS = 5; + private static final int ID_COLUMN_INDEX = 4; + private static final int V_COLUMN_INDEX = 2; + private static final int ANGLE_COLUMN_INDEX = 3; private static final String SEP = ";"; public static class BusResult { @@ -70,7 +74,7 @@ public void read(BufferedReader reader, StringToIntMapper stringToIn } else { String line = reader.readLine(); while (line != null) { - readLine(line.split(SEP), stringToIntMapper); + readLine(line.split(SEP)); line = reader.readLine(); } } @@ -82,10 +86,10 @@ public boolean throwOnMissingFile() { return false; } - private void readLine(String[] tokens, StringToIntMapper stringToIntMapper) { - String id = stringToIntMapper.getId(AmplSubset.BUS, Integer.parseInt(tokens[1])); - double v = readDouble(tokens[2]); - double angle = readDouble(tokens[3]); + private void readLine(String[] tokens) { + double v = readDouble(tokens[V_COLUMN_INDEX]); + double angle = readDouble(tokens[ANGLE_COLUMN_INDEX]); + String id = AmplIOUtils.removeQuotes(tokens[ID_COLUMN_INDEX]); voltagePlan.add(new BusResult(id, v, angle)); } diff --git a/open-reac/src/main/resources/openreac/reactiveopfoutput.run b/open-reac/src/main/resources/openreac/reactiveopfoutput.run index 9d5d563a..ead2ff57 100644 --- a/open-reac/src/main/resources/openreac/reactiveopfoutput.run +++ b/open-reac/src/main/resources/openreac/reactiveopfoutput.run @@ -198,9 +198,9 @@ close (fileOut); if final_status == "OK" then { let fileOut := "reactiveopf_results_voltages.csv"; - printf "#variant;bus;V;theta;\n" > (fileOut); + printf "#variant;bus;V;theta;%s;\n" > (fileOut); printf {n in BUSCC} "%i;%i;%.3f;%.3f;%s;\n", - 1, n, V[n], teta[n] + 1, n, V[n], teta[n], '"' & bus_id[1,n] & '"' > (fileOut); close (fileOut); diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java new file mode 100644 index 00000000..e89bf854 --- /dev/null +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java @@ -0,0 +1,48 @@ +package com.powsybl.openreac.parameters.output; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class VoltagePlanOutputTest { + + @Test + void busResultTest() { + VoltagePlanOutput.BusResult busResult = new VoltagePlanOutput.BusResult("id", 0.98, 0.23); + assertEquals("id", busResult.getBusId()); + assertEquals(0.98, busResult.getV()); + assertEquals(0.23, busResult.getAngle()); + } + + @Test + void readTest() throws IOException { + VoltagePlanOutput output = new VoltagePlanOutput(); + try (InputStream input = getClass().getResourceAsStream("/mock_outputs/reactiveopf_results_voltages.csv"); + InputStreamReader in = new InputStreamReader(input); + BufferedReader reader = new BufferedReader(in)) { + + output.read(reader, null); + assertEquals(3, output.getVoltagePlan().size()); + VoltagePlanOutput.BusResult busResult1 = output.getVoltagePlan().get(0); + VoltagePlanOutput.BusResult busResult2 = output.getVoltagePlan().get(1); + VoltagePlanOutput.BusResult busResult3 = output.getVoltagePlan().get(2); + Assertions.assertAll( + () -> assertEquals("bus1", busResult1.getBusId()), + () -> assertEquals(0.8, busResult1.getV()), + () -> assertEquals(1.1, busResult1.getAngle()), + () -> assertEquals("bus2", busResult2.getBusId()), + () -> assertEquals(1.2, busResult2.getV()), + () -> assertEquals(Double.NaN, busResult2.getAngle()), + () -> assertEquals("bus3", busResult3.getBusId()), + () -> assertEquals(Double.NaN, busResult3.getV()), + () -> assertEquals(0.11, busResult3.getAngle()) + ); + } + } +} diff --git a/open-reac/src/test/resources/mock_outputs/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/mock_outputs/reactiveopf_results_voltages.csv new file mode 100644 index 00000000..ee561a0f --- /dev/null +++ b/open-reac/src/test/resources/mock_outputs/reactiveopf_results_voltages.csv @@ -0,0 +1,4 @@ +col1;col2;col3;col4;col5; +1;1;0.8;1.1;'bus1'; +1;2;1.2;-99999;'bus2'; +1;1;-99999;0.11;'bus3'; \ No newline at end of file From 5115f1b1be764e48a3b56bad70c79925e657069c Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 10 Jan 2024 15:46:18 +0100 Subject: [PATCH 09/28] update/add TU. Signed-off-by: parvy --- .../parameters/output/OpenReacResult.java | 10 ++-- .../parameters/output/VoltagePlanOutput.java | 2 +- .../resources/openreac/reactiveopfoutput.run | 2 +- .../powsybl/openreac/OpenReacRunnerTest.java | 30 +++++++--- .../reactiveopf_results_voltages.csv | 4 +- .../reactiveopf_results_indic.txt | 8 +-- .../reactiveopf_results_voltages.csv | 15 +++++ .../reactiveopf_results_indic.txt | 6 +- .../reactiveopf_results_voltages.csv | 58 +++++++++++++++++++ .../reactiveopf_results_indic.txt | 8 +-- .../reactiveopf_results_voltages.csv | 4 ++ .../reactiveopf_results_indic.txt | 6 +- .../reactiveopf_results_voltages.csv | 3 + .../reactiveopf_results_indic.txt | 6 +- .../reactiveopf_results_voltages.csv | 4 ++ .../reactiveopf_results_indic.txt | 4 +- .../reactiveopf_results_voltages.csv | 7 +++ 17 files changed, 143 insertions(+), 34 deletions(-) create mode 100644 open-reac/src/test/resources/openreac-output-ieee14/reactiveopf_results_voltages.csv create mode 100644 open-reac/src/test/resources/openreac-output-real-network/reactiveopf_results_voltages.csv create mode 100644 open-reac/src/test/resources/openreac-output-shunt/reactiveopf_results_voltages.csv create mode 100644 open-reac/src/test/resources/openreac-output-svc/reactiveopf_results_voltages.csv create mode 100644 open-reac/src/test/resources/openreac-output-transfo/reactiveopf_results_voltages.csv create mode 100644 open-reac/src/test/resources/openreac-output-vsc/reactiveopf_results_voltages.csv diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index 09234147..1d8535a3 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -110,21 +110,23 @@ public void applyAllModifications(Network network) { for (BusResult busResult : getVoltagePlan()) { Bus b = network.getBusView().getBus(busResult.getBusId()); + double nomV = b.getVoltageLevel().getNominalV(); // TODO : update voltage values of b ? // Update target of ratio tap changers regulating voltage network.getTwoWindingsTransformerStream() + .filter(RatioTapChangerHolder::hasRatioTapChanger) .map(RatioTapChangerHolder::getRatioTapChanger) .filter(TapChanger::isRegulating) - .filter(ratioTapChanger -> ratioTapChanger.getRegulationTerminal().getBusView().getBus() == b) - .forEach(ratioTapChanger -> ratioTapChanger.setTargetV(busResult.getV())); + .filter(ratioTapChanger -> ratioTapChanger.getRegulationTerminal().getBusView().getBus().equals(b)) + .forEach(ratioTapChanger -> ratioTapChanger.setTargetV(busResult.getV() * nomV)); // Update target of shunts regulating voltage network.getShuntCompensatorStream() .filter(ShuntCompensator::isVoltageRegulatorOn) - .filter(shuntCompensator -> shuntCompensator.getRegulatingTerminal().getBusView().getBus() == b) - .forEach(shuntCompensator -> shuntCompensator.setTargetV(busResult.getV())); + .filter(shuntCompensator -> shuntCompensator.getRegulatingTerminal().getBusView().getBus().equals(b)) + .forEach(shuntCompensator -> shuntCompensator.setTargetV(busResult.getV() * nomV)); } } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java index 4a6e1667..3562e6c4 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java @@ -87,9 +87,9 @@ public boolean throwOnMissingFile() { } private void readLine(String[] tokens) { + String id = AmplIOUtils.removeQuotes(tokens[ID_COLUMN_INDEX]); double v = readDouble(tokens[V_COLUMN_INDEX]); double angle = readDouble(tokens[ANGLE_COLUMN_INDEX]); - String id = AmplIOUtils.removeQuotes(tokens[ID_COLUMN_INDEX]); voltagePlan.add(new BusResult(id, v, angle)); } diff --git a/open-reac/src/main/resources/openreac/reactiveopfoutput.run b/open-reac/src/main/resources/openreac/reactiveopfoutput.run index ead2ff57..184edefb 100644 --- a/open-reac/src/main/resources/openreac/reactiveopfoutput.run +++ b/open-reac/src/main/resources/openreac/reactiveopfoutput.run @@ -198,7 +198,7 @@ close (fileOut); if final_status == "OK" then { let fileOut := "reactiveopf_results_voltages.csv"; - printf "#variant;bus;V;theta;%s;\n" > (fileOut); + printf "#variant;bus;V(pu);theta(rad);id;\n" > (fileOut); printf {n in BUSCC} "%i;%i;%.3f;%.3f;%s;\n", 1, n, V[n], teta[n], '"' & bus_id[1,n] & '"' > (fileOut); diff --git a/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java b/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java index cc081d71..953c75fc 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java @@ -41,8 +41,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; /** * @author Geoffroy Jamgotchian @@ -200,7 +199,8 @@ public void testOutputFileParsing() throws IOException { "mock_outputs/reactiveopf_results_rtc.csv", "mock_outputs/reactiveopf_results_shunts.csv", "mock_outputs/reactiveopf_results_static_var_compensators.csv", - "mock_outputs/reactiveopf_results_vsc_converter_stations.csv")); + "mock_outputs/reactiveopf_results_vsc_converter_stations.csv", + "mock_outputs/reactiveopf_results_voltages.csv")); try (ComputationManager computationManager = new LocalComputationManager(new LocalComputationConfig(tmpDir), localCommandExecutor, ForkJoinPool.commonPool())) { OpenReacResult openReacResult = OpenReacRunner.run(network, @@ -213,6 +213,7 @@ public void testOutputFileParsing() throws IOException { assertEquals(1, openReacResult.getSvcModifications().size()); assertEquals(1, openReacResult.getVscModifications().size()); assertEquals(7, openReacResult.getGeneratorModifications().size()); + assertEquals(3, openReacResult.getVoltagePlan().size()); assertEquals(82, openReacResult.getIndicators().size()); assertTrue(openReacResult.getReactiveSlacks().isEmpty()); } @@ -250,7 +251,8 @@ private void testAllModifAndLoadFlow(Network network, String subFolder, OpenReac subFolder + "/reactiveopf_results_rtc.csv", subFolder + "/reactiveopf_results_shunts.csv", subFolder + "/reactiveopf_results_static_var_compensators.csv", - subFolder + "/reactiveopf_results_vsc_converter_stations.csv")); + subFolder + "/reactiveopf_results_vsc_converter_stations.csv", + subFolder + "/reactiveopf_results_voltages.csv")); // To really run open reac, use the commentede line below. Be sure that open-reac/src/test/resources/com/powsybl/config/test/config.yml contains your ampl path // try (ComputationManager computationManager = new LocalComputationManager()) { try (ComputationManager computationManager = new LocalComputationManager(new LocalComputationConfig(tmpDir), @@ -295,23 +297,37 @@ public void testSvc() throws IOException { } @Test - public void testShuntReconnection() throws IOException { + public void testShuntModification() throws IOException { Network network = create(); setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network + ShuntCompensator shunt = network.getShuntCompensator("SHUNT"); + assertFalse(shunt.getTerminal().isConnected()); + assertEquals(393, shunt.getTargetV()); + OpenReacParameters parameters = new OpenReacParameters(); - parameters.addVariableShuntCompensators(List.of("SHUNT")); + parameters.addVariableShuntCompensators(List.of(shunt.getId())); testAllModifAndLoadFlow(network, "openreac-output-shunt", parameters); + assertTrue(shunt.getTerminal().isConnected()); // shunt has been reconnected + assertEquals(420.8, shunt.getTargetV()); // targetV has been updated } @Test public void testTransformer() throws IOException { Network network = VoltageControlNetworkFactory.createNetworkWithT2wt(); setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network - network.getTwoWindingsTransformer("T2wT").getRatioTapChanger().setTapPosition(2); + RatioTapChanger rtc = network.getTwoWindingsTransformer("T2wT").getRatioTapChanger() + .setTapPosition(2) + .setTargetDeadband(0) + .setRegulating(true); + assertEquals(2, rtc.getTapPosition()); + assertEquals(33.0, rtc.getTargetV()); + OpenReacParameters parameters = new OpenReacParameters(); parameters.addConstantQGenerators(List.of("GEN_1")); parameters.addVariableTwoWindingsTransformers(List.of("T2wT")); testAllModifAndLoadFlow(network, "openreac-output-transfo", parameters); + assertEquals(0, rtc.getTapPosition()); + assertEquals(22.935, rtc.getTargetV()); // TODO : verify the value } @Test diff --git a/open-reac/src/test/resources/mock_outputs/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/mock_outputs/reactiveopf_results_voltages.csv index ee561a0f..0ab28a0e 100644 --- a/open-reac/src/test/resources/mock_outputs/reactiveopf_results_voltages.csv +++ b/open-reac/src/test/resources/mock_outputs/reactiveopf_results_voltages.csv @@ -1,4 +1,4 @@ -col1;col2;col3;col4;col5; +#variant;bus;V;angle;id; 1;1;0.8;1.1;'bus1'; 1;2;1.2;-99999;'bus2'; -1;1;-99999;0.11;'bus3'; \ No newline at end of file +1;1;-99999;0.11;'bus3'; diff --git a/open-reac/src/test/resources/openreac-output-ieee14/reactiveopf_results_indic.txt b/open-reac/src/test/resources/openreac-output-ieee14/reactiveopf_results_indic.txt index 46d921f9..cfcba5f7 100644 --- a/open-reac/src/test/resources/openreac-output-ieee14/reactiveopf_results_indic.txt +++ b/open-reac/src/test/resources/openreac-output-ieee14/reactiveopf_results_indic.txt @@ -1,18 +1,18 @@ final_status OK dcopf_status OK -ctime_start 'Fri Nov 24 11:59:34 2023' +ctime_start 'Wed Jan 10 14:48:12 2024' last_solve_result_num 0 nb_iter_last 6 nb_iter_total 6 -_ampl_elapsed_time 0.125000 -_total_solve_time 0.031250 +_ampl_elapsed_time 0.047000 +_total_solve_time 0.046875 total_time 0 operatingSystem windows OS 'Windows_NT' COMPUTERNAME 'ARTELYS-PC253' -directory 'C:\Users\parvy\AppData\Local\Temp\ampl_12583331805904096086' +directory 'C:\Users\parvy\AppData\Local\Temp\ampl_18317757654451996032' log_level_ampl INFO log_level_knitro 2 diff --git a/open-reac/src/test/resources/openreac-output-ieee14/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/openreac-output-ieee14/reactiveopf_results_voltages.csv new file mode 100644 index 00000000..b4453c67 --- /dev/null +++ b/open-reac/src/test/resources/openreac-output-ieee14/reactiveopf_results_voltages.csv @@ -0,0 +1,15 @@ +#variant;bus;V;theta;id; +1;1;1.083;0.168;"VL1_0"; +1;2;1.045;0.089;"VL2_0"; +1;3;0.971;-0.042;"VL3_0"; +1;4;0.991;0.000;"VL4_0"; +1;5;0.995;0.027;"VL5_0"; +1;6;0.973;-0.084;"VL6_0"; +1;7;1.050;-0.057;"VL7_0"; +1;8;1.500;-0.057;"VL8_0"; +1;9;0.918;-0.085;"VL9_0"; +1;10;0.919;-0.091;"VL10_0"; +1;11;0.942;-0.090;"VL11_0"; +1;12;0.954;-0.102;"VL12_0"; +1;13;0.945;-0.102;"VL13_0"; +1;14;0.909;-0.115;"VL14_0"; diff --git a/open-reac/src/test/resources/openreac-output-real-network/reactiveopf_results_indic.txt b/open-reac/src/test/resources/openreac-output-real-network/reactiveopf_results_indic.txt index 420331e6..b617eff6 100644 --- a/open-reac/src/test/resources/openreac-output-real-network/reactiveopf_results_indic.txt +++ b/open-reac/src/test/resources/openreac-output-real-network/reactiveopf_results_indic.txt @@ -1,18 +1,18 @@ final_status OK dcopf_status OK -ctime_start 'Fri Nov 24 12:03:02 2023' +ctime_start 'Wed Jan 10 14:49:19 2024' last_solve_result_num 0 nb_iter_last 7 nb_iter_total 7 -_ampl_elapsed_time 0.110000 +_ampl_elapsed_time 0.095000 _total_solve_time 0.031250 total_time 0 operatingSystem windows OS 'Windows_NT' COMPUTERNAME 'ARTELYS-PC253' -directory 'C:\Users\parvy\AppData\Local\Temp\ampl_3114721600970297698' +directory 'C:\Users\parvy\AppData\Local\Temp\ampl_7845811466926249191' log_level_ampl INFO log_level_knitro 2 diff --git a/open-reac/src/test/resources/openreac-output-real-network/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/openreac-output-real-network/reactiveopf_results_voltages.csv new file mode 100644 index 00000000..dcc50f40 --- /dev/null +++ b/open-reac/src/test/resources/openreac-output-real-network/reactiveopf_results_voltages.csv @@ -0,0 +1,58 @@ +#variant;bus;V;theta;id; +1;1;1.393;0.040;"VL1_0"; +1;2;1.382;0.040;"VL2_0"; +1;3;1.390;0.032;"VL3_0"; +1;4;1.392;0.023;"VL4_0"; +1;5;1.442;-0.016;"VL4_1"; +1;6;1.391;0.018;"VL5_0"; +1;7;1.393;0.020;"VL6_0"; +1;8;1.395;0.034;"VL7_0"; +1;9;1.442;0.014;"VL7_1"; +1;10;1.403;0.067;"VL8_0"; +1;11;1.379;0.013;"VL9_0"; +1;12;1.460;0.002;"VL9_1"; +1;13;1.374;-0.008;"VL10_0"; +1;14;1.475;-0.017;"VL10_1"; +1;15;1.372;0.001;"VL11_0"; +1;16;1.432;-0.032;"VL11_1"; +1;17;1.431;-0.009;"VL11_2"; +1;18;1.376;0.001;"VL12_0"; +1;19;1.368;0.000;"VL13_0"; +1;20;1.480;-0.029;"VL13_1"; +1;21;1.364;-0.001;"VL14_0"; +1;22;1.500;-0.016;"VL14_1"; +1;23;1.380;0.012;"VL15_0"; +1;24;1.456;-0.001;"VL15_1"; +1;25;1.379;-0.001;"VL16_0"; +1;26;1.381;0.011;"VL17_0"; +1;27;1.413;-0.029;"VL19_0"; +1;28;1.404;-0.031;"VL20_0"; +1;29;1.461;-0.030;"VL20_1"; +1;30;1.460;-0.029;"VL22_0"; +1;31;1.460;-0.030;"VL23_0"; +1;32;1.467;-0.031;"VL24_0"; +1;33;1.482;-0.070;"VL24_1"; +1;34;1.406;-0.027;"VL24_2"; +1;35;1.422;-0.006;"VL27_0"; +1;36;1.432;0.006;"VL28_0"; +1;37;1.467;-0.074;"VL30_0"; +1;38;1.445;-0.078;"VL31_0"; +1;39;1.447;-0.071;"VL32_0"; +1;40;1.424;-0.039;"VL32_1"; +1;41;1.445;-0.071;"VL33_0"; +1;42;1.427;-0.037;"VL35_0"; +1;43;1.433;-0.034;"VL36_0"; +1;44;1.439;-0.033;"VL37_0"; +1;45;1.461;-0.028;"VL38_0"; +1;46;1.438;-0.033;"VL39_0"; +1;47;1.427;-0.059;"VL39_1"; +1;48;1.429;-0.034;"VL40_0"; +1;49;1.427;-0.054;"VL40_1"; +1;50;1.419;-0.047;"VL42_0"; +1;51;1.457;-0.022;"VL44_0"; +1;52;1.478;-0.028;"VL47_0"; +1;53;1.473;-0.028;"VL48_0"; +1;54;1.465;-0.030;"VL50_0"; +1;55;1.428;-0.005;"VL52_0"; +1;56;1.425;-0.013;"VL53_0"; +1;57;1.440;-0.007;"VL54_0"; diff --git a/open-reac/src/test/resources/openreac-output-shunt/reactiveopf_results_indic.txt b/open-reac/src/test/resources/openreac-output-shunt/reactiveopf_results_indic.txt index a205a5f3..bd50fa75 100644 --- a/open-reac/src/test/resources/openreac-output-shunt/reactiveopf_results_indic.txt +++ b/open-reac/src/test/resources/openreac-output-shunt/reactiveopf_results_indic.txt @@ -1,18 +1,18 @@ final_status OK dcopf_status OK -ctime_start 'Fri Nov 24 12:01:56 2023' +ctime_start 'Wed Jan 10 12:29:15 2024' last_solve_result_num 0 nb_iter_last 29 nb_iter_total 29 -_ampl_elapsed_time 0.077000 -_total_solve_time 0.031250 +_ampl_elapsed_time 0.062000 +_total_solve_time 0.000000 total_time 0 operatingSystem windows OS 'Windows_NT' COMPUTERNAME 'ARTELYS-PC253' -directory 'C:\Users\parvy\AppData\Local\Temp\ampl_12369045109419234150' +directory 'C:\Users\parvy\AppData\Local\Temp\ampl_16952986494138910718' log_level_ampl INFO log_level_knitro 2 diff --git a/open-reac/src/test/resources/openreac-output-shunt/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/openreac-output-shunt/reactiveopf_results_voltages.csv new file mode 100644 index 00000000..d46d1c5c --- /dev/null +++ b/open-reac/src/test/resources/openreac-output-shunt/reactiveopf_results_voltages.csv @@ -0,0 +1,4 @@ +#variant;bus;V;theta;id; +1;1;1.050;0.002;"vl1_0"; +1;2;1.049;0.000;"vl2_0"; +1;3;1.052;-0.001;"vl3_0"; diff --git a/open-reac/src/test/resources/openreac-output-svc/reactiveopf_results_indic.txt b/open-reac/src/test/resources/openreac-output-svc/reactiveopf_results_indic.txt index a9224ea0..76c4722a 100644 --- a/open-reac/src/test/resources/openreac-output-svc/reactiveopf_results_indic.txt +++ b/open-reac/src/test/resources/openreac-output-svc/reactiveopf_results_indic.txt @@ -1,18 +1,18 @@ final_status OK dcopf_status OK -ctime_start 'Fri Nov 24 12:01:27 2023' +ctime_start 'Wed Jan 10 12:32:41 2024' last_solve_result_num 0 nb_iter_last 6 nb_iter_total 6 -_ampl_elapsed_time 0.094000 +_ampl_elapsed_time 0.093000 _total_solve_time 0.031250 total_time 0 operatingSystem windows OS 'Windows_NT' COMPUTERNAME 'ARTELYS-PC253' -directory 'C:\Users\parvy\AppData\Local\Temp\ampl_11598000998118468803' +directory 'C:\Users\parvy\AppData\Local\Temp\ampl_60840544416039339' log_level_ampl INFO log_level_knitro 2 diff --git a/open-reac/src/test/resources/openreac-output-svc/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/openreac-output-svc/reactiveopf_results_voltages.csv new file mode 100644 index 00000000..98063dc6 --- /dev/null +++ b/open-reac/src/test/resources/openreac-output-svc/reactiveopf_results_voltages.csv @@ -0,0 +1,3 @@ +#variant;bus;V;theta;id; +1;1;1.050;0.002;"vl1_0"; +1;2;1.049;0.000;"vl2_0"; diff --git a/open-reac/src/test/resources/openreac-output-transfo/reactiveopf_results_indic.txt b/open-reac/src/test/resources/openreac-output-transfo/reactiveopf_results_indic.txt index b898ef32..6c3fb12f 100644 --- a/open-reac/src/test/resources/openreac-output-transfo/reactiveopf_results_indic.txt +++ b/open-reac/src/test/resources/openreac-output-transfo/reactiveopf_results_indic.txt @@ -1,18 +1,18 @@ final_status OK dcopf_status OK -ctime_start 'Fri Nov 24 12:02:34 2023' +ctime_start 'Wed Jan 10 12:32:01 2024' last_solve_result_num 0 nb_iter_last 4 nb_iter_total 4 -_ampl_elapsed_time 0.095000 +_ampl_elapsed_time 0.125000 _total_solve_time 0.031250 total_time 0 operatingSystem windows OS 'Windows_NT' COMPUTERNAME 'ARTELYS-PC253' -directory 'C:\Users\parvy\AppData\Local\Temp\ampl_7140935963031466466' +directory 'C:\Users\parvy\AppData\Local\Temp\ampl_4525712114905560758' log_level_ampl INFO log_level_knitro 2 diff --git a/open-reac/src/test/resources/openreac-output-transfo/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/openreac-output-transfo/reactiveopf_results_voltages.csv new file mode 100644 index 00000000..32e404c4 --- /dev/null +++ b/open-reac/src/test/resources/openreac-output-transfo/reactiveopf_results_voltages.csv @@ -0,0 +1,4 @@ +#variant;bus;V;theta;id; +1;1;0.906;0.014;"VL_1_0"; +1;2;0.900;0.000;"VL_2_0"; +1;3;0.695;-0.082;"VL_3_0"; diff --git a/open-reac/src/test/resources/openreac-output-vsc/reactiveopf_results_indic.txt b/open-reac/src/test/resources/openreac-output-vsc/reactiveopf_results_indic.txt index 07bad8c4..79889398 100644 --- a/open-reac/src/test/resources/openreac-output-vsc/reactiveopf_results_indic.txt +++ b/open-reac/src/test/resources/openreac-output-vsc/reactiveopf_results_indic.txt @@ -1,7 +1,7 @@ final_status OK dcopf_status OK -ctime_start 'Fri Nov 24 12:01:03 2023' +ctime_start 'Wed Jan 10 12:33:19 2024' last_solve_result_num 0 nb_iter_last 6 nb_iter_total 6 @@ -12,7 +12,7 @@ total_time 0 operatingSystem windows OS 'Windows_NT' COMPUTERNAME 'ARTELYS-PC253' -directory 'C:\Users\parvy\AppData\Local\Temp\ampl_2514974589581916563' +directory 'C:\Users\parvy\AppData\Local\Temp\ampl_1855145751103852938' log_level_ampl INFO log_level_knitro 2 diff --git a/open-reac/src/test/resources/openreac-output-vsc/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/openreac-output-vsc/reactiveopf_results_voltages.csv new file mode 100644 index 00000000..0aa3b336 --- /dev/null +++ b/open-reac/src/test/resources/openreac-output-vsc/reactiveopf_results_voltages.csv @@ -0,0 +1,7 @@ +#variant;bus;V;theta;id; +1;1;0.568;-0.707;"b1_vl_0"; +1;2;0.500;-0.927;"b2_vl_0"; +1;3;0.651;-0.810;"b3_vl_0"; +1;4;0.651;0.117;"b4_vl_0"; +1;5;0.500;0.000;"b5_vl_0"; +1;6;0.568;0.220;"b6_vl_0"; From 2ef091c7456ab853e6fef626384c99fcbe3c7ded Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 10 Jan 2024 16:10:52 +0100 Subject: [PATCH 10/28] refactor. Signed-off-by: parvy --- .../powsybl/openreac/parameters/output/OpenReacResult.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index 1d8535a3..933d9a02 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -8,6 +8,7 @@ import com.powsybl.iidm.modification.*; import com.powsybl.iidm.modification.tapchanger.RatioTapPositionModification; +import com.powsybl.iidm.modification.util.VoltageRegulationUtils; import com.powsybl.iidm.network.*; import com.powsybl.openreac.parameters.OpenReacAmplIOFiles; import com.powsybl.openreac.parameters.output.ReactiveSlackOutput.ReactiveSlack; @@ -123,9 +124,7 @@ public void applyAllModifications(Network network) { .forEach(ratioTapChanger -> ratioTapChanger.setTargetV(busResult.getV() * nomV)); // Update target of shunts regulating voltage - network.getShuntCompensatorStream() - .filter(ShuntCompensator::isVoltageRegulatorOn) - .filter(shuntCompensator -> shuntCompensator.getRegulatingTerminal().getBusView().getBus().equals(b)) + VoltageRegulationUtils.getRegulatingShuntCompensators(network, b) .forEach(shuntCompensator -> shuntCompensator.setTargetV(busResult.getV() * nomV)); } } From 711d14c56f2de8afe17a5836e2b4339d267d3391 Mon Sep 17 00:00:00 2001 From: parvy Date: Thu, 11 Jan 2024 15:21:30 +0100 Subject: [PATCH 11/28] Add warm-start and TU. Signed-off-by: parvy --- .../parameters/output/OpenReacResult.java | 15 ++-- .../powsybl/openreac/OpenReacRunnerTest.java | 34 ++++++- .../reactiveopf_results_generators.csv | 2 + .../reactiveopf_results_indic.txt | 88 +++++++++++++++++++ .../reactiveopf_results_rtc.csv | 1 + .../reactiveopf_results_shunts.csv | 1 + ...iveopf_results_static_var_compensators.csv | 1 + .../reactiveopf_results_voltages.csv | 4 + ...tiveopf_results_vsc_converter_stations.csv | 1 + 9 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_generators.csv create mode 100644 open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_indic.txt create mode 100644 open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_rtc.csv create mode 100644 open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_shunts.csv create mode 100644 open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_static_var_compensators.csv create mode 100644 open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_voltages.csv create mode 100644 open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_vsc_converter_stations.csv diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index 933d9a02..811c0e66 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -111,21 +111,24 @@ public void applyAllModifications(Network network) { for (BusResult busResult : getVoltagePlan()) { Bus b = network.getBusView().getBus(busResult.getBusId()); - double nomV = b.getVoltageLevel().getNominalV(); + double v = busResult.getV() * b.getVoltageLevel().getNominalV(); + double angle = busResult.getAngle(); - // TODO : update voltage values of b ? + // warm start + b.setV(v); + b.setAngle(angle); - // Update target of ratio tap changers regulating voltage + // update target of ratio tap changers regulating voltage on b network.getTwoWindingsTransformerStream() .filter(RatioTapChangerHolder::hasRatioTapChanger) .map(RatioTapChangerHolder::getRatioTapChanger) .filter(TapChanger::isRegulating) .filter(ratioTapChanger -> ratioTapChanger.getRegulationTerminal().getBusView().getBus().equals(b)) - .forEach(ratioTapChanger -> ratioTapChanger.setTargetV(busResult.getV() * nomV)); + .forEach(ratioTapChanger -> ratioTapChanger.setTargetV(v)); - // Update target of shunts regulating voltage + // update target of shunts regulating voltage on b VoltageRegulationUtils.getRegulatingShuntCompensators(network, b) - .forEach(shuntCompensator -> shuntCompensator.setTargetV(busResult.getV() * nomV)); + .forEach(shuntCompensator -> shuntCompensator.setTargetV(v)); } } } diff --git a/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java b/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java index 953c75fc..3b2d7307 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java @@ -327,7 +327,7 @@ public void testTransformer() throws IOException { parameters.addVariableTwoWindingsTransformers(List.of("T2wT")); testAllModifAndLoadFlow(network, "openreac-output-transfo", parameters); assertEquals(0, rtc.getTapPosition()); - assertEquals(22.935, rtc.getTargetV()); // TODO : verify the value + assertEquals(22.935, rtc.getTargetV()); } @Test @@ -338,6 +338,38 @@ public void testRealNetwork() throws IOException { testAllModifAndLoadFlow(network, "openreac-output-real-network", parameters); } + @Test + public void testWarmStart() throws IOException { + Network network = VoltageControlNetworkFactory.createNetworkWithT2wt(); + setDefaultVoltageLimits(network); + String subFolder = "openreac-output-warm-start"; + LocalCommandExecutor localCommandExecutor = new TestLocalCommandExecutor( + List.of(subFolder + "/reactiveopf_results_generators.csv", + subFolder + "/reactiveopf_results_indic.txt", + subFolder + "/reactiveopf_results_rtc.csv", + subFolder + "/reactiveopf_results_shunts.csv", + subFolder + "/reactiveopf_results_static_var_compensators.csv", + subFolder + "/reactiveopf_results_vsc_converter_stations.csv", + subFolder + "/reactiveopf_results_voltages.csv")); + // To really run open reac, use the commentede line below. Be sure that open-reac/src/test/resources/com/powsybl/config/test/config.yml contains your ampl path +// try (ComputationManager computationManager = new LocalComputationManager()) { + try (ComputationManager computationManager = new LocalComputationManager(new LocalComputationConfig(tmpDir), + localCommandExecutor, ForkJoinPool.commonPool())) { + OpenReacResult openReacResult = OpenReacRunner.run(network, + network.getVariantManager().getWorkingVariantId(), new OpenReacParameters(), + new OpenReacConfig(true), computationManager); + assertEquals(OpenReacStatus.OK, openReacResult.getStatus()); + openReacResult.applyAllModifications(network); + } + + assertEquals(119.592, network.getBusBreakerView().getBus("BUS_1").getV()); + assertEquals(0.014, network.getBusBreakerView().getBus("BUS_1").getAngle()); + assertEquals(118.8, network.getBusBreakerView().getBus("BUS_2").getV()); + assertEquals(0, network.getBusBreakerView().getBus("BUS_2").getAngle()); + assertEquals(22.935, network.getBusBreakerView().getBus("BUS_3").getV()); + assertEquals(-0.082, network.getBusBreakerView().getBus("BUS_3").getAngle()); + } + public static Network create() { Network network = Network.create("svc", "test"); Substation s1 = network.newSubstation() diff --git a/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_generators.csv b/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_generators.csv new file mode 100644 index 00000000..d111e44e --- /dev/null +++ b/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_generators.csv @@ -0,0 +1,2 @@ +#variant;num;bus;vRegul;V(pu);targetP(MW);targetQ(Mvar);P(MW);Q(MW); +1;1;1;'true';0.906;25.0;7.9;-21.2;-7.9; diff --git a/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_indic.txt b/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_indic.txt new file mode 100644 index 00000000..22759e32 --- /dev/null +++ b/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_indic.txt @@ -0,0 +1,88 @@ +final_status OK +dcopf_status OK + +ctime_start 'Thu Jan 11 15:12:16 2024' +last_solve_result_num 0 +nb_iter_last 5 +nb_iter_total 5 +_ampl_elapsed_time 0.047000 +_total_solve_time 0.031250 +total_time 0 + +operatingSystem windows +OS 'Windows_NT' +COMPUTERNAME 'ARTELYS-PC253' +directory 'C:\Users\parvy\AppData\Local\Temp\ampl_1724309836662612364' + +log_level_ampl INFO +log_level_knitro 2 +objective_choice 0 +ratio_voltage_target 0.500000 +coeff_alpha 1.000000 +Pnull 0.010000 +Znull 0.000100 +epsilon_nominal_voltage 1.000000 +min_plausible_low_voltage_limit 0.500000 +max_plausible_high_voltage_limit 1.500000 +ignore_voltage_bounds 0.000000 +buses_with_reactive_slacks NO_GENERATION +PQmax 9000.000000 +defaultPmax 1000.000000 +defaultPmin 0.000000 +defaultQmaxPmaxRatio 0.300000 +defaultQmin -300.000000 +defaultQmax 300.000000 +minimalQPrange 1.000000 + +nb_substations 3 +nb_bus_in_data_file 3 +nb_bus_in_ACDC_CC 3 +nb_bus_in_AC_CC 3 +nb_bus_in_ACDC_but_out_AC_CC 0 +nb_bus_with_voltage_value 0 +nb_bus_with_reactive_slacks 2 +nb_bus_without_reactive_slacks 1 +nb_branch_in_data_file 2 +nb_branch_in_AC_CC 2 +nb_branch_with_nonsmall_impedance 2 +nb_branch_with_zero_or_small_impedance 0 +nb_unit_in_data_file 1 +nb_unit_in_AC_CC 1 +nb_unit_up_and_running 1 +nb_unit_with_variable_reactive_power 1 +nb_unit_with_fixed_reactive_power 0 +nb_load_in_data_file 2 +nb_load_in_AC_CC 2 +nb_shunt_in_data_file 0 +nb_shunt_connectable_or_in_AC_CC 0 +nb_shunt_with_fixed_value 0 +nb_shunt_with_variable_value 0 +nb_transformers_with_variable_ratio 0 +nb_transformers_with_fixed_ratio 1 +nb_svc_in_data_file 0 +nb_svc_in_AC_CC 0 +nb_svc_up_and_operating 0 +nb_vsc_converter_in_data_file 0 +nb_vsc_converter_up_and_running 0 +nb_lcc_converter_in_data_file 0 +nb_lcc_converter_up_and_running 0 +nb_batteries 0 +sum_batteries_pmax 0.0 +sum_batteries_pmin 0.0 + +max_teta_dc 0.01 +max_teta_ac 0.01 +teta_max 3.01 +min_teta_dc -0.05 +min_teta_ac -0.08 +teta_min -3.05 +max_delta_teta_dc 0.045914 +max_delta_teta_ac 0.081650 +min_delta_teta_dc 0.009298 +min_delta_teta_ac 0.014293 + +nb_reactive_slacks 0 +nb_slacks_condensator 0 +sum_slacks_condensator 0.0 +nb_slacks_self 0 +sum_slacks_self 0.0 diff --git a/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_rtc.csv b/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_rtc.csv new file mode 100644 index 00000000..9a62a138 --- /dev/null +++ b/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_rtc.csv @@ -0,0 +1 @@ +#variant;num;tap; diff --git a/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_shunts.csv b/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_shunts.csv new file mode 100644 index 00000000..8d515fde --- /dev/null +++ b/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_shunts.csv @@ -0,0 +1 @@ +#variant;num;bus;b(pu);Q(Mvar);section; diff --git a/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_static_var_compensators.csv b/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_static_var_compensators.csv new file mode 100644 index 00000000..6792ddb9 --- /dev/null +++ b/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_static_var_compensators.csv @@ -0,0 +1 @@ +#variant;num;bus;vRegul;V(pu);Q(Mvar); diff --git a/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_voltages.csv new file mode 100644 index 00000000..38af3a57 --- /dev/null +++ b/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_voltages.csv @@ -0,0 +1,4 @@ +#variant;bus;V(pu);theta(rad);id; +1;1;0.906;0.014;"VL_1_0"; +1;2;0.900;0.000;"VL_2_0"; +1;3;0.695;-0.082;"VL_3_0"; diff --git a/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_vsc_converter_stations.csv b/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_vsc_converter_stations.csv new file mode 100644 index 00000000..aa24858c --- /dev/null +++ b/open-reac/src/test/resources/openreac-output-warm-start/reactiveopf_results_vsc_converter_stations.csv @@ -0,0 +1 @@ +#variant;num;bus;vRegul;targetV(pu);targetQ(Mvar);P(MW);Q(Mvar); From 295119b5dc1f08ccb5b3d647338187546a75bcf2 Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 17 Jan 2024 17:53:32 +0100 Subject: [PATCH 12/28] refactor. Signed-off-by: parvy --- .../parameters/output/VoltagePlanOutput.java | 38 +++++-------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java index 3562e6c4..a41062b0 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java @@ -6,14 +6,10 @@ */ package com.powsybl.openreac.parameters.output; -import com.powsybl.ampl.converter.AmplConstants; import com.powsybl.ampl.converter.AmplSubset; import com.powsybl.commons.util.StringToIntMapper; -import com.powsybl.openreac.exceptions.IncompatibleModelException; import com.powsybl.openreac.parameters.AmplIOUtils; -import java.io.BufferedReader; -import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -23,11 +19,11 @@ */ public class VoltagePlanOutput extends AbstractNoThrowOutput { + private static final String ELEMENT = "voltages"; public static final int EXPECTED_COLS = 5; private static final int ID_COLUMN_INDEX = 4; private static final int V_COLUMN_INDEX = 2; private static final int ANGLE_COLUMN_INDEX = 3; - private static final String SEP = ";"; public static class BusResult { private final String busId; @@ -60,41 +56,27 @@ public List getVoltagePlan() { } @Override - public String getFileName() { - return "reactiveopf_results_voltages.csv"; + public String getElement() { + return ELEMENT; } @Override - public void read(BufferedReader reader, StringToIntMapper stringToIntMapper) throws IOException { - String headers = reader.readLine(); - int readCols = headers.split(SEP).length; - if (readCols != EXPECTED_COLS) { - triggerErrorState(); - throw new IncompatibleModelException("Error reading " + getFileName() + ", wrong number of columns. Expected: " + EXPECTED_COLS + ", found:" + readCols); - } else { - String line = reader.readLine(); - while (line != null) { - readLine(line.split(SEP)); - line = reader.readLine(); - } - } + public int getExpectedColumns() { + return EXPECTED_COLS; } @Override - public boolean throwOnMissingFile() { - triggerErrorState(); - return false; - } - - private void readLine(String[] tokens) { + protected void readLine(String[] tokens, StringToIntMapper stringToIntMapper) { String id = AmplIOUtils.removeQuotes(tokens[ID_COLUMN_INDEX]); double v = readDouble(tokens[V_COLUMN_INDEX]); double angle = readDouble(tokens[ANGLE_COLUMN_INDEX]); voltagePlan.add(new BusResult(id, v, angle)); } - private double readDouble(String d) { - return Float.parseFloat(d) != AmplConstants.INVALID_FLOAT_VALUE ? Double.parseDouble(d) : Double.NaN; + @Override + public boolean throwOnMissingFile() { + triggerErrorState(); + return false; } } From 023995c825dc0dbd2ac0649716c6c4dafa7eb710 Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 17 Jan 2024 18:20:23 +0100 Subject: [PATCH 13/28] add boolean for warm start update and refactor TUs. Signed-off-by: parvy --- .../parameters/output/OpenReacResult.java | 16 ++++-- .../powsybl/openreac/OpenReacRunnerTest.java | 54 +++++++++---------- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index 811c0e66..13907de9 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -35,6 +35,7 @@ public class OpenReacResult { private final List svcModifications; private final List tapPositionModifications; private final List voltagePlan; + private boolean warmStart = true; /** * @param status the final status of the OpenReac run. @@ -90,6 +91,14 @@ public List getVoltagePlan() { return voltagePlan; } + public boolean getWarmStat() { + return warmStart; + } + + public void setWarmStart(boolean warmStart) { + this.warmStart = warmStart; + } + public List getAllNetworkModifications() { List modifs = new ArrayList<>(getGeneratorModifications().size() + getShuntsModifications().size() + @@ -114,9 +123,10 @@ public void applyAllModifications(Network network) { double v = busResult.getV() * b.getVoltageLevel().getNominalV(); double angle = busResult.getAngle(); - // warm start - b.setV(v); - b.setAngle(angle); + if (getWarmStat()) { + b.setV(v); + b.setAngle(angle); + } // update target of ratio tap changers regulating voltage on b network.getTwoWindingsTransformerStream() diff --git a/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java b/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java index 3b2d7307..6652f838 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java @@ -231,7 +231,8 @@ void testRunAsync() throws IOException { subFolder + "/reactiveopf_results_rtc.csv", subFolder + "/reactiveopf_results_shunts.csv", subFolder + "/reactiveopf_results_static_var_compensators.csv", - subFolder + "/reactiveopf_results_vsc_converter_stations.csv")); + subFolder + "/reactiveopf_results_vsc_converter_stations.csv", + subFolder + "/reactiveopf_results_voltages.csv")); // To really run open reac, use the commented line below. Be sure that open-reac/src/test/resources/com/powsybl/config/test/config.yml contains your ampl path // try (ComputationManager computationManager = new LocalComputationManager()) { try (ComputationManager computationManager = new LocalComputationManager(new LocalComputationConfig(tmpDir), @@ -245,24 +246,7 @@ void testRunAsync() throws IOException { } private void testAllModifAndLoadFlow(Network network, String subFolder, OpenReacParameters parameters) throws IOException { - LocalCommandExecutor localCommandExecutor = new TestLocalCommandExecutor( - List.of(subFolder + "/reactiveopf_results_generators.csv", - subFolder + "/reactiveopf_results_indic.txt", - subFolder + "/reactiveopf_results_rtc.csv", - subFolder + "/reactiveopf_results_shunts.csv", - subFolder + "/reactiveopf_results_static_var_compensators.csv", - subFolder + "/reactiveopf_results_vsc_converter_stations.csv", - subFolder + "/reactiveopf_results_voltages.csv")); - // To really run open reac, use the commentede line below. Be sure that open-reac/src/test/resources/com/powsybl/config/test/config.yml contains your ampl path -// try (ComputationManager computationManager = new LocalComputationManager()) { - try (ComputationManager computationManager = new LocalComputationManager(new LocalComputationConfig(tmpDir), - localCommandExecutor, ForkJoinPool.commonPool())) { - OpenReacResult openReacResult = OpenReacRunner.run(network, - network.getVariantManager().getWorkingVariantId(), parameters, new OpenReacConfig(true), - computationManager); - assertEquals(OpenReacStatus.OK, openReacResult.getStatus()); - openReacResult.applyAllModifications(network); - } + runAndApplyAllModifications(network, subFolder, parameters, true); LoadFlowResult loadFlowResult = LoadFlow.run(network); assertTrue(loadFlowResult.isOk()); } @@ -343,6 +327,26 @@ public void testWarmStart() throws IOException { Network network = VoltageControlNetworkFactory.createNetworkWithT2wt(); setDefaultVoltageLimits(network); String subFolder = "openreac-output-warm-start"; + OpenReacParameters parameters = new OpenReacParameters(); + + runAndApplyAllModifications(network, subFolder, parameters, false); // without warm start, no update + assertEquals(Double.NaN, network.getBusBreakerView().getBus("BUS_1").getV()); + assertEquals(Double.NaN, network.getBusBreakerView().getBus("BUS_1").getAngle()); + assertEquals(Double.NaN, network.getBusBreakerView().getBus("BUS_2").getV()); + assertEquals(Double.NaN, network.getBusBreakerView().getBus("BUS_2").getAngle()); + assertEquals(Double.NaN, network.getBusBreakerView().getBus("BUS_3").getV()); + assertEquals(Double.NaN, network.getBusBreakerView().getBus("BUS_3").getAngle()); + + runAndApplyAllModifications(network, subFolder, parameters, true); + assertEquals(119.592, network.getBusBreakerView().getBus("BUS_1").getV()); + assertEquals(0.014, network.getBusBreakerView().getBus("BUS_1").getAngle()); + assertEquals(118.8, network.getBusBreakerView().getBus("BUS_2").getV()); + assertEquals(0, network.getBusBreakerView().getBus("BUS_2").getAngle()); + assertEquals(22.935, network.getBusBreakerView().getBus("BUS_3").getV()); + assertEquals(-0.082, network.getBusBreakerView().getBus("BUS_3").getAngle()); + } + + private void runAndApplyAllModifications(Network network, String subFolder, OpenReacParameters parameters, boolean warmStart) throws IOException { LocalCommandExecutor localCommandExecutor = new TestLocalCommandExecutor( List.of(subFolder + "/reactiveopf_results_generators.csv", subFolder + "/reactiveopf_results_indic.txt", @@ -354,20 +358,14 @@ public void testWarmStart() throws IOException { // To really run open reac, use the commentede line below. Be sure that open-reac/src/test/resources/com/powsybl/config/test/config.yml contains your ampl path // try (ComputationManager computationManager = new LocalComputationManager()) { try (ComputationManager computationManager = new LocalComputationManager(new LocalComputationConfig(tmpDir), - localCommandExecutor, ForkJoinPool.commonPool())) { + localCommandExecutor, ForkJoinPool.commonPool())) { OpenReacResult openReacResult = OpenReacRunner.run(network, - network.getVariantManager().getWorkingVariantId(), new OpenReacParameters(), + network.getVariantManager().getWorkingVariantId(), parameters, new OpenReacConfig(true), computationManager); assertEquals(OpenReacStatus.OK, openReacResult.getStatus()); + openReacResult.setWarmStart(warmStart); openReacResult.applyAllModifications(network); } - - assertEquals(119.592, network.getBusBreakerView().getBus("BUS_1").getV()); - assertEquals(0.014, network.getBusBreakerView().getBus("BUS_1").getAngle()); - assertEquals(118.8, network.getBusBreakerView().getBus("BUS_2").getV()); - assertEquals(0, network.getBusBreakerView().getBus("BUS_2").getAngle()); - assertEquals(22.935, network.getBusBreakerView().getBus("BUS_3").getV()); - assertEquals(-0.082, network.getBusBreakerView().getBus("BUS_3").getAngle()); } public static Network create() { From 0cd592244bc94fecc2b0b41cca56bb566a5fe03c Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 17 Jan 2024 18:26:26 +0100 Subject: [PATCH 14/28] fix codesmell. Signed-off-by: parvy --- .../test/java/com/powsybl/openreac/OpenReacRunnerTest.java | 4 ++-- .../openreac/parameters/output/VoltagePlanOutputTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java b/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java index 6652f838..4ee22b88 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java @@ -281,7 +281,7 @@ public void testSvc() throws IOException { } @Test - public void testShuntModification() throws IOException { + void testShunt() throws IOException { Network network = create(); setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network ShuntCompensator shunt = network.getShuntCompensator("SHUNT"); @@ -323,7 +323,7 @@ public void testRealNetwork() throws IOException { } @Test - public void testWarmStart() throws IOException { + void testWarmStart() throws IOException { Network network = VoltageControlNetworkFactory.createNetworkWithT2wt(); setDefaultVoltageLimits(network); String subFolder = "openreac-output-warm-start"; diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java index e89bf854..b2c2d1fc 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java @@ -10,7 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class VoltagePlanOutputTest { +class VoltagePlanOutputTest { @Test void busResultTest() { From b107540afd5b8e6512c0077fd556c42c232a19f3 Mon Sep 17 00:00:00 2001 From: parvy Date: Thu, 18 Jan 2024 12:45:10 +0100 Subject: [PATCH 15/28] refactor. Signed-off-by: parvy --- .../parameters/output/OpenReacResult.java | 54 +++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index 13907de9..e5edfa9d 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -8,7 +8,6 @@ import com.powsybl.iidm.modification.*; import com.powsybl.iidm.modification.tapchanger.RatioTapPositionModification; -import com.powsybl.iidm.modification.util.VoltageRegulationUtils; import com.powsybl.iidm.network.*; import com.powsybl.openreac.parameters.OpenReacAmplIOFiles; import com.powsybl.openreac.parameters.output.ReactiveSlackOutput.ReactiveSlack; @@ -118,27 +117,40 @@ public void applyAllModifications(Network network) { modif.apply(network); } - for (BusResult busResult : getVoltagePlan()) { - Bus b = network.getBusView().getBus(busResult.getBusId()); - double v = busResult.getV() * b.getVoltageLevel().getNominalV(); - double angle = busResult.getAngle(); - - if (getWarmStat()) { - b.setV(v); - b.setAngle(angle); + // update target of ratio tap changers regulating voltage + network.getTwoWindingsTransformerStream() + .filter(RatioTapChangerHolder::hasRatioTapChanger) + .map(RatioTapChangerHolder::getRatioTapChanger) + .filter(TapChanger::isRegulating) + .forEach(ratioTapChanger -> { + Bus bus = ratioTapChanger.getRegulationTerminal().getBusView().getBus(); + BusResult busResult = voltagePlan.stream() + .filter(result -> Objects.equals(result.getBusId(), bus.getId())) + .findFirst() + .orElseThrow(); + ratioTapChanger.setTargetV(busResult.getV() * bus.getVoltageLevel().getNominalV()); + } + ); + + // update target of shunts regulating voltage + network.getShuntCompensatorStream() + .filter(ShuntCompensator::isVoltageRegulatorOn) + .forEach(shuntCompensator -> { + Bus bus = shuntCompensator.getRegulatingTerminal().getBusView().getBus(); + BusResult busResult = voltagePlan.stream() + .filter(result -> Objects.equals(result.getBusId(), bus.getId())) + .findFirst() + .orElseThrow(); + shuntCompensator.setTargetV(busResult.getV() * bus.getVoltageLevel().getNominalV()); + }); + + // update voltages of the buses + if (getWarmStat()) { + for (BusResult busResult : voltagePlan) { + Bus b = network.getBusView().getBus(busResult.getBusId()); + b.setV(busResult.getV() * b.getVoltageLevel().getNominalV()); + b.setAngle(busResult.getAngle()); } - - // update target of ratio tap changers regulating voltage on b - network.getTwoWindingsTransformerStream() - .filter(RatioTapChangerHolder::hasRatioTapChanger) - .map(RatioTapChangerHolder::getRatioTapChanger) - .filter(TapChanger::isRegulating) - .filter(ratioTapChanger -> ratioTapChanger.getRegulationTerminal().getBusView().getBus().equals(b)) - .forEach(ratioTapChanger -> ratioTapChanger.setTargetV(v)); - - // update target of shunts regulating voltage on b - VoltageRegulationUtils.getRegulatingShuntCompensators(network, b) - .forEach(shuntCompensator -> shuntCompensator.setTargetV(v)); } } } From c117747b0c37d3dd91b71b6b19e57324caaa8c89 Mon Sep 17 00:00:00 2001 From: parvy Date: Thu, 18 Jan 2024 12:56:39 +0100 Subject: [PATCH 16/28] refactor. Signed-off-by: parvy --- .../parameters/output/OpenReacResult.java | 37 ++++++++----------- .../parameters/output/VoltagePlanOutput.java | 35 +++--------------- .../output/VoltagePlanOutputTest.java | 30 +++++---------- 3 files changed, 30 insertions(+), 72 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index e5edfa9d..49aa3161 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -11,12 +11,9 @@ import com.powsybl.iidm.network.*; import com.powsybl.openreac.parameters.OpenReacAmplIOFiles; import com.powsybl.openreac.parameters.output.ReactiveSlackOutput.ReactiveSlack; -import com.powsybl.openreac.parameters.output.VoltagePlanOutput.BusResult; +import org.jgrapht.alg.util.Pair; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; /** * OpenReac user interface to get results information. @@ -33,7 +30,7 @@ public class OpenReacResult { private final List vscModifications; private final List svcModifications; private final List tapPositionModifications; - private final List voltagePlan; + private final HashMap> voltagePlan; private boolean warmStart = true; /** @@ -51,7 +48,7 @@ public OpenReacResult(OpenReacStatus status, OpenReacAmplIOFiles amplIOFiles, Ma this.vscModifications = List.copyOf(amplIOFiles.getNetworkModifications().getVscModifications()); this.svcModifications = List.copyOf(amplIOFiles.getNetworkModifications().getSvcModifications()); this.tapPositionModifications = List.copyOf(amplIOFiles.getNetworkModifications().getTapPositionModifications()); - this.voltagePlan = List.copyOf(amplIOFiles.getVoltagePlanOutput().getVoltagePlan()); + this.voltagePlan = new HashMap<>(amplIOFiles.getVoltagePlanOutput().getVoltagePlan()); } public OpenReacStatus getStatus() { @@ -86,7 +83,7 @@ public List getVscModifications() { return vscModifications; } - public List getVoltagePlan() { + public HashMap> getVoltagePlan() { return voltagePlan; } @@ -124,11 +121,8 @@ public void applyAllModifications(Network network) { .filter(TapChanger::isRegulating) .forEach(ratioTapChanger -> { Bus bus = ratioTapChanger.getRegulationTerminal().getBusView().getBus(); - BusResult busResult = voltagePlan.stream() - .filter(result -> Objects.equals(result.getBusId(), bus.getId())) - .findFirst() - .orElseThrow(); - ratioTapChanger.setTargetV(busResult.getV() * bus.getVoltageLevel().getNominalV()); + double v = voltagePlan.get(bus.getId()).getFirst(); + ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); } ); @@ -137,19 +131,18 @@ public void applyAllModifications(Network network) { .filter(ShuntCompensator::isVoltageRegulatorOn) .forEach(shuntCompensator -> { Bus bus = shuntCompensator.getRegulatingTerminal().getBusView().getBus(); - BusResult busResult = voltagePlan.stream() - .filter(result -> Objects.equals(result.getBusId(), bus.getId())) - .findFirst() - .orElseThrow(); - shuntCompensator.setTargetV(busResult.getV() * bus.getVoltageLevel().getNominalV()); + double v = voltagePlan.get(bus.getId()).getFirst(); + shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV()); }); // update voltages of the buses if (getWarmStat()) { - for (BusResult busResult : voltagePlan) { - Bus b = network.getBusView().getBus(busResult.getBusId()); - b.setV(busResult.getV() * b.getVoltageLevel().getNominalV()); - b.setAngle(busResult.getAngle()); + for (String busId : voltagePlan.keySet()) { + Bus b = network.getBusView().getBus(busId); + double v = voltagePlan.get(busId).getFirst(); + double angle = voltagePlan.get(busId).getSecond(); + b.setV(v * b.getVoltageLevel().getNominalV()); + b.setAngle(angle); } } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java index a41062b0..657d04b3 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java @@ -9,10 +9,9 @@ import com.powsybl.ampl.converter.AmplSubset; import com.powsybl.commons.util.StringToIntMapper; import com.powsybl.openreac.parameters.AmplIOUtils; +import org.jgrapht.alg.util.Pair; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; /** * @author Pierre Arvy @@ -25,33 +24,9 @@ public class VoltagePlanOutput extends AbstractNoThrowOutput { private static final int V_COLUMN_INDEX = 2; private static final int ANGLE_COLUMN_INDEX = 3; - public static class BusResult { - private final String busId; - private final double v; - private final double angle; + private final Map> voltagePlan = new HashMap<>(); - public BusResult(String busId, double v, double angle) { - this.busId = Objects.requireNonNull(busId); - this.v = v; - this.angle = angle; - } - - public String getBusId() { - return busId; - } - - public double getV() { - return v; - } - - public double getAngle() { - return angle; - } - } - - private final List voltagePlan = new ArrayList<>(); - - public List getVoltagePlan() { + public Map> getVoltagePlan() { return voltagePlan; } @@ -70,7 +45,7 @@ protected void readLine(String[] tokens, StringToIntMapper stringToI String id = AmplIOUtils.removeQuotes(tokens[ID_COLUMN_INDEX]); double v = readDouble(tokens[V_COLUMN_INDEX]); double angle = readDouble(tokens[ANGLE_COLUMN_INDEX]); - voltagePlan.add(new BusResult(id, v, angle)); + voltagePlan.put(id, Pair.of(v, angle)); } @Override diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java index b2c2d1fc..ed2dac2f 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java @@ -1,5 +1,6 @@ package com.powsybl.openreac.parameters.output; +import org.jgrapht.alg.util.Pair; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -12,14 +13,6 @@ class VoltagePlanOutputTest { - @Test - void busResultTest() { - VoltagePlanOutput.BusResult busResult = new VoltagePlanOutput.BusResult("id", 0.98, 0.23); - assertEquals("id", busResult.getBusId()); - assertEquals(0.98, busResult.getV()); - assertEquals(0.23, busResult.getAngle()); - } - @Test void readTest() throws IOException { VoltagePlanOutput output = new VoltagePlanOutput(); @@ -29,19 +22,16 @@ void readTest() throws IOException { output.read(reader, null); assertEquals(3, output.getVoltagePlan().size()); - VoltagePlanOutput.BusResult busResult1 = output.getVoltagePlan().get(0); - VoltagePlanOutput.BusResult busResult2 = output.getVoltagePlan().get(1); - VoltagePlanOutput.BusResult busResult3 = output.getVoltagePlan().get(2); + Pair busVoltage1 = output.getVoltagePlan().get("bus1"); + Pair busVoltage2 = output.getVoltagePlan().get("bus2"); + Pair busVoltage3 = output.getVoltagePlan().get("bus3"); Assertions.assertAll( - () -> assertEquals("bus1", busResult1.getBusId()), - () -> assertEquals(0.8, busResult1.getV()), - () -> assertEquals(1.1, busResult1.getAngle()), - () -> assertEquals("bus2", busResult2.getBusId()), - () -> assertEquals(1.2, busResult2.getV()), - () -> assertEquals(Double.NaN, busResult2.getAngle()), - () -> assertEquals("bus3", busResult3.getBusId()), - () -> assertEquals(Double.NaN, busResult3.getV()), - () -> assertEquals(0.11, busResult3.getAngle()) + () -> assertEquals(0.8, busVoltage1.getFirst()), + () -> assertEquals(1.1, busVoltage1.getSecond()), + () -> assertEquals(1.2, busVoltage2.getFirst()), + () -> assertEquals(Double.NaN, busVoltage2.getSecond()), + () -> assertEquals(Double.NaN, busVoltage3.getFirst()), + () -> assertEquals(0.11, busVoltage3.getSecond()) ); } } From adea8ae1225c312be611dbf8eddc0c3d85b31c7c Mon Sep 17 00:00:00 2001 From: parvy Date: Thu, 18 Jan 2024 13:01:04 +0100 Subject: [PATCH 17/28] fix codesmell. Signed-off-by: parvy --- .../openreac/parameters/output/OpenReacResult.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index 49aa3161..0a9e64f3 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -83,7 +83,7 @@ public List getVscModifications() { return vscModifications; } - public HashMap> getVoltagePlan() { + public Map> getVoltagePlan() { return voltagePlan; } @@ -137,10 +137,10 @@ public void applyAllModifications(Network network) { // update voltages of the buses if (getWarmStat()) { - for (String busId : voltagePlan.keySet()) { - Bus b = network.getBusView().getBus(busId); - double v = voltagePlan.get(busId).getFirst(); - double angle = voltagePlan.get(busId).getSecond(); + for (var busUpdate : voltagePlan.entrySet()) { + Bus b = network.getBusView().getBus(busUpdate.getKey()); + double v = busUpdate.getValue().getFirst(); + double angle = busUpdate.getValue().getSecond(); b.setV(v * b.getVoltageLevel().getNominalV()); b.setAngle(angle); } From c43485a1dcabad7bdb391249ff65bf05619b13d6 Mon Sep 17 00:00:00 2001 From: parvy Date: Thu, 25 Jan 2024 15:24:40 +0100 Subject: [PATCH 18/28] Refactor and add TUs. Signed-off-by: parvy --- .../parameters/OpenReacAmplIOFiles.java | 12 ++-- .../parameters/output/OpenReacResult.java | 69 +++++++++++-------- ...nOutput.java => VoltageProfileOutput.java} | 10 +-- .../powsybl/openreac/OpenReacResultsTest.java | 69 +++++++++++++++++++ .../powsybl/openreac/OpenReacRunnerTest.java | 10 +-- ...est.java => VoltageProfileOutputTest.java} | 12 ++-- 6 files changed, 133 insertions(+), 49 deletions(-) rename open-reac/src/main/java/com/powsybl/openreac/parameters/output/{VoltagePlanOutput.java => VoltageProfileOutput.java} (82%) create mode 100644 open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java rename open-reac/src/test/java/com/powsybl/openreac/parameters/output/{VoltagePlanOutputTest.java => VoltageProfileOutputTest.java} (85%) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/OpenReacAmplIOFiles.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/OpenReacAmplIOFiles.java index 2697d5a2..b11f47c5 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/OpenReacAmplIOFiles.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/OpenReacAmplIOFiles.java @@ -14,7 +14,7 @@ import com.powsybl.openreac.parameters.input.algo.AlgorithmInput; import com.powsybl.openreac.parameters.output.OpenReacResult; import com.powsybl.openreac.parameters.output.ReactiveSlackOutput; -import com.powsybl.openreac.parameters.output.VoltagePlanOutput; +import com.powsybl.openreac.parameters.output.VoltageProfileOutput; import com.powsybl.openreac.parameters.output.network.NetworkModifications; import java.util.ArrayList; @@ -41,7 +41,7 @@ public class OpenReacAmplIOFiles implements AmplParameters { private final VoltageLevelLimitsOverrideInput voltageLimitsOverride; private final ConfiguredBusesWithReactiveSlack configuredReactiveSlackBuses; private final NetworkModifications networkModifications; - private final VoltagePlanOutput voltagePlanOutput; + private final VoltageProfileOutput voltageProfileOutput; private final boolean debug; public OpenReacAmplIOFiles(OpenReacParameters params, Network network, boolean debug) { @@ -56,7 +56,7 @@ public OpenReacAmplIOFiles(OpenReacParameters params, Network network, boolean d //outputs this.reactiveSlackOutput = new ReactiveSlackOutput(); this.networkModifications = new NetworkModifications(network); - this.voltagePlanOutput = new VoltagePlanOutput(); + this.voltageProfileOutput = new VoltageProfileOutput(); this.debug = debug; } @@ -69,8 +69,8 @@ public NetworkModifications getNetworkModifications() { return networkModifications; } - public VoltagePlanOutput getVoltagePlanOutput() { - return voltagePlanOutput; + public VoltageProfileOutput getVoltageProfileOutput() { + return voltageProfileOutput; } @Override @@ -86,7 +86,7 @@ public Collection getOutputParameters(boolean isConvergenceOk) { List list = new ArrayList<>(networkModificationsOutputFiles.size() + 2); list.addAll(networkModificationsOutputFiles); list.add(reactiveSlackOutput); - list.add(voltagePlanOutput); + list.add(voltageProfileOutput); return list; } return List.of(); diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index 0a9e64f3..da467c7e 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -30,8 +30,8 @@ public class OpenReacResult { private final List vscModifications; private final List svcModifications; private final List tapPositionModifications; - private final HashMap> voltagePlan; - private boolean warmStart = true; + private final HashMap> voltageProfile; + private boolean updateNetworkWithVoltages = true; /** * @param status the final status of the OpenReac run. @@ -48,7 +48,7 @@ public OpenReacResult(OpenReacStatus status, OpenReacAmplIOFiles amplIOFiles, Ma this.vscModifications = List.copyOf(amplIOFiles.getNetworkModifications().getVscModifications()); this.svcModifications = List.copyOf(amplIOFiles.getNetworkModifications().getSvcModifications()); this.tapPositionModifications = List.copyOf(amplIOFiles.getNetworkModifications().getTapPositionModifications()); - this.voltagePlan = new HashMap<>(amplIOFiles.getVoltagePlanOutput().getVoltagePlan()); + this.voltageProfile = new HashMap<>(amplIOFiles.getVoltageProfileOutput().getVoltageProfile()); } public OpenReacStatus getStatus() { @@ -83,16 +83,16 @@ public List getVscModifications() { return vscModifications; } - public Map> getVoltagePlan() { - return voltagePlan; + public Map> getVoltageProfile() { + return voltageProfile; } - public boolean getWarmStat() { - return warmStart; + public boolean isUpdateNetworkWithVoltages() { + return updateNetworkWithVoltages; } - public void setWarmStart(boolean warmStart) { - this.warmStart = warmStart; + public void setUpdateNetworkWithVoltages(boolean updateNetworkWithVoltages) { + this.updateNetworkWithVoltages = updateNetworkWithVoltages; } public List getAllNetworkModifications() { @@ -119,30 +119,45 @@ public void applyAllModifications(Network network) { .filter(RatioTapChangerHolder::hasRatioTapChanger) .map(RatioTapChangerHolder::getRatioTapChanger) .filter(TapChanger::isRegulating) - .forEach(ratioTapChanger -> { - Bus bus = ratioTapChanger.getRegulationTerminal().getBusView().getBus(); - double v = voltagePlan.get(bus.getId()).getFirst(); - ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); - } - ); + .forEach(ratioTapChanger -> Optional.ofNullable(ratioTapChanger.getRegulationTerminal().getBusView().getBus()).ifPresentOrElse( + bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( + busUpdate -> { + double v = busUpdate.getFirst(); + ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); + }, () -> { + throw new IllegalStateException("Voltage result not found for bus " + bus.getId()); + }), + () -> { + throw new IllegalStateException(); + })); // update target of shunts regulating voltage network.getShuntCompensatorStream() .filter(ShuntCompensator::isVoltageRegulatorOn) - .forEach(shuntCompensator -> { - Bus bus = shuntCompensator.getRegulatingTerminal().getBusView().getBus(); - double v = voltagePlan.get(bus.getId()).getFirst(); - shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV()); - }); + .forEach(shuntCompensator -> Optional.ofNullable(shuntCompensator.getRegulatingTerminal().getBusView().getBus()).ifPresentOrElse( + bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( + busUpdate -> { + double v = busUpdate.getFirst(); + shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV()); + }, () -> { + throw new IllegalStateException("Voltage result not found for bus " + bus.getId()); + }), + () -> { + throw new IllegalStateException("Shunt compensator" + shuntCompensator.getId() + "has a null regulating terminal."); + })); // update voltages of the buses - if (getWarmStat()) { - for (var busUpdate : voltagePlan.entrySet()) { - Bus b = network.getBusView().getBus(busUpdate.getKey()); - double v = busUpdate.getValue().getFirst(); - double angle = busUpdate.getValue().getSecond(); - b.setV(v * b.getVoltageLevel().getNominalV()); - b.setAngle(angle); + if (isUpdateNetworkWithVoltages()) { + for (var busUpdate : voltageProfile.entrySet()) { + Optional.ofNullable(network.getBusView().getBus(busUpdate.getKey())).ifPresentOrElse( + bus -> { + double v = busUpdate.getValue().getFirst(); + double angle = busUpdate.getValue().getSecond(); + bus.setV(v * bus.getVoltageLevel().getNominalV()); + bus.setAngle(Math.toDegrees(angle)); + }, () -> { + throw new IllegalStateException("Bus " + busUpdate.getKey() + " not found in the in the network."); + }); } } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltageProfileOutput.java similarity index 82% rename from open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java rename to open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltageProfileOutput.java index 657d04b3..8ace718d 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltagePlanOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/VoltageProfileOutput.java @@ -16,7 +16,7 @@ /** * @author Pierre Arvy */ -public class VoltagePlanOutput extends AbstractNoThrowOutput { +public class VoltageProfileOutput extends AbstractNoThrowOutput { private static final String ELEMENT = "voltages"; public static final int EXPECTED_COLS = 5; @@ -24,10 +24,10 @@ public class VoltagePlanOutput extends AbstractNoThrowOutput { private static final int V_COLUMN_INDEX = 2; private static final int ANGLE_COLUMN_INDEX = 3; - private final Map> voltagePlan = new HashMap<>(); + private final Map> voltageProfile = new HashMap<>(); - public Map> getVoltagePlan() { - return voltagePlan; + public Map> getVoltageProfile() { + return voltageProfile; } @Override @@ -45,7 +45,7 @@ protected void readLine(String[] tokens, StringToIntMapper stringToI String id = AmplIOUtils.removeQuotes(tokens[ID_COLUMN_INDEX]); double v = readDouble(tokens[V_COLUMN_INDEX]); double angle = readDouble(tokens[ANGLE_COLUMN_INDEX]); - voltagePlan.put(id, Pair.of(v, angle)); + voltageProfile.put(id, Pair.of(v, angle)); } @Override diff --git a/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java b/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java new file mode 100644 index 00000000..ef19216a --- /dev/null +++ b/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java @@ -0,0 +1,69 @@ +package com.powsybl.openreac; + +import com.powsybl.ieeecdf.converter.IeeeCdfNetworkFactory; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.RatioTapChanger; +import com.powsybl.openreac.network.ShuntNetworkFactory; +import com.powsybl.openreac.network.VoltageControlNetworkFactory; +import com.powsybl.openreac.parameters.OpenReacAmplIOFiles; +import com.powsybl.openreac.parameters.input.OpenReacParameters; +import com.powsybl.openreac.parameters.output.OpenReacResult; +import com.powsybl.openreac.parameters.output.OpenReacStatus; +import org.junit.jupiter.api.Test; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.HashMap; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class OpenReacResultsTest { + + @Test + void testRegulatingTransformerWithoutVoltageProfile() throws IOException { + Network network = VoltageControlNetworkFactory.createNetworkWithT2wt(); + RatioTapChanger rtc = network.getTwoWindingsTransformer("T2wT").getRatioTapChanger() + .setTargetDeadband(0) + .setRegulating(true); + String regulatedBusId = rtc.getRegulationTerminal().getBusView().getBus().getId(); + + OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); + OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); + IllegalStateException e = assertThrows(IllegalStateException.class, () -> results.applyAllModifications(network)); + assertEquals("Voltage result not found for bus " + regulatedBusId, e.getMessage()); + } + + @Test + void testRegulatingShuntWithoutVoltageProfile() throws IOException { + Network network = ShuntNetworkFactory.create(); + String regulatedBusId = network.getShuntCompensator("SHUNT").getRegulatingTerminal().getBusView().getBus().getId(); + + OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); + OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); + IllegalStateException e = assertThrows(IllegalStateException.class, () -> results.applyAllModifications(network)); + assertEquals("Voltage result not found for bus " + regulatedBusId, e.getMessage()); + } + + @Test + void testWrongVoltageProfile() throws IOException { + Network network = IeeeCdfNetworkFactory.create14(); + OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); + String idBusNotFound = io.getVoltageProfileOutput().getVoltageProfile().keySet().iterator().next(); + OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); + IllegalStateException e = assertThrows(IllegalStateException.class, () -> results.applyAllModifications(network)); + assertEquals("Bus " + idBusNotFound + " not found in the in the network.", e.getMessage()); + } + + private OpenReacAmplIOFiles getIOWithMockVoltageProfile(Network network) throws IOException { + OpenReacAmplIOFiles io = new OpenReacAmplIOFiles(new OpenReacParameters(), network, true); + try (InputStream input = getClass().getResourceAsStream("/mock_outputs/reactiveopf_results_voltages.csv"); + InputStreamReader in = new InputStreamReader(input); + BufferedReader reader = new BufferedReader(in)) { + io.getVoltageProfileOutput().read(reader, null); + } + return io; + } +} diff --git a/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java b/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java index 4ee22b88..91edd507 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java @@ -213,7 +213,7 @@ public void testOutputFileParsing() throws IOException { assertEquals(1, openReacResult.getSvcModifications().size()); assertEquals(1, openReacResult.getVscModifications().size()); assertEquals(7, openReacResult.getGeneratorModifications().size()); - assertEquals(3, openReacResult.getVoltagePlan().size()); + assertEquals(3, openReacResult.getVoltageProfile().size()); assertEquals(82, openReacResult.getIndicators().size()); assertTrue(openReacResult.getReactiveSlacks().isEmpty()); } @@ -339,14 +339,14 @@ void testWarmStart() throws IOException { runAndApplyAllModifications(network, subFolder, parameters, true); assertEquals(119.592, network.getBusBreakerView().getBus("BUS_1").getV()); - assertEquals(0.014, network.getBusBreakerView().getBus("BUS_1").getAngle()); + assertEquals(0.802, network.getBusBreakerView().getBus("BUS_1").getAngle(), 0.001); assertEquals(118.8, network.getBusBreakerView().getBus("BUS_2").getV()); assertEquals(0, network.getBusBreakerView().getBus("BUS_2").getAngle()); assertEquals(22.935, network.getBusBreakerView().getBus("BUS_3").getV()); - assertEquals(-0.082, network.getBusBreakerView().getBus("BUS_3").getAngle()); + assertEquals(-4.698, network.getBusBreakerView().getBus("BUS_3").getAngle(), 0.001); } - private void runAndApplyAllModifications(Network network, String subFolder, OpenReacParameters parameters, boolean warmStart) throws IOException { + private void runAndApplyAllModifications(Network network, String subFolder, OpenReacParameters parameters, boolean updateNetworkWithVoltages) throws IOException { LocalCommandExecutor localCommandExecutor = new TestLocalCommandExecutor( List.of(subFolder + "/reactiveopf_results_generators.csv", subFolder + "/reactiveopf_results_indic.txt", @@ -363,7 +363,7 @@ private void runAndApplyAllModifications(Network network, String subFolder, Open network.getVariantManager().getWorkingVariantId(), parameters, new OpenReacConfig(true), computationManager); assertEquals(OpenReacStatus.OK, openReacResult.getStatus()); - openReacResult.setWarmStart(warmStart); + openReacResult.setUpdateNetworkWithVoltages(updateNetworkWithVoltages); openReacResult.applyAllModifications(network); } } diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltageProfileOutputTest.java similarity index 85% rename from open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java rename to open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltageProfileOutputTest.java index ed2dac2f..74b7689b 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltagePlanOutputTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltageProfileOutputTest.java @@ -11,20 +11,20 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -class VoltagePlanOutputTest { +class VoltageProfileOutputTest { @Test void readTest() throws IOException { - VoltagePlanOutput output = new VoltagePlanOutput(); + VoltageProfileOutput output = new VoltageProfileOutput(); try (InputStream input = getClass().getResourceAsStream("/mock_outputs/reactiveopf_results_voltages.csv"); InputStreamReader in = new InputStreamReader(input); BufferedReader reader = new BufferedReader(in)) { output.read(reader, null); - assertEquals(3, output.getVoltagePlan().size()); - Pair busVoltage1 = output.getVoltagePlan().get("bus1"); - Pair busVoltage2 = output.getVoltagePlan().get("bus2"); - Pair busVoltage3 = output.getVoltagePlan().get("bus3"); + assertEquals(3, output.getVoltageProfile().size()); + Pair busVoltage1 = output.getVoltageProfile().get("bus1"); + Pair busVoltage2 = output.getVoltageProfile().get("bus2"); + Pair busVoltage3 = output.getVoltageProfile().get("bus3"); Assertions.assertAll( () -> assertEquals(0.8, busVoltage1.getFirst()), () -> assertEquals(1.1, busVoltage1.getSecond()), From bace3c3d182fb3d8c7185d23edd81f22410b9676 Mon Sep 17 00:00:00 2001 From: parvy Date: Thu, 25 Jan 2024 15:27:22 +0100 Subject: [PATCH 19/28] refactor mock files. Signed-off-by: parvy --- .../resources/mock_outputs/reactiveopf_results_voltages.csv | 2 +- .../openreac-output-ieee14/reactiveopf_results_voltages.csv | 2 +- .../reactiveopf_results_voltages.csv | 2 +- .../openreac-output-shunt/reactiveopf_results_voltages.csv | 2 +- .../openreac-output-svc/reactiveopf_results_voltages.csv | 2 +- .../openreac-output-transfo/reactiveopf_results_voltages.csv | 2 +- .../openreac-output-vsc/reactiveopf_results_voltages.csv | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/open-reac/src/test/resources/mock_outputs/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/mock_outputs/reactiveopf_results_voltages.csv index 0ab28a0e..c2325da4 100644 --- a/open-reac/src/test/resources/mock_outputs/reactiveopf_results_voltages.csv +++ b/open-reac/src/test/resources/mock_outputs/reactiveopf_results_voltages.csv @@ -1,4 +1,4 @@ -#variant;bus;V;angle;id; +#variant;bus;V(pu);theta(rad);id; 1;1;0.8;1.1;'bus1'; 1;2;1.2;-99999;'bus2'; 1;1;-99999;0.11;'bus3'; diff --git a/open-reac/src/test/resources/openreac-output-ieee14/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/openreac-output-ieee14/reactiveopf_results_voltages.csv index b4453c67..58d56b24 100644 --- a/open-reac/src/test/resources/openreac-output-ieee14/reactiveopf_results_voltages.csv +++ b/open-reac/src/test/resources/openreac-output-ieee14/reactiveopf_results_voltages.csv @@ -1,4 +1,4 @@ -#variant;bus;V;theta;id; +#variant;bus;V(pu);theta(rad);id; 1;1;1.083;0.168;"VL1_0"; 1;2;1.045;0.089;"VL2_0"; 1;3;0.971;-0.042;"VL3_0"; diff --git a/open-reac/src/test/resources/openreac-output-real-network/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/openreac-output-real-network/reactiveopf_results_voltages.csv index dcc50f40..52ca94d3 100644 --- a/open-reac/src/test/resources/openreac-output-real-network/reactiveopf_results_voltages.csv +++ b/open-reac/src/test/resources/openreac-output-real-network/reactiveopf_results_voltages.csv @@ -1,4 +1,4 @@ -#variant;bus;V;theta;id; +#variant;bus;V(pu);theta(rad);id; 1;1;1.393;0.040;"VL1_0"; 1;2;1.382;0.040;"VL2_0"; 1;3;1.390;0.032;"VL3_0"; diff --git a/open-reac/src/test/resources/openreac-output-shunt/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/openreac-output-shunt/reactiveopf_results_voltages.csv index d46d1c5c..d6f739bd 100644 --- a/open-reac/src/test/resources/openreac-output-shunt/reactiveopf_results_voltages.csv +++ b/open-reac/src/test/resources/openreac-output-shunt/reactiveopf_results_voltages.csv @@ -1,4 +1,4 @@ -#variant;bus;V;theta;id; +#variant;bus;V(pu);theta(rad);id; 1;1;1.050;0.002;"vl1_0"; 1;2;1.049;0.000;"vl2_0"; 1;3;1.052;-0.001;"vl3_0"; diff --git a/open-reac/src/test/resources/openreac-output-svc/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/openreac-output-svc/reactiveopf_results_voltages.csv index 98063dc6..e9648927 100644 --- a/open-reac/src/test/resources/openreac-output-svc/reactiveopf_results_voltages.csv +++ b/open-reac/src/test/resources/openreac-output-svc/reactiveopf_results_voltages.csv @@ -1,3 +1,3 @@ -#variant;bus;V;theta;id; +#variant;bus;V(pu);theta(rad);id; 1;1;1.050;0.002;"vl1_0"; 1;2;1.049;0.000;"vl2_0"; diff --git a/open-reac/src/test/resources/openreac-output-transfo/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/openreac-output-transfo/reactiveopf_results_voltages.csv index 32e404c4..38af3a57 100644 --- a/open-reac/src/test/resources/openreac-output-transfo/reactiveopf_results_voltages.csv +++ b/open-reac/src/test/resources/openreac-output-transfo/reactiveopf_results_voltages.csv @@ -1,4 +1,4 @@ -#variant;bus;V;theta;id; +#variant;bus;V(pu);theta(rad);id; 1;1;0.906;0.014;"VL_1_0"; 1;2;0.900;0.000;"VL_2_0"; 1;3;0.695;-0.082;"VL_3_0"; diff --git a/open-reac/src/test/resources/openreac-output-vsc/reactiveopf_results_voltages.csv b/open-reac/src/test/resources/openreac-output-vsc/reactiveopf_results_voltages.csv index 0aa3b336..7859766f 100644 --- a/open-reac/src/test/resources/openreac-output-vsc/reactiveopf_results_voltages.csv +++ b/open-reac/src/test/resources/openreac-output-vsc/reactiveopf_results_voltages.csv @@ -1,4 +1,4 @@ -#variant;bus;V;theta;id; +#variant;bus;V(pu);theta(rad);id; 1;1;0.568;-0.707;"b1_vl_0"; 1;2;0.500;-0.927;"b2_vl_0"; 1;3;0.651;-0.810;"b3_vl_0"; From c4d80124c46b166a02c5f27f902d17a082efcc55 Mon Sep 17 00:00:00 2001 From: parvy Date: Thu, 25 Jan 2024 15:43:47 +0100 Subject: [PATCH 20/28] add TU for missing regulated bus. Signed-off-by: parvy --- .../parameters/output/OpenReacResult.java | 4 +-- .../powsybl/openreac/OpenReacResultsTest.java | 36 ++++++++++++++++--- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index da467c7e..602a6ada 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -128,7 +128,7 @@ public void applyAllModifications(Network network) { throw new IllegalStateException("Voltage result not found for bus " + bus.getId()); }), () -> { - throw new IllegalStateException(); + throw new IllegalStateException("No bus found for regulating ratio tap changer."); })); // update target of shunts regulating voltage @@ -143,7 +143,7 @@ public void applyAllModifications(Network network) { throw new IllegalStateException("Voltage result not found for bus " + bus.getId()); }), () -> { - throw new IllegalStateException("Shunt compensator" + shuntCompensator.getId() + "has a null regulating terminal."); + throw new IllegalStateException("No bus found for regulating shunt compensator " + shuntCompensator.getId()); })); // update voltages of the buses diff --git a/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java b/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java index ef19216a..1dcb2f62 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java @@ -3,6 +3,7 @@ import com.powsybl.ieeecdf.converter.IeeeCdfNetworkFactory; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.RatioTapChanger; +import com.powsybl.iidm.network.ShuntCompensator; import com.powsybl.openreac.network.ShuntNetworkFactory; import com.powsybl.openreac.network.VoltageControlNetworkFactory; import com.powsybl.openreac.parameters.OpenReacAmplIOFiles; @@ -23,7 +24,7 @@ class OpenReacResultsTest { @Test - void testRegulatingTransformerWithoutVoltageProfile() throws IOException { + void testTransformerWithoutVoltageResult() throws IOException { Network network = VoltageControlNetworkFactory.createNetworkWithT2wt(); RatioTapChanger rtc = network.getTwoWindingsTransformer("T2wT").getRatioTapChanger() .setTargetDeadband(0) @@ -37,9 +38,24 @@ void testRegulatingTransformerWithoutVoltageProfile() throws IOException { } @Test - void testRegulatingShuntWithoutVoltageProfile() throws IOException { + void testTransformerWithNullBus() throws IOException { + Network network = VoltageControlNetworkFactory.createNetworkWithT2wt(); + RatioTapChanger rtc = network.getTwoWindingsTransformer("T2wT").getRatioTapChanger() + .setTargetDeadband(0) + .setRegulating(true); + rtc.getRegulationTerminal().disconnect(); + + OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); + OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); + IllegalStateException e = assertThrows(IllegalStateException.class, () -> results.applyAllModifications(network)); + assertEquals("No bus found for regulating ratio tap changer.", e.getMessage()); + } + + @Test + void testShuntWithoutVoltageResult() throws IOException { Network network = ShuntNetworkFactory.create(); - String regulatedBusId = network.getShuntCompensator("SHUNT").getRegulatingTerminal().getBusView().getBus().getId(); + ShuntCompensator shunt = network.getShuntCompensator("SHUNT"); + String regulatedBusId = shunt.getRegulatingTerminal().getBusView().getBus().getId(); OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); @@ -48,7 +64,19 @@ void testRegulatingShuntWithoutVoltageProfile() throws IOException { } @Test - void testWrongVoltageProfile() throws IOException { + void testShuntWithNullBus() throws IOException { + Network network = ShuntNetworkFactory.create(); + ShuntCompensator shunt = network.getShuntCompensator("SHUNT"); + shunt.getRegulatingTerminal().disconnect(); + + OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); + OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); + IllegalStateException e = assertThrows(IllegalStateException.class, () -> results.applyAllModifications(network)); + assertEquals("No bus found for regulating shunt compensator " + shunt.getId(), e.getMessage()); + } + + @Test + void testWrongVoltageResult() throws IOException { Network network = IeeeCdfNetworkFactory.create14(); OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); String idBusNotFound = io.getVoltageProfileOutput().getVoltageProfile().keySet().iterator().next(); From 504f6f5499d26b011b1fbc60e7172b03b8709eeb Mon Sep 17 00:00:00 2001 From: parvy Date: Thu, 25 Jan 2024 17:15:38 +0100 Subject: [PATCH 21/28] wip. Signed-off-by: parvy --- .../parameters/output/OpenReacResult.java | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index 602a6ada..78d34952 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -12,6 +12,8 @@ import com.powsybl.openreac.parameters.OpenReacAmplIOFiles; import com.powsybl.openreac.parameters.output.ReactiveSlackOutput.ReactiveSlack; import org.jgrapht.alg.util.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.*; @@ -22,6 +24,7 @@ */ public class OpenReacResult { + private static final Logger LOGGER = LoggerFactory.getLogger(OpenReacResult.class); private final OpenReacStatus status; private final List reactiveSlacks; private final Map indicators; @@ -119,17 +122,18 @@ public void applyAllModifications(Network network) { .filter(RatioTapChangerHolder::hasRatioTapChanger) .map(RatioTapChangerHolder::getRatioTapChanger) .filter(TapChanger::isRegulating) - .forEach(ratioTapChanger -> Optional.ofNullable(ratioTapChanger.getRegulationTerminal().getBusView().getBus()).ifPresentOrElse( - bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( - busUpdate -> { - double v = busUpdate.getFirst(); - ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); - }, () -> { - throw new IllegalStateException("Voltage result not found for bus " + bus.getId()); - }), - () -> { - throw new IllegalStateException("No bus found for regulating ratio tap changer."); - })); + .forEach(ratioTapChanger -> Optional.ofNullable(ratioTapChanger.getRegulationTerminal()).ifPresentOrElse( + regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( + bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( + busUpdate -> { + LOGGER.warn("TODO"); + double v = busUpdate.getFirst(); + ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); + }, () -> { + throw new IllegalStateException("Voltage result not found for bus " + bus.getId()); + }), + () -> LOGGER.warn("TODO")), + () -> LOGGER.warn("TODO"))); // update target of shunts regulating voltage network.getShuntCompensatorStream() From 03eb0a246c6ec6f3a72d8b02874f39146f1acccf Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 31 Jan 2024 17:54:14 +0100 Subject: [PATCH 22/28] Add log when bus/regulation terminal is null. Signed-off-by: parvy --- .../parameters/output/OpenReacResult.java | 31 +++++++++--------- .../powsybl/openreac/OpenReacResultsTest.java | 32 ++++++++++++------- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index 78d34952..f90b014f 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -126,29 +126,28 @@ public void applyAllModifications(Network network) { regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( busUpdate -> { - LOGGER.warn("TODO"); double v = busUpdate.getFirst(); ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); }, () -> { - throw new IllegalStateException("Voltage result not found for bus " + bus.getId()); + throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); }), - () -> LOGGER.warn("TODO")), - () -> LOGGER.warn("TODO"))); + () -> LOGGER.warn("Bus of regulation terminal is null.")), + () -> LOGGER.warn("Regulation terminal of ratio tap changer is null."))); // update target of shunts regulating voltage network.getShuntCompensatorStream() .filter(ShuntCompensator::isVoltageRegulatorOn) - .forEach(shuntCompensator -> Optional.ofNullable(shuntCompensator.getRegulatingTerminal().getBusView().getBus()).ifPresentOrElse( - bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( - busUpdate -> { - double v = busUpdate.getFirst(); - shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV()); - }, () -> { - throw new IllegalStateException("Voltage result not found for bus " + bus.getId()); - }), - () -> { - throw new IllegalStateException("No bus found for regulating shunt compensator " + shuntCompensator.getId()); - })); + .forEach(shuntCompensator -> Optional.ofNullable(shuntCompensator.getRegulatingTerminal()).ifPresentOrElse( + regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( + bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( + busUpdate -> { + double v = busUpdate.getFirst(); + shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV()); + }, () -> { + throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); + }), + () -> LOGGER.warn("Bus of regulation terminal is null.")), + () -> LOGGER.warn("Regulating terminal of shunt compensator {} is null.", shuntCompensator.getId()))); // update voltages of the buses if (isUpdateNetworkWithVoltages()) { @@ -160,7 +159,7 @@ public void applyAllModifications(Network network) { bus.setV(v * bus.getVoltageLevel().getNominalV()); bus.setAngle(Math.toDegrees(angle)); }, () -> { - throw new IllegalStateException("Bus " + busUpdate.getKey() + " not found in the in the network."); + throw new IllegalStateException("Bus " + busUpdate.getKey() + " not found in network " + network.getId()); }); } } diff --git a/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java b/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java index 1dcb2f62..9ee7e097 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java @@ -24,7 +24,7 @@ class OpenReacResultsTest { @Test - void testTransformerWithoutVoltageResult() throws IOException { + void testTransformerUpdateWithoutVoltageResult() throws IOException { Network network = VoltageControlNetworkFactory.createNetworkWithT2wt(); RatioTapChanger rtc = network.getTwoWindingsTransformer("T2wT").getRatioTapChanger() .setTargetDeadband(0) @@ -34,11 +34,11 @@ void testTransformerWithoutVoltageResult() throws IOException { OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); IllegalStateException e = assertThrows(IllegalStateException.class, () -> results.applyAllModifications(network)); - assertEquals("Voltage result not found for bus " + regulatedBusId, e.getMessage()); + assertEquals("Voltage profile not found for bus " + regulatedBusId, e.getMessage()); } @Test - void testTransformerWithNullBus() throws IOException { + void testTransformerUpdateWithNullRegulatedBus() throws IOException { Network network = VoltageControlNetworkFactory.createNetworkWithT2wt(); RatioTapChanger rtc = network.getTwoWindingsTransformer("T2wT").getRatioTapChanger() .setTargetDeadband(0) @@ -47,12 +47,17 @@ void testTransformerWithNullBus() throws IOException { OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); - IllegalStateException e = assertThrows(IllegalStateException.class, () -> results.applyAllModifications(network)); - assertEquals("No bus found for regulating ratio tap changer.", e.getMessage()); + + // apply results without warm start + results.setUpdateNetworkWithVoltages(false); + results.applyAllModifications(network); + + // target V not updated + assertEquals(33, rtc.getTargetV()); } @Test - void testShuntWithoutVoltageResult() throws IOException { + void testShuntUpdateWithoutVoltageResult() throws IOException { Network network = ShuntNetworkFactory.create(); ShuntCompensator shunt = network.getShuntCompensator("SHUNT"); String regulatedBusId = shunt.getRegulatingTerminal().getBusView().getBus().getId(); @@ -60,19 +65,24 @@ void testShuntWithoutVoltageResult() throws IOException { OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); IllegalStateException e = assertThrows(IllegalStateException.class, () -> results.applyAllModifications(network)); - assertEquals("Voltage result not found for bus " + regulatedBusId, e.getMessage()); + assertEquals("Voltage profile not found for bus " + regulatedBusId, e.getMessage()); } @Test - void testShuntWithNullBus() throws IOException { + void testShuntUpdateWithNullRegulatedBus() throws IOException { Network network = ShuntNetworkFactory.create(); ShuntCompensator shunt = network.getShuntCompensator("SHUNT"); shunt.getRegulatingTerminal().disconnect(); OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); - IllegalStateException e = assertThrows(IllegalStateException.class, () -> results.applyAllModifications(network)); - assertEquals("No bus found for regulating shunt compensator " + shunt.getId(), e.getMessage()); + + // apply results without warm start + results.setUpdateNetworkWithVoltages(false); + results.applyAllModifications(network); + + // target V not updated + assertEquals(393, shunt.getTargetV()); } @Test @@ -82,7 +92,7 @@ void testWrongVoltageResult() throws IOException { String idBusNotFound = io.getVoltageProfileOutput().getVoltageProfile().keySet().iterator().next(); OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); IllegalStateException e = assertThrows(IllegalStateException.class, () -> results.applyAllModifications(network)); - assertEquals("Bus " + idBusNotFound + " not found in the in the network.", e.getMessage()); + assertEquals("Bus " + idBusNotFound + " not found in network " + network.getId(), e.getMessage()); } private OpenReacAmplIOFiles getIOWithMockVoltageProfile(Network network) throws IOException { From ae63972e6e31162a382fb6683b872ce350794ddc Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 31 Jan 2024 18:07:05 +0100 Subject: [PATCH 23/28] improve coverage. Signed-off-by: parvy --- .../parameters/output/VoltageProfileOutputTest.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltageProfileOutputTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltageProfileOutputTest.java index 74b7689b..45f31e26 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltageProfileOutputTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/VoltageProfileOutputTest.java @@ -9,7 +9,7 @@ import java.io.InputStream; import java.io.InputStreamReader; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.*; class VoltageProfileOutputTest { @@ -35,4 +35,12 @@ void readTest() throws IOException { ); } } + + @Test + void testErrorState() { + VoltageProfileOutput output = new VoltageProfileOutput(); + boolean throwOnMissingFile = output.throwOnMissingFile(); + assertFalse(throwOnMissingFile); + assertTrue(output.isErrorState()); + } } From 0bc03144e05ab64b6e6e35bd217363a9c44fdb67 Mon Sep 17 00:00:00 2001 From: parvy Date: Thu, 1 Feb 2024 12:42:52 +0100 Subject: [PATCH 24/28] keep same changes but on modifiable tap changers/shunts. Signed-off-by: parvy --- .../parameters/output/OpenReacResult.java | 67 ++++++++++--------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index f90b014f..7e7669c3 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -7,6 +7,7 @@ package com.powsybl.openreac.parameters.output; import com.powsybl.iidm.modification.*; +import com.powsybl.iidm.modification.tapchanger.AbstractTapPositionModification; import com.powsybl.iidm.modification.tapchanger.RatioTapPositionModification; import com.powsybl.iidm.network.*; import com.powsybl.openreac.parameters.OpenReacAmplIOFiles; @@ -117,37 +118,41 @@ public void applyAllModifications(Network network) { modif.apply(network); } - // update target of ratio tap changers regulating voltage - network.getTwoWindingsTransformerStream() - .filter(RatioTapChangerHolder::hasRatioTapChanger) - .map(RatioTapChangerHolder::getRatioTapChanger) - .filter(TapChanger::isRegulating) - .forEach(ratioTapChanger -> Optional.ofNullable(ratioTapChanger.getRegulationTerminal()).ifPresentOrElse( - regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( - bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( - busUpdate -> { - double v = busUpdate.getFirst(); - ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); - }, () -> { - throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); - }), - () -> LOGGER.warn("Bus of regulation terminal is null.")), - () -> LOGGER.warn("Regulation terminal of ratio tap changer is null."))); - - // update target of shunts regulating voltage - network.getShuntCompensatorStream() - .filter(ShuntCompensator::isVoltageRegulatorOn) - .forEach(shuntCompensator -> Optional.ofNullable(shuntCompensator.getRegulatingTerminal()).ifPresentOrElse( - regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( - bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( - busUpdate -> { - double v = busUpdate.getFirst(); - shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV()); - }, () -> { - throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); - }), - () -> LOGGER.warn("Bus of regulation terminal is null.")), - () -> LOGGER.warn("Regulating terminal of shunt compensator {} is null.", shuntCompensator.getId()))); + // update target of ratio tap changers specified as variable by user + getTapPositionModifications().stream() + .map(AbstractTapPositionModification::getTransformerId) + .forEach(transformerId -> Optional.ofNullable(network.getTwoWindingsTransformer(transformerId)).ifPresentOrElse( + transformer -> Optional.ofNullable(transformer.getRatioTapChanger()).ifPresentOrElse( + ratioTapChanger -> Optional.ofNullable(ratioTapChanger.getRegulationTerminal()).ifPresentOrElse( + regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( + bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( + busUpdate -> { + double v = busUpdate.getFirst(); + ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); + }, () -> { + throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); + }), + () -> LOGGER.warn("Bus of regulation terminal is null.")), + () -> LOGGER.warn("Regulation terminal of ratio tap changer is null.")), + () -> LOGGER.warn("Transformer {} has no ratio tap changer", transformerId)), + () -> LOGGER.warn("Network {} has no transformer with id {}", network.getId(), transformerId))); + + // update target of shunts specified as variable by user + getShuntsModifications().stream() + .map(ShuntCompensatorModification::getShuntCompensatorId) + .forEach(id -> Optional.ofNullable(network.getShuntCompensator(id)).ifPresentOrElse( + shuntCompensator -> Optional.ofNullable(shuntCompensator.getRegulatingTerminal()).ifPresentOrElse( + regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( + bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( + busUpdate -> { + double v = busUpdate.getFirst(); + shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV()); + }, () -> { + throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); + }), + () -> LOGGER.warn("Bus of regulation terminal is null.")), + () -> LOGGER.warn("Regulating terminal of shunt compensator {} is null.", id)), + () -> LOGGER.warn("Network {} has no shunt compensator with id {}", network.getId(), id))); // update voltages of the buses if (isUpdateNetworkWithVoltages()) { From e49f9aae2b9d44a127b7918a9a7a1b667afbc1d1 Mon Sep 17 00:00:00 2001 From: parvy Date: Thu, 1 Feb 2024 16:13:45 +0100 Subject: [PATCH 25/28] refactor. Signed-off-by: parvy --- .../parameters/output/OpenReacResult.java | 12 ++++--- .../powsybl/openreac/OpenReacResultsTest.java | 35 ++++++++++++------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index 7e7669c3..5ba251f6 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -127,8 +127,10 @@ public void applyAllModifications(Network network) { regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( busUpdate -> { - double v = busUpdate.getFirst(); - ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); + if (!Double.isNaN(ratioTapChanger.getTargetV())) { + double v = busUpdate.getFirst(); + ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); + } }, () -> { throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); }), @@ -145,8 +147,10 @@ public void applyAllModifications(Network network) { regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( busUpdate -> { - double v = busUpdate.getFirst(); - shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV()); + if (!Double.isNaN(shuntCompensator.getTargetV())) { + double v = busUpdate.getFirst(); + shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV()); + } }, () -> { throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); }), diff --git a/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java b/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java index 9ee7e097..0ef57e52 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/OpenReacResultsTest.java @@ -1,6 +1,8 @@ package com.powsybl.openreac; import com.powsybl.ieeecdf.converter.IeeeCdfNetworkFactory; +import com.powsybl.iidm.modification.ShuntCompensatorModification; +import com.powsybl.iidm.modification.tapchanger.RatioTapPositionModification; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.RatioTapChanger; import com.powsybl.iidm.network.ShuntCompensator; @@ -24,60 +26,69 @@ class OpenReacResultsTest { @Test - void testTransformerUpdateWithoutVoltageResult() throws IOException { + void testTransformerTargetVUpdateWithoutVoltageResult() throws IOException { Network network = VoltageControlNetworkFactory.createNetworkWithT2wt(); - RatioTapChanger rtc = network.getTwoWindingsTransformer("T2wT").getRatioTapChanger() + String t2wtId = "T2wT"; + RatioTapChanger rtc = network.getTwoWindingsTransformer(t2wtId).getRatioTapChanger() .setTargetDeadband(0) .setRegulating(true); - String regulatedBusId = rtc.getRegulationTerminal().getBusView().getBus().getId(); + // add transformer as variable for target V update OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); + io.getNetworkModifications().getTapPositionModifications().add(new RatioTapPositionModification(t2wtId, 0)); + OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); IllegalStateException e = assertThrows(IllegalStateException.class, () -> results.applyAllModifications(network)); - assertEquals("Voltage profile not found for bus " + regulatedBusId, e.getMessage()); + assertEquals("Voltage profile not found for bus " + rtc.getRegulationTerminal().getBusView().getBus().getId(), e.getMessage()); } @Test - void testTransformerUpdateWithNullRegulatedBus() throws IOException { + void testTransformerTargetVUpdateWithoutRegulationBus() throws IOException { Network network = VoltageControlNetworkFactory.createNetworkWithT2wt(); - RatioTapChanger rtc = network.getTwoWindingsTransformer("T2wT").getRatioTapChanger() + String t2wtId = "T2wT"; + RatioTapChanger rtc = network.getTwoWindingsTransformer(t2wtId).getRatioTapChanger() .setTargetDeadband(0) .setRegulating(true); rtc.getRegulationTerminal().disconnect(); + // add transformer as variable for target V update OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); - OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); + io.getNetworkModifications().getTapPositionModifications().add(new RatioTapPositionModification(t2wtId, 0)); - // apply results without warm start + // apply results without warm start (to avoid exception) + OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); results.setUpdateNetworkWithVoltages(false); results.applyAllModifications(network); - // target V not updated + // target V is not updated assertEquals(33, rtc.getTargetV()); } @Test - void testShuntUpdateWithoutVoltageResult() throws IOException { + void testShuntTargetVUpdateWithoutVoltageResult() throws IOException { Network network = ShuntNetworkFactory.create(); ShuntCompensator shunt = network.getShuntCompensator("SHUNT"); String regulatedBusId = shunt.getRegulatingTerminal().getBusView().getBus().getId(); OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); + io.getNetworkModifications().getShuntModifications().add(new ShuntCompensatorModification("SHUNT", true, 0)); + OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); IllegalStateException e = assertThrows(IllegalStateException.class, () -> results.applyAllModifications(network)); assertEquals("Voltage profile not found for bus " + regulatedBusId, e.getMessage()); } @Test - void testShuntUpdateWithNullRegulatedBus() throws IOException { + void testShuntUpdateWithoutRegulationBus() throws IOException { Network network = ShuntNetworkFactory.create(); ShuntCompensator shunt = network.getShuntCompensator("SHUNT"); shunt.getRegulatingTerminal().disconnect(); OpenReacAmplIOFiles io = getIOWithMockVoltageProfile(network); - OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); + io.getNetworkModifications().getShuntModifications().add(new ShuntCompensatorModification("SHUNT", null, 0)); // apply results without warm start + OpenReacResult results = new OpenReacResult(OpenReacStatus.OK, io, new HashMap<>()); results.setUpdateNetworkWithVoltages(false); results.applyAllModifications(network); From 810b10f61b40d9281ac6c21a1004b962a7d76f9d Mon Sep 17 00:00:00 2001 From: parvy Date: Thu, 1 Feb 2024 16:33:36 +0100 Subject: [PATCH 26/28] fix codesmell. Signed-off-by: parvy --- .../parameters/output/OpenReacResult.java | 62 +++++++++---------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index 5ba251f6..c14ccdd2 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -121,42 +121,40 @@ public void applyAllModifications(Network network) { // update target of ratio tap changers specified as variable by user getTapPositionModifications().stream() .map(AbstractTapPositionModification::getTransformerId) - .forEach(transformerId -> Optional.ofNullable(network.getTwoWindingsTransformer(transformerId)).ifPresentOrElse( - transformer -> Optional.ofNullable(transformer.getRatioTapChanger()).ifPresentOrElse( - ratioTapChanger -> Optional.ofNullable(ratioTapChanger.getRegulationTerminal()).ifPresentOrElse( - regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( - bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( - busUpdate -> { - if (!Double.isNaN(ratioTapChanger.getTargetV())) { - double v = busUpdate.getFirst(); - ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); - } - }, () -> { - throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); - }), - () -> LOGGER.warn("Bus of regulation terminal is null.")), - () -> LOGGER.warn("Regulation terminal of ratio tap changer is null.")), - () -> LOGGER.warn("Transformer {} has no ratio tap changer", transformerId)), - () -> LOGGER.warn("Network {} has no transformer with id {}", network.getId(), transformerId))); + .map(network::getTwoWindingsTransformer) + .forEach(transformer -> Optional.ofNullable(transformer.getRatioTapChanger()).ifPresentOrElse( + ratioTapChanger -> Optional.ofNullable(ratioTapChanger.getRegulationTerminal()).ifPresentOrElse( + regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( + bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( + busUpdate -> { + if (!Double.isNaN(ratioTapChanger.getTargetV())) { + double v = busUpdate.getFirst(); + ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); + } + }, () -> { + throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); + }), + () -> LOGGER.warn("Bus of regulation terminal is null.")), + () -> LOGGER.warn("Regulation terminal of ratio tap changer is null.")), + () -> LOGGER.warn("Transformer {} has no ratio tap changer.", transformer.getId()))); // update target of shunts specified as variable by user getShuntsModifications().stream() .map(ShuntCompensatorModification::getShuntCompensatorId) - .forEach(id -> Optional.ofNullable(network.getShuntCompensator(id)).ifPresentOrElse( - shuntCompensator -> Optional.ofNullable(shuntCompensator.getRegulatingTerminal()).ifPresentOrElse( - regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( - bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( - busUpdate -> { - if (!Double.isNaN(shuntCompensator.getTargetV())) { - double v = busUpdate.getFirst(); - shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV()); - } - }, () -> { - throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); - }), - () -> LOGGER.warn("Bus of regulation terminal is null.")), - () -> LOGGER.warn("Regulating terminal of shunt compensator {} is null.", id)), - () -> LOGGER.warn("Network {} has no shunt compensator with id {}", network.getId(), id))); + .map(network::getShuntCompensator) + .forEach(shuntCompensator -> Optional.ofNullable(shuntCompensator.getRegulatingTerminal()).ifPresentOrElse( + regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( + bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( + busUpdate -> { + if (!Double.isNaN(shuntCompensator.getTargetV())) { + double v = busUpdate.getFirst(); + shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV()); + } + }, () -> { + throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); + }), + () -> LOGGER.warn("Bus of regulation terminal is null.")), + () -> LOGGER.warn("Regulating terminal of shunt compensator {} is null.", shuntCompensator.getId()))); // update voltages of the buses if (isUpdateNetworkWithVoltages()) { From 4d192d2f0e01265f781aa9367dcfbb4b90d26fa4 Mon Sep 17 00:00:00 2001 From: parvy Date: Thu, 1 Feb 2024 17:16:11 +0100 Subject: [PATCH 27/28] remove restriction on target V update. Signed-off-by: parvy --- .../openreac/parameters/output/OpenReacResult.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index c14ccdd2..b909d029 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -127,10 +127,8 @@ public void applyAllModifications(Network network) { regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( busUpdate -> { - if (!Double.isNaN(ratioTapChanger.getTargetV())) { - double v = busUpdate.getFirst(); - ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); - } + double v = busUpdate.getFirst(); + ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); }, () -> { throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); }), @@ -146,10 +144,8 @@ public void applyAllModifications(Network network) { regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( busUpdate -> { - if (!Double.isNaN(shuntCompensator.getTargetV())) { - double v = busUpdate.getFirst(); - shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV()); - } + double v = busUpdate.getFirst(); + shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV()); }, () -> { throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); }), From 24704ce646476c63f23a6b650872bfebea3ceaf3 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Mon, 5 Feb 2024 14:50:45 +0100 Subject: [PATCH 28/28] Rework to clarify. Signed-off-by: Anne Tilloy --- .../parameters/output/OpenReacResult.java | 70 +++++++++++-------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java index b909d029..361df858 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/OpenReacResult.java @@ -120,37 +120,38 @@ public void applyAllModifications(Network network) { // update target of ratio tap changers specified as variable by user getTapPositionModifications().stream() - .map(AbstractTapPositionModification::getTransformerId) - .map(network::getTwoWindingsTransformer) - .forEach(transformer -> Optional.ofNullable(transformer.getRatioTapChanger()).ifPresentOrElse( - ratioTapChanger -> Optional.ofNullable(ratioTapChanger.getRegulationTerminal()).ifPresentOrElse( - regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( - bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( - busUpdate -> { - double v = busUpdate.getFirst(); - ratioTapChanger.setTargetV(v * bus.getVoltageLevel().getNominalV()); - }, () -> { - throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); - }), - () -> LOGGER.warn("Bus of regulation terminal is null.")), - () -> LOGGER.warn("Regulation terminal of ratio tap changer is null.")), - () -> LOGGER.warn("Transformer {} has no ratio tap changer.", transformer.getId()))); + .map(AbstractTapPositionModification::getTransformerId) + .map(network::getTwoWindingsTransformer) + .forEach(transformer -> { + RatioTapChanger ratioTapChanger = transformer.getRatioTapChanger(); + if (ratioTapChanger != null) { + Optional bus = getRegulatingBus(ratioTapChanger.getRegulationTerminal(), transformer.getId()); + bus.ifPresent(b -> { + Pair busUpdate = voltageProfile.get(b.getId()); + if (busUpdate != null) { + ratioTapChanger.setTargetV(busUpdate.getFirst() * b.getVoltageLevel().getNominalV()); + } else { + throw new IllegalStateException("Voltage profile not found for bus " + b.getId()); + } + }); + } + }); // update target of shunts specified as variable by user getShuntsModifications().stream() - .map(ShuntCompensatorModification::getShuntCompensatorId) - .map(network::getShuntCompensator) - .forEach(shuntCompensator -> Optional.ofNullable(shuntCompensator.getRegulatingTerminal()).ifPresentOrElse( - regulationTerminal -> Optional.ofNullable(regulationTerminal.getBusView().getBus()).ifPresentOrElse( - bus -> Optional.ofNullable(voltageProfile.get(bus.getId())).ifPresentOrElse( - busUpdate -> { - double v = busUpdate.getFirst(); - shuntCompensator.setTargetV(v * bus.getVoltageLevel().getNominalV()); - }, () -> { - throw new IllegalStateException("Voltage profile not found for bus " + bus.getId()); - }), - () -> LOGGER.warn("Bus of regulation terminal is null.")), - () -> LOGGER.warn("Regulating terminal of shunt compensator {} is null.", shuntCompensator.getId()))); + .map(ShuntCompensatorModification::getShuntCompensatorId) + .map(network::getShuntCompensator) + .forEach(shunt -> { + Optional bus = getRegulatingBus(shunt.getRegulatingTerminal(), shunt.getId()); + bus.ifPresent(b -> { + Pair busUpdate = voltageProfile.get(b.getId()); + if (busUpdate != null) { + shunt.setTargetV(busUpdate.getFirst() * b.getVoltageLevel().getNominalV()); + } else { + throw new IllegalStateException("Voltage profile not found for bus " + b.getId()); + } + }); + }); // update voltages of the buses if (isUpdateNetworkWithVoltages()) { @@ -167,4 +168,17 @@ public void applyAllModifications(Network network) { } } } + + Optional getRegulatingBus(Terminal terminal, String elementId) { + if (terminal == null) { + LOGGER.warn("Regulating terminal of element {} is null.", elementId); + return Optional.empty(); + } + Bus bus = terminal.getBusView().getBus(); + if (bus == null) { + LOGGER.warn("Bus of regulating terminal of element {} is null.", elementId); + return Optional.empty(); + } + return Optional.ofNullable(bus); + } }