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

[WIP INTERNSHIP] Balance constraint for injection #1135

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
57 changes: 41 additions & 16 deletions docs/castor/linear-problem/core-problem-filler.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@

## Used input data

| Name | Symbol | Details |
|-----------------------|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| FlowCnecs | $c \in \mathcal{C}$ | set of FlowCnecs[^1]. Note that FlowCnecs are all the CBCO for which we compute the flow in the MILP, either: <br> - because we are optimizing their flow (optimized flowCnec = CNEC) <br> - because we are monitoring their flow, and ensuring it does not exceed its threshold (monitored flowCnec = MNEC) <br> - or both |
| RangeActions | $r,s \in \mathcal{RA}$ | set of RangeActions and state on which they are applied, could be PSTs, HVDCs, or injection range actions |
| RangeActions | $r \in \mathcal{RA(s)}$ | set of RangeActions available on state $s$, could be PSTs, HVDCs, or injection range actions |
| Iteration number | $n$ | number of current iteration |
| ReferenceFlow | $f_{n}(c)$ | reference flow, for FlowCnec $c$. <br>The reference flow is the flow at the beginning of the current iteration of the MILP, around which the sensitivities are computed |
| PrePerimeterSetpoints | $\alpha _0(r)$ | setpoint of RangeAction $r$ at the beginning of the optimization |
| ReferenceSetpoints | $\alpha _n(r)$ | setpoint of RangeAction $r$ at the beginning of the current iteration of the MILP, around which the sensitivities are computed |
| Sensitivities | $\sigma _{n}(r,c,s)$ | sensitivity of RangeAction $r$ on FlowCnec $c$ for state $s$ |
| Previous RA setpoint | $A_{n-1}(r,s)$ | optimal setpoint of RangeAction $r$ on state $s$ in previous iteration ($n-1$) |
| Name | Symbol | Details |
|-----------------------------|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| FlowCnecs | $c \in \mathcal{C}$ | set of FlowCnecs[^1]. Note that FlowCnecs are all the CBCO for which we compute the flow in the MILP, either: <br> - because we are optimizing their flow (optimized flowCnec = CNEC) <br> - because we are monitoring their flow, and ensuring it does not exceed its threshold (monitored flowCnec = MNEC) <br> - or both |
| RangeActions | $r,s \in \mathcal{RA}$ | set of RangeActions and state on which they are applied, could be PSTs, HVDCs, or injection range actions |
| RangeActions | $r \in \mathcal{RA(s)}$ | set of RangeActions available on state $s$, could be PSTs, HVDCs, or injection range actions |
| InjectionRangeActions | $r,s \in \mathcal{IRA}$ | set of InjectionRangeActions and state on which they are applied. |
| Injection Distribution keys | $d \in \mathcal{DK(r)}$ | set of distribution keys of InjectionRangeAction $r$. Each distribution key is linked to a NetworkElement. |
| Iteration number | $n$ | number of current iteration |
| ReferenceFlow | $f_{n}(c)$ | reference flow, for FlowCnec $c$. <br>The reference flow is the flow at the beginning of the current iteration of the MILP, around which the sensitivities are computed |
| PrePerimeterSetpoints | $\alpha _0(r)$ | setpoint of RangeAction $r$ at the beginning of the optimization |
| ReferenceSetpoints | $\alpha _n(r)$ | setpoint of RangeAction $r$ at the beginning of the current iteration of the MILP, around which the sensitivities are computed |
| Sensitivities | $\sigma _{n}(r,c,s)$ | sensitivity of RangeAction $r$ on FlowCnec $c$ for state $s$ |
| Previous RA setpoint | $A_{n-1}(r,s)$ | optimal setpoint of RangeAction $r$ on state $s$ in previous iteration ($n-1$) |

[^1]: CNECs that belong to a state for which sensitivity computations failed are ignored in the MILP

Expand All @@ -25,11 +27,12 @@

## Defined optimization variables

