Skip to content

Commit 6a5ea2f

Browse files
committed
Merge branch 'main' into experiment/robustify-one-state-only-rao-result
# Conflicts: # ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/castor/algorithm/CastorFullOptimization.java
2 parents a1bbd5c + 70394fe commit 6a5ea2f

File tree

187 files changed

+5117
-178
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

187 files changed

+5117
-178
lines changed

docs/algorithms/castor/special-features.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
special-features/loop-flows.md
66
special-features/mnecs.md
77
special-features/do-not-optimize-specific-cnecs.md
8+
special-features/pst-regulation.md
89
```
910

1011
Several special features can be included in the RAO optimisation:
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# PST Regulation
2+
3+
## Presentation
4+
5+
In some processes and/or regions, certain critical elements are operated in series with a PST such that when these
6+
elements are overloaded and there is still a possibility to change the tap position of the associated PST and if is not
7+
in abutment, the latter is used to secure the constrained elements.
8+
9+
At the end of the curative optimization of the RAO, such critical lines can still be unsecure because they are not
10+
limiting elements. Indeed, some other lines can have a margin which is way more negative so the RAO cannot improve its
11+
objective function by changing the taps of the PSTs in series with overloaded critical elements. The results must then
12+
be post-processed to check if changing the taps of these PSTs of interest could help secure the critical element they
13+
monitor, even if this means increasing the flow in surrounding lines. This is called **PST regulation**.
14+
15+
> Even if only one critical element is overloaded, all PSTs are regulated at once since they may have side effects on
16+
> other lines than the ones they protect.
17+
18+
The set of PSTs to regulate can be provided in the
19+
[RAO parameters](../../../parameters/implementation-specific-parameters.md#pst-regulation-parameters). Then, for each curative
20+
scenario, if the most limiting element is a FlowCNEC in series with a PST, all the PSTs are regulated.
21+
22+
Such monitored lines can be the PSTs themselves or lines connected in series. In the second case, the threshold of the
23+
FlowCNEC defined on this line in series is used as the regulation value.
24+
25+
> ⚠️ **Remark: Sub-optimality**
26+
>
27+
> Note that there is a risk that PST regulation worsens the minimal margin.
28+
29+
PST regulation is performed directly by the load flow engine provided
30+
by [PowSyBl Open Load Flow](https://powsybl.readthedocs.io/projects/powsybl-open-loadflow/en/stable/index.html). This
31+
basically consists in iterative load flow computations with the tap of one of the regulated PST moved in the direction
32+
that favors the security of the monitored line each time. As soon as the monitored line is secure, the tap does no
33+
longer need to be moved. When all taps have reached a fixed position, the iterations stop and the regulation is over.
34+
35+
Regulation results are then merged with the RAO result to provide the final results. If a PST was moved during
36+
regulation, this will appear as a result from the curative optimization.
37+
38+
## Example
39+
40+
Let us consider a simple network of only two nodes and three parallel branches, one of these being a PST. We will denote
41+
these lines as `branch-1`, `branch-2` and `branch-3`; `branch-3` being the PST to regulate. All three branches are
42+
considered to have the same permanent limit (PATL) and the same impedance. The PST is initially on tap -5 and its
43+
neutral tap is 0.
44+
45+
The first step is to fill the RAO parameters with
46+
[PST regulation parameters](../../../parameters/implementation-specific-parameters.md#pst-regulation-parameters) to indicate
47+
that the PST can be regulated.
48+
49+
```json
50+
{
51+
"version": "3.2.1",
52+
"extensions": {
53+
"open-rao-search-tree-parameters": {
54+
"pst-regulation-parameters" : {
55+
"psts-to-regulate": { "branch-3" : "branch-3" }
56+
}
57+
}
58+
}
59+
}
60+
```
61+
62+
We will consider that there is a contingency on `branch-1` and that when it occurs, there is no way to secure both
63+
`branch-2` and `branch-3` at the same time.
64+
65+
As these two branches have the same impedance and the same permanent limit, the status quo found by the RAO during
66+
curative optimization is to set the PST on its neutral tap (position 0). That way, both branches are overloaded but the
67+
minimal margin is maximized, because no branch is relieved to the detriment of the other.
68+
69+
If the RAO were to stop here, the activation of the PST in the RAO result would look like:
70+
71+
```json
72+
{
73+
"rangeActionId": "pstRangeAction",
74+
"initialTap": -5,
75+
"activatedStates": [
76+
{
77+
"instant": "curative",
78+
"contingencyId": "contingency-branch-1",
79+
"tap": 0
80+
}
81+
]
82+
}
83+
```
84+
85+
However, the PST on `branch-3` can be regulated. As it is overloaded and is also the most limiting element, regulation
86+
can be performed to try to secure the PST. We will consider that in the network configuration, the PST can be secured
87+
from tap position 7, though it increases the overload on `branch-2`.
88+
89+
Thus, the regulation algorithm will move the tap of the PST from position 0 to position 7 and the final RAO result will
90+
contain this activation result instead of the previous one:
91+
92+
```json
93+
{
94+
"rangeActionId": "pstRangeAction",
95+
"initialTap": -5,
96+
"activatedStates": [
97+
{
98+
"instant": "curative",
99+
"contingencyId": "contingency-branch-1",
100+
"tap": 7
101+
}
102+
]
103+
}
104+
```
105+
106+
The flows will also be updated and the limiting element is now `branch-2` alone with a greater overload than previously.

docs/parameters.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Examples of rao parameters with business and implementation specific parameters
3636
:::{group-tab} JSON
3737
~~~json
3838
{
39-
"version" : "3.2",
39+
"version" : "3.2.1",
4040
"objective-function" : {
4141
"type" : "SECURE_FLOW",
4242
"unit" : "A",

docs/parameters/business-parameters.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ See also: [Modelling the maximum minimum relative margin objective function](../
183183
:::{group-tab} JSON
184184
~~~json
185185
{
186-
"version" : "3.2",
186+
"version" : "3.2.1",
187187
"objective-function" : {
188188
"type" : "SECURE_FLOW",
189189
"unit" : "A",

docs/parameters/implementation-specific-parameters.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,14 @@ These parameters are meant to be used in costly optimization only.
396396
- **Default value**: 5
397397
- **Usage**: If `add-unsecure-cnecs` is enabled, a CNEC will be considered unsecure if its margin is lower than `margin-limit`.
398398

399+
#### PST regulation parameters
400+
401+
##### psts-to-regulate
402+
403+
- **Expected value**: a map with string keys (each being the identifier of a PST in the network) and string values (each being the line secured by the regulated PST)
404+
- **Default value**: empty map
405+
- **Usage**: List of PSTs to regulate at the end of curative optimization if a FlowCNEC defined on any of their associated elements is overloaded and is the most limiting element.
406+
399407
## Examples
400408
> ⚠️ **NOTE**
401409
> The following examples in json and yaml are not equivalent
@@ -404,7 +412,7 @@ These parameters are meant to be used in costly optimization only.
404412
:::{group-tab} JSON
405413
~~~json
406414
{
407-
"version" : "3.2",
415+
"version" : "3.2.1",
408416
"extensions" : {
409417
"fast-rao-parameters" : {
410418
"number-of-cnecs-to-add" : 20,
@@ -511,6 +519,12 @@ These parameters are meant to be used in costly optimization only.
511519
"costly-min-margin-parameters" : {
512520
"shifted-violation-penalty": 1000.0,
513521
"shifted-violation-threshold": 0.0
522+
},
523+
"pst-regulation-parameters" : {
524+
"psts-to-regulate": {
525+
"pst-1": "line-1",
526+
"pst-2": "line-2"
527+
}
514528
}
515529
}
516530
}
@@ -565,4 +579,3 @@ fast-rao-parameters:
565579
~~~
566580
:::
567581
::::
568-

ra-optimisation/rao-api/src/main/java/com/powsybl/openrao/raoapi/RaoParametersCommons.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ private RaoParametersCommons() {
2222
---------------------------
2323
3.1: remove max-auto-search-tree-depth
2424
3.2: remove re-optimize-curative-range-actions
25+
3.2.1: add pst-regulation-parameters
2526
*/
2627

27-
public static final String RAO_PARAMETERS_VERSION = "3.2";
28+
public static final String RAO_PARAMETERS_VERSION = "3.2.1";
2829

2930
// header
3031
public static final String VERSION = "version";
@@ -143,4 +144,9 @@ public static PtdfApproximation stringToPtdfApproximation(String string) {
143144
public static final String ST_COSTLY_MIN_MARGIN_SECTION = "search-tree-costly-min-margin-parameters";
144145
public static final String SHIFTED_VIOLATION_PENALTY = "shifted-violation-penalty";
145146
public static final String SHIFTED_VIOLATION_THRESHOLD = "shifted-violation-threshold";
147+
148+
// -- PST regulation parameters
149+
public static final String PST_REGULATION_PARAMETERS = "pst-regulation-parameters";
150+
public static final String ST_PST_REGULATION_SECTION = "search-tree-pst-regulation-parameters";
151+
public static final String PSTS_TO_REGULATE = "psts-to-regulate";
146152
}

ra-optimisation/rao-api/src/main/java/com/powsybl/openrao/raoapi/json/extensions/JsonOpenRaoSearchTreeParameters.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public void serialize(OpenRaoSearchTreeParameters parameters, JsonGenerator json
3939
JsonRelativeMarginsParameters.serialize(parameters, jsonGenerator);
4040
JsonLoopFlowParameters.serialize(parameters, jsonGenerator);
4141
JsonMinMarginsParameters.serialize(parameters, jsonGenerator);
42+
JsonSearchTreeRaoPstRegulationParameters.serialize(parameters, jsonGenerator);
4243
jsonGenerator.writeEndObject();
4344
}
4445

@@ -91,7 +92,12 @@ public OpenRaoSearchTreeParameters deserializeAndUpdate(JsonParser parser, Deser
9192
parser.nextToken();
9293
JsonMinMarginsParameters.deserialize(parser, parameters);
9394
}
94-
default -> throw new OpenRaoException("Unexpected field in open rao search tree parameters: " + parser.getCurrentName());
95+
case PST_REGULATION_PARAMETERS -> {
96+
parser.nextToken();
97+
JsonSearchTreeRaoPstRegulationParameters.deserialize(parser, parameters);
98+
}
99+
default ->
100+
throw new OpenRaoException("Unexpected field in open rao search tree parameters: " + parser.getCurrentName());
95101
}
96102
}
97103
return parameters;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
package com.powsybl.openrao.raoapi.json.extensions;
9+
10+
import com.fasterxml.jackson.core.JsonGenerator;
11+
import com.fasterxml.jackson.core.JsonParser;
12+
import com.powsybl.openrao.commons.OpenRaoException;
13+
import com.powsybl.openrao.raoapi.parameters.extensions.OpenRaoSearchTreeParameters;
14+
import com.powsybl.openrao.raoapi.parameters.extensions.SearchTreeRaoPstRegulationParameters;
15+
16+
import java.io.IOException;
17+
import java.util.HashMap;
18+
import java.util.Map;
19+
import java.util.Optional;
20+
21+
import static com.powsybl.openrao.raoapi.RaoParametersCommons.PSTS_TO_REGULATE;
22+
import static com.powsybl.openrao.raoapi.RaoParametersCommons.PST_REGULATION_PARAMETERS;
23+
24+
/**
25+
* @author Thomas Bouquet {@literal <thomas.bouquet at rte-france.com>}
26+
*/
27+
public final class JsonSearchTreeRaoPstRegulationParameters {
28+
private JsonSearchTreeRaoPstRegulationParameters() {
29+
}
30+
31+
static void serialize(OpenRaoSearchTreeParameters parameters, JsonGenerator jsonGenerator) throws IOException {
32+
Optional<SearchTreeRaoPstRegulationParameters> pstRegulationParameters = parameters.getPstRegulationParameters();
33+
if (pstRegulationParameters.isPresent()) {
34+
jsonGenerator.writeObjectFieldStart(PST_REGULATION_PARAMETERS);
35+
jsonGenerator.writeObjectFieldStart(PSTS_TO_REGULATE);
36+
for (Map.Entry<String, String> entry : pstRegulationParameters.get().getPstsToRegulate().entrySet().stream().sorted(Map.Entry.comparingByValue()).toList()) {
37+
jsonGenerator.writeStringField(entry.getKey(), entry.getValue());
38+
}
39+
jsonGenerator.writeEndObject();
40+
jsonGenerator.writeEndObject();
41+
}
42+
43+
}
44+
45+
static void deserialize(JsonParser jsonParser, OpenRaoSearchTreeParameters searchTreeParameters) throws IOException {
46+
SearchTreeRaoPstRegulationParameters pstRegulationParameters = new SearchTreeRaoPstRegulationParameters();
47+
while (!jsonParser.nextToken().isStructEnd()) {
48+
switch (jsonParser.getCurrentName()) {
49+
case PSTS_TO_REGULATE:
50+
jsonParser.nextToken();
51+
pstRegulationParameters.setPstsToRegulate(jsonParser.readValueAs(HashMap.class));
52+
break;
53+
default:
54+
throw new OpenRaoException(String.format("Cannot deserialize PST regulation parameters: unexpected field in %s (%s)", PST_REGULATION_PARAMETERS, jsonParser.getCurrentName()));
55+
}
56+
searchTreeParameters.setPstRegulationParameters(pstRegulationParameters);
57+
}
58+
}
59+
}

ra-optimisation/rao-api/src/main/java/com/powsybl/openrao/raoapi/parameters/extensions/OpenRaoSearchTreeParameters.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public class OpenRaoSearchTreeParameters extends AbstractExtension<RaoParameters
2828
private Optional<SearchTreeRaoMnecParameters> mnecParameters = Optional.empty();
2929
private Optional<SearchTreeRaoRelativeMarginsParameters> relativeMarginsParameters = Optional.empty();
3030
private Optional<SearchTreeRaoLoopFlowParameters> loopFlowParameters = Optional.empty();
31+
private Optional<SearchTreeRaoPstRegulationParameters> pstRegulationParameters = Optional.empty();
3132

3233
// Getters and setters
3334
public void setObjectiveFunctionParameters(SearchTreeRaoObjectiveFunctionParameters objectiveFunctionParameters) {
@@ -70,6 +71,10 @@ public void setMinMarginsParameters(SearchTreeRaoCostlyMinMarginParameters minMa
7071
this.minMarginsParameters = Optional.of(minMarginsParameters);
7172
}
7273

74+
public void setPstRegulationParameters(SearchTreeRaoPstRegulationParameters pstRegulationParameters) {
75+
this.pstRegulationParameters = Optional.of(pstRegulationParameters);
76+
}
77+
7378
public SearchTreeRaoObjectiveFunctionParameters getObjectiveFunctionParameters() {
7479
return objectiveFunctionParameters;
7580
}
@@ -110,6 +115,10 @@ public Optional<SearchTreeRaoLoopFlowParameters> getLoopFlowParameters() {
110115
return loopFlowParameters;
111116
}
112117

118+
public Optional<SearchTreeRaoPstRegulationParameters> getPstRegulationParameters() {
119+
return pstRegulationParameters;
120+
}
121+
113122
@Override
114123
public String getName() {
115124
return SEARCH_TREE_PARAMETERS;

ra-optimisation/rao-api/src/main/java/com/powsybl/openrao/raoapi/parameters/extensions/OpenRaoSearchTreeParametersConfigLoader.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class OpenRaoSearchTreeParametersConfigLoader implements RaoParameters.Co
2727
@Override
2828
public OpenRaoSearchTreeParameters load(PlatformConfig platformConfig) {
2929
Objects.requireNonNull(platformConfig);
30-
List<String> searchTreeParams = Arrays.asList(ST_OBJECTIVE_FUNCTION_SECTION, ST_RANGE_ACTIONS_OPTIMIZATION_SECTION, ST_TOPOLOGICAL_ACTIONS_OPTIMIZATION_SECTION, MULTI_THREADING_SECTION, SECOND_PREVENTIVE_RAO_SECTION, LOAD_FLOW_AND_SENSITIVITY_COMPUTATION_SECTION, ST_MNEC_PARAMETERS_SECTION, ST_RELATIVE_MARGINS_SECTION, ST_LOOP_FLOW_PARAMETERS_SECTION, ST_COSTLY_MIN_MARGIN_SECTION);
30+
List<String> searchTreeParams = Arrays.asList(ST_OBJECTIVE_FUNCTION_SECTION, ST_RANGE_ACTIONS_OPTIMIZATION_SECTION, ST_TOPOLOGICAL_ACTIONS_OPTIMIZATION_SECTION, MULTI_THREADING_SECTION, SECOND_PREVENTIVE_RAO_SECTION, LOAD_FLOW_AND_SENSITIVITY_COMPUTATION_SECTION, ST_MNEC_PARAMETERS_SECTION, ST_RELATIVE_MARGINS_SECTION, ST_LOOP_FLOW_PARAMETERS_SECTION, ST_COSTLY_MIN_MARGIN_SECTION, ST_PST_REGULATION_SECTION);
3131
boolean anySearchTreeParams = searchTreeParams.stream().map(platformConfig::getOptionalModuleConfig).anyMatch(Optional::isPresent);
3232
if (!anySearchTreeParams) {
3333
return null;
@@ -43,6 +43,7 @@ public OpenRaoSearchTreeParameters load(PlatformConfig platformConfig) {
4343
SearchTreeRaoMnecParameters.load(platformConfig).ifPresent(parameters::setMnecParameters);
4444
SearchTreeRaoRelativeMarginsParameters.load(platformConfig).ifPresent(parameters::setRelativeMarginsParameters);
4545
SearchTreeRaoLoopFlowParameters.load(platformConfig).ifPresent(parameters::setLoopFlowParameters);
46+
SearchTreeRaoPstRegulationParameters.load(platformConfig).ifPresent(parameters::setPstRegulationParameters);
4647
return parameters;
4748
}
4849

0 commit comments

Comments
 (0)