Skip to content

Commit 2227bf2

Browse files
Add the possibility to launch a state estimation on a network (#578)
* Add the possibility to launch a state estimation on a network Signed-off-by: Franck LECUYER <[email protected]> Co-authored-by: David BRAQUART <[email protected]>
1 parent fb41203 commit 2227bf2

34 files changed

+936
-72
lines changed

src/main/java/org/gridsuite/study/server/RestResponseEntityExceptionHandler.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ protected ResponseEntity<Object> handleStudyException(StudyException exception)
4343
VOLTAGE_INIT_PARAMETERS_NOT_FOUND,
4444
SECURITY_ANALYSIS_PARAMETERS_NOT_FOUND,
4545
LOADFLOW_PARAMETERS_NOT_FOUND,
46-
SENSITIVITY_ANALYSIS_PARAMETERS_NOT_FOUND
46+
SENSITIVITY_ANALYSIS_PARAMETERS_NOT_FOUND,
47+
STATE_ESTIMATION_NOT_FOUND
4748
-> ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getType());
4849
case CASE_NOT_FOUND -> ResponseEntity.status(HttpStatus.FAILED_DEPENDENCY).body(exception.getMessage());
4950
case STUDY_ALREADY_EXISTS -> ResponseEntity.status(HttpStatus.CONFLICT).body(type);
@@ -54,7 +55,8 @@ protected ResponseEntity<Object> handleStudyException(StudyException exception)
5455
NON_EVACUATED_ENERGY_RUNNING,
5556
DYNAMIC_SIMULATION_RUNNING,
5657
SHORT_CIRCUIT_ANALYSIS_RUNNING,
57-
VOLTAGE_INIT_RUNNING
58+
VOLTAGE_INIT_RUNNING,
59+
STATE_ESTIMATION_RUNNING
5860
-> ResponseEntity.status(HttpStatus.FORBIDDEN).body(type);
5961
case NOT_ALLOWED,
6062
BAD_NODE_TYPE,