| Name | Symbol | Details | Type | Index | Unit | Lower bound | Upper bound |
|--------------------------------|-----------------|-------------------------------------------------------------------------------------------------------------------|---------------------|--------------------------------------------------|-----------------------------------------------------------|-----------------------|-----------------------|
| Flow | $F(c)$ | flow of FlowCnec $c$ | Real value | One variable for every element of (FlowCnecs) | MW | $-\infty$ | $+\infty$ |
| RA setpoint | $A(r,s)$ | setpoint of RangeAction $r$ on state $s$ | Real value | One variable for every element of (RangeActions) | Degrees for PST range actions; MW for other range actions | Range lower bound[^2] | Range upper bound[^2] |
| RA setpoint absolute variation | $\Delta A(r,s)$ | The absolute setpoint variation of RangeAction $r$ on state $s$, from setpoint on previous state to "RA setpoint" | Real positive value | One variable for every element of (RangeActions) | Degrees for PST range actions; MW for other range actions | 0 | $+\infty$ |
| Name | Symbol | Details | Type | Index | Unit | Lower bound | Upper bound |
|--------------------------------|-----------------|-------------------------------------------------------------------------------------------------------------------|---------------------|-----------------------------------------------------------|-----------------------------------------------------------|-----------------------|-----------------------|
| Flow | $F(c)$ | flow of FlowCnec $c$ | Real value | One variable for every element of (FlowCnecs) | MW | $-\infty$ | $+\infty$ |
| RA setpoint | $A(r,s)$ | setpoint of RangeAction $r$ on state $s$ | Real value | One variable for every element of (RangeActions) | Degrees for PST range actions; MW for other range actions | Range lower bound[^2] | Range upper bound[^2] |
| RA setpoint absolute variation | $\Delta A(r,s)$ | The absolute setpoint variation of RangeAction $r$ on state $s$, from setpoint on previous state to "RA setpoint" | Real positive value | One variable for every element of (RangeActions) | Degrees for PST range actions; MW for other range actions | 0 | $+\infty$ |
| RA injection variation | $\Delta I(r,s)$ | The signed variation of one Injection RangeAction $r$ on state $s$, after considering distribution keys. | Real value | One variable for every element of (InjectionRangeActions) | MW for other range actions | $-\infty$ | $+\infty$ |

