Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix return impacts when active power control modification #378

Merged
merged 9 commits into from
Dec 1, 2023
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@
<groupId>com.powsybl</groupId>
<artifactId>powsybl-network-store-client</artifactId>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-network-store-iidm-impl</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-ws-commons</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,15 @@
*/
package org.gridsuite.modification.server.dto;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.*;
import lombok.experimental.SuperBuilder;

/**
* @author Achour Berrahma <achour.berrahma at rte-france.com>
*/
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@ToString
@EqualsAndHashCode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,15 @@
*/
package org.gridsuite.modification.server.dto;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.*;
import lombok.experimental.SuperBuilder;

/**
* @author Nicolas Noir <nicolas.noir at rte-france.com>
*/
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@ToString
@EqualsAndHashCode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,4 @@ public static Set<SubstationInfos> getSubstationsInfos(@NonNull Identifiable<?>
.name(vl.getSubstation().map(Substation::getNameOrId).orElse(null)).build())
.collect(Collectors.toSet());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -780,44 +780,53 @@ public void modifyMinMaxReactiveLimits(MinMaxReactiveLimits minMaxReactiveLimits
reportModifications(subReporterReactiveLimits, reports, "minMaxReactiveLimitsModified", "By range");
}

private void modifyExistingActivePowerControl(ActivePowerControl<?> activePowerControl,
AttributeModification<Boolean> participateInfo,
AttributeModification<Float> droopInfo,
List<Report> reports) {
double oldDroop = activePowerControl.getDroop();
boolean oldParticipate = activePowerControl.isParticipate();

Optional.ofNullable(participateInfo).ifPresent(info -> {
activePowerControl.setParticipate(info.getValue());
reports.add(buildModificationReport(oldParticipate, info.getValue(), "Participate"));
});

Optional.ofNullable(droopInfo).ifPresent(info -> {
activePowerControl.setDroop(info.getValue());
reports.add(buildModificationReport(oldDroop, info.getValue(), "Droop"));
});
}

private void createNewActivePowerControl(ActivePowerControlAdder<?> adder,
AttributeModification<Boolean> participateInfo,
AttributeModification<Float> droopInfo,
List<Report> reports) {
boolean participate = participateInfo != null ? participateInfo.getValue() : false;
adder.withParticipate(participate);
if (participateInfo != null) {
reports.add(buildModificationReport(null, participate, "Participate"));
}
double droop = droopInfo != null ? droopInfo.getValue() : Double.NaN;
adder.withDroop(droop);
if (droopInfo != null) {
reports.add(buildModificationReport(Double.NaN, droop, "Droop"));
}
adder.add();
}

