diff --git a/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/SensitivityAnalysisParameters.java b/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/SensitivityAnalysisParameters.java index 485b6c43226..683517a2c3c 100644 --- a/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/SensitivityAnalysisParameters.java +++ b/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/SensitivityAnalysisParameters.java @@ -21,7 +21,17 @@ */ public class SensitivityAnalysisParameters extends AbstractExtendable { - public static final String VERSION = "1.0"; + public static final String VERSION = "1.1"; + + static final double FLOW_FLOW_SENSITIVITY_VALUE_THRESHOLD_DEFAULT_VALUE = 0.0; + static final double VOLTAGE_VOLTAGE_SENSITIVITY_VALUE_THRESHOLD_DEFAULT_VALUE = 0.0; + static final double FLOW_VOLTAGE_SENSITIVITY_VALUE_THRESHOLD_DEFAULT_VALUE = 0.0; + static final double ANGLE_FLOW_SENSITIVITY_VALUE_THRESHOLD_DEFAULT_VALUE = 0.0; + + private double flowFlowSensitivityValueThreshold = FLOW_FLOW_SENSITIVITY_VALUE_THRESHOLD_DEFAULT_VALUE; + private double voltageVoltageSensitivityValueThreshold = VOLTAGE_VOLTAGE_SENSITIVITY_VALUE_THRESHOLD_DEFAULT_VALUE; + private double flowVoltageSensitivityValueThreshold = FLOW_VOLTAGE_SENSITIVITY_VALUE_THRESHOLD_DEFAULT_VALUE; + private double angleFlowSensitivityValueThreshold = ANGLE_FLOW_SENSITIVITY_VALUE_THRESHOLD_DEFAULT_VALUE; private LoadFlowParameters loadFlowParameters = new LoadFlowParameters(); @@ -40,7 +50,6 @@ public static SensitivityAnalysisParameters load(PlatformConfig platformConfig) SensitivityAnalysisParameters parameters = new SensitivityAnalysisParameters(); parameters.readExtensions(platformConfig); - parameters.setLoadFlowParameters(LoadFlowParameters.load(platformConfig)); return parameters; @@ -61,4 +70,66 @@ public SensitivityAnalysisParameters setLoadFlowParameters(LoadFlowParameters lo this.loadFlowParameters = Objects.requireNonNull(loadFlowParameters); return this; } + + public SensitivityAnalysisParameters setFlowFlowSensitivityValueThreshold(double threshold) { + flowFlowSensitivityValueThreshold = threshold; + return this; + } + + /** + * FlowFlowSensitivityValueThreshold is the threshold under which sensitivity values having + * variable type among INJECTION_ACTIVE_POWER, INJECTION_REACTIVE_POWER and HVDC_LINE_ACTIVE_POWER + * and function type among BRANCH_ACTIVE_POWER_1/2/3, BRANCH_REACTIVE_POWER_1/2/3 and BRANCH_CURRENT_1/2/3 + * will be filtered from the analysis results. + * @return The threshold + */ + public double getFlowFlowSensitivityValueThreshold() { + return flowFlowSensitivityValueThreshold; + } + + public SensitivityAnalysisParameters setVoltageVoltageSensitivityValueThreshold(double threshold) { + voltageVoltageSensitivityValueThreshold = threshold; + return this; + } + + /** + * VoltageVoltageSensitivityValueThreshold is the threshold under which sensitivity values having + * variable type BUS_TARGET_VOLTAGE and function type BUS_VOLTAGE will be filtered from the analysis results. + * @return The threshold + */ + public double getVoltageVoltageSensitivityValueThreshold() { + return voltageVoltageSensitivityValueThreshold; + } + + public SensitivityAnalysisParameters setFlowVoltageSensitivityValueThreshold(double threshold) { + flowVoltageSensitivityValueThreshold = threshold; + return this; + } + + /** + * FlowVoltageSensitivityValueThreshold is the threshold under which sensitivity values having + * variable type among INJECTION_REACTIVE_POWER and BUS_TARGET_VOLTAGE + * and function type among BUS_VOLTAGE, BRANCH_REACTIVE_POWER_1/2/3 and BRANCH_CURRENT_1/2/3 + * will be filtered from the analysis results. + * @return The threshold + */ + public double getFlowVoltageSensitivityValueThreshold() { + return flowVoltageSensitivityValueThreshold; + } + + public SensitivityAnalysisParameters setAngleFlowSensitivityValueThreshold(double threshold) { + angleFlowSensitivityValueThreshold = threshold; + return this; + } + + /** + * AngleFlowSensitivityValueThreshold is the threshold under which sensitivity values having + * variable type among TRANSFORMER_PHASE and TRANSFORMER_PHASE_1/2/3 + * and function type among BRANCH_ACTIVE_POWER_1/2/3, BRANCH_REACTIVE_POWER_1/2/3 and BRANCH_CURRENT_1/2/3 + * will be filtered from the analysis results. + * @return The threshold + */ + public double getAngleFlowSensitivityValueThreshold() { + return angleFlowSensitivityValueThreshold; + } } diff --git a/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/json/JsonSensitivityAnalysisParameters.java b/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/json/JsonSensitivityAnalysisParameters.java index a42d9e00a31..168007db2aa 100644 --- a/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/json/JsonSensitivityAnalysisParameters.java +++ b/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/json/JsonSensitivityAnalysisParameters.java @@ -11,10 +11,17 @@ import com.powsybl.commons.extensions.ExtensionProvider; import com.powsybl.commons.json.JsonUtil; import com.powsybl.commons.util.ServiceLoaderCache; +import com.powsybl.sensitivity.SensitivityAnalysisParameters; import com.powsybl.sensitivity.SensitivityAnalysisProvider; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -33,6 +40,41 @@ public static Map getExtensionSerializers() { private JsonSensitivityAnalysisParameters() { } + public static SensitivityAnalysisParameters read(Path jsonFile) { + return update(new SensitivityAnalysisParameters(), jsonFile); + } + + /** + * Reads parameters from a JSON file (will NOT rely on platform config). + */ + public static SensitivityAnalysisParameters read(InputStream jsonStream) { + return update(new SensitivityAnalysisParameters(), jsonStream); + } + + /** + * Updates parameters by reading the content of a JSON file. + */ + public static SensitivityAnalysisParameters update(SensitivityAnalysisParameters parameters, Path jsonFile) { + Objects.requireNonNull(jsonFile); + try (InputStream is = Files.newInputStream(jsonFile)) { + return update(parameters, is); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * Updates parameters by reading the content of a JSON stream. + */ + public static SensitivityAnalysisParameters update(SensitivityAnalysisParameters parameters, InputStream jsonStream) { + try { + ObjectMapper objectMapper = createObjectMapper(); + return objectMapper.readerForUpdating(parameters).readValue(jsonStream); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + public static ObjectMapper createObjectMapper() { return JsonUtil.createObjectMapper() .registerModule(new SensitivityJsonModule()); diff --git a/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/json/SensitivityAnalysisParametersDeserializer.java b/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/json/SensitivityAnalysisParametersDeserializer.java index b82526f4fe7..b7c2ec0cd91 100644 --- a/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/json/SensitivityAnalysisParametersDeserializer.java +++ b/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/json/SensitivityAnalysisParametersDeserializer.java @@ -26,6 +26,8 @@ */ public class SensitivityAnalysisParametersDeserializer extends StdDeserializer { + private static final String CONTEXT_NAME = "SensitivityAnalysisParameters"; + SensitivityAnalysisParametersDeserializer() { super(SensitivityAnalysisParameters.class); } @@ -39,11 +41,13 @@ public SensitivityAnalysisParameters deserialize(JsonParser parser, Deserializat public SensitivityAnalysisParameters deserialize(JsonParser parser, DeserializationContext deserializationContext, SensitivityAnalysisParameters parameters) throws IOException { List> extensions = Collections.emptyList(); + String version = null; while (parser.nextToken() != JsonToken.END_OBJECT) { switch (parser.getCurrentName()) { case "version": parser.nextToken(); + version = parser.getValueAsString(); break; case "load-flow-parameters": @@ -51,6 +55,33 @@ public SensitivityAnalysisParameters deserialize(JsonParser parser, Deserializat JsonLoadFlowParameters.deserialize(parser, deserializationContext, parameters.getLoadFlowParameters()); break; + case "flow-flow-sensitivity-value-threshold": + JsonUtil.assertGreaterOrEqualThanReferenceVersion(CONTEXT_NAME, parser.getCurrentName(), version, "1.1"); + parser.nextToken(); + parameters.setFlowFlowSensitivityValueThreshold(parser.readValueAs(Double.class)); + break; + + case "voltage-voltage-sensitivity-value-threshold": + JsonUtil.assertGreaterOrEqualThanReferenceVersion(CONTEXT_NAME, parser.getCurrentName(), version, "1.1"); + + parser.nextToken(); + parameters.setVoltageVoltageSensitivityValueThreshold(parser.readValueAs(Double.class)); + break; + + case "flow-voltage-sensitivity-value-threshold": + JsonUtil.assertGreaterOrEqualThanReferenceVersion(CONTEXT_NAME, parser.getCurrentName(), version, "1.1"); + + parser.nextToken(); + parameters.setFlowVoltageSensitivityValueThreshold(parser.readValueAs(Double.class)); + break; + + case "angle-flow-sensitivity-value-threshold": + JsonUtil.assertGreaterOrEqualThanReferenceVersion(CONTEXT_NAME, parser.getCurrentName(), version, "1.1"); + + parser.nextToken(); + parameters.setAngleFlowSensitivityValueThreshold(parser.readValueAs(Double.class)); + break; + case "extensions": parser.nextToken(); extensions = JsonUtil.updateExtensions(parser, deserializationContext, JsonSensitivityAnalysisParameters.getExtensionSerializers()::get, parameters); diff --git a/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/json/SensitivityAnalysisParametersSerializer.java b/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/json/SensitivityAnalysisParametersSerializer.java index c256715e9d2..49c054da5b3 100644 --- a/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/json/SensitivityAnalysisParametersSerializer.java +++ b/sensitivity-analysis-api/src/main/java/com/powsybl/sensitivity/json/SensitivityAnalysisParametersSerializer.java @@ -36,6 +36,11 @@ public void serialize(SensitivityAnalysisParameters parameters, JsonGenerator js jsonGenerator.writeFieldName("load-flow-parameters"); JsonLoadFlowParameters.serialize(parameters.getLoadFlowParameters(), jsonGenerator, serializerProvider); + jsonGenerator.writeNumberField("flow-flow-sensitivity-value-threshold", parameters.getFlowFlowSensitivityValueThreshold()); + jsonGenerator.writeNumberField("voltage-voltage-sensitivity-value-threshold", parameters.getVoltageVoltageSensitivityValueThreshold()); + jsonGenerator.writeNumberField("flow-voltage-sensitivity-value-threshold", parameters.getFlowVoltageSensitivityValueThreshold()); + jsonGenerator.writeNumberField("angle-flow-sensitivity-value-threshold", parameters.getAngleFlowSensitivityValueThreshold()); + JsonUtil.writeExtensions(parameters, jsonGenerator, serializerProvider, JsonSensitivityAnalysisParameters.getExtensionSerializers()::get); jsonGenerator.writeEndObject(); diff --git a/sensitivity-analysis-api/src/test/java/com/powsybl/sensitivity/SensitivityAnalysisParametersTest.java b/sensitivity-analysis-api/src/test/java/com/powsybl/sensitivity/SensitivityAnalysisParametersTest.java index 894a6e74200..e9a45ec889d 100644 --- a/sensitivity-analysis-api/src/test/java/com/powsybl/sensitivity/SensitivityAnalysisParametersTest.java +++ b/sensitivity-analysis-api/src/test/java/com/powsybl/sensitivity/SensitivityAnalysisParametersTest.java @@ -13,6 +13,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.SerializerProvider; +import com.powsybl.commons.PowsyblException; import com.powsybl.commons.extensions.AbstractExtension; import com.powsybl.commons.extensions.ExtensionJsonSerializer; import com.powsybl.commons.json.JsonUtil; @@ -225,4 +226,38 @@ void testSensitivityAnalysisResultContingencyStatusSerializer() throws IOExcepti roundTripTest(value, (value2, jsonFile) -> JsonUtil.writeJson(jsonFile, value, objectMapper), jsonFile -> JsonUtil.readJson(jsonFile, SensitivityAnalysisResult.SensitivityContingencyStatus.class, objectMapper), "/contingencyStatusRef.json"); } + + @Test + void updateThresholdParameters() { + SensitivityAnalysisParameters parameters = new SensitivityAnalysisParameters(); + + assertEquals(0.0, parameters.getFlowFlowSensitivityValueThreshold(), 1e-3); + assertEquals(0.0, parameters.getAngleFlowSensitivityValueThreshold(), 1e-3); + assertEquals(0.0, parameters.getFlowVoltageSensitivityValueThreshold(), 1e-3); + assertEquals(0.0, parameters.getVoltageVoltageSensitivityValueThreshold(), 1e-3); + + parameters.setFlowFlowSensitivityValueThreshold(0.1) + .setAngleFlowSensitivityValueThreshold(0.2) + .setFlowVoltageSensitivityValueThreshold(0.3) + .setVoltageVoltageSensitivityValueThreshold(0.4); + + assertEquals(0.1, parameters.getFlowFlowSensitivityValueThreshold(), 1e-3); + assertEquals(0.2, parameters.getAngleFlowSensitivityValueThreshold(), 1e-3); + assertEquals(0.3, parameters.getFlowVoltageSensitivityValueThreshold(), 1e-3); + assertEquals(0.4, parameters.getVoltageVoltageSensitivityValueThreshold(), 1e-3); + } + + @Test + void readJsonVersion10() { + SensitivityAnalysisParameters parameters = JsonSensitivityAnalysisParameters + .read(getClass().getResourceAsStream("/SensitivityAnalysisParametersV1.0.json")); + assertEquals(0.0, parameters.getFlowFlowSensitivityValueThreshold(), 0.0001); + } + + @Test + void readJsonVersion10Invalid() { + assertThrows(PowsyblException.class, () -> JsonSensitivityAnalysisParameters + .read(getClass().getResourceAsStream("/SensitivityAnalysisParametersV1.0Invalid.json")), + "SensitivityAnalysisParameters. flow-flow-sensitivity-value-threshold is not valid for version 1.0. Version should be >= 1.1"); + } } diff --git a/sensitivity-analysis-api/src/test/resources/SensitivityAnalysisParameters.json b/sensitivity-analysis-api/src/test/resources/SensitivityAnalysisParameters.json index f164664f960..4510c1cbfda 100644 --- a/sensitivity-analysis-api/src/test/resources/SensitivityAnalysisParameters.json +++ b/sensitivity-analysis-api/src/test/resources/SensitivityAnalysisParameters.json @@ -1,5 +1,5 @@ { - "version" : "1.0", + "version" : "1.1", "load-flow-parameters" : { "version" : "1.9", "voltageInitMode" : "UNIFORM_VALUES", @@ -18,5 +18,9 @@ "connectedComponentMode" : "MAIN", "hvdcAcEmulation" : true, "dcPowerFactor" : 1.0 - } + }, + "flow-flow-sensitivity-value-threshold" : 0.0, + "voltage-voltage-sensitivity-value-threshold" : 0.0, + "flow-voltage-sensitivity-value-threshold" : 0.0, + "angle-flow-sensitivity-value-threshold" : 0.0 } \ No newline at end of file diff --git a/sensitivity-analysis-api/src/test/resources/SensitivityAnalysisParametersV1.0.json b/sensitivity-analysis-api/src/test/resources/SensitivityAnalysisParametersV1.0.json new file mode 100644 index 00000000000..f164664f960 --- /dev/null +++ b/sensitivity-analysis-api/src/test/resources/SensitivityAnalysisParametersV1.0.json @@ -0,0 +1,22 @@ +{ + "version" : "1.0", + "load-flow-parameters" : { + "version" : "1.9", + "voltageInitMode" : "UNIFORM_VALUES", + "transformerVoltageControlOn" : false, + "phaseShifterRegulationOn" : false, + "useReactiveLimits" : true, + "twtSplitShuntAdmittance" : false, + "shuntCompensatorVoltageControlOn" : false, + "readSlackBus" : true, + "writeSlackBus" : false, + "dc" : false, + "distributedSlack" : true, + "balanceType" : "PROPORTIONAL_TO_GENERATION_P_MAX", + "dcUseTransformerRatio" : true, + "countriesToBalance" : [ ], + "connectedComponentMode" : "MAIN", + "hvdcAcEmulation" : true, + "dcPowerFactor" : 1.0 + } +} \ No newline at end of file diff --git a/sensitivity-analysis-api/src/test/resources/SensitivityAnalysisParametersV1.0Invalid.json b/sensitivity-analysis-api/src/test/resources/SensitivityAnalysisParametersV1.0Invalid.json new file mode 100644 index 00000000000..4e953df5b6f --- /dev/null +++ b/sensitivity-analysis-api/src/test/resources/SensitivityAnalysisParametersV1.0Invalid.json @@ -0,0 +1,23 @@ +{ + "version" : "1.0", + "load-flow-parameters" : { + "version" : "1.9", + "voltageInitMode" : "UNIFORM_VALUES", + "transformerVoltageControlOn" : false, + "phaseShifterRegulationOn" : false, + "useReactiveLimits" : true, + "twtSplitShuntAdmittance" : false, + "shuntCompensatorVoltageControlOn" : false, + "readSlackBus" : true, + "writeSlackBus" : false, + "dc" : false, + "distributedSlack" : true, + "balanceType" : "PROPORTIONAL_TO_GENERATION_P_MAX", + "dcUseTransformerRatio" : true, + "countriesToBalance" : [ ], + "connectedComponentMode" : "MAIN", + "hvdcAcEmulation" : true, + "dcPowerFactor" : 1.0 + }, + "flow-flow-sensitivity-value-threshold" : 0.0 +} \ No newline at end of file diff --git a/sensitivity-analysis-api/src/test/resources/SensitivityAnalysisParametersWithExtension.json b/sensitivity-analysis-api/src/test/resources/SensitivityAnalysisParametersWithExtension.json index 4d044662ce0..698688bab21 100644 --- a/sensitivity-analysis-api/src/test/resources/SensitivityAnalysisParametersWithExtension.json +++ b/sensitivity-analysis-api/src/test/resources/SensitivityAnalysisParametersWithExtension.json @@ -1,5 +1,5 @@ { - "version" : "1.0", + "version" : "1.1", "load-flow-parameters" : { "version" : "1.9", "voltageInitMode" : "UNIFORM_VALUES", @@ -19,6 +19,10 @@ "hvdcAcEmulation" : true, "dcPowerFactor" : 1.0 }, + "flow-flow-sensitivity-value-threshold" : 0.0, + "voltage-voltage-sensitivity-value-threshold" : 0.0, + "flow-voltage-sensitivity-value-threshold" : 0.0, + "angle-flow-sensitivity-value-threshold" : 0.0, "extensions" : { "dummy-extension" : { } }