Skip to content

Commit

Permalink
fix bug
Browse files Browse the repository at this point in the history
Signed-off-by: belthlemar <[email protected]>
  • Loading branch information
MartinBelthle committed Jun 26, 2024
1 parent 1e320e8 commit d378fa5
Show file tree
Hide file tree
Showing 10 changed files with 641 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,8 @@ private List<Double> getMinAndMaxAbsoluteAndRelativeSetpoints(RangeAction<?> ran
minRelativeTap = Math.max(minRelativeTap, range.getMinTap());
maxRelativeTap = Math.min(maxRelativeTap, range.getMaxTap());
break;
default:
throw new OpenRaoException(String.format("Unsupported range type %s", rangeType));
}
}
// The taps are not necessarily in order of increasing angle.
Expand Down Expand Up @@ -398,6 +400,8 @@ private List<Double> getMinAndMaxAbsoluteAndRelativeSetpoints(RangeAction<?> ran
minRelativeSetpoint = Math.max(minRelativeSetpoint, range.getMin());
maxRelativeSetpoint = Math.min(maxRelativeSetpoint, range.getMax());
break;
default:
throw new OpenRaoException(String.format("Unsupported range type %s", rangeType));
}
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

import com.powsybl.openrao.data.cracapi.State;
import com.powsybl.openrao.data.cracapi.rangeaction.PstRangeAction;
import com.powsybl.openrao.data.cracapi.rangeaction.RangeAction;
import com.powsybl.openrao.searchtreerao.commons.RaoUtil;
import com.powsybl.openrao.searchtreerao.commons.optimizationperimeters.OptimizationPerimeter;
import com.powsybl.openrao.searchtreerao.linearoptimisation.algorithms.linearproblem.OpenRaoMPConstraint;
import com.powsybl.openrao.searchtreerao.linearoptimisation.algorithms.linearproblem.OpenRaoMPVariable;
import com.powsybl.openrao.searchtreerao.linearoptimisation.algorithms.linearproblem.LinearProblem;
Expand All @@ -17,6 +20,7 @@
import com.powsybl.openrao.searchtreerao.result.api.RangeActionSetpointResult;
import com.powsybl.openrao.searchtreerao.result.api.SensitivityResult;
import com.powsybl.iidm.network.Network;
import org.apache.commons.lang3.tuple.Pair;

