Skip to content

Commit

Permalink
Add range modes MIN_MAX, MAX and TARGET_P to check reactive capabilit…
Browse files Browse the repository at this point in the history
…y curves (#653)

Signed-off-by: Anne Tilloy <anne.tilloy@rte-france.com>
Co-authored-by: Geoffroy Jamgotchian <geoffroy.jamgotchian@gmail.com>
  • Loading branch information
annetill and geofjamg authored Nov 17, 2022
1 parent 172765f commit 0515857
Show file tree
Hide file tree
Showing 18 changed files with 209 additions and 71 deletions.
35 changes: 31 additions & 4 deletions src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ public class OpenLoadFlowParameters extends AbstractExtension<LoadFlowParameters

public static final String MAX_REALISTIC_VOLTAGE_NAME = "maxRealisticVoltage";

public static final String REACTIVE_RANGE_CHECK_MODE_NAME = "reactiveRangeCheckMode";

public static final List<String> SPECIFIC_PARAMETERS_NAMES = List.of(SLACK_BUS_SELECTION_PARAM_NAME,
SLACK_BUSES_IDS_PARAM_NAME,
LOW_IMPEDANCE_BRANCH_MODE_PARAM_NAME,
Expand All @@ -122,7 +124,8 @@ public class OpenLoadFlowParameters extends AbstractExtension<LoadFlowParameters
MIN_PLAUSIBLE_TARGET_VOLTAGE_NAME,
MAX_PLAUSIBLE_TARGET_VOLTAGE_NAME,
MIN_REALISTIC_VOLTAGE_NAME,
MAX_REALISTIC_VOLTAGE_NAME);
MAX_REALISTIC_VOLTAGE_NAME,
REACTIVE_RANGE_CHECK_MODE_NAME);

public enum VoltageInitModeOverride {
NONE,
Expand Down Expand Up @@ -185,6 +188,14 @@ public enum LowImpedanceBranchMode {

private double maxRealisticVoltage = NewtonRaphsonParameters.DEFAULT_MAX_REALISTIC_VOLTAGE;

public enum ReactiveRangeCheckMode {
MIN_MAX,
MAX,
TARGET_P
}

private ReactiveRangeCheckMode reactiveRangeCheckMode = LfNetworkParameters.REACTIVE_RANGE_CHECK_MODE_DEFAULT_VALUE;

@Override
public String getName() {
return "open-load-flow-parameters";
Expand Down Expand Up @@ -378,6 +389,15 @@ public OpenLoadFlowParameters setMaxRealisticVoltage(double maxRealisticVoltage)
return this;
}

public ReactiveRangeCheckMode getReactiveRangeCheckMode() {
return reactiveRangeCheckMode;
}

public OpenLoadFlowParameters setReactiveRangeCheckMode(ReactiveRangeCheckMode reactiveRangeCheckMode) {
this.reactiveRangeCheckMode = reactiveRangeCheckMode;
return this;
}

public static OpenLoadFlowParameters load() {
return load(PlatformConfig.defaultConfig());
}
Expand Down Expand Up @@ -407,7 +427,8 @@ public static OpenLoadFlowParameters load(PlatformConfig platformConfig) {
.setMinPlausibleTargetVoltage(config.getDoubleProperty(MIN_PLAUSIBLE_TARGET_VOLTAGE_NAME, LfNetworkParameters.MIN_PLAUSIBLE_TARGET_VOLTAGE_DEFAULT_VALUE))
.setMaxPlausibleTargetVoltage(config.getDoubleProperty(MAX_PLAUSIBLE_TARGET_VOLTAGE_NAME, LfNetworkParameters.MAX_PLAUSIBLE_TARGET_VOLTAGE_DEFAULT_VALUE))
.setMinRealisticVoltage(config.getDoubleProperty(MIN_REALISTIC_VOLTAGE_NAME, NewtonRaphsonParameters.DEFAULT_MIN_REALISTIC_VOLTAGE))
.setMaxRealisticVoltage(config.getDoubleProperty(MAX_REALISTIC_VOLTAGE_NAME, NewtonRaphsonParameters.DEFAULT_MAX_REALISTIC_VOLTAGE)));
.setMaxRealisticVoltage(config.getDoubleProperty(MAX_REALISTIC_VOLTAGE_NAME, NewtonRaphsonParameters.DEFAULT_MAX_REALISTIC_VOLTAGE))
.setReactiveRangeCheckMode(config.getEnumProperty(REACTIVE_RANGE_CHECK_MODE_NAME, ReactiveRangeCheckMode.class, LfNetworkParameters.REACTIVE_RANGE_CHECK_MODE_DEFAULT_VALUE)));
return parameters;
}