public Reporter modifyActivePowerControlAttributes(ActivePowerControl<?> activePowerControl,
ActivePowerControlAdder<?> activePowerControlAdder,
AttributeModification<Boolean> participateInfo,
AttributeModification<Float> droopInfo,
Reporter subReporter,
Reporter subReporterSetpoints) {
List<Report> reports = new ArrayList<>();
double oldDroop = Double.NaN;
boolean oldParticipate = false;
double droop = droopInfo != null ? droopInfo.getValue() : Double.NaN;
if (activePowerControl != null) {
oldDroop = activePowerControl.getDroop();
oldParticipate = activePowerControl.isParticipate();
}

if (participateInfo != null) {
activePowerControlAdder
.withParticipate(participateInfo.getValue());
reports.add(ModificationUtils.getInstance().buildModificationReport(activePowerControl != null ? activePowerControl.isParticipate() : null,
participateInfo.getValue(),
"Participate"));
} else {
activePowerControlAdder
.withParticipate(oldParticipate);
}

if (droopInfo != null) {
activePowerControlAdder
.withDroop(droop);
reports.add(ModificationUtils.getInstance().buildModificationReport(oldDroop,
droop,
"Droop"));
modifyExistingActivePowerControl(activePowerControl, participateInfo, droopInfo, reports);
} else {
activePowerControlAdder
.withDroop(oldDroop);
createNewActivePowerControl(activePowerControlAdder, participateInfo, droopInfo, reports);
}
activePowerControlAdder
.add();

Reporter subReporterSetpoints2 = subReporterSetpoints;
if (subReporterSetpoints == null && !reports.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package org.gridsuite.modification.server.modifications;

import com.google.common.collect.Iterables;
import com.powsybl.iidm.network.*;
import com.powsybl.network.store.client.NetworkStoreService;
import lombok.Setter;
Expand Down Expand Up @@ -40,6 +41,8 @@ public class NetworkStoreListener implements NetworkListener {

private final List<EquipmentInfos> createdEquipments = new ArrayList<>();

private final List<EquipmentInfos> modifiedEquipments = new ArrayList<>();

private final Set<SimpleElementImpact> networkImpacts = new LinkedHashSet<>();

// TODO : Move to the NetworkModificationApplicator class
Expand Down Expand Up @@ -92,18 +95,6 @@ public Network getNetwork() {
return network;
}

@Override
public void onUpdate(Identifiable identifiable, String attribute, Object oldValue, Object newValue) {
networkImpacts.add(
SimpleElementImpact.builder()
.impactType(SimpleElementImpact.SimpleImpactType.MODIFICATION)
.elementType(identifiable.getType())
.elementId(identifiable.getId())
.substationIds(getSubstationIds(identifiable))
.build()
);
}

private void addSimpleModificationImpact(Identifiable<?> identifiable) {
networkImpacts.add(
SimpleElementImpact.builder()
Expand All @@ -130,9 +121,66 @@ public void onElementReplaced(Identifiable identifiable, String attribute, Objec
addSimpleModificationImpact(identifiable);
}

@Override
public void onUpdate(Identifiable identifiable, String attribute, Object oldValue, Object newValue) {
addSimpleModificationImpact(identifiable);
updateEquipmentIndexation(identifiable, attribute, networkUuid, network.getVariantManager().getWorkingVariantId());
}

@Override
public void onUpdate(Identifiable identifiable, String attribute, String variantId, Object oldValue, Object newValue) {
addSimpleModificationImpact(identifiable);
updateEquipmentIndexation(identifiable, attribute, networkUuid, network.getVariantManager().getWorkingVariantId());
}

private void updateEquipmentIndexation(Identifiable<?> identifiable, String attribute, UUID networkUuid, String variantId) {
modifiedEquipments.add(toEquipmentInfos(identifiable, networkUuid, variantId));

// because all each equipment carry its linked voltage levels/substations name within its document
// if attribute is "name" and identifiable type is VOLTAGE_LEVEL or SUBSTATION, we need to update all equipments linked to it
if (attribute.equals("name") && (identifiable.getType().equals(IdentifiableType.VOLTAGE_LEVEL) || identifiable.getType().equals(IdentifiableType.SUBSTATION))) {
updateLinkedEquipments(identifiable);
}
}

private void updateLinkedEquipments(Identifiable<?> identifiable) {
if (identifiable.getType().equals(IdentifiableType.VOLTAGE_LEVEL)) {
VoltageLevel updatedVoltageLevel = network.getVoltageLevel(identifiable.getId());
// update all equipments linked to voltageLevel
updateEquipmentsLinkedToVoltageLevel(updatedVoltageLevel);
// update substation linked to voltageLevel
Optional<Substation> linkedSubstation = updatedVoltageLevel.getSubstation();
if (linkedSubstation.isPresent()) {
modifiedEquipments.add(toEquipmentInfos(linkedSubstation.get(), networkUuid, network.getVariantManager().getWorkingVariantId()));
}
} else if (identifiable.getType().equals(IdentifiableType.SUBSTATION)) {
Substation updatedSubstation = network.getSubstation(identifiable.getId());
updateEquipmentsLinkedToSubstation(updatedSubstation);
}
}

private void updateEquipmentsLinkedToSubstation(Substation substation) {
Iterable<VoltageLevel> linkedVoltageLevels = substation.getVoltageLevels();
// update all voltageLevels linked to substation
linkedVoltageLevels.forEach(vl -> modifiedEquipments.add(toEquipmentInfos(vl, networkUuid, network.getVariantManager().getWorkingVariantId())));
// update all equipments linked to each of the voltageLevels
linkedVoltageLevels.forEach(vl ->
Iterables.concat(
vl.getConnectables(),
vl.getSwitches()
).forEach(c ->
modifiedEquipments.add(toEquipmentInfos(c, networkUuid, network.getVariantManager().getWorkingVariantId()))
)
);
}

private void updateEquipmentsLinkedToVoltageLevel(VoltageLevel voltageLevel) {
Iterables.concat(
voltageLevel.getConnectables(),
voltageLevel.getSwitches()
).forEach(c ->
modifiedEquipments.add(toEquipmentInfos(c, networkUuid, network.getVariantManager().getWorkingVariantId()))
);
}

@Override
Expand Down Expand Up @@ -192,6 +240,18 @@ public NetworkModificationResult flushNetworkModifications() {
.build();
}

private static EquipmentInfos toEquipmentInfos(Identifiable<?> identifiable, UUID networkUuid, String variantId) {
return EquipmentInfos.builder()
.networkUuid(networkUuid)
.variantId(variantId)
.id(identifiable.getId())
.name(identifiable.getNameOrId())
.type(identifiable.getType().name())
.voltageLevels(EquipmentInfos.getVoltageLevelsInfos(identifiable))
.substations(EquipmentInfos.getSubstationsInfos(identifiable))
.build();
}

private void flushEquipmentInfos() {
String variantId = network.getVariantManager().getWorkingVariantId();
Set<String> presentEquipmentDeletionsIds = equipmentInfosService.findEquipmentInfosList(deletedEquipmentsIds, networkUuid, variantId).stream().map(EquipmentInfos::getId).collect(Collectors.toSet());
Expand All @@ -213,5 +273,6 @@ private void flushEquipmentInfos() {
equipmentInfosService.deleteEquipmentInfosList(equipmentDeletionsIds, networkUuid, variantId);
equipmentInfosService.addAllTombstonedEquipmentInfos(tombstonedEquipmentInfos);
equipmentInfosService.addAllEquipmentInfos(createdEquipments);
equipmentInfosService.addAllEquipmentInfos(modifiedEquipments);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.junit.Test;
import org.junit.jupiter.api.Tag;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.util.CollectionUtils;

import java.util.*;
Expand Down Expand Up @@ -217,6 +218,40 @@ public void testDroopUnchanged() throws Exception {
assertEquals(18f, createdModification.getDroop().getValue());
}

@Test
public void testImpactsAfterActivePowerControlModifications() throws Exception {
BatteryModificationInfos batteryModificationInfos = (BatteryModificationInfos) buildModification();
String modificationToCreateJson = mapper.writeValueAsString(batteryModificationInfos);
mockMvc.perform(post(getNetworkModificationUri()).content(modificationToCreateJson).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andReturn();
Battery battery = getNetwork().getBattery("v3Battery");
assertEquals(0.1f, battery.getExtension(ActivePowerControl.class).getDroop());
assertEquals(true, battery.getExtension(ActivePowerControl.class).isParticipate());
//modify only droop
batteryModificationInfos.setDroop(new AttributeModification<>(0.5f, OperationType.SET));
modificationToCreateJson = mapper.writeValueAsString(batteryModificationInfos);
MvcResult mvcResult = mockMvc.perform(post(getNetworkModificationUri()).content(modificationToCreateJson).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andReturn();
//check impacts
String resultAsString = mvcResult.getResponse().getContentAsString();
NetworkModificationResult networkModificationResult = mapper.readValue(resultAsString, NetworkModificationResult.class);
assertEquals(1, networkModificationResult.getNetworkImpacts().size());
assertEquals(1, networkModificationResult.getImpactedSubstationsIds().size());
assertEquals("[s2]", networkModificationResult.getImpactedSubstationsIds().toString());
//modify only participate
batteryModificationInfos.setParticipate(new AttributeModification<>(false, OperationType.SET));
modificationToCreateJson = mapper.writeValueAsString(batteryModificationInfos);
mvcResult = mockMvc.perform(post(getNetworkModificationUri()).content(modificationToCreateJson).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andReturn();
//check impacts
resultAsString = mvcResult.getResponse().getContentAsString();
networkModificationResult = mapper.readValue(resultAsString, NetworkModificationResult.class);
assertEquals(1, networkModificationResult.getNetworkImpacts().size());
assertEquals(1, networkModificationResult.getImpactedSubstationsIds().size());
assertEquals("[s2]", networkModificationResult.getImpactedSubstationsIds().toString());

Meklo marked this conversation as resolved.
Show resolved Hide resolved
}

@Test
public void testMinQGreaterThanMaxQ() throws Exception {
BatteryModificationInfos batteryModificationInfos = (BatteryModificationInfos) buildModification();
Expand Down
Loading
Loading