-
Notifications
You must be signed in to change notification settings - Fork 0
limits modification logs #124
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
Merged
Merged
Changes from 12 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
a1ee8a6
first refacto
Mathieu-Deharbe f31fdc2
corrects TU
Mathieu-Deharbe 47b4492
permanent limit
Mathieu-Deharbe 8d6e732
applicabilityToString
Mathieu-Deharbe 2f4df9d
applicabilityToString in the UTs
Mathieu-Deharbe fc9d514
correct handling of ambiguous ADD or MODIFY
Mathieu-Deharbe 6ce5c99
code style
Mathieu-Deharbe 6bc3cc7
sub report node for each side
Mathieu-Deharbe 05eab30
remove olgUtils
Mathieu-Deharbe 617b04c
corrects logSideNode
Mathieu-Deharbe dda8e3d
corrects logSideNode
Mathieu-Deharbe c0e89d2
log limits only if there is at least one actual modification
Mathieu-Deharbe a722970
Merge branch 'main' into limits-modification-logs
Mathieu-Deharbe cc3401c
corrections post merge conflicts
Mathieu-Deharbe 9df943c
if (!limitsReportsSide1.isEmpty() || !limitsReportsSide2.isEmpty()) {
Mathieu-Deharbe 0d9870d
createLogNodeForSide
Mathieu-Deharbe fd828df
Merge remote-tracking branch 'origin/limits-modification-logs' into l…
Mathieu-Deharbe 777057f
if (!limitsReportsSide1.isEmpty() || !limitsReportsSide2.isEmpty()) {
Mathieu-Deharbe 803482c
check on createLogNodeForSide parameter
Mathieu-Deharbe a3df970
corrections post review
Mathieu-Deharbe 7b57038
corrects name modification
Mathieu-Deharbe 77930de
logs in case of line ceration and transfo creation
Mathieu-Deharbe 188eed4
rename classes
Mathieu-Deharbe 6155133
TU testRename
Mathieu-Deharbe 1a1aa0b
Merge branch 'main' into limits-modification-logs
basseche File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
650 changes: 11 additions & 639 deletions
650
src/main/java/org/gridsuite/modification/modifications/AbstractBranchModification.java
Large diffs are not rendered by default.
Oops, something went wrong.
598 changes: 598 additions & 0 deletions
598
src/main/java/org/gridsuite/modification/modifications/olg/OlgModification.java
Large diffs are not rendered by default.
Oops, something went wrong.
209 changes: 209 additions & 0 deletions
209
src/main/java/org/gridsuite/modification/modifications/olg/OlgsModification.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,209 @@ | ||
| /** | ||
| * Copyright (c) 2025, 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.modifications.olg; | ||
|
|
||
| import com.powsybl.commons.report.ReportNode; | ||
| import com.powsybl.commons.report.TypedValue; | ||
| import com.powsybl.iidm.network.*; | ||
| import org.gridsuite.modification.dto.*; | ||
|
|
||
| import java.util.*; | ||
|
|
||
| import static org.gridsuite.modification.dto.OperationalLimitsGroupInfos.Applicability.*; | ||
| import static org.gridsuite.modification.dto.OperationalLimitsGroupInfos.Applicability.EQUIPMENT; | ||
| import static org.gridsuite.modification.dto.OperationalLimitsGroupModificationType.DELETE; | ||
| import static org.gridsuite.modification.modifications.AbstractBranchModification.*; | ||
|
|
||
| /** | ||
| * handles the modification of a list of operational limits groups from AbstractBranchModification | ||
| * | ||
| * @author Mathieu DEHARBE <mathieu.deharbe at rte-france.com> | ||
| */ | ||
| public class OlgsModification { | ||
| private final Branch<?> modifiedBranch; // branch modified by the network modification | ||
| private final List<OperationalLimitsGroupModificationInfos> olgModificationInfos; | ||
| private final ReportNode olgsReportNode; | ||
|
|
||
| public OlgsModification( | ||
| Branch<?> branch, | ||
| List<OperationalLimitsGroupModificationInfos> operationalLimitsInfos, | ||
| ReportNode limitSetsReportNode) { | ||
| modifiedBranch = branch; | ||
| olgModificationInfos = operationalLimitsInfos != null ? operationalLimitsInfos : new ArrayList<>(); | ||
| olgsReportNode = limitSetsReportNode; | ||
| } | ||
|
|
||
| public void modifyOperationalLimitsGroups(OperationalLimitsGroupsModificationType operationalLimitsGroupsModificationType) { | ||
|
|
||
| if (operationalLimitsGroupsModificationType == OperationalLimitsGroupsModificationType.REPLACE) { | ||
| // because we are replacing all the limit sets we remove all the limit sets that are not specified in the network modification | ||
| // the others may be modified instead of recreated so it is better to not delete them in order to have more precise logs | ||
| deleteOlgsUnspecifiedInTheModification(SIDE1); | ||
| deleteOlgsUnspecifiedInTheModification(SIDE2); | ||
| } | ||
|
|
||
| for (OperationalLimitsGroupModificationInfos opLGModifInfos : olgModificationInfos) { | ||
| if (opLGModifInfos.getModificationType() == null) { | ||
| continue; | ||
| } | ||
|
|
||
| ArrayList<ReportNode> olgSetReports = new ArrayList<>(); | ||
|
|
||
| if (!opLGModifInfos.getModificationType().equals(DELETE)) { | ||
| detectApplicabilityChange(opLGModifInfos, olgSetReports); | ||
| } | ||
|
|
||
| new OlgModification( | ||
| modifiedBranch, | ||
| opLGModifInfos, | ||
| olgsReportNode | ||
| ).applyModificationToOperationalLimitsGroup(); | ||
| } | ||
| } | ||
|
|
||
| private void deleteOlgsUnspecifiedInTheModification(OperationalLimitsGroupInfos.Applicability applicability) { | ||
| List<String> olgToBeDeleted = new ArrayList<>(); | ||
| Collection<OperationalLimitsGroup> operationalLimitsGroups = applicability == SIDE1 ? | ||
| modifiedBranch.getOperationalLimitsGroups1() : | ||
| modifiedBranch.getOperationalLimitsGroups2(); | ||
| operationalLimitsGroups.stream().filter( | ||
| operationalLimitsGroup -> | ||
| olgModificationInfos.stream().noneMatch( | ||
| operationalLimitsGroupModificationInfos -> | ||
| // we don't want to remove the limit sets specified in the network modification (operationalLimitsGroups) : | ||
| Objects.equals(operationalLimitsGroupModificationInfos.getId(), operationalLimitsGroup.getId()) | ||
| && (operationalLimitsGroupModificationInfos.getApplicability() == applicability | ||
| || operationalLimitsGroupModificationInfos.getApplicability() == EQUIPMENT) | ||
| ) | ||
| ).forEach(operationalLimitsGroup -> olgToBeDeleted.add(operationalLimitsGroup.getId())); | ||
|
|
||
| Iterator<String> i = olgToBeDeleted.iterator(); | ||
| while (i.hasNext()) { | ||
| String s = i.next(); | ||
| new OlgModification( | ||
| modifiedBranch, | ||
| OperationalLimitsGroupModificationInfos.builder() | ||
| .id(s) | ||
| .applicability(applicability) | ||
| .build(), | ||
| olgsReportNode | ||
| ).removeOlg(); | ||
| } | ||
| } | ||
|
|
||
| private void logApplicabilityChange(List<ReportNode> olgReports, String groupId, OperationalLimitsGroupInfos.Applicability applicability) { | ||
| olgReports.add(ReportNode.newRootReportNode().withMessageTemplate("network.modification.applicabilityChanged") | ||
| .withUntypedValue(OPERATIONAL_LIMITS_GROUP_NAME, groupId) | ||
| .withUntypedValue(APPLICABILITY, applicability.toString()) | ||
| .withSeverity(TypedValue.INFO_SEVERITY) | ||
| .build()); | ||
| } | ||
|
|
||
| private boolean shouldDeletedOtherSide(Branch<?> branch, OperationalLimitsGroupModificationInfos limitsModifInfos) { | ||
| boolean hasModificationOnSideOne = !olgModificationInfos.stream().filter(opLimitModifInfo -> | ||
| opLimitModifInfo.getId().equals(limitsModifInfos.getId()) && opLimitModifInfo.getApplicability().equals(SIDE1)) | ||
| .toList().isEmpty(); | ||
|
|
||
| boolean hasModificationOnSideTwo = !olgModificationInfos.stream().filter(opLimitModifInfo -> | ||
| opLimitModifInfo.getId().equals(limitsModifInfos.getId()) && opLimitModifInfo.getApplicability().equals(SIDE2)) | ||
| .toList().isEmpty(); | ||
|
|
||
| switch (limitsModifInfos.getApplicability()) { | ||
| case SIDE1 -> { | ||
| return !hasModificationOnSideTwo && branch.getOperationalLimitsGroup2(limitsModifInfos.getId()).isPresent(); | ||
| } | ||
| case SIDE2 -> { | ||
| return !hasModificationOnSideOne && branch.getOperationalLimitsGroup1(limitsModifInfos.getId()).isPresent(); | ||
| } | ||
| default -> { | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // If we are changing applicability we may not find operational limits group where we should so check both sides | ||
| private void detectApplicabilityChange(OperationalLimitsGroupModificationInfos modifiedLimitSetInfos, List<ReportNode> olgReports) { | ||
|
|
||
| OperationalLimitsGroup limitsGroup1 = modifiedBranch.getOperationalLimitsGroup1(modifiedLimitSetInfos.getId()).orElse(null); | ||
| OperationalLimitsGroup limitsGroup2 = modifiedBranch.getOperationalLimitsGroup2(modifiedLimitSetInfos.getId()).orElse(null); | ||
| if (limitsGroup1 == null && modifiedLimitSetInfos.getApplicability().equals(SIDE2) | ||
| || limitsGroup2 == null && modifiedLimitSetInfos.getApplicability().equals(SIDE1)) { | ||
| return; | ||
| } else if (limitsGroup1 != null && limitsGroup2 != null && !modifiedLimitSetInfos.getApplicability().equals(EQUIPMENT)) { | ||
| // applicability change from EQUIPMENT to one side | ||
| if (shouldDeletedOtherSide(modifiedBranch, modifiedLimitSetInfos)) { | ||
| if (modifiedLimitSetInfos.getApplicability().equals(SIDE1)) { | ||
| modifiedBranch.removeOperationalLimitsGroup2(modifiedLimitSetInfos.getId()); | ||
| logApplicabilityChange(olgReports, limitsGroup1.getId(), SIDE1); | ||
| } else if (modifiedLimitSetInfos.getApplicability().equals(SIDE2)) { | ||
| modifiedBranch.removeOperationalLimitsGroup1(modifiedLimitSetInfos.getId()); | ||
| logApplicabilityChange(olgReports, limitsGroup2.getId(), SIDE2); | ||
| } | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| switch (modifiedLimitSetInfos.getApplicability()) { | ||
| case SIDE1 -> moveLimitSetToTheOtherSide(modifiedBranch, limitsGroup2, modifiedLimitSetInfos.getId(), true, olgReports); | ||
| case SIDE2 -> moveLimitSetToTheOtherSide(modifiedBranch, limitsGroup1, modifiedLimitSetInfos.getId(), false, olgReports); | ||
| case EQUIPMENT -> { | ||
| boolean applicabilityChanged = false; | ||
| if (limitsGroup1 == null && limitsGroup2 != null) { | ||
| limitsGroup1 = modifiedBranch.newOperationalLimitsGroup1(limitsGroup2.getId()); | ||
| copyOperationalLimitsGroup(limitsGroup1.newCurrentLimits(), limitsGroup2); | ||
| applicabilityChanged = true; | ||
| } | ||
| if (limitsGroup2 == null && limitsGroup1 != null) { | ||
| limitsGroup2 = modifiedBranch.newOperationalLimitsGroup2(limitsGroup1.getId()); | ||
| copyOperationalLimitsGroup(limitsGroup2.newCurrentLimits(), limitsGroup1); | ||
| applicabilityChanged = true; | ||
| } | ||
| if (applicabilityChanged) { | ||
| logApplicabilityChange(olgReports, limitsGroup1.getId(), EQUIPMENT); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private void moveLimitSetToTheOtherSide(Branch<?> branch, | ||
| OperationalLimitsGroup limitsGroupToCopy, String modifiedLimitSet, | ||
| boolean isSide1, | ||
| List<ReportNode> olgReports) { | ||
| // if we have only one limit set with the same name but applicability is not good | ||
| // we should copy existing limit set on the right side and removed it from the other side | ||
| if (olgModificationInfos.stream().filter(limitSet -> limitSet.getId().equals(modifiedLimitSet)).toList().size() == 1) { | ||
| // Copy operational limits group to the other side | ||
| OperationalLimitsGroup limitsGroup = isSide1 ? branch.newOperationalLimitsGroup1(limitsGroupToCopy.getId()) | ||
| : branch.newOperationalLimitsGroup2(limitsGroupToCopy.getId()); | ||
| copyOperationalLimitsGroup(limitsGroup.newCurrentLimits(), limitsGroupToCopy); | ||
|
|
||
| olgReports.add(ReportNode.newRootReportNode().withMessageTemplate("network.modification.applicabilityChanged") | ||
| .withUntypedValue(OPERATIONAL_LIMITS_GROUP_NAME, limitsGroupToCopy.getId()) | ||
| .withUntypedValue(APPLICABILITY, isSide1 ? SIDE1.toString() : SIDE2.toString()) | ||
| .withSeverity(TypedValue.INFO_SEVERITY) | ||
| .build()); | ||
| // Remove copied operational limits group | ||
| if (isSide1) { | ||
| branch.removeOperationalLimitsGroup2(modifiedLimitSet); | ||
| } else { | ||
| branch.removeOperationalLimitsGroup1(modifiedLimitSet); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private void copyOperationalLimitsGroup(CurrentLimitsAdder limitsAdder, OperationalLimitsGroup opLimitGroupToCopy) { | ||
| // Copy all limits of the other side | ||
| opLimitGroupToCopy.getCurrentLimits().ifPresent(currentLimits -> { | ||
| limitsAdder.setPermanentLimit(currentLimits.getPermanentLimit()); | ||
|
|
||
| for (LoadingLimits.TemporaryLimit tempLimit : currentLimits.getTemporaryLimits()) { | ||
| addTemporaryLimit(limitsAdder, tempLimit.getName(), tempLimit.getValue(), tempLimit.getAcceptableDuration()); | ||
| } | ||
| limitsAdder.add(); | ||
| }); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.