Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Voltage limit override new version #27

Merged
merged 17 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@geofjamg can we delete the tool now? If yes, I will dot that in a other PR.

openReacParameters.addSpecificVoltageLimits(Map.of(voltageId,
new VoltageLimitOverride(VoltageLimitOverride.OverrideKind.RELATIVE, VoltageLimitOverride.OverrideKind.RELATIVE,
lowerPercent, upperPercent)));
});
}
boolean objectiveSet = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -180,34 +179,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 (voltageLevel.getNominalV()
+ override.getDeltaLowVoltageLimit()
< 0) {
throw new InvalidParametersException("Voltage level " + voltageLevelId + " override leads to negative lower voltage level.");
// 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;
}
}

}

if (inconsistentOverride) {
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 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.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -43,14 +42,46 @@ private void transformToNormalizedVoltage(Map<String, VoltageLimitOverride> volt
for (Map.Entry<String, VoltageLimitOverride> 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());
}
}

Expand All @@ -64,18 +95,22 @@ public InputStream getParameterFileAsStream(StringToIntMapper<AmplSubset> string
StringBuilder dataBuilder = new StringBuilder();
dataBuilder.append("#num minV (pu) maxV (pu) id");
dataBuilder.append(System.lineSeparator());

for (Map.Entry<String, VoltageLimitOverride> 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 = 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));
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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,42 @@
* Class to store an override of a voltage level voltage limits.
*
* @author Nicolas Pierre <nicolas.pierre at artelys.com>
* @author Pierre Arvy <pierre.arvy at artelys.com>
*/
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
Expand All @@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* 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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Loading