Skip to content

Commit

Permalink
Add collection impact (#356)
Browse files Browse the repository at this point in the history
* feat(): Add collection impacts, which reduce simple element impacts into typed collection impacts.
It uses a collection threshold to compute.
Note: DELETION type impacts are ignored for this computation

Signed-off-by: sBouzols <[email protected]>
Co-authored-by: Slimane AMAR <[email protected]>
  • Loading branch information
sBouzols and Slimane AMAR authored Mar 5, 2024
1 parent 62f9709 commit ac7c3ad
Show file tree
Hide file tree
Showing 22 changed files with 470 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
import org.gridsuite.modification.server.impacts.AbstractBaseImpact;
import org.gridsuite.modification.server.impacts.SimpleElementImpact;

import java.util.List;
Expand All @@ -18,6 +19,7 @@

/**
* @author Slimane Amar <slimane.amar at rte-france.com>
* @author Sylvain Bouzols <sylvain.bouzols at rte-france.com>
*/
@Builder
@Data
Expand Down Expand Up @@ -47,10 +49,12 @@ public ApplicationStatus max(ApplicationStatus other) {

@Schema(description = "Network modification impacts")
@Builder.Default
private List<SimpleElementImpact> networkImpacts = List.of();
private List<AbstractBaseImpact> networkImpacts = List.of();

public Set<String> getImpactedSubstationsIds() {
return networkImpacts.stream().flatMap(impact -> impact.getSubstationIds().stream()).collect(Collectors.toCollection(TreeSet::new));
return networkImpacts.stream()
.filter(impact -> impact.isSimple())
.flatMap(impact -> ((SimpleElementImpact) impact).getSubstationIds().stream())
.collect(Collectors.toCollection(TreeSet::new)); // using TreeSet to keep natural order
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
Copyright (c) 2024, All partners of the iTesla project (http://www.itesla-project.eu/consortium)
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.impacts;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.powsybl.iidm.network.IdentifiableType;

import lombok.*;
import lombok.experimental.SuperBuilder;

/**
* This class describes a base impact
* This is the base type of all network impacts
*
* @author Sylvain Bouzols <sylvain.bouzols at rte-france.com>
*/
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY,
property = "type",
visible = true
)
@JsonSubTypes({
@JsonSubTypes.Type(value = SimpleElementImpact.class, name = "SIMPLE"),
@JsonSubTypes.Type(value = CollectionElementImpact.class, name = "COLLECTION")
})
@SuperBuilder
@Data
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@NoArgsConstructor
public abstract class AbstractBaseImpact {


public enum ImpactType {
SIMPLE,
COLLECTION
}

@Setter(AccessLevel.NONE)
private ImpactType type;

private IdentifiableType elementType;

@JsonIgnore
public abstract boolean isSimple();

@JsonIgnore
public abstract boolean isCollection();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
Copyright (c) 2024, All partners of the iTesla project (http://www.itesla-project.eu/consortium)
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.impacts;

import lombok.*;
import lombok.experimental.SuperBuilder;

/**
* This class describes a collection type network impact
* This type of network impact describes an impact on multiple items of the same IdentifiableType
*
* @author Sylvain Bouzols <sylvain.bouzols at rte-france.com>
*/
@SuperBuilder
@Data
@ToString(callSuper = true)
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class CollectionElementImpact extends AbstractBaseImpact {
@Override
public ImpactType getType() {
return ImpactType.COLLECTION;
}

public boolean isSimple() {
return false;
}

public boolean isCollection() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,67 @@
*/
package org.gridsuite.modification.server.impacts;

import com.powsybl.iidm.network.IdentifiableType;
import lombok.*;
import lombok.experimental.SuperBuilder;

import java.util.Set;

import com.fasterxml.jackson.annotation.JsonIgnore;

/**
* This class describes an element type network impact
* This type of network impact only describes an individual impacted item and the list of associated subtractions
* This type of network impact only describes an individual impacted item and the list of associated substations
*
* @author Slimane Amar <slimane.amar at rte-france.com>
* @author Sylvain Bouzols <sylvain.bouzols at rte-france.com>
*/
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Setter
@Getter
@Builder
@SuperBuilder
@Data
@ToString(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
@ToString
public class SimpleElementImpact {
@EqualsAndHashCode(callSuper = true)
public class SimpleElementImpact extends AbstractBaseImpact {

public enum SimpleImpactType {
CREATION,
MODIFICATION,
DELETION
}

private SimpleImpactType impactType;
private SimpleImpactType simpleImpactType;

/** The impacted element ID */
private String elementId;

private IdentifiableType elementType;

/** The impacted substations IDs */
private Set<String> substationIds;

@Override
public ImpactType getType() {
return ImpactType.SIMPLE;
}

public boolean isSimple() {
return true;
}

public boolean isCollection() {
return false;
}

@JsonIgnore
public boolean isCreation() {
return getSimpleImpactType() == SimpleImpactType.CREATION;
}

@JsonIgnore
public boolean isModification() {
return getSimpleImpactType() == SimpleImpactType.MODIFICATION;
}

@JsonIgnore
public boolean isDeletion() {
return getSimpleImpactType() == SimpleImpactType.DELETION;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.powsybl.iidm.network.Network;
import com.powsybl.network.store.client.NetworkStoreService;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.tuple.Pair;
import org.gridsuite.modification.server.NetworkModificationException;
import org.gridsuite.modification.server.dto.ModificationInfos;
Expand All @@ -23,10 +24,12 @@
import org.gridsuite.modification.server.dto.NetworkModificationResult.ApplicationStatus;
import org.gridsuite.modification.server.dto.ReportInfos;
import org.gridsuite.modification.server.elasticsearch.EquipmentInfosService;
import org.gridsuite.modification.server.impacts.AbstractBaseImpact;
import org.gridsuite.modification.server.service.FilterService;
import org.gridsuite.modification.server.service.ReportService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;
Expand All @@ -50,6 +53,10 @@ public class NetworkModificationApplicator {

@Getter private final FilterService filterService;

@Value("${impacts.collection-threshold:50}")
@Setter // TODO REMOVE when VoltageInitReportTest will no longer use NetworkModificationApplicator
private Integer collectionThreshold;

public NetworkModificationApplicator(NetworkStoreService networkStoreService, EquipmentInfosService equipmentInfosService,
ReportService reportService, FilterService filterService) {
this.networkStoreService = networkStoreService;
Expand All @@ -59,33 +66,40 @@ public NetworkModificationApplicator(NetworkStoreService networkStoreService, Eq
}

public NetworkModificationResult applyModifications(List<ModificationInfos> modificationInfosList, NetworkInfos networkInfos, ReportInfos reportInfos) {
NetworkStoreListener listener = NetworkStoreListener.create(networkInfos.getNetwork(), networkInfos.getNetworkUuuid(), networkStoreService, equipmentInfosService);
ApplicationStatus applicationStatus = apply(modificationInfosList, listener.getNetwork(), reportInfos);
listener.setApplicationStatus(applicationStatus);
listener.setLastGroupApplicationStatus(applicationStatus);
return listener.flushNetworkModifications();
NetworkStoreListener listener = NetworkStoreListener.create(networkInfos.getNetwork(), networkInfos.getNetworkUuuid(), networkStoreService, equipmentInfosService, collectionThreshold);
ApplicationStatus groupApplicationStatus = apply(modificationInfosList, listener.getNetwork(), reportInfos);
List<AbstractBaseImpact> networkImpacts = listener.flushNetworkModifications();
return
NetworkModificationResult.builder()
.applicationStatus(groupApplicationStatus)
.lastGroupApplicationStatus(groupApplicationStatus)
.networkImpacts(networkImpacts)
.build();
}

public NetworkModificationResult applyModifications(List<Pair<String, List<ModificationInfos>>> modificationInfosGroups, NetworkInfos networkInfos, UUID reportUuid) {
NetworkStoreListener listener = NetworkStoreListener.create(networkInfos.getNetwork(), networkInfos.getNetworkUuuid(), networkStoreService, equipmentInfosService);
List<ApplicationStatus> groupsStatuses =
NetworkStoreListener listener = NetworkStoreListener.create(networkInfos.getNetwork(), networkInfos.getNetworkUuuid(), networkStoreService, equipmentInfosService, collectionThreshold);
List<ApplicationStatus> groupsApplicationStatuses =
modificationInfosGroups.stream()
.map(g -> apply(g.getRight(), listener.getNetwork(), new ReportInfos(reportUuid, g.getLeft())))
.toList();
listener.setApplicationStatus(groupsStatuses.stream().reduce(ApplicationStatus::max).orElse(ApplicationStatus.ALL_OK));
listener.setLastGroupApplicationStatus(Streams.findLast(groupsStatuses.stream()).orElse(ApplicationStatus.ALL_OK));
return listener.flushNetworkModifications();
List<AbstractBaseImpact> networkImpacts = listener.flushNetworkModifications();
return NetworkModificationResult.builder()
.applicationStatus(groupsApplicationStatuses.stream().reduce(ApplicationStatus::max).orElse(ApplicationStatus.ALL_OK))
.lastGroupApplicationStatus(Streams.findLast(groupsApplicationStatuses.stream()).orElse(ApplicationStatus.ALL_OK))
.networkImpacts(networkImpacts)
.build();
}

private ApplicationStatus apply(List<ModificationInfos> modificationInfosList, Network network, ReportInfos reportInfos) {
String rootReporterId = reportInfos.getReporterId() + "@" + NETWORK_MODIFICATION_TYPE_REPORT;
ReporterModel reporter = new ReporterModel(rootReporterId, rootReporterId);
ApplicationStatus applicationStatus = modificationInfosList.stream()
ApplicationStatus groupApplicationStatus = modificationInfosList.stream()
.map(m -> apply(m, network, reporter))
.reduce(ApplicationStatus::max)
.orElse(ApplicationStatus.ALL_OK);
reportService.sendReport(reportInfos.getReportUuid(), reporter);
return applicationStatus;
return groupApplicationStatus;
}

private ApplicationStatus apply(ModificationInfos modificationInfos, Network network, ReporterModel reporter) {
Expand Down
Loading

0 comments on commit ac7c3ad

Please sign in to comment.