import java.util.Map;
import java.util.Set;
Expand All @@ -27,16 +31,16 @@
public class DiscretePstTapFiller implements ProblemFiller {

private final Network network;
private final State optimizedState;
private final OptimizationPerimeter optimizationPerimeter;
private final Map<State, Set<PstRangeAction>> rangeActions;
private final RangeActionSetpointResult prePerimeterRangeActionSetpoints;

public DiscretePstTapFiller(Network network,
State optimizedState,
OptimizationPerimeter optimizationPerimeter,
Map<State, Set<PstRangeAction>> rangeActions,
RangeActionSetpointResult prePerimeterRangeActionSetpoints) {
this.network = network;
this.optimizedState = optimizedState;
this.optimizationPerimeter = optimizationPerimeter;
this.rangeActions = rangeActions;
this.prePerimeterRangeActionSetpoints = prePerimeterRangeActionSetpoints;
}
Expand Down Expand Up @@ -65,12 +69,12 @@ public void updateBetweenMipIteration(LinearProblem linearProblem, RangeActionAc
private void buildPstTapVariablesAndConstraints(LinearProblem linearProblem, PstRangeAction pstRangeAction, State state) {

// compute a few values on PST taps and angle
double prePerimeterAngle = prePerimeterRangeActionSetpoints.getSetpoint(pstRangeAction);
double currentAngle = pstRangeAction.getCurrentSetpoint(network);
int currentTap = pstRangeAction.getCurrentTapPosition(network);

int minAdmissibleTap = Math.min(pstRangeAction.convertAngleToTap(pstRangeAction.getMinAdmissibleSetpoint(prePerimeterAngle)), pstRangeAction.convertAngleToTap(pstRangeAction.getMaxAdmissibleSetpoint(prePerimeterAngle)));
int maxAdmissibleTap = Math.max(pstRangeAction.convertAngleToTap(pstRangeAction.getMinAdmissibleSetpoint(prePerimeterAngle)), pstRangeAction.convertAngleToTap(pstRangeAction.getMaxAdmissibleSetpoint(prePerimeterAngle)));
Pair<Integer, Integer> admissibleTaps = getMinAndMaxAdmissibleTaps(pstRangeAction, state);
int minAdmissibleTap = admissibleTaps.getLeft();
int maxAdmissibleTap = admissibleTaps.getRight();

int maxDownwardTapVariation = Math.max(0, currentTap - minAdmissibleTap);
int maxUpwardTapVariation = Math.max(0, maxAdmissibleTap - currentTap);
Expand Down Expand Up @@ -126,18 +130,16 @@ private void buildPstTapVariablesAndConstraints(LinearProblem linearProblem, Pst
private void refineTapToAngleConversionCoefficientAndUpdateBounds(LinearProblem linearProblem, PstRangeAction pstRangeAction, RangeActionActivationResult rangeActionActivationResult, State state) {

// compute a few values on PST taps and angle
double newAngle = rangeActionActivationResult.getOptimizedSetpoint(pstRangeAction, optimizedState);
int newTapPosition = rangeActionActivationResult.getOptimizedTap(pstRangeAction, optimizedState);
double newAngle = rangeActionActivationResult.getOptimizedSetpoint(pstRangeAction, state);
int newTapPosition = rangeActionActivationResult.getOptimizedTap(pstRangeAction, state);

double prePerimeterAngle = prePerimeterRangeActionSetpoints.getSetpoint(pstRangeAction);
int minAdmissibleTap = Math.min(pstRangeAction.convertAngleToTap(pstRangeAction.getMinAdmissibleSetpoint(prePerimeterAngle)), pstRangeAction.convertAngleToTap(pstRangeAction.getMaxAdmissibleSetpoint(prePerimeterAngle)));
int maxAdmissibleTap = Math.max(pstRangeAction.convertAngleToTap(pstRangeAction.getMinAdmissibleSetpoint(prePerimeterAngle)), pstRangeAction.convertAngleToTap(pstRangeAction.getMaxAdmissibleSetpoint(prePerimeterAngle)));
Pair<Integer, Integer> admissibleTaps = getMinAndMaxAdmissibleTaps(pstRangeAction, state);
int minAdmissibleTap = admissibleTaps.getLeft();
int maxAdmissibleTap = admissibleTaps.getRight();

int maxDownwardTapVariation = Math.max(0, newTapPosition - minAdmissibleTap);
int maxUpwardTapVariation = Math.max(0, maxAdmissibleTap - newTapPosition);

Map<Integer, Double> tapToAngleConversionMap = pstRangeAction.getTapToAngleConversionMap();

// get variables and constraints
OpenRaoMPConstraint tapToAngleConversionConstraint = linearProblem.getTapToAngleConversionConstraint(pstRangeAction, state);
OpenRaoMPVariable pstTapUpwardVariationVariable = linearProblem.getPstTapVariationVariable(pstRangeAction, state, LinearProblem.VariationDirectionExtension.UPWARD);
Expand All @@ -153,6 +155,7 @@ private void refineTapToAngleConversionCoefficientAndUpdateBounds(LinearProblem

// update coefficients of the constraint with newly calculated ones, except if the tap is already at the limit of the PST range
// when updating the MIP, the factors are calibrated on a change of one tap
Map<Integer, Double> tapToAngleConversionMap = pstRangeAction.getTapToAngleConversionMap();
if (tapToAngleConversionMap.containsKey(newTapPosition + 1)) {
double angleToTapUpwardConversionFactor = tapToAngleConversionMap.get(newTapPosition + 1) - tapToAngleConversionMap.get(newTapPosition);
tapToAngleConversionConstraint.setCoefficient(pstTapUpwardVariationVariable, -angleToTapUpwardConversionFactor);
Expand All @@ -167,4 +170,19 @@ private void refineTapToAngleConversionCoefficientAndUpdateBounds(LinearProblem
downAuthorizationConstraint.setCoefficient(pstTapDownwardVariationBinary, -maxDownwardTapVariation);
upAuthorizationConstraint.setCoefficient(pstTapUpwardVariationBinary, -maxUpwardTapVariation);
}

private Pair<Integer, Integer> getMinAndMaxAdmissibleTaps(PstRangeAction pstRangeAction, State state) {
double prePerimeterAngle = prePerimeterRangeActionSetpoints.getSetpoint(pstRangeAction);
int minAdmissibleTap = Math.min(pstRangeAction.convertAngleToTap(pstRangeAction.getMinAdmissibleSetpoint(prePerimeterAngle)), pstRangeAction.convertAngleToTap(pstRangeAction.getMaxAdmissibleSetpoint(prePerimeterAngle)));
int maxAdmissibleTap = Math.max(pstRangeAction.convertAngleToTap(pstRangeAction.getMinAdmissibleSetpoint(prePerimeterAngle)), pstRangeAction.convertAngleToTap(pstRangeAction.getMaxAdmissibleSetpoint(prePerimeterAngle)));

Pair<RangeAction<?>, State> lastAvailableRangeAction = RaoUtil.getLastAvailableRangeActionOnSameNetworkElement(optimizationPerimeter, pstRangeAction, state);
if (lastAvailableRangeAction != null) {
Map<Integer, Double> tapToAngleConversionMap = pstRangeAction.getTapToAngleConversionMap();
minAdmissibleTap = tapToAngleConversionMap.keySet().stream().mapToInt(k -> k).min().orElseThrow();
maxAdmissibleTap = tapToAngleConversionMap.keySet().stream().mapToInt(k -> k).max().orElseThrow();

}
return Pair.of(minAdmissibleTap, maxAdmissibleTap);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ private ProblemFiller buildUnoptimizedCnecFiller() {
private ProblemFiller buildIntegerPstTapFiller(Map<State, Set<PstRangeAction>> pstRangeActions) {
return new DiscretePstTapFiller(
inputs.getNetwork(),
inputs.getOptimizationPerimeter().getMainOptimizationState(),
inputs.getOptimizationPerimeter(),
pstRangeActions,
inputs.getPrePerimeterSetpoints()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ void testFillAndUpdateMethods() {
pstRangeActions.put(state, Set.of(pstRa1, pstRa2));
DiscretePstTapFiller discretePstTapFiller = new DiscretePstTapFiller(
network,
state,
optimizationPerimeter,
pstRangeActions,
initialRangeActionSetpointResult);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ void testFillAndUpdateMethods() {
pstRangeActions.put(state, Set.of(pstRangeAction));
DiscretePstTapFiller discretePstTapFiller = new DiscretePstTapFiller(
network,
state,
optimizationPerimeter,
pstRangeActions,
initialRangeActionSetpointResult);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright (c) 2024, 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/.

Feature: US 19.11: Handle maximum number of elementary actions per TSO

@fast @rao @second-preventive
Scenario: US.19.11.9: Reference case with optimal solution (no global optimization).
Given network file is "epic19/small-network-2P.uct"
Given crac file is "epic19/SL_ep19us11case9.json"
Given configuration file is "epic19/RaoParameters_19_11_9.json"
When I launch search_tree_rao
Then 1 remedial actions are used in preventive
And the tap of PstRangeAction "pst_be" should be -10 in preventive
And the tap of PstRangeAction "pst_be" should be -16 after "co1_fr2_fr3_1" at "curative"
And the tap of PstRangeAction "pst_fr" should be 13 after "co1_fr2_fr3_1" at "curative"
And the worst margin is -218.5 A

@fast @rao @second-preventive
Scenario: US.19.11.9.bis: Same case with global optimization: should have the same results
Given network file is "epic19/small-network-2P.uct"
Given crac file is "epic19/SL_ep19us11case9.json"
Given configuration file is "epic19/RaoParameters_19_11_9_bis.json"
When I launch search_tree_rao
Then 1 remedial actions are used in preventive
And the tap of PstRangeAction "pst_be" should be -16 after "co1_fr2_fr3_1" at "curative"
And the tap of PstRangeAction "pst_fr" should be 13 after "co1_fr2_fr3_1" at "curative"
And the worst margin is -218.5 A

56 changes: 56 additions & 0 deletions tests/src/test/resources/files/cases/epic19/small-network-2P.uct
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
##C 2007.05.01
##N
##ZBE
BBE1AA1 BE1 0 2 400.00 2500.00 0.00000 -1500.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
BBE2AA1 BE2 0 2 400.00 1000.00 0.00000 -3000.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
BBE3AA1 BE3 0 2 400.00 1500.00 0.00000 -2500.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
BBE4AA1 BE4 0 2 400.00 2000.00 0.00000 -2500.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
##ZDE
DDE1AA1 DE1 0 2 400.00 3500.00 0.00000 -2500.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
DDE2AA1 DE2 0 2 400.00 3000.00 0.00000 -2000.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
DDE3AA1 DE3 0 2 400.00 2000.00 0.00000 -1500.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
DDE4AA1 DE3 0 2 400.00 1000.00 0.00000 -1500.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
##ZFR
FFR1AA1 FR1 0 2 400.00 1000.00 0.00000 -2000.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
FFR2AA1 FR2 0 2 400.00 3500.00 0.00000 -2000.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
FFR3AA1 FR3 0 2 400.00 1500.00 0.00000 -3000.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
FFR4AA1 FR4 0 2 400.00 2000.00 0.00000 -1000.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
FFR5AA1 FR5 0 2 400.00 1500.00 0.00000 -1500.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
##ZNL
NNL1AA1 NL1 0 2 400.00 1000.00 0.00000 -1500.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
NNL2AA1 NL2 0 2 400.00 1000.00 0.00000 -500.00 0.00000 9000.00 -9000.0 9000.00 -9000.0
NNL3AA1 NL3 0 2 400.00 2500.00 0.00000 -2000.0 0.00000 9000.00 -9000.0 9000.00 -9000.0
##L
BBE1AA1 BBE2AA1 1 0 0.0000 10.000 0.000000 2000
BBE1AA1 BBE3AA1 1 0 0.0000 10.000 0.000000 2000
BBE1AA1 BBE3AA1 2 0 0.0000 10.000 0.000000 2000
BBE1AA1 BBE4AA1 1 0 0.0000 0.0050 0.000000 2000
BBE3AA1 BBE4AA1 1 0 0.0000 10.000 0.000000 2000
FFR1AA1 FFR2AA1 1 0 0.0000 10.000 0.000000 2000
FFR1AA1 FFR3AA1 1 0 0.0000 10.000 0.000000 2000
FFR1AA1 FFR4AA1 1 0 0.0000 10.000 0.000000 2000
FFR1AA1 FFR5AA1 1 8 0.0000 10.000 0.000000 2000
FFR2AA1 FFR3AA1 1 0 0.0000 10.000 0.000000 2000
FFR2AA1 FFR3AA1 2 0 0.0000 10.000 0.000000 2000
FFR3AA1 FFR5AA1 1 0 0.0000 10.000 0.000000 2000
DDE1AA1 DDE2AA1 1 0 0.0000 10.000 0.000000 2000
DDE1AA1 DDE4AA1 1 0 0.0000 10.000 0.000000 2000
DDE2AA1 DDE3AA1 1 0 0.0000 10.000 0.000000 2000
DDE3AA1 DDE4AA1 1 7 0.0000 0.0050 0.000000 2000
NNL1AA1 NNL2AA1 1 0 0.0000 10.000 0.000000 2000
NNL1AA1 NNL3AA1 1 0 0.0000 10.000 0.000000 2000
NNL2AA1 NNL3AA1 1 0 0.0000 10.000 0.000000 2000
FFR4AA1 DDE1AA1 1 0 0.0000 10.000 0.000000 2000
FFR4AA1 DDE4AA1 1 0 0.0000 10.000 0.000000 2000
FFR2AA1 DDE3AA1 1 0 0.0000 10.000 0.000000 2000
DDE2AA1 NNL3AA1 1 0 0.0000 10.000 0.000000 2000
NNL2AA1 BBE3AA1 1 0 0.0000 10.000 0.000000 2000
BBE2AA1 FFR3AA1 1 0 0.0000 10.000 0.000000 2000
BBE1AA1 FFR5AA1 1 0 0.0000 10.000 0.000000 2000
BBE4AA1 FFR5AA1 1 0 0.0000 10.000 0.000000 2000
##T
BBE2AA1 BBE3AA1 1 0 400.0 400.0 1000. 0.0000 10.000 0.000000 0.0 2000 PST
FFR2AA1 FFR4AA1 1 0 400.0 400.0 1000. 0.0000 10.000 0.000000 0.0 2000 PST
##R
BBE2AA1 BBE3AA1 1 -0.68 90.00 16 0 SYMM
FFR2AA1 FFR4AA1 1 -0.68 90.00 16 15 SYMM
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
{
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_MARGIN_IN_AMPERE",
"forbid-cost-increase" : false,
"curative-min-obj-improvement" : 0.0,
"preventive-stop-criterion" : "MIN_OBJECTIVE",
"curative-stop-criterion" : "MIN_OBJECTIVE"
},
"range-actions-optimization" : {
"max-mip-iterations" : 5,
"pst-penalty-cost" : 0.01,
"pst-sensitivity-threshold" : 1.0E-6,
"pst-model" : "APPROXIMATED_INTEGERS",
"hvdc-penalty-cost" : 0.001,
"hvdc-sensitivity-threshold" : 1.0E-6,
"injection-ra-penalty-cost" : 0.001,
"injection-ra-sensitivity-threshold" : 1.0E-6,
"linear-optimization-solver" : {
"solver" : "CBC",
"relative-mip-gap" : 1.0E-4,
"solver-specific-parameters" : null
}
},
"topological-actions-optimization" : {
"max-preventive-search-tree-depth" : 5,
"max-auto-search-tree-depth" : 2,
"max-curative-search-tree-depth" : 5,
"predefined-combinations" : [ ],
"relative-minimum-impact-threshold" : 0.0,
"absolute-minimum-impact-threshold" : 0.0,
"skip-actions-far-from-most-limiting-element" : false,
"max-number-of-boundaries-for-skipping-actions" : 2
},
"multi-threading" : {
"contingency-scenarios-in-parallel" : 1,
"preventive-leaves-in-parallel" : 1,
"curative-leaves-in-parallel" : 1
},
"second-preventive-rao" : {
"execution-condition" : "COST_INCREASE",
"re-optimize-curative-range-actions" : false,
"hint-from-first-preventive-rao" : false
},
"not-optimized-cnecs" : {
"do-not-optimize-curative-cnecs-for-tsos-without-cras" : false
},
"load-flow-and-sensitivity-computation" : {
"load-flow-provider" : "OpenLoadFlow",
"sensitivity-provider" : "OpenLoadFlow",
"sensitivity-failure-overcost" : 100000.0,
"sensitivity-parameters" : {
"version" : "1.0",
"load-flow-parameters" : {
"version" : "1.9",
"voltageInitMode" : "UNIFORM_VALUES",
"transformerVoltageControlOn" : false,
"phaseShifterRegulationOn" : false,
"useReactiveLimits" : true,
"twtSplitShuntAdmittance" : true,
"shuntCompensatorVoltageControlOn" : false,
"readSlackBus" : false,
"writeSlackBus" : true,
"dc" : false,
"distributedSlack" : true,
"balanceType" : "PROPORTIONAL_TO_GENERATION_P",
"dcUseTransformerRatio" : false,
"countriesToBalance" : [ "PL", "NL", "IT", "ES", "BA", "MK", "AT", "ME", "FR", "UA", "AL", "TR", "SK", "CH", "GR", "PT", "BE", "CZ", "HR", "SI", "RO", "RS", "DE", "BG", "HU" ],
"connectedComponentMode" : "MAIN",
"hvdcAcEmulation" : true,
"dcPowerFactor" : 1.0,
"extensions" : {
"open-load-flow-parameters" : {
"slackBusSelectionMode" : "MOST_MESHED",
"slackBusesIds" : [ ],
"slackDistributionFailureBehavior" : "LEAVE_ON_SLACK_BUS",
"voltageRemoteControl" : true,
"lowImpedanceBranchMode" : "REPLACE_BY_ZERO_IMPEDANCE_LINE",
"loadPowerFactorConstant" : false,
"plausibleActivePowerLimit" : 10000.0,
"slackBusPMaxMismatch" : 1.0,
"voltagePerReactivePowerControl" : false,
"maxNewtonRaphsonIterations" : 30,
"newtonRaphsonConvEpsPerEq" : 1.0E-4,
"voltageInitModeOverride" : "NONE",
"transformerVoltageControlMode" : "WITH_GENERATOR_VOLTAGE_CONTROL",
"shuntVoltageControlMode" : "WITH_GENERATOR_VOLTAGE_CONTROL",
"minPlausibleTargetVoltage" : 0.8,
"maxPlausibleTargetVoltage" : 1.2,
"minRealisticVoltage" : 0.5,
"maxRealisticVoltage" : 1.5,
"lowImpedanceThreshold" : 1.0E-8,
"reactiveRangeCheckMode" : "MAX",
"networkCacheEnabled" : false,
"svcVoltageMonitoring" : true,
"stateVectorScalingMode" : "NONE",
"maxSlackBusCount" : 1,
"debugDir" : null,
"incrementalTransformerRatioTapControlOuterLoopMaxTapShift" : 3,
"secondaryVoltageControl" : false,
"reactiveLimitsMaxPqPvSwitch" : 3
}
}
}
}
}
}
Loading

0 comments on commit d378fa5

Please sign in to comment.