Expand Down Expand Up @@ -456,6 +477,8 @@ public OpenLoadFlowParameters update(Map<String, String> properties) {
.ifPresent(prop -> this.setMinRealisticVoltage(Double.parseDouble(prop)));
Optional.ofNullable(properties.get(MAX_REALISTIC_VOLTAGE_NAME))
.ifPresent(prop -> this.setMaxRealisticVoltage(Double.parseDouble(prop)));
Optional.ofNullable(properties.get(REACTIVE_RANGE_CHECK_MODE_NAME))
.ifPresent(prop -> this.setReactiveRangeCheckMode(ReactiveRangeCheckMode.valueOf(prop)));
return this;
}

Expand All @@ -482,6 +505,7 @@ public String toString() {
", maxPlausibleTargetVoltage=" + maxPlausibleTargetVoltage +
", minRealisticVoltage=" + minRealisticVoltage +
", maxRealisticVoltage=" + maxRealisticVoltage +
", reactiveRangeCheckMode=" + reactiveRangeCheckMode +
')';
}

Expand Down Expand Up @@ -548,6 +572,7 @@ public static void logAc(LoadFlowParameters parameters, OpenLoadFlowParameters p
LOGGER.info("Max plausible target voltage: {}", parametersExt.getMaxPlausibleTargetVoltage());
LOGGER.info("Min realistic voltage: {}", parametersExt.getMinRealisticVoltage());
LOGGER.info("Max realistic voltage: {}", parametersExt.getMaxRealisticVoltage());
LOGGER.info("Reactive range check mode: {}", parametersExt.getReactiveRangeCheckMode());
}

