Skip to content

Commit

Permalink
Add configuration of reactive slacks repartition (#41)
Browse files Browse the repository at this point in the history
Signed-off-by: parvy <[email protected]>
Co-authored-by: Anne Tilloy <[email protected]>
  • Loading branch information
p-arvy and annetill authored Nov 27, 2023
1 parent 6db56d4 commit a129815
Show file tree
Hide file tree
Showing 31 changed files with 295 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class OpenReacAmplIOFiles implements AmplParameters {
private final AlgorithmInput algorithmParams;
private final ReactiveSlackOutput reactiveSlackOutput;
private final VoltageLevelLimitsOverrideInput voltageLimitsOverride;
private final ConfiguredBusesWithReactiveSlack configuredReactiveSlackBuses;
private final NetworkModifications networkModifications;
private final boolean debug;

Expand All @@ -48,6 +49,7 @@ public OpenReacAmplIOFiles(OpenReacParameters params, Network network, boolean d
this.variableTwoWindingsTransformers = new VariableTwoWindingsTransformers(params.getVariableTwoWindingsTransformers());
this.algorithmParams = new AlgorithmInput(params.getAllAlgorithmParams());
this.voltageLimitsOverride = new VoltageLevelLimitsOverrideInput(params.getSpecificVoltageLimits(), network);
this.configuredReactiveSlackBuses = new ConfiguredBusesWithReactiveSlack(params.getConfiguredReactiveSlackBuses());

//outputs
this.reactiveSlackOutput = new ReactiveSlackOutput();
Expand All @@ -67,7 +69,7 @@ public NetworkModifications getNetworkModifications() {
@Override
public Collection<AmplInputFile> getInputParameters() {
return List.of(constantQGenerators, variableShuntCompensators, variableTwoWindingsTransformers,
algorithmParams, voltageLimitsOverride);
algorithmParams, voltageLimitsOverride, configuredReactiveSlackBuses);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ protected AbstractElementsInput(List<String> elementIds) {

@Override
public void write(BufferedWriter writer, StringToIntMapper<AmplSubset> stringToIntMapper) throws IOException {
writer.write("#amplId powsyblId\n");
writer.write("#num id\n");
for (String elementID : elementIds) {
int amplId = stringToIntMapper.getInt(getElementAmplSubset(), elementID);
String[] tokens = {Integer.toString(amplId), AmplIOUtils.addQuotes(elementID)};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* 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 com.powsybl.ampl.converter.AmplSubset;

import java.util.List;

/**
* @author Pierre Arvy <pierre.arvy at artelys.com>
*/
public class ConfiguredBusesWithReactiveSlack extends AbstractElementsInput {
public static final String PARAM_BUSES_FILE_NAME = "param_buses_with_reactive_slack.txt";

public ConfiguredBusesWithReactiveSlack(List<String> elementIds) {
super(elementIds);
}

@Override
public String getFileName() {
return PARAM_BUSES_FILE_NAME;
}

@Override
AmplSubset getElementAmplSubset() {
return AmplSubset.BUS;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* This class stores all inputs parameters specific to the OpenReac optimizer.
*
* @author Nicolas Pierre <nicolas.pierre at artelys.com>
* @author Pierre Arvy <pierre.arvy at artelys.com>
*/
public class OpenReacParameters {

Expand All @@ -33,6 +34,8 @@ public class OpenReacParameters {

private final List<String> variableTwoWindingsTransformers = new ArrayList<>();

private final List<String> configuredReactiveSlackBuses = new ArrayList<>();

// Algo parameters

private OpenReacOptimisationObjective objective = OpenReacOptimisationObjective.MIN_GENERATION;
Expand All @@ -53,6 +56,8 @@ public class OpenReacParameters {

private double maxPlausibleHighVoltageLimit = 1.5; // in pu

private ReactiveSlackBusesMode reactiveSlackBusesMode = ReactiveSlackBusesMode.NO_GENERATION;

/**
* Override some voltage level limits in the network. This will NOT modify the network object.
* <p>
Expand Down Expand Up @@ -89,6 +94,14 @@ public OpenReacParameters addVariableTwoWindingsTransformers(List<String> transf
return this;
}

/**
* A list of buses, to which reactive slacks variable will be attached by the optimizer.
*/
public OpenReacParameters addConfiguredReactiveSlackBuses(List<String> busesIds) {
this.configuredReactiveSlackBuses.addAll(busesIds);
return this;
}

/**
* The definition of the objective function for the optimization.
*/
Expand Down Expand Up @@ -190,6 +203,19 @@ public OpenReacParameters setMaxPlausibleHighVoltageLimit(double maxPlausibleHig
return this;
}

/**
* @return the mode used to select which buses will have reactive slack variables attached in the optimization.
* If mode is CONFIGURED, the buses in configuredReactiveSlackBuses are used.
*/
public ReactiveSlackBusesMode getReactiveSlackBusesMode() {
return reactiveSlackBusesMode;
}

public OpenReacParameters setReactiveSlackBusesMode(ReactiveSlackBusesMode reactiveSlackBusesMode) {
this.reactiveSlackBusesMode = Objects.requireNonNull(reactiveSlackBusesMode);
return this;
}

public List<String> getVariableShuntCompensators() {
return variableShuntCompensators;
}
Expand All @@ -206,6 +232,10 @@ public List<String> getVariableTwoWindingsTransformers() {
return variableTwoWindingsTransformers;
}

public List<String> getConfiguredReactiveSlackBuses() {
return configuredReactiveSlackBuses;
}

public List<OpenReacAlgoParam> getAllAlgorithmParams() {
ArrayList<OpenReacAlgoParam> allAlgoParams = new ArrayList<>();
allAlgoParams.add(objective.toParam());
Expand All @@ -216,6 +246,7 @@ public List<OpenReacAlgoParam> getAllAlgorithmParams() {
allAlgoParams.add(this.logLevelSolver.toParam());
allAlgoParams.add(new OpenReacAlgoParamImpl(MIN_PLAUSIBLE_LOW_VOLTAGE_LIMIT_KEY, Double.toString(minPlausibleLowVoltageLimit)));
allAlgoParams.add(new OpenReacAlgoParamImpl(MAX_PLAUSIBLE_HIGH_VOLTAGE_LIMIT_KEY, Double.toString(maxPlausibleHighVoltageLimit)));
allAlgoParams.add(reactiveSlackBusesMode.toParam());
return allAlgoParams;
}

Expand All @@ -241,6 +272,11 @@ public void checkIntegrity(Network network) throws InvalidParametersException {
throw new InvalidParametersException("Two windings transformer " + transformerId + " not found in the network.");
}
}
for (String busId : getConfiguredReactiveSlackBuses()) {
if (network.getBusView().getBus(busId) == null) {
throw new InvalidParametersException("Bus " + busId + " not found in the network.");
}
}

// Check integrity of voltage overrides
boolean integrityVoltageLimitOverrides = checkVoltageLimitOverrides(network);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* 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.algo;

/**
* @author Pierre Arvy <pierre.arvy at artelys.com>
*/
public enum ReactiveSlackBusesMode {
CONFIGURED("CONFIGURED"),
NO_GENERATION("NO_GENERATION"),
ALL("ALL");

private static final String REACTIVE_SLACK_BUSES_KEY = "buses_with_reactive_slacks";

private final String amplKey;

/**
* @param amplKey value used in param_algo.txt to define the slacks repartition.
*/
ReactiveSlackBusesMode(String amplKey) {
this.amplKey = amplKey;
}

public OpenReacAlgoParam toParam() {
return new OpenReacAlgoParamImpl(REACTIVE_SLACK_BUSES_KEY, amplKey);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.powsybl.openreac.parameters.input.OpenReacParameters;
import com.powsybl.openreac.parameters.input.VoltageLimitOverride;
import com.powsybl.openreac.parameters.input.algo.OpenReacAmplLogLevel;
import com.powsybl.openreac.parameters.input.algo.ReactiveSlackBusesMode;
import com.powsybl.openreac.parameters.input.algo.OpenReacOptimisationObjective;
import com.powsybl.openreac.parameters.input.algo.OpenReacSolverLogLevel;

Expand Down Expand Up @@ -57,6 +58,10 @@ public OpenReacParameters deserialize(JsonParser parser, DeserializationContext
parser.nextToken();
parameters.addVariableTwoWindingsTransformers(parser.readValueAs(new TypeReference<List<String>>() { }));
break;
case "configuredReactiveSlackBuses":
parser.nextToken();
parameters.addConfiguredReactiveSlackBuses(parser.readValueAs(new TypeReference<List<String>>() { }));
break;
case "objective":
parser.nextToken();
parameters.setObjective(OpenReacOptimisationObjective.valueOf(parser.getText()));
Expand All @@ -81,6 +86,10 @@ public OpenReacParameters deserialize(JsonParser parser, DeserializationContext
parser.nextToken();
parameters.setMaxPlausibleHighVoltageLimit(parser.readValueAs(Double.class));
break;
case "reactiveSlackBusesMode":
parser.nextToken();
parameters.setReactiveSlackBusesMode(ReactiveSlackBusesMode.valueOf(parser.getText()));
break;
default:
throw new IllegalStateException("Unexpected field: " + parser.getCurrentName());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.powsybl.openreac.parameters.input.OpenReacParameters;
import com.powsybl.openreac.parameters.input.algo.ReactiveSlackBusesMode;

import java.io.IOException;

Expand All @@ -34,6 +35,9 @@ public void serialize(OpenReacParameters openReacParameters, JsonGenerator jsonG
serializerProvider.defaultSerializeField("constantQGenerators", openReacParameters.getConstantQGenerators(), jsonGenerator);
serializerProvider.defaultSerializeField("variableTwoWindingsTransformers", openReacParameters.getVariableTwoWindingsTransformers(), jsonGenerator);
serializerProvider.defaultSerializeField("variableShuntCompensators", openReacParameters.getVariableShuntCompensators(), jsonGenerator);
if (openReacParameters.getReactiveSlackBusesMode() == ReactiveSlackBusesMode.CONFIGURED) {
serializerProvider.defaultSerializeField("configuredReactiveSlackBuses", openReacParameters.getConfiguredReactiveSlackBuses(), jsonGenerator);
}
serializerProvider.defaultSerializeField("objective", openReacParameters.getObjective().name(), jsonGenerator);
if (openReacParameters.getObjectiveDistance() != null) {
serializerProvider.defaultSerializeField("objectiveDistance", openReacParameters.getObjectiveDistance(), jsonGenerator);
Expand All @@ -42,6 +46,7 @@ public void serialize(OpenReacParameters openReacParameters, JsonGenerator jsonG
serializerProvider.defaultSerializeField("logLevelSolver", openReacParameters.getLogLevelSolver(), jsonGenerator);
serializerProvider.defaultSerializeField("minPlausibleLowVoltageLimit", openReacParameters.getMinPlausibleLowVoltageLimit(), jsonGenerator);
serializerProvider.defaultSerializeField("maxPlausibleHighVoltageLimit", openReacParameters.getMaxPlausibleHighVoltageLimit(), jsonGenerator);
serializerProvider.defaultSerializeField("reactiveSlackBusesMode", openReacParameters.getReactiveSlackBusesMode().name(), jsonGenerator);
jsonGenerator.writeEndObject();
}
}
10 changes: 7 additions & 3 deletions open-reac/src/main/resources/openreac/reactiveopf.dat
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,17 @@ param: BRANCH: branch_3wt branch_subor branch_subex branch_R branch_X branch_Gor
param: BOUND_OVERRIDES: substation_new_Vmin, substation_new_Vmax, substation_new_checkId := include ampl_network_substations_override.txt;

# param_shunts.txt
#"variant" "num" "bus" "id"
#"num" "id"
param: PARAM_SHUNT: param_shunt_id := include param_shunts.txt;

# param_generators_reactive.txt
#"variant" "num" "bus" "id"
#"num" "id"
param: PARAM_UNIT_FIXQ: param_unit_fixq_id := include param_generators_reactive.txt;

# param_transformers.txt
#"variant" "num" "bus1" "bus2" "id"
#"num" "id"
param: PARAM_TRANSFORMERS_RATIO_VARIABLE: param_transformers_ratio_variable_id := include param_transformers.txt;

# param_buses_with_reactive_slack.txt
#"num" "id"
param: PARAM_BUSES_WITH_REACTIVE_SLACK: param_buses_with_reactive_slack_id := include param_buses_with_reactive_slack.txt;
27 changes: 16 additions & 11 deletions open-reac/src/main/resources/openreac/reactiveopf.mod
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,16 @@ param param_transformers_ratio_variable_id{PARAM_TRANSFORMERS_RATIO_VARIABLE} sy
check {(t,qq,m,n) in BRANCH: qq in PARAM_TRANSFORMERS_RATIO_VARIABLE}: branch_id[t,qq,m,n] == param_transformers_ratio_variable_id[qq];


###############################################################################
# Buses with reactive slacks
###############################################################################
# param_buses_with_reactive_slack.txt
# If buses_with_reactive_slacks == "CONFIGURED" then only buses listed in this file will have reactive slacks attached in ACOPF
#"num" "id"
set PARAM_BUSES_WITH_REACTIVE_SLACK dimen 1 default {};
param param_buses_with_reactive_slack_id{PARAM_BUSES_WITH_REACTIVE_SLACK} symbolic;
check {(t,n) in BUS: n in PARAM_BUSES_WITH_REACTIVE_SLACK}: bus_id[t,n] == param_buses_with_reactive_slack_id[n];


###############################################################################
# Additional sets for equipments which are really working
Expand Down Expand Up @@ -939,17 +949,12 @@ subject to ctr_balance_P{PROBLEM_ACOPF,k in BUSCC}:
# Reactive Balance
#

# Reactive balance slack variables only if there is a load or a shunt connected
# If there is a unit, or SVC, or VSC, they already have reactive power generation, so no need to add slack variables
set BUSCC_SLACK := {n in BUSCC:
(
card{(g,n) in UNITON: (g,n) not in UNIT_FIXQ}==0
and card{(svc,n) in SVCON}==0
and card{(vscconv,n) in VSCCONVON}==0
)
} ;
var slack1_balance_Q{BUSCC_SLACK} >=0, <= 500; # 500 Mvar is already HUGE
var slack2_balance_Q{BUSCC_SLACK} >=0, <= 500;
# Reactive balance slack variables at configured nodes
set BUSCC_SLACK := if buses_with_reactive_slacks == "ALL" then BUSCC
else if buses_with_reactive_slacks == "NO_GENERATION" then {n in BUSCC: (card{(g,n) in UNITON: (g,n) not in UNIT_FIXQ}==0 and card{(svc,n) in SVCON}==0 and card{(vscconv,n) in VSCCONVON}==0)}
else BUSCC inter PARAM_BUSES_WITH_REACTIVE_SLACK; # if = "CONFIGURED", buses given as parameter but in connex component
var slack1_balance_Q{BUSCC_SLACK} >=0;
var slack2_balance_Q{BUSCC_SLACK} >=0;
#subject to ctr_compl_slack_Q{PROBLEM_ACOPF,k in BUSCC_SLACK}: slack1_balance_Q[k] >= 0 complements slack2_balance_Q[k] >= 0;

subject to ctr_balance_Q{PROBLEM_ACOPF,k in BUSCC}:
Expand Down
Loading

0 comments on commit a129815

Please sign in to comment.