Skip to content

Commit

Permalink
AUTO instant: ignore overloaded CNECs if they can be secured by their…
Browse files Browse the repository at this point in the history
… PST (#754)

* Not optimized CNEC-PST at AUTO instant

* refactor

* correction and unit tests

* refacto

* checkstyle

* sensi only available in MW

* fix after merge

* update psbl

* update psbl

* rollback update psbl
  • Loading branch information
pet-mit authored Apr 21, 2023
1 parent 88be4a8 commit 9876627
Show file tree
Hide file tree
Showing 11 changed files with 243 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import com.farao_community.farao.commons.FaraoException;
import com.farao_community.farao.commons.RandomizedString;
import com.farao_community.farao.commons.Unit;
import com.farao_community.farao.data.crac_api.Crac;
import com.farao_community.farao.data.crac_api.Identifiable;
import com.farao_community.farao.data.crac_api.State;
Expand All @@ -25,6 +26,7 @@
import com.farao_community.farao.search_tree_rao.commons.ToolProvider;
import com.farao_community.farao.search_tree_rao.commons.objective_function_evaluator.ObjectiveFunction;
import com.farao_community.farao.search_tree_rao.commons.objective_function_evaluator.ObjectiveFunctionResultImpl;
import com.farao_community.farao.search_tree_rao.commons.parameters.UnoptimizedCnecParameters;
import com.farao_community.farao.search_tree_rao.result.api.*;
import com.farao_community.farao.search_tree_rao.result.impl.AutomatonPerimeterResultImpl;
import com.farao_community.farao.search_tree_rao.result.impl.PrePerimeterSensitivityResultImpl;
Expand Down Expand Up @@ -57,22 +59,26 @@ public final class AutomatonSimulator {

private final Crac crac;
private final RaoParameters raoParameters;
private final Unit flowUnit;
private final ToolProvider toolProvider;
private final FlowResult initialFlowResult;
private final RangeActionSetpointResult prePerimeterRangeActionSetpointResult;
private final PrePerimeterResult prePerimeterSensitivityOutput;
private final Set<String> operatorsNotSharingCras;
private final int numberLoggedElementsDuringRao;
private final Map<FlowCnec, RangeAction<?>> flowCnecRangeActionMap;

public AutomatonSimulator(Crac crac, RaoParameters raoParameters, ToolProvider toolProvider, FlowResult initialFlowResult, RangeActionSetpointResult prePerimeterRangeActionSetpointResult, PrePerimeterResult prePerimeterSensitivityOutput, Set<String> operatorsNotSharingCras, int numberLoggedElementsDuringRao) {
this.crac = crac;
this.raoParameters = raoParameters;
this.flowUnit = raoParameters.getObjectiveFunctionParameters().getType().getUnit();
this.toolProvider = toolProvider;
this.initialFlowResult = initialFlowResult;
this.prePerimeterRangeActionSetpointResult = prePerimeterRangeActionSetpointResult;
this.prePerimeterSensitivityOutput = prePerimeterSensitivityOutput;
this.operatorsNotSharingCras = operatorsNotSharingCras;
this.numberLoggedElementsDuringRao = numberLoggedElementsDuringRao;
this.flowCnecRangeActionMap = UnoptimizedCnecParameters.getDoNotOptimizeCnecsSecuredByTheirPst(raoParameters.getNotOptimizedCnecsParameters(), crac);
}

/**
Expand Down Expand Up @@ -556,7 +562,7 @@ RangeAutomatonSimulationResult shiftRangeActionsUntilFlowCnecsSecure(List<RangeA
Set<Pair<FlowCnec, Side>> flowCnecsToBeExcluded = new HashSet<>();
PrePerimeterResult automatonRangeActionOptimizationSensitivityAnalysisOutput = prePerimeterSensitivityOutput;
Map<RangeAction<?>, Double> activatedRangeActionsWithSetpoint = new HashMap<>();
List<Pair<FlowCnec, Side>> flowCnecsWithNegativeMargin = getCnecsWithNegativeMarginWithoutExcludedCnecs(flowCnecs, flowCnecsToBeExcluded, automatonRangeActionOptimizationSensitivityAnalysisOutput);
List<Pair<FlowCnec, Side>> flowCnecsWithNegativeMargin = getCnecsWithNegativeMarginWithoutExcludedCnecs(flowCnecs, flowCnecsToBeExcluded, automatonRangeActionOptimizationSensitivityAnalysisOutput, activatedRangeActionsWithSetpoint);

if (alignedRangeActions.stream().allMatch(HvdcRangeAction.class::isInstance) && !flowCnecsWithNegativeMargin.isEmpty()) {
// Disable HvdcAngleDroopActivePowerControl for HVDC lines, fetch their set-point, re-run sensitivity analysis and fetch new negative margins
Expand All @@ -567,7 +573,7 @@ RangeAutomatonSimulationResult shiftRangeActionsUntilFlowCnecsSecure(List<RangeA
if (automatonRangeActionOptimizationSensitivityAnalysisOutput.getSensitivityStatus(automatonState) == ComputationStatus.FAILURE) {
return new RangeAutomatonSimulationResult(automatonRangeActionOptimizationSensitivityAnalysisOutput, Collections.emptySet(), Collections.emptyMap());
}
flowCnecsWithNegativeMargin = getCnecsWithNegativeMarginWithoutExcludedCnecs(flowCnecs, flowCnecsToBeExcluded, automatonRangeActionOptimizationSensitivityAnalysisOutput);
flowCnecsWithNegativeMargin = getCnecsWithNegativeMarginWithoutExcludedCnecs(flowCnecs, flowCnecsToBeExcluded, automatonRangeActionOptimizationSensitivityAnalysisOutput, activatedRangeActionsWithSetpoint);
}

// -- Define setpoint bounds
Expand All @@ -591,9 +597,9 @@ RangeAutomatonSimulationResult shiftRangeActionsUntilFlowCnecsSecure(List<RangeA
// Aligned range actions have the same set-point :
double currentSetpoint = alignedRangeActions.get(0).getCurrentSetpoint(network);
double optimalSetpoint = currentSetpoint;
double conversionToMegawatt = RaoUtil.getFlowUnitMultiplier(toBeShiftedCnec, side, raoParameters.getObjectiveFunctionParameters().getType().getUnit(), MEGAWATT);
double cnecFlow = conversionToMegawatt * automatonRangeActionOptimizationSensitivityAnalysisOutput.getFlow(toBeShiftedCnec, side, raoParameters.getObjectiveFunctionParameters().getType().getUnit());
double cnecMargin = conversionToMegawatt * automatonRangeActionOptimizationSensitivityAnalysisOutput.getMargin(toBeShiftedCnec, side, raoParameters.getObjectiveFunctionParameters().getType().getUnit());
double conversionToMegawatt = RaoUtil.getFlowUnitMultiplier(toBeShiftedCnec, side, flowUnit, MEGAWATT);
double cnecFlow = conversionToMegawatt * automatonRangeActionOptimizationSensitivityAnalysisOutput.getFlow(toBeShiftedCnec, side, flowUnit);
double cnecMargin = conversionToMegawatt * automatonRangeActionOptimizationSensitivityAnalysisOutput.getMargin(toBeShiftedCnec, side, flowUnit);
double sensitivityValue = 0;
// Under-estimate range action sensitivity if convergence to margin = 0 is slow (ie if multiple passes
// through this loop have been needed to secure the same CNEC)
Expand All @@ -603,7 +609,7 @@ RangeAutomatonSimulationResult shiftRangeActionsUntilFlowCnecsSecure(List<RangeA
// if sensitivity value is zero, CNEC cannot be secured. move on to the next CNEC with a negative margin
if (Math.abs(sensitivityValue) < DOUBLE_NON_NULL) {
flowCnecsToBeExcluded.add(Pair.of(toBeShiftedCnec, side));
flowCnecsWithNegativeMargin = getCnecsWithNegativeMarginWithoutExcludedCnecs(flowCnecs, flowCnecsToBeExcluded, automatonRangeActionOptimizationSensitivityAnalysisOutput);
flowCnecsWithNegativeMargin = getCnecsWithNegativeMarginWithoutExcludedCnecs(flowCnecs, flowCnecsToBeExcluded, automatonRangeActionOptimizationSensitivityAnalysisOutput, activatedRangeActionsWithSetpoint);
continue;
}

Expand Down Expand Up @@ -638,7 +644,7 @@ RangeAutomatonSimulationResult shiftRangeActionsUntilFlowCnecsSecure(List<RangeA
return new RangeAutomatonSimulationResult(automatonRangeActionOptimizationSensitivityAnalysisOutput, activatedRangeActionsWithSetpoint.keySet(), activatedRangeActionsWithSetpoint);
}
RaoLogger.logMostLimitingElementsResults(TECHNICAL_LOGS, automatonRangeActionOptimizationSensitivityAnalysisOutput, Set.of(automatonState), raoParameters.getObjectiveFunctionParameters().getType(), numberLoggedElementsDuringRao);
flowCnecsWithNegativeMargin = getCnecsWithNegativeMarginWithoutExcludedCnecs(flowCnecs, flowCnecsToBeExcluded, automatonRangeActionOptimizationSensitivityAnalysisOutput);
flowCnecsWithNegativeMargin = getCnecsWithNegativeMarginWithoutExcludedCnecs(flowCnecs, flowCnecsToBeExcluded, automatonRangeActionOptimizationSensitivityAnalysisOutput, activatedRangeActionsWithSetpoint);
iteration++;
previouslyShiftedCnec = toBeShiftedCnec;
}
Expand Down Expand Up @@ -672,11 +678,13 @@ private static int safeDiffSignum(double newValue, double oldValue) {
*/
List<Pair<FlowCnec, Side>> getCnecsWithNegativeMarginWithoutExcludedCnecs(Set<FlowCnec> flowCnecs,
Set<Pair<FlowCnec, Side>> cnecsToBeExcluded,
PrePerimeterResult prePerimeterSensitivityOutput) {
PrePerimeterResult prePerimeterSensitivityOutput,
Map<RangeAction<?>, Double> activatedRangeActionsWithSetpoint) {
Map<Pair<FlowCnec, Side>, Double> cnecsAndMargins = new HashMap<>();
flowCnecs.forEach(flowCnec -> flowCnec.getMonitoredSides().forEach(side -> {
double margin = prePerimeterSensitivityOutput.getMargin(flowCnec, side, raoParameters.getObjectiveFunctionParameters().getType().getUnit());
if (!cnecsToBeExcluded.contains(Pair.of(flowCnec, side)) && margin < 0) {
double margin = prePerimeterSensitivityOutput.getMargin(flowCnec, side, flowUnit);
boolean cnecShouldBeOptimized = RaoUtil.cnecShouldBeOptimized(flowCnecRangeActionMap, prePerimeterSensitivityOutput, flowCnec, side, activatedRangeActionsWithSetpoint, prePerimeterRangeActionSetpointResult, prePerimeterSensitivityOutput, flowUnit);
if (cnecShouldBeOptimized && !cnecsToBeExcluded.contains(Pair.of(flowCnec, side)) && margin < 0) {
cnecsAndMargins.put(Pair.of(flowCnec, side), margin);
}
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@
import com.farao_community.farao.rao_api.parameters.extensions.RelativeMarginsParametersExtension;
import com.farao_community.farao.search_tree_rao.commons.optimization_perimeters.OptimizationPerimeter;
import com.farao_community.farao.search_tree_rao.result.api.FlowResult;
import com.farao_community.farao.search_tree_rao.result.api.RangeActionActivationResult;
import com.farao_community.farao.search_tree_rao.result.api.RangeActionSetpointResult;
import com.farao_community.farao.search_tree_rao.result.api.SensitivityResult;
import com.powsybl.iidm.network.Network;
import org.apache.commons.lang3.tuple.Pair;

import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
Expand Down Expand Up @@ -161,4 +165,44 @@ public static double getLargestCnecThreshold(Set<FlowCnec> flowCnecs, Unit unit)
.max(Double::compare)
.orElse(0.);
}

public static boolean cnecShouldBeOptimized(Map<FlowCnec, RangeAction<?>> flowCnecPstRangeActionMap,
FlowResult flowResult,
FlowCnec flowCnec,
Side side,
RangeActionActivationResult rangeActionActivationResult,
RangeActionSetpointResult prePerimeterRangeActionSetpointResult,
SensitivityResult sensitivityResult,
Unit unit) {
return cnecShouldBeOptimized(flowCnecPstRangeActionMap, flowResult, flowCnec, side, rangeActionActivationResult.getOptimizedSetpointsOnState(flowCnec.getState()), prePerimeterRangeActionSetpointResult, sensitivityResult, unit);
}

public static boolean cnecShouldBeOptimized(Map<FlowCnec, RangeAction<?>> flowCnecPstRangeActionMap,
FlowResult flowResult,
FlowCnec flowCnec,
Side side,
Map<RangeAction<?>, Double> activatedRangeActionsWithSetpoint,
RangeActionSetpointResult prePerimeterRangeActionSetpointResult,
SensitivityResult sensitivityResult,
Unit unit) {
if (!flowCnecPstRangeActionMap.containsKey(flowCnec)) {
return true;
}

RangeAction<?> ra = flowCnecPstRangeActionMap.get(flowCnec);
double cnecMarginToUpperBound = flowCnec.getUpperBound(side, unit).orElse(Double.POSITIVE_INFINITY) - flowResult.getFlow(flowCnec, side, unit);
double cnecMarginToLowerBound = flowResult.getFlow(flowCnec, side, unit) - flowCnec.getLowerBound(side, unit).orElse(Double.NEGATIVE_INFINITY);
if (cnecMarginToUpperBound >= 0 && cnecMarginToLowerBound >= 0) {
return false;
}

double sensitivity = sensitivityResult.getSensitivityValue(flowCnec, side, ra, Unit.MEGAWATT) * getFlowUnitMultiplier(flowCnec, side, Unit.MEGAWATT, unit);
double raCurrentSetpoint = activatedRangeActionsWithSetpoint.getOrDefault(ra, prePerimeterRangeActionSetpointResult.getSetpoint(ra));
double raMaxDecrease = raCurrentSetpoint - ra.getMinAdmissibleSetpoint(prePerimeterRangeActionSetpointResult.getSetpoint(ra));
double raMaxIncrease = ra.getMaxAdmissibleSetpoint(prePerimeterRangeActionSetpointResult.getSetpoint(ra)) - raCurrentSetpoint;
double maxFlowDecrease = sensitivity >= 0 ? sensitivity * raMaxDecrease : -sensitivity * raMaxIncrease;
double maxFlowIncrease = sensitivity >= 0 ? sensitivity * raMaxIncrease : -sensitivity * raMaxDecrease;

return cnecMarginToUpperBound + maxFlowDecrease < 0 || cnecMarginToLowerBound + maxFlowIncrease < 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
import com.farao_community.farao.commons.Unit;
import com.farao_community.farao.data.crac_api.cnec.FlowCnec;
import com.farao_community.farao.data.crac_api.cnec.Side;
import com.farao_community.farao.data.crac_api.range_action.PstRangeAction;
import com.farao_community.farao.data.crac_api.range_action.RangeAction;
import com.farao_community.farao.search_tree_rao.commons.RaoUtil;
import com.farao_community.farao.search_tree_rao.result.api.FlowResult;
import com.farao_community.farao.search_tree_rao.result.api.RangeActionActivationResult;
import com.farao_community.farao.search_tree_rao.result.api.RangeActionSetpointResult;
Expand All @@ -27,14 +28,14 @@
*/
public class MarginEvaluatorWithPstLimitationUnoptimizedCnecs implements MarginEvaluator {
private final MarginEvaluator marginEvaluator;
private final Map<FlowCnec, PstRangeAction> flowCnecPstRangeActionMap;
private final Map<FlowCnec, RangeAction<?>> flowCnecRangeActionMap;
private final RangeActionSetpointResult prePerimeterRangeActionSetpointResult;

public MarginEvaluatorWithPstLimitationUnoptimizedCnecs(MarginEvaluator marginEvaluator,
Map<FlowCnec, PstRangeAction> flowCnecPstRangeActionMap,
Map<FlowCnec, RangeAction<?>> flowCnecRangeActionMap,
RangeActionSetpointResult rangeActionActivationResult) {
this.marginEvaluator = marginEvaluator;
this.flowCnecPstRangeActionMap = flowCnecPstRangeActionMap;
this.flowCnecRangeActionMap = flowCnecRangeActionMap;
this.prePerimeterRangeActionSetpointResult = rangeActionActivationResult;
}

Expand All @@ -47,36 +48,10 @@ public double getMargin(FlowResult flowResult, FlowCnec flowCnec, RangeActionAct

@Override
public double getMargin(FlowResult flowResult, FlowCnec flowCnec, Side side, RangeActionActivationResult rangeActionActivationResult, SensitivityResult sensitivityResult, Unit unit) {
if (cnecShouldBeConsidered(flowResult, flowCnec, side, rangeActionActivationResult, sensitivityResult, unit)) {
if (RaoUtil.cnecShouldBeOptimized(flowCnecRangeActionMap, flowResult, flowCnec, side, rangeActionActivationResult, prePerimeterRangeActionSetpointResult, sensitivityResult, unit)) {
return marginEvaluator.getMargin(flowResult, flowCnec, side, rangeActionActivationResult, sensitivityResult, unit);
} else {
return Double.MAX_VALUE;
}
}

private boolean cnecShouldBeConsidered(FlowResult flowResult, FlowCnec flowCnec, Side side, RangeActionActivationResult rangeActionActivationResult, SensitivityResult sensitivityResult, Unit unit) {
if (!flowCnecPstRangeActionMap.containsKey(flowCnec)) {
return true;
}
PstRangeAction pstRangeAction = flowCnecPstRangeActionMap.get(flowCnec);
double sensitivity = sensitivityResult.getSensitivityValue(flowCnec, side, pstRangeAction, Unit.MEGAWATT);
double minSetpoint = pstRangeAction.getMinAdmissibleSetpoint(prePerimeterRangeActionSetpointResult.getSetpoint(pstRangeAction));
double maxSetpoint = pstRangeAction.getMaxAdmissibleSetpoint(prePerimeterRangeActionSetpointResult.getSetpoint(pstRangeAction));
// GetOptimizedSetpoint retrieves the latest activated range action's setpoint
double currentSetpoint = rangeActionActivationResult.getOptimizedSetpoint(pstRangeAction, flowCnec.getState());
double aboveThresholdMargin = flowCnec.getUpperBound(side, unit).orElse(Double.POSITIVE_INFINITY) - flowResult.getFlow(flowCnec, side, unit);
double belowThresholdMargin = flowResult.getFlow(flowCnec, side, unit) - flowCnec.getLowerBound(side, unit).orElse(Double.NEGATIVE_INFINITY);

double aboveThresholdConstraint;
double belowThresholdConstraint;
if (sensitivity >= 0) {
aboveThresholdConstraint = sensitivity * (currentSetpoint - minSetpoint) + aboveThresholdMargin;
belowThresholdConstraint = sensitivity * (maxSetpoint - currentSetpoint) + belowThresholdMargin;
} else {
aboveThresholdConstraint = Math.abs(sensitivity) * (maxSetpoint - currentSetpoint) + aboveThresholdMargin;
belowThresholdConstraint = Math.abs(sensitivity) * (currentSetpoint - minSetpoint) + belowThresholdMargin;
}

return aboveThresholdConstraint <= 0 || belowThresholdConstraint <= 0;
}
}
Loading

0 comments on commit 9876627

Please sign in to comment.