src/main/java/org/gridsuite/study/server/StudyConstants.java

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ private StudyConstants() {
3434
public static final String TIME_SERIES_API_VERSION = "v1";
3535
public static final String DYNAMIC_MAPPING_API_VERSION = ""; // mapping server is now without version, must be v1 in the next time
3636
public static final String FILTER_API_VERSION = "v1";
37+
public static final String STATE_ESTIMATION_API_VERSION = "v1";
3738

3839
public static final String NETWORK_UUID = "networkUuid";
3940
public static final String CASE_UUID = "caseUuid";

src/main/java/org/gridsuite/study/server/StudyController.java

+47-1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public class StudyController {
7777
private final LoadFlowService loadflowService;
7878
private final CaseService caseService;
7979
private final RemoteServicesInspector remoteServicesInspector;
80+
private final StateEstimationService stateEstimationService;
8081

8182
public StudyController(StudyService studyService,
8283
NetworkService networkStoreService,
@@ -90,7 +91,8 @@ public StudyController(StudyService studyService,
9091
VoltageInitService voltageInitService,
9192
LoadFlowService loadflowService,
9293
CaseService caseService,
93-
RemoteServicesInspector remoteServicesInspector) {
94+
RemoteServicesInspector remoteServicesInspector,
95+
StateEstimationService stateEstimationService) {
9496
this.studyService = studyService;
9597
this.networkModificationTreeService = networkModificationTreeService;
9698
this.networkStoreService = networkStoreService;
@@ -104,6 +106,7 @@ public StudyController(StudyService studyService,
104106
this.loadflowService = loadflowService;
105107
this.caseService = caseService;
106108
this.remoteServicesInspector = remoteServicesInspector;
109+
this.stateEstimationService = stateEstimationService;
107110
}
108111

109112
@InitBinder
@@ -1905,4 +1908,47 @@ public ResponseEntity<String> exportFilter(
19051908
@Parameter(description = "Filter uuid to be applied") @PathVariable("filterUuid") UUID filterUuid) {
19061909
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(studyService.exportFilter(studyUuid, filterUuid));
19071910
}
1911+
1912+
@PostMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/state-estimation/run")
1913+
@Operation(summary = "run state estimation on study")
1914+
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The state estimation has started")})
1915+
public ResponseEntity<Void> runStateEstimation(@Parameter(description = "studyUuid") @PathVariable("studyUuid") UUID studyUuid,
1916+
@Parameter(description = "nodeUuid") @PathVariable("nodeUuid") UUID nodeUuid,
1917+
@RequestHeader(HEADER_USER_ID) String userId) {
1918+
studyService.assertIsNodeNotReadOnly(nodeUuid);
1919+
studyService.runStateEstimation(studyUuid, nodeUuid, userId);
1920+
return ResponseEntity.ok().build();
1921+
}
1922+
1923+
@GetMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/state-estimation/result")
1924+
@Operation(summary = "Get a state estimation result on study")
1925+
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The state estimation result"),
1926+
@ApiResponse(responseCode = "204", description = "No state estimation has been done yet"),
1927+
@ApiResponse(responseCode = "404", description = "The state estimation has not been found")})
1928+
public ResponseEntity<String> getStateEstimationResult(@Parameter(description = "study UUID") @PathVariable("studyUuid") UUID studyUuid,
1929+
@Parameter(description = "nodeUuid") @PathVariable("nodeUuid") UUID nodeUuid) {
1930+
String result = stateEstimationService.getStateEstimationResult(nodeUuid);
1931+
return result != null ? ResponseEntity.ok().body(result) :
1932+
ResponseEntity.noContent().build();
1933+
}
1934+
1935+
@GetMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/state-estimation/status")
1936+
@Operation(summary = "Get the state estimation status on study")
1937+
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The state estimation status"),
1938+
@ApiResponse(responseCode = "204", description = "No state estimation has been done yet"),
1939+
@ApiResponse(responseCode = "404", description = "The state estimation status has not been found")})
1940+
public ResponseEntity<String> getStateEstimationStatus(@Parameter(description = "Study UUID") @PathVariable("studyUuid") UUID studyUuid,
1941+
@Parameter(description = "nodeUuid") @PathVariable("nodeUuid") UUID nodeUuid) {
1942+
String status = stateEstimationService.getStateEstimationStatus(nodeUuid);
1943+
return status != null ? ResponseEntity.ok().body(status) : ResponseEntity.noContent().build();
1944+
}
1945+
1946+
@PutMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/state-estimation/stop")
1947+
@Operation(summary = "stop state estimation on study")
1948+
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The state estimation has been stopped")})
1949+
public ResponseEntity<Void> stopStateEstimation(@Parameter(description = "Study uuid") @PathVariable("studyUuid") UUID studyUuid,
1950+
@Parameter(description = "nodeUuid") @PathVariable("nodeUuid") UUID nodeUuid) {
1951+
stateEstimationService.stopStateEstimation(studyUuid, nodeUuid);
1952+
return ResponseEntity.ok().build();
1953+
}
19081954
}

src/main/java/org/gridsuite/study/server/StudyException.java

+3
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ public enum Type {
107107
NOT_IMPLEMENTED,
108108
EVALUATE_FILTER_FAILED,
109109
GET_USER_PROFILE_FAILED,
110+
STATE_ESTIMATION_RUNNING,
111+
STATE_ESTIMATION_NOT_FOUND,
112+
STATE_ESTIMATION_ERROR,
110113
}
111114

112115
private final Type type;

src/main/java/org/gridsuite/study/server/SupervisionController.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public SupervisionController(SupervisionService supervisionService, StudyService
4949

5050
@DeleteMapping(value = "/computation/results")
5151
@Operation(summary = "delete all results of a given computation")
52-
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "all loadflow results have been deleted")})
52+
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "all computation results have been deleted")})
5353
public ResponseEntity<Integer> deleteComputationResults(@Parameter(description = "Computation type") @RequestParam("type") ComputationType computationType,
5454
@Parameter(description = "Dry run") @RequestParam("dryRun") boolean dryRun) {
5555
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(supervisionService.deleteComputationResults(computationType, dryRun));

src/main/java/org/gridsuite/study/server/dto/ComputationType.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ public enum ComputationType {
2828
NotificationService.UPDATE_TYPE_DYNAMIC_SIMULATION_FAILED),
2929
SHORT_CIRCUIT_ONE_BUS("One bus Short circuit analysis", "oneBusShortCircuitAnalysisResultUuid",
3030
NotificationService.UPDATE_TYPE_ONE_BUS_SHORT_CIRCUIT_STATUS, NotificationService.UPDATE_TYPE_ONE_BUS_SHORT_CIRCUIT_RESULT,
31-
NotificationService.UPDATE_TYPE_ONE_BUS_SHORT_CIRCUIT_FAILED);
31+
NotificationService.UPDATE_TYPE_ONE_BUS_SHORT_CIRCUIT_FAILED),
32+
STATE_ESTIMATION("State estimation", "stateEstimationResultUuid",
33+
NotificationService.UPDATE_TYPE_STATE_ESTIMATION_STATUS, NotificationService.UPDATE_TYPE_STATE_ESTIMATION_RESULT,
34+
NotificationService.UPDATE_TYPE_STATE_ESTIMATION_FAILED);
3235

