Skip to content

Commit e319b10

Browse files
authored
Use contingency context in operator strategies (#2429)
Signed-off-by: Geoffroy Jamgotchian <geoffroy.jamgotchian@gmail.com>
1 parent 368b96a commit e319b10

18 files changed

+90
-37
lines changed

security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ private static void addOperatorStrategyFile(SecurityAnalysisCommandOptions optio
229229
options.strategiesFile(path);
230230
LOGGER.debug("Writing operator strategies to file {}", path);
231231
new OperatorStrategyList(operatorStrategies)
232-
.writeFile(path);
232+
.write(path);
233233
}
234234

235235
/**

security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/OperatorStrategyDeserializer.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import com.powsybl.commons.extensions.ExtensionJsonSerializer;
1717
import com.powsybl.commons.extensions.ExtensionProviders;
1818
import com.powsybl.commons.json.JsonUtil;
19+
import com.powsybl.contingency.ContingencyContext;
20+
import com.powsybl.contingency.ContingencyContextType;
1921
import com.powsybl.security.condition.Condition;
2022
import com.powsybl.security.strategy.OperatorStrategy;
2123

@@ -37,6 +39,7 @@ public OperatorStrategyDeserializer() {
3739

3840
private static class ParsingContext {
3941
String id;
42+
ContingencyContextType contingencyContextType;
4043
String contingencyId;
4144
Condition condition;
4245
List<String> actionIds;
@@ -52,6 +55,9 @@ public OperatorStrategy deserialize(JsonParser parser, DeserializationContext de
5255
parser.nextToken();
5356
context.id = parser.getValueAsString();
5457
return true;
58+
case "contingencyContextType":
59+
context.contingencyContextType = ContingencyContextType.valueOf(parser.nextTextValue());
60+
return true;
5561
case "contingencyId":
5662
parser.nextToken();
5763
context.contingencyId = parser.getValueAsString();
@@ -73,7 +79,12 @@ public OperatorStrategy deserialize(JsonParser parser, DeserializationContext de
7379
return false;
7480
}
7581
});
76-
OperatorStrategy operatorStrategy = new OperatorStrategy(context.id, context.contingencyId, context.condition, context.actionIds);
82+
// First version of the operator strategy only allows association to one contingency. Next versions use contingency
83+
// context. So, for backward compatibility purposes, we consider that if contingencyContextType is null, we have
84+
// a specific contingency context type.
85+
ContingencyContext contingencyContext = new ContingencyContext(context.contingencyId,
86+
context.contingencyContextType != null ? context.contingencyContextType : ContingencyContextType.SPECIFIC);
87+
OperatorStrategy operatorStrategy = new OperatorStrategy(context.id, contingencyContext, context.condition, context.actionIds);
7788
SUPPLIER.get().addExtensions(operatorStrategy, context.extensions);
7889
return operatorStrategy;
7990
}

security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/OperatorStrategyListDeserializer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ public OperatorStrategyList deserialize(JsonParser parser, DeserializationContex
4949
return false;
5050
}
5151
});
52-
if (context.version == null || !context.version.equals(OperatorStrategyList.VERSION)) {
53-
throw new JsonMappingException(parser, "version is missing or not equal to 1.0");
52+
if (context.version == null) {
53+
throw new JsonMappingException(parser, "version is missing");
5454
}
5555
return new OperatorStrategyList(context.operatorStrategies);
5656
}

security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/OperatorStrategySerializer.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.fasterxml.jackson.databind.SerializerProvider;
1111
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
1212
import com.powsybl.commons.json.JsonUtil;
13+
import com.powsybl.contingency.ContingencyContext;
1314
import com.powsybl.security.strategy.OperatorStrategy;
1415

1516
import java.io.IOException;
@@ -27,7 +28,11 @@ public OperatorStrategySerializer() {
2728
public void serialize(OperatorStrategy operatorStrategy, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
2829
jsonGenerator.writeStartObject();
2930
jsonGenerator.writeStringField("id", operatorStrategy.getId());
30-
jsonGenerator.writeStringField("contingencyId", operatorStrategy.getContingencyId());
31+
ContingencyContext contingencyContext = operatorStrategy.getContingencyContext();
32+
jsonGenerator.writeStringField("contingencyContextType", contingencyContext.getContextType().name());
33+
if (contingencyContext.getContingencyId() != null) {
34+
jsonGenerator.writeStringField("contingencyId", contingencyContext.getContingencyId());
35+
}
3136
jsonGenerator.writeObjectField("condition", operatorStrategy.getCondition());
3237
jsonGenerator.writeObjectField("actionIds", operatorStrategy.getActionIds());
3338
JsonUtil.writeExtensions(operatorStrategy, jsonGenerator, serializerProvider);

security-analysis/security-analysis-api/src/main/java/com/powsybl/security/strategy/OperatorStrategy.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import com.google.common.collect.ImmutableList;
1010
import com.powsybl.commons.extensions.AbstractExtendable;
11+
import com.powsybl.contingency.ContingencyContext;
1112
import com.powsybl.security.condition.Condition;
1213

1314
import java.util.List;
@@ -26,13 +27,13 @@
2627
*/
2728
public class OperatorStrategy extends AbstractExtendable<OperatorStrategy> {
2829
private final String id;
29-
private final String contingencyId;
30+
private final ContingencyContext contingencyContext;
3031
private final Condition condition; // under which circumstances do I want to trigger my action
3132
private final List<String> actionIds;
3233

33-
public OperatorStrategy(String id, String contingencyId, Condition condition, List<String> actionIds) {
34+
public OperatorStrategy(String id, ContingencyContext contingencyContext, Condition condition, List<String> actionIds) {
3435
this.id = Objects.requireNonNull(id);
35-
this.contingencyId = Objects.requireNonNull(contingencyId);
36+
this.contingencyContext = Objects.requireNonNull(contingencyContext);
3637
this.condition = Objects.requireNonNull(condition);
3738
this.actionIds = ImmutableList.copyOf(Objects.requireNonNull(actionIds));
3839
}
@@ -47,8 +48,8 @@ public String getId() {
4748
/**
4849
* The contingency which this strategy applies to.
4950
*/
50-
public String getContingencyId() {
51-
return contingencyId;
51+
public ContingencyContext getContingencyContext() {
52+
return contingencyContext;
5253
}
5354

5455
/**

security-analysis/security-analysis-api/src/main/java/com/powsybl/security/strategy/OperatorStrategyList.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
*/
3030
public class OperatorStrategyList {
3131
private final List<OperatorStrategy> operatorStrategies;
32-
public static final String VERSION = "1.0";
32+
public static final String VERSION = "1.1";
3333

3434
public OperatorStrategyList(List<OperatorStrategy> operatorStrategies) {
3535
this.operatorStrategies = ImmutableList.copyOf(Objects.requireNonNull(operatorStrategies));
@@ -39,15 +39,15 @@ public List<OperatorStrategy> getOperatorStrategies() {
3939
return operatorStrategies;
4040
}
4141

42-
public static OperatorStrategyList readFile(Path jsonFile) {
42+
public static OperatorStrategyList read(Path jsonFile) {
4343
try (InputStream is = Files.newInputStream(jsonFile)) {
44-
return readOutputStream(is);
44+
return read(is);
4545
} catch (IOException e) {
4646
throw new UncheckedIOException(e);
4747
}
4848
}
4949

50-
public static OperatorStrategyList readOutputStream(InputStream is) {
50+
public static OperatorStrategyList read(InputStream is) {
5151
Objects.requireNonNull(is);
5252

5353
ObjectMapper objectMapper = JsonUtil.createObjectMapper()
@@ -62,10 +62,10 @@ public static OperatorStrategyList readOutputStream(InputStream is) {
6262
/**
6363
* Writes action list as JSON to a file.
6464
*/
65-
public void writeFile(Path jsonFile) {
65+
public void write(Path jsonFile) {
6666
Objects.requireNonNull(jsonFile);
6767
try (OutputStream outputStream = Files.newOutputStream(jsonFile)) {
68-
writeOutputStream(outputStream);
68+
write(outputStream);
6969
} catch (IOException e) {
7070
throw new UncheckedIOException(e);
7171
}
@@ -74,7 +74,7 @@ public void writeFile(Path jsonFile) {
7474
/**
7575
* Writes action list as JSON to an output stream.
7676
*/
77-
public void writeOutputStream(OutputStream outputStream) {
77+
public void write(OutputStream outputStream) {
7878
try {
7979
ObjectMapper objectMapper = createObjectMapper();
8080
ObjectWriter writer = objectMapper.writerWithDefaultPrettyPrinter();

security-analysis/security-analysis-api/src/main/java/com/powsybl/security/tools/SecurityAnalysisTool.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ void run(CommandLine line, ToolRunningContext context,
301301
.setParameters(parametersLoader.get());
302302

303303
options.getPath(MONITORING_FILE).ifPresent(monitorFilePath -> executionInput.setMonitors(StateMonitor.read(monitorFilePath)));
304-
options.getPath(STRATEGIES_FILE).ifPresent(operatorStrategyFilePath -> executionInput.setOperatorStrategies(OperatorStrategyList.readFile(operatorStrategyFilePath).getOperatorStrategies()));
304+
options.getPath(STRATEGIES_FILE).ifPresent(operatorStrategyFilePath -> executionInput.setOperatorStrategies(OperatorStrategyList.read(operatorStrategyFilePath).getOperatorStrategies()));
305305
options.getPath(ACTIONS_FILE).ifPresent(actionFilePath -> executionInput.setActions(ActionList.readJsonFile(actionFilePath).getActions()));
306306

307307
updateInput(options, executionInput);

security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultBuilderTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.powsybl.security;
22

33
import com.powsybl.contingency.Contingency;
4+
import com.powsybl.contingency.ContingencyContext;
45
import com.powsybl.iidm.network.Network;
56
import com.powsybl.iidm.network.VoltageLevel;
67
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
@@ -228,7 +229,7 @@ public void onSecurityAnalysisResult(SecurityAnalysisResult result, SecurityAnal
228229
@Test
229230
public void operatorStrategyResultCreation() {
230231
//Build result with 1 operator strategy
231-
OperatorStrategy operatorStrategy = new OperatorStrategy("strat1", "cont1", new TrueCondition(),
232+
OperatorStrategy operatorStrategy = new OperatorStrategy("strat1", ContingencyContext.specificContingency("cont1"), new TrueCondition(),
232233
List.of("action1", "action2"));
233234

234235
SecurityAnalysisResultBuilder builder = new SecurityAnalysisResultBuilder(new LimitViolationFilter(),

security-analysis/security-analysis-api/src/test/java/com/powsybl/security/converter/ExporterTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ private static SecurityAnalysisResult create() {
7070
List<BusResult> preContingencyBusResults = List.of(new BusResult("voltageLevelId", "busId", 400, 3.14));
7171
List<ThreeWindingsTransformerResult> threeWindingsTransformerResults = List.of(new ThreeWindingsTransformerResult("threeWindingsTransformerId", 1, 2, 3, 1.1, 2.1, 3.1, 1.2, 2.2, 3.2));
7272
List<OperatorStrategyResult> operatorStrategyResults = new ArrayList<>();
73-
operatorStrategyResults.add(new OperatorStrategyResult(new OperatorStrategy("strategyId", "contingency1", new AtLeastOneViolationCondition(Collections.singletonList("violationId1")),
73+
operatorStrategyResults.add(new OperatorStrategyResult(new OperatorStrategy("strategyId", ContingencyContext.specificContingency("contingency1"), new AtLeastOneViolationCondition(Collections.singletonList("violationId1")),
7474
Collections.singletonList("actionId1")), PostContingencyComputationStatus.CONVERGED, new LimitViolationsResult(Collections.emptyList()),
7575
new NetworkResult(Collections.emptyList(), Collections.emptyList(), Collections.emptyList())));
7676
SecurityAnalysisResult result = new SecurityAnalysisResult(preContingencyResult, LoadFlowResult.ComponentResult.Status.CONVERGED,

security-analysis/security-analysis-api/src/test/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlersTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.google.common.jimfs.Jimfs;
1414
import com.powsybl.computation.*;
1515
import com.powsybl.contingency.Contingency;
16+
import com.powsybl.contingency.ContingencyContext;
1617
import com.powsybl.iidm.network.VariantManagerConstants;
1718
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
1819
import com.powsybl.loadflow.LoadFlowResult;
@@ -117,7 +118,7 @@ public void forwardedAfter() throws IOException {
117118
@Test
118119
public void forwardedBeforeWithCompleteInput() throws IOException {
119120
Action action = new SwitchAction("action", "switch", false);
120-
OperatorStrategy strategy = new OperatorStrategy("strat", "cont", new TrueCondition(), List.of("action"));
121+
OperatorStrategy strategy = new OperatorStrategy("strat", ContingencyContext.specificContingency("cont"), new TrueCondition(), List.of("action"));
121122

122123
SecurityAnalysisExecutionInput input = new SecurityAnalysisExecutionInput()
123124
.setParameters(new SecurityAnalysisParameters())

security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/JsonActionAndOperatorStrategyTest.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@
1414
import com.fasterxml.jackson.databind.ObjectMapper;
1515
import com.fasterxml.jackson.databind.module.SimpleModule;
1616
import com.powsybl.commons.test.AbstractConverterTest;
17+
import com.powsybl.commons.test.ComparisonUtils;
18+
import com.powsybl.contingency.ContingencyContext;
1719
import com.powsybl.iidm.network.ThreeWindingsTransformer;
1820
import com.powsybl.security.action.*;
1921
import com.powsybl.security.condition.TrueCondition;
2022
import com.powsybl.security.strategy.OperatorStrategy;
2123
import com.powsybl.security.strategy.OperatorStrategyList;
2224
import org.junit.Test;
2325

24-
import java.io.IOException;
25-
import java.io.InputStream;
26-
import java.io.UncheckedIOException;
26+
import java.io.*;
2727
import java.util.ArrayList;
2828
import java.util.Arrays;
2929
import java.util.Collections;
@@ -56,13 +56,22 @@ public void actionRoundTrip() throws IOException {
5656
roundTripTest(actionList, ActionList::writeJsonFile, ActionList::readJsonFile, "/ActionFileTest.json");
5757
}
5858

59+
@Test
60+
public void operatorStrategyReadV10() throws IOException {
61+
OperatorStrategyList operatorStrategies = OperatorStrategyList.read(getClass().getResourceAsStream("/OperatorStrategyFileTestV1.0.json"));
62+
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
63+
operatorStrategies.write(bos);
64+
ComparisonUtils.compareTxt(getClass().getResourceAsStream("/OperatorStrategyFileTest.json"), new ByteArrayInputStream(bos.toByteArray()));
65+
}
66+
}
67+
5968
@Test
6069
public void operatorStrategyRoundTrip() throws IOException {
6170
List<OperatorStrategy> operatorStrategies = new ArrayList<>();
62-
operatorStrategies.add(new OperatorStrategy("id1", "contingencyId1", new TrueCondition(), Arrays.asList("actionId1", "actionId2", "actionId3")));
63-
operatorStrategies.add(new OperatorStrategy("id1", "contingencyId1", new TrueCondition(), Arrays.asList("actionId1", "actionId2", "actionId3")));
71+
operatorStrategies.add(new OperatorStrategy("id1", ContingencyContext.specificContingency("contingencyId1"), new TrueCondition(), Arrays.asList("actionId1", "actionId2", "actionId3")));
72+
operatorStrategies.add(new OperatorStrategy("id1", ContingencyContext.specificContingency("contingencyId1"), new TrueCondition(), Arrays.asList("actionId1", "actionId2", "actionId3")));
6473
OperatorStrategyList operatorStrategyList = new OperatorStrategyList(operatorStrategies);
65-
roundTripTest(operatorStrategyList, OperatorStrategyList::writeFile, OperatorStrategyList::readFile, "/OperatorStrategyFileTest.json");
74+
roundTripTest(operatorStrategyList, OperatorStrategyList::write, OperatorStrategyList::read, "/OperatorStrategyFileTest.json");
6675
}
6776

6877
@Test

security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/JsonOperatorStrategyExtensionTest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.powsybl.commons.extensions.AbstractExtension;
2222
import com.powsybl.commons.extensions.ExtensionJsonSerializer;
2323
import com.powsybl.commons.json.JsonUtil;
24+
import com.powsybl.contingency.ContingencyContext;
2425
import com.powsybl.security.condition.TrueCondition;
2526
import com.powsybl.security.strategy.OperatorStrategy;
2627
import com.powsybl.security.strategy.OperatorStrategyList;
@@ -37,24 +38,24 @@ public class JsonOperatorStrategyExtensionTest extends AbstractConverterTest {
3738

3839
@Test
3940
public void testWrite() throws IOException {
40-
OperatorStrategy operatorStrategy = new OperatorStrategy("id1", "contingencyId1",
41+
OperatorStrategy operatorStrategy = new OperatorStrategy("id1", ContingencyContext.specificContingency("contingencyId1"),
4142
new TrueCondition(), Arrays.asList("actionId1", "actionId2", "actionId3"));
4243
operatorStrategy.addExtension(DummyExtension.class, new DummyExtension());
4344
OperatorStrategyList operatorStrategyList = new OperatorStrategyList(Collections.singletonList(operatorStrategy));
44-
writeTest(operatorStrategyList, OperatorStrategyList::writeFile, ComparisonUtils::compareTxt,
45+
writeTest(operatorStrategyList, OperatorStrategyList::write, ComparisonUtils::compareTxt,
4546
"/OperatorStrategyFileExtensionsTest.json");
4647
}
4748

4849
@Test
4950
public void testRoundTrip() throws IOException {
50-
OperatorStrategy operatorStrategy = new OperatorStrategy("id1", "contingencyId1",
51+
OperatorStrategy operatorStrategy = new OperatorStrategy("id1", ContingencyContext.specificContingency("contingencyId1"),
5152
new TrueCondition(), Arrays.asList("actionId1", "actionId2", "actionId3"));
5253
operatorStrategy.addExtension(DummyExtension.class, new DummyExtension());
53-
OperatorStrategy operatorStrategy2 = new OperatorStrategy("id2", "contingencyId2",
54+
OperatorStrategy operatorStrategy2 = new OperatorStrategy("id2", ContingencyContext.specificContingency("contingencyId2"),
5455
new TrueCondition(), Collections.singletonList("actionId4"));
5556
operatorStrategy2.addExtension(DummyExtension.class, new DummyExtension());
5657
OperatorStrategyList operatorStrategyList = new OperatorStrategyList(Arrays.asList(operatorStrategy, operatorStrategy2));
57-
roundTripTest(operatorStrategyList, OperatorStrategyList::writeFile, OperatorStrategyList::readFile,
58+
roundTripTest(operatorStrategyList, OperatorStrategyList::write, OperatorStrategyList::read,
5859
"/OperatorStrategyFileExtensionsTest2.json");
5960
}
6061

security-analysis/security-analysis-api/src/test/resources/OperatorStrategyFileExtensionsTest.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
2-
"version" : "1.0",
2+
"version" : "1.1",
33
"operatorStrategies" : [ {
44
"id" : "id1",
5+
"contingencyContextType" : "SPECIFIC",
56
"contingencyId" : "contingencyId1",
67
"condition" : {
78
"type" : "TRUE_CONDITION"

security-analysis/security-analysis-api/src/test/resources/OperatorStrategyFileExtensionsTest2.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
2-
"version" : "1.0",
2+
"version" : "1.1",
33
"operatorStrategies" : [ {
44
"id" : "id1",
5+
"contingencyContextType" : "SPECIFIC",
56
"contingencyId" : "contingencyId1",
67
"condition" : {
78
"type" : "TRUE_CONDITION"
@@ -16,6 +17,7 @@
1617
}
1718
}, {
1819
"id" : "id2",
20+
"contingencyContextType" : "SPECIFIC",
1921
"contingencyId" : "contingencyId2",
2022
"condition" : {
2123
"type" : "TRUE_CONDITION"

security-analysis/security-analysis-api/src/test/resources/OperatorStrategyFileTest.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
{
2-
"version" : "1.0",
2+
"version" : "1.1",
33
"operatorStrategies" : [ {
44
"id" : "id1",
5+
"contingencyContextType" : "SPECIFIC",
56
"contingencyId" : "contingencyId1",
67
"condition" : {
78
"type" : "TRUE_CONDITION"
89
},
910
"actionIds" : [ "actionId1", "actionId2", "actionId3" ]
1011
}, {
1112
"id" : "id1",
13+
"contingencyContextType" : "SPECIFIC",
1214
"contingencyId" : "contingencyId1",
1315
"condition" : {
1416
"type" : "TRUE_CONDITION"
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"version" : "1.0",
3+
"operatorStrategies" : [ {
4+
"id" : "id1",
5+
"contingencyId" : "contingencyId1",
6+
"condition" : {
7+
"type" : "TRUE_CONDITION"
8+
},
9+
"actionIds" : [ "actionId1", "actionId2", "actionId3" ]
10+
}, {
11+
"id" : "id1",
12+
"contingencyId" : "contingencyId1",
13+
"condition" : {
14+
"type" : "TRUE_CONDITION"
15+
},
16+
"actionIds" : [ "actionId1", "actionId2", "actionId3" ]
17+
} ]
18+
}

security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisResult.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@
155155
"operatorStrategyResults" : [ {
156156
"operatorStrategy" : {
157157
"id" : "strategyId",
158+
"contingencyContextType" : "SPECIFIC",
158159
"contingencyId" : "contingency1",
159160
"condition" : {
160161
"type" : "AT_LEAST_ONE_VIOLATION",

0 commit comments

Comments
 (0)