From f8157eb291019efff37fbafc07245db01664bc8c Mon Sep 17 00:00:00 2001 From: Antoine Bouhours Date: Fri, 11 Oct 2024 16:58:20 +0200 Subject: [PATCH 1/2] Upgrade to network store v1.18.1 (#544) Signed-off-by: Antoine Bouhours --- pom.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/pom.xml b/pom.xml index d4631d1fe..e82f2161a 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,8 @@ 0.0.2 1.16.2 org.gridsuite.modification.server + + 1.18.1 @@ -84,6 +86,24 @@ + + com.powsybl + powsybl-network-store-client + + ${powsybl-network-store.version} + + + + com.powsybl + powsybl-network-store-iidm-impl + ${powsybl-network-store.version} + + + + com.powsybl + powsybl-network-store-model + ${powsybl-network-store.version} + From b1f129524ccbc2777f4f6acf5321e4c6a9770b5a Mon Sep 17 00:00:00 2001 From: Ghazoua Rehili Date: Fri, 11 Oct 2024 17:10:25 +0200 Subject: [PATCH 2/2] add creation cspr modification network (#519) Signed-off-by: REHILI Ghazwa --- .../modification/server/ModificationType.java | 1 + .../server/NetworkModificationException.java | 3 + .../server/dto/ModificationInfos.java | 1 + .../StaticVarCompensatorCreationInfos.java | 109 ++++++++ .../StaticCompensatorCreationEntity.java | 168 ++++++++++++ .../server/modifications/BatteryCreation.java | 55 +--- .../modifications/GeneratorCreation.java | 62 +---- .../server/modifications/LoadCreation.java | 16 +- .../modifications/ModificationUtils.java | 112 +++++++- .../ShuntCompensatorCreation.java | 19 +- .../StaticVarCompensatorCreation.java | 234 +++++++++++++++++ .../server/modifications/VscCreation.java | 53 +--- .../changesets/changelog_20240912T100256Z.xml | 40 +++ .../db/changelog/db.changelog-master.yaml | 5 +- ...arCompensatorCreationInBusBreakerTest.java | 147 +++++++++++ ...rCompensatorCreationInNodeBreakerTest.java | 240 ++++++++++++++++++ .../service/ModificationRepositoryTest.java | 73 ++++++ 17 files changed, 1142 insertions(+), 196 deletions(-) create mode 100644 src/main/java/org/gridsuite/modification/server/dto/StaticVarCompensatorCreationInfos.java create mode 100644 src/main/java/org/gridsuite/modification/server/entities/equipment/creation/StaticCompensatorCreationEntity.java create mode 100644 src/main/java/org/gridsuite/modification/server/modifications/StaticVarCompensatorCreation.java create mode 100644 src/main/resources/db/changelog/changesets/changelog_20240912T100256Z.xml create mode 100644 src/test/java/org/gridsuite/modification/server/modifications/StaticVarCompensatorCreationInBusBreakerTest.java create mode 100644 src/test/java/org/gridsuite/modification/server/modifications/StaticVarCompensatorCreationInNodeBreakerTest.java diff --git a/src/main/java/org/gridsuite/modification/server/ModificationType.java b/src/main/java/org/gridsuite/modification/server/ModificationType.java index a95415d71..2abc233c9 100644 --- a/src/main/java/org/gridsuite/modification/server/ModificationType.java +++ b/src/main/java/org/gridsuite/modification/server/ModificationType.java @@ -31,6 +31,7 @@ public enum ModificationType { SUBSTATION_MODIFICATION(PreloadingStrategy.NONE), SHUNT_COMPENSATOR_CREATION(PreloadingStrategy.NONE), SHUNT_COMPENSATOR_MODIFICATION(PreloadingStrategy.NONE), + STATIC_VAR_COMPENSATOR_CREATION(PreloadingStrategy.NONE), VOLTAGE_LEVEL_CREATION(PreloadingStrategy.NONE), VOLTAGE_LEVEL_MODIFICATION(PreloadingStrategy.NONE), LINE_SPLIT_WITH_VOLTAGE_LEVEL(PreloadingStrategy.NONE), diff --git a/src/main/java/org/gridsuite/modification/server/NetworkModificationException.java b/src/main/java/org/gridsuite/modification/server/NetworkModificationException.java index 493c4f654..2c72e6545 100644 --- a/src/main/java/org/gridsuite/modification/server/NetworkModificationException.java +++ b/src/main/java/org/gridsuite/modification/server/NetworkModificationException.java @@ -49,6 +49,7 @@ public enum Type { CREATE_GENERATOR_ERROR(HttpStatus.INTERNAL_SERVER_ERROR), CREATE_SHUNT_COMPENSATOR_ERROR(HttpStatus.INTERNAL_SERVER_ERROR), MODIFY_SHUNT_COMPENSATOR_ERROR(HttpStatus.INTERNAL_SERVER_ERROR), + CREATE_STATIC_VAR_COMPENSATOR_ERROR(HttpStatus.INTERNAL_SERVER_ERROR), DELETE_EQUIPMENT_ERROR(HttpStatus.INTERNAL_SERVER_ERROR), BY_FILTER_DELETION_ERROR(HttpStatus.INTERNAL_SERVER_ERROR), EQUIPMENT_NOT_FOUND(HttpStatus.NOT_FOUND), @@ -70,6 +71,8 @@ public enum Type { GENERATOR_ALREADY_EXISTS(HttpStatus.BAD_REQUEST), SHUNT_COMPENSATOR_ALREADY_EXISTS(HttpStatus.BAD_REQUEST), SHUNT_COMPENSATOR_NOT_FOUND(HttpStatus.NOT_FOUND), + STATIC_VAR_COMPENSATOR_ALREADY_EXISTS(HttpStatus.BAD_REQUEST), + STATIC_VAR_COMPENSATOR_NOT_FOUND(HttpStatus.NOT_FOUND), LINE_ALREADY_EXISTS(HttpStatus.BAD_REQUEST), TWO_WINDINGS_TRANSFORMER_ALREADY_EXISTS(HttpStatus.BAD_REQUEST), TWO_WINDINGS_TRANSFORMER_CREATION_ERROR(HttpStatus.BAD_REQUEST), diff --git a/src/main/java/org/gridsuite/modification/server/dto/ModificationInfos.java b/src/main/java/org/gridsuite/modification/server/dto/ModificationInfos.java index eb5811353..2ef27c5e6 100644 --- a/src/main/java/org/gridsuite/modification/server/dto/ModificationInfos.java +++ b/src/main/java/org/gridsuite/modification/server/dto/ModificationInfos.java @@ -49,6 +49,7 @@ @JsonSubTypes.Type(value = VoltageLevelModificationInfos.class), @JsonSubTypes.Type(value = ShuntCompensatorCreationInfos.class), @JsonSubTypes.Type(value = ShuntCompensatorModificationInfos.class), + @JsonSubTypes.Type(value = StaticVarCompensatorCreationInfos.class), @JsonSubTypes.Type(value = TwoWindingsTransformerCreationInfos.class), @JsonSubTypes.Type(value = TwoWindingsTransformerModificationInfos.class), @JsonSubTypes.Type(value = EquipmentDeletionInfos.class), diff --git a/src/main/java/org/gridsuite/modification/server/dto/StaticVarCompensatorCreationInfos.java b/src/main/java/org/gridsuite/modification/server/dto/StaticVarCompensatorCreationInfos.java new file mode 100644 index 000000000..b86fd6927 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/StaticVarCompensatorCreationInfos.java @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2024, 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/. + */ +package org.gridsuite.modification.server.dto; + +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.powsybl.commons.report.ReportNode; +import com.powsybl.iidm.network.StaticVarCompensator; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.SuperBuilder; +import org.gridsuite.modification.server.ModificationType; +import org.gridsuite.modification.server.dto.annotation.ModificationErrorTypeName; +import org.gridsuite.modification.server.entities.equipment.creation.StaticCompensatorCreationEntity; +import org.gridsuite.modification.server.modifications.AbstractModification; +import org.gridsuite.modification.server.modifications.StaticVarCompensatorCreation; + +/** + * @author Ghazwa Rehili + */ + +@SuperBuilder +@NoArgsConstructor +@Getter +@Setter +@ToString(callSuper = true) +@Schema(description = "Static var compensator creation") +@JsonTypeName("STATIC_VAR_COMPENSATOR_CREATION") +@ModificationErrorTypeName("CREATE_STATIC_VAR_COMPENSATOR_ERROR") +public class StaticVarCompensatorCreationInfos extends InjectionCreationInfos { + @Schema(description = "Susceptance max") + private Double maxSusceptance; + + @Schema(description = "Susceptance min") + private Double minSusceptance; + + @Schema(description = "Q max at nominal voltage") + private Double maxQAtNominalV; + + @Schema(description = "Q min at nominal voltage") + private Double minQAtNominalV; + + @Schema(description = "regulation mode") + private StaticVarCompensator.RegulationMode regulationMode; + + @Schema(description = "Voltage set point") + private Double voltageSetpoint; + + @Schema(description = "Reactive power set point") + private Double reactivePowerSetpoint; + + @Schema(description = "Voltage Regulation type") + private VoltageRegulationType voltageRegulationType; + + @Schema(description = "Regulating terminal equipment id") + private String regulatingTerminalId; + + @Schema(description = "Regulating terminal equipment type") + private String regulatingTerminalType; + + @Schema(description = "Regulating terminal voltage level id") + private String regulatingTerminalVlId; + + @Schema(description = "standby automaton on") + private boolean standbyAutomatonOn; + + @Schema(description = "Standby") + private boolean standby; + + @Schema(description = "Fixed part of susceptance") + private Double b0; + + @Schema(description = "Fixed part of Q at nominal voltage") + private Double q0; + + @Schema(description = "Low voltage set point ") + private Double lowVoltageSetpoint; + + @Schema(description = "High voltage set point") + private Double highVoltageSetpoint; + + @Schema(description = "Low voltage threshold") + private Double lowVoltageThreshold; + + @Schema(description = "High voltage threshold") + private Double highVoltageThreshold; + + @Override + public StaticCompensatorCreationEntity toEntity() { + return new StaticCompensatorCreationEntity(this); + } + + @Override + public AbstractModification toModification() { + return new StaticVarCompensatorCreation(this); + } + + @Override + public ReportNode createSubReportNode(ReportNode reportNode) { + return reportNode.newReportNode().withMessageTemplate(ModificationType.STATIC_VAR_COMPENSATOR_CREATION.name(), + "Static var compensator creation ${id}").withUntypedValue("id", this.getEquipmentId()).add(); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/entities/equipment/creation/StaticCompensatorCreationEntity.java b/src/main/java/org/gridsuite/modification/server/entities/equipment/creation/StaticCompensatorCreationEntity.java new file mode 100644 index 000000000..2e0d55800 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/entities/equipment/creation/StaticCompensatorCreationEntity.java @@ -0,0 +1,168 @@ +/** + * Copyright (c) 2024, 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/. + */ +package org.gridsuite.modification.server.entities.equipment.creation; + +import com.powsybl.iidm.network.StaticVarCompensator; +import jakarta.persistence.*; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.gridsuite.modification.server.dto.ModificationInfos; +import org.gridsuite.modification.server.dto.StaticVarCompensatorCreationInfos; +import org.gridsuite.modification.server.dto.VoltageRegulationType; +import org.gridsuite.modification.server.entities.equipment.modification.FreePropertyEntity; +import org.springframework.util.CollectionUtils; + +/** + * @author Ghazwa Rehili + */ +@NoArgsConstructor +@Getter +@Entity +@Table(name = "staticVarCompensatorCreation") +@PrimaryKeyJoinColumn(foreignKey = @ForeignKey(name = "staticVarCompensatorCreation_id_fk_constraint")) +public class StaticCompensatorCreationEntity extends InjectionCreationEntity { + @Column + private Double maxSusceptance; + + @Column + private Double minSusceptance; + + @Column + private Double maxQAtNominalV; + + @Column + private Double minQAtNominalV; + + @Enumerated(EnumType.STRING) + @Column(name = "regulationMode") + private StaticVarCompensator.RegulationMode regulationMode; + + @Column + private Double voltageSetpoint; + + @Column + private Double reactivePowerSetpoint; + + @Enumerated(EnumType.STRING) + @Column(name = "voltageRegulationType") + private VoltageRegulationType voltageRegulationType; + + @Column(name = "regulatingTerminalId") + private String regulatingTerminalId; + + @Column(name = "regulatingTerminalType") + private String regulatingTerminalType; + + @Column(name = "regulatingTerminalVlId") + private String regulatingTerminalVlId; + + @Column + private boolean standbyAutomatonOn; + + @Column + private boolean standby; + + @Column + private Double b0; + + @Column + private Double q0; + + @Column + private Double lowVoltageSetpoint; + + @Column + private Double highVoltageSetpoint; + + @Column + private Double lowVoltageThreshold; + + @Column + private Double highVoltageThreshold; + + public StaticCompensatorCreationEntity(StaticVarCompensatorCreationInfos creationInfos) { + super(creationInfos); + assignAttributes(creationInfos); + } + + @Override + public void update(ModificationInfos modificationInfos) { + super.update(modificationInfos); + StaticVarCompensatorCreationInfos staticVarCompensatorCreationInfos = (StaticVarCompensatorCreationInfos) modificationInfos; + assignAttributes(staticVarCompensatorCreationInfos); + } + + private void assignAttributes(StaticVarCompensatorCreationInfos creationInfos) { + this.maxSusceptance = creationInfos.getMaxSusceptance(); + this.minSusceptance = creationInfos.getMinSusceptance(); + this.maxQAtNominalV = creationInfos.getMaxQAtNominalV(); + this.minQAtNominalV = creationInfos.getMinQAtNominalV(); + this.regulationMode = creationInfos.getRegulationMode(); + this.voltageSetpoint = creationInfos.getVoltageSetpoint(); + this.reactivePowerSetpoint = creationInfos.getReactivePowerSetpoint(); + this.voltageRegulationType = creationInfos.getVoltageRegulationType(); + this.regulatingTerminalId = creationInfos.getRegulatingTerminalId(); + this.regulatingTerminalType = creationInfos.getRegulatingTerminalType(); + this.regulatingTerminalVlId = creationInfos.getRegulatingTerminalVlId(); + this.standbyAutomatonOn = creationInfos.isStandbyAutomatonOn(); + this.standby = creationInfos.isStandby(); + this.b0 = creationInfos.getB0(); + this.q0 = creationInfos.getQ0(); + this.highVoltageSetpoint = creationInfos.getHighVoltageSetpoint(); + this.lowVoltageSetpoint = creationInfos.getLowVoltageSetpoint(); + this.lowVoltageThreshold = creationInfos.getLowVoltageThreshold(); + this.highVoltageThreshold = creationInfos.getHighVoltageThreshold(); + } + + @Override + public StaticVarCompensatorCreationInfos toModificationInfos() { + return toStaticVarCompensatorCreationInfosBuilder().build(); + } + + private StaticVarCompensatorCreationInfos.StaticVarCompensatorCreationInfosBuilder toStaticVarCompensatorCreationInfosBuilder() { + return StaticVarCompensatorCreationInfos + .builder() + .uuid(getId()) + .date(getDate()) + .stashed(getStashed()) + .activated(getActivated()) + .equipmentId(getEquipmentId()) + .equipmentName(getEquipmentName()) + // Injection + .voltageLevelId(getVoltageLevelId()) + .busOrBusbarSectionId(getBusOrBusbarSectionId()) + .connectionName(getConnectionName()) + .connectionDirection(getConnectionDirection()) + .connectionPosition(getConnectionPosition()) + .terminalConnected(isTerminalConnected()) + .maxSusceptance(getMaxSusceptance()) + .minSusceptance(getMinSusceptance()) + .minQAtNominalV(getMinQAtNominalV()) + .maxQAtNominalV(getMaxQAtNominalV()) + .regulationMode(getRegulationMode()) + .reactivePowerSetpoint(getReactivePowerSetpoint()) + .voltageSetpoint(getVoltageSetpoint()) + .voltageRegulationType(getVoltageRegulationType()) + .regulatingTerminalId(getRegulatingTerminalId()) + .regulatingTerminalType(getRegulatingTerminalType()) + .regulatingTerminalVlId(getRegulatingTerminalVlId()) + // Standby automaton + .standbyAutomatonOn(isStandbyAutomatonOn()) + .standby(isStandby()) + .b0(getB0()) + .q0(getQ0()) + .lowVoltageSetpoint(getLowVoltageSetpoint()) + .highVoltageSetpoint(getHighVoltageSetpoint()) + .lowVoltageThreshold(getLowVoltageThreshold()) + .highVoltageThreshold(getHighVoltageThreshold()) + // properties + .properties(CollectionUtils.isEmpty(getProperties()) ? null : + getProperties().stream() + .map(FreePropertyEntity::toInfos) + .toList()); + } +} diff --git a/src/main/java/org/gridsuite/modification/server/modifications/BatteryCreation.java b/src/main/java/org/gridsuite/modification/server/modifications/BatteryCreation.java index d1c129089..10345a8e2 100644 --- a/src/main/java/org/gridsuite/modification/server/modifications/BatteryCreation.java +++ b/src/main/java/org/gridsuite/modification/server/modifications/BatteryCreation.java @@ -9,8 +9,6 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.commons.report.ReportNode; import com.powsybl.commons.report.TypedValue; -import com.powsybl.iidm.modification.topology.CreateFeederBay; -import com.powsybl.iidm.modification.topology.CreateFeederBayBuilder; import com.powsybl.iidm.network.*; import com.powsybl.iidm.network.extensions.ActivePowerControlAdder; import org.gridsuite.modification.server.NetworkModificationException; @@ -20,7 +18,7 @@ import java.util.List; import static org.gridsuite.modification.server.NetworkModificationException.Type.BATTERY_ALREADY_EXISTS; -import static org.gridsuite.modification.server.modifications.ModificationUtils.nanIfNull; +import static org.gridsuite.modification.server.modifications.ModificationUtils.*; /** * @author Ghazwa Rehili @@ -30,7 +28,6 @@ public class BatteryCreation extends AbstractModification { private final BatteryCreationInfos modificationInfos; private static final String LIMITS = "Limits"; private static final String ACTIVE_LIMITS = "Active limits"; - private static final String CONNECTIVITY = "Connectivity"; public BatteryCreation(BatteryCreationInfos modificationInfos) { this.modificationInfos = modificationInfos; @@ -73,21 +70,7 @@ public void apply(Network network, ReportNode subReportNode) { private void createBatteryInNodeBreaker(VoltageLevel voltageLevel, BatteryCreationInfos batteryCreationInfos, Network network, ReportNode subReportNode) { BatteryAdder batteryAdder = createBatteryAdderInNodeBreaker(voltageLevel, batteryCreationInfos); - var position = ModificationUtils.getInstance().getPosition(batteryCreationInfos.getConnectionPosition(), - batteryCreationInfos.getBusOrBusbarSectionId(), network, voltageLevel); - - CreateFeederBay algo = new CreateFeederBayBuilder() - .withBusOrBusbarSectionId(batteryCreationInfos.getBusOrBusbarSectionId()) - .withInjectionDirection(batteryCreationInfos.getConnectionDirection()) - .withInjectionFeederName(batteryCreationInfos.getConnectionName() != null - ? batteryCreationInfos.getConnectionName() - : batteryCreationInfos.getEquipmentId()) - .withInjectionPositionOrder(position) - .withInjectionAdder(batteryAdder) - .build(); - - algo.apply(network, true, subReportNode); - + createInjectionInNodeBreaker(voltageLevel, batteryCreationInfos, network, batteryAdder, subReportNode); var battery = ModificationUtils.getInstance().getBattery(network, batteryCreationInfos.getEquipmentId()); addExtensionsToBattery(batteryCreationInfos, battery, subReportNode); } @@ -131,7 +114,7 @@ private void addExtensionsToBattery(BatteryCreationInfos batteryCreationInfos, B if (batteryCreationInfos.getEquipmentName() != null) { ModificationUtils.getInstance().reportElementaryCreation(subReportNode, batteryCreationInfos.getEquipmentName(), "Name"); } - reportBatteryConnectivity(batteryCreationInfos, subReportNode); + reportInjectionCreationConnectivity(batteryCreationInfos, subReportNode); ReportNode subReportNodeLimits = reportBatteryActiveLimits(batteryCreationInfos, subReportNode); ModificationUtils.getInstance().createReactiveLimits(batteryCreationInfos, battery, subReportNodeLimits); ReportNode subReportNodeSetpoints = reportBatterySetPoints(batteryCreationInfos, subReportNode); @@ -149,38 +132,6 @@ private ReportNode reportBatterySetPoints(BatteryCreationInfos batteryCreationIn return ModificationUtils.getInstance().reportModifications(subReportNode, setPointReports, "SetPointCreated", "Setpoints"); } - private void reportBatteryConnectivity(BatteryCreationInfos batteryCreationInfos, ReportNode subReportNode) { - if (batteryCreationInfos.getVoltageLevelId() == null || batteryCreationInfos.getBusOrBusbarSectionId() == null) { - return; - } - - if (batteryCreationInfos.getConnectionName() != null || - batteryCreationInfos.getConnectionDirection() != null || - batteryCreationInfos.getConnectionPosition() != null) { - List connectivityReports = new ArrayList<>(); - if (batteryCreationInfos.getConnectionName() != null) { - connectivityReports.add(ModificationUtils.getInstance() - .buildCreationReport(batteryCreationInfos.getConnectionName(), "Connection name")); - } - if (batteryCreationInfos.getConnectionDirection() != null) { - connectivityReports.add(ModificationUtils.getInstance() - .buildCreationReport(batteryCreationInfos.getConnectionDirection(), "Connection direction")); - } - if (batteryCreationInfos.getConnectionPosition() != null) { - connectivityReports.add(ModificationUtils.getInstance() - .buildCreationReport(batteryCreationInfos.getConnectionPosition(), "Connection position")); - } - if (!batteryCreationInfos.isTerminalConnected()) { - connectivityReports.add(ReportNode.newRootReportNode() - .withMessageTemplate("equipmentDisconnected", " Equipment with id=${id} disconnected") - .withUntypedValue("id", batteryCreationInfos.getEquipmentId()) - .withSeverity(TypedValue.INFO_SEVERITY) - .build()); - } - ModificationUtils.getInstance().reportModifications(subReportNode, connectivityReports, "ConnectivityCreated", CONNECTIVITY); - } - } - private ReportNode reportBatteryActiveLimits(BatteryCreationInfos batteryCreationInfos, ReportNode subReportNode) { ReportNode subReportNodeLimits = subReportNode.newReportNode().withMessageTemplate(LIMITS, LIMITS).add(); List limitsReports = new ArrayList<>(); diff --git a/src/main/java/org/gridsuite/modification/server/modifications/GeneratorCreation.java b/src/main/java/org/gridsuite/modification/server/modifications/GeneratorCreation.java index da8c55a93..8931f4a3d 100644 --- a/src/main/java/org/gridsuite/modification/server/modifications/GeneratorCreation.java +++ b/src/main/java/org/gridsuite/modification/server/modifications/GeneratorCreation.java @@ -9,15 +9,7 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.commons.report.ReportNode; import com.powsybl.commons.report.TypedValue; -import com.powsybl.iidm.modification.topology.CreateFeederBay; -import com.powsybl.iidm.modification.topology.CreateFeederBayBuilder; -import com.powsybl.iidm.network.Bus; -import com.powsybl.iidm.network.Generator; -import com.powsybl.iidm.network.GeneratorAdder; -import com.powsybl.iidm.network.Network; -import com.powsybl.iidm.network.Terminal; -import com.powsybl.iidm.network.TopologyKind; -import com.powsybl.iidm.network.VoltageLevel; +import com.powsybl.iidm.network.*; import com.powsybl.iidm.network.extensions.ActivePowerControlAdder; import com.powsybl.iidm.network.extensions.GeneratorShortCircuitAdder; import com.powsybl.network.store.iidm.impl.extensions.CoordinatedReactiveControlAdderImpl; @@ -29,7 +21,7 @@ import java.util.List; import static org.gridsuite.modification.server.NetworkModificationException.Type.GENERATOR_ALREADY_EXISTS; -import static org.gridsuite.modification.server.modifications.ModificationUtils.nanIfNull; +import static org.gridsuite.modification.server.modifications.ModificationUtils.*; /** * @author Ayoub Labidi @@ -39,7 +31,6 @@ public class GeneratorCreation extends AbstractModification { private final GeneratorCreationInfos modificationInfos; private static final String LIMITS = "Limits"; private static final String ACTIVE_LIMITS = "Active limits"; - private static final String CONNECTIVITY = "Connectivity"; public GeneratorCreation(GeneratorCreationInfos modificationInfos) { this.modificationInfos = modificationInfos; @@ -88,20 +79,7 @@ public void apply(Network network, ReportNode subReportNode) { private void createGeneratorInNodeBreaker(VoltageLevel voltageLevel, GeneratorCreationInfos generatorCreationInfos, Network network, ReportNode subReportNode) { GeneratorAdder generatorAdder = createGeneratorAdderInNodeBreaker(voltageLevel, generatorCreationInfos); - var position = ModificationUtils.getInstance().getPosition(generatorCreationInfos.getConnectionPosition(), - generatorCreationInfos.getBusOrBusbarSectionId(), network, voltageLevel); - - CreateFeederBay algo = new CreateFeederBayBuilder() - .withBusOrBusbarSectionId(generatorCreationInfos.getBusOrBusbarSectionId()) - .withInjectionDirection(generatorCreationInfos.getConnectionDirection()) - .withInjectionFeederName(generatorCreationInfos.getConnectionName() != null - ? generatorCreationInfos.getConnectionName() - : generatorCreationInfos.getEquipmentId()) - .withInjectionPositionOrder(position) - .withInjectionAdder(generatorAdder) - .build(); - - algo.apply(network, true, subReportNode); + createInjectionInNodeBreaker(voltageLevel, generatorCreationInfos, network, generatorAdder, subReportNode); // CreateFeederBayBuilder already create the generator using // (withInjectionAdder(generatorAdder)) so then we can add the additional informations and extensions @@ -143,7 +121,7 @@ private void addExtensionsToGenerator(GeneratorCreationInfos generatorCreationIn if (generatorCreationInfos.getEnergySource() != null) { ModificationUtils.getInstance().reportElementaryCreation(subReportNode, generatorCreationInfos.getEnergySource(), "Energy source"); } - reportGeneratorConnectivity(generatorCreationInfos, subReportNode); + reportInjectionCreationConnectivity(generatorCreationInfos, subReportNode); ReportNode subReporterLimits = reportGeneratorActiveLimits(generatorCreationInfos, subReportNode); ModificationUtils.getInstance().createReactiveLimits(generatorCreationInfos, generator, subReporterLimits); ReportNode subReporterSetpoints = reportGeneratorSetPoints(generatorCreationInfos, subReportNode); @@ -241,38 +219,6 @@ private void updateGeneratorRegulatingTerminal(GeneratorCreationInfos generatorC } } - private void reportGeneratorConnectivity(GeneratorCreationInfos generatorCreationInfos, ReportNode subReporter) { - if (generatorCreationInfos.getVoltageLevelId() == null || generatorCreationInfos.getBusOrBusbarSectionId() == null) { - return; - } - - if (generatorCreationInfos.getConnectionName() != null || - generatorCreationInfos.getConnectionDirection() != null || - generatorCreationInfos.getConnectionPosition() != null) { - List connectivityReports = new ArrayList<>(); - if (generatorCreationInfos.getConnectionName() != null) { - connectivityReports.add(ModificationUtils.getInstance() - .buildCreationReport(generatorCreationInfos.getConnectionName(), "Connection name")); - } - if (generatorCreationInfos.getConnectionDirection() != null) { - connectivityReports.add(ModificationUtils.getInstance() - .buildCreationReport(generatorCreationInfos.getConnectionDirection(), "Connection direction")); - } - if (generatorCreationInfos.getConnectionPosition() != null) { - connectivityReports.add(ModificationUtils.getInstance() - .buildCreationReport(generatorCreationInfos.getConnectionPosition(), "Connection position")); - } - if (!generatorCreationInfos.isTerminalConnected()) { - connectivityReports.add(ReportNode.newRootReportNode() - .withMessageTemplate("equipmentDisconnected", " Equipment with id=${id} disconnected") - .withUntypedValue("id", generatorCreationInfos.getEquipmentId()) - .withSeverity(TypedValue.INFO_SEVERITY) - .build()); - } - ModificationUtils.getInstance().reportModifications(subReporter, connectivityReports, "ConnectivityCreated", CONNECTIVITY); - } - } - private ReportNode reportGeneratorActiveLimits(GeneratorCreationInfos generatorCreationInfos, ReportNode subReportNode) { ReportNode subReportNodeLimits = subReportNode.newReportNode().withMessageTemplate(LIMITS, LIMITS).add(); List limitsReports = new ArrayList<>(); diff --git a/src/main/java/org/gridsuite/modification/server/modifications/LoadCreation.java b/src/main/java/org/gridsuite/modification/server/modifications/LoadCreation.java index 5afdcde99..db0e67219 100644 --- a/src/main/java/org/gridsuite/modification/server/modifications/LoadCreation.java +++ b/src/main/java/org/gridsuite/modification/server/modifications/LoadCreation.java @@ -8,13 +8,12 @@ import com.powsybl.commons.report.ReportNode; import com.powsybl.commons.report.TypedValue; -import com.powsybl.iidm.modification.topology.CreateFeederBay; -import com.powsybl.iidm.modification.topology.CreateFeederBayBuilder; import com.powsybl.iidm.network.*; import org.gridsuite.modification.server.NetworkModificationException; import org.gridsuite.modification.server.dto.LoadCreationInfos; -import static org.gridsuite.modification.server.NetworkModificationException.Type.*; +import static org.gridsuite.modification.server.NetworkModificationException.Type.LOAD_ALREADY_EXISTS; +import static org.gridsuite.modification.server.modifications.ModificationUtils.createInjectionInNodeBreaker; /** * @author Slimane Amar @@ -42,16 +41,7 @@ public void apply(Network network, ReportNode subReporter) { VoltageLevel voltageLevel = ModificationUtils.getInstance().getVoltageLevel(network, modificationInfos.getVoltageLevelId()); if (voltageLevel.getTopologyKind() == TopologyKind.NODE_BREAKER) { LoadAdder loadAdder = createLoadAdderInNodeBreaker(voltageLevel, modificationInfos); - var position = ModificationUtils.getInstance().getPosition(modificationInfos.getConnectionPosition(), - modificationInfos.getBusOrBusbarSectionId(), network, voltageLevel); - CreateFeederBay algo = new CreateFeederBayBuilder() - .withBbsId(modificationInfos.getBusOrBusbarSectionId()) - .withInjectionDirection(modificationInfos.getConnectionDirection()) - .withInjectionFeederName(modificationInfos.getConnectionName() != null ? modificationInfos.getConnectionName() : modificationInfos.getEquipmentId()) - .withInjectionPositionOrder(position) - .withInjectionAdder(loadAdder) - .build(); - algo.apply(network, true, subReporter); + createInjectionInNodeBreaker(voltageLevel, modificationInfos, network, loadAdder, subReporter); } else { createLoadInBusBreaker(voltageLevel, modificationInfos); subReporter.newReportNode() diff --git a/src/main/java/org/gridsuite/modification/server/modifications/ModificationUtils.java b/src/main/java/org/gridsuite/modification/server/modifications/ModificationUtils.java index b68ecc296..a2f5a4833 100644 --- a/src/main/java/org/gridsuite/modification/server/modifications/ModificationUtils.java +++ b/src/main/java/org/gridsuite/modification/server/modifications/ModificationUtils.java @@ -10,9 +10,7 @@ import com.powsybl.commons.report.ReportNode; import com.powsybl.commons.report.ReportNodeAdder; import com.powsybl.commons.report.TypedValue; -import com.powsybl.iidm.modification.topology.CreateCouplingDeviceBuilder; -import com.powsybl.iidm.modification.topology.CreateVoltageLevelTopologyBuilder; -import com.powsybl.iidm.modification.topology.TopologyModificationUtils; +import com.powsybl.iidm.modification.topology.*; import com.powsybl.iidm.network.*; import com.powsybl.iidm.network.extensions.*; import com.powsybl.network.store.iidm.impl.MinMaxReactiveLimitsImpl; @@ -44,6 +42,9 @@ public final class ModificationUtils { public static final String DISCONNECTOR = "disconnector_"; public static final String BREAKER = "breaker_"; public static final String BUS_BAR_SECTION_ID = "busbarSectionId"; + + public static final String DOES_NOT_EXIST_IN_NETWORK = " does not exist in network"; + public static final String EQUIPMENT_DISCONNECTED = "equipmentDisconnected"; public static final String NO_VALUE = "No value"; public static final String LIMITS = "Limits"; public static final String REACTIVE_LIMITS = "Reactive limits"; @@ -120,6 +121,14 @@ HvdcLine getHvdcLine(Network network, String hvdcLineId) { return hvdcLine; } + StaticVarCompensator getStaticVarCompensator(Network network, String staticVarCompensatorId) { + StaticVarCompensator staticVarCompensator = network.getStaticVarCompensator(staticVarCompensatorId); + if (staticVarCompensator == null) { + throw new NetworkModificationException(STATIC_VAR_COMPENSATOR_NOT_FOUND, "Static var compensator " + staticVarCompensatorId + DOES_NOT_EXIST_IN_NETWORK); + } + return staticVarCompensator; + } + public void controlConnectivity(Network network, String voltageLevelId, String busOrBusbarSectionId, Integer connectionPosition) { VoltageLevel voltageLevel = getVoltageLevel(network, voltageLevelId); if (voltageLevel.getTopologyKind() == TopologyKind.NODE_BREAKER) { @@ -280,7 +289,7 @@ public void controlVoltageLevelCreation(VoltageLevelCreationInfos voltageLevelCr throw new NetworkModificationException(CREATE_VOLTAGE_LEVEL_ERROR, "IpMax is required"); } if (Objects.nonNull(voltageLevelCreationInfos.getIpMin()) && Objects.nonNull(voltageLevelCreationInfos.getIpMax()) - && voltageLevelCreationInfos.getIpMin() > voltageLevelCreationInfos.getIpMax()) { + && voltageLevelCreationInfos.getIpMin() > voltageLevelCreationInfos.getIpMax()) { throw new NetworkModificationException(CREATE_VOLTAGE_LEVEL_ERROR, "IpMin cannot be greater than IpMax"); } } @@ -593,7 +602,7 @@ public void disconnectCreatedInjection(InjectionCreationInfos modificationInfos, if (!modificationInfos.isTerminalConnected()) { injection.getTerminal().disconnect(); subReportNode.newReportNode() - .withMessageTemplate("equipmentDisconnected", "Equipment with id=${id} disconnected") + .withMessageTemplate(EQUIPMENT_DISCONNECTED, "Equipment with id=${id} disconnected") .withUntypedValue("id", modificationInfos.getEquipmentId()) .withSeverity(TypedValue.INFO_SEVERITY) .add(); @@ -1218,10 +1227,10 @@ public void checkMaxQGreaterThanMinQ( } public void checkMaxReactivePowerGreaterThanMinReactivePower(MinMaxReactiveLimits minMaxReactiveLimits, AttributeModification minimumReactivePowerInfo, AttributeModification maximumReactivePowerInfo, NetworkModificationException.Type exceptionType, String errorMessage) { - Double previousMinimumReactivePower = minMaxReactiveLimits.getMinQ(); - Double previousMaximumReactivePower = minMaxReactiveLimits.getMaxQ(); - Double minReactivePower = minimumReactivePowerInfo != null ? minimumReactivePowerInfo.getValue() : previousMinimumReactivePower; - Double maxReactivePower = maximumReactivePowerInfo != null ? maximumReactivePowerInfo.getValue() : previousMaximumReactivePower; + double previousMinimumReactivePower = minMaxReactiveLimits.getMinQ(); + double previousMaximumReactivePower = minMaxReactiveLimits.getMaxQ(); + double minReactivePower = minimumReactivePowerInfo != null ? minimumReactivePowerInfo.getValue() : previousMinimumReactivePower; + double maxReactivePower = maximumReactivePowerInfo != null ? maximumReactivePowerInfo.getValue() : previousMaximumReactivePower; if (minReactivePower > maxReactivePower) { throw new NetworkModificationException(exceptionType, errorMessage + "maximum reactive power " + maxReactivePower + " is expected to be greater than or equal to minimum reactive power " + minReactivePower); } @@ -1292,6 +1301,43 @@ public void checkReactiveLimitsCreation(ReactiveLimitsHolderInfos modificationIn } } + public void checkReactivePowerLimitsAndSetPointsCreation(StaticVarCompensatorCreationInfos creationInfos) { + String equipmentName = "StaticVarCompensator"; + // check min max reactive limits + if (Objects.isNull(creationInfos.getMinSusceptance()) && Objects.isNull(creationInfos.getMinQAtNominalV())) { + throw makeEquipmentException(creationInfos.getErrorType(), creationInfos.getEquipmentId(), equipmentName, "minimum susceptance is not set"); + } + if (Objects.isNull(creationInfos.getMaxSusceptance()) && Objects.isNull(creationInfos.getMaxQAtNominalV())) { + throw makeEquipmentException(creationInfos.getErrorType(), creationInfos.getEquipmentId(), equipmentName, "maximum susceptance is not set"); + } + if (Objects.nonNull(creationInfos.getMaxSusceptance()) && Objects.nonNull(creationInfos.getMinSusceptance()) && creationInfos.getMaxSusceptance() < creationInfos.getMinSusceptance() || + Objects.nonNull(creationInfos.getMaxQAtNominalV()) && Objects.nonNull(creationInfos.getMinQAtNominalV()) && creationInfos.getMaxQAtNominalV() < creationInfos.getMinQAtNominalV()) { + throw makeEquipmentException(creationInfos.getErrorType(), creationInfos.getEquipmentId(), equipmentName, "maximum susceptance is expected to be greater than or equal to minimum susceptance"); + } + + // check set points + if (Objects.requireNonNull(creationInfos.getRegulationMode()) == StaticVarCompensator.RegulationMode.VOLTAGE && creationInfos.getVoltageSetpoint() == null) { + throw makeEquipmentException(creationInfos.getErrorType(), creationInfos.getEquipmentId(), equipmentName, "Voltage setpoint is not set"); + } + if (creationInfos.getRegulationMode() == StaticVarCompensator.RegulationMode.REACTIVE_POWER && creationInfos.getReactivePowerSetpoint() == null) { + throw makeEquipmentException(creationInfos.getErrorType(), creationInfos.getEquipmentId(), equipmentName, "Reactive power setpoint is not set"); + } + } + + public void checkStandbyAutomatonCreation(StaticVarCompensatorCreationInfos creationInfos) { + String equipmentName = "StaticVarCompensator"; + if (Boolean.TRUE.equals(creationInfos.isStandby()) && creationInfos.getRegulationMode() != StaticVarCompensator.RegulationMode.VOLTAGE) { + throw makeEquipmentException(creationInfos.getErrorType(), creationInfos.getEquipmentId(), equipmentName, "Standby is only supported in Voltage Regulation mode"); + } + if (Objects.nonNull(creationInfos.getB0()) && Objects.nonNull(creationInfos.getMinSusceptance()) && Objects.nonNull(creationInfos.getMaxSusceptance()) && + (creationInfos.getB0() < creationInfos.getMinSusceptance() || creationInfos.getB0() > creationInfos.getMaxSusceptance()) + || Objects.nonNull(creationInfos.getQ0()) && Objects.nonNull(creationInfos.getMinQAtNominalV()) && Objects.nonNull(creationInfos.getMaxQAtNominalV()) && + (creationInfos.getQ0() < creationInfos.getMinQAtNominalV() || creationInfos.getQ0() > creationInfos.getMaxQAtNominalV())) { + throw makeEquipmentException(creationInfos.getErrorType(), creationInfos.getEquipmentId(), equipmentName, + "b0 must be within the range of minimun susceptance and maximum susceptance"); + } + } + public static void addToReports(List reports, Double newValue, String fieldName) { if (newValue != null) { reports.add(ModificationUtils.getInstance().buildCreationReport(newValue, fieldName)); @@ -1438,5 +1484,53 @@ public static void insertReportNode(ReportNode parent, ReportNode child) { child.getChildren().forEach(grandChild -> insertReportNode(insertedChild, grandChild)); } } + + public static void createInjectionInNodeBreaker(VoltageLevel voltageLevel, InjectionCreationInfos injectionCreationInfos, + Network network, InjectionAdder injectionAdder, ReportNode subReportNode) { + int position = ModificationUtils.getInstance().getPosition(injectionCreationInfos.getConnectionPosition(), + injectionCreationInfos.getBusOrBusbarSectionId(), network, voltageLevel); + CreateFeederBay algo = new CreateFeederBayBuilder() + .withBusOrBusbarSectionId(injectionCreationInfos.getBusOrBusbarSectionId()) + .withInjectionDirection(injectionCreationInfos.getConnectionDirection()) + .withInjectionFeederName(injectionCreationInfos.getConnectionName() != null + ? injectionCreationInfos.getConnectionName() + : injectionCreationInfos.getEquipmentId()) + .withInjectionPositionOrder(position) + .withInjectionAdder(injectionAdder) + .build(); + algo.apply(network, true, subReportNode); + } + + public static void reportInjectionCreationConnectivity(InjectionCreationInfos injectionCreationInfos, ReportNode subReporter) { + if (Objects.isNull(injectionCreationInfos.getVoltageLevelId()) || Objects.isNull(injectionCreationInfos.getBusOrBusbarSectionId())) { + return; + } + + if (injectionCreationInfos.getConnectionName() != null || + injectionCreationInfos.getConnectionDirection() != null || + injectionCreationInfos.getConnectionPosition() != null) { + List connectivityReports = new ArrayList<>(); + if (injectionCreationInfos.getConnectionName() != null) { + connectivityReports.add(ModificationUtils.getInstance() + .buildCreationReport(injectionCreationInfos.getConnectionName(), CONNECTION_NAME_FIELD_NAME)); + } + if (injectionCreationInfos.getConnectionDirection() != null) { + connectivityReports.add(ModificationUtils.getInstance() + .buildCreationReport(injectionCreationInfos.getConnectionDirection(), CONNECTION_DIRECTION_FIELD_NAME)); + } + if (injectionCreationInfos.getConnectionPosition() != null) { + connectivityReports.add(ModificationUtils.getInstance() + .buildCreationReport(injectionCreationInfos.getConnectionPosition(), CONNECTION_POSITION_FIELD_NAME)); + } + if (!injectionCreationInfos.isTerminalConnected()) { + connectivityReports.add(ReportNode.newRootReportNode() + .withMessageTemplate(EQUIPMENT_DISCONNECTED, " Equipment with id=${id} disconnected") + .withUntypedValue("id", injectionCreationInfos.getEquipmentId()) + .withSeverity(TypedValue.INFO_SEVERITY) + .build()); + } + ModificationUtils.getInstance().reportModifications(subReporter, connectivityReports, "ConnectivityCreated", CONNECTIVITY); + } + } } diff --git a/src/main/java/org/gridsuite/modification/server/modifications/ShuntCompensatorCreation.java b/src/main/java/org/gridsuite/modification/server/modifications/ShuntCompensatorCreation.java index 2d957edb7..4c219d4ea 100644 --- a/src/main/java/org/gridsuite/modification/server/modifications/ShuntCompensatorCreation.java +++ b/src/main/java/org/gridsuite/modification/server/modifications/ShuntCompensatorCreation.java @@ -8,14 +8,14 @@ import com.powsybl.commons.report.ReportNode; import com.powsybl.commons.report.TypedValue; -import com.powsybl.iidm.modification.topology.CreateFeederBay; -import com.powsybl.iidm.modification.topology.CreateFeederBayBuilder; import com.powsybl.iidm.network.*; import org.gridsuite.modification.server.NetworkModificationException; import org.gridsuite.modification.server.dto.ShuntCompensatorCreationInfos; import org.gridsuite.modification.server.dto.ShuntCompensatorType; -import static org.gridsuite.modification.server.NetworkModificationException.Type.*; +import static org.gridsuite.modification.server.NetworkModificationException.Type.CREATE_SHUNT_COMPENSATOR_ERROR; +import static org.gridsuite.modification.server.NetworkModificationException.Type.SHUNT_COMPENSATOR_ALREADY_EXISTS; +import static org.gridsuite.modification.server.modifications.ModificationUtils.createInjectionInNodeBreaker; /** * @author Slimane Amar @@ -52,7 +52,7 @@ public void apply(Network network, ReportNode subReportNode) { // create the shunt compensator in the network VoltageLevel voltageLevel = ModificationUtils.getInstance().getVoltageLevel(network, modificationInfos.getVoltageLevelId()); if (modificationInfos.getMaxSusceptance() == null) { - Double maxSusceptance = (modificationInfos.getMaxQAtNominalV()) / Math.pow(voltageLevel.getNominalV(), 2); + double maxSusceptance = (modificationInfos.getMaxQAtNominalV()) / Math.pow(voltageLevel.getNominalV(), 2); modificationInfos.setMaxSusceptance( modificationInfos.getShuntCompensatorType() == ShuntCompensatorType.CAPACITOR ? maxSusceptance @@ -60,16 +60,7 @@ public void apply(Network network, ReportNode subReportNode) { } if (voltageLevel.getTopologyKind() == TopologyKind.NODE_BREAKER) { ShuntCompensatorAdder shuntCompensatorAdder = createShuntAdderInNodeBreaker(voltageLevel, modificationInfos); - var position = ModificationUtils.getInstance().getPosition(modificationInfos.getConnectionPosition(), - modificationInfos.getBusOrBusbarSectionId(), network, voltageLevel); - CreateFeederBay algo = new CreateFeederBayBuilder() - .withBbsId(modificationInfos.getBusOrBusbarSectionId()) - .withInjectionDirection(modificationInfos.getConnectionDirection()) - .withInjectionFeederName(modificationInfos.getConnectionName()) - .withInjectionPositionOrder(position) - .withInjectionAdder(shuntCompensatorAdder) - .build(); - algo.apply(network, true, subReportNode); + createInjectionInNodeBreaker(voltageLevel, modificationInfos, network, shuntCompensatorAdder, subReportNode); } else { createShuntInBusBreaker(voltageLevel, modificationInfos); subReportNode.newReportNode() diff --git a/src/main/java/org/gridsuite/modification/server/modifications/StaticVarCompensatorCreation.java b/src/main/java/org/gridsuite/modification/server/modifications/StaticVarCompensatorCreation.java new file mode 100644 index 000000000..bc99bbaa3 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/modifications/StaticVarCompensatorCreation.java @@ -0,0 +1,234 @@ +/** + * Copyright (c) 2024, 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/. + */ +package org.gridsuite.modification.server.modifications; + +import com.powsybl.commons.PowsyblException; +import com.powsybl.commons.report.ReportNode; +import com.powsybl.commons.report.TypedValue; +import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.extensions.StandbyAutomatonAdder; +import org.gridsuite.modification.server.NetworkModificationException; +import org.gridsuite.modification.server.dto.StaticVarCompensatorCreationInfos; +import org.gridsuite.modification.server.dto.VoltageRegulationType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import static org.gridsuite.modification.server.NetworkModificationException.Type.STATIC_VAR_COMPENSATOR_ALREADY_EXISTS; +import static org.gridsuite.modification.server.modifications.ModificationUtils.*; + +/** + * @author Ghazwa Rehili + */ +public class StaticVarCompensatorCreation extends AbstractModification { + + private final StaticVarCompensatorCreationInfos modificationInfos; + + public StaticVarCompensatorCreation(StaticVarCompensatorCreationInfos modificationInfos) { + this.modificationInfos = modificationInfos; + } + + @Override + public void check(Network network) throws NetworkModificationException { + if (network.getStaticVarCompensator(modificationInfos.getEquipmentId()) != null) { + throw new NetworkModificationException(STATIC_VAR_COMPENSATOR_ALREADY_EXISTS, modificationInfos.getEquipmentId()); + } + + // check connectivity + ModificationUtils.getInstance() + .controlConnectivity(network, modificationInfos.getVoltageLevelId(), + modificationInfos.getBusOrBusbarSectionId(), modificationInfos.getConnectionPosition()); + + // check reactive power limits and set points + ModificationUtils.getInstance().checkReactivePowerLimitsAndSetPointsCreation(modificationInfos); + + // check regulated terminal + VoltageLevel voltageLevel = ModificationUtils.getInstance().getVoltageLevel(network, modificationInfos.getVoltageLevelId()); + ModificationUtils.getInstance().getTerminalFromIdentifiable(voltageLevel.getNetwork(), modificationInfos.getRegulatingTerminalId(), + modificationInfos.getRegulatingTerminalType(), modificationInfos.getRegulatingTerminalVlId()); + + // check standby automaton + ModificationUtils.getInstance().checkStandbyAutomatonCreation(modificationInfos); + } + + @Override + public void apply(Network network, ReportNode subReportNode) { + // create the static var compensator in the network + VoltageLevel voltageLevel = ModificationUtils.getInstance().getVoltageLevel(network, modificationInfos.getVoltageLevelId()); + if (Objects.isNull(modificationInfos.getMaxSusceptance()) && Objects.nonNull(modificationInfos.getMaxQAtNominalV())) { + modificationInfos.setMaxSusceptance((modificationInfos.getMaxQAtNominalV()) / Math.pow(voltageLevel.getNominalV(), 2)); + } + if (Objects.isNull(modificationInfos.getMinSusceptance()) && Objects.nonNull(modificationInfos.getMinQAtNominalV())) { + modificationInfos.setMinSusceptance((modificationInfos.getMinQAtNominalV()) / Math.pow(voltageLevel.getNominalV(), 2)); + } + if (Boolean.TRUE.equals(modificationInfos.isStandbyAutomatonOn()) && Objects.isNull(modificationInfos.getB0()) + && Objects.nonNull(modificationInfos.getQ0())) { + modificationInfos.setB0((modificationInfos.getQ0()) / Math.pow(voltageLevel.getNominalV(), 2)); + } + if (voltageLevel.getTopologyKind() == TopologyKind.NODE_BREAKER) { + createStaticVarCompensatorInNodeBreaker(voltageLevel, modificationInfos, network, subReportNode); + } else { + createStaticVarCompensatorInBusBreaker(voltageLevel, modificationInfos, subReportNode); + } + ModificationUtils.getInstance().disconnectCreatedInjection(modificationInfos, network.getStaticVarCompensator(modificationInfos.getEquipmentId()), subReportNode); + // properties + StaticVarCompensator staticVarCompensator = network.getStaticVarCompensator(modificationInfos.getEquipmentId()); + PropertiesUtils.applyProperties(staticVarCompensator, subReportNode, modificationInfos.getProperties(), "StaticVarCompensatorProperties"); + subReportNode.newReportNode() + .withMessageTemplate("staticVarCompensatorCreated", "New static var compensator with id=${id} created") + .withUntypedValue("id", modificationInfos.getEquipmentId()) + .withSeverity(TypedValue.INFO_SEVERITY) + .add(); + } + + private void createStaticVarCompensatorInNodeBreaker(VoltageLevel voltageLevel, StaticVarCompensatorCreationInfos staticVarCompensatorCreationInfos, + Network network, ReportNode subReportNode) { + StaticVarCompensatorAdder staticVarCompensatorAdder = createStaticVarCompensatorAdderInNodeBreaker(voltageLevel, staticVarCompensatorCreationInfos); + createInjectionInNodeBreaker(voltageLevel, staticVarCompensatorCreationInfos, network, staticVarCompensatorAdder, subReportNode); + var staticVarCompensator = ModificationUtils.getInstance().getStaticVarCompensator(network, staticVarCompensatorCreationInfos.getEquipmentId()); + addExtensionsToStaticVarCompensator(staticVarCompensatorCreationInfos, staticVarCompensator, voltageLevel, subReportNode); + } + + private StaticVarCompensatorAdder createStaticVarCompensatorAdderInNodeBreaker(VoltageLevel voltageLevel, StaticVarCompensatorCreationInfos staticVarCompensatorCreationInfos) { + Terminal terminal = ModificationUtils.getInstance().getTerminalFromIdentifiable(voltageLevel.getNetwork(), + staticVarCompensatorCreationInfos.getRegulatingTerminalId(), + staticVarCompensatorCreationInfos.getRegulatingTerminalType(), + staticVarCompensatorCreationInfos.getRegulatingTerminalVlId()); + + StaticVarCompensatorAdder staticVarCompensatorAdder = voltageLevel.newStaticVarCompensator() + .setId(staticVarCompensatorCreationInfos.getEquipmentId()) + .setName(staticVarCompensatorCreationInfos.getEquipmentName()) + .setBmax(nanIfNull(staticVarCompensatorCreationInfos.getMaxSusceptance())) + .setBmin(nanIfNull(staticVarCompensatorCreationInfos.getMinSusceptance())) + .setVoltageSetpoint(nanIfNull(staticVarCompensatorCreationInfos.getVoltageSetpoint())) + .setReactivePowerSetpoint(nanIfNull(staticVarCompensatorCreationInfos.getReactivePowerSetpoint())) + .setRegulationMode(staticVarCompensatorCreationInfos.getRegulationMode()); + + if (terminal != null) { + staticVarCompensatorAdder.setRegulatingTerminal(terminal); + } + + return staticVarCompensatorAdder; + } + + private void addExtensionsToStaticVarCompensator(StaticVarCompensatorCreationInfos staticVarCompensatorCreationInfos, + StaticVarCompensator staticVarCompensator, + VoltageLevel voltageLevel, + ReportNode subReportNode) { + if (staticVarCompensatorCreationInfos.getEquipmentName() != null) { + ModificationUtils.getInstance().reportElementaryCreation(subReportNode, staticVarCompensatorCreationInfos.getEquipmentName(), "Name"); + } + + reportInjectionCreationConnectivity(staticVarCompensatorCreationInfos, subReportNode); + createStaticVarCompensatorVoltageRegulation(staticVarCompensatorCreationInfos, staticVarCompensator, voltageLevel, subReportNode); + reportStaticVarCompensatorStandbyAutomaton(staticVarCompensatorCreationInfos, staticVarCompensator, subReportNode); + } + + private void reportStaticVarCompensatorStandbyAutomaton(StaticVarCompensatorCreationInfos staticVarCompensatorCreationInfos, + StaticVarCompensator staticVarCompensator, ReportNode subReportNode) { + if (Boolean.TRUE.equals(staticVarCompensatorCreationInfos.isStandbyAutomatonOn())) { + List standbyAutomatonReports = new ArrayList<>(); + try { + staticVarCompensator.newExtension(StandbyAutomatonAdder.class) + .withStandbyStatus(staticVarCompensatorCreationInfos.isStandby()) + .withB0(staticVarCompensatorCreationInfos.getB0()) + .withLowVoltageSetpoint(staticVarCompensatorCreationInfos.getLowVoltageSetpoint()) + .withHighVoltageSetpoint(staticVarCompensatorCreationInfos.getHighVoltageSetpoint()) + .withLowVoltageThreshold(staticVarCompensatorCreationInfos.getLowVoltageThreshold()) + .withHighVoltageThreshold(staticVarCompensatorCreationInfos.getHighVoltageThreshold()) + .add(); + standbyAutomatonReports.add(ModificationUtils.getInstance().buildCreationReport( + staticVarCompensatorCreationInfos.isStandby(), + "Standby")); + standbyAutomatonReports.add(ModificationUtils.getInstance().buildCreationReport( + staticVarCompensatorCreationInfos.getB0(), + "Fixed part of susceptance")); + standbyAutomatonReports.add(ModificationUtils.getInstance().buildCreationReport( + staticVarCompensatorCreationInfos.getLowVoltageSetpoint(), + "Low voltage set point")); + standbyAutomatonReports.add(ModificationUtils.getInstance().buildCreationReport( + staticVarCompensatorCreationInfos.getHighVoltageSetpoint(), + "High voltage set point")); + standbyAutomatonReports.add(ModificationUtils.getInstance().buildCreationReport( + staticVarCompensatorCreationInfos.getHighVoltageThreshold(), + "High voltage threshold")); + standbyAutomatonReports.add(ModificationUtils.getInstance().buildCreationReport( + staticVarCompensatorCreationInfos.getLowVoltageThreshold(), + "Low voltage threshold")); + } catch (PowsyblException e) { + standbyAutomatonReports.add(ReportNode.newRootReportNode() + .withMessageTemplate("StandbyAutomatonExtensionAddError", + "Cannot add standby automaton extension on static var compensator with id=${id} : ${message}") + .withUntypedValue("id", staticVarCompensatorCreationInfos.getEquipmentId()) + .withUntypedValue("message", e.getMessage()) + .withSeverity(TypedValue.ERROR_SEVERITY) + .build()); + + } + ModificationUtils.getInstance().reportModifications(subReportNode, standbyAutomatonReports, + "StandbyAutomatonCreated", "Standby automaton"); + } + } + + private void createStaticVarCompensatorInBusBreaker(VoltageLevel voltageLevel, StaticVarCompensatorCreationInfos staticVarCompensatorCreationInfos, + ReportNode subReportNode) { + + Bus bus = ModificationUtils.getInstance().getBusBreakerBus(voltageLevel, staticVarCompensatorCreationInfos.getBusOrBusbarSectionId()); + /* creating the static var compensator */ + StaticVarCompensator staticVarCompensator = voltageLevel.newStaticVarCompensator() + .setId(staticVarCompensatorCreationInfos.getEquipmentId()) + .setName(staticVarCompensatorCreationInfos.getEquipmentName()) + .setBus(bus.getId()) + .setConnectableBus(bus.getId()) + .setBmax(staticVarCompensatorCreationInfos.getMaxSusceptance()) + .setBmin(staticVarCompensatorCreationInfos.getMinSusceptance()) + .setVoltageSetpoint(staticVarCompensatorCreationInfos.getVoltageSetpoint()) + .setReactivePowerSetpoint(staticVarCompensatorCreationInfos.getReactivePowerSetpoint()) + .setRegulationMode(staticVarCompensatorCreationInfos.getRegulationMode()) + .add(); + + addExtensionsToStaticVarCompensator(staticVarCompensatorCreationInfos, staticVarCompensator, voltageLevel, subReportNode); + } + + private void createStaticVarCompensatorVoltageRegulation(StaticVarCompensatorCreationInfos staticVarCompensatorCreationInfos, + StaticVarCompensator staticVarCompensator, VoltageLevel voltageLevel, ReportNode subReportNode) { + List voltageReports = new ArrayList<>(); + voltageReports.add(ModificationUtils.getInstance() + .createEnabledDisabledReport("VoltageRegulationOn", modificationInfos.getVoltageRegulationType() == VoltageRegulationType.DISTANT && + modificationInfos.getRegulationMode() == StaticVarCompensator.RegulationMode.VOLTAGE)); + voltageReports.add(ModificationUtils.getInstance().buildCreationReport(staticVarCompensatorCreationInfos.getVoltageSetpoint(), "Voltage set point")); + if (staticVarCompensatorCreationInfos.getRegulatingTerminalVlId() != null && staticVarCompensatorCreationInfos.getRegulatingTerminalId() != null && + staticVarCompensatorCreationInfos.getRegulatingTerminalType() != null) { + Terminal terminal = ModificationUtils.getInstance().getTerminalFromIdentifiable(voltageLevel.getNetwork(), + staticVarCompensatorCreationInfos.getRegulatingTerminalId(), + staticVarCompensatorCreationInfos.getRegulatingTerminalType(), + staticVarCompensatorCreationInfos.getRegulatingTerminalVlId()); + if (terminal != null) { + updateCompensatorRegulatingTerminal(staticVarCompensatorCreationInfos, staticVarCompensator, terminal, voltageReports); + } + } + ModificationUtils.getInstance().reportModifications(subReportNode, voltageReports, "VoltageRegulationCreated", "Voltage regulation"); + } + + private void updateCompensatorRegulatingTerminal(StaticVarCompensatorCreationInfos staticVarCompensatorCreationInfos, StaticVarCompensator staticVarCompensator, + Terminal terminal, List voltageReports) { + if (staticVarCompensatorCreationInfos.getRegulatingTerminalId() != null + && staticVarCompensatorCreationInfos.getRegulatingTerminalType() != null + && staticVarCompensatorCreationInfos.getRegulatingTerminalVlId() != null) { + staticVarCompensator.setRegulatingTerminal(terminal); + voltageReports.add(ModificationUtils.getInstance().buildCreationReport( + staticVarCompensatorCreationInfos.getRegulatingTerminalVlId(), + "Voltage level")); + voltageReports.add(ModificationUtils.getInstance().buildCreationReport( + staticVarCompensatorCreationInfos.getRegulatingTerminalType() + ":" + + staticVarCompensatorCreationInfos.getRegulatingTerminalId(), + "Equipment")); + } + } + +} diff --git a/src/main/java/org/gridsuite/modification/server/modifications/VscCreation.java b/src/main/java/org/gridsuite/modification/server/modifications/VscCreation.java index 4e4540e1c..8d0e0862e 100644 --- a/src/main/java/org/gridsuite/modification/server/modifications/VscCreation.java +++ b/src/main/java/org/gridsuite/modification/server/modifications/VscCreation.java @@ -9,8 +9,6 @@ import com.powsybl.commons.report.ReportNode; import com.powsybl.commons.report.TypedValue; -import com.powsybl.iidm.modification.topology.CreateFeederBay; -import com.powsybl.iidm.modification.topology.CreateFeederBayBuilder; import com.powsybl.iidm.network.*; import com.powsybl.iidm.network.extensions.HvdcAngleDroopActivePowerControlAdder; import com.powsybl.iidm.network.extensions.HvdcOperatorActivePowerRangeAdder; @@ -22,6 +20,8 @@ import java.util.List; import static org.gridsuite.modification.server.NetworkModificationException.Type.*; +import static org.gridsuite.modification.server.modifications.ModificationUtils.createInjectionInNodeBreaker; +import static org.gridsuite.modification.server.modifications.ModificationUtils.reportInjectionCreationConnectivity; /** * @author Seddik Yengui @@ -212,22 +212,7 @@ private VscConverterStation createConverterStationInNodeBreaker(Network network, if (converterStationCreationInfos.getVoltageSetpoint() != null) { converterStationAdder.setVoltageSetpoint(converterStationCreationInfos.getVoltageSetpoint()); } - int position = ModificationUtils.getInstance().getPosition(converterStationCreationInfos.getConnectionPosition(), - converterStationCreationInfos.getBusOrBusbarSectionId(), - network, - voltageLevel); - - CreateFeederBay algo = new CreateFeederBayBuilder() - .withBusOrBusbarSectionId(converterStationCreationInfos.getBusOrBusbarSectionId()) - .withInjectionDirection(converterStationCreationInfos.getConnectionDirection()) - .withInjectionFeederName(converterStationCreationInfos.getConnectionName() != null - ? converterStationCreationInfos.getConnectionName() - : converterStationCreationInfos.getEquipmentId()) - .withInjectionPositionOrder(position) - .withInjectionAdder(converterStationAdder) - .build(); - - algo.apply(network, true, subReportNode); + createInjectionInNodeBreaker(voltageLevel, converterStationCreationInfos, network, converterStationAdder, subReportNode); VscConverterStation vscConverterStation = ModificationUtils.getInstance() .getVscConverterStation(network, converterStationCreationInfos.getEquipmentId()); @@ -261,7 +246,7 @@ private VscConverterStation createConverterStationInBusBreaker(VoltageLevel volt private void addExtensionsAndReports(VscConverterStation vscConverterStation, ConverterStationCreationInfos converterStationCreationInfos, ReportNode subReporter) { - reportConnectivity(converterStationCreationInfos, subReporter); + reportInjectionCreationConnectivity(converterStationCreationInfos, subReporter); ModificationUtils.getInstance().reportModifications(subReporter, List.of(ModificationUtils.getInstance().buildCreationReport(converterStationCreationInfos.getLossFactor(), "Loss Factor")), @@ -294,34 +279,4 @@ private void reportConverterStationSetPoints(ConverterStationCreationInfos conve "converterStationSetPointsVoltageRegulation", "Voltage regulation"); } - - private void reportConnectivity(ConverterStationCreationInfos converterStationCreationInfos, ReportNode subReportNode) { - if (converterStationCreationInfos.getConnectionName() == null && - converterStationCreationInfos.getConnectionDirection() == null && - converterStationCreationInfos.getConnectionPosition() == null) { - return; - } - - List connectivityReports = new ArrayList<>(); - if (converterStationCreationInfos.getConnectionName() != null) { - connectivityReports.add(ModificationUtils.getInstance() - .buildCreationReport(converterStationCreationInfos.getConnectionName(), "Connection name")); - } - if (converterStationCreationInfos.getConnectionDirection() != null) { - connectivityReports.add(ModificationUtils.getInstance() - .buildCreationReport(converterStationCreationInfos.getConnectionDirection(), "Connection direction")); - } - if (converterStationCreationInfos.getConnectionPosition() != null) { - connectivityReports.add(ModificationUtils.getInstance() - .buildCreationReport(converterStationCreationInfos.getConnectionPosition(), "Connection position")); - } - if (!converterStationCreationInfos.isTerminalConnected()) { - connectivityReports.add(ReportNode.newRootReportNode() - .withMessageTemplate("equipmentDisconnected", " Equipment with id=${id} disconnected") - .withUntypedValue("id", converterStationCreationInfos.getEquipmentId()) - .withSeverity(TypedValue.INFO_SEVERITY) - .build()); - } - ModificationUtils.getInstance().reportModifications(subReportNode, connectivityReports, "ConnectivityCreated", "Connectivity"); - } } diff --git a/src/main/resources/db/changelog/changesets/changelog_20240912T100256Z.xml b/src/main/resources/db/changelog/changesets/changelog_20240912T100256Z.xml new file mode 100644 index 000000000..9a6dd2ebd --- /dev/null +++ b/src/main/resources/db/changelog/changesets/changelog_20240912T100256Z.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 1e8120d72..4ef96dc04 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -310,5 +310,8 @@ databaseChangeLog: file: changesets/changelog_20240904T211456Z.xml relativeToChangelogFile: true - include: - file: changesets/changelog_20240912T130742Z.xml + file: changesets/changelog_20240912T100256Z.xml + relativeToChangelogFile: true + - include: relativeToChangelogFile: true + file: changesets/changelog_20240912T130742Z.xml diff --git a/src/test/java/org/gridsuite/modification/server/modifications/StaticVarCompensatorCreationInBusBreakerTest.java b/src/test/java/org/gridsuite/modification/server/modifications/StaticVarCompensatorCreationInBusBreakerTest.java new file mode 100644 index 000000000..d1b9ee08d --- /dev/null +++ b/src/test/java/org/gridsuite/modification/server/modifications/StaticVarCompensatorCreationInBusBreakerTest.java @@ -0,0 +1,147 @@ +/** + * Copyright (c) 2024, 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/. + */ +package org.gridsuite.modification.server.modifications; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.StaticVarCompensator; +import com.powsybl.iidm.network.extensions.ConnectablePosition; +import lombok.SneakyThrows; +import org.gridsuite.modification.server.NetworkModificationException; +import org.gridsuite.modification.server.dto.FreePropertyInfos; +import org.gridsuite.modification.server.dto.ModificationInfos; +import org.gridsuite.modification.server.dto.StaticVarCompensatorCreationInfos; +import org.gridsuite.modification.server.dto.VoltageRegulationType; +import org.gridsuite.modification.server.utils.NetworkCreation; +import org.junit.Test; +import org.junit.jupiter.api.Tag; +import org.springframework.http.MediaType; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static org.gridsuite.modification.server.NetworkModificationException.Type.*; +import static org.gridsuite.modification.server.utils.TestUtils.assertLogMessage; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author Ghazwa Rehili + */ +@Tag("IntegrationTest") +public class StaticVarCompensatorCreationInBusBreakerTest extends AbstractNetworkModificationTest { + private static final String PROPERTY_NAME = "property-name"; + private static final String PROPERTY_VALUE = "property-value"; + + @Override + protected Network createNetwork(UUID networkUuid) { + return NetworkCreation.createBusBreaker(networkUuid); + } + + @Override + protected ModificationInfos buildModification() { + return StaticVarCompensatorCreationInfos.builder() + .stashed(false) + .equipmentId("idStaticVarCompensator2") + .equipmentName("nameStaticVarCompensator2") + .voltageLevelId("v1") + .busOrBusbarSectionId("bus1") + .connectionName("top") + .connectionDirection(ConnectablePosition.Direction.TOP) + .maxSusceptance(224.0) + .minSusceptance(200.0) + .regulationMode(StaticVarCompensator.RegulationMode.VOLTAGE) + .voltageSetpoint(120.0) + .reactivePowerSetpoint(300.0) + .voltageRegulationType(VoltageRegulationType.DISTANT) + .regulatingTerminalVlId("v1") + .regulatingTerminalId("idGenerator1") + .regulatingTerminalType("GENERATOR") + .standbyAutomatonOn(true) + .standby(true) + .b0(221.0) + .lowVoltageSetpoint(200.0) + .highVoltageSetpoint(400.0) + .lowVoltageThreshold(250.0) + .highVoltageThreshold(300.0) + .properties(List.of(FreePropertyInfos.builder().name(PROPERTY_NAME).value(PROPERTY_VALUE).build())) + .build(); + } + + @Override + protected ModificationInfos buildModificationUpdate() { + return StaticVarCompensatorCreationInfos.builder() + .stashed(false) + .equipmentId("idStaticVarCompensator2Edited") + .equipmentName("staticVarCompensatorNameEdited") + .voltageRegulationType(VoltageRegulationType.LOCAL) + .regulatingTerminalId("idStaticVarCompensator1") + .regulatingTerminalType("STATIC_VAR_COMPENSATOR") + .regulatingTerminalVlId("v1") + .build(); + } + + @Override + protected void assertAfterNetworkModificationCreation() { + assertNotNull(getNetwork().getStaticVarCompensator("idStaticVarCompensator2")); + assertEquals(1, getNetwork().getVoltageLevel("v1").getStaticVarCompensatorStream() + .filter(transformer -> transformer.getId().equals("idStaticVarCompensator2")).count()); + assertEquals(PROPERTY_VALUE, getNetwork().getStaticVarCompensator("idStaticVarCompensator2").getProperty(PROPERTY_NAME)); + } + + @Override + protected void assertAfterNetworkModificationDeletion() { + assertNull(getNetwork().getStaticVarCompensator("idStaticVarCompensator2")); + assertEquals(0, getNetwork().getVoltageLevel("v1").getStaticVarCompensatorStream() + .filter(transformer -> transformer.getId().equals("idStaticVarCompensator2")).count()); + } + + @Test + public void testCreateWithBusBarSectionErrors() throws Exception { + StaticVarCompensatorCreationInfos staticVarCompensatorCreationInfos = (StaticVarCompensatorCreationInfos) buildModification(); + staticVarCompensatorCreationInfos.setBusOrBusbarSectionId("notFoundBus"); + mockMvc.perform(post(getNetworkModificationUri()).content(mapper.writeValueAsString(staticVarCompensatorCreationInfos)).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + assertLogMessage(new NetworkModificationException(BUS_NOT_FOUND, "notFoundBus").getMessage(), + staticVarCompensatorCreationInfos.getErrorType().name(), reportService); + } + + @Test + public void testCreateWithRegulatedTerminalError() throws Exception { + StaticVarCompensatorCreationInfos staticVarCompensatorCreationInfos = (StaticVarCompensatorCreationInfos) buildModification(); + staticVarCompensatorCreationInfos.setVoltageRegulationType(VoltageRegulationType.DISTANT); + staticVarCompensatorCreationInfos.setRegulatingTerminalVlId("v1"); + staticVarCompensatorCreationInfos.setRegulatingTerminalId("test"); + staticVarCompensatorCreationInfos.setRegulatingTerminalType("STATIC_VAR_COMPENSATOR"); + + String staticVarCompensatorInfosJson = mapper.writeValueAsString(staticVarCompensatorCreationInfos); + mockMvc.perform(post(getNetworkModificationUri()).content(staticVarCompensatorInfosJson).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + assertLogMessage(new NetworkModificationException(EQUIPMENT_NOT_FOUND, "Equipment with id=test not found with type STATIC_VAR_COMPENSATOR").getMessage(), + staticVarCompensatorCreationInfos.getErrorType().name(), reportService); + } + + @Override + @SneakyThrows + protected void testCreationModificationMessage(ModificationInfos modificationInfos) { + assertEquals("STATIC_VAR_COMPENSATOR_CREATION", modificationInfos.getMessageType()); + Map createdValues = mapper.readValue(modificationInfos.getMessageValues(), new TypeReference<>() { }); + assertEquals("idStaticVarCompensator2", createdValues.get("equipmentId")); + } + + @Override + @SneakyThrows + protected void testUpdateModificationMessage(ModificationInfos modificationInfos) { + assertEquals("STATIC_VAR_COMPENSATOR_CREATION", modificationInfos.getMessageType()); + Map createdValues = mapper.readValue(modificationInfos.getMessageValues(), new TypeReference<>() { }); + assertEquals("idStaticVarCompensator2Edited", createdValues.get("equipmentId")); + } +} diff --git a/src/test/java/org/gridsuite/modification/server/modifications/StaticVarCompensatorCreationInNodeBreakerTest.java b/src/test/java/org/gridsuite/modification/server/modifications/StaticVarCompensatorCreationInNodeBreakerTest.java new file mode 100644 index 000000000..eed31aafb --- /dev/null +++ b/src/test/java/org/gridsuite/modification/server/modifications/StaticVarCompensatorCreationInNodeBreakerTest.java @@ -0,0 +1,240 @@ +/** + * Copyright (c) 2024, 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/. + */ +package org.gridsuite.modification.server.modifications; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.StaticVarCompensator; +import com.powsybl.iidm.network.extensions.ConnectablePosition; +import lombok.SneakyThrows; +import org.gridsuite.modification.server.NetworkModificationException; +import org.gridsuite.modification.server.dto.*; +import org.gridsuite.modification.server.utils.NetworkCreation; +import org.junit.Test; +import org.junit.jupiter.api.Tag; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MvcResult; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +import static com.powsybl.iidm.network.StaticVarCompensator.RegulationMode.OFF; +import static org.gridsuite.modification.server.NetworkModificationException.Type.BUSBAR_SECTION_NOT_FOUND; +import static org.gridsuite.modification.server.NetworkModificationException.Type.VOLTAGE_LEVEL_NOT_FOUND; +import static org.gridsuite.modification.server.utils.TestUtils.assertLogMessage; +import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author Ghazwa Rehili + */ +@Tag("IntegrationTest") +public class StaticVarCompensatorCreationInNodeBreakerTest extends AbstractNetworkModificationTest { + private static final String PROPERTY_NAME = "property-name"; + private static final String PROPERTY_VALUE = "property-value"; + + @Override + protected Network createNetwork(UUID networkUuid) { + return NetworkCreation.create(networkUuid, true); + } + + @Override + protected ModificationInfos buildModification() { + return StaticVarCompensatorCreationInfos.builder() + .stashed(false) + .equipmentId("idStaticVarCompensator1") + .equipmentName("nameStaticVarCompensator1") + .voltageLevelId("v2") + .busOrBusbarSectionId("1B") + .connectionName("top") + .connectionDirection(ConnectablePosition.Direction.TOP) + .maxSusceptance(224.0) + .minSusceptance(200.0) + .regulationMode(StaticVarCompensator.RegulationMode.VOLTAGE) + .voltageSetpoint(120.0) + .reactivePowerSetpoint(300.0) + .voltageRegulationType(VoltageRegulationType.LOCAL) + .standbyAutomatonOn(false) + .properties(List.of(FreePropertyInfos.builder().name(PROPERTY_NAME).value(PROPERTY_VALUE).build())) + .build(); + } + + @Override + protected ModificationInfos buildModificationUpdate() { + return StaticVarCompensatorCreationInfos.builder() + .stashed(false) + .equipmentId("idStaticVarCompensator1Edited") + .equipmentName("staticVarCompensatorNameEdited") + .standbyAutomatonOn(true) + .standby(true) + .b0(221.0) + .lowVoltageSetpoint(200.0) + .highVoltageSetpoint(400.0) + .lowVoltageThreshold(250.0) + .highVoltageThreshold(300.0) + .voltageRegulationType(VoltageRegulationType.DISTANT) + .regulatingTerminalId("idStaticVarCompensator1") + .regulatingTerminalType("STATIC_VAR_COMPENSATOR") + .regulatingTerminalVlId("v2") + .build(); + } + + @Override + protected void assertAfterNetworkModificationCreation() { + assertNotNull(getNetwork().getStaticVarCompensator("idStaticVarCompensator1")); + assertEquals(1, getNetwork().getVoltageLevel("v2").getStaticVarCompensatorStream() + .filter(transformer -> transformer.getId().equals("idStaticVarCompensator1")).count()); + assertEquals(PROPERTY_VALUE, getNetwork().getStaticVarCompensator("idStaticVarCompensator1").getProperty(PROPERTY_NAME)); + } + + @Override + protected void assertAfterNetworkModificationDeletion() { + assertNull(getNetwork().getStaticVarCompensator("idStaticVarCompensator2")); + assertEquals(0, getNetwork().getVoltageLevel("v2").getStaticVarCompensatorStream() + .filter(transformer -> transformer.getId().equals("idStaticVarCompensator2")).count()); + } + + @Test + public void testCreateWithErrors() throws Exception { + // invalid Generator id + StaticVarCompensatorCreationInfos compensatorCreationInfos = (StaticVarCompensatorCreationInfos) buildModification(); + compensatorCreationInfos.setEquipmentId(""); + String compensatorCreationInfosJson = mapper.writeValueAsString(compensatorCreationInfos); + mockMvc.perform(post(getNetworkModificationUri()).content(compensatorCreationInfosJson).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + assertLogMessage("Invalid id ''", compensatorCreationInfos.getErrorType().name(), reportService); + + // not found voltage level + compensatorCreationInfos.setEquipmentId("idStaticVarCompensator2"); + compensatorCreationInfos.setVoltageLevelId("notFoundVoltageLevelId"); + compensatorCreationInfosJson = mapper.writeValueAsString(compensatorCreationInfos); + mockMvc.perform(post(getNetworkModificationUri()).content(compensatorCreationInfosJson).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + assertLogMessage(new NetworkModificationException(VOLTAGE_LEVEL_NOT_FOUND, "notFoundVoltageLevelId").getMessage(), + compensatorCreationInfos.getErrorType().name(), reportService); + + // not found busbar section + compensatorCreationInfos.setVoltageLevelId("v2"); + compensatorCreationInfos.setBusOrBusbarSectionId("notFoundBusbarSection"); + compensatorCreationInfosJson = mapper.writeValueAsString(compensatorCreationInfos); + mockMvc.perform(post(getNetworkModificationUri()).content(compensatorCreationInfosJson).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + assertLogMessage(new NetworkModificationException(BUSBAR_SECTION_NOT_FOUND, "notFoundBusbarSection").getMessage(), + compensatorCreationInfos.getErrorType().name(), reportService); + + // invalid min susceptance + compensatorCreationInfos.setVoltageLevelId("v2"); + compensatorCreationInfos.setBusOrBusbarSectionId("1B"); + compensatorCreationInfos.setMinSusceptance(null); + compensatorCreationInfos.setMinQAtNominalV(null); + + compensatorCreationInfosJson = mapper.writeValueAsString(compensatorCreationInfos); + mockMvc.perform(post(getNetworkModificationUri()).content(compensatorCreationInfosJson).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + assertLogMessage("CREATE_STATIC_VAR_COMPENSATOR_ERROR : StaticVarCompensator 'idStaticVarCompensator2' : minimum susceptance is not set", + compensatorCreationInfos.getErrorType().name(), reportService); + compensatorCreationInfos.setMinSusceptance(200.0); + compensatorCreationInfos.setMaxSusceptance(null); + compensatorCreationInfos.setMaxQAtNominalV(null); + compensatorCreationInfosJson = mapper.writeValueAsString(compensatorCreationInfos); + mockMvc.perform(post(getNetworkModificationUri()).content(compensatorCreationInfosJson).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + assertLogMessage("CREATE_STATIC_VAR_COMPENSATOR_ERROR : " + + "StaticVarCompensator 'idStaticVarCompensator2' : maximum susceptance is not set", + compensatorCreationInfos.getErrorType().name(), reportService); + + compensatorCreationInfos.setMaxSusceptance(100.0); + compensatorCreationInfos.setMinSusceptance(200.0); + compensatorCreationInfos.setRegulationMode(StaticVarCompensator.RegulationMode.REACTIVE_POWER); + compensatorCreationInfos.setReactivePowerSetpoint(null); + compensatorCreationInfosJson = mapper.writeValueAsString(compensatorCreationInfos); + mockMvc.perform(post(getNetworkModificationUri()).content(compensatorCreationInfosJson).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + assertLogMessage("CREATE_STATIC_VAR_COMPENSATOR_ERROR : " + + "StaticVarCompensator 'idStaticVarCompensator2' : maximum susceptance is expected to be greater than or equal to minimum susceptance", + compensatorCreationInfos.getErrorType().name(), reportService); + compensatorCreationInfos.setMaxSusceptance(200.0); + compensatorCreationInfos.setMinSusceptance(100.0); + compensatorCreationInfos.setRegulationMode(StaticVarCompensator.RegulationMode.REACTIVE_POWER); + compensatorCreationInfos.setReactivePowerSetpoint(null); + compensatorCreationInfosJson = mapper.writeValueAsString(compensatorCreationInfos); + mockMvc.perform(post(getNetworkModificationUri()).content(compensatorCreationInfosJson).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + assertLogMessage("CREATE_STATIC_VAR_COMPENSATOR_ERROR : " + + "StaticVarCompensator 'idStaticVarCompensator2' : Reactive power setpoint is not set", + compensatorCreationInfos.getErrorType().name(), reportService); + + compensatorCreationInfos.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE); + compensatorCreationInfos.setVoltageSetpoint(null); + compensatorCreationInfosJson = mapper.writeValueAsString(compensatorCreationInfos); + mockMvc.perform(post(getNetworkModificationUri()).content(compensatorCreationInfosJson).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + assertLogMessage("CREATE_STATIC_VAR_COMPENSATOR_ERROR : " + + "StaticVarCompensator 'idStaticVarCompensator2' : Voltage setpoint is not set", + compensatorCreationInfos.getErrorType().name(), reportService); + compensatorCreationInfos.setEquipmentId("idStaticVarCompensator3"); + compensatorCreationInfos.setEquipmentName("nameStaticVarCompensator3"); + compensatorCreationInfos.setVoltageLevelId("v2"); + compensatorCreationInfos.setBusOrBusbarSectionId("1B"); + compensatorCreationInfosJson = mapper.writeValueAsString(compensatorCreationInfos); + MvcResult mvcResult = mockMvc.perform(post(getNetworkModificationUriWithBadVariant()).content(compensatorCreationInfosJson).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andReturn(); + Optional networkModificationResult = mapper.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<>() { + }); + assertTrue(networkModificationResult.isEmpty()); + assertNull(getNetwork().getStaticVarCompensator("idStaticVarCompensator3")); + testNetworkModificationsCount(getGroupId(), 9); + } + + @Test + public void testCreateWithStandbyAutomatonErrors() throws Exception { + StaticVarCompensatorCreationInfos compensatorCreationInfos = (StaticVarCompensatorCreationInfos) buildModification(); + compensatorCreationInfos.setStandbyAutomatonOn(true); + compensatorCreationInfos.setB0(300.0); + + String compensatorCreationInfosJson = mapper.writeValueAsString(compensatorCreationInfos); + mockMvc.perform(post(getNetworkModificationUri()).content(compensatorCreationInfosJson).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + assertLogMessage("CREATE_STATIC_VAR_COMPENSATOR_ERROR : " + + "StaticVarCompensator 'idStaticVarCompensator1' : b0 must be within the range of minimun susceptance and maximum susceptance", + compensatorCreationInfos.getErrorType().name(), reportService); + + compensatorCreationInfos.setB0(200.0); + compensatorCreationInfos.setRegulationMode(OFF); + compensatorCreationInfos.setStandby(true); + + compensatorCreationInfosJson = mapper.writeValueAsString(compensatorCreationInfos); + mockMvc.perform(post(getNetworkModificationUri()).content(compensatorCreationInfosJson).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + assertLogMessage("CREATE_STATIC_VAR_COMPENSATOR_ERROR : " + + "StaticVarCompensator 'idStaticVarCompensator1' : Standby is only supported in Voltage Regulation mode", + compensatorCreationInfos.getErrorType().name(), reportService); + + } + + @Override + @SneakyThrows + protected void testCreationModificationMessage(ModificationInfos modificationInfos) { + assertEquals("STATIC_VAR_COMPENSATOR_CREATION", modificationInfos.getMessageType()); + Map updatedValues = mapper.readValue(modificationInfos.getMessageValues(), new TypeReference<>() { + }); + assertEquals("idStaticVarCompensator1", updatedValues.get("equipmentId")); + } + + @Override + @SneakyThrows + protected void testUpdateModificationMessage(ModificationInfos modificationInfos) { + assertEquals("STATIC_VAR_COMPENSATOR_CREATION", modificationInfos.getMessageType()); + Map updatedValues = mapper.readValue(modificationInfos.getMessageValues(), new TypeReference<>() { + }); + assertEquals("idStaticVarCompensator1Edited", updatedValues.get("equipmentId")); + } +} diff --git a/src/test/java/org/gridsuite/modification/server/service/ModificationRepositoryTest.java b/src/test/java/org/gridsuite/modification/server/service/ModificationRepositoryTest.java index 4c72c8a2f..643898006 100644 --- a/src/test/java/org/gridsuite/modification/server/service/ModificationRepositoryTest.java +++ b/src/test/java/org/gridsuite/modification/server/service/ModificationRepositoryTest.java @@ -35,9 +35,11 @@ import java.util.*; import java.util.stream.Collectors; +import static com.powsybl.iidm.network.StaticVarCompensator.RegulationMode.VOLTAGE; import static org.gridsuite.modification.server.NetworkModificationException.Type.MODIFICATION_GROUP_NOT_FOUND; import static org.gridsuite.modification.server.NetworkModificationException.Type.MODIFICATION_NOT_FOUND; import static org.gridsuite.modification.server.NetworkModificationException.Type.MOVE_MODIFICATION_ERROR; +import static org.gridsuite.modification.server.dto.VoltageRegulationType.DISTANT; import static org.gridsuite.modification.server.utils.TestUtils.assertRequestsCount; import static org.gridsuite.modification.server.utils.assertions.Assertions.assertThat; import static org.junit.Assert.*; @@ -103,6 +105,10 @@ public ShuntCompensatorCreationInfos getShuntCompensatorCreationModification(UUI return (ShuntCompensatorCreationInfos) networkModificationRepository.getModificationInfo(modificationUuid); } + private StaticVarCompensatorCreationInfos getStaticVarCompensatorCreationModification(UUID modificationUuid) { + return (StaticVarCompensatorCreationInfos) networkModificationRepository.getModificationInfo(modificationUuid); + } + private LineSplitWithVoltageLevelInfos getLineSplitWithVoltageLevelModification(UUID modificationUuid) { return (LineSplitWithVoltageLevelInfos) networkModificationRepository.getModificationInfo(modificationUuid); } @@ -1272,4 +1278,71 @@ public void testModificationOrder() { assertEquals(1, movedEntities.size()); assertEquals(0, movedEntities.get(0).getModificationsOrder()); } + + @Test + public void testStaticVarCompensatorCreation() { + var createStaticVarCompensator1 = StaticVarCompensatorCreationInfos.builder() + .equipmentId("idStaticVarCompensator1").equipmentName("nameStaticVarCompensator1") + .voltageLevelId("vlId1") + .busOrBusbarSectionId("busId1") + .minSusceptance(200.0) + .maxSusceptance(224.0) + .regulationMode(VOLTAGE) + .voltageSetpoint(200.0) + .voltageRegulationType(DISTANT) + .regulatingTerminalId("testTerminalId1") + .regulatingTerminalType("STATIC_VAR_COMPENSATOR").regulatingTerminalVlId("idVlTest1") + .connectionName("Top").connectionDirection(ConnectablePosition.Direction.TOP) + .connectionPosition(1).build().toEntity(); + var createStaticVarCompensator2 = StaticVarCompensatorCreationInfos.builder() + .equipmentId("idStaticVarCompensator2").equipmentName("nameStaticVarCompensator2") + .voltageLevelId("vlId2") + .busOrBusbarSectionId("busId2") + .regulatingTerminalId(null) + .regulatingTerminalType(null).regulatingTerminalVlId("idVlTest2") + .connectionName("Bot").connectionDirection(ConnectablePosition.Direction.BOTTOM) + .connectionPosition(2).build().toEntity(); + var createStaticVarCompensator3 = StaticVarCompensatorCreationInfos.builder() + .equipmentId("idStaticVarCompensator3").equipmentName("nameStaticVarCompensator3") + .voltageLevelId("vlId2") + .busOrBusbarSectionId("busId2") + .regulatingTerminalId(null) + .regulatingTerminalType(null).regulatingTerminalVlId("idVlTest2") + .connectionName("Bot").connectionDirection(ConnectablePosition.Direction.BOTTOM) + .connectionPosition(2) + .regulationMode(VOLTAGE) + .standbyAutomatonOn(true) + .standby(true) + .build().toEntity(); + + networkModificationRepository.saveModifications(TEST_GROUP_ID, List.of(createStaticVarCompensator1, createStaticVarCompensator2, createStaticVarCompensator3)); + assertRequestsCount(1, 3, 1, 0); + + List modificationInfos = networkModificationRepository.getModifications(TEST_GROUP_ID, true, true); + assertEquals(3, modificationInfos.size()); + + assertThat(getStaticVarCompensatorCreationModification(modificationInfos.get(0).getUuid())) + .recursivelyEquals(createStaticVarCompensator1.toModificationInfos()); + assertThat(getStaticVarCompensatorCreationModification(modificationInfos.get(1).getUuid())) + .recursivelyEquals(createStaticVarCompensator2.toModificationInfos()); + + assertEquals(3, networkModificationRepository.getModifications(TEST_GROUP_ID, true, true).size()); + assertEquals(List.of(TEST_GROUP_ID), this.networkModificationRepository.getModificationGroupsUuids()); + + SQLStatementCountValidator.reset(); + networkModificationRepository.deleteModifications(TEST_GROUP_ID, List.of(createStaticVarCompensator2.getId(), createStaticVarCompensator3.getId())); + assertRequestsCount(4, 0, 1, 2); + + SQLStatementCountValidator.reset(); + assertEquals(1, networkModificationRepository.getModifications(TEST_GROUP_ID, true, true).size()); + assertRequestsCount(2, 0, 0, 0); + + SQLStatementCountValidator.reset(); + networkModificationRepository.deleteModificationGroup(TEST_GROUP_ID, true); + assertRequestsCount(3, 0, 0, 3); + + assertThrows(new NetworkModificationException(MODIFICATION_GROUP_NOT_FOUND, TEST_GROUP_ID.toString()).getMessage(), + NetworkModificationException.class, () -> networkModificationRepository.getModifications(TEST_GROUP_ID, true, true) + ); + } }