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

Use contingency context in operator strategies #2429

Merged
merged 4 commits into from
Jan 12, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ private static void addOperatorStrategyFile(SecurityAnalysisCommandOptions optio
options.strategiesFile(path);
LOGGER.debug("Writing operator strategies to file {}", path);
new OperatorStrategyList(operatorStrategies)
.writeFile(path);
.write(path);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import com.powsybl.commons.extensions.ExtensionJsonSerializer;
import com.powsybl.commons.extensions.ExtensionProviders;
import com.powsybl.commons.json.JsonUtil;
import com.powsybl.contingency.ContingencyContext;
import com.powsybl.contingency.ContingencyContextType;
import com.powsybl.security.condition.Condition;
import com.powsybl.security.strategy.OperatorStrategy;

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

private static class ParsingContext {
String id;
ContingencyContextType contingencyContextType;
String contingencyId;
Condition condition;
List<String> actionIds;
Expand All @@ -52,6 +55,9 @@ public OperatorStrategy deserialize(JsonParser parser, DeserializationContext de
parser.nextToken();
context.id = parser.getValueAsString();
return true;
case "contingencyContextType":
context.contingencyContextType = ContingencyContextType.valueOf(parser.nextTextValue());
return true;
case "contingencyId":
parser.nextToken();
context.contingencyId = parser.getValueAsString();
Expand All @@ -73,7 +79,12 @@ public OperatorStrategy deserialize(JsonParser parser, DeserializationContext de
return false;
}
});
OperatorStrategy operatorStrategy = new OperatorStrategy(context.id, context.contingencyId, context.condition, context.actionIds);
// First version of the operator strategy only allows association to one contingency. Next versions use contingency
// context. So, for backward compatibility purposes, we consider that if contingencyContextType is null, we have
// a specific contingency context type.
ContingencyContext contingencyContext = new ContingencyContext(context.contingencyId,
context.contingencyContextType != null ? context.contingencyContextType : ContingencyContextType.SPECIFIC);
jeandemanged marked this conversation as resolved.
Show resolved Hide resolved
OperatorStrategy operatorStrategy = new OperatorStrategy(context.id, contingencyContext, context.condition, context.actionIds);
SUPPLIER.get().addExtensions(operatorStrategy, context.extensions);
return operatorStrategy;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ public OperatorStrategyList deserialize(JsonParser parser, DeserializationContex
return false;
}
});
if (context.version == null || !context.version.equals(OperatorStrategyList.VERSION)) {
throw new JsonMappingException(parser, "version is missing or not equal to 1.0");
if (context.version == null) {
throw new JsonMappingException(parser, "version is missing");
jeandemanged marked this conversation as resolved.
Show resolved Hide resolved
}
return new OperatorStrategyList(context.operatorStrategies);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.powsybl.commons.json.JsonUtil;
import com.powsybl.contingency.ContingencyContext;
import com.powsybl.security.strategy.OperatorStrategy;

import java.io.IOException;
Expand All @@ -27,7 +28,11 @@ public OperatorStrategySerializer() {
public void serialize(OperatorStrategy operatorStrategy, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("id", operatorStrategy.getId());
jsonGenerator.writeStringField("contingencyId", operatorStrategy.getContingencyId());
ContingencyContext contingencyContext = operatorStrategy.getContingencyContext();
jsonGenerator.writeStringField("contingencyContextType", contingencyContext.getContextType().name());
if (contingencyContext.getContingencyId() != null) {
jsonGenerator.writeStringField("contingencyId", contingencyContext.getContingencyId());
}
jsonGenerator.writeObjectField("condition", operatorStrategy.getCondition());
jsonGenerator.writeObjectField("actionIds", operatorStrategy.getActionIds());
JsonUtil.writeExtensions(operatorStrategy, jsonGenerator, serializerProvider);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import com.google.common.collect.ImmutableList;
import com.powsybl.commons.extensions.AbstractExtendable;
import com.powsybl.contingency.ContingencyContext;
import com.powsybl.security.condition.Condition;

import java.util.List;
Expand All @@ -26,13 +27,13 @@
*/
public class OperatorStrategy extends AbstractExtendable<OperatorStrategy> {
private final String id;
private final String contingencyId;
private final ContingencyContext contingencyContext;
private final Condition condition; // under which circumstances do I want to trigger my action
private final List<String> actionIds;

public OperatorStrategy(String id, String contingencyId, Condition condition, List<String> actionIds) {
public OperatorStrategy(String id, ContingencyContext contingencyContext, Condition condition, List<String> actionIds) {
this.id = Objects.requireNonNull(id);
this.contingencyId = Objects.requireNonNull(contingencyId);
this.contingencyContext = Objects.requireNonNull(contingencyContext);
this.condition = Objects.requireNonNull(condition);
this.actionIds = ImmutableList.copyOf(Objects.requireNonNull(actionIds));
}
Expand All @@ -47,8 +48,8 @@ public String getId() {
/**
* The contingency which this strategy applies to.
*/
public String getContingencyId() {
return contingencyId;
public ContingencyContext getContingencyContext() {
return contingencyContext;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
*/
public class OperatorStrategyList {
private final List<OperatorStrategy> operatorStrategies;
public static final String VERSION = "1.0";
public static final String VERSION = "1.1";

public OperatorStrategyList(List<OperatorStrategy> operatorStrategies) {
this.operatorStrategies = ImmutableList.copyOf(Objects.requireNonNull(operatorStrategies));
Expand All @@ -39,15 +39,15 @@ public List<OperatorStrategy> getOperatorStrategies() {
return operatorStrategies;
}

public static OperatorStrategyList readFile(Path jsonFile) {
public static OperatorStrategyList read(Path jsonFile) {
try (InputStream is = Files.newInputStream(jsonFile)) {
return readOutputStream(is);
return read(is);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

public static OperatorStrategyList readOutputStream(InputStream is) {
public static OperatorStrategyList read(InputStream is) {
Objects.requireNonNull(is);

ObjectMapper objectMapper = JsonUtil.createObjectMapper()
Expand All @@ -62,10 +62,10 @@ public static OperatorStrategyList readOutputStream(InputStream is) {
/**
* Writes action list as JSON to a file.
*/
public void writeFile(Path jsonFile) {
public void write(Path jsonFile) {
Objects.requireNonNull(jsonFile);
try (OutputStream outputStream = Files.newOutputStream(jsonFile)) {
writeOutputStream(outputStream);
write(outputStream);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Expand All @@ -74,7 +74,7 @@ public void writeFile(Path jsonFile) {
/**
* Writes action list as JSON to an output stream.
*/
public void writeOutputStream(OutputStream outputStream) {
public void write(OutputStream outputStream) {
try {
ObjectMapper objectMapper = createObjectMapper();
ObjectWriter writer = objectMapper.writerWithDefaultPrettyPrinter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ void run(CommandLine line, ToolRunningContext context,
.setParameters(parametersLoader.get());

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

updateInput(options, executionInput);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.powsybl.security;

import com.powsybl.contingency.Contingency;
import com.powsybl.contingency.ContingencyContext;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.VoltageLevel;
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
Expand Down Expand Up @@ -228,7 +229,7 @@ public void onSecurityAnalysisResult(SecurityAnalysisResult result, SecurityAnal
@Test
public void operatorStrategyResultCreation() {
//Build result with 1 operator strategy
OperatorStrategy operatorStrategy = new OperatorStrategy("strat1", "cont1", new TrueCondition(),
OperatorStrategy operatorStrategy = new OperatorStrategy("strat1", ContingencyContext.specificContingency("cont1"), new TrueCondition(),
List.of("action1", "action2"));

SecurityAnalysisResultBuilder builder = new SecurityAnalysisResultBuilder(new LimitViolationFilter(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ private static SecurityAnalysisResult create() {
List<BusResult> preContingencyBusResults = List.of(new BusResult("voltageLevelId", "busId", 400, 3.14));
List<ThreeWindingsTransformerResult> threeWindingsTransformerResults = List.of(new ThreeWindingsTransformerResult("threeWindingsTransformerId", 1, 2, 3, 1.1, 2.1, 3.1, 1.2, 2.2, 3.2));
List<OperatorStrategyResult> operatorStrategyResults = new ArrayList<>();
operatorStrategyResults.add(new OperatorStrategyResult(new OperatorStrategy("strategyId", "contingency1", new AtLeastOneViolationCondition(Collections.singletonList("violationId1")),
operatorStrategyResults.add(new OperatorStrategyResult(new OperatorStrategy("strategyId", ContingencyContext.specificContingency("contingency1"), new AtLeastOneViolationCondition(Collections.singletonList("violationId1")),
Collections.singletonList("actionId1")), PostContingencyComputationStatus.CONVERGED, new LimitViolationsResult(Collections.emptyList()),
new NetworkResult(Collections.emptyList(), Collections.emptyList(), Collections.emptyList())));
SecurityAnalysisResult result = new SecurityAnalysisResult(preContingencyResult, LoadFlowResult.ComponentResult.Status.CONVERGED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.google.common.jimfs.Jimfs;
import com.powsybl.computation.*;
import com.powsybl.contingency.Contingency;
import com.powsybl.contingency.ContingencyContext;
import com.powsybl.iidm.network.VariantManagerConstants;
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
import com.powsybl.loadflow.LoadFlowResult;
Expand Down Expand Up @@ -117,7 +118,7 @@ public void forwardedAfter() throws IOException {
@Test
public void forwardedBeforeWithCompleteInput() throws IOException {
Action action = new SwitchAction("action", "switch", false);
OperatorStrategy strategy = new OperatorStrategy("strat", "cont", new TrueCondition(), List.of("action"));
OperatorStrategy strategy = new OperatorStrategy("strat", ContingencyContext.specificContingency("cont"), new TrueCondition(), List.of("action"));

SecurityAnalysisExecutionInput input = new SecurityAnalysisExecutionInput()
.setParameters(new SecurityAnalysisParameters())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.powsybl.commons.test.AbstractConverterTest;
import com.powsybl.commons.test.ComparisonUtils;
import com.powsybl.contingency.ContingencyContext;
import com.powsybl.iidm.network.ThreeWindingsTransformer;
import com.powsybl.security.action.*;
import com.powsybl.security.condition.TrueCondition;
import com.powsybl.security.strategy.OperatorStrategy;
import com.powsybl.security.strategy.OperatorStrategyList;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -56,13 +56,22 @@ public void actionRoundTrip() throws IOException {
roundTripTest(actionList, ActionList::writeJsonFile, ActionList::readJsonFile, "/ActionFileTest.json");
}

@Test
public void operatorStrategyReadV10() throws IOException {
OperatorStrategyList operatorStrategies = OperatorStrategyList.read(getClass().getResourceAsStream("/OperatorStrategyFileTestV1.0.json"));
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
operatorStrategies.write(bos);
ComparisonUtils.compareTxt(getClass().getResourceAsStream("/OperatorStrategyFileTest.json"), new ByteArrayInputStream(bos.toByteArray()));
}
}

@Test
public void operatorStrategyRoundTrip() throws IOException {
List<OperatorStrategy> operatorStrategies = new ArrayList<>();
operatorStrategies.add(new OperatorStrategy("id1", "contingencyId1", new TrueCondition(), Arrays.asList("actionId1", "actionId2", "actionId3")));
operatorStrategies.add(new OperatorStrategy("id1", "contingencyId1", new TrueCondition(), Arrays.asList("actionId1", "actionId2", "actionId3")));
operatorStrategies.add(new OperatorStrategy("id1", ContingencyContext.specificContingency("contingencyId1"), new TrueCondition(), Arrays.asList("actionId1", "actionId2", "actionId3")));
operatorStrategies.add(new OperatorStrategy("id1", ContingencyContext.specificContingency("contingencyId1"), new TrueCondition(), Arrays.asList("actionId1", "actionId2", "actionId3")));
OperatorStrategyList operatorStrategyList = new OperatorStrategyList(operatorStrategies);
roundTripTest(operatorStrategyList, OperatorStrategyList::writeFile, OperatorStrategyList::readFile, "/OperatorStrategyFileTest.json");
roundTripTest(operatorStrategyList, OperatorStrategyList::write, OperatorStrategyList::read, "/OperatorStrategyFileTest.json");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.powsybl.commons.extensions.AbstractExtension;
import com.powsybl.commons.extensions.ExtensionJsonSerializer;
import com.powsybl.commons.json.JsonUtil;
import com.powsybl.contingency.ContingencyContext;
import com.powsybl.security.condition.TrueCondition;
import com.powsybl.security.strategy.OperatorStrategy;
import com.powsybl.security.strategy.OperatorStrategyList;
Expand All @@ -37,24 +38,24 @@ public class JsonOperatorStrategyExtensionTest extends AbstractConverterTest {

@Test
public void testWrite() throws IOException {
OperatorStrategy operatorStrategy = new OperatorStrategy("id1", "contingencyId1",
OperatorStrategy operatorStrategy = new OperatorStrategy("id1", ContingencyContext.specificContingency("contingencyId1"),
new TrueCondition(), Arrays.asList("actionId1", "actionId2", "actionId3"));
operatorStrategy.addExtension(DummyExtension.class, new DummyExtension());
OperatorStrategyList operatorStrategyList = new OperatorStrategyList(Collections.singletonList(operatorStrategy));
writeTest(operatorStrategyList, OperatorStrategyList::writeFile, ComparisonUtils::compareTxt,
writeTest(operatorStrategyList, OperatorStrategyList::write, ComparisonUtils::compareTxt,
"/OperatorStrategyFileExtensionsTest.json");
}

@Test
public void testRoundTrip() throws IOException {
OperatorStrategy operatorStrategy = new OperatorStrategy("id1", "contingencyId1",
OperatorStrategy operatorStrategy = new OperatorStrategy("id1", ContingencyContext.specificContingency("contingencyId1"),
new TrueCondition(), Arrays.asList("actionId1", "actionId2", "actionId3"));
operatorStrategy.addExtension(DummyExtension.class, new DummyExtension());
OperatorStrategy operatorStrategy2 = new OperatorStrategy("id2", "contingencyId2",
OperatorStrategy operatorStrategy2 = new OperatorStrategy("id2", ContingencyContext.specificContingency("contingencyId2"),
new TrueCondition(), Collections.singletonList("actionId4"));
operatorStrategy2.addExtension(DummyExtension.class, new DummyExtension());
OperatorStrategyList operatorStrategyList = new OperatorStrategyList(Arrays.asList(operatorStrategy, operatorStrategy2));
roundTripTest(operatorStrategyList, OperatorStrategyList::writeFile, OperatorStrategyList::readFile,
roundTripTest(operatorStrategyList, OperatorStrategyList::write, OperatorStrategyList::read,
"/OperatorStrategyFileExtensionsTest2.json");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"version" : "1.0",
"version" : "1.1",
"operatorStrategies" : [ {
"id" : "id1",
"contingencyContextType" : "SPECIFIC",
"contingencyId" : "contingencyId1",
"condition" : {
"type" : "TRUE_CONDITION"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"version" : "1.0",
"version" : "1.1",
"operatorStrategies" : [ {
"id" : "id1",
"contingencyContextType" : "SPECIFIC",
"contingencyId" : "contingencyId1",
"condition" : {
"type" : "TRUE_CONDITION"
Expand All @@ -16,6 +17,7 @@
}
}, {
"id" : "id2",
"contingencyContextType" : "SPECIFIC",
"contingencyId" : "contingencyId2",
"condition" : {
"type" : "TRUE_CONDITION"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
{
"version" : "1.0",
"version" : "1.1",
"operatorStrategies" : [ {
"id" : "id1",
"contingencyContextType" : "SPECIFIC",
"contingencyId" : "contingencyId1",
"condition" : {
"type" : "TRUE_CONDITION"
},
"actionIds" : [ "actionId1", "actionId2", "actionId3" ]
}, {
"id" : "id1",
"contingencyContextType" : "SPECIFIC",
"contingencyId" : "contingencyId1",
"condition" : {
"type" : "TRUE_CONDITION"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"version" : "1.0",
"operatorStrategies" : [ {
"id" : "id1",
"contingencyId" : "contingencyId1",
"condition" : {
"type" : "TRUE_CONDITION"
},
"actionIds" : [ "actionId1", "actionId2", "actionId3" ]
}, {
"id" : "id1",
"contingencyId" : "contingencyId1",
"condition" : {
"type" : "TRUE_CONDITION"
},
"actionIds" : [ "actionId1", "actionId2", "actionId3" ]
} ]
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@
"operatorStrategyResults" : [ {
"operatorStrategy" : {
"id" : "strategyId",
"contingencyContextType" : "SPECIFIC",
"contingencyId" : "contingency1",
"condition" : {
"type" : "AT_LEAST_ONE_VIOLATION",
Expand Down
Loading