Skip to content

Commit

Permalink
[Shortcircuit] Add voltage value in VoltageRange (#2728)
Browse files Browse the repository at this point in the history
* Proposition for range voltage.
* Add serialization/deserialization
* Improvements and add tests on FaultParameters
* Add test on voltage ranges
* Change FaultParameters version and improve tests
* Fix version control for voltage field in deserialization.
* Use the same SOURCE_VERSION_ATTRIBUTE key + identify the processed parameters' type

---------

Signed-off-by: Coline PILOQUET <[email protected]>
Signed-off-by: Olivier Perrin <[email protected]>
Co-authored-by: Olivier Perrin <[email protected]>
  • Loading branch information
colinepiloquet and olperr1 authored Dec 5, 2023
1 parent df8015f commit 1884fe9
Show file tree
Hide file tree
Showing 15 changed files with 263 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ public class FaultParameters {
// VERSION = 1.0 withLimitViolations, withVoltageMap, withFeederResult, studyType and minVoltageDropProportionalThreshold
// VERSION = 1.1 withVoltageMap -> withFortescueResult and withVoltageResult
// VERSION = 1.2 subTransientCoefficient, withLoads, withShuntCompensators, withVSCConverterStations, withNeutralPosition,
// initialVoltageProfileMode, voltageRanges
public static final String VERSION = "1.2";
// initialVoltageProfileMode, voltageRange
// VERSION = 1.3 voltage in voltageRange
public static final String VERSION = "1.3";

private final String id;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ public class ShortCircuitParameters extends AbstractExtendable<ShortCircuitParam
// VERSION = 1.0 withLimitViolations, withVoltageMap, withFeederResult, studyType and minVoltageDropProportionalThreshold
// VERSION = 1.1 withVoltageMap -> withFortescueResult and withVoltageResult
// VERSION = 1.2 subTransientCoefficient, withLoads, withShuntCompensators, withVSCConverterStations, withNeutralPosition,
// initialVoltageProfileMode, voltageRanges
// VERSION = 1.3 detailedLog
// initialVoltageProfileMode, voltageRange
// VERSION = 1.3 detailedLog, voltage in voltageRange
public static final String VERSION = "1.3";

private boolean withLimitViolations = DEFAULT_WITH_LIMIT_VIOLATIONS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,25 @@
import java.util.Objects;

/**
* A class that stores coefficients to be applied to every nominal voltage in a range. This is used to define the configured initial voltage profile
* for short circuit calculation.
* A class that stores coefficients and nominal voltages to be applied to each nominal voltage of the network in a range.
* This is used to define the configured initial voltage profile for short circuit calculation.
* The voltage attribute allows to modify the nominal voltage to be considered for each nominal voltage of the range.
* The coefficient is a coefficient that is applied to each nominal voltage.
* @author Coline Piloquet {@literal <coline.piloquet at rte-france.com>}
*/
public class VoltageRange {
private final Range<Double> range;
private final double rangeCoefficient;
private final double voltage;

public VoltageRange(double lowVoltage, double highVoltage, double rangeCoefficient) {
this(lowVoltage, highVoltage, rangeCoefficient, Double.NaN);
}

public VoltageRange(double lowVoltage, double highVoltage, double rangeCoefficient, double voltage) {
this.range = Range.of(lowVoltage, highVoltage);
this.rangeCoefficient = checkCoefficient(rangeCoefficient);
this.voltage = checkVoltage(voltage, this.range);
}

/**
Expand Down Expand Up @@ -55,6 +63,13 @@ public double getMaximumNominalVoltage() {
return range.getMaximum();
}

/**
* The nominal voltage to consider for the range. All nominal voltages in the range will be replaced by this value.
*/
public double getVoltage() {
return voltage;
}

static void checkVoltageRange(List<VoltageRange> voltageRange) {
if (voltageRange == null || voltageRange.isEmpty()) {
return;
Expand All @@ -76,6 +91,13 @@ private static double checkCoefficient(double rangeCoefficient) {
return rangeCoefficient;
}

private static double checkVoltage(double voltage, Range<Double> voltageRange) {
if (!Double.isNaN(voltage) && !voltageRange.contains(voltage)) {
throw new PowsyblException("Range voltage should be in voltageRange " + voltageRange + " but it is " + voltage);
}
return voltage;
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand All @@ -85,12 +107,12 @@ public boolean equals(Object o) {
return false;
}
VoltageRange that = (VoltageRange) o;
return range.equals(that.range) && rangeCoefficient == that.rangeCoefficient;
return range.equals(that.range) && rangeCoefficient == that.rangeCoefficient && voltage == that.voltage;
}

@Override
public int hashCode() {
return Objects.hash(range, rangeCoefficient);
return Objects.hash(range, rangeCoefficient, voltage);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import java.io.IOException;
import java.util.List;

import static com.powsybl.shortcircuit.json.ParametersDeserializationConstants.*;

/**
* @author Thomas Adam {@literal <tadam at silicom.fr>}
*/
Expand Down Expand Up @@ -54,6 +56,8 @@ public FaultParameters deserialize(JsonParser parser, DeserializationContext des
case "version" -> {
parser.nextToken();
version = parser.getValueAsString();
JsonUtil.setSourceVersion(deserializationContext, version, SOURCE_VERSION_ATTRIBUTE);
deserializationContext.setAttribute(SOURCE_PARAMETER_TYPE_ATTRIBUTE, ParametersType.FAULT);
}
case "id" -> {
parser.nextToken();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright (c) 2023, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.shortcircuit.json;

/**
* @author Olivier Perrin {@literal <olivier.perrin at rte-france.com>}
*/
public final class ParametersDeserializationConstants {
private ParametersDeserializationConstants() {
}

public static final String SOURCE_VERSION_ATTRIBUTE = "sourceVersionAttribute";

public static final String SOURCE_PARAMETER_TYPE_ATTRIBUTE = "sourceParameterTypeAttribute";

public enum ParametersType {
FAULT,
SHORT_CIRCUIT
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.List;

import static com.powsybl.shortcircuit.json.JsonShortCircuitParameters.getExtensionSerializers;
import static com.powsybl.shortcircuit.json.ParametersDeserializationConstants.*;

/**
* @author Boubakeur Brahimi
Expand Down Expand Up @@ -46,6 +47,8 @@ public ShortCircuitParameters deserialize(JsonParser parser, DeserializationCont
case "version" -> {
parser.nextToken();
version = parser.getValueAsString();
JsonUtil.setSourceVersion(deserializationContext, version, SOURCE_VERSION_ATTRIBUTE);
deserializationContext.setAttribute(SOURCE_PARAMETER_TYPE_ATTRIBUTE, ParametersType.SHORT_CIRCUIT);
}
case "withLimitViolations" -> {
parser.nextToken();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,20 @@
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.powsybl.commons.json.JsonUtil;
import com.powsybl.shortcircuit.VoltageRange;

import java.io.IOException;

import static com.powsybl.shortcircuit.json.ParametersDeserializationConstants.SOURCE_VERSION_ATTRIBUTE;

/**
* @author Coline Piloquet {@literal <coline.piloquet at rte-france.com>}
*/
public class VoltageRangeDeserializer extends StdDeserializer<VoltageRange> {

private static final String CONTEXT_NAME = "VoltageRange";

public VoltageRangeDeserializer() {
super(VoltageRange.class);
}
Expand All @@ -28,6 +33,10 @@ public VoltageRange deserialize(JsonParser parser, DeserializationContext contex
Double minimumVoltage = Double.NaN;
Double maximumVoltage = Double.NaN;
Double coefficient = Double.NaN;
Double voltage = Double.NaN;
String version = JsonUtil.getSourceVersion(context, SOURCE_VERSION_ATTRIBUTE);
// If needed, the type of the enclosing Parameters (Fault, Short-circuit, ...) can be retrieved
// from the context with `context.getAttribute(ParametersDeserializationConstants.SOURCE_PARAMETER_TYPE_ATTRIBUTE)`

while (parser.nextToken() != JsonToken.END_OBJECT) {
switch (parser.getCurrentName()) {
Expand All @@ -43,10 +52,15 @@ public VoltageRange deserialize(JsonParser parser, DeserializationContext contex
parser.nextToken();
coefficient = parser.readValueAs(Double.class);
}
case "voltage" -> {
JsonUtil.assertGreaterOrEqualThanReferenceVersion(CONTEXT_NAME, "Tag: " + parser.getCurrentName(), version, "1.3");
parser.nextToken();
voltage = parser.readValueAs(Double.class);
}
default -> throw new IllegalStateException("Unexpected field: " + parser.getCurrentName());
}
}

return new VoltageRange(minimumVoltage, maximumVoltage, coefficient);
return new VoltageRange(minimumVoltage, maximumVoltage, coefficient, voltage);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ public class VoltageRangeSerializer extends StdSerializer<VoltageRange> {
}

@Override
public void serialize(VoltageRange coefficient, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException {
Objects.requireNonNull(coefficient);
public void serialize(VoltageRange voltageRange, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException {
Objects.requireNonNull(voltageRange);

jsonGenerator.writeStartObject();
JsonUtil.writeOptionalDoubleField(jsonGenerator, "minimumNominalVoltage", coefficient.getMinimumNominalVoltage());
JsonUtil.writeOptionalDoubleField(jsonGenerator, "maximumNominalVoltage", coefficient.getMaximumNominalVoltage());
JsonUtil.writeOptionalDoubleField(jsonGenerator, "voltageRangeCoefficient", coefficient.getRangeCoefficient());
JsonUtil.writeOptionalDoubleField(jsonGenerator, "minimumNominalVoltage", voltageRange.getMinimumNominalVoltage());
JsonUtil.writeOptionalDoubleField(jsonGenerator, "maximumNominalVoltage", voltageRange.getMaximumNominalVoltage());
JsonUtil.writeOptionalDoubleField(jsonGenerator, "voltageRangeCoefficient", voltageRange.getRangeCoefficient());
JsonUtil.writeOptionalDoubleField(jsonGenerator, "voltage", voltageRange.getVoltage());
jsonGenerator.writeEndObject();

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
Expand Down Expand Up @@ -120,8 +121,7 @@ public DummyExtension deserialize(JsonParser jsonParser, DeserializationContext
public DummyExtension deserializeAndUpdate(JsonParser jsonParser, DeserializationContext deserializationContext, DummyExtension parameters) throws IOException {
ObjectMapper objectMapper = createMapper();
ObjectReader objectReader = objectMapper.readerForUpdating(parameters);
DummyExtension updatedParameters = objectReader.readValue(jsonParser, DummyExtension.class);
return updatedParameters;
return objectReader.readValue(jsonParser, DummyExtension.class);
}

@Override
Expand Down Expand Up @@ -295,6 +295,13 @@ void readVersion12() {
assertEquals(Range.of(230., 375.), voltageRanges.get(2).getRange());
}

@Test
void testInvalidVersion12VoltageNotSupportedInVoltageRange() {
InputStream is = getClass().getResourceAsStream("/ShortCircuitParametersVersion12Invalid.json");
UncheckedIOException e = assertThrows(UncheckedIOException.class, () -> JsonShortCircuitParameters.read(is));
assertTrue(e.getMessage().contains("VoltageRange. Tag: voltage is not valid for version 1.2. Version should be >= 1.3"));
}

@Test
void readVersion13() {
ShortCircuitParameters parameters = JsonShortCircuitParameters
Expand All @@ -306,8 +313,13 @@ void readVersion13() {
assertEquals(StudyType.SUB_TRANSIENT, parameters.getStudyType());
assertEquals(0, parameters.getMinVoltageDropProportionalThreshold(), 0);
assertEquals(0.7, parameters.getSubTransientCoefficient(), 0);
assertEquals(InitialVoltageProfileMode.NOMINAL, parameters.getInitialVoltageProfileMode());
assertFalse(parameters.isDetailedReport());
assertEquals(InitialVoltageProfileMode.CONFIGURED, parameters.getInitialVoltageProfileMode());
assertEquals(1, parameters.getVoltageRanges().size());
VoltageRange voltageRange = parameters.getVoltageRanges().get(0);
assertEquals(Range.of(380., 410.), voltageRange.getRange());
assertEquals(1.05, voltageRange.getRangeCoefficient());
assertEquals(380., voltageRange.getVoltage());
}

@Test
Expand Down Expand Up @@ -412,4 +424,41 @@ void testReadWithUnsortedRanges() {
.read(stream));
assertEquals("Voltage ranges for configured initial voltage profile are overlapping", e0.getMessage());
}

@Test
void testVoltageRangeWithSpecificVoltage() {
VoltageRange range = new VoltageRange(100, 200, 0.9, 150);
assertEquals(100, range.getMinimumNominalVoltage());
assertEquals(200, range.getMaximumNominalVoltage());
assertEquals(0.9, range.getRangeCoefficient());
assertEquals(150, range.getVoltage());
}

@Test
void testVoltageRangeWithSpecificVoltageOutOfBounds() {
PowsyblException e = assertThrows(PowsyblException.class, () -> new VoltageRange(100, 150, 0.9, 200));
assertEquals("Range voltage should be in voltageRange [100.0..150.0] but it is 200.0", e.getMessage());
}

@Test
void roundTripWithVoltageInVoltageRange() throws IOException {
List<VoltageRange> voltageRanges = new ArrayList<>();
voltageRanges.add(new VoltageRange(0, 100, 0.95, 100));
voltageRanges.add(new VoltageRange(101, 150, 1.1, 140));
ShortCircuitParameters parameters = new ShortCircuitParameters()
.setInitialVoltageProfileMode(InitialVoltageProfileMode.CONFIGURED)
.setVoltageRanges(voltageRanges);
roundTripTest(parameters, JsonShortCircuitParameters::write, JsonShortCircuitParameters::read,
"/ShortCircuitParametersWithRangeVoltage.json");
}

@Test
void testVoltageRange() {
VoltageRange voltageRange0 = new VoltageRange(350.0, 400.0, 1.05, 380.0);
VoltageRange voltageRange1 = new VoltageRange(350.0, 400.0, 1.05, 380.0);
assertEquals(voltageRange1, voltageRange0);
assertNotNull(voltageRange0);
assertNotEquals(new VoltageRange(350.0, 400.0, 1.05), voltageRange0);
assertEquals(voltageRange0.hashCode(), voltageRange1.hashCode());
}
}
Loading

0 comments on commit 1884fe9

Please sign in to comment.