[^2]: Range actions' lower & upper bounds are computed using CRAC + network + previous RAO results, depending on the
types of their ranges: ABSOLUTE, RELATIVE_TO_INITIAL_NETWORK, RELATIVE_TO_PREVIOUS_INSTANT (more
Expand Down Expand Up @@ -103,6 +106,28 @@ $$
The value $\frac{2}{3}$ has been chosen to force the linear problem convergence while allowing the RA to go
back to its initial solution if needed.

### Definition of the injection variation

Define the injection variation. We need to multiply by the sum of the distribution keys in order to match the real variation on the network.

$$
\begin{equation}
\Delta I(r,s) = (A(r,s) - \alpha_{0}) * \sum_{d \in \mathcal{DK(r)}} d
\end{equation}
$$

with $r$ an InjectionRangeAction, and $s$ the state on which $r$ is evaluated.

### Balance constraint for Injection RangeActions

The sum of injection variations of all InjectionRangeActions must be equal to 0, for balance reasons.

$$
\begin{equation}
\sum_{r,s \in \mathcal{IRA}} ( \Delta I(r,s)) = 0
\end{equation}
$$

## Contribution to the objective function

Small penalisation for the use of RangeActions:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,20 @@ private void buildFlowVariables(LinearProblem linearProblem, Set<FlowCnec> valid
* Build one absolute variation variable AV[r] for each RangeAction r
* This variable describes the absolute difference between the range action setpoint
* and its initial value. It is given in the same unit as S[r].
* <p>
* Build one injection variation variable IV[r] for each InjectionRangeAction r
* This variable describes the injection difference between the injection setpoint and its initial value
* after taking into account the distribution keys.
*/
private void buildRangeActionVariables(LinearProblem linearProblem) {
optimizationContext.getRangeActionsPerState().forEach((state, rangeActions) ->
rangeActions.forEach(rangeAction -> {
linearProblem.addRangeActionSetpointVariable(-linearProblem.infinity(), linearProblem.infinity(), rangeAction, state);
linearProblem.addAbsoluteRangeActionVariationVariable(0, linearProblem.infinity(), rangeAction, state);
if (rangeAction instanceof InjectionRangeAction injectionRangeAction) {
//injection variation variable needed for balance contraint
linearProblem.addInjectionVariationVariable(-linearProblem.infinity(), linearProblem.infinity(), injectionRangeAction, state);
}
})
);
}
Expand Down Expand Up @@ -199,9 +207,22 @@ private boolean isRangeActionSensitivityAboveThreshold(RangeAction<?> rangeActio

private void buildRangeActionConstraints(LinearProblem linearProblem) {
optimizationContext.getRangeActionsPerState().entrySet().stream()
.sorted(Comparator.comparingInt(e -> e.getKey().getInstant().getOrder()))
.forEach(entry ->
entry.getValue().forEach(rangeAction -> buildConstraintsForRangeActionAndState(linearProblem, rangeAction, entry.getKey())));
.sorted(Comparator.comparing(e -> e.getKey().getInstant()))
.forEach(entry -> {
Set<InjectionRangeAction> injectionRangeActions = new HashSet<>();
for (RangeAction<?> rangeAction : entry.getValue()) {
if (rangeAction instanceof InjectionRangeAction injectionRangeAction) {
injectionRangeActions.add(injectionRangeAction);
}
}
if (!injectionRangeActions.isEmpty()) {
// create the constraint
OpenRaoMPConstraint injectionBalanceConstraint = linearProblem.addInjectionBalanceVariationConstraint(0., 0., entry.getKey());
// add the injection variation variables to the constraint
injectionRangeActions.forEach(injectionRangeAction -> buildInjectionBalanceConstraint(linearProblem, injectionRangeAction, entry.getKey(), injectionBalanceConstraint));
}
entry.getValue().forEach(rangeAction -> buildConstraintsForRangeActionAndState(linearProblem, rangeAction, entry.getKey()));
});
}

private void checkAndActivateRangeShrinking(LinearProblem linearProblem, RangeActionActivationResult rangeActionActivationResult) {
Expand Down Expand Up @@ -316,6 +337,30 @@ private void buildConstraintsForRangeActionAndState(LinearProblem linearProblem,
}
}

/**
* Adds injection variation variable of given InjectionRangeAction to balance constraint
* sum( {r in RangeActions} SV[r])
* Constraint for defining Injection Variation:
* IV[r] = (setpoint[r] - prePerimeterSetPoint[r]) * sum(distributionKeys[r])
*/
private void buildInjectionBalanceConstraint(LinearProblem linearProblem, InjectionRangeAction injectionRangeAction, State state, OpenRaoMPConstraint injectionBalanceConstraint) {
OpenRaoMPVariable signedInjectionVariationVariable = linearProblem.getInjectionVariationVariable(injectionRangeAction, state);
injectionBalanceConstraint.setCoefficient(signedInjectionVariationVariable, 1);

OpenRaoMPVariable setPointVariable = linearProblem.getRangeActionSetpointVariable(injectionRangeAction, state);

double sumDistributionKeys = injectionRangeAction.getInjectionDistributionKeys().values().stream().mapToDouble(d -> d).sum();

// TODO: use variable for 2P in case the setpoint was changed in a previous state
if (sumDistributionKeys != 0) {
double bound = -prePerimeterRangeActionSetpoints.getSetpoint(injectionRangeAction) * sumDistributionKeys;
OpenRaoMPConstraint injectionRelativeVariationConstraint = linearProblem.addInjectionVariationConstraint(bound, bound, injectionRangeAction, state);
injectionRelativeVariationConstraint.setCoefficient(signedInjectionVariationVariable, 1);
injectionRelativeVariationConstraint.setCoefficient(setPointVariable, -sumDistributionKeys);
}

}

private static List<Double> getMinAndMaxAbsoluteAndRelativeSetpoints(RangeAction<?> rangeAction, double infinity) {

// if relative to previous instant range
Expand Down
Loading