From 94fe8c0ea1276b98a5fd9dc827663563561a592e Mon Sep 17 00:00:00 2001 From: EtienneLt <32468651+EtienneLt@users.noreply.github.com> Date: Tue, 22 Aug 2023 11:47:46 +0200 Subject: [PATCH] Support of static var compensator action (#2654) * add static var compensator action * review * remove regulating Terminal * Fix typo. * Fix again. --------- Signed-off-by: Etienne LESOT Signed-off-by: Anne Tilloy Co-authored-by: Anne Tilloy <48123713+annetill@users.noreply.github.com> Co-authored-by: Anne Tilloy --- .../action/StaticVarCompensatorAction.java | 63 ++++++++++++++ .../StaticVarCompensatorActionBuilder.java | 51 ++++++++++++ .../json/SecurityAnalysisJsonModule.java | 5 +- ...taticVarCompensatorActionDeserializer.java | 83 +++++++++++++++++++ .../StaticVarCompensatorActionSerializer.java | 57 +++++++++++++ .../JsonActionAndOperatorStrategyTest.java | 7 ++ .../src/test/resources/ActionFileTest.json | 12 +++ .../test/resources/ActionFileTestV1.0.json | 12 +++ 8 files changed, 287 insertions(+), 3 deletions(-) create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/action/StaticVarCompensatorAction.java create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/action/StaticVarCompensatorActionBuilder.java create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/action/StaticVarCompensatorActionDeserializer.java create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/action/StaticVarCompensatorActionSerializer.java diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/action/StaticVarCompensatorAction.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/action/StaticVarCompensatorAction.java new file mode 100644 index 00000000000..4478bc9a0dd --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/action/StaticVarCompensatorAction.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2023, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.security.action; + +import com.powsybl.iidm.network.StaticVarCompensator; + +import java.util.Objects; +import java.util.Optional; +import java.util.OptionalDouble; + +/** + * An action to: + *
    + *
  • change the regulationMode of a static var compensator, three options are available VOLTAGE, REACTIVE_POWER or OFF
  • + *
  • change voltageSetPoint to change the voltage setpoint if the regulation mode is set to VOLTAGE (kV)
  • + *
  • change reactivePowerSetpoint to change the reactive power setpoint if the regulation mode is set to REACTIVE_POWER (MVAR)
  • + *
+ * @author Etienne Lesot + */ +public class StaticVarCompensatorAction extends AbstractAction { + + public static final String NAME = "STATIC_VAR_COMPENSATOR"; + private final String staticVarCompensatorId; + private final StaticVarCompensator.RegulationMode regulationMode; + private final Double voltageSetpoint; + private final Double reactivePowerSetpoint; + + protected StaticVarCompensatorAction(String id, String staticVarCompensatorId, + StaticVarCompensator.RegulationMode regulationMode, + Double voltageSetpoint, Double reactivePowerSetpoint) { + super(id); + this.staticVarCompensatorId = Objects.requireNonNull(staticVarCompensatorId); + this.regulationMode = regulationMode; + this.voltageSetpoint = voltageSetpoint; + this.reactivePowerSetpoint = reactivePowerSetpoint; + } + + @Override + public String getType() { + return NAME; + } + + public String getStaticVarCompensatorId() { + return staticVarCompensatorId; + } + + public Optional getRegulationMode() { + return Optional.ofNullable(regulationMode); + } + + public OptionalDouble getVoltageSetpoint() { + return voltageSetpoint == null ? OptionalDouble.empty() : OptionalDouble.of(voltageSetpoint); + } + + public OptionalDouble getReactivePowerSetpoint() { + return reactivePowerSetpoint == null ? OptionalDouble.empty() : OptionalDouble.of(reactivePowerSetpoint); + } +} diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/action/StaticVarCompensatorActionBuilder.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/action/StaticVarCompensatorActionBuilder.java new file mode 100644 index 00000000000..c99c62e4781 --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/action/StaticVarCompensatorActionBuilder.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2023, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.security.action; + +import com.powsybl.iidm.network.StaticVarCompensator; + +/** + * @author Etienne Lesot + */ +public class StaticVarCompensatorActionBuilder { + + private String id; + private String staticVarCompensatorId; + private StaticVarCompensator.RegulationMode regulationMode; + private Double voltageSetpoint; + private Double reactivePowerSetpoint; + + public StaticVarCompensatorAction build() { + return new StaticVarCompensatorAction(id, staticVarCompensatorId, regulationMode, voltageSetpoint, reactivePowerSetpoint); + } + + public StaticVarCompensatorActionBuilder withId(String id) { + this.id = id; + return this; + } + + public StaticVarCompensatorActionBuilder withStaticVarCompensatorId(String staticVarCompensatorId) { + this.staticVarCompensatorId = staticVarCompensatorId; + return this; + } + + public StaticVarCompensatorActionBuilder withRegulationMode(StaticVarCompensator.RegulationMode regulationMode) { + this.regulationMode = regulationMode; + return this; + } + + public StaticVarCompensatorActionBuilder withVoltageSetpoint(Double voltageSetpoint) { + this.voltageSetpoint = voltageSetpoint; + return this; + } + + public StaticVarCompensatorActionBuilder withReactivePowerSetpoint(Double reactivePowerSetpoint) { + this.reactivePowerSetpoint = reactivePowerSetpoint; + return this; + } +} diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisJsonModule.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisJsonModule.java index d4e6a61a5cf..a79df712493 100644 --- a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisJsonModule.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisJsonModule.java @@ -104,15 +104,14 @@ private void configureActionsSerialization() { new PhaseTapChangerRegulationActionSerializer(), new PhaseTapChangerRegulationActionDeserializer()); registerActionType(RatioTapChangerRegulationAction.class, RatioTapChangerRegulationAction.NAME, new RatioTapChangerRegulationActionSerializer(), new RatioTapChangerRegulationActionDeserializer()); - registerActionType(GeneratorAction.class, GeneratorAction.NAME, new GeneratorActionSerializer(), new GeneratorActionDeserializer()); registerActionType(LoadAction.class, LoadAction.NAME, new LoadActionSerializer(), new LoadActionDeserializer()); registerActionType(HvdcAction.class, HvdcAction.NAME, new HvdcActionSerializer(), new HvdcActionDeserializer()); registerActionType(GeneratorAction.class, GeneratorAction.NAME, new GeneratorActionSerializer(), new GeneratorActionDeserializer()); - registerActionType(LoadAction.class, LoadAction.NAME, - new LoadActionSerializer(), new LoadActionDeserializer()); registerActionType(ShuntCompensatorPositionAction.class, ShuntCompensatorPositionAction.NAME, new ShuntCompensatorPositionActionSerializer(), new ShuntCompensatorPositionActionDeserializer()); + registerActionType(StaticVarCompensatorAction.class, StaticVarCompensatorAction.NAME, + new StaticVarCompensatorActionSerializer(), new StaticVarCompensatorActionDeserializer()); } private void registerActionType(Class actionClass, String typeName, JsonSerializer serializer, JsonDeserializer deserializer) { diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/action/StaticVarCompensatorActionDeserializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/action/StaticVarCompensatorActionDeserializer.java new file mode 100644 index 00000000000..5c63b6569a5 --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/action/StaticVarCompensatorActionDeserializer.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2023, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.security.json.action; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.powsybl.commons.json.JsonUtil; +import com.powsybl.iidm.network.StaticVarCompensator; +import com.powsybl.security.action.StaticVarCompensatorAction; +import com.powsybl.security.action.StaticVarCompensatorActionBuilder; + +import java.io.IOException; + +/** + * @author Etienne Lesot + */ +public class StaticVarCompensatorActionDeserializer extends StdDeserializer { + + public StaticVarCompensatorActionDeserializer() { + super(StaticVarCompensatorAction.class); + } + + private static class ParsingContext { + String id; + String staticVarCompensatorId; + String regulationMode; + Double voltageSetpoint; + Double reactivePowerSetpoint; + } + + @Override + public StaticVarCompensatorAction deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + ParsingContext context = new ParsingContext(); + JsonUtil.parsePolymorphicObject(jsonParser, name -> { + switch (name) { + case "type": + if (!StaticVarCompensatorAction.NAME.equals(jsonParser.nextTextValue())) { + throw JsonMappingException.from(jsonParser, "Expected type " + StaticVarCompensatorAction.NAME); + } + return true; + case "id": + context.id = jsonParser.nextTextValue(); + return true; + case "staticVarCompensatorId": + context.staticVarCompensatorId = jsonParser.nextTextValue(); + return true; + case "regulationMode": + context.regulationMode = jsonParser.nextTextValue(); + return true; + case "voltageSetpoint": + jsonParser.nextToken(); + context.voltageSetpoint = jsonParser.getValueAsDouble(); + return true; + case "reactivePowerSetpoint": + jsonParser.nextToken(); + context.reactivePowerSetpoint = jsonParser.getValueAsDouble(); + return true; + default: + return false; + } + }); + StaticVarCompensatorActionBuilder builder = new StaticVarCompensatorActionBuilder(); + builder.withId(context.id) + .withStaticVarCompensatorId(context.staticVarCompensatorId); + if (context.regulationMode != null) { + builder.withRegulationMode(StaticVarCompensator.RegulationMode.valueOf(context.regulationMode)); + } + if (context.voltageSetpoint != null) { + builder.withVoltageSetpoint(context.voltageSetpoint); + } + if (context.reactivePowerSetpoint != null) { + builder.withReactivePowerSetpoint(context.reactivePowerSetpoint); + } + return builder.build(); + } +} diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/action/StaticVarCompensatorActionSerializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/action/StaticVarCompensatorActionSerializer.java new file mode 100644 index 00000000000..d84759b0112 --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/action/StaticVarCompensatorActionSerializer.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2023, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.security.json.action; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import com.powsybl.security.action.StaticVarCompensatorAction; + +import java.io.IOException; +import java.io.UncheckedIOException; + +/** + * @author Etienne Lesot + */ +public class StaticVarCompensatorActionSerializer extends StdSerializer { + + public StaticVarCompensatorActionSerializer() { + super(StaticVarCompensatorAction.class); + } + + @Override + public void serialize(StaticVarCompensatorAction action, JsonGenerator jsonGenerator, + SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeStartObject(); + jsonGenerator.writeStringField("type", action.getType()); + jsonGenerator.writeStringField("id", action.getId()); + jsonGenerator.writeStringField("staticVarCompensatorId", action.getStaticVarCompensatorId()); + action.getRegulationMode().ifPresent(regulationMode -> { + try { + jsonGenerator.writeStringField("regulationMode", String.valueOf(regulationMode)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + action.getReactivePowerSetpoint().ifPresent(reactivePowerSetpoint -> { + try { + jsonGenerator.writeNumberField("reactivePowerSetpoint", reactivePowerSetpoint); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + action.getVoltageSetpoint().ifPresent(voltageSetpoint -> { + try { + jsonGenerator.writeNumberField("voltageSetpoint", voltageSetpoint); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + jsonGenerator.writeEndObject(); + } +} diff --git a/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/JsonActionAndOperatorStrategyTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/JsonActionAndOperatorStrategyTest.java index 596534f206c..72d0c193459 100644 --- a/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/JsonActionAndOperatorStrategyTest.java +++ b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/JsonActionAndOperatorStrategyTest.java @@ -17,6 +17,7 @@ import com.powsybl.commons.test.ComparisonUtils; import com.powsybl.contingency.ContingencyContext; import com.powsybl.iidm.network.PhaseTapChanger; +import com.powsybl.iidm.network.StaticVarCompensator; import com.powsybl.iidm.network.ThreeWindingsTransformer; import com.powsybl.security.action.*; import com.powsybl.security.condition.AllViolationCondition; @@ -96,6 +97,12 @@ void actionRoundTrip() throws IOException { .withRelativeValue(true) .build()); actions.add(new ShuntCompensatorPositionActionBuilder().withId("id22").withShuntCompensatorId("shuntId1").withSectionCount(5).build()); + actions.add(new StaticVarCompensatorActionBuilder().withId("id23") + .withStaticVarCompensatorId("svc").withRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE) + .withVoltageSetpoint(56.0).build()); + actions.add(new StaticVarCompensatorActionBuilder().withId("id24") + .withStaticVarCompensatorId("svc").withRegulationMode(StaticVarCompensator.RegulationMode.REACTIVE_POWER) + .withReactivePowerSetpoint(120.0).build()); ActionList actionList = new ActionList(actions); roundTripTest(actionList, ActionList::writeJsonFile, ActionList::readJsonFile, "/ActionFileTest.json"); } diff --git a/security-analysis/security-analysis-api/src/test/resources/ActionFileTest.json b/security-analysis/security-analysis-api/src/test/resources/ActionFileTest.json index ba7df9962ba..0fee70288e8 100644 --- a/security-analysis/security-analysis-api/src/test/resources/ActionFileTest.json +++ b/security-analysis/security-analysis-api/src/test/resources/ActionFileTest.json @@ -167,5 +167,17 @@ "id" : "id22", "shuntCompensatorId" : "shuntId1", "sectionCount" : 5 + }, { + "type" : "STATIC_VAR_COMPENSATOR", + "id" : "id23", + "staticVarCompensatorId" : "svc", + "regulationMode" : "VOLTAGE", + "voltageSetpoint" : 56.0 + }, { + "type" : "STATIC_VAR_COMPENSATOR", + "id" : "id24", + "staticVarCompensatorId" : "svc", + "regulationMode" : "REACTIVE_POWER", + "reactivePowerSetpoint" : 120.0 } ] } \ No newline at end of file diff --git a/security-analysis/security-analysis-api/src/test/resources/ActionFileTestV1.0.json b/security-analysis/security-analysis-api/src/test/resources/ActionFileTestV1.0.json index 04d730aaef9..8bd8f28f184 100644 --- a/security-analysis/security-analysis-api/src/test/resources/ActionFileTestV1.0.json +++ b/security-analysis/security-analysis-api/src/test/resources/ActionFileTestV1.0.json @@ -167,5 +167,17 @@ "id" : "id22", "shuntCompensatorId" : "shuntId1", "sectionCount" : 5 + }, { + "type" : "STATIC_VAR_COMPENSATOR", + "id" : "id23", + "staticVarCompensatorId" : "svc", + "regulationMode" : "VOLTAGE", + "voltageSetpoint" : 56.0 + }, { + "type" : "STATIC_VAR_COMPENSATOR", + "id" : "id24", + "staticVarCompensatorId" : "svc", + "regulationMode" : "REACTIVE_POWER", + "reactivePowerSetpoint" : 120.0 } ] } \ No newline at end of file