static VoltageInitializer getVoltageInitializer(LoadFlowParameters parameters, LfNetworkParameters networkParameters, MatrixFactory matrixFactory, Reporter reporter) {
Expand Down Expand Up @@ -610,7 +635,8 @@ static LfNetworkParameters getNetworkParameters(LoadFlowParameters parameters, O
.setReactiveLimits(!parameters.isNoGeneratorReactiveLimits())
.setHvdcAcEmulation(parameters.isHvdcAcEmulation())
.setMinPlausibleTargetVoltage(parametersExt.getMinPlausibleTargetVoltage())
.setMaxPlausibleTargetVoltage(parametersExt.getMaxPlausibleTargetVoltage());
.setMaxPlausibleTargetVoltage(parametersExt.getMaxPlausibleTargetVoltage())
.setReactiveRangeCheckMode(parametersExt.getReactiveRangeCheckMode());
}

public static AcLoadFlowParameters createAcParameters(Network network, LoadFlowParameters parameters, OpenLoadFlowParameters parametersExt,
Expand Down Expand Up @@ -693,7 +719,8 @@ public static DcLoadFlowParameters createDcParameters(LoadFlowParameters paramet
.setReactiveLimits(false)
.setHvdcAcEmulation(false) // FIXME
.setMinPlausibleTargetVoltage(parametersExt.getMinPlausibleTargetVoltage())
.setMaxPlausibleTargetVoltage(parametersExt.getMaxPlausibleTargetVoltage());
.setMaxPlausibleTargetVoltage(parametersExt.getMaxPlausibleTargetVoltage())
.setReactiveRangeCheckMode(ReactiveRangeCheckMode.MAX); // not useful for DC.

var equationSystemCreationParameters = new DcEquationSystemCreationParameters(true,
false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ enum GeneratorControlType {
OFF, REMOTE_REACTIVE_POWER, VOLTAGE
}

enum ReactiveRangeMode {
MIN, MAX, TARGET_P
}

String getId();

String getOriginalId();
Expand Down Expand Up @@ -51,7 +55,7 @@ enum GeneratorControlType {

double getMaxQ();

double getMaxRangeQ();
double getRangeQ(ReactiveRangeMode reactiveRangeMode);

default boolean isParticipating() {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package com.powsybl.openloadflow.network;

import com.powsybl.iidm.network.Country;
import com.powsybl.openloadflow.OpenLoadFlowParameters;
import com.powsybl.openloadflow.graph.EvenShiloachGraphDecrementalConnectivityFactory;
import com.powsybl.openloadflow.graph.GraphConnectivityFactory;

Expand All @@ -28,6 +29,8 @@ public class LfNetworkParameters {

public static final double MAX_PLAUSIBLE_TARGET_VOLTAGE_DEFAULT_VALUE = 1.2;

public static final OpenLoadFlowParameters.ReactiveRangeCheckMode REACTIVE_RANGE_CHECK_MODE_DEFAULT_VALUE = OpenLoadFlowParameters.ReactiveRangeCheckMode.MAX;

private SlackBusSelector slackBusSelector = new FirstSlackBusSelector();

private GraphConnectivityFactory<LfBus, LfBranch> connectivityFactory = new EvenShiloachGraphDecrementalConnectivityFactory<>();
Expand Down Expand Up @@ -72,6 +75,8 @@ public class LfNetworkParameters {

private Set<String> loaderPostProcessorSelection = Collections.emptySet();

private OpenLoadFlowParameters.ReactiveRangeCheckMode reactiveRangeCheckMode = REACTIVE_RANGE_CHECK_MODE_DEFAULT_VALUE;

public SlackBusSelector getSlackBusSelector() {
return slackBusSelector;
}
Expand Down Expand Up @@ -261,6 +266,15 @@ public LfNetworkParameters setMaxPlausibleTargetVoltage(double maxPlausibleTarge
return this;
}

public OpenLoadFlowParameters.ReactiveRangeCheckMode getReactiveRangeCheckMode() {
return reactiveRangeCheckMode;
}

public LfNetworkParameters setReactiveRangeCheckMode(OpenLoadFlowParameters.ReactiveRangeCheckMode reactiveRangeCheckMode) {
this.reactiveRangeCheckMode = reactiveRangeCheckMode;
return this;
}

public Set<String> getLoaderPostProcessorSelection() {
return loaderPostProcessorSelection;
}
Expand Down Expand Up @@ -294,6 +308,7 @@ public String toString() {
", minPlausibleTargetVoltage=" + minPlausibleTargetVoltage +
", maxPlausibleTargetVoltage=" + maxPlausibleTargetVoltage +
", loaderPostProcessorSelection=" + loaderPostProcessorSelection +
", reactiveRangeCheckMode=" + reactiveRangeCheckMode +
')';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ private static double[] createReactiveKeysFromMaxReactivePowerRange(List<LfBus>
for (int i = 0; i < controllerBuses.size(); i++) {
LfBus controllerBus = controllerBuses.get(i);
for (LfGenerator generator : controllerBus.getGenerators()) {
double maxRangeQ = generator.getMaxRangeQ();
double maxRangeQ = generator.getRangeQ(LfGenerator.ReactiveRangeMode.MAX);
// if one reactive range is not plausible, we fallback to uniform keys
if (maxRangeQ < PlausibleValues.MIN_REACTIVE_RANGE / PerUnit.SB || maxRangeQ > PlausibleValues.MAX_REACTIVE_RANGE / PerUnit.SB) {
return createUniformReactiveKeys(controllerBuses);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import com.powsybl.commons.PowsyblException;
import com.powsybl.iidm.network.*;
import com.powsybl.openloadflow.OpenLoadFlowParameters;
import com.powsybl.openloadflow.network.*;
import com.powsybl.openloadflow.util.Evaluable;
import com.powsybl.openloadflow.util.PerUnit;
Expand Down Expand Up @@ -226,16 +227,16 @@ protected void add(LfGenerator generator) {
}

void addGenerator(Generator generator, boolean breakers, double plausibleActivePowerLimit, boolean reactiveLimits,
LfNetworkLoadingReport report, double minPlausibleTargetVoltage, double maxPlausibleTargetVoltage) {
add(LfGeneratorImpl.create(generator, network, breakers, plausibleActivePowerLimit, reactiveLimits, report, minPlausibleTargetVoltage, maxPlausibleTargetVoltage));
LfNetworkLoadingReport report, double minPlausibleTargetVoltage, double maxPlausibleTargetVoltage, OpenLoadFlowParameters.ReactiveRangeCheckMode reactiveRangeCheckMode) {
add(LfGeneratorImpl.create(generator, network, breakers, plausibleActivePowerLimit, reactiveLimits, report, minPlausibleTargetVoltage, maxPlausibleTargetVoltage, reactiveRangeCheckMode));
}

void addStaticVarCompensator(StaticVarCompensator staticVarCompensator, boolean voltagePerReactivePowerControl,
boolean breakers, boolean reactiveLimits, LfNetworkLoadingReport report,
double minPlausibleTargetVoltage, double maxPlausibleTargetVoltage) {
double minPlausibleTargetVoltage, double maxPlausibleTargetVoltage, OpenLoadFlowParameters.ReactiveRangeCheckMode reactiveRangeCheckMode) {
if (staticVarCompensator.getRegulationMode() != StaticVarCompensator.RegulationMode.OFF) {
LfStaticVarCompensatorImpl lfSvc = LfStaticVarCompensatorImpl.create(staticVarCompensator, network, this, voltagePerReactivePowerControl,
breakers, reactiveLimits, report, minPlausibleTargetVoltage, maxPlausibleTargetVoltage);
breakers, reactiveLimits, report, minPlausibleTargetVoltage, maxPlausibleTargetVoltage, reactiveRangeCheckMode);
add(lfSvc);
if (lfSvc.getSlope() != 0) {
hasGeneratorsWithSlope = true;
Expand All @@ -244,8 +245,8 @@ void addStaticVarCompensator(StaticVarCompensator staticVarCompensator, boolean
}

void addVscConverterStation(VscConverterStation vscCs, boolean breakers, boolean reactiveLimits, LfNetworkLoadingReport report,
double minPlausibleTargetVoltage, double maxPlausibleTargetVoltage) {
add(LfVscConverterStationImpl.create(vscCs, network, breakers, reactiveLimits, report, minPlausibleTargetVoltage, maxPlausibleTargetVoltage));
double minPlausibleTargetVoltage, double maxPlausibleTargetVoltage, OpenLoadFlowParameters.ReactiveRangeCheckMode reactiveRangeCheckMode) {
add(LfVscConverterStationImpl.create(vscCs, network, breakers, reactiveLimits, report, minPlausibleTargetVoltage, maxPlausibleTargetVoltage, reactiveRangeCheckMode));
}

void addBattery(Battery generator, double plausibleActivePowerLimit, LfNetworkLoadingReport report) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
*/
package com.powsybl.openloadflow.network.impl;

import com.powsybl.commons.PowsyblException;
import com.powsybl.iidm.network.*;
import com.powsybl.openloadflow.OpenLoadFlowParameters;
import com.powsybl.openloadflow.network.*;
import com.powsybl.openloadflow.util.PerUnit;
import org.slf4j.Logger;
Expand Down Expand Up @@ -129,31 +131,38 @@ public double getMaxQ() {
}

@Override
public double getMaxRangeQ() {
double maxRangeQ = Double.NaN;
public double getRangeQ(ReactiveRangeMode rangeMode) {
double rangeQ = Double.NaN;
ReactiveLimits reactiveLimits = getReactiveLimits().orElse(null);
if (reactiveLimits != null) {
switch (reactiveLimits.getKind()) {
case CURVE:
ReactiveCapabilityCurve reactiveCapabilityCurve = (ReactiveCapabilityCurve) reactiveLimits;
for (ReactiveCapabilityCurve.Point point : reactiveCapabilityCurve.getPoints()) {
if (Double.isNaN(maxRangeQ)) {
maxRangeQ = point.getMaxQ() - point.getMinQ();
} else {
maxRangeQ = Math.max(maxRangeQ, point.getMaxQ() - point.getMinQ());
if (rangeMode == ReactiveRangeMode.MIN || rangeMode == ReactiveRangeMode.MAX) {
for (ReactiveCapabilityCurve.Point point : reactiveCapabilityCurve.getPoints()) {
if (Double.isNaN(rangeQ)) {
rangeQ = point.getMaxQ() - point.getMinQ();
} else {
rangeQ = rangeMode == ReactiveRangeMode.MAX ? Math.max(rangeQ, point.getMaxQ() - point.getMinQ())
: Math.min(rangeQ, point.getMaxQ() - point.getMinQ());
}
}
} else if (rangeMode == ReactiveRangeMode.TARGET_P) {
rangeQ = reactiveLimits.getMaxQ(targetP) - reactiveLimits.getMinQ(targetP);
} else {
throw new PowsyblException("Unsupported reactive range mode: " + rangeMode);
}
break;

case MIN_MAX:
MinMaxReactiveLimits minMaxReactiveLimits = (MinMaxReactiveLimits) reactiveLimits;
maxRangeQ = minMaxReactiveLimits.getMaxQ() - minMaxReactiveLimits.getMinQ();
rangeQ = minMaxReactiveLimits.getMaxQ() - minMaxReactiveLimits.getMinQ();
break;

default:
throw new IllegalStateException("Unknown reactive limits kind: " + reactiveLimits.getKind());
}
return maxRangeQ / PerUnit.SB;
return rangeQ / PerUnit.SB;
} else {
return Double.MAX_VALUE;
}
Expand All @@ -176,8 +185,8 @@ public LfBus getControlledBus() {

protected void setVoltageControl(double targetV, Terminal terminal, Terminal regulatingTerminal, boolean breakers,
boolean reactiveLimits, LfNetworkLoadingReport report, double minPlausibleTargetVoltage,
double maxPlausibleTargetVoltage) {
if (!checkVoltageControlConsistency(reactiveLimits, report)) {
double maxPlausibleTargetVoltage, OpenLoadFlowParameters.ReactiveRangeCheckMode reactiveRangeCheckMode) {
if (!checkVoltageControlConsistency(reactiveLimits, report, reactiveRangeCheckMode)) {
return;
}
Bus controlledBus = breakers ? regulatingTerminal.getBusBreakerView().getBus() : regulatingTerminal.getBusView().getBus();
Expand All @@ -200,14 +209,38 @@ protected void setVoltageControl(double targetV, Terminal terminal, Terminal reg
this.generatorControlType = GeneratorControlType.VOLTAGE;
}

protected boolean checkVoltageControlConsistency(boolean reactiveLimits, LfNetworkLoadingReport report) {
protected boolean checkVoltageControlConsistency(boolean reactiveLimits, LfNetworkLoadingReport report, OpenLoadFlowParameters.ReactiveRangeCheckMode reactiveRangeCheckMode) {
boolean consistency = true;
if (reactiveLimits) {
double maxRangeQ = getMaxRangeQ();
if (maxRangeQ < PlausibleValues.MIN_REACTIVE_RANGE / PerUnit.SB) {
LOGGER.trace("Discard generator '{}' from voltage control because max reactive range ({}) is too small", getId(), maxRangeQ);
report.generatorsDiscardedFromVoltageControlBecauseMaxReactiveRangeIsTooSmall++;
consistency = false;
double rangeQ;
switch (reactiveRangeCheckMode) {
case MIN_MAX:
double minRangeQ = getRangeQ(ReactiveRangeMode.MIN);
double maxRangeQ = getRangeQ(ReactiveRangeMode.MAX);
if (maxRangeQ < PlausibleValues.MIN_REACTIVE_RANGE / PerUnit.SB || minRangeQ == 0.0) {
LOGGER.trace("Discard generator '{}' from voltage control because min or max reactive ranges (min: {} and max: {}) are too small", getId(), minRangeQ, maxRangeQ);
report.generatorsDiscardedFromVoltageControlBecauseReactiveRangeIsTooSmall++;
consistency = false;
}
break;
case MAX:
rangeQ = getRangeQ(ReactiveRangeMode.MAX);
if (rangeQ < PlausibleValues.MIN_REACTIVE_RANGE / PerUnit.SB) {
LOGGER.trace("Discard generator '{}' from voltage control because max reactive range ({}) is too small", getId(), rangeQ);
report.generatorsDiscardedFromVoltageControlBecauseReactiveRangeIsTooSmall++;
consistency = false;
}
break;
case TARGET_P:
rangeQ = getRangeQ(ReactiveRangeMode.TARGET_P);
if (rangeQ < PlausibleValues.MIN_REACTIVE_RANGE / PerUnit.SB) {
LOGGER.trace("Discard generator '{}' from voltage control because reactive range at targetP ({}) is too small", getId(), rangeQ);
report.generatorsDiscardedFromVoltageControlBecauseReactiveRangeIsTooSmall++;
consistency = false;
}
break;
default:
throw new IllegalStateException("Unknown reactive range check mode: " + reactiveRangeCheckMode);
}
}
if (Math.abs(getTargetP()) < POWER_EPSILON_SI && getMinP() > POWER_EPSILON_SI) {
Expand Down
Loading

0 comments on commit 0515857

Please sign in to comment.