3336
private final String label; // used for logs
3437
private final String resultUuidLabel;

src/main/java/org/gridsuite/study/server/dto/DeleteNodeInfos.java

+6
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public class DeleteNodeInfos {
4343
private List<UUID> voltageInitResultUuids = new ArrayList<>();
4444
private List<UUID> dynamicSimulationResultUuids = new ArrayList<>();
4545

46+
private List<UUID> stateEstimationResultUuids = new ArrayList<>();
47+
4648
public void addModificationGroupUuid(UUID modificationGroupUuid) {
4749
modificationGroupUuids.add(modificationGroupUuid);
4850
}
@@ -86,4 +88,8 @@ public void addOneBusShortCircuitAnalysisResultUuid(UUID oneBusShortCircuitAnaly
8688
public void addVoltageInitResultUuid(UUID voltageInitResultUuid) {
8789
voltageInitResultUuids.add(voltageInitResultUuid);
8890
}
91+
92+
public void addStateEstimationResultUuid(UUID stateEstimationResultUuid) {
93+
stateEstimationResultUuids.add(stateEstimationResultUuid);
94+
}
8995
}

src/main/java/org/gridsuite/study/server/dto/InvalidateNodeInfos.java

+6
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ public class InvalidateNodeInfos {
4646
private List<UUID> voltageInitResultUuids = new ArrayList<>();
4747
private List<UUID> dynamicSimulationResultUuids = new ArrayList<>();
4848

49+
private List<UUID> stateEstimationResultUuids = new ArrayList<>();
50+
4951
public void addReportUuid(UUID reportUuid) {
5052
reportUuids.add(reportUuid);
5153
}
@@ -92,4 +94,8 @@ public void addVoltageInitResultUuid(UUID voltageInitResultUuid) {
9294
public void addDynamicSimulationResultUuid(UUID dynamicSimulationResultUuid) {
9395
dynamicSimulationResultUuids.add(dynamicSimulationResultUuid);
9496
}
97+
98+
public void addStateEstimationResultUuid(UUID stateEstimationResultUuid) {
99+
stateEstimationResultUuids.add(stateEstimationResultUuid);
100+
}
95101
}

src/main/java/org/gridsuite/study/server/dto/NodeModificationInfos.java

+2
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,6 @@ public class NodeModificationInfos {
4040
private UUID voltageInitUuid;
4141

4242
private UUID dynamicSimulationUuid;
43+
44+
private UUID stateEstimationUuid;
4345
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* Copyright (c) 2024, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.study.server.dto;
8+
9+
/**
10+
* @author Franck Lecuyer <franck.lecuyer at rte-france.com>
11+
*/
12+
public enum StateEstimationStatus {
13+
NOT_DONE,
14+
RUNNING,
15+
COMPLETED,
16+
}

src/main/java/org/gridsuite/study/server/networkmodificationtree/NetworkModificationNodeInfoRepositoryProxy.java

+5
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public NetworkModificationNodeInfoEntity toEntity(AbstractNode node) {
5858
modificationNode.getSensitivityAnalysisResultUuid(),
5959
modificationNode.getNonEvacuatedEnergyResultUuid(),
6060
modificationNode.getDynamicSimulationResultUuid(),
61+
modificationNode.getStateEstimationResultUuid(),
6162
modificationNode.getNodeBuildStatus().toEntity());
6263
return completeEntityNodeInfo(node, networkModificationNodeInfoEntity);
6364
}
@@ -77,6 +78,7 @@ public NetworkModificationNode toDto(NetworkModificationNodeInfoEntity node) {
7778
node.getSensitivityAnalysisResultUuid(),
7879
node.getNonEvacuatedEnergyResultUuid(),
7980
node.getDynamicSimulationResultUuid(),
81+
node.getStateEstimationResultUuid(),
8082
node.getNodeBuildStatus().toDto()));
8183
}
8284

