Skip to content

Commit

Permalink
Merge branch 'main' into ayolab/remove-hack-and-update-report-management
Browse files Browse the repository at this point in the history
  • Loading branch information
ayolab authored Sep 6, 2024
2 parents 3785d6e + 742c211 commit dd2143e
Show file tree
Hide file tree
Showing 7 changed files with 278 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,9 @@ private void createNewConnectivityPosition(ConnectablePositionAdder<?> adder,
if (connectionPositionReport != null) {
reports.add(connectionPositionReport);
}

// Finalize by adding the feeder
adder.add();
}

public void modifyInjectionConnection(InjectionModificationInfos modificationInfos, Injection<?> injection, List<ReportNode> subReportNode) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.powsybl.commons.report.ReportNode;
import com.powsybl.commons.report.TypedValue;
import com.powsybl.iidm.modification.tripping.BranchTripping;
import com.powsybl.iidm.modification.tripping.BusbarSectionTripping;
import com.powsybl.iidm.modification.tripping.HvdcLineTripping;
import com.powsybl.iidm.modification.tripping.ThreeWindingsTransformerTripping;
import com.powsybl.iidm.modification.tripping.Tripping;
Expand Down Expand Up @@ -178,6 +179,8 @@ private boolean connectOneTerminal(Terminal terminal) {
public Tripping getTrippingFromIdentifiable(Identifiable<?> identifiable) {
if (identifiable instanceof Branch<?> branch) {
return new BranchTripping(branch.getId());
} else if (identifiable instanceof BusbarSection bbs) {
return new BusbarSectionTripping(bbs.getId());
} else if (identifiable instanceof ThreeWindingsTransformer w3t) {
return new ThreeWindingsTransformerTripping(w3t.getId());
} else if (identifiable instanceof HvdcLine hvdcLine) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.util.Map;

import static org.gridsuite.modification.server.NetworkModificationException.Type.*;
import static org.gridsuite.modification.server.modifications.VscModification.DROOP_ACTIVE_POWER_CONTROL_P0_DROOP_REQUIRED_ERROR_MSG;

/**
* @author Seddik Yengui <seddik.yengui at rte-france.com>
Expand Down Expand Up @@ -52,16 +51,22 @@ public void check(Network network) throws NetworkModificationException {
}

private void checkDroop() {
// extension is not enabled => ignore check inside fields
if (!Boolean.TRUE.equals(modificationInfos.getAngleDroopActivePowerControl())) {
boolean isPresentAngleDroopActivePowerControl = modificationInfos.getAngleDroopActivePowerControl() != null;
boolean isPresentDroop = modificationInfos.getDroop() != null;
boolean isPresentP0 = modificationInfos.getP0() != null;
// all fields are provided => OK extension will be created
if (isPresentAngleDroopActivePowerControl && isPresentDroop && isPresentP0) {
return;
}

// enable the extension => should verify whether all fields have been filled
if (modificationInfos.getDroop() == null || modificationInfos.getP0() == null) {
throw new NetworkModificationException(WRONG_HVDC_ANGLE_DROOP_ACTIVE_POWER_CONTROL,
String.format(DROOP_ACTIVE_POWER_CONTROL_P0_DROOP_REQUIRED_ERROR_MSG));
// particular case, not enabling extension and others fields are not provided => OK extension will not be created
if (Boolean.FALSE.equals(modificationInfos.getAngleDroopActivePowerControl()) && !isPresentDroop && !isPresentP0) {
return;
}
// at least one field is provided but not for the others => NOT OK
if (isPresentAngleDroopActivePowerControl || isPresentDroop || isPresentP0) {
throw new NetworkModificationException(WRONG_HVDC_ANGLE_DROOP_ACTIVE_POWER_CONTROL, VscModification.ACTIVE_POWER_CONTROL_DROOP_P0_REQUIRED_ERROR_MSG);
}
// otherwise, i.e. none of the fields is not provided => OK extension will not be created
}

private void checkConverterStation(Network network,
Expand Down Expand Up @@ -134,9 +139,8 @@ public void apply(Network network, ReportNode subReportNode) {
}

private boolean shouldCreateDroopActivePowerControlExtension() {
return Boolean.TRUE.equals(modificationInfos.getAngleDroopActivePowerControl()) &&
modificationInfos.getDroop() != null &&
modificationInfos.getP0() != null;
return VscModification.shouldCreateDroopActivePowerControlExtension(
modificationInfos.getAngleDroopActivePowerControl() != null, modificationInfos.getDroop() != null, modificationInfos.getP0() != null);
}

private void reportHvdcLineInfos(ReportNode subReportNode) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
import javax.annotation.Nonnull;
import java.util.*;

import static org.gridsuite.modification.server.NetworkModificationException.Type.*;
import static org.gridsuite.modification.server.NetworkModificationException.Type.MODIFY_VSC_ERROR;
import static org.gridsuite.modification.server.NetworkModificationException.Type.WRONG_HVDC_ANGLE_DROOP_ACTIVE_POWER_CONTROL;
import static org.gridsuite.modification.server.modifications.VscCreation.VSC_CHARACTERISTICS;
import static org.gridsuite.modification.server.modifications.VscCreation.VSC_SETPOINTS;

Expand All @@ -34,15 +35,18 @@ public class VscModification extends AbstractModification {
public static final String ANGLE_DROOP_ACTIVE_POWER_CONTROL_FIELD = "AngleDroopActivePowerControl";
public static final String DROOP_FIELD = "Droop";
public static final String P0_FIELD = "P0";
public static final String DROOP_ACTIVE_POWER_CONTROL_P0_DROOP_REQUIRED_ERROR_MSG = "Both Droop and P0 are required when angle droop active power control is activated";
public static final String DROOP_ACTIVE_POWER_CONTROL_P0_REQUIRED_ERROR_MSG = "P0 is required when Droop is provided";
public static final String ACTIVE_POWER_CONTROL_DROOP_P0_REQUIRED_ERROR_MSG = "Angle droop active power control, Droop and P0 must be all provided or none";

private final VscModificationInfos modificationInfos;

public VscModification(VscModificationInfos vscModificationInfos) {
this.modificationInfos = vscModificationInfos;
}

public static boolean shouldCreateDroopActivePowerControlExtension(boolean isPresentAngleDroopActivePowerControl, boolean isPresentDroop, boolean isPresentP0) {
return isPresentAngleDroopActivePowerControl && isPresentDroop && isPresentP0;
}

protected void checkConverterStation(@Nonnull ConverterStationModificationInfos converterStationModificationInfos, @Nonnull VscConverterStation vscConverterStation) {
String errorMessage = "Converter station '" + converterStationModificationInfos.getEquipmentId() + "' : ";
ModificationUtils.getInstance().checkReactiveLimit(vscConverterStation, converterStationModificationInfos.getMinQ(), converterStationModificationInfos.getMaxQ(),
Expand All @@ -54,41 +58,37 @@ public void check(Network network) throws NetworkModificationException {
if (modificationInfos == null
|| modificationInfos.getConverterStation1() == null
|| modificationInfos.getConverterStation2() == null) {
throw new NetworkModificationException(MODIFY_BATTERY_ERROR, "Missing required attributes to modify the equipment");
throw new NetworkModificationException(MODIFY_VSC_ERROR, "Missing required attributes to modify the equipment");
}
HvdcLine hvdcLine = ModificationUtils.getInstance().getHvdcLine(network, modificationInfos.getEquipmentId());

VscConverterStation converterStation1 = ModificationUtils.getInstance().getVscConverterStation(network, hvdcLine.getConverterStation1().getId());
VscConverterStation converterStation2 = ModificationUtils.getInstance().getVscConverterStation(network, hvdcLine.getConverterStation2().getId());
checkConverterStation(modificationInfos.getConverterStation1(), converterStation1);
checkConverterStation(modificationInfos.getConverterStation2(), converterStation2);
checkDroopModification(hvdcLine);
checkDroop(hvdcLine);
}

private void checkDroopModification(HvdcLine hvdcLine) {
// the extension already exists
private void checkDroop(HvdcLine hvdcLine) {
//--- the extension already exists ---//
HvdcAngleDroopActivePowerControl hvdcAngleDroopActivePowerControl = hvdcLine.getExtension(HvdcAngleDroopActivePowerControl.class);
if (hvdcAngleDroopActivePowerControl != null) {
// if droop is set p0 should be also
if (modificationInfos.getDroop() != null && modificationInfos.getP0() == null) {
throw new NetworkModificationException(WRONG_HVDC_ANGLE_DROOP_ACTIVE_POWER_CONTROL,
String.format(DROOP_ACTIVE_POWER_CONTROL_P0_REQUIRED_ERROR_MSG));
}
return;
}

// the extension doesn't exist yet and the modification wants to enable the extension =>
// should verify whether all fields have been filled
boolean isEnabledAngleDroopActivePowerControl = modificationInfos.getAngleDroopActivePowerControl() != null
&& Boolean.TRUE.equals(modificationInfos.getAngleDroopActivePowerControl().getValue());
if (!isEnabledAngleDroopActivePowerControl) {
//--- the extension doesn't exist yet ---//
boolean isPresentAngleDroopActivePowerControl = modificationInfos.getAngleDroopActivePowerControl() != null;
boolean isPresentDroop = modificationInfos.getDroop() != null;
boolean isPresentP0 = modificationInfos.getP0() != null;
// all fields are provided => OK extension will be created
if (isPresentAngleDroopActivePowerControl && isPresentDroop && isPresentP0) {
return;
}

if (modificationInfos.getDroop() == null || modificationInfos.getP0() == null) {
throw new NetworkModificationException(WRONG_HVDC_ANGLE_DROOP_ACTIVE_POWER_CONTROL,
String.format(DROOP_ACTIVE_POWER_CONTROL_P0_DROOP_REQUIRED_ERROR_MSG));
// at least one field is provided but not for the others => NOT OK
if (isPresentAngleDroopActivePowerControl || isPresentDroop || isPresentP0) {
throw new NetworkModificationException(WRONG_HVDC_ANGLE_DROOP_ACTIVE_POWER_CONTROL, ACTIVE_POWER_CONTROL_DROOP_P0_REQUIRED_ERROR_MSG);
}
// otherwise, i.e. none of the fields is provided => OK extension will not be created
}

@Override
Expand Down Expand Up @@ -241,10 +241,8 @@ private void modifyExistingHvdcAngleDroopActivePowerControl(HvdcAngleDroopActive
}

private boolean shouldCreateDroopActivePowerControlExtension() {
return modificationInfos.getAngleDroopActivePowerControl() != null &&
modificationInfos.getAngleDroopActivePowerControl().getValue() &&
modificationInfos.getDroop() != null &&
modificationInfos.getP0() != null;
return shouldCreateDroopActivePowerControlExtension(
modificationInfos.getAngleDroopActivePowerControl() != null, modificationInfos.getDroop() != null, modificationInfos.getP0() != null);
}

private List<ReportNode> hvdcAngleDroopActivePowerControlAdder(HvdcLine hvdcLine) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* 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.*;
import com.powsybl.iidm.network.extensions.OperatingStatus;
import lombok.SneakyThrows;
import org.gridsuite.modification.server.dto.ModificationInfos;
import org.gridsuite.modification.server.dto.OperatingStatusModificationInfos;
import org.gridsuite.modification.server.utils.NetworkCreation;
import org.gridsuite.modification.server.utils.TestUtils;
import org.junit.Assert;
import org.junit.jupiter.api.Tag;

import java.util.Map;
import java.util.UUID;

import static com.powsybl.iidm.network.extensions.OperatingStatus.Status.FORCED_OUTAGE;
import static com.powsybl.iidm.network.extensions.OperatingStatus.Status.IN_OPERATION;
import static org.junit.jupiter.api.Assertions.assertEquals;

@Tag("IntegrationTest")
public class OperatingStatusModificationTripBusBarTest extends AbstractNetworkModificationTest {

private static final String TARGET_BUSBAR_ID = "1.A";
private static final OperatingStatus.Status TARGET_BUSBAR_STATUS = FORCED_OUTAGE;
private static final OperatingStatus.Status INITIAL_BUSBAR_STATUS = IN_OPERATION;

@Override
protected Network createNetwork(UUID networkUuid) {
Network network = NetworkCreation.create(networkUuid, true);
// force a branch status different from the expected one, after testCreate
TestUtils.setOperatingStatus(network, TARGET_BUSBAR_ID, INITIAL_BUSBAR_STATUS);
return network;
}

@Override
protected ModificationInfos buildModification() {
return OperatingStatusModificationInfos.builder()
.stashed(false)
.equipmentId(TARGET_BUSBAR_ID)
.action(OperatingStatusModificationInfos.ActionType.TRIP).build();
}

@Override
protected ModificationInfos buildModificationUpdate() {
return OperatingStatusModificationInfos.builder()
.stashed(false)
.equipmentId(TARGET_BUSBAR_ID)
.action(OperatingStatusModificationInfos.ActionType.SWITCH_ON).build();
}

@Override
protected void assertAfterNetworkModificationCreation() {
TestUtils.assertOperatingStatus(getNetwork(), TARGET_BUSBAR_ID, TARGET_BUSBAR_STATUS);
assertTerminalsStatusAfterNetworkModification(false);
}

@Override
protected void assertAfterNetworkModificationDeletion() {
// back to init status
TestUtils.assertOperatingStatus(getNetwork(), TARGET_BUSBAR_ID, INITIAL_BUSBAR_STATUS);
assertTerminalsStatusAfterNetworkModification(true);
}

@Override
@SneakyThrows
protected void testCreationModificationMessage(ModificationInfos modificationInfos) {
assertEquals("OPERATING_STATUS_MODIFICATION", modificationInfos.getMessageType());
Map<String, String> createdValues = mapper.readValue(modificationInfos.getMessageValues(), new TypeReference<>() { });
assertEquals("TRIP", createdValues.get("action"));
}

@Override
@SneakyThrows
protected void testUpdateModificationMessage(ModificationInfos modificationInfos) {
assertEquals("OPERATING_STATUS_MODIFICATION", modificationInfos.getMessageType());
Map<String, String> updatedValues = mapper.readValue(modificationInfos.getMessageValues(), new TypeReference<>() { });
assertEquals("SWITCH_ON", updatedValues.get("action"));
}

private void assertTerminalsStatusAfterNetworkModification(boolean shouldBeConnected) {
BusbarSection busbarSection = getNetwork().getBusbarSection(TARGET_BUSBAR_ID);
Assert.assertEquals(busbarSection.getTerminal().isConnected(), shouldBeConnected);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.gridsuite.modification.server.NetworkModificationException.Type.*;
import static org.gridsuite.modification.server.modifications.VscModification.DROOP_ACTIVE_POWER_CONTROL_P0_DROOP_REQUIRED_ERROR_MSG;
import static org.gridsuite.modification.server.modifications.VscModification.ACTIVE_POWER_CONTROL_DROOP_P0_REQUIRED_ERROR_MSG;
import static org.gridsuite.modification.server.utils.TestUtils.assertLogMessage;
import static org.junit.Assert.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
Expand Down Expand Up @@ -302,32 +302,74 @@ public void testCreateWithErrors() throws Exception {
}

@Test
public void testCreateWithoutEnablingDroopPowerControl() throws Exception {
// create without enabling droop power control
public void testCreateAngleDroopPowerControlWithoutEnabling() throws Exception {
VscCreationInfos vscCreationInfos = (VscCreationInfos) buildModification();
vscCreationInfos.setAngleDroopActivePowerControl(false);
String vscCreationInfosJson = mapper.writeValueAsString(vscCreationInfos);
mockMvc.perform(post(getNetworkModificationUri()).content(vscCreationInfosJson).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
assertThat(getNetwork().getHvdcLine("vsc1")).isNotNull();
HvdcLine hvdcLine = getNetwork().getHvdcLine("vsc1");
assertThat(hvdcLine).isNotNull();
HvdcAngleDroopActivePowerControl activePowerControl = hvdcLine.getExtension(HvdcAngleDroopActivePowerControl.class);
assertThat(activePowerControl).isNull();
HvdcAngleDroopActivePowerControl activePowerControlExt = hvdcLine.getExtension(HvdcAngleDroopActivePowerControl.class);
assertThat(activePowerControlExt).isNotNull();
assertThat(activePowerControlExt.isEnabled()).isFalse();
assertThat(activePowerControlExt.getDroop()).isEqualTo(1F);
assertThat(activePowerControlExt.getP0()).isEqualTo(5F);
}

@Test
public void testCreateWithEnablingDroopPowerControl() throws Exception {
// create with enabling droop power control but not provide Droop and P0
public void testNotCreateAngleDroopPowerControlWithoutEnabling() throws Exception {
VscCreationInfos vscCreationInfos = (VscCreationInfos) buildModification();
vscCreationInfos.setAngleDroopActivePowerControl(true);
vscCreationInfos.setAngleDroopActivePowerControl(false);
vscCreationInfos.setDroop(null);
vscCreationInfos.setP0(null);
String vscCreationInfosJson = mapper.writeValueAsString(vscCreationInfos);
mockMvc.perform(post(getNetworkModificationUri()).content(vscCreationInfosJson).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
HvdcLine hvdcLine = getNetwork().getHvdcLine("vsc1");
assertThat(hvdcLine).isNotNull();
HvdcAngleDroopActivePowerControl activePowerControlExt = hvdcLine.getExtension(HvdcAngleDroopActivePowerControl.class);
assertThat(activePowerControlExt).isNull();
}

@Test
public void testAngleDroopPowerControlWithAbsentInfos() throws Exception {
boolean[][] droopInfosIsPresentData = {
{true, false, false},
{true, true, false},
{true, false, true},
{false, true, false},
{false, true, true},
{false, false, true},
};

for (boolean[] droopInfoIsPresent : droopInfosIsPresentData) {
VscCreationInfos vscCreationInfos = buildModificationWithDroopAbsentInfos(droopInfoIsPresent[0], droopInfoIsPresent[1], droopInfoIsPresent[2]);
checkDroopWithAbsentInfos(vscCreationInfos);
}
}

private VscCreationInfos buildModificationWithDroopAbsentInfos(boolean isPresentAngleDroopActivePowerControl, boolean isPresentDroop, boolean isPresentP0) {
VscCreationInfos vscCreationInfos = (VscCreationInfos) buildModification();
// reset null depending to test arguments
if (!isPresentAngleDroopActivePowerControl) {
vscCreationInfos.setAngleDroopActivePowerControl(null);
}
if (!isPresentDroop) {
vscCreationInfos.setDroop(null);
}
if (!isPresentP0) {
vscCreationInfos.setP0(null);
}
return vscCreationInfos;
}

private void checkDroopWithAbsentInfos(VscCreationInfos vscCreationInfos) throws Exception {
String vscCreationInfosJson = mapper.writeValueAsString(vscCreationInfos);
mockMvc.perform(post(getNetworkModificationUri()).content(vscCreationInfosJson).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
assertLogMessage(new NetworkModificationException(WRONG_HVDC_ANGLE_DROOP_ACTIVE_POWER_CONTROL,
String.format(DROOP_ACTIVE_POWER_CONTROL_P0_DROOP_REQUIRED_ERROR_MSG)).getMessage(),
ACTIVE_POWER_CONTROL_DROOP_P0_REQUIRED_ERROR_MSG).getMessage(),
vscCreationInfos.getErrorType().name(), reportService);
}
}
Loading

0 comments on commit dd2143e

Please sign in to comment.