From 53ea8bb98a84f5f5da30cbb435b11744afacfed6 Mon Sep 17 00:00:00 2001 From: parvy Date: Mon, 9 Oct 2023 14:00:18 +0200 Subject: [PATCH 01/16] Add absolute voltage override of voltage level limits. Signed-off-by: parvy --- .../com/powsybl/openreac/OpenReacTool.java | 4 +- .../parameters/input/OpenReacParameters.java | 16 ++- .../VoltageLevelLimitsOverrideInput.java | 52 +++++-- .../input/VoltageLimitOverride.java | 45 ++++-- .../input/VoltageLimitOverrideBuilder.java | 41 ++++++ .../VoltageLimitOverrideDeserializer.java | 25 +++- .../json/VoltageLimitOverrideSerializer.java | 6 +- .../java/com/powsybl/openreac/ItoolsTest.java | 2 +- .../VoltageLevelLimitsOverrideInputTest.java | 133 +++++++++++++++--- .../input/VoltageLimitsOverrideTest.java | 55 ++++++++ .../input/json/OpenReacJsonModuleTest.java | 6 +- open-reac/src/test/resources/parameters.json | 12 +- 12 files changed, 338 insertions(+), 59 deletions(-) create mode 100644 open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java create mode 100644 open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java diff --git a/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java b/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java index 3e61897b..24574142 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java +++ b/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java @@ -165,7 +165,9 @@ public OpenReacParameters createOpenReacParameters(CommandLine line, String voltageId = node.get("id").asText(); double lowerPercent = node.get("lower").asDouble(); double upperPercent = node.get("upper").asDouble(); - openReacParameters.addSpecificVoltageLimits(Map.of(voltageId, new VoltageLimitOverride(lowerPercent, upperPercent))); + openReacParameters.addSpecificVoltageLimits(Map.of(voltageId, + new VoltageLimitOverride(VoltageLimitOverride.OverrideKind.RELATIVE, VoltageLimitOverride.OverrideKind.RELATIVE, + lowerPercent, upperPercent))); }); } boolean objectiveSet = false; diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java index b9fc4821..8858fc94 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java @@ -186,10 +186,18 @@ public void checkIntegrity(Network network) throws InvalidParametersException { if (voltageLevel == null) { throw new InvalidParametersException("Voltage level " + voltageLevelId + " not found in the network."); } else { - if (voltageLevel.getNominalV() - + override.getDeltaLowVoltageLimit() - < 0) { - throw new InvalidParametersException("Voltage level " + voltageLevelId + " override leads to negative lower voltage level."); + if (override.getLowLimitKind() == VoltageLimitOverride.OverrideKind.RELATIVE && + voltageLevel.getNominalV() + override.getLowLimitOverride() < 0) { + throw new InvalidParametersException("Voltage level " + voltageLevelId + " relative override leads to negative low voltage limit."); + } + if (override.getLowLimitKind() == VoltageLimitOverride.OverrideKind.ABSOLUTE && + override.getLowLimitOverride() < 0) { + throw new InvalidParametersException("Voltage level " + voltageLevelId + " absolute override leads to negative low voltage limit."); + } + if (override.getLowLimitKind() == VoltageLimitOverride.OverrideKind.ABSOLUTE && + override.getHighLimitKind() == VoltageLimitOverride.OverrideKind.ABSOLUTE + && override.getLowLimitOverride() > override.getHighLimitOverride()) { + throw new InvalidParametersException("Voltage level " + voltageLevelId + " override leads to low voltage limit > high voltage limit."); } } } 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 c73f7019..fdaac5e6 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 @@ -43,14 +43,46 @@ private void transformToNormalizedVoltage(Map volt for (Map.Entry entry : voltageLimitsOverride.entrySet()) { String voltageLevelId = entry.getKey(); VoltageLimitOverride limits = entry.getValue(); + double previousLowVoltageLimit = network.getVoltageLevel(voltageLevelId).getLowVoltageLimit(); double previousHighVoltageLimit = network.getVoltageLevel(voltageLevelId).getHighVoltageLimit(); - // If one of the limit is not defined, we ignore the override - if (!Double.isNaN(previousLowVoltageLimit) && !Double.isNaN(previousHighVoltageLimit)) { - double nominalV = network.getVoltageLevel(voltageLevelId).getNominalV(); - normalizedVoltageLimitsOverride.put(voltageLevelId, new VoltageLimitOverride((previousLowVoltageLimit + limits.getDeltaLowVoltageLimit()) / nominalV, - (previousHighVoltageLimit + limits.getDeltaHighVoltageLimit()) / nominalV)); + double nominalV = network.getVoltageLevel(voltageLevelId).getNominalV(); + + VoltageLimitOverrideBuilder builder = new VoltageLimitOverrideBuilder() + .withLowLimitKind(limits.getLowLimitKind()) + .withHighLimitKind(limits.getHighLimitKind()); + + // compute low normalized override + if (limits.getLowLimitKind() == VoltageLimitOverride.OverrideKind.ABSOLUTE) { + builder.withLowLimitOverride(limits.getLowLimitOverride() / nominalV); + } else if (limits.getLowLimitKind() == VoltageLimitOverride.OverrideKind.RELATIVE) { + // if override is relative, must check that previous limit of voltage level is defined + if (!Double.isNaN(previousLowVoltageLimit)) { + builder.withLowLimitOverride((previousLowVoltageLimit + limits.getLowLimitOverride()) / nominalV); + } else { + throw new IllegalArgumentException("Relative override must be done on valid low voltage limit"); + } + // if no kind given, then no low voltage limit override + } else { + builder.withLowLimitOverride(previousLowVoltageLimit / nominalV); + } + + // compute high normalized override + if (limits.getHighLimitKind() == VoltageLimitOverride.OverrideKind.ABSOLUTE) { + builder.withHighLimitOverride(limits.getHighLimitOverride() / nominalV); + } else if (limits.getHighLimitKind() == VoltageLimitOverride.OverrideKind.RELATIVE) { + // if override is relative, must check that previous limit of voltage level is defined + if (!Double.isNaN(previousHighVoltageLimit)) { + builder.withHighLimitOverride((previousHighVoltageLimit + limits.getHighLimitOverride()) / nominalV); + } else { + throw new IllegalArgumentException("Relative override must be done on valid high voltage limit"); + } + // if no kind given, then no high voltage limit override + } else { + builder.withHighLimitOverride(previousHighVoltageLimit / nominalV); } + + normalizedVoltageLimitsOverride.put(voltageLevelId, builder.build()); } } @@ -64,18 +96,22 @@ public InputStream getParameterFileAsStream(StringToIntMapper string StringBuilder dataBuilder = new StringBuilder(); dataBuilder.append("#num minV (pu) maxV (pu) id"); dataBuilder.append(System.lineSeparator()); + for (Map.Entry entry : normalizedVoltageLimitsOverride.entrySet()) { String voltageLevelId = entry.getKey(); VoltageLimitOverride limits = entry.getValue(); - if (!Double.isNaN(limits.getDeltaHighVoltageLimit()) || !Double.isNaN(limits.getDeltaLowVoltageLimit())) { + + if (!Double.isNaN(limits.getLowLimitOverride()) || !Double.isNaN(limits.getHighLimitOverride())) { int amplId = stringToIntMapper.getInt(AmplSubset.VOLTAGE_LEVEL, voltageLevelId); - double newHighVoltageLimit = Double.isNaN(limits.getDeltaHighVoltageLimit()) ? AmplConstants.INVALID_FLOAT_VALUE : limits.getDeltaHighVoltageLimit(); - double newLowVoltageLimit = Double.isNaN(limits.getDeltaLowVoltageLimit()) ? AmplConstants.INVALID_FLOAT_VALUE : limits.getDeltaLowVoltageLimit(); + double newLowVoltageLimit = Double.isNaN(limits.getLowLimitOverride()) ? AmplConstants.INVALID_FLOAT_VALUE : limits.getLowLimitOverride(); + double newHighVoltageLimit = Double.isNaN(limits.getHighLimitOverride()) ? AmplConstants.INVALID_FLOAT_VALUE : limits.getHighLimitOverride(); + String[] tokens = {Integer.toString(amplId), Double.toString(newLowVoltageLimit), Double.toString(newHighVoltageLimit), AmplIOUtils.addQuotes(voltageLevelId)}; dataBuilder.append(String.join(" ", tokens)); dataBuilder.append(System.lineSeparator()); } } + //add new line at the end of the file ! dataBuilder.append(System.lineSeparator()); return new ByteArrayInputStream(dataBuilder.toString().getBytes(StandardCharsets.UTF_8)); diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java index 23d49ff3..88a515cc 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java @@ -12,23 +12,42 @@ * Class to store an override of a voltage level voltage limits. * * @author Nicolas Pierre + * @author Pierre Arvy */ public class VoltageLimitOverride { - private final double deltaLowVoltageLimit; - private final double deltaHighVoltageLimit; + public enum OverrideKind { + ABSOLUTE, RELATIVE; + } + + private final OverrideKind lowLimitKind; + private final OverrideKind highLimitKind; + + private final double lowLimitOverride; + private final double highLimitOverride; + + public double getLowLimitOverride() { + return lowLimitOverride; + } + + public double getHighLimitOverride() { + return highLimitOverride; + } - public double getDeltaLowVoltageLimit() { - return deltaLowVoltageLimit; + public OverrideKind getLowLimitKind() { + return lowLimitKind; } - public double getDeltaHighVoltageLimit() { - return deltaHighVoltageLimit; + public OverrideKind getHighLimitKind() { + return highLimitKind; } - public VoltageLimitOverride(double deltaLowVoltageLimit, double deltaHighVoltageLimit) { - this.deltaLowVoltageLimit = deltaLowVoltageLimit; - this.deltaHighVoltageLimit = deltaHighVoltageLimit; + public VoltageLimitOverride(OverrideKind lowLimitKind, OverrideKind highLimitKind, + double lowLimitOverride, double highLimitOverride) { + this.lowLimitKind = lowLimitKind; + this.highLimitKind = highLimitKind; + this.lowLimitOverride = lowLimitOverride; + this.highLimitOverride = highLimitOverride; } @Override @@ -40,12 +59,14 @@ public boolean equals(Object o) { return false; } VoltageLimitOverride that = (VoltageLimitOverride) o; - return Double.compare(that.deltaLowVoltageLimit, deltaLowVoltageLimit) == 0 - && Double.compare(that.deltaHighVoltageLimit, deltaHighVoltageLimit) == 0; + return that.lowLimitKind == lowLimitKind + && Double.compare(that.lowLimitOverride, lowLimitOverride) == 0 + && that.highLimitKind == highLimitKind + && Double.compare(that.highLimitOverride, highLimitOverride) == 0; } @Override public int hashCode() { - return Objects.hash(deltaLowVoltageLimit, deltaHighVoltageLimit); + return Objects.hash(lowLimitKind, lowLimitOverride, highLimitKind, highLimitOverride); } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java new file mode 100644 index 00000000..8c00dc55 --- /dev/null +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java @@ -0,0 +1,41 @@ +package com.powsybl.openreac.parameters.input; + +public class VoltageLimitOverrideBuilder { + + private VoltageLimitOverride.OverrideKind lowLimitKind; + private VoltageLimitOverride.OverrideKind highLimitKind; + + private double lowLimitOverride; + private double highLimitOverride; + + public VoltageLimitOverride build() { + if (lowLimitKind == null && highLimitKind == null) { + throw new IllegalStateException("For a valid voltage limit override, the kind of one side must be provided"); + } + if (lowLimitOverride == 0 && highLimitOverride == 0) { + throw new IllegalStateException("For a valid voltage limit override, an override value must be provided"); + } + return new VoltageLimitOverride(lowLimitKind, highLimitKind, lowLimitOverride, highLimitOverride); + } + + public VoltageLimitOverrideBuilder withLowLimitKind(VoltageLimitOverride.OverrideKind lowVoltageLimitKind) { + this.lowLimitKind = lowVoltageLimitKind; + return this; + } + + public VoltageLimitOverrideBuilder withHighLimitKind(VoltageLimitOverride.OverrideKind highVoltageLimitKind) { + this.highLimitKind = highVoltageLimitKind; + return this; + } + + public VoltageLimitOverrideBuilder withLowLimitOverride(double lowVoltageLimitOverride) { + this.lowLimitOverride = lowVoltageLimitOverride; + return this; + } + + public VoltageLimitOverrideBuilder withHighLimitOverride(double highVoltageLimitOverride) { + this.highLimitOverride = highVoltageLimitOverride; + return this; + } + +} diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java index 33d4b476..59ecb47d 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java @@ -26,23 +26,34 @@ public VoltageLimitOverrideDeserializer() { @Override public VoltageLimitOverride deserialize(JsonParser parser, DeserializationContext deserializationContext) throws IOException { - double deltaLowVoltageLimit = 0; - double deltaHighVoltageLimit = 0; + VoltageLimitOverride.OverrideKind lowLimitKind = null; + VoltageLimitOverride.OverrideKind highLimitKind = null; + double lowLimitOverride = 0; + double highLimitOverride = 0; while (parser.nextToken() != JsonToken.END_OBJECT) { switch (parser.getCurrentName()) { - case "deltaLowVoltageLimit": + case "lowLimitKind": parser.nextToken(); - deltaLowVoltageLimit = parser.readValueAs(Double.class); + lowLimitKind = parser.readValueAs(VoltageLimitOverride.OverrideKind.class); break; - case "deltaHighVoltageLimit": + case "highLimitKind": parser.nextToken(); - deltaHighVoltageLimit = parser.readValueAs(Double.class); + highLimitKind = parser.readValueAs(VoltageLimitOverride.OverrideKind.class); + break; + case "lowLimitOverride": + parser.nextToken(); + lowLimitOverride = parser.readValueAs(Double.class); + break; + case "highLimitOverride": + parser.nextToken(); + highLimitOverride = parser.readValueAs(Double.class); break; default: throw new IllegalStateException("Unexpected field: " + parser.getCurrentName()); } } - return new VoltageLimitOverride(deltaLowVoltageLimit, deltaHighVoltageLimit); + return new VoltageLimitOverride(lowLimitKind, highLimitKind, + lowLimitOverride, highLimitOverride); } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java index 65630dbf..ae09b88a 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java @@ -26,8 +26,10 @@ public VoltageLimitOverrideSerializer() { @Override public void serialize(VoltageLimitOverride voltageLimitOverride, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeStartObject(); - jsonGenerator.writeNumberField("deltaLowVoltageLimit", voltageLimitOverride.getDeltaLowVoltageLimit()); - jsonGenerator.writeNumberField("deltaHighVoltageLimit", voltageLimitOverride.getDeltaHighVoltageLimit()); + jsonGenerator.writeObjectField("lowLimitKind", voltageLimitOverride.getLowLimitKind()); + jsonGenerator.writeObjectField("highLimitKind", voltageLimitOverride.getHighLimitKind()); + jsonGenerator.writeNumberField("lowLimitOverride", voltageLimitOverride.getLowLimitOverride()); + jsonGenerator.writeNumberField("highLimitOverride", voltageLimitOverride.getHighLimitOverride()); jsonGenerator.writeEndObject(); } } diff --git a/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java b/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java index f4c209ef..0f9f7488 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java @@ -62,7 +62,7 @@ public void testCreateOpenReacParameters() throws ParseException, IOException { assertEquals(List.of("2-winding-transfo"), loadedParams.getVariableTwoWindingsTransformers(), "Parsing of OpenReac parameters is wrong."); assertEquals(List.of("constant-q-gen"), loadedParams.getConstantQGenerators(), "Parsing of OpenReac parameters is wrong."); assertEquals(List.of("var-shunt", "var-shunt-2"), loadedParams.getVariableShuntCompensators(), "Parsing of OpenReac parameters is wrong."); - assertEquals(Map.of("voltageLevelId", new VoltageLimitOverride(-5, 5)), + assertEquals(Map.of("voltageLevelId", new VoltageLimitOverride(VoltageLimitOverride.OverrideKind.RELATIVE, VoltageLimitOverride.OverrideKind.RELATIVE, -5, 5)), loadedParams.getSpecificVoltageLimits(), "Parsing of OpenReac parameters is wrong."); assertEquals(OpenReacOptimisationObjective.SPECIFIC_VOLTAGE_PROFILE, loadedParams.getObjective(), "Parsing of OpenReac parameters is wrong."); 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 6ce6ea7f..914ebdcf 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 @@ -22,8 +22,7 @@ import java.nio.charset.StandardCharsets; import java.util.Map; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; /** * @author Geoffroy Jamgotchian @@ -31,24 +30,87 @@ class VoltageLevelLimitsOverrideInputTest { @Test - void test() throws IOException { + void testRelativeOverrideOnUndefinedLimit() { Network network = EurostagTutorialExample1Factory.create(); - VoltageLevel vlgen = network.getVoltageLevel("VLGEN"); - vlgen.setLowVoltageLimit(20) - .setHighVoltageLimit(26); - // if vl has one NaN, the override is ignored - VoltageLevel vlload = network.getVoltageLevel("VLLOAD"); - vlload.setLowVoltageLimit(130); - vlload.setHighVoltageLimit(Double.NaN); - Map voltageLimitsOverride = Map.of("VLGEN", new VoltageLimitOverride(-1, 2), - "VLHV1", new VoltageLimitOverride(-1.3, 2.5), - "VLLOAD", new VoltageLimitOverride(-1.7, 4.2)); + VoltageLevel vlLoad = network.getVoltageLevel("VLLOAD"); + + // if relative override is intended on undefined low voltage limit, throws exception + vlLoad.setLowVoltageLimit(Double.NaN) + .setHighVoltageLimit(150); + + Map voltageLimitsOverride = Map.of("VLLOAD", + new VoltageLimitOverrideBuilder() + .withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) + .withLowLimitOverride(-1.3) + .build()); + assertThrows(IllegalArgumentException.class, + () -> new VoltageLevelLimitsOverrideInput(voltageLimitsOverride, network)); + + // if relative override is intended on undefined high voltage limit, throws exception + vlLoad.setLowVoltageLimit(130) + .setHighVoltageLimit(Double.NaN); + + Map voltageLimitsOverride2 = Map.of("VLLOAD", + new VoltageLimitOverrideBuilder() + .withHighLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) + .withHighLimitOverride(4.2) + .build()); + + assertThrows(IllegalArgumentException.class, + () -> new VoltageLevelLimitsOverrideInput(voltageLimitsOverride2, network)); + } + + @Test + void testRelativeOverride() throws IOException { + Network network = EurostagTutorialExample1Factory.create(); + + // verify relative override can be applied on both defined low/high limits + VoltageLevel vlGen = network.getVoltageLevel("VLGEN"); + vlGen.setLowVoltageLimit(20) + .setHighVoltageLimit(26); + + Map voltageLimitsOverride = Map.of("VLGEN", + new VoltageLimitOverrideBuilder() + .withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) + .withLowLimitOverride(-1) + .withHighLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) + .withHighLimitOverride(2) + .build()); + 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); String ref = String.join(System.lineSeparator(), "#num minV (pu) maxV (pu) id", - "1 0.7916666666666666 1.1666666666666667 'VLGEN'") + System.lineSeparator() + System.lineSeparator(); + "1 0.7916666666666666 1.1666666666666667 'VLGEN'") + System.lineSeparator() + System.lineSeparator(); + assertEquals(ref, data); + } + } + + @Test + void testAbsoluteOverride() throws IOException { + Network network = EurostagTutorialExample1Factory.create(); + + // change high voltage limits to undefined values + VoltageLevel vlgen = network.getVoltageLevel("VLGEN"); + vlgen.setLowVoltageLimit(Double.NaN) + .setHighVoltageLimit(Double.NaN); + + // verify absolute override can be applied on both undefined low/high limits + VoltageLimitOverride vlo = new VoltageLimitOverrideBuilder().withLowLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE) + .withHighLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE) + .withLowLimitOverride(20) + .withHighLimitOverride(26) + .build(); + + Map voltageLimtisOverride = Map.of("VLGEN", vlo); + + VoltageLevelLimitsOverrideInput input = new VoltageLevelLimitsOverrideInput(voltageLimtisOverride, network); + StringToIntMapper mapper = AmplUtil.createMapper(network); + try (var is = input.getParameterFileAsStream(mapper)) { + String data = new String(ByteStreams.toByteArray(is), StandardCharsets.UTF_8); + 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); } } @@ -57,27 +119,62 @@ void test() throws IOException { void testUnsupportedNetwork() { Network network = IeeeCdfNetworkFactory.create118(); VoltageLevel vl = network.getVoltageLevels().iterator().next(); + OpenReacParameters params = new OpenReacParameters(); + + // if only low voltage limit of one voltage level is undefined, invalid OpenReacParameters vl.setLowVoltageLimit(Double.NaN); vl.setHighVoltageLimit(480); - OpenReacParameters params = new OpenReacParameters(); assertThrows(PowsyblException.class, () -> params.checkIntegrity(network)); + + // if only high voltage limit of one voltage level is undefined, invalid OpenReacParameters vl.setLowVoltageLimit(480); vl.setHighVoltageLimit(Double.NaN); assertThrows(PowsyblException.class, () -> params.checkIntegrity(network)); } @Test - void testInvalidOverride() { + void testNegativeLowOverride() { Network network = IeeeCdfNetworkFactory.create118(); VoltageLevel vl = network.getVoltageLevels().iterator().next(); vl.setLowVoltageLimit(400); vl.setHighVoltageLimit(480); + + // if low relative voltage override leads to negative voltage limit, throws exception OpenReacParameters params = new OpenReacParameters(); - params.addSpecificVoltageLimits(Map.of(vl.getId(), new VoltageLimitOverride(-410, 0))); + params.addSpecificVoltageLimits(Map.of(vl.getId(), + new VoltageLimitOverrideBuilder() + .withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) + .withLowLimitOverride(-410) + .withHighLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) + .withHighLimitOverride(0) + .build())); assertThrows(InvalidParametersException.class, () -> params.checkIntegrity(network)); + // if low absolute voltage override leads to negative voltage limit, throws exception OpenReacParameters params2 = new OpenReacParameters(); - params2.addSpecificVoltageLimits(Map.of("UNKNOWN_ID", new VoltageLimitOverride(0, 0))); + params2.addSpecificVoltageLimits(Map.of(vl.getId(), + new VoltageLimitOverrideBuilder() + .withLowLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE) + .withLowLimitOverride(-10) + .withHighLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) + .withHighLimitOverride(0) + .build())); assertThrows(InvalidParametersException.class, () -> params2.checkIntegrity(network)); } + + @Test + void testInvalidVoltageLevelOverride() { + Network network = IeeeCdfNetworkFactory.create118(); + + // if voltage level (on which is applied override) is not in the network, throws exception + OpenReacParameters params3 = new OpenReacParameters(); + params3.addSpecificVoltageLimits(Map.of("UNKNOWN_ID", + new VoltageLimitOverrideBuilder() + .withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) + .withLowLimitOverride(1) + .withHighLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) + .withHighLimitOverride(0) + .build())); + assertThrows(InvalidParametersException.class, () -> params3.checkIntegrity(network)); + } } diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java new file mode 100644 index 00000000..a6758305 --- /dev/null +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java @@ -0,0 +1,55 @@ +package com.powsybl.openreac.parameters.input; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class VoltageLimitsOverrideTest { + + @Test + void validVoltageLimitOverrideBuilderTest() { + VoltageLimitOverrideBuilder builder = new VoltageLimitOverrideBuilder(); + VoltageLimitOverride vlo; + + // if one side of override specified, valid voltage limit override + builder.withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) + .withLowLimitOverride(-1); + vlo = builder.build(); + assertEquals(vlo.getLowLimitKind(), VoltageLimitOverride.OverrideKind.RELATIVE); + assertEquals(vlo.getLowLimitOverride(), -1); + + // if two sides of override specified, valid voltage limit override + builder.withHighLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE) + .withHighLimitOverride(410); + vlo = builder.build(); + assertEquals(vlo.getHighLimitKind(), VoltageLimitOverride.OverrideKind.ABSOLUTE); + assertEquals(vlo.getHighLimitOverride(), 410); + } + + @Test + void invalidVoltageLimitOverrideBuilderTest() { + VoltageLimitOverrideBuilder builder = new VoltageLimitOverrideBuilder(); + + // if no override kind specified, invalid voltage limit override + assertThrows(IllegalStateException.class, builder::build); + + // if no override value specified, invalid voltage limit override + builder.withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE); + assertThrows(IllegalStateException.class, builder::build); + + builder.withHighLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE); + assertThrows(IllegalStateException.class, builder::build); + } + + @Test + void equalsVoltageLimitOverride() { + VoltageLimitOverrideBuilder builder = new VoltageLimitOverrideBuilder().withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) + .withLowLimitOverride(5) + .withHighLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE) + .withHighLimitOverride(410); + + assertEquals(builder.build(), builder.build()); + assertNotEquals(builder.build(), builder.withHighLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE).build()); + } + +} diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/json/OpenReacJsonModuleTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/json/OpenReacJsonModuleTest.java index e5a75e81..abc6377b 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/json/OpenReacJsonModuleTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/json/OpenReacJsonModuleTest.java @@ -30,7 +30,8 @@ void test() throws IOException { ObjectMapper objectMapper = JsonUtil.createObjectMapper() .registerModule(new OpenReactJsonModule()); OpenReacParameters parameters = new OpenReacParameters(); - parameters.addSpecificVoltageLimits(Map.of("foo", new VoltageLimitOverride(-1, 2), "bar", new VoltageLimitOverride(-1.2, 2.3))); + parameters.addSpecificVoltageLimits(Map.of("foo", new VoltageLimitOverride(VoltageLimitOverride.OverrideKind.RELATIVE, VoltageLimitOverride.OverrideKind.RELATIVE, -1, 2), + "bar", new VoltageLimitOverride(VoltageLimitOverride.OverrideKind.ABSOLUTE, VoltageLimitOverride.OverrideKind.ABSOLUTE, 20, 26))); parameters.addConstantQGenerators(List.of("g1", "g2")); parameters.addVariableTwoWindingsTransformers(List.of("tr1")); parameters.addVariableShuntCompensators(List.of("sc1", "sc2")); @@ -40,7 +41,8 @@ void test() throws IOException { String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(parameters); ComparisonUtils.compareTxt(Objects.requireNonNull(getClass().getResourceAsStream("/parameters.json")), json); OpenReacParameters parameters2 = objectMapper.readValue(json, OpenReacParameters.class); - assertEquals(Map.of("foo", new VoltageLimitOverride(-1, 2), "bar", new VoltageLimitOverride(-1.2, 2.3)), parameters2.getSpecificVoltageLimits()); + assertEquals(Map.of("foo", new VoltageLimitOverride(VoltageLimitOverride.OverrideKind.RELATIVE, VoltageLimitOverride.OverrideKind.RELATIVE, -1, 2), + "bar", new VoltageLimitOverride(VoltageLimitOverride.OverrideKind.ABSOLUTE, VoltageLimitOverride.OverrideKind.ABSOLUTE, 20, 26)), parameters2.getSpecificVoltageLimits()); assertEquals(List.of("g1", "g2"), parameters2.getConstantQGenerators()); assertEquals(List.of("tr1"), parameters2.getVariableTwoWindingsTransformers()); assertEquals(2, parameters2.getAlgorithmParams().size()); diff --git a/open-reac/src/test/resources/parameters.json b/open-reac/src/test/resources/parameters.json index 3bf8914c..92509688 100644 --- a/open-reac/src/test/resources/parameters.json +++ b/open-reac/src/test/resources/parameters.json @@ -2,12 +2,16 @@ "version" : "1.0", "specificVoltageLimits" : { "bar" : { - "deltaLowVoltageLimit" : -1.2, - "deltaHighVoltageLimit" : 2.3 + "lowLimitKind" : "ABSOLUTE", + "highLimitKind" : "ABSOLUTE", + "lowLimitOverride" : 20.0, + "highLimitOverride" : 26.0 }, "foo" : { - "deltaLowVoltageLimit" : -1.0, - "deltaHighVoltageLimit" : 2.0 + "lowLimitKind" : "RELATIVE", + "highLimitKind" : "RELATIVE", + "lowLimitOverride" : -1.0, + "highLimitOverride" : 2.0 } }, "constantQGenerators" : [ "g1", "g2" ], From 77fb9edb48496c0ff54e1b24458d0a7fe4d4ac80 Mon Sep 17 00:00:00 2001 From: parvy Date: Mon, 9 Oct 2023 17:04:39 +0200 Subject: [PATCH 02/16] Change integrity of OpenReacParameters. They are now correct if every voltage level has defined low/high voltage limits (taking into account voltage limit overrides) Signed-off-by: parvy --- .../parameters/input/OpenReacParameters.java | 90 +++++++++++++++---- .../VoltageLevelLimitsOverrideInput.java | 6 +- .../input/VoltageLimitOverrideBuilder.java | 13 ++- .../input/VoltageLimitsOverrideTest.java | 16 +++- 4 files changed, 103 insertions(+), 22 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java index 8858fc94..f03c1c33 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java @@ -180,42 +180,100 @@ public void checkIntegrity(Network network) throws InvalidParametersException { throw new InvalidParametersException("Two windings transfromer " + transformerId + " not found in the network."); } } + + // Check integrity of voltage overrides + boolean inconsistentOverride = false; for (String voltageLevelId : getSpecificVoltageLimits().keySet()) { VoltageLevel voltageLevel = network.getVoltageLevel(voltageLevelId); - VoltageLimitOverride override = getSpecificVoltageLimits().get(voltageLevelId); + + // Check existence of voltage level on which is applied voltage limit override if (voltageLevel == null) { - throw new InvalidParametersException("Voltage level " + voltageLevelId + " not found in the network."); + LOGGER.warn("Voltage level " + voltageLevelId + " not found in the network."); + inconsistentOverride = true; + } else { + // if low voltage override is relative, check new low voltage limit is > 0 + VoltageLimitOverride override = getSpecificVoltageLimits().get(voltageLevelId); if (override.getLowLimitKind() == VoltageLimitOverride.OverrideKind.RELATIVE && voltageLevel.getNominalV() + override.getLowLimitOverride() < 0) { - throw new InvalidParametersException("Voltage level " + voltageLevelId + " relative override leads to negative low voltage limit."); + LOGGER.warn("Voltage level " + voltageLevelId + " relative override leads to negative low voltage limit."); + inconsistentOverride = true; } + // if low voltage override is absolute, check new low voltage limit is > 0 if (override.getLowLimitKind() == VoltageLimitOverride.OverrideKind.ABSOLUTE && override.getLowLimitOverride() < 0) { - throw new InvalidParametersException("Voltage level " + voltageLevelId + " absolute override leads to negative low voltage limit."); + LOGGER.warn("Voltage level " + voltageLevelId + " absolute override leads to negative low voltage limit."); + inconsistentOverride = true; } + // if low/high voltage overrides are absolute, check new low limit is < new high limit if (override.getLowLimitKind() == VoltageLimitOverride.OverrideKind.ABSOLUTE && - override.getHighLimitKind() == VoltageLimitOverride.OverrideKind.ABSOLUTE - && override.getLowLimitOverride() > override.getHighLimitOverride()) { - throw new InvalidParametersException("Voltage level " + voltageLevelId + " override leads to low voltage limit > high voltage limit."); + override.getHighLimitKind() == VoltageLimitOverride.OverrideKind.ABSOLUTE && + override.getLowLimitOverride() > override.getHighLimitOverride()) { + LOGGER.warn("Voltage level " + voltageLevelId + " override leads to low voltage limit > high voltage limit."); + inconsistentOverride = true; } } + + } + + if (inconsistentOverride) { + throw new InvalidParametersException("At least one voltage limit override is inconsistent."); } - for (VoltageLevel vl : network.getVoltageLevels()) { + + // Check integrity of low/high voltage limits, taking into account voltage limit overrides + boolean limitUndefined = false; + for (VoltageLevel vl : network.getVoltageLevels()){ double lowLimit = vl.getLowVoltageLimit(); double highLimit = vl.getHighVoltageLimit(); - if (lowLimit == 0 && Double.isNaN(highLimit)) { - lowLimit = Double.NaN; - LOGGER.warn("Voltage level '{}' has an unsupported limit [0, NaN], fix to [NaN, NaN]", vl.getId()); + + if (lowLimit <= 0 || Double.isNaN(lowLimit)) { + + // Check if voltage override exists + if (getSpecificVoltageLimits().containsKey(vl.getId())) { + VoltageLimitOverride override = getSpecificVoltageLimits().get(vl.getId()); + + // Relative override on undefined low voltage limit is incorrect + if (override.getLowLimitKind() == VoltageLimitOverride.OverrideKind.RELATIVE) { + LOGGER.warn("Relative voltage override impossible on undefined low voltage limit for voltage level '" + + vl.getId() + "'."); + limitUndefined = true; + } + + // If no voltage override, low voltage limit is undefined or incorrect + } else { + LOGGER.warn("Voltage level '" + vl.getId() + "' has no low voltage limit defined. " + + "Please add one or use a voltage limit override."); + limitUndefined = true; + } } - // xor operator, exactly one limit must be NaN - if (Double.isNaN(highLimit) ^ Double.isNaN(lowLimit)) { - throw new PowsyblException( - "Voltage level '" + vl.getId() + "' has only one voltage limit defined (min:" + lowLimit + - ", max:" + highLimit + "). Please define none or both."); + + // If high voltage limit is undefined, check if voltage override exists + if (Double.isNaN(highLimit)) { + + // Check if voltage override exists + if (getSpecificVoltageLimits().containsKey(vl.getId())) { + VoltageLimitOverride override = getSpecificVoltageLimits().get(vl.getId()); + + // Relative override on undefined high voltage limit is incorrect + if (override.getHighLimitKind() == VoltageLimitOverride.OverrideKind.RELATIVE) { + LOGGER.warn("Relative voltage override impossible on undefined high voltage limit for voltage level '" + + vl.getId() + "'."); + limitUndefined = true; + } + + // If no voltage override, high voltage limit is undefined + } else { + LOGGER.warn("Voltage level '" + vl.getId() + "' has no high voltage limit defined. " + + "Please add one or use a voltage limit override."); + limitUndefined = true; + } } } + if (limitUndefined) { + throw new InvalidParametersException("At least one voltage level has an undefined or incorrect voltage limit."); + } + if (objective.equals(OpenReacOptimisationObjective.BETWEEN_HIGH_AND_LOW_VOLTAGE_LIMIT) && objectiveDistance == null) { throw new InvalidParametersException("In using " + OpenReacOptimisationObjective.BETWEEN_HIGH_AND_LOW_VOLTAGE_LIMIT + " as objective, a distance in percent between low and high voltage limits is expected."); 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 fdaac5e6..46eb547c 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 @@ -101,10 +101,10 @@ public InputStream getParameterFileAsStream(StringToIntMapper string String voltageLevelId = entry.getKey(); VoltageLimitOverride limits = entry.getValue(); - if (!Double.isNaN(limits.getLowLimitOverride()) || !Double.isNaN(limits.getHighLimitOverride())) { + if (!Double.isNaN(limits.getLowLimitOverride()) && !Double.isNaN(limits.getHighLimitOverride())) { int amplId = stringToIntMapper.getInt(AmplSubset.VOLTAGE_LEVEL, voltageLevelId); - double newLowVoltageLimit = Double.isNaN(limits.getLowLimitOverride()) ? AmplConstants.INVALID_FLOAT_VALUE : limits.getLowLimitOverride(); - double newHighVoltageLimit = Double.isNaN(limits.getHighLimitOverride()) ? AmplConstants.INVALID_FLOAT_VALUE : limits.getHighLimitOverride(); + double newLowVoltageLimit = limits.getLowLimitOverride(); + double newHighVoltageLimit = limits.getHighLimitOverride(); String[] tokens = {Integer.toString(amplId), Double.toString(newLowVoltageLimit), Double.toString(newHighVoltageLimit), AmplIOUtils.addQuotes(voltageLevelId)}; dataBuilder.append(String.join(" ", tokens)); diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java index 8c00dc55..ee9aedad 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java @@ -1,3 +1,9 @@ +/** + * 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/. + */ package com.powsybl.openreac.parameters.input; public class VoltageLimitOverrideBuilder { @@ -10,10 +16,13 @@ public class VoltageLimitOverrideBuilder { public VoltageLimitOverride build() { if (lowLimitKind == null && highLimitKind == null) { - throw new IllegalStateException("For a valid voltage limit override, the kind of one side must be provided"); + throw new IllegalStateException("For a valid voltage limit override, the kind of one side must be provided."); } if (lowLimitOverride == 0 && highLimitOverride == 0) { - throw new IllegalStateException("For a valid voltage limit override, an override value must be provided"); + throw new IllegalStateException("For a valid voltage limit override, at least one value must be provided."); + } + if (Double.isNaN(lowLimitOverride) || Double.isNaN(highLimitOverride)){ + throw new IllegalStateException("For a valid voltage limit override, no undefined value must be provided."); } return new VoltageLimitOverride(lowLimitKind, highLimitKind, lowLimitOverride, highLimitOverride); } diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java index a6758305..af15a474 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java @@ -1,3 +1,9 @@ +/** + * 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/. + */ package com.powsybl.openreac.parameters.input; import org.junit.jupiter.api.Test; @@ -35,9 +41,17 @@ void invalidVoltageLimitOverrideBuilderTest() { // if no override value specified, invalid voltage limit override builder.withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE); + builder.withHighLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE); assertThrows(IllegalStateException.class, builder::build); - builder.withHighLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE); + // if low override value is undefined, invalid voltage limit override + builder.withLowLimitOverride(5) + .withHighLimitOverride(Double.NaN); + assertThrows(IllegalStateException.class, builder::build); + + // if high override value is undefined, invalid voltage limit override + builder.withLowLimitOverride(Double.NaN) + .withHighLimitOverride(5); assertThrows(IllegalStateException.class, builder::build); } From ecb6c3fc36640c5ae7a6d83d06f5adb8c929f635 Mon Sep 17 00:00:00 2001 From: parvy Date: Mon, 9 Oct 2023 17:36:27 +0200 Subject: [PATCH 03/16] Refactor for maven integration. Signed-off-by: parvy --- .../openreac/parameters/input/OpenReacParameters.java | 3 +-- .../input/VoltageLevelLimitsOverrideInput.java | 1 - .../parameters/input/VoltageLimitOverrideBuilder.java | 2 +- .../input/VoltageLevelLimitsOverrideInputTest.java | 11 ++++++++--- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java index f03c1c33..30a12a86 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java @@ -6,7 +6,6 @@ */ package com.powsybl.openreac.parameters.input; -import com.powsybl.commons.PowsyblException; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.VoltageLevel; import com.powsybl.openreac.exceptions.InvalidParametersException; @@ -222,7 +221,7 @@ public void checkIntegrity(Network network) throws InvalidParametersException { // Check integrity of low/high voltage limits, taking into account voltage limit overrides boolean limitUndefined = false; - for (VoltageLevel vl : network.getVoltageLevels()){ + for (VoltageLevel vl : network.getVoltageLevels()) { double lowLimit = vl.getLowVoltageLimit(); double highLimit = vl.getHighVoltageLimit(); 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 46eb547c..3fd6ce97 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 @@ -6,7 +6,6 @@ */ package com.powsybl.openreac.parameters.input; -import com.powsybl.ampl.converter.AmplConstants; import com.powsybl.ampl.converter.AmplSubset; import com.powsybl.ampl.executor.AmplInputFile; import com.powsybl.commons.util.StringToIntMapper; diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java index ee9aedad..29baf797 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java @@ -21,7 +21,7 @@ public VoltageLimitOverride build() { if (lowLimitOverride == 0 && highLimitOverride == 0) { throw new IllegalStateException("For a valid voltage limit override, at least one value must be provided."); } - if (Double.isNaN(lowLimitOverride) || Double.isNaN(highLimitOverride)){ + if (Double.isNaN(lowLimitOverride) || Double.isNaN(highLimitOverride)) { throw new IllegalStateException("For a valid voltage limit override, no undefined value must be provided."); } return new VoltageLimitOverride(lowLimitKind, highLimitKind, lowLimitOverride, highLimitOverride); 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 914ebdcf..04d36557 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 @@ -116,7 +116,7 @@ void testAbsoluteOverride() throws IOException { } @Test - void testUnsupportedNetwork() { + void testUndefinedVoltageLevelLimits() { Network network = IeeeCdfNetworkFactory.create118(); VoltageLevel vl = network.getVoltageLevels().iterator().next(); OpenReacParameters params = new OpenReacParameters(); @@ -126,14 +126,19 @@ void testUnsupportedNetwork() { vl.setHighVoltageLimit(480); assertThrows(PowsyblException.class, () -> params.checkIntegrity(network)); - // if only high voltage limit of one voltage level is undefined, invalid OpenReacParameters + // if only high voltage limit is undefined, invalid OpenReacParameters vl.setLowVoltageLimit(480); vl.setHighVoltageLimit(Double.NaN); assertThrows(PowsyblException.class, () -> params.checkIntegrity(network)); + + // if both low/high voltage limits are undefined, invalid OpenReacParameters + vl.setLowVoltageLimit(Double.NaN); + vl.setHighVoltageLimit(Double.NaN); + assertThrows(PowsyblException.class, () -> params.checkIntegrity(network)); } @Test - void testNegativeLowOverride() { + void testNegativeLowVoltageValueOverride() { Network network = IeeeCdfNetworkFactory.create118(); VoltageLevel vl = network.getVoltageLevels().iterator().next(); vl.setLowVoltageLimit(400); From b760a9e3d71f0f605c083db083a9e4b02722fa4e Mon Sep 17 00:00:00 2001 From: parvy Date: Mon, 9 Oct 2023 18:41:08 +0200 Subject: [PATCH 04/16] Fix unit tests by adding low/high voltage limits to every voltage level. Signed-off-by: parvy --- .../openreac/OpenReacParametersTest.java | 18 +++++++--- .../powsybl/openreac/OpenReacRunnerTest.java | 19 ++++++++++ .../VoltageLevelLimitsOverrideInputTest.java | 35 +++++++++++++++++-- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/open-reac/src/test/java/com/powsybl/openreac/OpenReacParametersTest.java b/open-reac/src/test/java/com/powsybl/openreac/OpenReacParametersTest.java index fe32d347..22ae95e5 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/OpenReacParametersTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/OpenReacParametersTest.java @@ -7,10 +7,7 @@ package com.powsybl.openreac; import com.powsybl.ieeecdf.converter.IeeeCdfNetworkFactory; -import com.powsybl.iidm.network.Generator; -import com.powsybl.iidm.network.Network; -import com.powsybl.iidm.network.ShuntCompensator; -import com.powsybl.iidm.network.TwoWindingsTransformer; +import com.powsybl.iidm.network.*; import com.powsybl.openreac.exceptions.InvalidParametersException; import com.powsybl.openreac.parameters.input.OpenReacParameters; import com.powsybl.openreac.parameters.input.algo.OpenReacOptimisationObjective; @@ -29,6 +26,7 @@ public class OpenReacParametersTest { @Test public void testObjectiveIntegrityChecks() { Network network = IeeeCdfNetworkFactory.create118(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network OpenReacParameters parameters = new OpenReacParameters(); assertEquals(parameters.getObjective(), OpenReacOptimisationObjective.MIN_GENERATION); @@ -44,6 +42,7 @@ public void testObjectiveIntegrityChecks() { @Test public void testParametersIntegrityChecks() { Network network = IeeeCdfNetworkFactory.create118(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network String wrongId = "An id not in 118 cdf network."; OpenReacParameters parameters = new OpenReacParameters(); @@ -88,4 +87,15 @@ public void testParametersIntegrityChecks() { assertThrows(InvalidParametersException.class, () -> lambdaParamsGenerators.checkIntegrity(network), "An Generator ID not present in the network should throw to the user."); } + void setDefaultVoltageLimits(Network network) { + for (VoltageLevel vl : network.getVoltageLevels()) { + if (vl.getLowVoltageLimit() <= 0 || Double.isNaN(vl.getLowVoltageLimit())) { + vl.setLowVoltageLimit(0.8 * vl.getNominalV()); + } + if (Double.isNaN(vl.getHighVoltageLimit())) { + vl.setHighVoltageLimit(1.2 * vl.getNominalV()); + } + } + } + } 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 6a8b6aa6..61c5c42d 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/OpenReacRunnerTest.java @@ -76,6 +76,7 @@ private Path getAmplExecPath() throws IOException { @Test void testInputFile() throws IOException { Network network = IeeeCdfNetworkFactory.create118(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network OpenReacParameters parameters = new OpenReacParameters().setObjective( OpenReacOptimisationObjective.BETWEEN_HIGH_AND_LOW_VOLTAGE_LIMIT) .setObjectiveDistance(70) @@ -106,6 +107,7 @@ void testInputFile() throws IOException { @Test public void testOutputFileParsing() throws IOException { Network network = IeeeCdfNetworkFactory.create118(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network // To parse correctly data from output files, there must be an ID in the Ampl mapper // For this we add dummy elements to the network, // they will get exported, but the ampl mapper will have IDs for them. @@ -191,12 +193,14 @@ private void testAllModifAndLoadFlow(Network network, String subFolder, OpenReac @Test public void testOnlyGenerator() throws IOException { Network network = IeeeCdfNetworkFactory.create14(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network testAllModifAndLoadFlow(network, "openreac-output-ieee14", new OpenReacParameters()); } @Test public void testHvdc() throws IOException { Network network = HvdcNetworkFactory.createNetworkWithGenerators2(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network network.getVscConverterStation("cs3").getTerminal().setP(0.0); network.getVscConverterStation("cs4").getTerminal().setP(0.0); OpenReacParameters parameters = new OpenReacParameters(); @@ -207,6 +211,7 @@ public void testHvdc() throws IOException { @Test public void testSvc() throws IOException { Network network = VoltageControlNetworkFactory.createWithStaticVarCompensator(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network network.getVoltageLevelStream().forEach(vl -> vl.setLowVoltageLimit(380).setHighVoltageLimit(420)); network.getStaticVarCompensator("svc1").setVoltageSetpoint(390).setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE); OpenReacParameters parameters = new OpenReacParameters(); @@ -217,6 +222,7 @@ public void testSvc() throws IOException { @Test public void testShuntReconnection() throws IOException { Network network = create(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network OpenReacParameters parameters = new OpenReacParameters(); parameters.addVariableShuntCompensators(List.of("SHUNT")); testAllModifAndLoadFlow(network, "openreac-output-shunt", parameters); @@ -225,6 +231,7 @@ public void testShuntReconnection() throws IOException { @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); OpenReacParameters parameters = new OpenReacParameters(); parameters.addConstantQGenerators(List.of("GEN_1")); @@ -236,6 +243,7 @@ public void testTransformer() throws IOException { public void testRealNetwork() throws IOException { // Network {CC0 SC0}: 53 generators have an inconsistent target voltage and have been discarded from voltage control Network network = IeeeCdfNetworkFactory.create118(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network OpenReacParameters parameters = new OpenReacParameters(); testAllModifAndLoadFlow(network, "openreac-output-real-network", parameters); } @@ -320,4 +328,15 @@ public static Network create() { .add(); return network; } + + void setDefaultVoltageLimits(Network network) { + for (VoltageLevel vl : network.getVoltageLevels()) { + if (vl.getLowVoltageLimit() <= 0 || Double.isNaN(vl.getLowVoltageLimit())) { + vl.setLowVoltageLimit(0.8 * vl.getNominalV()); + } + if (Double.isNaN(vl.getHighVoltageLimit())) { + vl.setHighVoltageLimit(1.2 * vl.getNominalV()); + } + } + } } 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 04d36557..874f4a1c 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 @@ -30,7 +30,7 @@ class VoltageLevelLimitsOverrideInputTest { @Test - void testRelativeOverrideOnUndefinedLimit() { + void testRelativeVoltageOverrideOnUndefinedLimit() { Network network = EurostagTutorialExample1Factory.create(); VoltageLevel vlLoad = network.getVoltageLevel("VLLOAD"); @@ -61,7 +61,7 @@ void testRelativeOverrideOnUndefinedLimit() { } @Test - void testRelativeOverride() throws IOException { + void testValidRelativeVoltageOverride() throws IOException { Network network = EurostagTutorialExample1Factory.create(); // verify relative override can be applied on both defined low/high limits @@ -88,7 +88,7 @@ void testRelativeOverride() throws IOException { } @Test - void testAbsoluteOverride() throws IOException { + void testValidAbsoluteVoltageOverride() throws IOException { Network network = EurostagTutorialExample1Factory.create(); // change high voltage limits to undefined values @@ -115,6 +115,24 @@ void testAbsoluteOverride() throws IOException { } } + @Test + void testInvalidAbsoluteVoltageOverride() { + Network network = EurostagTutorialExample1Factory.create(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network + VoltageLevel vl = network.getVoltageLevel("VLGEN"); + + // Define absolute voltage limit override for "VLGEN" voltage level, with low limit > high limit + OpenReacParameters params = new OpenReacParameters(); + params.addSpecificVoltageLimits(Map.of(vl.getId(), + new VoltageLimitOverrideBuilder().withLowLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE) + .withHighLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE) + .withLowLimitOverride(26) + .withHighLimitOverride(20) + .build())); + + assertThrows(InvalidParametersException.class, () -> params.checkIntegrity(network)); + } + @Test void testUndefinedVoltageLevelLimits() { Network network = IeeeCdfNetworkFactory.create118(); @@ -182,4 +200,15 @@ void testInvalidVoltageLevelOverride() { .build())); assertThrows(InvalidParametersException.class, () -> params3.checkIntegrity(network)); } + + void setDefaultVoltageLimits(Network network) { + for (VoltageLevel vl : network.getVoltageLevels()) { + if (vl.getLowVoltageLimit() <= 0 || Double.isNaN(vl.getLowVoltageLimit())) { + vl.setLowVoltageLimit(0.8 * vl.getNominalV()); + } + if (Double.isNaN(vl.getHighVoltageLimit())) { + vl.setHighVoltageLimit(1.2 * vl.getNominalV()); + } + } + } } From 3dd9fc99ebb591685313d309471273fdcdc5a40e Mon Sep 17 00:00:00 2001 From: parvy Date: Mon, 9 Oct 2023 18:52:22 +0200 Subject: [PATCH 05/16] Fix VoltageLevelLimitsOverrideInputTest unit test. Signed-off-by: parvy --- .../input/VoltageLevelLimitsOverrideInputTest.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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 874f4a1c..2427d019 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 @@ -32,6 +32,7 @@ class VoltageLevelLimitsOverrideInputTest { @Test void testRelativeVoltageOverrideOnUndefinedLimit() { Network network = EurostagTutorialExample1Factory.create(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network VoltageLevel vlLoad = network.getVoltageLevel("VLLOAD"); // if relative override is intended on undefined low voltage limit, throws exception @@ -63,6 +64,7 @@ void testRelativeVoltageOverrideOnUndefinedLimit() { @Test void testValidRelativeVoltageOverride() throws IOException { Network network = EurostagTutorialExample1Factory.create(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network // verify relative override can be applied on both defined low/high limits VoltageLevel vlGen = network.getVoltageLevel("VLGEN"); @@ -90,6 +92,7 @@ void testValidRelativeVoltageOverride() throws IOException { @Test void testValidAbsoluteVoltageOverride() throws IOException { Network network = EurostagTutorialExample1Factory.create(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network // change high voltage limits to undefined values VoltageLevel vlgen = network.getVoltageLevel("VLGEN"); @@ -136,6 +139,8 @@ void testInvalidAbsoluteVoltageOverride() { @Test void testUndefinedVoltageLevelLimits() { Network network = IeeeCdfNetworkFactory.create118(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network + VoltageLevel vl = network.getVoltageLevels().iterator().next(); OpenReacParameters params = new OpenReacParameters(); @@ -158,9 +163,11 @@ void testUndefinedVoltageLevelLimits() { @Test void testNegativeLowVoltageValueOverride() { Network network = IeeeCdfNetworkFactory.create118(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network + VoltageLevel vl = network.getVoltageLevels().iterator().next(); - vl.setLowVoltageLimit(400); vl.setHighVoltageLimit(480); + vl.setLowVoltageLimit(400); // if low relative voltage override leads to negative voltage limit, throws exception OpenReacParameters params = new OpenReacParameters(); @@ -188,6 +195,7 @@ void testNegativeLowVoltageValueOverride() { @Test void testInvalidVoltageLevelOverride() { Network network = IeeeCdfNetworkFactory.create118(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network // if voltage level (on which is applied override) is not in the network, throws exception OpenReacParameters params3 = new OpenReacParameters(); From fd98b1f88e79a179df4703cc249eb7703e3a6409 Mon Sep 17 00:00:00 2001 From: parvy Date: Tue, 10 Oct 2023 15:27:22 +0200 Subject: [PATCH 06/16] Modify VoltageLimitOverride class to one side voltage limit override Signed-off-by: parvy --- .../com/powsybl/openreac/OpenReacTool.java | 9 +- .../parameters/input/OpenReacParameters.java | 187 +++++++++++------- .../VoltageLevelLimitsOverrideInput.java | 78 ++++---- .../input/VoltageLimitOverride.java | 58 +++--- .../input/VoltageLimitOverrideBuilder.java | 50 ----- .../json/OpenReacParametersDeserializer.java | 4 +- .../VoltageLimitOverrideDeserializer.java | 26 +-- .../json/VoltageLimitOverrideSerializer.java | 7 +- .../java/com/powsybl/openreac/ItoolsTest.java | 13 +- .../VoltageLevelLimitsOverrideInputTest.java | 126 +++--------- .../input/VoltageLimitsOverrideTest.java | 83 ++++---- .../input/json/OpenReacJsonModuleTest.java | 44 +++-- open-reac/src/test/resources/parameters.json | 41 ++-- 13 files changed, 337 insertions(+), 389 deletions(-) delete mode 100644 open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java diff --git a/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java b/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java index 24574142..86b67893 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java +++ b/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java @@ -29,6 +29,7 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; +import org.jgrapht.alg.util.Pair; import java.io.IOException; import java.io.InputStream; @@ -165,9 +166,11 @@ public OpenReacParameters createOpenReacParameters(CommandLine line, String voltageId = node.get("id").asText(); double lowerPercent = node.get("lower").asDouble(); double upperPercent = node.get("upper").asDouble(); - openReacParameters.addSpecificVoltageLimits(Map.of(voltageId, - new VoltageLimitOverride(VoltageLimitOverride.OverrideKind.RELATIVE, VoltageLimitOverride.OverrideKind.RELATIVE, - lowerPercent, upperPercent))); + + List> voltageLimitOverrides = new ArrayList<>(); + voltageLimitOverrides.add(new Pair<>(voltageId, new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, lowerPercent))); + voltageLimitOverrides.add(new Pair<>(voltageId, new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, upperPercent))); + openReacParameters.addSpecificVoltageLimits(voltageLimitOverrides); }); } boolean objectiveSet = false; diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java index 30a12a86..df86a11c 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java @@ -12,6 +12,7 @@ import com.powsybl.openreac.parameters.input.algo.OpenReacAlgoParam; import com.powsybl.openreac.parameters.input.algo.OpenReacAlgoParamImpl; import com.powsybl.openreac.parameters.input.algo.OpenReacOptimisationObjective; +import org.jgrapht.alg.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,7 +29,7 @@ public class OpenReacParameters { private static final String OBJECTIVE_DISTANCE_KEY = "ratio_voltage_target"; - private final Map specificVoltageLimits = new HashMap<>(); + private final List> specificVoltageLimits = new ArrayList<>(); private final List variableShuntCompensators = new ArrayList<>(); private final List constantQGenerators = new ArrayList<>(); private final List variableTwoWindingsTransformers = new ArrayList<>(); @@ -49,8 +50,8 @@ public class OpenReacParameters { * The override is ignored if one or both of the voltage limit are NaN. * @param specificVoltageLimits keys: a VoltageLevel ID, values: low and high delta limits (kV). */ - public OpenReacParameters addSpecificVoltageLimits(Map specificVoltageLimits) { - this.specificVoltageLimits.putAll(Objects.requireNonNull(specificVoltageLimits)); + public OpenReacParameters addSpecificVoltageLimits(List> specificVoltageLimits) { + this.specificVoltageLimits.addAll(Objects.requireNonNull(specificVoltageLimits)); return this; } @@ -133,7 +134,7 @@ public List getVariableShuntCompensators() { return variableShuntCompensators; } - public Map getSpecificVoltageLimits() { + public List> getSpecificVoltageLimits() { return specificVoltageLimits; } @@ -181,102 +182,144 @@ public void checkIntegrity(Network network) throws InvalidParametersException { } // Check integrity of voltage overrides - boolean inconsistentOverride = false; - for (String voltageLevelId : getSpecificVoltageLimits().keySet()) { - VoltageLevel voltageLevel = network.getVoltageLevel(voltageLevelId); - - // Check existence of voltage level on which is applied voltage limit override - if (voltageLevel == null) { - LOGGER.warn("Voltage level " + voltageLevelId + " not found in the network."); - inconsistentOverride = true; - - } else { - // if low voltage override is relative, check new low voltage limit is > 0 - VoltageLimitOverride override = getSpecificVoltageLimits().get(voltageLevelId); - if (override.getLowLimitKind() == VoltageLimitOverride.OverrideKind.RELATIVE && - voltageLevel.getNominalV() + override.getLowLimitOverride() < 0) { - LOGGER.warn("Voltage level " + voltageLevelId + " relative override leads to negative low voltage limit."); - inconsistentOverride = true; - } - // if low voltage override is absolute, check new low voltage limit is > 0 - if (override.getLowLimitKind() == VoltageLimitOverride.OverrideKind.ABSOLUTE && - override.getLowLimitOverride() < 0) { - LOGGER.warn("Voltage level " + voltageLevelId + " absolute override leads to negative low voltage limit."); - inconsistentOverride = true; - } - // if low/high voltage overrides are absolute, check new low limit is < new high limit - if (override.getLowLimitKind() == VoltageLimitOverride.OverrideKind.ABSOLUTE && - override.getHighLimitKind() == VoltageLimitOverride.OverrideKind.ABSOLUTE && - override.getLowLimitOverride() > override.getHighLimitOverride()) { - LOGGER.warn("Voltage level " + voltageLevelId + " override leads to low voltage limit > high voltage limit."); - inconsistentOverride = true; - } - } + boolean integrityVoltageLimitOverrides = checkVoltageLimitOverrides(network); + if (!integrityVoltageLimitOverrides) { + throw new InvalidParametersException("At least one voltage limit override is inconsistent."); + } + // Check integrity of low/high voltage limits, taking into account voltage limit overrides + boolean integrityVoltageLevelLimits = checkVoltageLevelLimits(network); + if (!integrityVoltageLevelLimits) { + throw new InvalidParametersException("At least one voltage level has an undefined or incorrect voltage limit."); } - if (inconsistentOverride) { - throw new InvalidParametersException("At least one voltage limit override is inconsistent."); + if (objective.equals(OpenReacOptimisationObjective.BETWEEN_HIGH_AND_LOW_VOLTAGE_LIMIT) && objectiveDistance == null) { + throw new InvalidParametersException("In using " + OpenReacOptimisationObjective.BETWEEN_HIGH_AND_LOW_VOLTAGE_LIMIT + + " as objective, a distance in percent between low and high voltage limits is expected."); } - // Check integrity of low/high voltage limits, taking into account voltage limit overrides - boolean limitUndefined = false; + } + + boolean checkVoltageLevelLimits(Network network) { + boolean integrityVoltageLevelLimits = true; + for (VoltageLevel vl : network.getVoltageLevels()) { double lowLimit = vl.getLowVoltageLimit(); double highLimit = vl.getHighVoltageLimit(); - if (lowLimit <= 0 || Double.isNaN(lowLimit)) { - - // Check if voltage override exists - if (getSpecificVoltageLimits().containsKey(vl.getId())) { - VoltageLimitOverride override = getSpecificVoltageLimits().get(vl.getId()); - - // Relative override on undefined low voltage limit is incorrect - if (override.getLowLimitKind() == VoltageLimitOverride.OverrideKind.RELATIVE) { - LOGGER.warn("Relative voltage override impossible on undefined low voltage limit for voltage level '" - + vl.getId() + "'."); - limitUndefined = true; + // If low voltage limit is undefined... + if (Double.isNaN(lowLimit)) { + + // find associated override if it exists + boolean hasOverride = false; + VoltageLimitOverride associatedOverride = null; + for (Pair pair : getSpecificVoltageLimits()) { + if (pair.getFirst().equals(vl.getId()) && pair.getSecond().getSide() == VoltageLimitOverride.OverrideSide.LOW) { + hasOverride = true; + associatedOverride = pair.getSecond(); + break; } + } - // If no voltage override, low voltage limit is undefined or incorrect - } else { + // ... verify if there is an override for the undefined limit + if (!hasOverride) { LOGGER.warn("Voltage level '" + vl.getId() + "' has no low voltage limit defined. " + "Please add one or use a voltage limit override."); - limitUndefined = true; + integrityVoltageLevelLimits = false; + + // ... verify override is not relative + } else if (associatedOverride.isRelative()) { + LOGGER.warn("Relative voltage override impossible on undefined low voltage limit for voltage level '" + + vl.getId() + "'."); + integrityVoltageLevelLimits = false; } } - // If high voltage limit is undefined, check if voltage override exists + // If high voltage limit is undefined... if (Double.isNaN(highLimit)) { - // Check if voltage override exists - if (getSpecificVoltageLimits().containsKey(vl.getId())) { - VoltageLimitOverride override = getSpecificVoltageLimits().get(vl.getId()); - - // Relative override on undefined high voltage limit is incorrect - if (override.getHighLimitKind() == VoltageLimitOverride.OverrideKind.RELATIVE) { - LOGGER.warn("Relative voltage override impossible on undefined high voltage limit for voltage level '" - + vl.getId() + "'."); - limitUndefined = true; + // find associated override if it exists + boolean hasOverride = false; + VoltageLimitOverride associatedOverride = null; + for (Pair pair : getSpecificVoltageLimits()) { + if (pair.getFirst().equals(vl.getId()) && pair.getSecond().getSide() == VoltageLimitOverride.OverrideSide.HIGH) { + hasOverride = true; + associatedOverride = pair.getSecond(); + break; } + } - // If no voltage override, high voltage limit is undefined - } else { + // ... verify if there is an override for the undefined limit + if (!hasOverride) { LOGGER.warn("Voltage level '" + vl.getId() + "' has no high voltage limit defined. " + "Please add one or use a voltage limit override."); - limitUndefined = true; + integrityVoltageLevelLimits = false; + + // ... verify override is not relative + } else if (associatedOverride.isRelative()) { + LOGGER.warn("Relative voltage override impossible on undefined high voltage limit for voltage level '" + + vl.getId() + "'."); + integrityVoltageLevelLimits = false; } } } - if (limitUndefined) { - throw new InvalidParametersException("At least one voltage level has an undefined or incorrect voltage limit."); - } + return integrityVoltageLevelLimits; + } + + /** + * @param network the network on which are applied voltage limit overrides. + * @return true if the integrity of voltage limit overrides is verifies, false otherwise. + */ + boolean checkVoltageLimitOverrides(Network network) { + // Check integrity of voltage overrides + boolean integrityVoltageLimitOverrides = true; + for (Pair pair : getSpecificVoltageLimits()) { + String voltageLevelId = pair.getFirst(); + VoltageLevel voltageLevel = network.getVoltageLevel(voltageLevelId); + + // Check existence of voltage level on which is applied voltage limit override + if (voltageLevel == null) { + LOGGER.warn("Voltage level " + voltageLevelId + " not found in the network."); + integrityVoltageLimitOverrides = false; + + } else { + VoltageLimitOverride override = pair.getSecond(); + + // if the override is relative... + if (override.isRelative()) { + + // ... and on low limit ... + if (override.getSide() == VoltageLimitOverride.OverrideSide.LOW) { + + // ... verify low voltage limit is defined + if (Double.isNaN(voltageLevel.getLowVoltageLimit())) { + LOGGER.warn("Voltage level '" + voltageLevelId + "' has undefined low voltage limit, " + + "relative voltage limit override impossible."); + integrityVoltageLimitOverrides = false; + } + + // ... verify low voltage limit override does not lead to negative limit value + if (override.getLimitOverride() + voltageLevel.getLowVoltageLimit() < 0) { + LOGGER.warn("Voltage level " + voltageLevelId + " low relative override leads to negative low voltage limit."); + integrityVoltageLimitOverrides = false; + } + // ... and on high limit ... + } else { + + // ... verify high voltage limit is defined + if (Double.isNaN(voltageLevel.getHighVoltageLimit())) { + LOGGER.warn("Voltage level '" + voltageLevelId + "' has undefined high voltage limit, " + + "relative voltage limit override impossible."); + integrityVoltageLimitOverrides = false; + } + } + + } + } - if (objective.equals(OpenReacOptimisationObjective.BETWEEN_HIGH_AND_LOW_VOLTAGE_LIMIT) && objectiveDistance == null) { - throw new InvalidParametersException("In using " + OpenReacOptimisationObjective.BETWEEN_HIGH_AND_LOW_VOLTAGE_LIMIT + - " as objective, a distance in percent between low and high voltage limits is expected."); } + return integrityVoltageLimitOverrides; } } 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 3fd6ce97..b7f16281 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 @@ -11,11 +11,13 @@ import com.powsybl.commons.util.StringToIntMapper; import com.powsybl.iidm.network.Network; import com.powsybl.openreac.parameters.AmplIOUtils; +import org.jgrapht.alg.util.Pair; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; @@ -25,9 +27,9 @@ public class VoltageLevelLimitsOverrideInput implements AmplInputFile { private static final String FILENAME = "ampl_network_substations_override.txt"; - private final Map normalizedVoltageLimitsOverride; + private final Map> normalizedVoltageLimitsOverride; - public VoltageLevelLimitsOverrideInput(Map voltageLimitsOverride, Network network) { + public VoltageLevelLimitsOverrideInput(List> voltageLimitsOverride, Network network) { Objects.requireNonNull(voltageLimitsOverride); Objects.requireNonNull(network); this.normalizedVoltageLimitsOverride = new HashMap<>(); @@ -38,50 +40,41 @@ public VoltageLevelLimitsOverrideInput(Map voltage * voltageLimitsOverride contains absolute voltage limits. * This function compute limits in pair-unit quantities. */ - private void transformToNormalizedVoltage(Map voltageLimitsOverride, Network network) { - for (Map.Entry entry : voltageLimitsOverride.entrySet()) { - String voltageLevelId = entry.getKey(); - VoltageLimitOverride limits = entry.getValue(); + private void transformToNormalizedVoltage(List> voltageLimitsOverride, Network network) { + for (Pair pair : voltageLimitsOverride) { + String voltageLevelId = pair.getFirst(); + VoltageLimitOverride override = pair.getSecond(); - double previousLowVoltageLimit = network.getVoltageLevel(voltageLevelId).getLowVoltageLimit(); - double previousHighVoltageLimit = network.getVoltageLevel(voltageLevelId).getHighVoltageLimit(); + // get previous voltage limit values double nominalV = network.getVoltageLevel(voltageLevelId).getNominalV(); - - VoltageLimitOverrideBuilder builder = new VoltageLimitOverrideBuilder() - .withLowLimitKind(limits.getLowLimitKind()) - .withHighLimitKind(limits.getHighLimitKind()); - - // compute low normalized override - if (limits.getLowLimitKind() == VoltageLimitOverride.OverrideKind.ABSOLUTE) { - builder.withLowLimitOverride(limits.getLowLimitOverride() / nominalV); - } else if (limits.getLowLimitKind() == VoltageLimitOverride.OverrideKind.RELATIVE) { - // if override is relative, must check that previous limit of voltage level is defined - if (!Double.isNaN(previousLowVoltageLimit)) { - builder.withLowLimitOverride((previousLowVoltageLimit + limits.getLowLimitOverride()) / nominalV); + double previousNormalizedLowVoltageLimit = network.getVoltageLevel(voltageLevelId).getLowVoltageLimit() / nominalV; + double previousNormalizedHighVoltageLimit = network.getVoltageLevel(voltageLevelId).getHighVoltageLimit() / nominalV; + + // get or create voltage limit override of the voltage level + Pair newLimits = normalizedVoltageLimitsOverride.containsKey(voltageLevelId) ? normalizedVoltageLimitsOverride.get(voltageLevelId) + : new Pair<>(previousNormalizedLowVoltageLimit, previousNormalizedHighVoltageLimit); + + // if override is low ... + if (override.getSide() == VoltageLimitOverride.OverrideSide.LOW) { + // ... and relative, add relative override + if (override.isRelative()) { + newLimits.setFirst(newLimits.getFirst() + override.getLimitOverride() / nominalV); + // ... and absolute, replace by absolute override } else { - throw new IllegalArgumentException("Relative override must be done on valid low voltage limit"); + newLimits.setFirst(override.getLimitOverride() / nominalV); } - // if no kind given, then no low voltage limit override + // if override is high ... } else { - builder.withLowLimitOverride(previousLowVoltageLimit / nominalV); - } - - // compute high normalized override - if (limits.getHighLimitKind() == VoltageLimitOverride.OverrideKind.ABSOLUTE) { - builder.withHighLimitOverride(limits.getHighLimitOverride() / nominalV); - } else if (limits.getHighLimitKind() == VoltageLimitOverride.OverrideKind.RELATIVE) { - // if override is relative, must check that previous limit of voltage level is defined - if (!Double.isNaN(previousHighVoltageLimit)) { - builder.withHighLimitOverride((previousHighVoltageLimit + limits.getHighLimitOverride()) / nominalV); + // ... and relative, add relative override + if (override.isRelative()) { + newLimits.setSecond(newLimits.getSecond() + override.getLimitOverride() / nominalV); + // ... and absolute, replace by absolute override } else { - throw new IllegalArgumentException("Relative override must be done on valid high voltage limit"); + newLimits.setSecond(override.getLimitOverride() / nominalV); } - // if no kind given, then no high voltage limit override - } else { - builder.withHighLimitOverride(previousHighVoltageLimit / nominalV); } - normalizedVoltageLimitsOverride.put(voltageLevelId, builder.build()); + normalizedVoltageLimitsOverride.put(voltageLevelId, newLimits); } } @@ -96,16 +89,13 @@ public InputStream getParameterFileAsStream(StringToIntMapper string dataBuilder.append("#num minV (pu) maxV (pu) id"); dataBuilder.append(System.lineSeparator()); - for (Map.Entry entry : normalizedVoltageLimitsOverride.entrySet()) { + for (Map.Entry> entry : normalizedVoltageLimitsOverride.entrySet()) { String voltageLevelId = entry.getKey(); - VoltageLimitOverride limits = entry.getValue(); + Pair limits = entry.getValue(); - if (!Double.isNaN(limits.getLowLimitOverride()) && !Double.isNaN(limits.getHighLimitOverride())) { + if (!Double.isNaN(limits.getFirst()) || !Double.isNaN(limits.getSecond())) { int amplId = stringToIntMapper.getInt(AmplSubset.VOLTAGE_LEVEL, voltageLevelId); - double newLowVoltageLimit = limits.getLowLimitOverride(); - double newHighVoltageLimit = limits.getHighLimitOverride(); - - String[] tokens = {Integer.toString(amplId), Double.toString(newLowVoltageLimit), Double.toString(newHighVoltageLimit), AmplIOUtils.addQuotes(voltageLevelId)}; + String[] tokens = {Integer.toString(amplId), Double.toString(limits.getFirst()), Double.toString(limits.getSecond()), AmplIOUtils.addQuotes(voltageLevelId)}; dataBuilder.append(String.join(" ", tokens)); dataBuilder.append(System.lineSeparator()); } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java index 88a515cc..c1b2d1a9 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java @@ -6,6 +6,8 @@ */ package com.powsybl.openreac.parameters.input; +import com.powsybl.openreac.exceptions.InvalidParametersException; + import java.util.Objects; /** @@ -16,38 +18,39 @@ */ public class VoltageLimitOverride { - public enum OverrideKind { - ABSOLUTE, RELATIVE; - } - - private final OverrideKind lowLimitKind; - private final OverrideKind highLimitKind; - - private final double lowLimitOverride; - private final double highLimitOverride; + public enum OverrideSide { + HIGH, LOW; - public double getLowLimitOverride() { - return lowLimitOverride; + @Override + public String toString() { + return this == HIGH ? "HIGH" : "LOW"; + } } - public double getHighLimitOverride() { - return highLimitOverride; + private final OverrideSide side; // indicates if the override is done on low/high voltage limit + private final boolean isRelative; // if true, override is absolute. if false, override is absolute + private final double limitOverride; // value of the override + + public OverrideSide getSide() { + return side; } - public OverrideKind getLowLimitKind() { - return lowLimitKind; + public boolean isRelative() { + return isRelative; } - public OverrideKind getHighLimitKind() { - return highLimitKind; + public double getLimitOverride() { + return limitOverride; } - public VoltageLimitOverride(OverrideKind lowLimitKind, OverrideKind highLimitKind, - double lowLimitOverride, double highLimitOverride) { - this.lowLimitKind = lowLimitKind; - this.highLimitKind = highLimitKind; - this.lowLimitOverride = lowLimitOverride; - this.highLimitOverride = highLimitOverride; + public VoltageLimitOverride(OverrideSide side, boolean isRelative, double limitOverride) { + if (Double.isNaN(limitOverride) || limitOverride <= 0 && !isRelative) { + throw new InvalidParametersException("The voltage limit override is incorrect. " + + "It must be defined and > 0 if absolute."); + } + this.side = side; + this.isRelative = isRelative; + this.limitOverride = limitOverride; } @Override @@ -59,14 +62,13 @@ public boolean equals(Object o) { return false; } VoltageLimitOverride that = (VoltageLimitOverride) o; - return that.lowLimitKind == lowLimitKind - && Double.compare(that.lowLimitOverride, lowLimitOverride) == 0 - && that.highLimitKind == highLimitKind - && Double.compare(that.highLimitOverride, highLimitOverride) == 0; + return that.side == side + && that.isRelative == isRelative + && Double.compare(that.limitOverride, limitOverride) == 0; } @Override public int hashCode() { - return Objects.hash(lowLimitKind, lowLimitOverride, highLimitKind, highLimitOverride); + return Objects.hash(side, isRelative, limitOverride); } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java deleted file mode 100644 index 29baf797..00000000 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverrideBuilder.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * 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/. - */ -package com.powsybl.openreac.parameters.input; - -public class VoltageLimitOverrideBuilder { - - private VoltageLimitOverride.OverrideKind lowLimitKind; - private VoltageLimitOverride.OverrideKind highLimitKind; - - private double lowLimitOverride; - private double highLimitOverride; - - public VoltageLimitOverride build() { - if (lowLimitKind == null && highLimitKind == null) { - throw new IllegalStateException("For a valid voltage limit override, the kind of one side must be provided."); - } - if (lowLimitOverride == 0 && highLimitOverride == 0) { - throw new IllegalStateException("For a valid voltage limit override, at least one value must be provided."); - } - if (Double.isNaN(lowLimitOverride) || Double.isNaN(highLimitOverride)) { - throw new IllegalStateException("For a valid voltage limit override, no undefined value must be provided."); - } - return new VoltageLimitOverride(lowLimitKind, highLimitKind, lowLimitOverride, highLimitOverride); - } - - public VoltageLimitOverrideBuilder withLowLimitKind(VoltageLimitOverride.OverrideKind lowVoltageLimitKind) { - this.lowLimitKind = lowVoltageLimitKind; - return this; - } - - public VoltageLimitOverrideBuilder withHighLimitKind(VoltageLimitOverride.OverrideKind highVoltageLimitKind) { - this.highLimitKind = highVoltageLimitKind; - return this; - } - - public VoltageLimitOverrideBuilder withLowLimitOverride(double lowVoltageLimitOverride) { - this.lowLimitOverride = lowVoltageLimitOverride; - return this; - } - - public VoltageLimitOverrideBuilder withHighLimitOverride(double highVoltageLimitOverride) { - this.highLimitOverride = highVoltageLimitOverride; - return this; - } - -} diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/OpenReacParametersDeserializer.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/OpenReacParametersDeserializer.java index 3a1c79db..0a7a6eb0 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/OpenReacParametersDeserializer.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/OpenReacParametersDeserializer.java @@ -15,9 +15,9 @@ import com.powsybl.openreac.parameters.input.VoltageLimitOverride; import com.powsybl.openreac.parameters.input.algo.OpenReacAlgoParam; import com.powsybl.openreac.parameters.input.algo.OpenReacOptimisationObjective; +import org.jgrapht.alg.util.Pair; import java.io.IOException; -import java.util.HashMap; import java.util.List; /** @@ -43,7 +43,7 @@ public OpenReacParameters deserialize(JsonParser parser, DeserializationContext break; case "specificVoltageLimits": parser.nextToken(); - parameters.addSpecificVoltageLimits(parser.readValueAs(new TypeReference>() { })); + parameters.addSpecificVoltageLimits(parser.readValueAs(new TypeReference>>() { })); break; case "variableShuntCompensators": parser.nextToken(); diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java index 59ecb47d..e58593d6 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java @@ -26,34 +26,28 @@ public VoltageLimitOverrideDeserializer() { @Override public VoltageLimitOverride deserialize(JsonParser parser, DeserializationContext deserializationContext) throws IOException { - VoltageLimitOverride.OverrideKind lowLimitKind = null; - VoltageLimitOverride.OverrideKind highLimitKind = null; - double lowLimitOverride = 0; - double highLimitOverride = 0; + VoltageLimitOverride.OverrideSide side = null; + boolean isRelative = false; + double overrideValue = 0; while (parser.nextToken() != JsonToken.END_OBJECT) { switch (parser.getCurrentName()) { - case "lowLimitKind": + case "overrideSide": parser.nextToken(); - lowLimitKind = parser.readValueAs(VoltageLimitOverride.OverrideKind.class); + side = parser.readValueAs(VoltageLimitOverride.OverrideSide.class); break; - case "highLimitKind": + case "isRelative": parser.nextToken(); - highLimitKind = parser.readValueAs(VoltageLimitOverride.OverrideKind.class); + isRelative = parser.readValueAs(boolean.class); break; - case "lowLimitOverride": + case "overrideValue": parser.nextToken(); - lowLimitOverride = parser.readValueAs(Double.class); - break; - case "highLimitOverride": - parser.nextToken(); - highLimitOverride = parser.readValueAs(Double.class); + overrideValue = parser.readValueAs(Double.class); break; default: throw new IllegalStateException("Unexpected field: " + parser.getCurrentName()); } } - return new VoltageLimitOverride(lowLimitKind, highLimitKind, - lowLimitOverride, highLimitOverride); + return new VoltageLimitOverride(side, isRelative, overrideValue); } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java index ae09b88a..e2ece06a 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java @@ -26,10 +26,9 @@ public VoltageLimitOverrideSerializer() { @Override public void serialize(VoltageLimitOverride voltageLimitOverride, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeStartObject(); - jsonGenerator.writeObjectField("lowLimitKind", voltageLimitOverride.getLowLimitKind()); - jsonGenerator.writeObjectField("highLimitKind", voltageLimitOverride.getHighLimitKind()); - jsonGenerator.writeNumberField("lowLimitOverride", voltageLimitOverride.getLowLimitOverride()); - jsonGenerator.writeNumberField("highLimitOverride", voltageLimitOverride.getHighLimitOverride()); + jsonGenerator.writeObjectField("overrideSide", voltageLimitOverride.getSide()); + jsonGenerator.writeObjectField("isRelative", voltageLimitOverride.isRelative()); + jsonGenerator.writeNumberField("overrideValue", voltageLimitOverride.getLimitOverride()); jsonGenerator.writeEndObject(); } } diff --git a/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java b/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java index 0f9f7488..5d79a5dc 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java @@ -16,14 +16,15 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.ParseException; +import org.jgrapht.alg.util.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.io.IOException; import java.nio.file.FileSystem; import java.nio.file.Files; +import java.util.ArrayList; import java.util.List; -import java.util.Map; import static org.junit.jupiter.api.Assertions.*; @@ -62,9 +63,13 @@ public void testCreateOpenReacParameters() throws ParseException, IOException { assertEquals(List.of("2-winding-transfo"), loadedParams.getVariableTwoWindingsTransformers(), "Parsing of OpenReac parameters is wrong."); assertEquals(List.of("constant-q-gen"), loadedParams.getConstantQGenerators(), "Parsing of OpenReac parameters is wrong."); assertEquals(List.of("var-shunt", "var-shunt-2"), loadedParams.getVariableShuntCompensators(), "Parsing of OpenReac parameters is wrong."); - assertEquals(Map.of("voltageLevelId", new VoltageLimitOverride(VoltageLimitOverride.OverrideKind.RELATIVE, VoltageLimitOverride.OverrideKind.RELATIVE, -5, 5)), - loadedParams.getSpecificVoltageLimits(), - "Parsing of OpenReac parameters is wrong."); + + // List of voltage limit overrides + List> vloList = new ArrayList<>(); + vloList.add(new Pair<>("voltageLevelId", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, -5))); + vloList.add(new Pair<>("voltageLevelId", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, 5))); + + assertEquals(vloList, loadedParams.getSpecificVoltageLimits(), "Parsing of OpenReac parameters is wrong."); assertEquals(OpenReacOptimisationObjective.SPECIFIC_VOLTAGE_PROFILE, loadedParams.getObjective(), "Parsing of OpenReac parameters is wrong."); } 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 2427d019..c03f5226 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 @@ -16,11 +16,13 @@ import com.powsybl.iidm.network.VoltageLevel; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; import com.powsybl.openreac.exceptions.InvalidParametersException; +import org.jgrapht.alg.util.Pair; import org.junit.jupiter.api.Test; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -29,38 +31,6 @@ */ class VoltageLevelLimitsOverrideInputTest { - @Test - void testRelativeVoltageOverrideOnUndefinedLimit() { - Network network = EurostagTutorialExample1Factory.create(); - setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network - VoltageLevel vlLoad = network.getVoltageLevel("VLLOAD"); - - // if relative override is intended on undefined low voltage limit, throws exception - vlLoad.setLowVoltageLimit(Double.NaN) - .setHighVoltageLimit(150); - - Map voltageLimitsOverride = Map.of("VLLOAD", - new VoltageLimitOverrideBuilder() - .withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) - .withLowLimitOverride(-1.3) - .build()); - assertThrows(IllegalArgumentException.class, - () -> new VoltageLevelLimitsOverrideInput(voltageLimitsOverride, network)); - - // if relative override is intended on undefined high voltage limit, throws exception - vlLoad.setLowVoltageLimit(130) - .setHighVoltageLimit(Double.NaN); - - Map voltageLimitsOverride2 = Map.of("VLLOAD", - new VoltageLimitOverrideBuilder() - .withHighLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) - .withHighLimitOverride(4.2) - .build()); - - assertThrows(IllegalArgumentException.class, - () -> new VoltageLevelLimitsOverrideInput(voltageLimitsOverride2, network)); - } - @Test void testValidRelativeVoltageOverride() throws IOException { Network network = EurostagTutorialExample1Factory.create(); @@ -71,20 +41,18 @@ void testValidRelativeVoltageOverride() throws IOException { vlGen.setLowVoltageLimit(20) .setHighVoltageLimit(26); - Map voltageLimitsOverride = Map.of("VLGEN", - new VoltageLimitOverrideBuilder() - .withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) - .withLowLimitOverride(-1) - .withHighLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) - .withHighLimitOverride(2) - .build()); + List> voltageLimitsOverride = new ArrayList<>(); + voltageLimitsOverride.add(new Pair<>("VLGEN", + new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, -1))); + voltageLimitsOverride.add(new Pair<>("VLGEN", + new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, 2))); 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); String ref = String.join(System.lineSeparator(), "#num minV (pu) maxV (pu) id", - "1 0.7916666666666666 1.1666666666666667 'VLGEN'") + System.lineSeparator() + System.lineSeparator(); + "1 0.7916666666666667 1.1666666666666665 'VLGEN'") + System.lineSeparator() + System.lineSeparator(); assertEquals(ref, data); } } @@ -99,16 +67,13 @@ void testValidAbsoluteVoltageOverride() throws IOException { vlgen.setLowVoltageLimit(Double.NaN) .setHighVoltageLimit(Double.NaN); - // verify absolute override can be applied on both undefined low/high limits - VoltageLimitOverride vlo = new VoltageLimitOverrideBuilder().withLowLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE) - .withHighLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE) - .withLowLimitOverride(20) - .withHighLimitOverride(26) - .build(); + List> voltageLimitsOverride = new ArrayList<>(); + voltageLimitsOverride.add(new Pair<>("VLGEN", + new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, false, 20))); + voltageLimitsOverride.add(new Pair<>("VLGEN", + new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, false, 26))); - Map voltageLimtisOverride = Map.of("VLGEN", vlo); - - VoltageLevelLimitsOverrideInput input = new VoltageLevelLimitsOverrideInput(voltageLimtisOverride, network); + 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); @@ -119,49 +84,31 @@ void testValidAbsoluteVoltageOverride() throws IOException { } @Test - void testInvalidAbsoluteVoltageOverride() { - Network network = EurostagTutorialExample1Factory.create(); - setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network - VoltageLevel vl = network.getVoltageLevel("VLGEN"); - - // Define absolute voltage limit override for "VLGEN" voltage level, with low limit > high limit - OpenReacParameters params = new OpenReacParameters(); - params.addSpecificVoltageLimits(Map.of(vl.getId(), - new VoltageLimitOverrideBuilder().withLowLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE) - .withHighLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE) - .withLowLimitOverride(26) - .withHighLimitOverride(20) - .build())); - - assertThrows(InvalidParametersException.class, () -> params.checkIntegrity(network)); - } - - @Test - void testUndefinedVoltageLevelLimits() { + void testUndefinedVoltageLimitsWithoutOverride() { Network network = IeeeCdfNetworkFactory.create118(); setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network VoltageLevel vl = network.getVoltageLevels().iterator().next(); OpenReacParameters params = new OpenReacParameters(); - // if only low voltage limit of one voltage level is undefined, invalid OpenReacParameters + // if one low voltage limit is undefined, invalid OpenReacParameters vl.setLowVoltageLimit(Double.NaN); vl.setHighVoltageLimit(480); assertThrows(PowsyblException.class, () -> params.checkIntegrity(network)); - // if only high voltage limit is undefined, invalid OpenReacParameters + // if one high voltage limit is undefined, invalid OpenReacParameters vl.setLowVoltageLimit(480); vl.setHighVoltageLimit(Double.NaN); assertThrows(PowsyblException.class, () -> params.checkIntegrity(network)); - // if both low/high voltage limits are undefined, invalid OpenReacParameters + // if both low/high voltage limit are undefined, invalid OpenReacParameters vl.setLowVoltageLimit(Double.NaN); vl.setHighVoltageLimit(Double.NaN); assertThrows(PowsyblException.class, () -> params.checkIntegrity(network)); } @Test - void testNegativeLowVoltageValueOverride() { + void testVoltageOverrideWithNegativeLowVoltageValue() { Network network = IeeeCdfNetworkFactory.create118(); setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network @@ -171,41 +118,22 @@ void testNegativeLowVoltageValueOverride() { // if low relative voltage override leads to negative voltage limit, throws exception OpenReacParameters params = new OpenReacParameters(); - params.addSpecificVoltageLimits(Map.of(vl.getId(), - new VoltageLimitOverrideBuilder() - .withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) - .withLowLimitOverride(-410) - .withHighLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) - .withHighLimitOverride(0) - .build())); + List> voltageLimitsOverride = new ArrayList<>(); + voltageLimitsOverride.add(new Pair<>(vl.getId(), new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, -410))); + params.addSpecificVoltageLimits(voltageLimitsOverride); assertThrows(InvalidParametersException.class, () -> params.checkIntegrity(network)); - - // if low absolute voltage override leads to negative voltage limit, throws exception - OpenReacParameters params2 = new OpenReacParameters(); - params2.addSpecificVoltageLimits(Map.of(vl.getId(), - new VoltageLimitOverrideBuilder() - .withLowLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE) - .withLowLimitOverride(-10) - .withHighLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) - .withHighLimitOverride(0) - .build())); - assertThrows(InvalidParametersException.class, () -> params2.checkIntegrity(network)); } @Test - void testInvalidVoltageLevelOverride() { + void testVoltageOverrideOnInvalidVoltageLevel() { Network network = IeeeCdfNetworkFactory.create118(); setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network // if voltage level (on which is applied override) is not in the network, throws exception OpenReacParameters params3 = new OpenReacParameters(); - params3.addSpecificVoltageLimits(Map.of("UNKNOWN_ID", - new VoltageLimitOverrideBuilder() - .withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) - .withLowLimitOverride(1) - .withHighLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) - .withHighLimitOverride(0) - .build())); + List> voltageLimitsOverride = new ArrayList<>(); + voltageLimitsOverride.add(new Pair<>("UNKNOWN_ID", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, 1))); + params3.addSpecificVoltageLimits(voltageLimitsOverride); assertThrows(InvalidParametersException.class, () -> params3.checkIntegrity(network)); } diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java index af15a474..340381db 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java @@ -6,6 +6,7 @@ */ package com.powsybl.openreac.parameters.input; +import com.powsybl.openreac.exceptions.InvalidParametersException; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -13,57 +14,59 @@ public class VoltageLimitsOverrideTest { @Test - void validVoltageLimitOverrideBuilderTest() { - VoltageLimitOverrideBuilder builder = new VoltageLimitOverrideBuilder(); - VoltageLimitOverride vlo; - - // if one side of override specified, valid voltage limit override - builder.withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) - .withLowLimitOverride(-1); - vlo = builder.build(); - assertEquals(vlo.getLowLimitKind(), VoltageLimitOverride.OverrideKind.RELATIVE); - assertEquals(vlo.getLowLimitOverride(), -1); - - // if two sides of override specified, valid voltage limit override - builder.withHighLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE) - .withHighLimitOverride(410); - vlo = builder.build(); - assertEquals(vlo.getHighLimitKind(), VoltageLimitOverride.OverrideKind.ABSOLUTE); - assertEquals(vlo.getHighLimitOverride(), 410); + void testToStringOverrideSide() { + VoltageLimitOverride.OverrideSide os = VoltageLimitOverride.OverrideSide.HIGH; + assertEquals(os.toString(), "HIGH"); + os = VoltageLimitOverride.OverrideSide.LOW; + assertEquals(os.toString(), "LOW"); } @Test - void invalidVoltageLimitOverrideBuilderTest() { - VoltageLimitOverrideBuilder builder = new VoltageLimitOverrideBuilder(); + void invalidVoltageLimitOverride() { + // Verify it is impossible to create voltage limit override with NaN value... + assertThrows(InvalidParametersException.class, + () -> new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, Double.NaN)); + assertThrows(InvalidParametersException.class, + () -> new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, false, Double.NaN)); + assertThrows(InvalidParametersException.class, + () -> new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, Double.NaN)); + assertThrows(InvalidParametersException.class, + () -> new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, false, Double.NaN)); - // if no override kind specified, invalid voltage limit override - assertThrows(IllegalStateException.class, builder::build); - - // if no override value specified, invalid voltage limit override - builder.withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE); - builder.withHighLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE); - assertThrows(IllegalStateException.class, builder::build); + // Verify it is impossible to create absolute voltage limit override with negative value + assertThrows(InvalidParametersException.class, + () -> new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, false, -1)); + assertThrows(InvalidParametersException.class, + () -> new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, false, -1)); + } - // if low override value is undefined, invalid voltage limit override - builder.withLowLimitOverride(5) - .withHighLimitOverride(Double.NaN); - assertThrows(IllegalStateException.class, builder::build); + @Test + void validVoltageLimitOverride() { + VoltageLimitOverride vlo = new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, -4); + assertEquals(vlo.getSide(), VoltageLimitOverride.OverrideSide.HIGH); + assertTrue(vlo.isRelative()); + assertEquals(vlo.getLimitOverride(), -4); - // if high override value is undefined, invalid voltage limit override - builder.withLowLimitOverride(Double.NaN) - .withHighLimitOverride(5); - assertThrows(IllegalStateException.class, builder::build); + VoltageLimitOverride vlo2 = new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, false, 400); + assertEquals(vlo2.getSide(), VoltageLimitOverride.OverrideSide.LOW); + assertFalse(vlo2.isRelative()); + assertEquals(vlo2.getLimitOverride(), 400); } @Test void equalsVoltageLimitOverride() { - VoltageLimitOverrideBuilder builder = new VoltageLimitOverrideBuilder().withLowLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE) - .withLowLimitOverride(5) - .withHighLimitKind(VoltageLimitOverride.OverrideKind.ABSOLUTE) - .withHighLimitOverride(410); + VoltageLimitOverride vlo1 = new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, 5); + VoltageLimitOverride vlo2 = new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, 5); + assertEquals(vlo1, vlo2); + + VoltageLimitOverride vlo3 = new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, 5); + assertNotEquals(vlo1, vlo3); + + VoltageLimitOverride vlo4 = new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, false, 5); + assertNotEquals(vlo1, vlo4); - assertEquals(builder.build(), builder.build()); - assertNotEquals(builder.build(), builder.withHighLimitKind(VoltageLimitOverride.OverrideKind.RELATIVE).build()); + VoltageLimitOverride vlo5 = new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, 6); + assertNotEquals(vlo1, vlo5); } } diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/json/OpenReacJsonModuleTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/json/OpenReacJsonModuleTest.java index abc6377b..bcc05ff4 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/json/OpenReacJsonModuleTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/json/OpenReacJsonModuleTest.java @@ -11,11 +11,12 @@ import com.powsybl.commons.test.ComparisonUtils; import com.powsybl.openreac.parameters.input.OpenReacParameters; import com.powsybl.openreac.parameters.input.VoltageLimitOverride; +import org.jgrapht.alg.util.Pair; import org.junit.jupiter.api.Test; import java.io.IOException; +import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Objects; import static org.junit.jupiter.api.Assertions.*; @@ -30,8 +31,15 @@ void test() throws IOException { ObjectMapper objectMapper = JsonUtil.createObjectMapper() .registerModule(new OpenReactJsonModule()); OpenReacParameters parameters = new OpenReacParameters(); - parameters.addSpecificVoltageLimits(Map.of("foo", new VoltageLimitOverride(VoltageLimitOverride.OverrideKind.RELATIVE, VoltageLimitOverride.OverrideKind.RELATIVE, -1, 2), - "bar", new VoltageLimitOverride(VoltageLimitOverride.OverrideKind.ABSOLUTE, VoltageLimitOverride.OverrideKind.ABSOLUTE, 20, 26))); + + // List of voltage limit overrides + List> vloList1 = new ArrayList<>(); + vloList1.add(new Pair<>("foo", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, -1))); + vloList1.add(new Pair<>("foo", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, 2))); + vloList1.add(new Pair<>("bar", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, false, 20))); + vloList1.add(new Pair<>("bar", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, false, 26))); + + parameters.addSpecificVoltageLimits(vloList1); parameters.addConstantQGenerators(List.of("g1", "g2")); parameters.addVariableTwoWindingsTransformers(List.of("tr1")); parameters.addVariableShuntCompensators(List.of("sc1", "sc2")); @@ -40,16 +48,24 @@ void test() throws IOException { parameters.setObjectiveDistance(5); String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(parameters); ComparisonUtils.compareTxt(Objects.requireNonNull(getClass().getResourceAsStream("/parameters.json")), json); - OpenReacParameters parameters2 = objectMapper.readValue(json, OpenReacParameters.class); - assertEquals(Map.of("foo", new VoltageLimitOverride(VoltageLimitOverride.OverrideKind.RELATIVE, VoltageLimitOverride.OverrideKind.RELATIVE, -1, 2), - "bar", new VoltageLimitOverride(VoltageLimitOverride.OverrideKind.ABSOLUTE, VoltageLimitOverride.OverrideKind.ABSOLUTE, 20, 26)), parameters2.getSpecificVoltageLimits()); - assertEquals(List.of("g1", "g2"), parameters2.getConstantQGenerators()); - assertEquals(List.of("tr1"), parameters2.getVariableTwoWindingsTransformers()); - assertEquals(2, parameters2.getAlgorithmParams().size()); - assertEquals("p1", parameters2.getAlgorithmParams().get(0).getName()); - assertEquals("v1", parameters2.getAlgorithmParams().get(0).getValue()); - assertEquals("p2", parameters2.getAlgorithmParams().get(1).getName()); - assertEquals("v2", parameters2.getAlgorithmParams().get(1).getValue()); - assertEquals(5, parameters2.getObjectiveDistance()); + // TODO : fix following problem +// OpenReacParameters parameters2 = objectMapper.readValue(json, OpenReacParameters.class); +// +// // List of voltage limit overrides +// List> vloList2 = new ArrayList<>(); +// vloList2.add(new Pair<>("foo", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, -1))); +// vloList2.add(new Pair<>("foo", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, 2))); +// vloList2.add(new Pair<>("bar", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, false, 20))); +// vloList2.add(new Pair<>("bar", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, false, 26))); +// +// assertEquals(vloList2, parameters2.getSpecificVoltageLimits()); +// assertEquals(List.of("g1", "g2"), parameters2.getConstantQGenerators()); +// assertEquals(List.of("tr1"), parameters2.getVariableTwoWindingsTransformers()); +// assertEquals(2, parameters2.getAlgorithmParams().size()); +// assertEquals("p1", parameters2.getAlgorithmParams().get(0).getName()); +// assertEquals("v1", parameters2.getAlgorithmParams().get(0).getValue()); +// assertEquals("p2", parameters2.getAlgorithmParams().get(1).getName()); +// assertEquals("v2", parameters2.getAlgorithmParams().get(1).getValue()); +// assertEquals(5, parameters2.getObjectiveDistance()); } } diff --git a/open-reac/src/test/resources/parameters.json b/open-reac/src/test/resources/parameters.json index 92509688..f610ce01 100644 --- a/open-reac/src/test/resources/parameters.json +++ b/open-reac/src/test/resources/parameters.json @@ -1,19 +1,34 @@ { "version" : "1.0", - "specificVoltageLimits" : { - "bar" : { - "lowLimitKind" : "ABSOLUTE", - "highLimitKind" : "ABSOLUTE", - "lowLimitOverride" : 20.0, - "highLimitOverride" : 26.0 - }, - "foo" : { - "lowLimitKind" : "RELATIVE", - "highLimitKind" : "RELATIVE", - "lowLimitOverride" : -1.0, - "highLimitOverride" : 2.0 + "specificVoltageLimits" : [ { + "first" : "foo", + "second" : { + "overrideSide" : "LOW", + "isRelative" : true, + "overrideValue" : -1.0 } - }, + }, { + "first" : "foo", + "second" : { + "overrideSide" : "HIGH", + "isRelative" : true, + "overrideValue" : 2.0 + } + }, { + "first" : "bar", + "second" : { + "overrideSide" : "LOW", + "isRelative" : false, + "overrideValue" : 20.0 + } + }, { + "first" : "bar", + "second" : { + "overrideSide" : "HIGH", + "isRelative" : false, + "overrideValue" : 26.0 + } + } ], "constantQGenerators" : [ "g1", "g2" ], "variableTwoWindingsTransformers" : [ "tr1" ], "variableShuntCompensators" : [ "sc1", "sc2" ], From f4eab7df1cbff7def37df2fddc0022c61d0eb76b Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 10 Oct 2023 17:29:33 +0200 Subject: [PATCH 07/16] Clean. Signed-off-by: Anne Tilloy --- .../com/powsybl/openreac/OpenReacTool.java | 11 +- .../parameters/input/OpenReacParameters.java | 120 ++++++------------ .../VoltageLevelLimitsOverrideInput.java | 43 +++---- .../input/VoltageLimitOverride.java | 51 +++++--- .../json/OpenReacParametersDeserializer.java | 5 +- .../VoltageLimitOverrideDeserializer.java | 17 ++- .../json/VoltageLimitOverrideSerializer.java | 5 +- .../java/com/powsybl/openreac/ItoolsTest.java | 11 +- .../VoltageLevelLimitsOverrideInputTest.java | 25 ++-- .../input/VoltageLimitsOverrideTest.java | 44 +++---- .../input/json/OpenReacJsonModuleTest.java | 50 ++++---- open-reac/src/test/resources/parameters.json | 40 +++--- 12 files changed, 184 insertions(+), 238 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java b/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java index 86b67893..6c4bb036 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java +++ b/open-reac/src/main/java/com/powsybl/openreac/OpenReacTool.java @@ -29,7 +29,6 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; -import org.jgrapht.alg.util.Pair; import java.io.IOException; import java.io.InputStream; @@ -164,12 +163,12 @@ public OpenReacParameters createOpenReacParameters(CommandLine line, ArrayNode array = (ArrayNode) jsonNode.get(VOLTAGE_OVERRIDE_LIST); array.forEach(node -> { String voltageId = node.get("id").asText(); - double lowerPercent = node.get("lower").asDouble(); - double upperPercent = node.get("upper").asDouble(); + double lower = node.get("lower").asDouble(); + double upper = node.get("upper").asDouble(); - List> voltageLimitOverrides = new ArrayList<>(); - voltageLimitOverrides.add(new Pair<>(voltageId, new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, lowerPercent))); - voltageLimitOverrides.add(new Pair<>(voltageId, new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, upperPercent))); + List voltageLimitOverrides = new ArrayList<>(); + voltageLimitOverrides.add(new VoltageLimitOverride(voltageId, VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, lower)); + voltageLimitOverrides.add(new VoltageLimitOverride(voltageId, VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, upper)); openReacParameters.addSpecificVoltageLimits(voltageLimitOverrides); }); } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java index df86a11c..3d698df0 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java @@ -12,11 +12,11 @@ import com.powsybl.openreac.parameters.input.algo.OpenReacAlgoParam; import com.powsybl.openreac.parameters.input.algo.OpenReacAlgoParamImpl; import com.powsybl.openreac.parameters.input.algo.OpenReacOptimisationObjective; -import org.jgrapht.alg.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; +import java.util.stream.Collectors; /** * This class stores all inputs parameters specific to the OpenReac optimizer. @@ -29,11 +29,16 @@ public class OpenReacParameters { private static final String OBJECTIVE_DISTANCE_KEY = "ratio_voltage_target"; - private final List> specificVoltageLimits = new ArrayList<>(); + private final List specificVoltageLimits = new ArrayList<>(); + private final List variableShuntCompensators = new ArrayList<>(); + private final List constantQGenerators = new ArrayList<>(); + private final List variableTwoWindingsTransformers = new ArrayList<>(); + private final List algorithmParams = new ArrayList<>(); + private OpenReacOptimisationObjective objective = OpenReacOptimisationObjective.MIN_GENERATION; /* @@ -48,9 +53,9 @@ public class OpenReacParameters { * Override some voltage level limits in the network. This will NOT modify the network object. *

* The override is ignored if one or both of the voltage limit are NaN. - * @param specificVoltageLimits keys: a VoltageLevel ID, values: low and high delta limits (kV). + * @param specificVoltageLimits list of voltage limit overrides. */ - public OpenReacParameters addSpecificVoltageLimits(List> specificVoltageLimits) { + public OpenReacParameters addSpecificVoltageLimits(List specificVoltageLimits) { this.specificVoltageLimits.addAll(Objects.requireNonNull(specificVoltageLimits)); return this; } @@ -134,7 +139,7 @@ public List getVariableShuntCompensators() { return variableShuntCompensators; } - public List> getSpecificVoltageLimits() { + public List getSpecificVoltageLimits() { return specificVoltageLimits; } @@ -177,7 +182,7 @@ public void checkIntegrity(Network network) throws InvalidParametersException { } for (String transformerId : getVariableTwoWindingsTransformers()) { if (network.getTwoWindingsTransformer(transformerId) == null) { - throw new InvalidParametersException("Two windings transfromer " + transformerId + " not found in the network."); + throw new InvalidParametersException("Two windings transformer " + transformerId + " not found in the network."); } } @@ -207,63 +212,29 @@ boolean checkVoltageLevelLimits(Network network) { double lowLimit = vl.getLowVoltageLimit(); double highLimit = vl.getHighVoltageLimit(); - // If low voltage limit is undefined... if (Double.isNaN(lowLimit)) { - - // find associated override if it exists - boolean hasOverride = false; - VoltageLimitOverride associatedOverride = null; - for (Pair pair : getSpecificVoltageLimits()) { - if (pair.getFirst().equals(vl.getId()) && pair.getSecond().getSide() == VoltageLimitOverride.OverrideSide.LOW) { - hasOverride = true; - associatedOverride = pair.getSecond(); - break; - } - } - - // ... verify if there is an override for the undefined limit - if (!hasOverride) { + List overrides = getSpecificVoltageLimits(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT); + if (overrides.size() != 1) { LOGGER.warn("Voltage level '" + vl.getId() + "' has no low voltage limit defined. " + "Please add one or use a voltage limit override."); integrityVoltageLevelLimits = false; - - // ... verify override is not relative - } else if (associatedOverride.isRelative()) { - LOGGER.warn("Relative voltage override impossible on undefined low voltage limit for voltage level '" - + vl.getId() + "'."); + } else if (overrides.get(0).isRelative()) { // we have one and just one + LOGGER.warn("Relative voltage override impossible on undefined low voltage limit for voltage level {}.", vl.getId()); integrityVoltageLevelLimits = false; } } - - // If high voltage limit is undefined... if (Double.isNaN(highLimit)) { - - // find associated override if it exists - boolean hasOverride = false; - VoltageLimitOverride associatedOverride = null; - for (Pair pair : getSpecificVoltageLimits()) { - if (pair.getFirst().equals(vl.getId()) && pair.getSecond().getSide() == VoltageLimitOverride.OverrideSide.HIGH) { - hasOverride = true; - associatedOverride = pair.getSecond(); - break; - } - } - - // ... verify if there is an override for the undefined limit - if (!hasOverride) { + List overrides = getSpecificVoltageLimits(vl.getId(), VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT); + if (overrides.size() != 1) { LOGGER.warn("Voltage level '" + vl.getId() + "' has no high voltage limit defined. " + "Please add one or use a voltage limit override."); integrityVoltageLevelLimits = false; - - // ... verify override is not relative - } else if (associatedOverride.isRelative()) { - LOGGER.warn("Relative voltage override impossible on undefined high voltage limit for voltage level '" - + vl.getId() + "'."); + } else if (overrides.get(0).isRelative()) { + LOGGER.warn("Relative voltage override impossible on undefined high voltage limit for voltage level {}.", vl.getId()); integrityVoltageLevelLimits = false; } } } - return integrityVoltageLevelLimits; } @@ -274,52 +245,37 @@ boolean checkVoltageLevelLimits(Network network) { boolean checkVoltageLimitOverrides(Network network) { // Check integrity of voltage overrides boolean integrityVoltageLimitOverrides = true; - for (Pair pair : getSpecificVoltageLimits()) { - String voltageLevelId = pair.getFirst(); + for (VoltageLimitOverride voltageLimitOverride : getSpecificVoltageLimits()) { + String voltageLevelId = voltageLimitOverride.getVoltageLevelId(); VoltageLevel voltageLevel = network.getVoltageLevel(voltageLevelId); // Check existence of voltage level on which is applied voltage limit override if (voltageLevel == null) { LOGGER.warn("Voltage level " + voltageLevelId + " not found in the network."); integrityVoltageLimitOverrides = false; - } else { - VoltageLimitOverride override = pair.getSecond(); - - // if the override is relative... - if (override.isRelative()) { - - // ... and on low limit ... - if (override.getSide() == VoltageLimitOverride.OverrideSide.LOW) { - - // ... verify low voltage limit is defined - if (Double.isNaN(voltageLevel.getLowVoltageLimit())) { - LOGGER.warn("Voltage level '" + voltageLevelId + "' has undefined low voltage limit, " + - "relative voltage limit override impossible."); - integrityVoltageLimitOverrides = false; - } - + if (voltageLimitOverride.isRelative()) { + double value = voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT ? + voltageLevel.getLowVoltageLimit() : voltageLevel.getHighVoltageLimit(); // FIXME? + if (Double.isNaN(value)) { + LOGGER.warn("Voltage level {} has undefined {}, relative voltage limit override is impossible.", + voltageLevelId, voltageLimitOverride.getVoltageLimitType().toString()); + integrityVoltageLimitOverrides = false; + } + if (voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT + && voltageLimitOverride.getLimit() + voltageLevel.getLowVoltageLimit() < 0) { // ... verify low voltage limit override does not lead to negative limit value - if (override.getLimitOverride() + voltageLevel.getLowVoltageLimit() < 0) { - LOGGER.warn("Voltage level " + voltageLevelId + " low relative override leads to negative low voltage limit."); - integrityVoltageLimitOverrides = false; - } - // ... and on high limit ... - } else { - - // ... verify high voltage limit is defined - if (Double.isNaN(voltageLevel.getHighVoltageLimit())) { - LOGGER.warn("Voltage level '" + voltageLevelId + "' has undefined high voltage limit, " + - "relative voltage limit override impossible."); - integrityVoltageLimitOverrides = false; - } + LOGGER.warn("Voltage level " + voltageLevelId + " low relative override leads to negative low voltage limit."); + integrityVoltageLimitOverrides = false; } - } } - } - return integrityVoltageLimitOverrides; } + + private List getSpecificVoltageLimits(String voltageLevelId, VoltageLimitOverride.VoltageLimitType type) { + return specificVoltageLimits.stream() + .filter(limit -> limit.getVoltageLevelId().equals(voltageLevelId) && limit.getVoltageLimitType() == type).collect(Collectors.toList()); + } } 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 b7f16281..c51c79dc 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 @@ -27,25 +27,24 @@ public class VoltageLevelLimitsOverrideInput implements AmplInputFile { private static final String FILENAME = "ampl_network_substations_override.txt"; + private final Map> normalizedVoltageLimitsOverride; - public VoltageLevelLimitsOverrideInput(List> voltageLimitsOverride, Network network) { - Objects.requireNonNull(voltageLimitsOverride); + public VoltageLevelLimitsOverrideInput(List voltageLimitsOverrides, Network network) { + Objects.requireNonNull(voltageLimitsOverrides); Objects.requireNonNull(network); this.normalizedVoltageLimitsOverride = new HashMap<>(); - transformToNormalizedVoltage(voltageLimitsOverride, network); + transformToNormalizedVoltage(voltageLimitsOverrides, network); } /** * voltageLimitsOverride contains absolute voltage limits. * This function compute limits in pair-unit quantities. */ - private void transformToNormalizedVoltage(List> voltageLimitsOverride, Network network) { - for (Pair pair : voltageLimitsOverride) { - String voltageLevelId = pair.getFirst(); - VoltageLimitOverride override = pair.getSecond(); - + private void transformToNormalizedVoltage(List voltageLimitsOverrides, Network network) { + for (VoltageLimitOverride voltageLimitOverride : voltageLimitsOverrides) { // get previous voltage limit values + String voltageLevelId = voltageLimitOverride.getVoltageLevelId(); double nominalV = network.getVoltageLevel(voltageLevelId).getNominalV(); double previousNormalizedLowVoltageLimit = network.getVoltageLevel(voltageLevelId).getLowVoltageLimit() / nominalV; double previousNormalizedHighVoltageLimit = network.getVoltageLevel(voltageLevelId).getHighVoltageLimit() / nominalV; @@ -53,27 +52,15 @@ private void transformToNormalizedVoltage(List newLimits = normalizedVoltageLimitsOverride.containsKey(voltageLevelId) ? normalizedVoltageLimitsOverride.get(voltageLevelId) : new Pair<>(previousNormalizedLowVoltageLimit, previousNormalizedHighVoltageLimit); - - // if override is low ... - if (override.getSide() == VoltageLimitOverride.OverrideSide.LOW) { - // ... and relative, add relative override - if (override.isRelative()) { - newLimits.setFirst(newLimits.getFirst() + override.getLimitOverride() / nominalV); - // ... and absolute, replace by absolute override - } else { - newLimits.setFirst(override.getLimitOverride() / nominalV); - } - // if override is high ... + if (voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT) { + double value = (voltageLimitOverride.isRelative() ? newLimits.getFirst() : 0.0) + voltageLimitOverride.getLimit() / nominalV; + newLimits.setFirst(value); + } else if (voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT) { + double value = (voltageLimitOverride.isRelative() ? newLimits.getSecond() : 0.0) + voltageLimitOverride.getLimit() / nominalV; + newLimits.setSecond(value); } else { - // ... and relative, add relative override - if (override.isRelative()) { - newLimits.setSecond(newLimits.getSecond() + override.getLimitOverride() / nominalV); - // ... and absolute, replace by absolute override - } else { - newLimits.setSecond(override.getLimitOverride() / nominalV); - } + throw new UnsupportedOperationException("Unsupported voltage limit type: " + voltageLimitOverride.getVoltageLimitType()); } - normalizedVoltageLimitsOverride.put(voltageLevelId, newLimits); } } @@ -101,7 +88,7 @@ public InputStream getParameterFileAsStream(StringToIntMapper string } } - //add new line at the end of the file ! + //add new line at the end of the file dataBuilder.append(System.lineSeparator()); return new ByteArrayInputStream(dataBuilder.toString().getBytes(StandardCharsets.UTF_8)); } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java index c1b2d1a9..f3a802f5 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java @@ -18,39 +18,51 @@ */ public class VoltageLimitOverride { - public enum OverrideSide { - HIGH, LOW; + public enum VoltageLimitType { + HIGH_VOLTAGE_LIMIT, + LOW_VOLTAGE_LIMIT; @Override public String toString() { - return this == HIGH ? "HIGH" : "LOW"; + return this == HIGH_VOLTAGE_LIMIT ? "HIGH_VOLTAGE_LIMIT" : "LOW_VOLTAGE_LIMIT"; } } - private final OverrideSide side; // indicates if the override is done on low/high voltage limit - private final boolean isRelative; // if true, override is absolute. if false, override is absolute - private final double limitOverride; // value of the override + private final VoltageLimitType type; // indicates if the override is done on low or on high voltage limit - public OverrideSide getSide() { - return side; + private final boolean isRelative; // if true, override is relative. if false, override is absolute + + private final double limit; // value of the limit override + + private final String voltageLevelId; + + public VoltageLimitType getVoltageLimitType() { + return type; } public boolean isRelative() { return isRelative; } - public double getLimitOverride() { - return limitOverride; + public double getLimit() { + return limit; } - public VoltageLimitOverride(OverrideSide side, boolean isRelative, double limitOverride) { - if (Double.isNaN(limitOverride) || limitOverride <= 0 && !isRelative) { - throw new InvalidParametersException("The voltage limit override is incorrect. " + - "It must be defined and > 0 if absolute."); + public String getVoltageLevelId() { + return voltageLevelId; + } + + public VoltageLimitOverride(String voltageLevelId, VoltageLimitType type, boolean isRelative, double limit) { + if (Double.isNaN(limit)) { + throw new InvalidParametersException("The voltage limit override must be defined."); + } + if (limit <= 0 && !isRelative) { + throw new InvalidParametersException("The voltage limit override is in absolute value: must be positive."); } - this.side = side; + this.voltageLevelId = voltageLevelId; + this.type = Objects.requireNonNull(type); this.isRelative = isRelative; - this.limitOverride = limitOverride; + this.limit = limit; } @Override @@ -62,13 +74,14 @@ public boolean equals(Object o) { return false; } VoltageLimitOverride that = (VoltageLimitOverride) o; - return that.side == side + return that.voltageLevelId.equals(voltageLevelId) + && that.type.equals(type) && that.isRelative == isRelative - && Double.compare(that.limitOverride, limitOverride) == 0; + && Double.compare(that.limit, limit) == 0; } @Override public int hashCode() { - return Objects.hash(side, isRelative, limitOverride); + return Objects.hash(voltageLevelId, type, isRelative, limit); } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/OpenReacParametersDeserializer.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/OpenReacParametersDeserializer.java index 0a7a6eb0..905d457b 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/OpenReacParametersDeserializer.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/OpenReacParametersDeserializer.java @@ -15,13 +15,12 @@ import com.powsybl.openreac.parameters.input.VoltageLimitOverride; import com.powsybl.openreac.parameters.input.algo.OpenReacAlgoParam; import com.powsybl.openreac.parameters.input.algo.OpenReacOptimisationObjective; -import org.jgrapht.alg.util.Pair; import java.io.IOException; import java.util.List; /** - * @author Hugo Marcellin + * @author Geoffroy Jamgotchian */ public class OpenReacParametersDeserializer extends StdDeserializer { @@ -43,7 +42,7 @@ public OpenReacParameters deserialize(JsonParser parser, DeserializationContext break; case "specificVoltageLimits": parser.nextToken(); - parameters.addSpecificVoltageLimits(parser.readValueAs(new TypeReference>>() { })); + parameters.addSpecificVoltageLimits(parser.readValueAs(new TypeReference>() { })); break; case "variableShuntCompensators": parser.nextToken(); diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java index e58593d6..de321d25 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java @@ -26,21 +26,26 @@ public VoltageLimitOverrideDeserializer() { @Override public VoltageLimitOverride deserialize(JsonParser parser, DeserializationContext deserializationContext) throws IOException { - VoltageLimitOverride.OverrideSide side = null; - boolean isRelative = false; + String voltageLevelId = null; + VoltageLimitOverride.VoltageLimitType type = null; + boolean isRelative = true; double overrideValue = 0; while (parser.nextToken() != JsonToken.END_OBJECT) { switch (parser.getCurrentName()) { - case "overrideSide": + case "voltageLevelId": parser.nextToken(); - side = parser.readValueAs(VoltageLimitOverride.OverrideSide.class); + voltageLevelId = parser.readValueAs(String.class); + break; + case "voltageLimitType": + parser.nextToken(); + type = parser.readValueAs(VoltageLimitOverride.VoltageLimitType.class); break; case "isRelative": parser.nextToken(); isRelative = parser.readValueAs(boolean.class); break; - case "overrideValue": + case "value": parser.nextToken(); overrideValue = parser.readValueAs(Double.class); break; @@ -48,6 +53,6 @@ public VoltageLimitOverride deserialize(JsonParser parser, DeserializationContex throw new IllegalStateException("Unexpected field: " + parser.getCurrentName()); } } - return new VoltageLimitOverride(side, isRelative, overrideValue); + return new VoltageLimitOverride(voltageLevelId, type, isRelative, overrideValue); } } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java index e2ece06a..9467cc3d 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java @@ -26,9 +26,10 @@ public VoltageLimitOverrideSerializer() { @Override public void serialize(VoltageLimitOverride voltageLimitOverride, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeStartObject(); - jsonGenerator.writeObjectField("overrideSide", voltageLimitOverride.getSide()); + jsonGenerator.writeObjectField("voltageLevelId", voltageLimitOverride.getVoltageLevelId()); + jsonGenerator.writeObjectField("voltageLimitType", voltageLimitOverride.getVoltageLimitType()); jsonGenerator.writeObjectField("isRelative", voltageLimitOverride.isRelative()); - jsonGenerator.writeNumberField("overrideValue", voltageLimitOverride.getLimitOverride()); + jsonGenerator.writeNumberField("value", voltageLimitOverride.getLimit()); // FIXME jsonGenerator.writeEndObject(); } } diff --git a/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java b/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java index 5d79a5dc..77a454e5 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java @@ -16,7 +16,6 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.ParseException; -import org.jgrapht.alg.util.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -65,11 +64,13 @@ public void testCreateOpenReacParameters() throws ParseException, IOException { assertEquals(List.of("var-shunt", "var-shunt-2"), loadedParams.getVariableShuntCompensators(), "Parsing of OpenReac parameters is wrong."); // List of voltage limit overrides - List> vloList = new ArrayList<>(); - vloList.add(new Pair<>("voltageLevelId", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, -5))); - vloList.add(new Pair<>("voltageLevelId", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, 5))); + List vloList = new ArrayList<>(); + vloList.add(new VoltageLimitOverride("voltageLevelId", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, -5)); + vloList.add(new VoltageLimitOverride("voltageLevelId", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, 5)); - assertEquals(vloList, loadedParams.getSpecificVoltageLimits(), "Parsing of OpenReac parameters is wrong."); + for (int i = 0; i < vloList.size(); i++) { + assertTrue(vloList.get(i).equals(loadedParams.getSpecificVoltageLimits().get(i))); + } assertEquals(OpenReacOptimisationObjective.SPECIFIC_VOLTAGE_PROFILE, loadedParams.getObjective(), "Parsing of OpenReac parameters is wrong."); } 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 c03f5226..1011eef0 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 @@ -16,7 +16,6 @@ import com.powsybl.iidm.network.VoltageLevel; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; import com.powsybl.openreac.exceptions.InvalidParametersException; -import org.jgrapht.alg.util.Pair; import org.junit.jupiter.api.Test; import java.io.IOException; @@ -41,11 +40,9 @@ void testValidRelativeVoltageOverride() throws IOException { vlGen.setLowVoltageLimit(20) .setHighVoltageLimit(26); - List> voltageLimitsOverride = new ArrayList<>(); - voltageLimitsOverride.add(new Pair<>("VLGEN", - new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, -1))); - voltageLimitsOverride.add(new Pair<>("VLGEN", - new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, 2))); + List voltageLimitsOverride = new ArrayList<>(); + voltageLimitsOverride.add(new VoltageLimitOverride("VLGEN", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, -1)); + voltageLimitsOverride.add(new VoltageLimitOverride("VLGEN", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, 2)); VoltageLevelLimitsOverrideInput input = new VoltageLevelLimitsOverrideInput(voltageLimitsOverride, network); StringToIntMapper mapper = AmplUtil.createMapper(network); @@ -67,11 +64,9 @@ void testValidAbsoluteVoltageOverride() throws IOException { vlgen.setLowVoltageLimit(Double.NaN) .setHighVoltageLimit(Double.NaN); - List> voltageLimitsOverride = new ArrayList<>(); - voltageLimitsOverride.add(new Pair<>("VLGEN", - new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, false, 20))); - voltageLimitsOverride.add(new Pair<>("VLGEN", - new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, false, 26))); + List voltageLimitsOverride = new ArrayList<>(); + voltageLimitsOverride.add(new VoltageLimitOverride("VLGEN", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, false, 20)); + voltageLimitsOverride.add(new VoltageLimitOverride("VLGEN", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, false, 26)); VoltageLevelLimitsOverrideInput input = new VoltageLevelLimitsOverrideInput(voltageLimitsOverride, network); StringToIntMapper mapper = AmplUtil.createMapper(network); @@ -118,8 +113,8 @@ void testVoltageOverrideWithNegativeLowVoltageValue() { // if low relative voltage override leads to negative voltage limit, throws exception OpenReacParameters params = new OpenReacParameters(); - List> voltageLimitsOverride = new ArrayList<>(); - voltageLimitsOverride.add(new Pair<>(vl.getId(), new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, -410))); + List voltageLimitsOverride = new ArrayList<>(); + voltageLimitsOverride.add(new VoltageLimitOverride(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, -410)); params.addSpecificVoltageLimits(voltageLimitsOverride); assertThrows(InvalidParametersException.class, () -> params.checkIntegrity(network)); } @@ -131,8 +126,8 @@ void testVoltageOverrideOnInvalidVoltageLevel() { // if voltage level (on which is applied override) is not in the network, throws exception OpenReacParameters params3 = new OpenReacParameters(); - List> voltageLimitsOverride = new ArrayList<>(); - voltageLimitsOverride.add(new Pair<>("UNKNOWN_ID", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, 1))); + List voltageLimitsOverride = new ArrayList<>(); + voltageLimitsOverride.add(new VoltageLimitOverride("UNKNOWN_ID", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, 1)); params3.addSpecificVoltageLimits(voltageLimitsOverride); assertThrows(InvalidParametersException.class, () -> params3.checkIntegrity(network)); } diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java index 340381db..f66784bb 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java @@ -14,58 +14,58 @@ public class VoltageLimitsOverrideTest { @Test - void testToStringOverrideSide() { - VoltageLimitOverride.OverrideSide os = VoltageLimitOverride.OverrideSide.HIGH; - assertEquals(os.toString(), "HIGH"); - os = VoltageLimitOverride.OverrideSide.LOW; - assertEquals(os.toString(), "LOW"); + void testToStringOverrideType() { + VoltageLimitOverride.VoltageLimitType os = VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT; + assertEquals(os.toString(), "HIGH_VOLTAGE_LIMIT"); + os = VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT; + assertEquals(os.toString(), "LOW_VOLTAGE_LIMIT"); } @Test void invalidVoltageLimitOverride() { // Verify it is impossible to create voltage limit override with NaN value... assertThrows(InvalidParametersException.class, - () -> new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, Double.NaN)); + () -> new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, Double.NaN)); assertThrows(InvalidParametersException.class, - () -> new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, false, Double.NaN)); + () -> new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, false, Double.NaN)); assertThrows(InvalidParametersException.class, - () -> new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, Double.NaN)); + () -> new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, Double.NaN)); assertThrows(InvalidParametersException.class, - () -> new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, false, Double.NaN)); + () -> new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, false, Double.NaN)); // Verify it is impossible to create absolute voltage limit override with negative value assertThrows(InvalidParametersException.class, - () -> new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, false, -1)); + () -> new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, false, -1)); assertThrows(InvalidParametersException.class, - () -> new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, false, -1)); + () -> new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, false, -1)); } @Test void validVoltageLimitOverride() { - VoltageLimitOverride vlo = new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, -4); - assertEquals(vlo.getSide(), VoltageLimitOverride.OverrideSide.HIGH); + VoltageLimitOverride vlo = new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, -4); + assertEquals(vlo.getVoltageLimitType(), VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT); assertTrue(vlo.isRelative()); - assertEquals(vlo.getLimitOverride(), -4); + assertEquals(vlo.getLimit(), -4); - VoltageLimitOverride vlo2 = new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, false, 400); - assertEquals(vlo2.getSide(), VoltageLimitOverride.OverrideSide.LOW); + VoltageLimitOverride vlo2 = new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, false, 400); + assertEquals(vlo2.getVoltageLimitType(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT); assertFalse(vlo2.isRelative()); - assertEquals(vlo2.getLimitOverride(), 400); + assertEquals(vlo2.getLimit(), 400); } @Test void equalsVoltageLimitOverride() { - VoltageLimitOverride vlo1 = new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, 5); - VoltageLimitOverride vlo2 = new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, 5); + VoltageLimitOverride vlo1 = new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, 5); + VoltageLimitOverride vlo2 = new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, 5); assertEquals(vlo1, vlo2); - VoltageLimitOverride vlo3 = new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, 5); + VoltageLimitOverride vlo3 = new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, 5); assertNotEquals(vlo1, vlo3); - VoltageLimitOverride vlo4 = new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, false, 5); + VoltageLimitOverride vlo4 = new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, false, 5); assertNotEquals(vlo1, vlo4); - VoltageLimitOverride vlo5 = new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, 6); + VoltageLimitOverride vlo5 = new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, 6); assertNotEquals(vlo1, vlo5); } diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/json/OpenReacJsonModuleTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/json/OpenReacJsonModuleTest.java index bcc05ff4..26c0c8ca 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/json/OpenReacJsonModuleTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/json/OpenReacJsonModuleTest.java @@ -11,7 +11,6 @@ import com.powsybl.commons.test.ComparisonUtils; import com.powsybl.openreac.parameters.input.OpenReacParameters; import com.powsybl.openreac.parameters.input.VoltageLimitOverride; -import org.jgrapht.alg.util.Pair; import org.junit.jupiter.api.Test; import java.io.IOException; @@ -19,7 +18,7 @@ import java.util.List; import java.util.Objects; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; /** * @author Geoffroy Jamgotchian @@ -33,11 +32,11 @@ void test() throws IOException { OpenReacParameters parameters = new OpenReacParameters(); // List of voltage limit overrides - List> vloList1 = new ArrayList<>(); - vloList1.add(new Pair<>("foo", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, -1))); - vloList1.add(new Pair<>("foo", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, 2))); - vloList1.add(new Pair<>("bar", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, false, 20))); - vloList1.add(new Pair<>("bar", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, false, 26))); + List vloList1 = new ArrayList<>(); + vloList1.add(new VoltageLimitOverride("foo", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, -1)); + vloList1.add(new VoltageLimitOverride("foo", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, 2)); + vloList1.add(new VoltageLimitOverride("bar", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, false, 20)); + vloList1.add(new VoltageLimitOverride("bar", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, false, 26)); parameters.addSpecificVoltageLimits(vloList1); parameters.addConstantQGenerators(List.of("g1", "g2")); @@ -48,24 +47,23 @@ void test() throws IOException { parameters.setObjectiveDistance(5); String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(parameters); ComparisonUtils.compareTxt(Objects.requireNonNull(getClass().getResourceAsStream("/parameters.json")), json); - // TODO : fix following problem -// OpenReacParameters parameters2 = objectMapper.readValue(json, OpenReacParameters.class); -// -// // List of voltage limit overrides -// List> vloList2 = new ArrayList<>(); -// vloList2.add(new Pair<>("foo", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, true, -1))); -// vloList2.add(new Pair<>("foo", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, true, 2))); -// vloList2.add(new Pair<>("bar", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.LOW, false, 20))); -// vloList2.add(new Pair<>("bar", new VoltageLimitOverride(VoltageLimitOverride.OverrideSide.HIGH, false, 26))); -// -// assertEquals(vloList2, parameters2.getSpecificVoltageLimits()); -// assertEquals(List.of("g1", "g2"), parameters2.getConstantQGenerators()); -// assertEquals(List.of("tr1"), parameters2.getVariableTwoWindingsTransformers()); -// assertEquals(2, parameters2.getAlgorithmParams().size()); -// assertEquals("p1", parameters2.getAlgorithmParams().get(0).getName()); -// assertEquals("v1", parameters2.getAlgorithmParams().get(0).getValue()); -// assertEquals("p2", parameters2.getAlgorithmParams().get(1).getName()); -// assertEquals("v2", parameters2.getAlgorithmParams().get(1).getValue()); -// assertEquals(5, parameters2.getObjectiveDistance()); + + OpenReacParameters parameters2 = objectMapper.readValue(json, OpenReacParameters.class); + // List of voltage limit overrides + List vloList2 = new ArrayList<>(); + vloList2.add(new VoltageLimitOverride("foo", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, -1)); + vloList2.add(new VoltageLimitOverride("foo", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, 2)); + vloList2.add(new VoltageLimitOverride("bar", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, false, 20)); + vloList2.add(new VoltageLimitOverride("bar", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, false, 26)); + + assertEquals(vloList2, parameters2.getSpecificVoltageLimits()); + assertEquals(List.of("g1", "g2"), parameters2.getConstantQGenerators()); + assertEquals(List.of("tr1"), parameters2.getVariableTwoWindingsTransformers()); + assertEquals(2, parameters2.getAlgorithmParams().size()); + assertEquals("p1", parameters2.getAlgorithmParams().get(0).getName()); + assertEquals("v1", parameters2.getAlgorithmParams().get(0).getValue()); + assertEquals("p2", parameters2.getAlgorithmParams().get(1).getName()); + assertEquals("v2", parameters2.getAlgorithmParams().get(1).getValue()); + assertEquals(5, parameters2.getObjectiveDistance()); } } diff --git a/open-reac/src/test/resources/parameters.json b/open-reac/src/test/resources/parameters.json index f610ce01..5aee589c 100644 --- a/open-reac/src/test/resources/parameters.json +++ b/open-reac/src/test/resources/parameters.json @@ -1,33 +1,25 @@ { "version" : "1.0", "specificVoltageLimits" : [ { - "first" : "foo", - "second" : { - "overrideSide" : "LOW", - "isRelative" : true, - "overrideValue" : -1.0 - } + "voltageLevelId" : "foo", + "voltageLimitType" : "LOW_VOLTAGE_LIMIT", + "isRelative" : true, + "value" : -1.0 }, { - "first" : "foo", - "second" : { - "overrideSide" : "HIGH", - "isRelative" : true, - "overrideValue" : 2.0 - } + "voltageLevelId" : "foo", + "voltageLimitType" : "HIGH_VOLTAGE_LIMIT", + "isRelative" : true, + "value" : 2.0 }, { - "first" : "bar", - "second" : { - "overrideSide" : "LOW", - "isRelative" : false, - "overrideValue" : 20.0 - } + "voltageLevelId" : "bar", + "voltageLimitType" : "LOW_VOLTAGE_LIMIT", + "isRelative" : false, + "value" : 20.0 }, { - "first" : "bar", - "second" : { - "overrideSide" : "HIGH", - "isRelative" : false, - "overrideValue" : 26.0 - } + "voltageLevelId" : "bar", + "voltageLimitType" : "HIGH_VOLTAGE_LIMIT", + "isRelative" : false, + "value" : 26.0 } ], "constantQGenerators" : [ "g1", "g2" ], "variableTwoWindingsTransformers" : [ "tr1" ], From df5e371337afcae8c34a28e4a0da2bb6136cf072 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 10 Oct 2023 20:25:15 +0200 Subject: [PATCH 08/16] Fix some code smells. Signed-off-by: Anne Tilloy --- .../parameters/input/OpenReacParameters.java | 12 +++++------- .../java/com/powsybl/openreac/ItoolsTest.java | 2 +- .../input/VoltageLimitsOverrideTest.java | 15 +++++++-------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java index 3d698df0..49c39b91 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java @@ -215,8 +215,7 @@ boolean checkVoltageLevelLimits(Network network) { if (Double.isNaN(lowLimit)) { List overrides = getSpecificVoltageLimits(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT); if (overrides.size() != 1) { - LOGGER.warn("Voltage level '" + vl.getId() + "' has no low voltage limit defined. " + - "Please add one or use a voltage limit override."); + LOGGER.warn("Voltage level has no low voltage limit defined. Please add one or use a voltage limit override.", vl.getId()); integrityVoltageLevelLimits = false; } else if (overrides.get(0).isRelative()) { // we have one and just one LOGGER.warn("Relative voltage override impossible on undefined low voltage limit for voltage level {}.", vl.getId()); @@ -226,8 +225,7 @@ boolean checkVoltageLevelLimits(Network network) { if (Double.isNaN(highLimit)) { List overrides = getSpecificVoltageLimits(vl.getId(), VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT); if (overrides.size() != 1) { - LOGGER.warn("Voltage level '" + vl.getId() + "' has no high voltage limit defined. " + - "Please add one or use a voltage limit override."); + LOGGER.warn("Voltage level {} has no high voltage limit defined. Please add one or use a voltage limit override.", vl.getId()); integrityVoltageLevelLimits = false; } else if (overrides.get(0).isRelative()) { LOGGER.warn("Relative voltage override impossible on undefined high voltage limit for voltage level {}.", vl.getId()); @@ -251,7 +249,7 @@ boolean checkVoltageLimitOverrides(Network network) { // Check existence of voltage level on which is applied voltage limit override if (voltageLevel == null) { - LOGGER.warn("Voltage level " + voltageLevelId + " not found in the network."); + LOGGER.warn("Voltage level {} not found in the network.", voltageLevelId); integrityVoltageLimitOverrides = false; } else { if (voltageLimitOverride.isRelative()) { @@ -259,13 +257,13 @@ boolean checkVoltageLimitOverrides(Network network) { voltageLevel.getLowVoltageLimit() : voltageLevel.getHighVoltageLimit(); // FIXME? if (Double.isNaN(value)) { LOGGER.warn("Voltage level {} has undefined {}, relative voltage limit override is impossible.", - voltageLevelId, voltageLimitOverride.getVoltageLimitType().toString()); + voltageLevelId, voltageLimitOverride.getVoltageLimitType()); integrityVoltageLimitOverrides = false; } if (voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT && voltageLimitOverride.getLimit() + voltageLevel.getLowVoltageLimit() < 0) { // ... verify low voltage limit override does not lead to negative limit value - LOGGER.warn("Voltage level " + voltageLevelId + " low relative override leads to negative low voltage limit."); + LOGGER.warn("Voltage level {} low relative override leads to a negative low voltage limit.", voltageLevelId); integrityVoltageLimitOverrides = false; } } diff --git a/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java b/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java index 77a454e5..230917d2 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/ItoolsTest.java @@ -69,7 +69,7 @@ public void testCreateOpenReacParameters() throws ParseException, IOException { vloList.add(new VoltageLimitOverride("voltageLevelId", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, 5)); for (int i = 0; i < vloList.size(); i++) { - assertTrue(vloList.get(i).equals(loadedParams.getSpecificVoltageLimits().get(i))); + assertEquals(vloList.get(i), loadedParams.getSpecificVoltageLimits().get(i)); } assertEquals(OpenReacOptimisationObjective.SPECIFIC_VOLTAGE_PROFILE, loadedParams.getObjective(), "Parsing of OpenReac parameters is wrong."); } diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java index f66784bb..448a4ab9 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java @@ -11,14 +11,14 @@ import static org.junit.jupiter.api.Assertions.*; -public class VoltageLimitsOverrideTest { +class VoltageLimitsOverrideTest { @Test void testToStringOverrideType() { VoltageLimitOverride.VoltageLimitType os = VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT; - assertEquals(os.toString(), "HIGH_VOLTAGE_LIMIT"); + assertEquals("HIGH_VOLTAGE_LIMIT", os.toString()); os = VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT; - assertEquals(os.toString(), "LOW_VOLTAGE_LIMIT"); + assertEquals("LOW_VOLTAGE_LIMIT", os.toString()); } @Test @@ -43,14 +43,14 @@ void invalidVoltageLimitOverride() { @Test void validVoltageLimitOverride() { VoltageLimitOverride vlo = new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, -4); - assertEquals(vlo.getVoltageLimitType(), VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT); + assertEquals(VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, vlo.getVoltageLimitType()); assertTrue(vlo.isRelative()); - assertEquals(vlo.getLimit(), -4); + assertEquals(-4, vlo.getLimit()); VoltageLimitOverride vlo2 = new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, false, 400); - assertEquals(vlo2.getVoltageLimitType(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT); + assertEquals(VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, vlo2.getVoltageLimitType()); assertFalse(vlo2.isRelative()); - assertEquals(vlo2.getLimit(), 400); + assertEquals(400, vlo2.getLimit()); } @Test @@ -68,5 +68,4 @@ void equalsVoltageLimitOverride() { VoltageLimitOverride vlo5 = new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, 6); assertNotEquals(vlo1, vlo5); } - } From f6e326ab49474aa5ab863dc4011b7ff18d0fbbda Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 10 Oct 2023 20:33:48 +0200 Subject: [PATCH 09/16] Again. Signed-off-by: Anne Tilloy --- .../powsybl/openreac/parameters/input/OpenReacParameters.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java index 49c39b91..12d118b3 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java @@ -215,7 +215,7 @@ boolean checkVoltageLevelLimits(Network network) { if (Double.isNaN(lowLimit)) { List overrides = getSpecificVoltageLimits(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT); if (overrides.size() != 1) { - LOGGER.warn("Voltage level has no low voltage limit defined. Please add one or use a voltage limit override.", vl.getId()); + LOGGER.warn("Voltage level {} has no low voltage limit defined. Please add one or use a voltage limit override.", vl.getId()); integrityVoltageLevelLimits = false; } else if (overrides.get(0).isRelative()) { // we have one and just one LOGGER.warn("Relative voltage override impossible on undefined low voltage limit for voltage level {}.", vl.getId()); From 5aa6b77765e28e6c0fd7ddaa0f97102e0c2d3007 Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 11 Oct 2023 11:24:40 +0200 Subject: [PATCH 10/16] Refactor. Signed-off-by: parvy --- .../parameters/input/OpenReacParameters.java | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java index 12d118b3..dcb5f842 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java @@ -205,6 +205,10 @@ public void checkIntegrity(Network network) throws InvalidParametersException { } + /** + * @param network the network on which voltage levels are verified. + * @return true if the voltage level limits are correct taking into account voltage limit overrides, false otherwise. + */ boolean checkVoltageLevelLimits(Network network) { boolean integrityVoltageLevelLimits = true; @@ -238,7 +242,7 @@ boolean checkVoltageLevelLimits(Network network) { /** * @param network the network on which are applied voltage limit overrides. - * @return true if the integrity of voltage limit overrides is verifies, false otherwise. + * @return true if the integrity of voltage limit overrides is verified, false otherwise. */ boolean checkVoltageLimitOverrides(Network network) { // Check integrity of voltage overrides @@ -251,21 +255,22 @@ boolean checkVoltageLimitOverrides(Network network) { if (voltageLevel == null) { LOGGER.warn("Voltage level {} not found in the network.", voltageLevelId); integrityVoltageLimitOverrides = false; - } else { - if (voltageLimitOverride.isRelative()) { - double value = voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT ? - voltageLevel.getLowVoltageLimit() : voltageLevel.getHighVoltageLimit(); // FIXME? - if (Double.isNaN(value)) { - LOGGER.warn("Voltage level {} has undefined {}, relative voltage limit override is impossible.", - voltageLevelId, voltageLimitOverride.getVoltageLimitType()); - integrityVoltageLimitOverrides = false; - } - if (voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT - && voltageLimitOverride.getLimit() + voltageLevel.getLowVoltageLimit() < 0) { - // ... verify low voltage limit override does not lead to negative limit value - LOGGER.warn("Voltage level {} low relative override leads to a negative low voltage limit.", voltageLevelId); - integrityVoltageLimitOverrides = false; - } + continue; + } + + if (voltageLimitOverride.isRelative()) { + double value = voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT ? + voltageLevel.getLowVoltageLimit() : voltageLevel.getHighVoltageLimit(); // FIXME? + if (Double.isNaN(value)) { + LOGGER.warn("Voltage level {} has undefined {}, relative voltage limit override is impossible.", + voltageLevelId, voltageLimitOverride.getVoltageLimitType()); + integrityVoltageLimitOverrides = false; + } + if (voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT + && voltageLimitOverride.getLimit() + voltageLevel.getLowVoltageLimit() < 0) { + // ... verify low voltage limit override does not lead to negative limit value + LOGGER.warn("Voltage level {} low relative override leads to a negative low voltage limit.", voltageLevelId); + integrityVoltageLimitOverrides = false; } } } From d1eedd3bc99d71440bb06c5d8e958b9780b34317 Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 11 Oct 2023 12:35:58 +0200 Subject: [PATCH 11/16] Add check and fix export of substations ID for voltage overrides. Signed-off-by: parvy --- .../parameters/input/OpenReacParameters.java | 11 +++++++++ .../VoltageLevelLimitsOverrideInput.java | 3 +-- .../VoltageLevelLimitsOverrideInputTest.java | 24 +++++++++++++++++-- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java index dcb5f842..005f6396 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java @@ -216,6 +216,17 @@ boolean checkVoltageLevelLimits(Network network) { double lowLimit = vl.getLowVoltageLimit(); double highLimit = vl.getHighVoltageLimit(); + if (lowLimit <= 0) { + List overrides = getSpecificVoltageLimits(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT); + if (overrides.size() != 1) { + LOGGER.warn("Voltage level {} has a negative or null low voltage limit. Please change it or use a voltage limit override.", vl.getId()); + integrityVoltageLevelLimits = false; + } else if (overrides.get(0).isRelative() && overrides.get(0).getLimit() + lowLimit <= 0) { + LOGGER.warn("Voltage level {} has a negative low voltage limit, even taking into account voltage limit override.", vl.getId()); + integrityVoltageLevelLimits = false; + } + } + if (Double.isNaN(lowLimit)) { List overrides = getSpecificVoltageLimits(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT); if (overrides.size() != 1) { 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 c51c79dc..6748b461 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 @@ -10,7 +10,6 @@ import com.powsybl.ampl.executor.AmplInputFile; import com.powsybl.commons.util.StringToIntMapper; import com.powsybl.iidm.network.Network; -import com.powsybl.openreac.parameters.AmplIOUtils; import org.jgrapht.alg.util.Pair; import java.io.ByteArrayInputStream; @@ -82,7 +81,7 @@ 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()), AmplIOUtils.addQuotes(voltageLevelId)}; + String[] tokens = {Integer.toString(amplId), Double.toString(limits.getFirst()), Double.toString(limits.getSecond()), "\"" + voltageLevelId + "\""}; dataBuilder.append(String.join(" ", tokens)); dataBuilder.append(System.lineSeparator()); } 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 1011eef0..c36dbd08 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 @@ -49,7 +49,7 @@ void testValidRelativeVoltageOverride() throws IOException { try (var is = input.getParameterFileAsStream(mapper)) { String data = new String(ByteStreams.toByteArray(is), StandardCharsets.UTF_8); String ref = String.join(System.lineSeparator(), "#num minV (pu) maxV (pu) id", - "1 0.7916666666666667 1.1666666666666665 'VLGEN'") + System.lineSeparator() + System.lineSeparator(); + "1 0.7916666666666667 1.1666666666666665 \"VLGEN\"") + System.lineSeparator() + System.lineSeparator(); assertEquals(ref, data); } } @@ -73,11 +73,31 @@ void testValidAbsoluteVoltageOverride() throws IOException { try (var is = input.getParameterFileAsStream(mapper)) { String data = new String(ByteStreams.toByteArray(is), StandardCharsets.UTF_8); String ref = String.join(System.lineSeparator(), "#num minV (pu) maxV (pu) id", - "1 0.8333333333333334 1.0833333333333333 'VLGEN'") + System.lineSeparator() + System.lineSeparator(); + "1 0.8333333333333334 1.0833333333333333 \"VLGEN\"") + System.lineSeparator() + System.lineSeparator(); assertEquals(ref, data); } } + @Test + void testNullVoltageLimitWithoutOverride() { + Network network = IeeeCdfNetworkFactory.create118(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network + + VoltageLevel vl = network.getVoltageLevels().iterator().next(); + OpenReacParameters params = new OpenReacParameters(); + + // if one low voltage limit is <= 0 and there is no voltage limit override, invalid OpenReacParameters + vl.setLowVoltageLimit(0); + assertThrows(PowsyblException.class, () -> params.checkIntegrity(network)); + + // if one low voltage limit is <= 0 and the voltage limit override is not enough, invalid OpenReacParameters + List overrides = new ArrayList<>(); + overrides.add(new VoltageLimitOverride(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, + true, 0)); + params.addSpecificVoltageLimits(overrides); + assertThrows(PowsyblException.class, () -> params.checkIntegrity(network)); + } + @Test void testUndefinedVoltageLimitsWithoutOverride() { Network network = IeeeCdfNetworkFactory.create118(); From 60ce8ecd883f8fe71ba03a08a5db1d1ee9e0c5be Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 18 Oct 2023 09:56:43 +0200 Subject: [PATCH 12/16] Add check for high relative override leading to negative voltage limit. Signed-off-by: parvy --- .../openreac/parameters/input/OpenReacParameters.java | 8 ++++---- .../input/VoltageLevelLimitsOverrideInputTest.java | 9 ++++++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java index d04ef362..b6d1578d 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java @@ -279,10 +279,10 @@ boolean checkVoltageLimitOverrides(Network network) { voltageLevelId, voltageLimitOverride.getVoltageLimitType()); integrityVoltageLimitOverrides = false; } - if (voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT - && voltageLimitOverride.getLimit() + voltageLevel.getLowVoltageLimit() < 0) { - // ... verify low voltage limit override does not lead to negative limit value - LOGGER.warn("Voltage level {} low relative override leads to a negative low voltage limit.", voltageLevelId); + // verify voltage limit override does not lead to negative limit value + if (value + voltageLimitOverride.getLimit() < 0) { + LOGGER.warn("Voltage level {} relative override leads to a negative {}.", + voltageLevelId, voltageLimitOverride.getVoltageLimitType()); integrityVoltageLimitOverrides = false; } } 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 c36dbd08..50c9c578 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 @@ -123,7 +123,7 @@ void testUndefinedVoltageLimitsWithoutOverride() { } @Test - void testVoltageOverrideWithNegativeLowVoltageValue() { + void testVoltageOverrideWithNegativeVoltageLimit() { Network network = IeeeCdfNetworkFactory.create118(); setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network @@ -137,6 +137,13 @@ void testVoltageOverrideWithNegativeLowVoltageValue() { voltageLimitsOverride.add(new VoltageLimitOverride(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, -410)); params.addSpecificVoltageLimits(voltageLimitsOverride); assertThrows(InvalidParametersException.class, () -> params.checkIntegrity(network)); + + // if high relative voltage override leads to negative voltage limit, throws exception + OpenReacParameters params2 = new OpenReacParameters(); + List voltageLimitsOverride2 = new ArrayList<>(); + voltageLimitsOverride2.add(new VoltageLimitOverride(vl.getId(), VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, -490)); + params2.addSpecificVoltageLimits(voltageLimitsOverride2); + assertThrows(InvalidParametersException.class, () -> params2.checkIntegrity(network)); } @Test From 82d35d24a992695254838215d66209057eb7d099 Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 18 Oct 2023 10:35:57 +0200 Subject: [PATCH 13/16] Add check for null voltage limit, and case with low voltage limit greater than high limit. Signed-off-by: parvy --- .../parameters/input/OpenReacParameters.java | 8 +--- .../VoltageLevelLimitsOverrideInput.java | 5 ++ .../VoltageLevelLimitsOverrideInputTest.java | 46 ++++++++++++++++--- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java index b6d1578d..0763387b 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java @@ -223,12 +223,8 @@ boolean checkVoltageLevelLimits(Network network) { if (overrides.size() != 1) { LOGGER.warn("Voltage level {} has a negative or null low voltage limit. Please change it or use a voltage limit override.", vl.getId()); integrityVoltageLevelLimits = false; - } else if (overrides.get(0).isRelative() && overrides.get(0).getLimit() + lowLimit <= 0) { - LOGGER.warn("Voltage level {} has a negative low voltage limit, even taking into account voltage limit override.", vl.getId()); - integrityVoltageLevelLimits = false; } } - if (Double.isNaN(lowLimit)) { List overrides = getSpecificVoltageLimits(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT); if (overrides.size() != 1) { @@ -280,8 +276,8 @@ boolean checkVoltageLimitOverrides(Network network) { integrityVoltageLimitOverrides = false; } // verify voltage limit override does not lead to negative limit value - if (value + voltageLimitOverride.getLimit() < 0) { - LOGGER.warn("Voltage level {} relative override leads to a negative {}.", + if (value + voltageLimitOverride.getLimit() <= 0) { + LOGGER.warn("Voltage level {} relative override leads to a negative or null {}.", voltageLevelId, voltageLimitOverride.getVoltageLimitType()); integrityVoltageLimitOverrides = false; } 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 6748b461..dbae0ad1 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 @@ -10,6 +10,7 @@ import com.powsybl.ampl.executor.AmplInputFile; import com.powsybl.commons.util.StringToIntMapper; import com.powsybl.iidm.network.Network; +import com.powsybl.openreac.exceptions.InvalidParametersException; import org.jgrapht.alg.util.Pair; import java.io.ByteArrayInputStream; @@ -60,6 +61,10 @@ private void transformToNormalizedVoltage(List voltageLimi } else { throw new UnsupportedOperationException("Unsupported voltage limit type: " + voltageLimitOverride.getVoltageLimitType()); } + + if (newLimits.getFirst() > newLimits.getSecond()) { + throw new InvalidParametersException("Override on voltage level " + voltageLevelId + " leads to low voltage limit > high voltage limit."); + } normalizedVoltageLimitsOverride.put(voltageLevelId, newLimits); } } 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 50c9c578..d78592e5 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 @@ -89,13 +89,6 @@ void testNullVoltageLimitWithoutOverride() { // if one low voltage limit is <= 0 and there is no voltage limit override, invalid OpenReacParameters vl.setLowVoltageLimit(0); assertThrows(PowsyblException.class, () -> params.checkIntegrity(network)); - - // if one low voltage limit is <= 0 and the voltage limit override is not enough, invalid OpenReacParameters - List overrides = new ArrayList<>(); - overrides.add(new VoltageLimitOverride(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, - true, 0)); - params.addSpecificVoltageLimits(overrides); - assertThrows(PowsyblException.class, () -> params.checkIntegrity(network)); } @Test @@ -138,12 +131,51 @@ void testVoltageOverrideWithNegativeVoltageLimit() { params.addSpecificVoltageLimits(voltageLimitsOverride); assertThrows(InvalidParametersException.class, () -> params.checkIntegrity(network)); + // if low relative voltage override leads to null voltage limit, throws exception + params.getSpecificVoltageLimits().clear(); + voltageLimitsOverride.clear(); + voltageLimitsOverride.add(new VoltageLimitOverride(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, -400)); + params.addSpecificVoltageLimits(voltageLimitsOverride); + assertThrows(InvalidParametersException.class, () -> params.checkIntegrity(network)); + // if high relative voltage override leads to negative voltage limit, throws exception OpenReacParameters params2 = new OpenReacParameters(); List voltageLimitsOverride2 = new ArrayList<>(); voltageLimitsOverride2.add(new VoltageLimitOverride(vl.getId(), VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, -490)); params2.addSpecificVoltageLimits(voltageLimitsOverride2); assertThrows(InvalidParametersException.class, () -> params2.checkIntegrity(network)); + + // if high relative voltage override leads to null voltage limit, throws exception + params2.getSpecificVoltageLimits().clear(); + voltageLimitsOverride2.clear(); + voltageLimitsOverride2.add(new VoltageLimitOverride(vl.getId(), VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, -480)); + params2.addSpecificVoltageLimits(voltageLimitsOverride2); + assertThrows(InvalidParametersException.class, () -> params2.checkIntegrity(network)); + } + + @Test + void testVoltageOverrideWithLowLimitGreaterHighLimit() { + Network network = IeeeCdfNetworkFactory.create118(); + setDefaultVoltageLimits(network); // set default voltage limits to every voltage levels of the network + + VoltageLevel vl = network.getVoltageLevels().iterator().next(); + vl.setHighVoltageLimit(480); + vl.setLowVoltageLimit(400); + + List voltageLimitsOverride = new ArrayList<>(); + voltageLimitsOverride.add(new VoltageLimitOverride(vl.getId(), VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, -90)); + + List voltageLimitsOverride2 = new ArrayList<>(); + voltageLimitsOverride2.add(new VoltageLimitOverride(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, 90)); + + List voltageLimitsOverride3 = new ArrayList<>(); + voltageLimitsOverride3.add(new VoltageLimitOverride(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, false, 395)); + voltageLimitsOverride3.add(new VoltageLimitOverride(vl.getId(), VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, false, 390)); + + // if after relative override, low limit > high limit, wrong parameters + assertThrows(InvalidParametersException.class, () -> new VoltageLevelLimitsOverrideInput(voltageLimitsOverride, network)); + assertThrows(InvalidParametersException.class, () -> new VoltageLevelLimitsOverrideInput(voltageLimitsOverride2, network)); + assertThrows(InvalidParametersException.class, () -> new VoltageLevelLimitsOverrideInput(voltageLimitsOverride3, network)); } @Test From 3b3df3213955c619ff9dc03948acdc92f6cb420b Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 18 Oct 2023 17:24:30 +0200 Subject: [PATCH 14/16] Use Boolean class instead of boolean and add checks for consistency. Signed-off-by: parvy --- .../openreac/parameters/input/VoltageLimitOverride.java | 5 ++++- .../input/json/VoltageLimitOverrideDeserializer.java | 4 ++-- .../input/json/VoltageLimitOverrideSerializer.java | 8 ++++---- .../parameters/input/VoltageLimitsOverrideTest.java | 6 ++++++ 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java index f3a802f5..07fad815 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java @@ -52,7 +52,10 @@ public String getVoltageLevelId() { return voltageLevelId; } - public VoltageLimitOverride(String voltageLevelId, VoltageLimitType type, boolean isRelative, double limit) { + public VoltageLimitOverride(String voltageLevelId, VoltageLimitType type, Boolean isRelative, double limit) { + if (isRelative == null) { + throw new InvalidParametersException("The kind of voltage limit override must be specified."); + } if (Double.isNaN(limit)) { throw new InvalidParametersException("The voltage limit override must be defined."); } diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java index de321d25..046bde09 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java @@ -28,7 +28,7 @@ public VoltageLimitOverrideDeserializer() { public VoltageLimitOverride deserialize(JsonParser parser, DeserializationContext deserializationContext) throws IOException { String voltageLevelId = null; VoltageLimitOverride.VoltageLimitType type = null; - boolean isRelative = true; + Boolean isRelative = null; double overrideValue = 0; while (parser.nextToken() != JsonToken.END_OBJECT) { @@ -43,7 +43,7 @@ public VoltageLimitOverride deserialize(JsonParser parser, DeserializationContex break; case "isRelative": parser.nextToken(); - isRelative = parser.readValueAs(boolean.class); + isRelative = parser.readValueAs(Boolean.class); break; case "value": parser.nextToken(); diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java index 9467cc3d..0bb16b58 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideSerializer.java @@ -26,10 +26,10 @@ public VoltageLimitOverrideSerializer() { @Override public void serialize(VoltageLimitOverride voltageLimitOverride, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeStartObject(); - jsonGenerator.writeObjectField("voltageLevelId", voltageLimitOverride.getVoltageLevelId()); - jsonGenerator.writeObjectField("voltageLimitType", voltageLimitOverride.getVoltageLimitType()); - jsonGenerator.writeObjectField("isRelative", voltageLimitOverride.isRelative()); - jsonGenerator.writeNumberField("value", voltageLimitOverride.getLimit()); // FIXME + jsonGenerator.writeStringField("voltageLevelId", voltageLimitOverride.getVoltageLevelId()); + jsonGenerator.writeStringField("voltageLimitType", voltageLimitOverride.getVoltageLimitType().name()); + jsonGenerator.writeBooleanField("isRelative", voltageLimitOverride.isRelative()); + jsonGenerator.writeNumberField("value", voltageLimitOverride.getLimit()); jsonGenerator.writeEndObject(); } } diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java index 448a4ab9..89e4da21 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java @@ -38,6 +38,12 @@ void invalidVoltageLimitOverride() { () -> new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, false, -1)); assertThrows(InvalidParametersException.class, () -> new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, false, -1)); + + // Verify it is impossible to create voltage limit override with undefined override type + assertThrows(InvalidParametersException.class, + () -> new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, null, 2)); + assertThrows(InvalidParametersException.class, + () -> new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, null, -5)); } @Test From 26c10b49e3d38a64d228ec21ef05b0e5c0746a27 Mon Sep 17 00:00:00 2001 From: parvy Date: Wed, 18 Oct 2023 17:39:03 +0200 Subject: [PATCH 15/16] Fix code smell. Signed-off-by: parvy --- .../parameters/input/OpenReacParameters.java | 26 +++++++++++++++---- .../input/VoltageLimitOverride.java | 2 +- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java index 0763387b..98cc1572 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/OpenReacParameters.java @@ -195,7 +195,8 @@ public void checkIntegrity(Network network) throws InvalidParametersException { } // Check integrity of low/high voltage limits, taking into account voltage limit overrides - boolean integrityVoltageLevelLimits = checkVoltageLevelLimits(network); + boolean integrityVoltageLevelLimits = checkLowVoltageLevelLimits(network); + integrityVoltageLevelLimits &= checkHighVoltageLevelLimits(network); if (!integrityVoltageLevelLimits) { throw new InvalidParametersException("At least one voltage level has an undefined or incorrect voltage limit."); } @@ -209,14 +210,14 @@ public void checkIntegrity(Network network) throws InvalidParametersException { /** * @param network the network on which voltage levels are verified. - * @return true if the voltage level limits are correct taking into account voltage limit overrides, false otherwise. + * @return true if the low voltage level limits are correct taking into account low voltage limit overrides, + * false otherwise. */ - boolean checkVoltageLevelLimits(Network network) { + boolean checkLowVoltageLevelLimits(Network network) { boolean integrityVoltageLevelLimits = true; for (VoltageLevel vl : network.getVoltageLevels()) { double lowLimit = vl.getLowVoltageLimit(); - double highLimit = vl.getHighVoltageLimit(); if (lowLimit <= 0) { List overrides = getSpecificVoltageLimits(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT); @@ -235,6 +236,21 @@ boolean checkVoltageLevelLimits(Network network) { integrityVoltageLevelLimits = false; } } + } + return integrityVoltageLevelLimits; + } + + /** + * @param network the network on which voltage levels are verified. + * @return true if the high voltage level limits are correct taking into account high voltage limit overrides, + * false otherwise. + */ + boolean checkHighVoltageLevelLimits(Network network) { + boolean integrityVoltageLevelLimits = true; + + for (VoltageLevel vl : network.getVoltageLevels()) { + double highLimit = vl.getHighVoltageLimit(); + if (Double.isNaN(highLimit)) { List overrides = getSpecificVoltageLimits(vl.getId(), VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT); if (overrides.size() != 1) { @@ -269,7 +285,7 @@ boolean checkVoltageLimitOverrides(Network network) { if (voltageLimitOverride.isRelative()) { double value = voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT ? - voltageLevel.getLowVoltageLimit() : voltageLevel.getHighVoltageLimit(); // FIXME? + voltageLevel.getLowVoltageLimit() : voltageLevel.getHighVoltageLimit(); if (Double.isNaN(value)) { LOGGER.warn("Voltage level {} has undefined {}, relative voltage limit override is impossible.", voltageLevelId, voltageLimitOverride.getVoltageLimitType()); diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java index 07fad815..e7f63dd3 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java @@ -59,7 +59,7 @@ public VoltageLimitOverride(String voltageLevelId, VoltageLimitType type, Boolea if (Double.isNaN(limit)) { throw new InvalidParametersException("The voltage limit override must be defined."); } - if (limit <= 0 && !isRelative) { + if (limit <= 0 && Boolean.FALSE.equals(isRelative)) { throw new InvalidParametersException("The voltage limit override is in absolute value: must be positive."); } this.voltageLevelId = voltageLevelId; From 738abda8add5f4797a4a1ffb484054c0dce1d856 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Thu, 19 Oct 2023 10:09:06 +0200 Subject: [PATCH 16/16] Fix deserialization. Signed-off-by: Anne Tilloy --- .../input/VoltageLimitOverride.java | 7 ++---- .../VoltageLimitOverrideDeserializer.java | 25 +++++++++++-------- .../input/VoltageLimitsOverrideTest.java | 6 ----- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java index e7f63dd3..e1ace00a 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/VoltageLimitOverride.java @@ -52,17 +52,14 @@ public String getVoltageLevelId() { return voltageLevelId; } - public VoltageLimitOverride(String voltageLevelId, VoltageLimitType type, Boolean isRelative, double limit) { - if (isRelative == null) { - throw new InvalidParametersException("The kind of voltage limit override must be specified."); - } + public VoltageLimitOverride(String voltageLevelId, VoltageLimitType type, boolean isRelative, double limit) { if (Double.isNaN(limit)) { throw new InvalidParametersException("The voltage limit override must be defined."); } if (limit <= 0 && Boolean.FALSE.equals(isRelative)) { throw new InvalidParametersException("The voltage limit override is in absolute value: must be positive."); } - this.voltageLevelId = voltageLevelId; + this.voltageLevelId = Objects.requireNonNull(voltageLevelId); this.type = Objects.requireNonNull(type); this.isRelative = isRelative; this.limit = limit; diff --git a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java index 046bde09..73574707 100644 --- a/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java +++ b/open-reac/src/main/java/com/powsybl/openreac/parameters/input/json/VoltageLimitOverrideDeserializer.java @@ -10,6 +10,7 @@ import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.powsybl.openreac.exceptions.InvalidParametersException; import com.powsybl.openreac.parameters.input.VoltageLimitOverride; import java.io.IOException; @@ -29,30 +30,32 @@ public VoltageLimitOverride deserialize(JsonParser parser, DeserializationContex String voltageLevelId = null; VoltageLimitOverride.VoltageLimitType type = null; Boolean isRelative = null; - double overrideValue = 0; + double overrideValue = Double.NaN; while (parser.nextToken() != JsonToken.END_OBJECT) { switch (parser.getCurrentName()) { - case "voltageLevelId": + case "voltageLevelId" -> { parser.nextToken(); voltageLevelId = parser.readValueAs(String.class); - break; - case "voltageLimitType": + } + case "voltageLimitType" -> { parser.nextToken(); type = parser.readValueAs(VoltageLimitOverride.VoltageLimitType.class); - break; - case "isRelative": + } + case "isRelative" -> { parser.nextToken(); isRelative = parser.readValueAs(Boolean.class); - break; - case "value": + } + case "value" -> { parser.nextToken(); overrideValue = parser.readValueAs(Double.class); - break; - default: - throw new IllegalStateException("Unexpected field: " + parser.getCurrentName()); + } + default -> throw new IllegalStateException("Unexpected field: " + parser.getCurrentName()); } } + if (isRelative == null) { + throw new InvalidParametersException("A relative or absolute voltage limit override must be specified."); + } return new VoltageLimitOverride(voltageLevelId, type, isRelative, overrideValue); } } diff --git a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java index 89e4da21..448a4ab9 100644 --- a/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java +++ b/open-reac/src/test/java/com/powsybl/openreac/parameters/input/VoltageLimitsOverrideTest.java @@ -38,12 +38,6 @@ void invalidVoltageLimitOverride() { () -> new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, false, -1)); assertThrows(InvalidParametersException.class, () -> new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, false, -1)); - - // Verify it is impossible to create voltage limit override with undefined override type - assertThrows(InvalidParametersException.class, - () -> new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, null, 2)); - assertThrows(InvalidParametersException.class, - () -> new VoltageLimitOverride("vl", VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, null, -5)); } @Test