@@ -125,6 +127,7 @@ public void updateComputationResultUuid(AbstractNode node, UUID computationUuid,
125127
case SHORT_CIRCUIT_ONE_BUS -> modificationNode.setOneBusShortCircuitAnalysisResultUuid(computationUuid);
126128
case VOLTAGE_INITIALIZATION -> modificationNode.setVoltageInitResultUuid(computationUuid);
127129
case DYNAMIC_SIMULATION -> modificationNode.setDynamicSimulationResultUuid(computationUuid);
130+
case STATE_ESTIMATION -> modificationNode.setStateEstimationResultUuid(computationUuid);
128131
}
129132
updateNode(modificationNode, computationType.getResultUuidLabel());
130133
}
@@ -140,6 +143,7 @@ public UUID getComputationResultUuid(AbstractNode node, ComputationType computat
140143
case SHORT_CIRCUIT_ONE_BUS -> ((NetworkModificationNode) node).getOneBusShortCircuitAnalysisResultUuid();
141144
case VOLTAGE_INITIALIZATION -> ((NetworkModificationNode) node).getVoltageInitResultUuid();
142145
case DYNAMIC_SIMULATION -> ((NetworkModificationNode) node).getDynamicSimulationResultUuid();
146+
case STATE_ESTIMATION -> ((NetworkModificationNode) node).getStateEstimationResultUuid();
143147
};
144148
}
145149

@@ -189,6 +193,7 @@ public NodeModificationInfos getNodeModificationInfos(AbstractNode node) {
189193
.oneBusShortCircuitAnalysisUuid(networkModificationNode.getOneBusShortCircuitAnalysisResultUuid())
190194
.voltageInitUuid(networkModificationNode.getVoltageInitResultUuid())
191195
.dynamicSimulationUuid(networkModificationNode.getDynamicSimulationResultUuid())
196+
.stateEstimationUuid(networkModificationNode.getStateEstimationResultUuid())
192197
.build();
193198
}
194199
}

