diff --git a/open-reac/pom.xml b/open-reac/pom.xml index 44bcf018..def38356 100644 --- a/open-reac/pom.xml +++ b/open-reac/pom.xml @@ -22,8 +22,8 @@ OpenReac optimizer - 5.3.2 - 1.2.1 + 6.0.1 + 1.3.0 diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/AbstractElementsInput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/AbstractElementsInput.java index f62a7aae..34832d39 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/AbstractElementsInput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/AbstractElementsInput.java @@ -11,9 +11,8 @@ import com.powsybl.commons.util.StringToIntMapper; import com.powsybl.openreac.parameters.AmplIOUtils; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; +import java.io.BufferedWriter; +import java.io.IOException; import java.util.List; /** @@ -28,18 +27,17 @@ protected AbstractElementsInput(List elementIds) { } @Override - public InputStream getParameterFileAsStream(StringToIntMapper stringToIntMapper) { - StringBuilder dataBuilder = new StringBuilder(); - dataBuilder.append("#amplId powsyblId\n"); + public void write(BufferedWriter writer, StringToIntMapper stringToIntMapper) throws IOException { + writer.write("#amplId powsyblId\n"); for (String elementID : elementIds) { int amplId = stringToIntMapper.getInt(getElementAmplSubset(), elementID); String[] tokens = {Integer.toString(amplId), AmplIOUtils.addQuotes(elementID)}; - dataBuilder.append(String.join(" ", tokens)); - dataBuilder.append(System.lineSeparator()); + writer.write(String.join(" ", tokens)); + writer.newLine(); } //add new line at the end of the file ! - dataBuilder.append("\n"); - return new ByteArrayInputStream(dataBuilder.toString().getBytes(StandardCharsets.UTF_8)); + writer.newLine(); + writer.flush(); } abstract AmplSubset getElementAmplSubset(); diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLevelLimitsOverrideInput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLevelLimitsOverrideInput.java index dbae0ad1..adfacd64 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLevelLimitsOverrideInput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLevelLimitsOverrideInput.java @@ -13,9 +13,8 @@ import com.powsybl.openreac.exceptions.InvalidParametersException; import org.jgrapht.alg.util.Pair; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; +import java.io.BufferedWriter; +import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -75,10 +74,9 @@ public String getFileName() { } @Override - public InputStream getParameterFileAsStream(StringToIntMapper stringToIntMapper) { - StringBuilder dataBuilder = new StringBuilder(); - dataBuilder.append("#num minV (pu) maxV (pu) id"); - dataBuilder.append(System.lineSeparator()); + public void write(BufferedWriter writer, StringToIntMapper stringToIntMapper) throws IOException { + writer.write("#num minV (pu) maxV (pu) id"); + writer.newLine(); for (Map.Entry> entry : normalizedVoltageLimitsOverride.entrySet()) { String voltageLevelId = entry.getKey(); @@ -87,13 +85,13 @@ public InputStream getParameterFileAsStream(StringToIntMapper string if (!Double.isNaN(limits.getFirst()) || !Double.isNaN(limits.getSecond())) { int amplId = stringToIntMapper.getInt(AmplSubset.VOLTAGE_LEVEL, voltageLevelId); String[] tokens = {Integer.toString(amplId), Double.toString(limits.getFirst()), Double.toString(limits.getSecond()), "\"" + voltageLevelId + "\""}; - dataBuilder.append(String.join(" ", tokens)); - dataBuilder.append(System.lineSeparator()); + writer.write(String.join(" ", tokens)); + writer.newLine(); } } //add new line at the end of the file - dataBuilder.append(System.lineSeparator()); - return new ByteArrayInputStream(dataBuilder.toString().getBytes(StandardCharsets.UTF_8)); + writer.newLine(); + writer.flush(); } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/algo/AlgorithmInput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/algo/AlgorithmInput.java index ff6a5d92..c35949f3 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/algo/AlgorithmInput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/algo/AlgorithmInput.java @@ -10,9 +10,8 @@ import com.powsybl.ampl.executor.AmplInputFile; import com.powsybl.commons.util.StringToIntMapper; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; +import java.io.BufferedWriter; +import java.io.IOException; import java.util.List; /** @@ -33,13 +32,15 @@ public String getFileName() { } @Override - public InputStream getParameterFileAsStream(StringToIntMapper stringToIntMapper) { - StringBuilder dataBuilder = new StringBuilder(); + public void write(BufferedWriter writer, StringToIntMapper stringToIntMapper) throws IOException { for (OpenReacAlgoParam param : algoParameters) { - dataBuilder.append(param.getName()).append(" ").append(param.getValue()).append("\n"); + writer.append(param.getName()) + .append(" ") + .append(param.getValue()); + writer.newLine(); } //add new line at the end of the file ! - dataBuilder.append("\n"); - return new ByteArrayInputStream(dataBuilder.toString().getBytes(StandardCharsets.UTF_8)); + writer.newLine(); + writer.flush(); } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/NoThrowAmplOutput.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/NoThrowAmplOutput.java index 80273f53..b7182c3b 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/output/NoThrowAmplOutput.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/output/NoThrowAmplOutput.java @@ -10,7 +10,8 @@ import com.powsybl.ampl.executor.AmplOutputFile; import com.powsybl.commons.util.StringToIntMapper; -import java.nio.file.Path; +import java.io.BufferedReader; +import java.io.IOException; /** * Interface for output ampl files, which changes the behavior of errors during file reading. @@ -31,7 +32,7 @@ public interface NoThrowAmplOutput extends AmplOutputFile { * */ @Override - void read(Path path, StringToIntMapper stringToIntMapper); + void read(BufferedReader var1, StringToIntMapper var2) throws IOException; /** * @return True if the output reading went bad. WARNING, object might have undefined behavior. 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 2293362b..961c055c 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 @@ -12,10 +12,8 @@ import com.powsybl.openreac.exceptions.IncompatibleModelException; import com.powsybl.openreac.parameters.AmplIOUtils; +import java.io.BufferedReader; import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -65,30 +63,27 @@ public String getFileName() { } @Override - public void read(Path path, StringToIntMapper amplMapper) { - List reactiveSlackLines; - // if the file is missing, we know there is no reactive slack. - if (Files.isRegularFile(path)) { - try { - reactiveSlackLines = Files.readAllLines(path, StandardCharsets.UTF_8); - } catch (IOException e) { - // File reading went wrong - triggerErrorState(); - return; - } - String headers = reactiveSlackLines.get(0); - 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 { - for (String line : reactiveSlackLines.subList(1, reactiveSlackLines.size())) { - readLine(line.split(SEP)); - } + 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() { + // if the file is missing, we know there is no reactive slack. + return false; + } + private void readLine(String[] tokens) { // slack capacitor is a generation of reactive power. // slack self is a reactive load. 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 0705a38b..ef95a874 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 @@ -12,9 +12,8 @@ import com.powsybl.openreac.OpenReacModel; import com.powsybl.openreac.parameters.output.AbstractNoThrowOutput; +import java.io.BufferedReader; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; @@ -43,25 +42,23 @@ public String getFileName() { } @Override - public void read(Path path, StringToIntMapper stringToIntMapper) { - List lines = null; - try { - lines = Files.readAllLines(path); - } catch (IOException e) { - triggerErrorState(); - } - if (lines != null) { - for (String line : lines) { - if (!COMMENTED_LINE_TEST.test(line)) { - String[] tokens = line.split(OpenReacModel.OUTPUT_FILE_FORMAT.getTokenSeparator()); - modifications.add(doReadLine(tokens, stringToIntMapper)); - } + 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)); } - } + }); } 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/test/java/com/powsybl/openreac/parameters/input/VoltageLevelLimitsOverrideInputTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLevelLimitsOverrideInputTest.java index d78592e5..8fb89d23 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLevelLimitsOverrideInputTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLevelLimitsOverrideInputTest.java @@ -6,7 +6,6 @@ */ package com.powsybl.openreac.parameters.input; -import com.google.common.io.ByteStreams; import com.powsybl.ampl.converter.AmplSubset; import com.powsybl.ampl.converter.AmplUtil; import com.powsybl.commons.PowsyblException; @@ -18,12 +17,15 @@ import com.powsybl.openreac.exceptions.InvalidParametersException; import org.junit.jupiter.api.Test; +import java.io.BufferedWriter; import java.io.IOException; -import java.nio.charset.StandardCharsets; +import java.io.StringWriter; +import java.io.Writer; import java.util.ArrayList; import java.util.List; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * @author Geoffroy Jamgotchian @@ -46,8 +48,10 @@ void testValidRelativeVoltageOverride() throws IOException { VoltageLevelLimitsOverrideInput input = new VoltageLevelLimitsOverrideInput(voltageLimitsOverride, network); StringToIntMapper mapper = AmplUtil.createMapper(network); - try (var is = input.getParameterFileAsStream(mapper)) { - String data = new String(ByteStreams.toByteArray(is), StandardCharsets.UTF_8); + try (Writer w = new StringWriter(); + BufferedWriter writer = new BufferedWriter(w)) { + input.write(writer, mapper); + String data = w.toString(); String ref = String.join(System.lineSeparator(), "#num minV (pu) maxV (pu) id", "1 0.7916666666666667 1.1666666666666665 \"VLGEN\"") + System.lineSeparator() + System.lineSeparator(); assertEquals(ref, data); @@ -70,8 +74,11 @@ void testValidAbsoluteVoltageOverride() throws IOException { VoltageLevelLimitsOverrideInput input = new VoltageLevelLimitsOverrideInput(voltageLimitsOverride, network); StringToIntMapper mapper = AmplUtil.createMapper(network); - try (var is = input.getParameterFileAsStream(mapper)) { - String data = new String(ByteStreams.toByteArray(is), StandardCharsets.UTF_8); + + try (Writer w = new StringWriter(); + BufferedWriter writer = new BufferedWriter(w)) { + input.write(writer, mapper); + String data = w.toString(); String ref = String.join(System.lineSeparator(), "#num minV (pu) maxV (pu) id", "1 0.8333333333333334 1.0833333333333333 \"VLGEN\"") + System.lineSeparator() + System.lineSeparator(); assertEquals(ref, data); 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 new file mode 100644 index 00000000..9ddf7b22 --- /dev/null +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/output/ReactiveSlackOutputTest.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2023, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.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; + +/** + * @author Olivier Perrin {@literal } + */ +class ReactiveSlackOutputTest { + + @Test + void readTest() throws IOException { + ReactiveSlackOutput output = new ReactiveSlackOutput(); + try (InputStream input = getClass().getResourceAsStream("/mock_outputs/reactiveopf_results_reactive_slacks.csv"); + InputStreamReader in = new InputStreamReader(input); + BufferedReader reader = new BufferedReader(in)) { + + output.read(reader, null); + assertEquals(2, output.getSlacks().size()); + ReactiveSlackOutput.ReactiveSlack slack1 = output.getSlacks().get(0); + ReactiveSlackOutput.ReactiveSlack slack2 = output.getSlacks().get(1); + Assertions.assertAll( + () -> assertEquals(1.6, slack1.getSlack(), 0.01), + () -> assertEquals("slack1", slack1.getBusId()), + () -> assertEquals("voltageLevel1", slack1.getVoltageLevelId()), + () -> assertEquals(Double.NaN, slack2.getSlack()), + () -> assertEquals("slack2", slack2.getBusId()), + () -> assertEquals("voltageLevel2", slack2.getVoltageLevelId()) + ); + } + } + +} diff --git a/open-reac/src/test/resources/mock_outputs/reactiveopf_results_reactive_slacks.csv b/open-reac/src/test/resources/mock_outputs/reactiveopf_results_reactive_slacks.csv new file mode 100644 index 00000000..9eb06f5f --- /dev/null +++ b/open-reac/src/test/resources/mock_outputs/reactiveopf_results_reactive_slacks.csv @@ -0,0 +1,3 @@ +col1;col2;col3;col4;col5;col6; +'a1';'b1';5.3;6.9;'slack1';'voltageLevel1'; +'a2';'b2';1.2;-99999;'slack2';'voltageLevel2'; \ No newline at end of file