src/main/java/org/gridsuite/study/server/networkmodificationtree/dto/NetworkModificationNode.java

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ public class NetworkModificationNode extends AbstractNode {
5151

5252
private UUID dynamicSimulationResultUuid;
5353

54+
private UUID stateEstimationResultUuid;
55+
5456
private NodeBuildStatus nodeBuildStatus;
5557

5658
@Override

src/main/java/org/gridsuite/study/server/networkmodificationtree/entities/NetworkModificationNodeInfoEntity.java

+3
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ public class NetworkModificationNodeInfoEntity extends AbstractNodeInfoEntity {
6262
@Column(name = "dynamicSimulationResultUuid")
6363
private UUID dynamicSimulationResultUuid;
6464

65+
@Column(name = "stateEstimationResultUuid")
66+
private UUID stateEstimationResultUuid;
67+
6568
@Embedded
6669
@AttributeOverrides(value = {
6770
@AttributeOverride(name = "localBuildStatus", column = @Column(name = "localBuildStatus", nullable = false)),

src/main/java/org/gridsuite/study/server/notification/NotificationService.java

+3
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ public class NotificationService {
7676
public static final String UPDATE_TYPE_STUDY = "study";
7777
public static final String UPDATE_TYPE_STUDY_METADATA_UPDATED = "metadata_updated";
7878
public static final String UPDATE_TYPE_INDEXATION_STATUS = "indexation_status_updated";
79+
public static final String UPDATE_TYPE_STATE_ESTIMATION_FAILED = "stateEstimation_failed";
80+
public static final String UPDATE_TYPE_STATE_ESTIMATION_RESULT = "stateEstimationResult";
81+
public static final String UPDATE_TYPE_STATE_ESTIMATION_STATUS = "stateEstimation_status";
7982

8083
public static final String MODIFICATIONS_CREATING_IN_PROGRESS = "creatingInProgress";
8184
public static final String MODIFICATIONS_STASHING_IN_PROGRESS = "stashingInProgress";

src/main/java/org/gridsuite/study/server/repository/networkmodificationtree/NetworkModificationNodeInfoRepository.java

+2
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,6 @@ public interface NetworkModificationNodeInfoRepository extends NodeInfoRepositor
3636
List<NetworkModificationNodeInfoEntity> findAllByNodeStudyId(UUID studyUuid);
3737

3838
List<AbstractNodeInfoEntity> findAllByNodeStudyIdAndName(UUID studyUuid, String name);
39+
40+
List<NetworkModificationNodeInfoEntity> findAllByStateEstimationResultUuidNotNull();
3941
}

src/main/java/org/gridsuite/study/server/service/ConsumerService.java

+15
Original file line numberDiff line numberDiff line change
@@ -507,4 +507,19 @@ private UUID createDefaultSecurityAnalysisParameters() {
507507
}
508508
return null;
509509
}
510+
511+
@Bean
512+
public Consumer<Message<String>> consumeStateEstimationResult() {
513+
return message -> consumeCalculationResult(message, STATE_ESTIMATION);
514+
}
515+
516+
@Bean
517+
public Consumer<Message<String>> consumeStateEstimationStopped() {
518+
return message -> consumeCalculationStopped(message, STATE_ESTIMATION);
519+
}
520+
521+
@Bean
522+
public Consumer<Message<String>> consumeStateEstimationFailed() {
523+
return message -> consumeCalculationFailed(message, STATE_ESTIMATION);
524+
}
510525
}

src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java

+15
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import static org.gridsuite.study.server.dto.ComputationType.SHORT_CIRCUIT;
4141
import static org.gridsuite.study.server.dto.ComputationType.SHORT_CIRCUIT_ONE_BUS;
4242
import static org.gridsuite.study.server.dto.ComputationType.VOLTAGE_INITIALIZATION;
43+
import static org.gridsuite.study.server.dto.ComputationType.STATE_ESTIMATION;
4344

4445
/**
4546
* @author Jacques Borsenberger <jacques.borsenberger at rte-france.com
@@ -160,6 +161,7 @@ private UUID duplicateNode(UUID nodeToCopyUuid, UUID anchorNodeUuid, InsertMode
160161
null,
161162
null,
162163
null,
164+
null,
163165
NodeBuildStatus.from(BuildStatus.NOT_BUILT).toEntity()
164166
);
165167
UUID studyUuid = anchorNodeEntity.getStudy().getId();
@@ -352,6 +354,11 @@ private void deleteNodes(UUID id, boolean deleteChildren, boolean allowDeleteRoo
352354
deleteNodeInfos.addDynamicSimulationResultUuid(dynamicSimulationResultUuid);
353355
}
354356

357+
UUID stateEstimationResultUuid = repositories.get(nodeToDelete.getType()).getComputationResultUuid(id, STATE_ESTIMATION);
358+
if (stateEstimationResultUuid != null) {
359+
deleteNodeInfos.addStateEstimationResultUuid(stateEstimationResultUuid);
360+
}
361+
355362
if (!deleteChildren) {
356363
nodesRepository.findAllByParentNodeIdNode(id).forEach(node -> node.setParentNode(nodeToDelete.getParentNode()));
357364
} else {
@@ -454,6 +461,7 @@ public void cloneStudyTree(AbstractNode nodeToDuplicate, UUID nodeParentId, Stud
454461
model.setShortCircuitAnalysisResultUuid(null);
455462
model.setOneBusShortCircuitAnalysisResultUuid(null);
456463
model.setVoltageInitResultUuid(null);
464+
model.setStateEstimationResultUuid(null);
457465

458466
nextParentId = self.createNode(study.getId(), referenceParentNodeId, model, InsertMode.CHILD, null).getId();
459467
networkModificationService.createModifications(modificationGroupToDuplicateId, newModificationGroupId);
@@ -804,6 +812,12 @@ private void fillInvalidateNodeInfos(NodeEntity node, InvalidateNodeInfos invali
804812
}
805813
}
806814

815+
UUID stateEstimationResultUuid = repositories.get(node.getType()).getComputationResultUuid(node.getIdNode(), STATE_ESTIMATION);
816+
if (stateEstimationResultUuid != null) {
817+
invalidateNodeInfos.addStateEstimationResultUuid(stateEstimationResultUuid);
818+
reportTypes.add(StudyService.ReportType.STATE_ESTIMATION);
819+
}
820+
807821
invalidateNodeInfos.addReportTypes(reportUuid, reportTypes);
808822
}
809823

@@ -863,6 +877,7 @@ private void invalidateNodeProper(NodeEntity child, InvalidateNodeInfos invalida
863877
if (deleteVoltageInitResults) {
864878
nodeRepository.updateComputationResultUuid(childUuid, null, VOLTAGE_INITIALIZATION);
865879
}
880+
nodeRepository.updateComputationResultUuid(childUuid, null, STATE_ESTIMATION);
866881
}
867882
}
868883

0 commit comments

Comments
 (0)