diff --git a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracCreator.java b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracCreator.java index 6c5090d346..a521f705b8 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracCreator.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracCreator.java @@ -18,7 +18,6 @@ import com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.contingency.CsaProfileContingencyCreator; import com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.remedialaction.CsaProfileRemedialActionsCreator; import com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.remedialaction.ElementaryActionsHelper; -import com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.remedialaction.OnConstraintUsageRuleHelper; import com.google.auto.service.AutoService; import com.powsybl.iidm.network.Network; import com.powsybl.openrao.data.craccreation.creator.csaprofile.parameters.CsaCracCreationParameters; @@ -61,12 +60,12 @@ public CsaProfileCracCreationContext createCrac(CsaProfileCrac nativeCrac, Netwo Map overridingData = nativeCrac.getOverridingCracData(offsetDateTime); PropertyBags contingencies = CsaProfileCracUtils.overrideData(nativeCrac.getContingencies(), overridingData, CsaProfileConstants.OverridingObjectsFields.CONTINGENCY); PropertyBags assessedElements = CsaProfileCracUtils.overrideData(nativeCrac.getAssessedElements(), overridingData, CsaProfileConstants.OverridingObjectsFields.ASSESSED_ELEMENT); - PropertyBags assessedElementsWithContingencies = CsaProfileCracUtils.overrideData(nativeCrac.getAssessedElementsWithContingencies(), overridingData, CsaProfileConstants.OverridingObjectsFields.ASSESSED_ELEMENT_WITH_CONTINGENCY); + PropertyBags assessedElementWithContingencies = CsaProfileCracUtils.overrideData(nativeCrac.getAssessedElementsWithContingencies(), overridingData, CsaProfileConstants.OverridingObjectsFields.ASSESSED_ELEMENT_WITH_CONTINGENCY); PropertyBags currentLimits = CsaProfileCracUtils.overrideData(nativeCrac.getCurrentLimits(), overridingData, CsaProfileConstants.OverridingObjectsFields.CURRENT_LIMIT); PropertyBags voltageLimits = CsaProfileCracUtils.overrideData(nativeCrac.getVoltageLimits(), overridingData, CsaProfileConstants.OverridingObjectsFields.VOLTAGE_LIMIT); PropertyBags angleLimits = CsaProfileCracUtils.overrideData(nativeCrac.getAngleLimits(), overridingData, CsaProfileConstants.OverridingObjectsFields.VOLTAGE_ANGLE_LIMIT); - PropertyBags assessedElementsWithRemedialAction = CsaProfileCracUtils.overrideData(nativeCrac.getAssessedElementsWithRemedialAction(), overridingData, CsaProfileConstants.OverridingObjectsFields.ASSESSED_ELEMENT_WITH_REMEDIAL_ACTION); - PropertyBags contingenciesWithRemedialAction = CsaProfileCracUtils.overrideData(nativeCrac.getContingencyWithRemedialAction(), overridingData, CsaProfileConstants.OverridingObjectsFields.CONTINGENCY_WITH_REMEDIAL_ACTION); + PropertyBags assessedElementWithRemedialActions = CsaProfileCracUtils.overrideData(nativeCrac.getAssessedElementsWithRemedialAction(), overridingData, CsaProfileConstants.OverridingObjectsFields.ASSESSED_ELEMENT_WITH_REMEDIAL_ACTION); + PropertyBags contingencyWithRemedialActions = CsaProfileCracUtils.overrideData(nativeCrac.getContingencyWithRemedialAction(), overridingData, CsaProfileConstants.OverridingObjectsFields.CONTINGENCY_WITH_REMEDIAL_ACTION); PropertyBags gridStateAlterationRemedialAction = CsaProfileCracUtils.overrideData(nativeCrac.getGridStateAlterationRemedialAction(), overridingData, CsaProfileConstants.OverridingObjectsFields.GRID_STATE_ALTERATION_REMEDIAL_ACTION); PropertyBags remedialActionSchemes = CsaProfileCracUtils.overrideData(nativeCrac.getRemedialActionScheme(), overridingData, CsaProfileConstants.OverridingObjectsFields.REMEDIAL_ACTION_SCHEME); PropertyBags gridStateAlterationsCollection = CsaProfileCracUtils.overrideData(nativeCrac.getGridStateAlterationCollection(), overridingData, CsaProfileConstants.OverridingObjectsFields.GRID_STATE_ALTERATION); @@ -80,11 +79,10 @@ public CsaProfileCracCreationContext createCrac(CsaProfileCrac nativeCrac, Netwo createContingencies(contingencies, nativeCrac.getContingencyEquipments()); - createCnecs(assessedElements, assessedElementsWithContingencies, currentLimits, voltageLimits, angleLimits, cracCreationParameters.getDefaultMonitoredSides(), regionEicCode); + createCnecs(assessedElements, assessedElementWithContingencies, currentLimits, voltageLimits, angleLimits, cracCreationParameters.getDefaultMonitoredSides(), regionEicCode); - OnConstraintUsageRuleHelper onConstraintUsageRuleAdder = new OnConstraintUsageRuleHelper(creationContext.getCnecCreationContexts(), assessedElements, assessedElementsWithRemedialAction); - ElementaryActionsHelper elementaryActionsHelper = new ElementaryActionsHelper(gridStateAlterationRemedialAction, schemeRemedialActions, remedialActionSchemes, nativeCrac.getStage(), gridStateAlterationsCollection, assessedElementsWithRemedialAction, contingenciesWithRemedialAction, staticPropertyRanges, topologyActions, rotatingMachineActions, shuntCompensatorModifications, tapPositionActions, nativeCrac.getRemedialActionGroups(), remedialActionDependencies); - createRemedialActions(onConstraintUsageRuleAdder, elementaryActionsHelper, spsMaxTimeToImplementThreshold); + ElementaryActionsHelper elementaryActionsHelper = new ElementaryActionsHelper(gridStateAlterationRemedialAction, schemeRemedialActions, remedialActionSchemes, nativeCrac.getStage(), gridStateAlterationsCollection, assessedElementWithRemedialActions, contingencyWithRemedialActions, staticPropertyRanges, topologyActions, rotatingMachineActions, shuntCompensatorModifications, tapPositionActions, nativeCrac.getRemedialActionGroups(), remedialActionDependencies); + createRemedialActions(elementaryActionsHelper, spsMaxTimeToImplementThreshold, assessedElements, assessedElementWithRemedialActions, contingencyWithRemedialActions, creationContext.getCnecCreationContexts()); creationContext.buildCreationReport(); return creationContext.creationSuccess(crac); } @@ -116,8 +114,8 @@ private boolean checkTimeCoherence(PropertyBag header, OffsetDateTime offsetDate return isValidInterval(offsetDateTime, startTime, endTime); } - private void createRemedialActions(OnConstraintUsageRuleHelper onConstraintUsageRuleAdder, ElementaryActionsHelper elementaryActionsHelper, int spsMaxTimeToImplementThreshold) { - new CsaProfileRemedialActionsCreator(crac, network, creationContext, onConstraintUsageRuleAdder, elementaryActionsHelper, spsMaxTimeToImplementThreshold); + private void createRemedialActions(ElementaryActionsHelper elementaryActionsHelper, int spsMaxTimeToImplementThreshold, PropertyBags assessedElements, PropertyBags assessedElementWithRemedialActions, PropertyBags contingencyWithRemedialActions, Set cnecCreationContexts) { + new CsaProfileRemedialActionsCreator(crac, network, creationContext, elementaryActionsHelper, spsMaxTimeToImplementThreshold, assessedElements, assessedElementWithRemedialActions, contingencyWithRemedialActions, cnecCreationContexts); } private void createContingencies(PropertyBags contingenciesPropertyBags, PropertyBags contingencyEquipmentsPropertyBags) { diff --git a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracUtils.java b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracUtils.java index 08ded4c74c..c95790f229 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracUtils.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracUtils.java @@ -30,10 +30,10 @@ private CsaProfileCracUtils() { } - public static Map> getMappedPropertyBagsSet(PropertyBags propertyBags, String property) { + public static Map> groupPropertyBags(PropertyBags propertyBags, String groupingPoperty) { Map> mappedPropertyBags = new HashMap<>(); for (PropertyBag propertyBag : propertyBags) { - String propValue = propertyBag.getId(property); + String propValue = propertyBag.getId(groupingPoperty); Set propPropertyBags = mappedPropertyBags.computeIfAbsent(propValue, k -> new HashSet<>()); propPropertyBags.add(propertyBag); } diff --git a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/CsaProfileCnecCreator.java b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/CsaProfileCnecCreator.java index e92a340ba5..7c790ac6c0 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/CsaProfileCnecCreator.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/CsaProfileCnecCreator.java @@ -42,10 +42,10 @@ public CsaProfileCnecCreator(Crac crac, Network network, PropertyBags assessedEl this.crac = crac; this.network = network; this.assessedElementsPropertyBags = assessedElementsPropertyBags; - this.assessedElementsWithContingenciesPropertyBags = CsaProfileCracUtils.getMappedPropertyBagsSet(assessedElementsWithContingenciesPropertyBags, CsaProfileConstants.REQUEST_ASSESSED_ELEMENT); - this.currentLimitsPropertyBags = CsaProfileCracUtils.getMappedPropertyBagsSet(currentLimitsPropertyBags, CsaProfileConstants.REQUEST_CURRENT_LIMIT); - this.voltageLimitsPropertyBags = CsaProfileCracUtils.getMappedPropertyBagsSet(voltageLimitsPropertyBags, CsaProfileConstants.REQUEST_VOLTAGE_LIMIT); - this.angleLimitsPropertyBags = CsaProfileCracUtils.getMappedPropertyBagsSet(angleLimitsPropertyBags, CsaProfileConstants.REQUEST_VOLTAGE_ANGLE_LIMIT); + this.assessedElementsWithContingenciesPropertyBags = CsaProfileCracUtils.groupPropertyBags(assessedElementsWithContingenciesPropertyBags, CsaProfileConstants.REQUEST_ASSESSED_ELEMENT); + this.currentLimitsPropertyBags = CsaProfileCracUtils.groupPropertyBags(currentLimitsPropertyBags, CsaProfileConstants.REQUEST_CURRENT_LIMIT); + this.voltageLimitsPropertyBags = CsaProfileCracUtils.groupPropertyBags(voltageLimitsPropertyBags, CsaProfileConstants.REQUEST_VOLTAGE_LIMIT); + this.angleLimitsPropertyBags = CsaProfileCracUtils.groupPropertyBags(angleLimitsPropertyBags, CsaProfileConstants.REQUEST_VOLTAGE_ANGLE_LIMIT); this.cracCreationContext = cracCreationContext; this.defaultMonitoredSides = defaultMonitoredSides; this.regionEic = regionEic; diff --git a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/contingency/CsaProfileContingencyCreator.java b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/contingency/CsaProfileContingencyCreator.java index 9840e5d8a0..f21c220bfb 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/contingency/CsaProfileContingencyCreator.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/contingency/CsaProfileContingencyCreator.java @@ -52,7 +52,7 @@ public CsaProfileContingencyCreator(Crac crac, Network network, PropertyBags con this.crac = crac; this.network = network; this.contingenciesPropertyBags = contingenciesPropertyBags; - this.contingencyEquipmentsPropertyBags = CsaProfileCracUtils.getMappedPropertyBagsSet(contingencyEquipmentsPropertyBags, CsaProfileConstants.REQUEST_CONTINGENCY); + this.contingencyEquipmentsPropertyBags = CsaProfileCracUtils.groupPropertyBags(contingencyEquipmentsPropertyBags, CsaProfileConstants.REQUEST_CONTINGENCY); this.cracCreationContext = cracCreationContext; this.createAndAddContingencies(); } diff --git a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/AssociationStatus.java b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/AssociationStatus.java new file mode 100644 index 0000000000..d7d8d412ea --- /dev/null +++ b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/AssociationStatus.java @@ -0,0 +1,17 @@ +/* + * 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 com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.remedialaction; + +import com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileConstants; + +/** + * @author Thomas Bouquet + */ +public record AssociationStatus(boolean isValid, + CsaProfileConstants.ElementCombinationConstraintKind elementCombinationConstraintKind, + String statusDetails) { +} diff --git a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/CsaProfileRemedialActionsCreator.java b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/CsaProfileRemedialActionsCreator.java index 458315f55e..c0e4af4c6f 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/CsaProfileRemedialActionsCreator.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/CsaProfileRemedialActionsCreator.java @@ -6,14 +6,11 @@ */ package com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.remedialaction; -import com.powsybl.openrao.commons.OpenRaoException; import com.powsybl.openrao.data.cracapi.*; -import com.powsybl.openrao.data.cracapi.cnec.AngleCnec; import com.powsybl.openrao.data.cracapi.cnec.Cnec; import com.powsybl.openrao.data.cracapi.cnec.FlowCnec; import com.powsybl.openrao.data.cracapi.cnec.VoltageCnec; import com.powsybl.openrao.data.cracapi.networkaction.*; -import com.powsybl.openrao.data.cracapi.rangeaction.PstRangeActionAdder; import com.powsybl.openrao.data.cracapi.usagerule.*; import com.powsybl.openrao.data.craccreation.creator.api.ImportStatus; import com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileConstants; @@ -23,10 +20,9 @@ import com.powsybl.openrao.data.craccreation.util.OpenRaoImportException; import com.powsybl.iidm.network.Network; import com.powsybl.triplestore.api.PropertyBag; -import org.apache.commons.lang3.tuple.Pair; +import com.powsybl.triplestore.api.PropertyBags; import java.util.*; -import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; @@ -37,20 +33,20 @@ public class CsaProfileRemedialActionsCreator { private final Crac crac; private final CsaProfileCracCreationContext cracCreationContext; Map contextByRaId = new TreeMap<>(); - private final OnConstraintUsageRuleHelper onConstraintUsageRuleHelper; private final ElementaryActionsHelper elementaryActionsHelper; private final NetworkActionCreator networkActionCreator; private final PstRangeActionCreator pstRangeActionCreator; - public CsaProfileRemedialActionsCreator(Crac crac, Network network, CsaProfileCracCreationContext cracCreationContext, OnConstraintUsageRuleHelper onConstraintUsageRuleHelper, ElementaryActionsHelper elementaryActionsHelper, int spsMaxTimeToImplementThreshold) { + public CsaProfileRemedialActionsCreator(Crac crac, Network network, CsaProfileCracCreationContext cracCreationContext, ElementaryActionsHelper elementaryActionsHelper, int spsMaxTimeToImplementThreshold, PropertyBags assessedElementPropertyBags, PropertyBags assessedElementWithRemedialActions, PropertyBags contingencyWithRemedialActions, Set cnecCreationContexts) { this.crac = crac; this.cracCreationContext = cracCreationContext; - this.onConstraintUsageRuleHelper = onConstraintUsageRuleHelper; this.elementaryActionsHelper = elementaryActionsHelper; this.networkActionCreator = new NetworkActionCreator(this.crac, network); this.pstRangeActionCreator = new PstRangeActionCreator(this.crac, network); - createRemedialActions(false, spsMaxTimeToImplementThreshold); - createRemedialActions(true, spsMaxTimeToImplementThreshold); + Map> linkedAeWithRa = CsaProfileCracUtils.groupPropertyBags(assessedElementWithRemedialActions, CsaProfileConstants.REQUEST_REMEDIAL_ACTION); + Map> linkedCoWithRa = CsaProfileCracUtils.groupPropertyBags(contingencyWithRemedialActions, CsaProfileConstants.REQUEST_REMEDIAL_ACTION); + createRemedialActions(false, spsMaxTimeToImplementThreshold, assessedElementPropertyBags, linkedAeWithRa, linkedCoWithRa, cnecCreationContexts); + createRemedialActions(true, spsMaxTimeToImplementThreshold, assessedElementPropertyBags, linkedAeWithRa, linkedCoWithRa, cnecCreationContexts); // standaloneRaIdsImplicatedIntoAGroup contain ids of Ra's depending on a group whether the group is imported or not Set standaloneRaIdsImplicatedIntoAGroup = createRemedialActionGroups(); standaloneRaIdsImplicatedIntoAGroup.forEach(crac::removeRemedialAction); @@ -58,7 +54,7 @@ public CsaProfileRemedialActionsCreator(Crac crac, Network network, CsaProfileCr this.cracCreationContext.setRemedialActionCreationContexts(new HashSet<>(contextByRaId.values())); } - private void createRemedialActions(boolean isSchemeRemedialAction, int spsMaxTimeToImplementThreshold) { + private void createRemedialActions(boolean isSchemeRemedialAction, int spsMaxTimeToImplementThreshold, PropertyBags assessedElementPropertyBags, Map> linkedAeWithRa, Map> linkedCoWithRa, Set cnecCreationContexts) { for (PropertyBag parentRemedialActionPropertyBag : elementaryActionsHelper.getParentRemedialActionPropertyBags(isSchemeRemedialAction)) { List alterations = new ArrayList<>(); String remedialActionId = parentRemedialActionPropertyBag.get(CsaProfileConstants.MRID); @@ -78,21 +74,15 @@ private void createRemedialActions(boolean isSchemeRemedialAction, int spsMaxTim remedialActionAdder.withOperator(CsaProfileCracUtils.getTsoNameFromUrl(tsoName)); } speedOpt.ifPresent(remedialActionAdder::withSpeed); - if (elementaryActionsHelper.getContingenciesByRemedialAction().containsKey(remedialActionId)) { - addOnContingencyStateUsageRules(parentRemedialActionPropertyBag, remedialActionId, elementaryActionsHelper.getContingenciesByRemedialAction(), remedialActionAdder, alterations, isSchemeRemedialAction, spsMaxTimeToImplementThreshold, remedialActionType); - } else { - if (!isSchemeRemedialAction) { - // no contingency linked to RA --> on instant usage rule if remedial action is not Auto - addOnInstantUsageRules(parentRemedialActionPropertyBag, remedialActionAdder, remedialActionId, alterations, spsMaxTimeToImplementThreshold); - } else { - throw new OpenRaoImportException(ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action " + remedialActionId + " will not be imported because no contingency is linked to the remedial action"); - } - } + + Instant instant = defineInstant(isSchemeRemedialAction, parentRemedialActionPropertyBag, remedialActionId, spsMaxTimeToImplementThreshold); + addUsageRules(remedialActionId, assessedElementPropertyBags, linkedAeWithRa.getOrDefault(remedialActionId, Set.of()), linkedCoWithRa.getOrDefault(remedialActionId, Set.of()), cnecCreationContexts, remedialActionAdder, alterations, instant, isSchemeRemedialAction, remedialActionType); remedialActionAdder.add(); + if (alterations.isEmpty()) { contextByRaId.put(remedialActionId, CsaProfileElementaryCreationContext.imported(remedialActionId, remedialActionId, targetRemedialActionNameOpt.orElse(remedialActionId), "", false)); } else { - contextByRaId.put(remedialActionId, CsaProfileElementaryCreationContext.imported(remedialActionId, remedialActionId, targetRemedialActionNameOpt.orElse(remedialActionId), String.join(". ", alterations), true)); + contextByRaId.put(remedialActionId, CsaProfileElementaryCreationContext.imported(remedialActionId, remedialActionId, targetRemedialActionNameOpt.orElse(remedialActionId), String.join(" ", alterations), true)); } } catch (OpenRaoImportException e) { @@ -101,50 +91,84 @@ private void createRemedialActions(boolean isSchemeRemedialAction, int spsMaxTim } } - private RemedialActionAdder getRemedialActionAdder(String remedialActionId, String elementaryActionsAggregatorId, RemedialActionType remedialActionType, boolean isSchemeRemedialAction, List alterations) { - RemedialActionAdder remedialActionAdder; - if (remedialActionType.equals(RemedialActionType.NETWORK_ACTION)) { - remedialActionAdder = networkActionCreator.getNetworkActionAdder(elementaryActionsHelper.getTopologyActions(isSchemeRemedialAction), elementaryActionsHelper.getRotatingMachineActions(isSchemeRemedialAction), elementaryActionsHelper.getShuntCompensatorModifications(isSchemeRemedialAction), elementaryActionsHelper.getStaticPropertyRangesByElementaryActionsAggregator(), remedialActionId, elementaryActionsAggregatorId, alterations); - } else { - remedialActionAdder = pstRangeActionCreator.getPstRangeActionAdder(elementaryActionsHelper.getTapPositionActions(isSchemeRemedialAction), elementaryActionsHelper.getStaticPropertyRangesByElementaryActionsAggregator(), remedialActionId, elementaryActionsAggregatorId, alterations); + private void addUsageRules(String remedialActionId, PropertyBags assessedElementPropertyBags, Set linkedAssessedElementWithRemedialActions, Set linkedContingencyWithRemedialActions, Set cnecCreationContexts, RemedialActionAdder remedialActionAdder, List alterations, Instant instant, boolean isSchemeRemedialAction, RemedialActionType remedialActionType) { + if (addOnConstraintUsageRules(remedialActionId, assessedElementPropertyBags, linkedAssessedElementWithRemedialActions, linkedContingencyWithRemedialActions, cnecCreationContexts, remedialActionAdder, alterations, instant, isSchemeRemedialAction, remedialActionType)) { + return; } - return remedialActionAdder; + if (addOnContingencyStateUsageRules(remedialActionId, linkedContingencyWithRemedialActions, remedialActionAdder, alterations, instant, isSchemeRemedialAction, remedialActionType)) { + return; + } + addOnInstantUsageRules(remedialActionId, remedialActionAdder, instant); } - private void addOnInstantUsageRules(PropertyBag parentRemedialActionPropertyBag, RemedialActionAdder remedialActionAdder, String remedialActionId, List alterations, int durationLimit) { - Instant instant = parentRemedialActionPropertyBag.get(CsaProfileConstants.KIND).equals(CsaProfileConstants.RemedialActionKind.PREVENTIVE.toString()) ? crac.getPreventiveInstant() : crac.getInstant(InstantKind.CURATIVE); - if (instant.isCurative()) { - instant = defineInstant(false, parentRemedialActionPropertyBag, remedialActionId, durationLimit); + private boolean addOnConstraintUsageRules(String remedialActionId, PropertyBags assessedElementPropertyBags, Set linkedAssessedElementWithRemedialActions, Set linkedContingencyWithRemedialActions, Set cnecCreationContexts, RemedialActionAdder remedialActionAdder, List alterations, Instant instant, boolean isSchemeRemedialAction, RemedialActionType remedialActionType) { + Map cnecStatusMap = OnConstraintUsageRuleHelper.processCnecsLinkedToRemedialAction(crac, remedialActionId, assessedElementPropertyBags, linkedAssessedElementWithRemedialActions, linkedContingencyWithRemedialActions, cnecCreationContexts); + cnecStatusMap.forEach((cnecId, cnecStatus) -> { + if (cnecStatus.isValid()) { + Cnec cnec = crac.getCnec(cnecId); + UsageMethod usageMethod = getUsageMethod(cnecStatus.elementCombinationConstraintKind(), isSchemeRemedialAction, instant, remedialActionType); + if (isOnConstraintInstantCoherent(cnec.getState().getInstant(), instant)) { + if (cnec instanceof FlowCnec) { + remedialActionAdder.newOnFlowConstraintUsageRule() + .withInstant(instant.getId()) + .withFlowCnec(cnecId) + .withUsageMethod(usageMethod) + .add(); + } else if (cnec instanceof VoltageCnec) { + remedialActionAdder.newOnVoltageConstraintUsageRule() + .withInstant(instant.getId()) + .withVoltageCnec(cnecId) + .withUsageMethod(usageMethod) + .add(); + } else { + remedialActionAdder.newOnAngleConstraintUsageRule() + .withInstant(instant.getId()) + .withAngleCnec(cnecId) + .withUsageMethod(usageMethod) + .add(); + } + } + } else { + alterations.add(cnecStatus.statusDetails()); + } + }); + return !linkedAssessedElementWithRemedialActions.isEmpty(); + } + + private boolean addOnContingencyStateUsageRules(String remedialActionId, Set linkedContingencyWithRemedialActions, RemedialActionAdder remedialActionAdder, List alterations, Instant instant, boolean isSchemeRemedialAction, RemedialActionType remedialActionType) { + Map contingencyStatusMap = OnContingencyStateUsageRuleHelper.processContingenciesLinkedToRemedialAction(crac, remedialActionId, linkedContingencyWithRemedialActions); + if (instant.isPreventive() && !linkedContingencyWithRemedialActions.isEmpty()) { + throw new OpenRaoImportException(ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action %s will not be imported because it is linked to a contingency but is not curative".formatted(remedialActionId)); } - boolean isLinkedToAssessedElements = elementaryActionsHelper.remedialActionIsLinkedToAssessedElements(remedialActionId); + contingencyStatusMap.forEach((contingencyId, contingencyStatus) -> { + if (contingencyStatus.isValid()) { + remedialActionAdder.newOnContingencyStateUsageRule() + .withInstant(instant.getId()) + .withContingency(contingencyId) + .withUsageMethod(getUsageMethod(contingencyStatus.elementCombinationConstraintKind(), isSchemeRemedialAction, instant, remedialActionType)) + .add(); + } else { + alterations.add(contingencyStatus.statusDetails()); + } + }); + return !linkedContingencyWithRemedialActions.isEmpty(); + } - addOnConstraintUsageRules(instant, remedialActionAdder, remedialActionId, alterations); - if (!isLinkedToAssessedElements) { - remedialActionAdder.newOnInstantUsageRule().withUsageMethod(UsageMethod.AVAILABLE).withInstant(instant.getId()).add(); + private void addOnInstantUsageRules(String remedialActionId, RemedialActionAdder remedialActionAdder, Instant instant) { + if (instant.isAuto()) { + throw new OpenRaoImportException(ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action %s will not be imported because no contingency or assessed element is linked to the remedial action and this is nor supported for ARAs".formatted(remedialActionId)); } + remedialActionAdder.newOnInstantUsageRule().withInstant(instant.getId()).withUsageMethod(UsageMethod.AVAILABLE).add(); } - private void checkElementCombinationConstraintKindsCoherence(String remedialActionId, Map> linkedContingencyWithRAs, List alterations, boolean isSchemeRemedialAction) { - // The same contingency cannot have different Element Combination Constraint Kinds - // The same contingency can appear several times, so we need to create a memory system - Set contingenciesWithIncluded = new HashSet<>(); - Set contingenciesWithConsidered = new HashSet<>(); - Set linkedContingencyWithRA = linkedContingencyWithRAs.get(remedialActionId); - for (PropertyBag propertyBag : linkedContingencyWithRA) { - String combinationKind = propertyBag.get(CsaProfileConstants.COMBINATION_CONSTRAINT_KIND); - String contingencyId = propertyBag.getId(CsaProfileConstants.REQUEST_CONTINGENCY); - if (combinationKind.equals(CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED.toString())) { - contingenciesWithIncluded.add(contingencyId); - } else if (combinationKind.equals(CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED.toString())) { - if (isSchemeRemedialAction) { - throw new OpenRaoImportException(ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action " + remedialActionId + " will not be imported because it must be linked to the contingency " + contingencyId + " with an 'included' ElementCombinationConstraintKind"); - } - contingenciesWithConsidered.add(contingencyId); - } - if (contingenciesWithIncluded.contains(contingencyId) && contingenciesWithConsidered.contains(contingencyId)) { - throw new OpenRaoImportException(ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action " + remedialActionId + " will not be imported because the ElementCombinationConstraintKinds that link the remedial action to the contingency " + contingencyId + " are different"); - } + private RemedialActionAdder getRemedialActionAdder(String remedialActionId, String elementaryActionsAggregatorId, RemedialActionType remedialActionType, boolean isSchemeRemedialAction, List alterations) { + RemedialActionAdder remedialActionAdder; + if (remedialActionType.equals(RemedialActionType.NETWORK_ACTION)) { + remedialActionAdder = networkActionCreator.getNetworkActionAdder(elementaryActionsHelper.getTopologyActions(isSchemeRemedialAction), elementaryActionsHelper.getRotatingMachineActions(isSchemeRemedialAction), elementaryActionsHelper.getShuntCompensatorModifications(isSchemeRemedialAction), elementaryActionsHelper.getStaticPropertyRangesByElementaryActionsAggregator(), remedialActionId, elementaryActionsAggregatorId, alterations); + } else { + remedialActionAdder = pstRangeActionCreator.getPstRangeActionAdder(elementaryActionsHelper.getTapPositionActions(isSchemeRemedialAction), elementaryActionsHelper.getStaticPropertyRangesByElementaryActionsAggregator(), remedialActionId, elementaryActionsAggregatorId); } + return remedialActionAdder; } private static void checkAvailability(PropertyBag remedialActionPropertyBag, String remedialActionId) { @@ -169,99 +193,14 @@ private Optional getSpeedOpt(RemedialActionType remedialActionType, Str } } - private void addOnConstraintUsageRules(Instant remedialActionInstant, RemedialActionAdder remedialActionAdder, String importableRemedialActionId, List alterations) { - UsageMethod usageMethod = remedialActionInstant.isAuto() && remedialActionAdder instanceof PstRangeActionAdder ? UsageMethod.FORCED : UsageMethod.AVAILABLE; - if (!onConstraintUsageRuleHelper.getExcludedCnecsByRemedialAction().containsKey(importableRemedialActionId)) { - onConstraintUsageRuleHelper.getImportedCnecsCombinableWithRas().forEach(addOnConstraintUsageRuleForCnec(remedialActionInstant, remedialActionAdder, usageMethod)); - } else { - alterations.add(String.format("The association 'RemedialAction'/'Cnecs' '%s'/'%s' will be ignored because 'excluded' combination constraint kind is not supported", importableRemedialActionId, String.join(". ", onConstraintUsageRuleHelper.getExcludedCnecsByRemedialAction().get(importableRemedialActionId)))); - } - if (onConstraintUsageRuleHelper.getConsideredAndIncludedCnecsByRemedialAction().containsKey(importableRemedialActionId)) { - onConstraintUsageRuleHelper.getConsideredAndIncludedCnecsByRemedialAction().get(importableRemedialActionId).forEach(addOnConstraintUsageRuleForCnec(remedialActionInstant, remedialActionAdder, usageMethod)); - } - } - - private Consumer addOnConstraintUsageRuleForCnec(Instant remedialActionInstant, RemedialActionAdder remedialActionAdder, UsageMethod usageMethod) { - return cnecId -> { - Cnec cnec = crac.getCnec(cnecId); - if (isOnConstraintInstantCoherent(cnec.getState().getInstant(), remedialActionInstant)) { - if (cnec instanceof FlowCnec) { - remedialActionAdder.newOnFlowConstraintUsageRule() - .withInstant(remedialActionInstant.getId()) - .withFlowCnec(cnecId) - .withUsageMethod(usageMethod) - .add(); - } else if (cnec instanceof VoltageCnec) { - remedialActionAdder.newOnVoltageConstraintUsageRule() - .withInstant(remedialActionInstant.getId()) - .withVoltageCnec(cnecId) - .withUsageMethod(usageMethod) - .add(); - } else if (cnec instanceof AngleCnec) { - remedialActionAdder.newOnAngleConstraintUsageRule() - .withInstant(remedialActionInstant.getId()) - .withAngleCnec(cnecId) - .withUsageMethod(usageMethod) - .add(); - } else { - throw new OpenRaoException(String.format("Unsupported cnec type %s", cnec.getClass().toString())); - } - } - }; - } - private static boolean isOnConstraintInstantCoherent(Instant cnecInstant, Instant remedialInstant) { return remedialInstant.isAuto() ? cnecInstant.isAuto() : !cnecInstant.comesBefore(remedialInstant); } - private void addOnContingencyStateUsageRules(PropertyBag parentRemedialActionPropertyBag, String remedialActionId, Map> linkedContingencyWithRAs, RemedialActionAdder remedialActionAdder, List alterations, boolean isSchemeRemedialAction, int durationLimit, RemedialActionType remedialActionType) { - checkElementCombinationConstraintKindsCoherence(remedialActionId, linkedContingencyWithRAs, alterations, isSchemeRemedialAction); - List> validContingencies = new ArrayList<>(); - List ignoredContingenciesMessages = new ArrayList<>(); - for (PropertyBag contingencyWithRemedialActionPropertyBag : linkedContingencyWithRAs.get(remedialActionId)) { - Optional normalEnabledOpt = Optional.ofNullable(contingencyWithRemedialActionPropertyBag.get(CsaProfileConstants.NORMAL_ENABLED)); - if (normalEnabledOpt.isPresent() && !Boolean.parseBoolean(normalEnabledOpt.get())) { - alterations.add(String.format("Association CO/RA '%s'/'%s' will be ignored because field 'normalEnabled' in ContingencyWithRemedialAction is set to false", contingencyWithRemedialActionPropertyBag.getId(CsaProfileConstants.REQUEST_CONTINGENCY), remedialActionId)); - } - if (!parentRemedialActionPropertyBag.get(CsaProfileConstants.KIND).equals(CsaProfileConstants.RemedialActionKind.CURATIVE.toString())) { - throw new OpenRaoImportException(ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action " + remedialActionId + " will not be imported because it is linked to a contingency but is not curative"); - } - String contingencyId = contingencyWithRemedialActionPropertyBag.getId(CsaProfileConstants.REQUEST_CONTINGENCY); - Optional normalEnabled = Optional.ofNullable(contingencyWithRemedialActionPropertyBag.get(CsaProfileConstants.NORMAL_ENABLED)); - if (normalEnabled.isPresent() && !Boolean.parseBoolean(normalEnabled.get())) { - ignoredContingenciesMessages.add("OnContingencyState usage rule for remedial action %s with contingency %s ignored because the link between the remedial action and the contingency is disabled or missing".formatted(remedialActionId, contingencyId)); - continue; - } - String combinationConstraintKind = contingencyWithRemedialActionPropertyBag.get(CsaProfileConstants.COMBINATION_CONSTRAINT_KIND); - if (!combinationConstraintKind.equals(CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED.toString()) && !combinationConstraintKind.equals(CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED.toString())) { - ignoredContingenciesMessages.add("OnContingencyState usage rule for remedial action %s with contingency %s ignored because of an illegal combinationConstraintKind".formatted(remedialActionId, contingencyId)); - continue; - } - Optional importedCsaProfileContingencyCreationContextOpt = cracCreationContext.getContingencyCreationContexts().stream().filter(co -> co.isImported() && co.getNativeId().equals(contingencyId)).findAny(); - if (importedCsaProfileContingencyCreationContextOpt.isEmpty()) { - ignoredContingenciesMessages.add("OnContingencyState usage rule for remedial action %s with contingency %s ignored because this contingency does not exist or was not imported by Open RAO".formatted(remedialActionId, contingencyId)); - continue; - } - validContingencies.add(Pair.of(importedCsaProfileContingencyCreationContextOpt.get().getElementId(), combinationConstraintKind.equals(CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED.toString()) ? CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED : CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED)); - } - - // If the remedial action is linked to an assessed element, no matter if this link or this assessed element is - // valid or not, the remedial action cannot have an onContingencyState usage rule because it would make it more - // available than what it was designed for - Instant instant = defineInstant(isSchemeRemedialAction, parentRemedialActionPropertyBag, remedialActionId, durationLimit); - addOnConstraintUsageRules(instant, remedialActionAdder, remedialActionId, alterations); - boolean isLinkedToAssessedElements = elementaryActionsHelper.remedialActionIsLinkedToAssessedElements(remedialActionId); - if (!isLinkedToAssessedElements) { - validContingencies.forEach(openRaoContingencyId -> remedialActionAdder.newOnContingencyStateUsageRule() - .withInstant(instant.getId()) - .withContingency(openRaoContingencyId.getLeft()) - .withUsageMethod(getUsageMethod(openRaoContingencyId.getRight(), isSchemeRemedialAction, instant, remedialActionType)).add()); - - alterations.addAll(ignoredContingenciesMessages); - } - } - private Instant defineInstant(boolean isSchemeRemedialAction, PropertyBag parentRemedialActionPropertyBag, String remedialActionId, int durationLimit) { + if (CsaProfileConstants.RemedialActionKind.PREVENTIVE.toString().equals(parentRemedialActionPropertyBag.get(CsaProfileConstants.KIND))) { + return crac.getPreventiveInstant(); + } if (isSchemeRemedialAction) { return crac.getInstant(InstantKind.AUTO); } @@ -269,17 +208,13 @@ private Instant defineInstant(boolean isSchemeRemedialAction, PropertyBag parent if (timeToImplement == null) { return crac.getInstant(InstantKind.CURATIVE); } - int durationInSeconds = 0; + int durationInSeconds; try { durationInSeconds = CsaProfileCracUtils.convertDurationToSeconds(timeToImplement); } catch (RuntimeException e) { throw new OpenRaoImportException(ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action " + remedialActionId + " will not be imported because of an irregular timeToImplement pattern"); } - if (durationInSeconds <= durationLimit) { - return crac.getInstant(InstantKind.AUTO); - } else { - return crac.getInstant(InstantKind.CURATIVE); - } + return durationInSeconds <= durationLimit ? crac.getInstant(InstantKind.AUTO) : crac.getInstant(InstantKind.CURATIVE); } private UsageMethod getUsageMethod(CsaProfileConstants.ElementCombinationConstraintKind elementCombinationConstraintKind, boolean isSchemeRemedialAction, Instant instant, RemedialActionType remedialActionType) { diff --git a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/ElementaryActionsHelper.java b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/ElementaryActionsHelper.java index 3113e08046..682633ea09 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/ElementaryActionsHelper.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/ElementaryActionsHelper.java @@ -64,20 +64,20 @@ public ElementaryActionsHelper(PropertyBags gridStateAlterationRemedialActionPro this.gridStateAlterationCollectionPropertyBags = gridStateAlterationCollectionPropertyBags; this.assessedElementWithRemedialActionPropertyBags = assessedElementWithRemedialActionPropertyBags; - this.remedialActionDependenciesByGroup = CsaProfileCracUtils.getMappedPropertyBagsSet(remedialActionDependenciesPropertyBags, CsaProfileConstants.DEPENDING_REMEDIAL_ACTION_GROUP); + this.remedialActionDependenciesByGroup = CsaProfileCracUtils.groupPropertyBags(remedialActionDependenciesPropertyBags, CsaProfileConstants.DEPENDING_REMEDIAL_ACTION_GROUP); - this.linkedContingencyWithRAs = CsaProfileCracUtils.getMappedPropertyBagsSet(contingencyWithRemedialActionsPropertyBags, CsaProfileConstants.GRID_STATE_ALTERATION_REMEDIAL_ACTION); - this.linkedStaticPropertyRanges = CsaProfileCracUtils.getMappedPropertyBagsSet(staticPropertyRangesPropertyBags, CsaProfileConstants.GRID_STATE_ALTERATION_REMEDIAL_ACTION); // the id here is the id of the subclass of gridStateAlteration (tapPositionAction, RotatingMachine, ..) + this.linkedContingencyWithRAs = CsaProfileCracUtils.groupPropertyBags(contingencyWithRemedialActionsPropertyBags, CsaProfileConstants.GRID_STATE_ALTERATION_REMEDIAL_ACTION); + this.linkedStaticPropertyRanges = CsaProfileCracUtils.groupPropertyBags(staticPropertyRangesPropertyBags, CsaProfileConstants.GRID_STATE_ALTERATION_REMEDIAL_ACTION); // the id here is the id of the subclass of gridStateAlteration (tapPositionAction, RotatingMachine, ..) - this.linkedTopologyActions = CsaProfileCracUtils.getMappedPropertyBagsSet(filterElementaryActions(topologyActionsPropertyBags, false), CsaProfileConstants.GRID_STATE_ALTERATION_REMEDIAL_ACTION); - this.linkedRotatingMachineActions = CsaProfileCracUtils.getMappedPropertyBagsSet(filterElementaryActions(rotatingMachineActionsPropertyBags, false), CsaProfileConstants.GRID_STATE_ALTERATION_REMEDIAL_ACTION); - this.linkedShuntCompensatorModification = CsaProfileCracUtils.getMappedPropertyBagsSet(filterElementaryActions(shuntCompensatorModificationPropertyBags, false), CsaProfileConstants.GRID_STATE_ALTERATION_REMEDIAL_ACTION); - this.linkedTapPositionActions = CsaProfileCracUtils.getMappedPropertyBagsSet(filterElementaryActions(tapPositionActionsPropertyBags, false), CsaProfileConstants.GRID_STATE_ALTERATION_REMEDIAL_ACTION); + this.linkedTopologyActions = CsaProfileCracUtils.groupPropertyBags(filterElementaryActions(topologyActionsPropertyBags, false), CsaProfileConstants.GRID_STATE_ALTERATION_REMEDIAL_ACTION); + this.linkedRotatingMachineActions = CsaProfileCracUtils.groupPropertyBags(filterElementaryActions(rotatingMachineActionsPropertyBags, false), CsaProfileConstants.GRID_STATE_ALTERATION_REMEDIAL_ACTION); + this.linkedShuntCompensatorModification = CsaProfileCracUtils.groupPropertyBags(filterElementaryActions(shuntCompensatorModificationPropertyBags, false), CsaProfileConstants.GRID_STATE_ALTERATION_REMEDIAL_ACTION); + this.linkedTapPositionActions = CsaProfileCracUtils.groupPropertyBags(filterElementaryActions(tapPositionActionsPropertyBags, false), CsaProfileConstants.GRID_STATE_ALTERATION_REMEDIAL_ACTION); - this.linkedTopologyActionsAuto = CsaProfileCracUtils.getMappedPropertyBagsSet(filterElementaryActions(topologyActionsPropertyBags, true), CsaProfileConstants.GRID_STATE_ALTERATION_COLLECTION); - this.linkedRotatingMachineActionsAuto = CsaProfileCracUtils.getMappedPropertyBagsSet(filterElementaryActions(rotatingMachineActionsPropertyBags, true), CsaProfileConstants.GRID_STATE_ALTERATION_COLLECTION); - this.linkedShuntCompensatorModificationAuto = CsaProfileCracUtils.getMappedPropertyBagsSet(filterElementaryActions(shuntCompensatorModificationPropertyBags, true), CsaProfileConstants.GRID_STATE_ALTERATION_COLLECTION); - this.linkedTapPositionActionsAuto = CsaProfileCracUtils.getMappedPropertyBagsSet(filterElementaryActions(tapPositionActionsPropertyBags, true), CsaProfileConstants.GRID_STATE_ALTERATION_COLLECTION); + this.linkedTopologyActionsAuto = CsaProfileCracUtils.groupPropertyBags(filterElementaryActions(topologyActionsPropertyBags, true), CsaProfileConstants.GRID_STATE_ALTERATION_COLLECTION); + this.linkedRotatingMachineActionsAuto = CsaProfileCracUtils.groupPropertyBags(filterElementaryActions(rotatingMachineActionsPropertyBags, true), CsaProfileConstants.GRID_STATE_ALTERATION_COLLECTION); + this.linkedShuntCompensatorModificationAuto = CsaProfileCracUtils.groupPropertyBags(filterElementaryActions(shuntCompensatorModificationPropertyBags, true), CsaProfileConstants.GRID_STATE_ALTERATION_COLLECTION); + this.linkedTapPositionActionsAuto = CsaProfileCracUtils.groupPropertyBags(filterElementaryActions(tapPositionActionsPropertyBags, true), CsaProfileConstants.GRID_STATE_ALTERATION_COLLECTION); } diff --git a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/NetworkActionCreator.java b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/NetworkActionCreator.java index 3112d811bd..3ffaa5b3d8 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/NetworkActionCreator.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/NetworkActionCreator.java @@ -122,7 +122,7 @@ private boolean addInjectionSetPointFromRotatingMachineAction(Set s .add(); return true; } else { - alterations.add("Elementary rotating machine action on rotating machine %s for remedial action %s ignored because the RotatingMachineAction is disabled".formatted(rotatingMachineId, remedialActionId)); + alterations.add("Elementary rotating machine action on rotating machine %s for remedial action %s ignored because the RotatingMachineAction is disabled.".formatted(rotatingMachineId, remedialActionId)); return false; } } @@ -145,7 +145,7 @@ private boolean addInjectionSetPointFromShuntCompensatorModification(Set staticPropertyRa .withActionType("0".equals(normalValue) ? ActionType.CLOSE : ActionType.OPEN).add(); return true; } else { - alterations.add("Elementary topology action on switch %s for remedial action %s ignored because the TopologyAction is disabled".formatted(switchId, remedialActionId)); + alterations.add("Elementary topology action on switch %s for remedial action %s ignored because the TopologyAction is disabled.".formatted(switchId, remedialActionId)); return false; } } diff --git a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/OnConstraintUsageRuleHelper.java b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/OnConstraintUsageRuleHelper.java index 45b64c16d8..49ac06cd60 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/OnConstraintUsageRuleHelper.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/OnConstraintUsageRuleHelper.java @@ -1,97 +1,112 @@ /* - * Copyright (c) 2023, RTE (http://www.rte-france.com) + * 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 com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.remedialaction; -import com.powsybl.openrao.commons.OpenRaoException; +import com.powsybl.contingency.Contingency; +import com.powsybl.openrao.data.cracapi.Crac; +import com.powsybl.openrao.data.cracapi.cnec.Cnec; import com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileConstants; import com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileElementaryCreationContext; import com.powsybl.triplestore.api.PropertyBag; import com.powsybl.triplestore.api.PropertyBags; -import java.util.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; +import static com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileConstants.COMBINATION_CONSTRAINT_KIND; +import static com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileConstants.REQUEST_ASSESSED_ELEMENT; + /** - * @author Mohamed Ben-rejeb {@literal } + * @author Thomas Bouquet */ -public class OnConstraintUsageRuleHelper { - private final Set csaProfileCnecCreationContexts; - - private final Set importedCnecsCombinableWithRas = new HashSet<>(); - private final Map> excludedCnecsByRemedialAction = new HashMap<>(); - private final Map> includedCnecsByRemedialAction = new HashMap<>(); - private final Map> consideredCnecsByRemedialAction = new HashMap<>(); - - public OnConstraintUsageRuleHelper(Set csaProfileCnecCreationContexts, PropertyBags assessedElements, PropertyBags assessedElementsWithRemedialAction) { - this.csaProfileCnecCreationContexts = csaProfileCnecCreationContexts; - readAssessedElementsCombinableWithRemedialActions(assessedElements); - readAssessedElementsWithRemedialAction(assessedElementsWithRemedialAction); - } +public final class OnConstraintUsageRuleHelper { - private void readAssessedElementsCombinableWithRemedialActions(PropertyBags assessedElements) { - List nativeIdsOfCnecsCombinableWithRas = assessedElements.stream() - .filter(element -> element.getId(CsaProfileConstants.REQUEST_ASSESSED_ELEMENT_IS_COMBINABLE_WITH_REMEDIAL_ACTION) != null && Boolean.parseBoolean(element.getId(CsaProfileConstants.REQUEST_ASSESSED_ELEMENT_IS_COMBINABLE_WITH_REMEDIAL_ACTION))) - .map(element -> element.getId(CsaProfileConstants.REQUEST_ASSESSED_ELEMENT)).toList(); - Map> nativeToOpenRaoCnecIdsCombinableWithRas = getImportedCnecsNativeIdsToOpenRaoIds(); - nativeToOpenRaoCnecIdsCombinableWithRas.keySet().retainAll(nativeIdsOfCnecsCombinableWithRas); - nativeToOpenRaoCnecIdsCombinableWithRas.values().stream().flatMap(Set::stream).forEach(importedCnecsCombinableWithRas::add); + private OnConstraintUsageRuleHelper() { } - private void readAssessedElementsWithRemedialAction(PropertyBags assessedElementsWithRemedialAction) { - assessedElementsWithRemedialAction.stream().filter(this::checkNormalEnabled).filter(propertyBag -> getImportedCnecsNativeIdsToOpenRaoIds().containsKey(propertyBag.getId(CsaProfileConstants.REQUEST_ASSESSED_ELEMENT))).forEach(propertyBag -> { - String combinationConstraintKind = propertyBag.get(CsaProfileConstants.COMBINATION_CONSTRAINT_KIND); - String remedialActionId = propertyBag.getId(CsaProfileConstants.REQUEST_REMEDIAL_ACTION); - String assessedElementId = propertyBag.getId(CsaProfileConstants.REQUEST_ASSESSED_ELEMENT); - - Set openRaoCnecIds = getImportedCnecsNativeIdsToOpenRaoIds().get(assessedElementId); - - if (combinationConstraintKind.equals(CsaProfileConstants.ElementCombinationConstraintKind.EXCLUDED.toString())) { - excludedCnecsByRemedialAction - .computeIfAbsent(remedialActionId, k -> new HashSet<>()) - .addAll(openRaoCnecIds); - } else if (combinationConstraintKind.equals(CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED.toString())) { - includedCnecsByRemedialAction - .computeIfAbsent(remedialActionId, k -> new HashSet<>()) - .addAll(openRaoCnecIds); - } else if (combinationConstraintKind.equals(CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED.toString())) { - consideredCnecsByRemedialAction - .computeIfAbsent(remedialActionId, k -> new HashSet<>()) - .addAll(openRaoCnecIds); - } else { - throw new OpenRaoException(String.format("Unsupported combinationConstraintKind of AssessedElementsWithRemedialAction with id %s, only ['INCLUDED', 'EXCLUDED', 'CONSIDERED'] are supported ", propertyBag.get(CsaProfileConstants.REQUEST_ASSESSED_ELEMENT_WITH_REMEDIAL_ACTION))); - } - }); + public static Set getImportedCnecFromAssessedElementId(String assessedElementId, Crac crac, Set cnecCreationContexts) { + return cnecCreationContexts.stream().filter(context -> context.isImported() && assessedElementId.equals(context.getNativeId())).map(context -> crac.getCnec(context.getElementId())).collect(Collectors.toSet()); } - private boolean checkNormalEnabled(PropertyBag propertyBag) { - Optional normalEnabledOpt = Optional.ofNullable(propertyBag.get(CsaProfileConstants.NORMAL_ENABLED)); - return normalEnabledOpt.isEmpty() || Boolean.parseBoolean(normalEnabledOpt.get()); + public static Set getCnecsBuiltFromAssessedElementsCombinableWithRemedialActions(Crac crac, Set cnecCreationContexts, PropertyBags assessedElementPropertyBags) { + Set cnecsCombinableWithRemedialActions = new HashSet<>(); + assessedElementPropertyBags.stream().filter(propertyBag -> Boolean.parseBoolean(propertyBag.getId(CsaProfileConstants.REQUEST_ASSESSED_ELEMENT_IS_COMBINABLE_WITH_REMEDIAL_ACTION))).forEach(propertyBag -> cnecsCombinableWithRemedialActions.addAll(getImportedCnecFromAssessedElementId(propertyBag.getId(CsaProfileConstants.REQUEST_ASSESSED_ELEMENT), crac, cnecCreationContexts))); + return cnecsCombinableWithRemedialActions; } - private Map> getImportedCnecsNativeIdsToOpenRaoIds() { - return csaProfileCnecCreationContexts.stream() - .filter(CsaProfileElementaryCreationContext::isImported) - .collect(Collectors.groupingBy( - CsaProfileElementaryCreationContext::getNativeId, - Collectors.mapping(CsaProfileElementaryCreationContext::getElementId, Collectors.toSet()) - )); + public static Set filterCnecsThatHaveGivenContingencies(Set cnecs, Set contingenciesIds) { + return cnecs.stream().filter(cnec -> cnec.getState().getContingency().isPresent() && contingenciesIds.contains(cnec.getState().getContingency().get().getId())).collect(Collectors.toSet()); } - public Set getImportedCnecsCombinableWithRas() { - return importedCnecsCombinableWithRas; - } + public static Map processCnecsLinkedToRemedialAction(Crac crac, String remedialActionId, PropertyBags assessedElementPropertyBags, Set linkedAssessedElementWithRemedialActions, Set linkedContingencyWithRemedialActions, Set cnecCreationContexts) { + Map contingencyStatusMap = OnContingencyStateUsageRuleHelper.processContingenciesLinkedToRemedialAction(crac, remedialActionId, linkedContingencyWithRemedialActions); + Map cnecStatusMap = new HashMap<>(); + Set cnecsCombinableWithRemedialAction = getCnecsBuiltFromAssessedElementsCombinableWithRemedialActions(crac, cnecCreationContexts, assessedElementPropertyBags); + Map validContingenciesUsageRules = contingencyStatusMap.entrySet().stream().filter(entry -> entry.getValue().isValid()).collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().elementCombinationConstraintKind())); - public Map> getExcludedCnecsByRemedialAction() { - return this.excludedCnecsByRemedialAction; - } + for (PropertyBag assessedElementWithRemedialActionPropertyBag : linkedAssessedElementWithRemedialActions) { + String assessedElementId = assessedElementWithRemedialActionPropertyBag.getId(REQUEST_ASSESSED_ELEMENT); + Set cnecs = contingencyStatusMap.isEmpty() ? getImportedCnecFromAssessedElementId(assessedElementId, crac, cnecCreationContexts) : filterCnecsThatHaveGivenContingencies(getImportedCnecFromAssessedElementId(assessedElementId, crac, cnecCreationContexts), validContingenciesUsageRules.keySet()); + + if (cnecStatusMap.containsKey(assessedElementId) || cnecs.stream().anyMatch(cnec -> cnecStatusMap.containsKey(cnec.getId()))) { + cnecStatusMap.put(assessedElementId, new AssociationStatus(false, null, "OnConstraint usage rule for remedial action %s with assessed element %s ignored because this assessed element has several conflictual links to the remedial action.".formatted(remedialActionId, assessedElementId))); + cnecs.stream().map(Cnec::getId).forEach(cnecStatusMap::remove); + continue; + } + + String combinationConstraintKindStr = assessedElementWithRemedialActionPropertyBag.get(COMBINATION_CONSTRAINT_KIND); + Optional normalEnabledOpt = Optional.ofNullable(assessedElementWithRemedialActionPropertyBag.get(CsaProfileConstants.NORMAL_ENABLED)); + + cnecsCombinableWithRemedialAction.removeAll(cnecs); + + if (cnecs.isEmpty()) { + cnecStatusMap.put(assessedElementId, new AssociationStatus(false, null, "OnConstraint usage rule for remedial action %s with assessed element %s ignored because no CNEC was imported by Open RAO from this assessed element.".formatted(remedialActionId, assessedElementId))); + continue; + } + + if (normalEnabledOpt.isPresent() && !Boolean.parseBoolean(normalEnabledOpt.get())) { + cnecStatusMap.put(assessedElementId, new AssociationStatus(false, null, "OnConstraint usage rule for remedial action %s with assessed element %s ignored because the association is disabled.".formatted(remedialActionId, assessedElementId))); + continue; + } + + if (!combinationConstraintKindStr.equals(CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED.toString()) && !combinationConstraintKindStr.equals(CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED.toString())) { + cnecStatusMap.put(assessedElementId, new AssociationStatus(false, null, "OnConstraint usage rule for remedial action %s with assessed element %s ignored because of an illegal combinationConstraintKind.".formatted(remedialActionId, assessedElementId))); + continue; + } + + CsaProfileConstants.ElementCombinationConstraintKind combinationConstraintKind = CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED.toString().equals(combinationConstraintKindStr) ? CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED : CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED; + + cnecs.forEach( + cnec -> { + if (cnec.getState().getContingency().isPresent()) { + Contingency contingency = cnec.getState().getContingency().get(); + if (validContingenciesUsageRules.containsKey(contingency.getId()) && combinationConstraintKind != validContingenciesUsageRules.get(contingency.getId())) { + cnecStatusMap.put(cnec.getId(), new AssociationStatus(false, null, "OnConstraint usage rule for remedial action %s with CNEC %s ignored because the combinationConstraintKinds between of the AssessedElementWithRemedialAction for assessed element %s and the ContingencyWithRemedialAction for contingency %s are different.".formatted(remedialActionId, cnec.getId(), assessedElementId, contingency.getId()))); + return; + } + } + cnecStatusMap.put(cnec.getId(), new AssociationStatus(true, combinationConstraintKind, "")); + } + ); + } + + // Add CNECs built from AssessedElements which are combinable with remedial actions + if (contingencyStatusMap.isEmpty()) { + // The remedial action is not associated to contingencies + cnecsCombinableWithRemedialAction.forEach(cnec -> cnecStatusMap.put(cnec.getId(), new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED, ""))); + } else { + // The remedial action is associated to contingencies (valid or not) + filterCnecsThatHaveGivenContingencies(cnecsCombinableWithRemedialAction, validContingenciesUsageRules.keySet()).forEach(cnec -> cnecStatusMap.put(cnec.getId(), new AssociationStatus(true, validContingenciesUsageRules.get(cnec.getState().getContingency().orElseThrow().getId()), ""))); + } - public Map> getConsideredAndIncludedCnecsByRemedialAction() { - Map> result = new HashMap<>(this.includedCnecsByRemedialAction); - result.putAll(consideredCnecsByRemedialAction); - return result; + return cnecStatusMap; } } diff --git a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/OnContingencyStateUsageRuleHelper.java b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/OnContingencyStateUsageRuleHelper.java new file mode 100644 index 0000000000..44f2adb071 --- /dev/null +++ b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/OnContingencyStateUsageRuleHelper.java @@ -0,0 +1,64 @@ +/* + * 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 com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.remedialaction; + +import com.powsybl.contingency.Contingency; +import com.powsybl.openrao.data.cracapi.Crac; +import com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileConstants; +import com.powsybl.triplestore.api.PropertyBag; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import static com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileConstants.COMBINATION_CONSTRAINT_KIND; +import static com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileConstants.REQUEST_CONTINGENCY; + +/** + * @author Thomas Bouquet + */ +public final class OnContingencyStateUsageRuleHelper { + + private OnContingencyStateUsageRuleHelper() { } + + public static Map processContingenciesLinkedToRemedialAction(Crac crac, String remedialActionId, Set linkedContingencyWithRemedialActions) { + Map contingencyStatusMap = new HashMap<>(); + + for (PropertyBag contingencyWithRemedialActionPropertyBag : linkedContingencyWithRemedialActions) { + String contingencyId = contingencyWithRemedialActionPropertyBag.getId(REQUEST_CONTINGENCY); + + if (contingencyStatusMap.containsKey(contingencyId)) { + contingencyStatusMap.put(contingencyId, new AssociationStatus(false, null, "OnContingencyState usage rule for remedial action %s with contingency %s ignored because this contingency has several conflictual links to the remedial action.".formatted(remedialActionId, contingencyId))); + continue; + } + + Contingency contingency = crac.getContingency(contingencyId); + String combinationConstraintKindStr = contingencyWithRemedialActionPropertyBag.get(COMBINATION_CONSTRAINT_KIND); + Optional normalEnabledOpt = Optional.ofNullable(contingencyWithRemedialActionPropertyBag.get(CsaProfileConstants.NORMAL_ENABLED)); + + if (contingency == null) { + contingencyStatusMap.put(contingencyId, new AssociationStatus(false, null, "OnContingencyState usage rule for remedial action %s with contingency %s ignored because this contingency does not exist or was not imported by Open RAO.".formatted(remedialActionId, contingencyId))); + continue; + } + + if (normalEnabledOpt.isPresent() && !Boolean.parseBoolean(normalEnabledOpt.get())) { + contingencyStatusMap.put(contingencyId, new AssociationStatus(false, null, "OnContingencyState usage rule for remedial action %s with contingency %s ignored because the association is disabled.".formatted(remedialActionId, contingencyId))); + continue; + } + + if (!combinationConstraintKindStr.equals(CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED.toString()) && !combinationConstraintKindStr.equals(CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED.toString())) { + contingencyStatusMap.put(contingencyId, new AssociationStatus(false, null, "OnContingencyState usage rule for remedial action %s with contingency %s ignored because of an illegal combinationConstraintKind.".formatted(remedialActionId, contingencyId))); + continue; + } + + contingencyStatusMap.put(contingencyId, new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED.toString().equals(combinationConstraintKindStr) ? CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED : CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED, "")); + } + + return contingencyStatusMap; + } +} diff --git a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/PstRangeActionCreator.java b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/PstRangeActionCreator.java index 2e8ed3c7b3..5dd0b88bc4 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/PstRangeActionCreator.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/main/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/PstRangeActionCreator.java @@ -32,7 +32,7 @@ public PstRangeActionCreator(Crac crac, Network network) { this.network = network; } - public PstRangeActionAdder getPstRangeActionAdder(Map> linkedTapPositionActions, Map> linkedStaticPropertyRanges, String remedialActionId, String elementaryActionsAggregatorId, List alterations) { + public PstRangeActionAdder getPstRangeActionAdder(Map> linkedTapPositionActions, Map> linkedStaticPropertyRanges, String remedialActionId, String elementaryActionsAggregatorId) { PstRangeActionAdder pstRangeActionAdder = crac.newPstRangeAction().withId(remedialActionId); if (linkedTapPositionActions.containsKey(elementaryActionsAggregatorId)) { diff --git a/data/crac-creation/crac-creator-csa-profiles/src/main/resources/csa_profile.sparql b/data/crac-creation/crac-creator-csa-profiles/src/main/resources/csa_profile.sparql index c1b59181fc..29c81b67d3 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/main/resources/csa_profile.sparql +++ b/data/crac-creation/crac-creator-csa-profiles/src/main/resources/csa_profile.sparql @@ -273,8 +273,7 @@ SELECT * GRAPH <%s> { ?contingencyWithRemedialAction rdf:type nc:ContingencyWithRemedialAction ; - nc:ContingencyWithRemedialAction.mRID ?mRID ; - nc:ContingencyWithRemedialAction.RemedialAction ?gridStateAlterationRemedialAction ; + nc:ContingencyWithRemedialAction.RemedialAction ?remedialAction ; nc:ContingencyWithRemedialAction.Contingency ?contingency ; nc:ContingencyWithRemedialAction.combinationConstraintKind ?combinationConstraintKind ; diff --git a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracCreationTestUtil.java b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracCreationTestUtil.java index 1c6847d5dc..65580bc41d 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracCreationTestUtil.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracCreationTestUtil.java @@ -186,6 +186,10 @@ public static void assertHasOnFlowConstraintUsageRule(CsaProfileCracCreationCont ); } + public static void assertHasOnFlowConstraintUsageRule(CsaProfileCracCreationContext cracCreationContext, String raId, String flowCnecId, String instant, UsageMethod usageMethod) { + assertHasOnFlowConstraintUsageRule(cracCreationContext, raId, flowCnecId, cracCreationContext.getCrac().getInstant(instant), usageMethod); + } + public static void assertHasOnAngleConstraintUsageRule(CsaProfileCracCreationContext cracCreationContext, String raId, String angleCnecId, Instant instant, UsageMethod usageMethod) { assertTrue( cracCreationContext.getCrac().getRemedialAction(raId).getUsageRules().stream().filter(OnAngleConstraint.class::isInstance) diff --git a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracUtilsTest.java b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracUtilsTest.java index 560924958c..e3b5343b9e 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracUtilsTest.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/CsaProfileCracUtilsTest.java @@ -51,7 +51,7 @@ void testGetLinkedPropertyBags() { sourcesPb.addAll(Arrays.asList(sourcePb1, sourcePb2, sourcePb3)); - Map> map = CsaProfileCracUtils.getMappedPropertyBagsSet(sourcesPb, "sourceProperty2"); + Map> map = CsaProfileCracUtils.groupPropertyBags(sourcesPb, "sourceProperty2"); Set result = map.get(destPb.getId("destProperty3")); assertNotNull(result); assertEquals(1, result.size()); diff --git a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/AngleCnecCreationTest.java b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/AngleCnecCreationTest.java index cbcb3b308e..372b2addff 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/AngleCnecCreationTest.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/AngleCnecCreationTest.java @@ -148,7 +148,7 @@ void importAngleCnecs() { assertCnecNotImported(cracCreationContext, "assessed-element-12", ImportStatus.INCONSISTENCY_IN_DATA, "AssessedElement assessed-element-12 ignored because the network element FFR1AA1 _generator is not a bus bar section"); assertCnecNotImported(cracCreationContext, "assessed-element-13", ImportStatus.INCONSISTENCY_IN_DATA, "AssessedElement assessed-element-13 ignored because the network element FFR2AA1 _generator is not a bus bar section"); - assertHasOnAngleConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE1 (assessed-element-1) - RTE_CO1 - curative", cracCreationContext.getCrac().getInstant(CURATIVE_INSTANT_ID), UsageMethod.AVAILABLE); + assertHasOnAngleConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE1 (assessed-element-1) - RTE_CO1 - curative", cracCreationContext.getCrac().getInstant(CURATIVE_INSTANT_ID), UsageMethod.FORCED); assertHasOnAngleConstraintUsageRule(cracCreationContext, "remedial-action-2", "RTE_AE2 (assessed-element-2) - RTE_CO1 - curative", cracCreationContext.getCrac().getInstant(CURATIVE_INSTANT_ID), UsageMethod.AVAILABLE); assertHasOnAngleConstraintUsageRule(cracCreationContext, "remedial-action-2", "RTE_AE2 (assessed-element-2) - RTE_CO2 - curative", cracCreationContext.getCrac().getInstant(CURATIVE_INSTANT_ID), UsageMethod.AVAILABLE); } diff --git a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/FlowCnecCreationTest.java b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/FlowCnecCreationTest.java index 567e6be4ba..0a527f2a36 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/FlowCnecCreationTest.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/FlowCnecCreationTest.java @@ -300,7 +300,7 @@ void importFlowCnecs() { assertCnecNotImported(cracCreationContext, "assessed-element-13", ImportStatus.INCONSISTENCY_IN_DATA, "AssessedElement assessed-element-13 ignored because the assessed element is not in base case and not combinable with contingencies, but no explicit link to a contingency was found"); assertCnecNotImported(cracCreationContext, "assessed-element-14", ImportStatus.INCONSISTENCY_IN_DATA, "AssessedElement assessed-element-14 ignored because the network element FFR1AA1 _generator is not a branch"); - assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE1 (assessed-element-1) - RTE_CO1 - curative", cracCreationContext.getCrac().getInstant(CURATIVE_INSTANT_ID), UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE1 (assessed-element-1) - RTE_CO1 - curative", cracCreationContext.getCrac().getInstant(CURATIVE_INSTANT_ID), UsageMethod.FORCED); assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-2", "RTE_AE4 (assessed-element-4) - RTE_CO1 - curative", cracCreationContext.getCrac().getInstant(CURATIVE_INSTANT_ID), UsageMethod.AVAILABLE); assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-2", "RTE_AE4 (assessed-element-4) - RTE_CO2 - curative", cracCreationContext.getCrac().getInstant(CURATIVE_INSTANT_ID), UsageMethod.AVAILABLE); } diff --git a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/VoltageCnecCreationTest.java b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/VoltageCnecCreationTest.java index 39c30eb3ed..5678935b01 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/VoltageCnecCreationTest.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/cnec/VoltageCnecCreationTest.java @@ -77,8 +77,8 @@ void importVoltageCnecs() { assertCnecNotImported(cracCreationContext, "assessed-element-8", ImportStatus.INCOMPLETE_DATA, "AssessedElement assessed-element-8 ignored because no ConductingEquipment or OperationalLimit was provided"); assertHasOnVoltageConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE1 (assessed-element-1) - RTE_CO1 - curative", cracCreationContext.getCrac().getInstant(CURATIVE_INSTANT_ID), UsageMethod.AVAILABLE); - assertHasOnVoltageConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE2 (assessed-element-2) - RTE_CO1 - curative", cracCreationContext.getCrac().getInstant(CURATIVE_INSTANT_ID), UsageMethod.AVAILABLE); - assertHasOnVoltageConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE2 (assessed-element-2) - RTE_CO2 - curative", cracCreationContext.getCrac().getInstant(CURATIVE_INSTANT_ID), UsageMethod.AVAILABLE); + assertHasOnVoltageConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE2 (assessed-element-2) - RTE_CO1 - curative", cracCreationContext.getCrac().getInstant(CURATIVE_INSTANT_ID), UsageMethod.FORCED); + assertHasOnVoltageConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE2 (assessed-element-2) - RTE_CO2 - curative", cracCreationContext.getCrac().getInstant(CURATIVE_INSTANT_ID), UsageMethod.FORCED); assertHasOnVoltageConstraintUsageRule(cracCreationContext, "remedial-action-2", "RTE_AE1 (assessed-element-1) - RTE_CO1 - curative", cracCreationContext.getCrac().getInstant(CURATIVE_INSTANT_ID), UsageMethod.AVAILABLE); } } diff --git a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/AutoRemedialActionTest.java b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/AutoRemedialActionTest.java index 837306f8bc..c1e2f39eac 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/AutoRemedialActionTest.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/AutoRemedialActionTest.java @@ -62,19 +62,18 @@ void importAutoRemedialActions() { assertEquals(InstantKind.AUTO, networkSpsUsageRule.getInstant().getKind()); assertEquals(UsageMethod.FORCED, networkSpsUsageRule.getUsageMethod()); - assertEquals(12, cracCreationContext.getRemedialActionCreationContexts().stream().filter(ra -> !ra.isImported()).toList().size()); + assertEquals(11, cracCreationContext.getRemedialActionCreationContexts().stream().filter(ra -> !ra.isImported()).toList().size()); assertRaNotImported(cracCreationContext, "sps-with-multiple-remedial-action-schemes", ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action sps-with-multiple-remedial-action-schemes will not be imported because it has several conflictual RemedialActionSchemes"); assertRaNotImported(cracCreationContext, "sps-with-multiple-stages", ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action sps-with-multiple-stages will not be imported because it has several conflictual Stages"); assertRaNotImported(cracCreationContext, "pst-sps-without-speed", ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action pst-sps-without-speed will not be imported because an auto PST range action must have a speed defined"); assertRaNotImported(cracCreationContext, "preventive-sps", ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action preventive-sps will not be imported because auto remedial action must be of curative kind"); - assertRaNotImported(cracCreationContext, "not-forced-sps", ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action not-forced-sps will not be imported because it must be linked to the contingency contingency with an 'included' ElementCombinationConstraintKind"); assertRaNotImported(cracCreationContext, "sps-with-unarmed-remedial-action-scheme", ImportStatus.NOT_FOR_RAO, "Remedial action sps-with-unarmed-remedial-action-scheme will not be imported because RemedialActionScheme 5f7796db-a662-488d-a938-39c8a2b36055 is not armed"); assertRaNotImported(cracCreationContext, "not-sips-sps", ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action not-sips-sps will not be imported because of an unsupported kind for remedial action schedule (only SIPS allowed)"); assertRaNotImported(cracCreationContext, "sps-without-remedial-action-scheme", ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action sps-without-remedial-action-scheme will not be imported because it has no associated RemedialActionScheme"); assertRaNotImported(cracCreationContext, "sps-without-stage", ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action sps-without-stage will not be imported because it has no associated Stage"); assertRaNotImported(cracCreationContext, "sps-without-grid-state-alteration-collection", ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action sps-without-grid-state-alteration-collection will not be imported because it has no associated GridStateAlterationCollection"); assertRaNotImported(cracCreationContext, "sps-without-elementary-actions", ImportStatus.NOT_FOR_RAO, "Remedial action sps-without-elementary-actions will not be imported because it has no elementary action"); - assertRaNotImported(cracCreationContext, "sps-without-contingency", ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action sps-without-contingency will not be imported because no contingency is linked to the remedial action"); + assertRaNotImported(cracCreationContext, "sps-without-contingency", ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action sps-without-contingency will not be imported because no contingency or assessed element is linked to the remedial action and this is nor supported for ARAs"); } } diff --git a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/GroupRemedialActionTest.java b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/GroupRemedialActionTest.java index 99e4b2ede7..0ac3bb7dcc 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/GroupRemedialActionTest.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/GroupRemedialActionTest.java @@ -62,7 +62,7 @@ void importGroupedRemedialActions() { UsageRule ur3 = cracCreationContext.getCrac().getNetworkAction("7d2833e4-c5a8-4d79-b936-c735a58f1774").getUsageRules().iterator().next(); assertTrue(ur3 instanceof OnFlowConstraint); assertEquals(InstantKind.CURATIVE, ur3.getInstant().getKind()); - assertEquals(UsageMethod.AVAILABLE, ur3.getUsageMethod()); + assertEquals(UsageMethod.FORCED, ur3.getUsageMethod()); assertEquals("RTE_AE1 (f7708112-b880-4674-98a1-b005a01a61d5) - RTE_CO1 - curative", ((OnFlowConstraint) ur3).getFlowCnec().getId()); assertNetworkActionImported(cracCreationContext, "66979f64-3c52-486c-84f7-b5439cd71765", Set.of("BBE1AA1 BBE4AA1 1"), true, 1, "RTE"); diff --git a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/OnConstraintUsageRuleHelperTest.java b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/OnConstraintUsageRuleHelperTest.java new file mode 100644 index 0000000000..e82fffc64a --- /dev/null +++ b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/OnConstraintUsageRuleHelperTest.java @@ -0,0 +1,305 @@ +/* + * 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 com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.remedialaction; + +import com.powsybl.openrao.commons.Unit; +import com.powsybl.openrao.data.cracapi.Crac; +import com.powsybl.openrao.data.cracapi.InstantKind; +import com.powsybl.openrao.data.cracapi.cnec.Side; +import com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileConstants; +import com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileElementaryCreationContext; +import com.powsybl.openrao.data.cracimpl.CracImpl; +import com.powsybl.triplestore.api.PropertyBag; +import com.powsybl.triplestore.api.PropertyBags; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @author Thomas Bouquet + */ +class OnConstraintUsageRuleHelperTest { + private Crac crac; + private Set cnecCreationContexts; + private PropertyBags assessedElementPropertyBags; + private Set assessedElementWithRemedialActions; + private Set contingencyWithRemedialActions; + + @BeforeEach + void setUp() { + crac = new CracImpl("crac"); + + // Set-up instants + + crac.newInstant("preventive", InstantKind.PREVENTIVE); + crac.newInstant("outage", InstantKind.OUTAGE); + crac.newInstant("auto", InstantKind.AUTO); + crac.newInstant("curative", InstantKind.CURATIVE); + + // Add contingencies + + crac.newContingency().withId("contingency-1").add(); + crac.newContingency().withId("contingency-2").add(); + crac.newContingency().withId("contingency-3").add(); + crac.newContingency().withId("contingency-4").add(); + crac.newContingency().withId("contingency-5").add(); + crac.newContingency().withId("contingency-6").add(); + + // Add FlowCNECs + + crac.newFlowCnec().withId("Line 1 - curative - CO1").withNominalVoltage(400d).withNetworkElement("Line 1").withInstant("curative").withContingency("contingency-1").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 2 - preventive").withNominalVoltage(400d).withNetworkElement("Line 2").withInstant("preventive").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 2 - curative - CO1").withNominalVoltage(400d).withNetworkElement("Line 2").withInstant("curative").withContingency("contingency-1").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 2 - curative - CO2").withNominalVoltage(400d).withNetworkElement("Line 2").withInstant("curative").withContingency("contingency-2").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 2 - curative - CO3").withNominalVoltage(400d).withNetworkElement("Line 2").withInstant("curative").withContingency("contingency-3").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 2 - curative - CO4").withNominalVoltage(400d).withNetworkElement("Line 2").withInstant("curative").withContingency("contingency-4").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 2 - curative - CO5").withNominalVoltage(400d).withNetworkElement("Line 2").withInstant("curative").withContingency("contingency-5").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 2 - curative - CO6").withNominalVoltage(400d).withNetworkElement("Line 2").withInstant("curative").withContingency("contingency-6").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 3 - preventive").withNominalVoltage(400d).withNetworkElement("Line 3").withInstant("preventive").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 3 - curative - CO1").withNominalVoltage(400d).withNetworkElement("Line 3").withInstant("curative").withContingency("contingency-1").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 3 - curative - CO2").withNominalVoltage(400d).withNetworkElement("Line 3").withInstant("curative").withContingency("contingency-2").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 3 - curative - CO3").withNominalVoltage(400d).withNetworkElement("Line 3").withInstant("curative").withContingency("contingency-3").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 3 - curative - CO4").withNominalVoltage(400d).withNetworkElement("Line 3").withInstant("curative").withContingency("contingency-4").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 3 - curative - CO5").withNominalVoltage(400d).withNetworkElement("Line 3").withInstant("curative").withContingency("contingency-5").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 3 - curative - CO6").withNominalVoltage(400d).withNetworkElement("Line 3").withInstant("curative").withContingency("contingency-6").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 4 - curative - CO1").withNominalVoltage(400d).withNetworkElement("Line 4").withInstant("curative").withContingency("contingency-1").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 6 - curative - CO1").withNominalVoltage(400d).withNetworkElement("Line 6").withInstant("curative").withContingency("contingency-1").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + crac.newFlowCnec().withId("Line 8 - curative - CO1").withNominalVoltage(400d).withNetworkElement("Line 8").withInstant("curative").withContingency("contingency-1").newThreshold().withSide(Side.LEFT).withMax(1000d).withUnit(Unit.AMPERE).add().add(); + + // Add CNEC creation contexts + + cnecCreationContexts = new HashSet<>(); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-1", "Line 1 - curative - CO1", "Line 1 - curative - CO1", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-2", "Line 2 - preventive", "Line 2 - preventive", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-2", "Line 2 - curative - CO1", "Line 2 - curative - CO1", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-2", "Line 2 - curative - CO2", "Line 2 - curative - CO2", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-2", "Line 2 - curative - CO3", "Line 2 - curative - CO3", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-2", "Line 2 - curative - CO4", "Line 2 - curative - CO4", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-2", "Line 2 - curative - CO5", "Line 2 - curative - CO5", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-2", "Line 2 - curative - CO6", "Line 2 - curative - CO6", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-3", "Line 3 - preventive", "Line 3 - preventive", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-3", "Line 3 - curative - CO1", "Line 3 - curative - CO1", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-3", "Line 3 - curative - CO2", "Line 3 - curative - CO2", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-3", "Line 3 - curative - CO3", "Line 3 - curative - CO3", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-3", "Line 3 - curative - CO4", "Line 3 - curative - CO4", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-3", "Line 3 - curative - CO5", "Line 3 - curative - CO5", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-3", "Line 3 - curative - CO6", "Line 3 - curative - CO6", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-4", "Line 4 - curative - CO1", "Line 4 - curative - CO1", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-6", "Line 6 - curative - CO1", "Line 6 - curative - CO1", "", false)); + cnecCreationContexts.add(CsaProfileElementaryCreationContext.imported("assessed-element-8", "Line 8 - curative - CO1", "Line 8 - curative - CO1", "", false)); + + // Add AssessedElement property bags + + PropertyBag assessedElement1PropertyBag = new PropertyBag(List.of("assessedElement", "isCombinableWithRemedialAction"), true, false); + assessedElement1PropertyBag.put("assessedElement", "_assessed-element-1"); + assessedElement1PropertyBag.put("isCombinableWithRemedialAction", "false"); + + PropertyBag assessedElement2PropertyBag = new PropertyBag(List.of("assessedElement", "isCombinableWithRemedialAction"), true, false); + assessedElement2PropertyBag.put("assessedElement", "_assessed-element-2"); + assessedElement2PropertyBag.put("isCombinableWithRemedialAction", "true"); + + PropertyBag assessedElement3PropertyBag = new PropertyBag(List.of("assessedElement", "isCombinableWithRemedialAction"), true, false); + assessedElement3PropertyBag.put("assessedElement", "_assessed-element-3"); + assessedElement3PropertyBag.put("isCombinableWithRemedialAction", "true"); + + PropertyBag assessedElement4PropertyBag = new PropertyBag(List.of("assessedElement", "isCombinableWithRemedialAction"), true, false); + assessedElement4PropertyBag.put("assessedElement", "_assessed-element-4"); + assessedElement4PropertyBag.put("isCombinableWithRemedialAction", "false"); + + PropertyBag assessedElement5PropertyBag = new PropertyBag(List.of("assessedElement", "isCombinableWithRemedialAction"), true, false); + assessedElement5PropertyBag.put("assessedElement", "_assessed-element-5"); + assessedElement5PropertyBag.put("isCombinableWithRemedialAction", "false"); + + PropertyBag assessedElement6PropertyBag = new PropertyBag(List.of("assessedElement", "isCombinableWithRemedialAction"), true, false); + assessedElement6PropertyBag.put("assessedElement", "_assessed-element-6"); + assessedElement6PropertyBag.put("isCombinableWithRemedialAction", "false"); + + PropertyBag assessedElement8PropertyBag = new PropertyBag(List.of("assessedElement", "isCombinableWithRemedialAction"), true, false); + assessedElement8PropertyBag.put("assessedElement", "_assessed-element-8"); + assessedElement8PropertyBag.put("isCombinableWithRemedialAction", "false"); + + assessedElementPropertyBags = new PropertyBags(Set.of(assessedElement1PropertyBag, assessedElement2PropertyBag, assessedElement3PropertyBag, assessedElement4PropertyBag, assessedElement5PropertyBag, assessedElement6PropertyBag, assessedElement8PropertyBag)); + + // Add AssessedElementWithRemedialAction property bags + + PropertyBag ae1WithRaPropertyBag = new PropertyBag(List.of("assessedElementWithRemedialAction", "remedialAction", "assessedElement", "combinationConstraintKind"), true, false); + ae1WithRaPropertyBag.put("assessedElementWithRemedialAction", "_ae1xra"); + ae1WithRaPropertyBag.put("remedialAction", "remedial-action"); + ae1WithRaPropertyBag.put("assessedElement", "assessed-element-1"); + ae1WithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.included"); + + PropertyBag ae2WithRaPropertyBag = new PropertyBag(List.of("assessedElementWithRemedialAction", "remedialAction", "assessedElement", "combinationConstraintKind", "normalEnabled"), true, false); + ae2WithRaPropertyBag.put("assessedElementWithRemedialAction", "_ae2xra"); + ae2WithRaPropertyBag.put("remedialAction", "remedial-action"); + ae2WithRaPropertyBag.put("assessedElement", "assessed-element-2"); + ae2WithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.included"); + ae2WithRaPropertyBag.put("normalEnabled", "true"); + + PropertyBag ae4WithRaPropertyBag = new PropertyBag(List.of("assessedElementWithRemedialAction", "remedialAction", "assessedElement", "combinationConstraintKind", "normalEnabled"), true, false); + ae4WithRaPropertyBag.put("assessedElementWithRemedialAction", "_ae4xra"); + ae4WithRaPropertyBag.put("remedialAction", "remedial-action"); + ae4WithRaPropertyBag.put("assessedElement", "assessed-element-4"); + ae4WithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.considered"); + ae4WithRaPropertyBag.put("normalEnabled", "false"); + + PropertyBag ae5WithRaPropertyBag1 = new PropertyBag(List.of("assessedElementWithRemedialAction", "remedialAction", "assessedElement", "combinationConstraintKind"), true, false); + ae5WithRaPropertyBag1.put("assessedElementWithRemedialAction", "_ae5xra-included"); + ae5WithRaPropertyBag1.put("remedialAction", "remedial-action"); + ae5WithRaPropertyBag1.put("assessedElement", "assessed-element-5"); + ae5WithRaPropertyBag1.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.included"); + ae5WithRaPropertyBag1.setResourceNames(List.of("remedialAction", "assessedElement", "combinationConstraintKind")); + + PropertyBag ae5WithRaPropertyBag2 = new PropertyBag(List.of("assessedElementWithRemedialAction", "remedialAction", "assessedElement", "combinationConstraintKind"), true, false); + ae5WithRaPropertyBag2.put("assessedElementWithRemedialAction", "_ae5xra-considered"); + ae5WithRaPropertyBag2.put("remedialAction", "remedial-action"); + ae5WithRaPropertyBag2.put("assessedElement", "assessed-element-5"); + ae5WithRaPropertyBag2.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.considered"); + ae5WithRaPropertyBag2.setResourceNames(List.of("remedialAction", "assessedElement", "combinationConstraintKind")); + + PropertyBag ae6WithRaPropertyBag = new PropertyBag(List.of("assessedElementWithRemedialAction", "remedialAction", "assessedElement", "combinationConstraintKind"), true, false); + ae6WithRaPropertyBag.put("assessedElementWithRemedialAction", "_ae6xra"); + ae6WithRaPropertyBag.put("remedialAction", "remedial-action"); + ae6WithRaPropertyBag.put("assessedElement", "assessed-element-6"); + ae6WithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.excluded"); + ae6WithRaPropertyBag.setResourceNames(List.of("remedialAction", "assessedElement", "combinationConstraintKind")); + + PropertyBag ae7WithRaPropertyBag = new PropertyBag(List.of("assessedElementWithRemedialAction", "remedialAction", "assessedElement", "combinationConstraintKind"), true, false); + ae7WithRaPropertyBag.put("assessedElementWithRemedialAction", "_ae7xra"); + ae7WithRaPropertyBag.put("remedialAction", "remedial-action"); + ae7WithRaPropertyBag.put("assessedElement", "assessed-element-7"); + ae7WithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.included"); + + PropertyBag ae8WithRaPropertyBagIncluded = new PropertyBag(List.of("assessedElementWithRemedialAction", "remedialAction", "assessedElement", "combinationConstraintKind"), true, false); + ae8WithRaPropertyBagIncluded.put("assessedElementWithRemedialAction", "_ae8xra-included"); + ae8WithRaPropertyBagIncluded.put("remedialAction", "remedial-action"); + ae8WithRaPropertyBagIncluded.put("assessedElement", "assessed-element-8"); + ae8WithRaPropertyBagIncluded.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.included"); + + PropertyBag ae8WithRaPropertyBagConsidered = new PropertyBag(List.of("assessedElementWithRemedialAction", "remedialAction", "assessedElement", "combinationConstraintKind"), true, false); + ae8WithRaPropertyBagConsidered.put("assessedElementWithRemedialAction", "_ae8xra-considered"); + ae8WithRaPropertyBagConsidered.put("remedialAction", "remedial-action"); + ae8WithRaPropertyBagConsidered.put("assessedElement", "assessed-element-8"); + ae8WithRaPropertyBagConsidered.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.considered"); + + assessedElementWithRemedialActions = Set.of(ae1WithRaPropertyBag, ae2WithRaPropertyBag, ae4WithRaPropertyBag, ae5WithRaPropertyBag1, ae5WithRaPropertyBag2, ae6WithRaPropertyBag, ae7WithRaPropertyBag, ae8WithRaPropertyBagIncluded, ae8WithRaPropertyBagConsidered); + + // Add ContingencyWithRemedialAction property bags + + PropertyBag co1WithRaPropertyBag = new PropertyBag(List.of("contingencyWithRemedialAction", "mRID", "remedialAction", "contingency", "combinationConstraintKind", "normalEnabled"), true, false); + co1WithRaPropertyBag.put("contingencyWithRemedialAction", "_co1xra"); + co1WithRaPropertyBag.put("mRID", "_co1xra"); + co1WithRaPropertyBag.put("remedialAction", "remedial-action"); + co1WithRaPropertyBag.put("contingency", "contingency-1"); + co1WithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.included"); + co1WithRaPropertyBag.put("normalEnabled", "true"); + + PropertyBag co2WithRaPropertyBag = new PropertyBag(List.of("contingencyWithRemedialAction", "mRID", "remedialAction", "contingency", "combinationConstraintKind", "normalEnabled"), true, false); + co2WithRaPropertyBag.put("contingencyWithRemedialAction", "_co2xra"); + co2WithRaPropertyBag.put("mRID", "_co2xra"); + co2WithRaPropertyBag.put("remedialAction", "remedial-action"); + co2WithRaPropertyBag.put("contingency", "contingency-2"); + co2WithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.considered"); + co2WithRaPropertyBag.put("normalEnabled", "true"); + + PropertyBag co3WithRaPropertyBag = new PropertyBag(List.of("contingencyWithRemedialAction", "mRID", "remedialAction", "contingency", "combinationConstraintKind", "normalEnabled"), true, false); + co3WithRaPropertyBag.put("contingencyWithRemedialAction", "_co3xra"); + co3WithRaPropertyBag.put("mRID", "_co3xra"); + co3WithRaPropertyBag.put("remedialAction", "remedial-action"); + co3WithRaPropertyBag.put("contingency", "contingency-3"); + co3WithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.included"); + co3WithRaPropertyBag.put("normalEnabled", "true"); + + PropertyBag co4WithRaPropertyBag = new PropertyBag(List.of("contingencyWithRemedialAction", "mRID", "remedialAction", "contingency", "combinationConstraintKind", "normalEnabled"), true, false); + co4WithRaPropertyBag.put("contingencyWithRemedialAction", "_co4xra"); + co4WithRaPropertyBag.put("mRID", "_co4xra"); + co4WithRaPropertyBag.put("remedialAction", "remedial-action"); + co4WithRaPropertyBag.put("contingency", "contingency-4"); + co4WithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.considered"); + co4WithRaPropertyBag.put("normalEnabled", "true"); + + contingencyWithRemedialActions = Set.of(co1WithRaPropertyBag, co2WithRaPropertyBag, co3WithRaPropertyBag, co4WithRaPropertyBag); + } + + @Test + void getImportedCnecFromAssessedElementId() { + assertEquals( + Set.of(crac.getFlowCnec("Line 2 - preventive"), crac.getFlowCnec("Line 2 - curative - CO1"), crac.getFlowCnec("Line 2 - curative - CO2"), crac.getFlowCnec("Line 2 - curative - CO3"), crac.getFlowCnec("Line 2 - curative - CO4"), crac.getFlowCnec("Line 2 - curative - CO5"), crac.getFlowCnec("Line 2 - curative - CO6")), + OnConstraintUsageRuleHelper.getImportedCnecFromAssessedElementId("assessed-element-2", crac, cnecCreationContexts) + ); + } + + @Test + void getCnecsBuiltFromAssessedElementsCombinableWithRemedialActions() { + assertEquals( + Set.of(crac.getFlowCnec("Line 2 - preventive"), crac.getFlowCnec("Line 2 - curative - CO1"), crac.getFlowCnec("Line 2 - curative - CO2"), crac.getFlowCnec("Line 2 - curative - CO3"), crac.getFlowCnec("Line 2 - curative - CO4"), crac.getFlowCnec("Line 2 - curative - CO5"), crac.getFlowCnec("Line 2 - curative - CO6"), crac.getFlowCnec("Line 3 - preventive"), crac.getFlowCnec("Line 3 - curative - CO1"), crac.getFlowCnec("Line 3 - curative - CO2"), crac.getFlowCnec("Line 3 - curative - CO3"), crac.getFlowCnec("Line 3 - curative - CO4"), crac.getFlowCnec("Line 3 - curative - CO5"), crac.getFlowCnec("Line 3 - curative - CO6")), + OnConstraintUsageRuleHelper.getCnecsBuiltFromAssessedElementsCombinableWithRemedialActions(crac, cnecCreationContexts, assessedElementPropertyBags) + ); + } + + @Test + void filterCnecsThatHaveGivenContingencies() { + assertEquals( + Set.of(crac.getFlowCnec("Line 2 - curative - CO3"), crac.getFlowCnec("Line 3 - curative - CO3"), crac.getFlowCnec("Line 2 - curative - CO5"), crac.getFlowCnec("Line 3 - curative - CO5")), + OnConstraintUsageRuleHelper.filterCnecsThatHaveGivenContingencies(crac.getCnecs(), Set.of("contingency-3", "contingency-5")) + ); + } + + @Test + void processCnecsLinkedToRemedialActionWithContingencies() { + Map expectedResult = new HashMap<>(); + expectedResult.put("Line 1 - curative - CO1", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED, "")); + expectedResult.put("Line 2 - curative - CO1", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED, "")); + expectedResult.put("Line 2 - curative - CO2", new AssociationStatus(false, null, "OnConstraint usage rule for remedial action remedial-action with CNEC Line 2 - curative - CO2 ignored because the combinationConstraintKinds between of the AssessedElementWithRemedialAction for assessed element assessed-element-2 and the ContingencyWithRemedialAction for contingency contingency-2 are different.")); + expectedResult.put("Line 2 - curative - CO3", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED, "")); + expectedResult.put("Line 2 - curative - CO4", new AssociationStatus(false, null, "OnConstraint usage rule for remedial action remedial-action with CNEC Line 2 - curative - CO4 ignored because the combinationConstraintKinds between of the AssessedElementWithRemedialAction for assessed element assessed-element-2 and the ContingencyWithRemedialAction for contingency contingency-4 are different.")); + expectedResult.put("Line 3 - curative - CO1", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED, "")); + expectedResult.put("Line 3 - curative - CO2", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED, "")); + expectedResult.put("Line 3 - curative - CO3", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED, "")); + expectedResult.put("Line 3 - curative - CO4", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED, "")); + expectedResult.put("assessed-element-4", new AssociationStatus(false, null, "OnConstraint usage rule for remedial action remedial-action with assessed element assessed-element-4 ignored because the association is disabled.")); + expectedResult.put("assessed-element-5", new AssociationStatus(false, null, "OnConstraint usage rule for remedial action remedial-action with assessed element assessed-element-5 ignored because this assessed element has several conflictual links to the remedial action.")); + expectedResult.put("assessed-element-6", new AssociationStatus(false, null, "OnConstraint usage rule for remedial action remedial-action with assessed element assessed-element-6 ignored because of an illegal combinationConstraintKind.")); + expectedResult.put("assessed-element-7", new AssociationStatus(false, null, "OnConstraint usage rule for remedial action remedial-action with assessed element assessed-element-7 ignored because no CNEC was imported by Open RAO from this assessed element.")); + expectedResult.put("assessed-element-8", new AssociationStatus(false, null, "OnConstraint usage rule for remedial action remedial-action with assessed element assessed-element-8 ignored because this assessed element has several conflictual links to the remedial action.")); + + assertEquals(expectedResult, OnConstraintUsageRuleHelper.processCnecsLinkedToRemedialAction(crac, "remedial-action", assessedElementPropertyBags, assessedElementWithRemedialActions, contingencyWithRemedialActions, cnecCreationContexts)); + } + + @Test + void processCnecsLinkedToRemedialActionWithoutContingencies() { + Map expectedResult = new HashMap<>(); + expectedResult.put("Line 1 - curative - CO1", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED, "")); + expectedResult.put("Line 2 - preventive", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED, "")); + expectedResult.put("Line 2 - curative - CO1", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED, "")); + expectedResult.put("Line 2 - curative - CO2", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED, "")); + expectedResult.put("Line 2 - curative - CO3", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED, "")); + expectedResult.put("Line 2 - curative - CO4", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED, "")); + expectedResult.put("Line 2 - curative - CO5", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED, "")); + expectedResult.put("Line 2 - curative - CO6", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED, "")); + expectedResult.put("Line 3 - preventive", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED, "")); + expectedResult.put("Line 3 - curative - CO1", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED, "")); + expectedResult.put("Line 3 - curative - CO2", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED, "")); + expectedResult.put("Line 3 - curative - CO3", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED, "")); + expectedResult.put("Line 3 - curative - CO4", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED, "")); + expectedResult.put("Line 3 - curative - CO5", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED, "")); + expectedResult.put("Line 3 - curative - CO6", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED, "")); + expectedResult.put("assessed-element-4", new AssociationStatus(false, null, "OnConstraint usage rule for remedial action remedial-action with assessed element assessed-element-4 ignored because the association is disabled.")); + expectedResult.put("assessed-element-5", new AssociationStatus(false, null, "OnConstraint usage rule for remedial action remedial-action with assessed element assessed-element-5 ignored because this assessed element has several conflictual links to the remedial action.")); + expectedResult.put("assessed-element-6", new AssociationStatus(false, null, "OnConstraint usage rule for remedial action remedial-action with assessed element assessed-element-6 ignored because of an illegal combinationConstraintKind.")); + expectedResult.put("assessed-element-7", new AssociationStatus(false, null, "OnConstraint usage rule for remedial action remedial-action with assessed element assessed-element-7 ignored because no CNEC was imported by Open RAO from this assessed element.")); + expectedResult.put("assessed-element-8", new AssociationStatus(false, null, "OnConstraint usage rule for remedial action remedial-action with assessed element assessed-element-8 ignored because this assessed element has several conflictual links to the remedial action.")); + + assertEquals(expectedResult, OnConstraintUsageRuleHelper.processCnecsLinkedToRemedialAction(crac, "remedial-action", assessedElementPropertyBags, assessedElementWithRemedialActions, Set.of(), cnecCreationContexts)); + } +} diff --git a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/OnContingencyStateUsageRuleHelperTest.java b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/OnContingencyStateUsageRuleHelperTest.java new file mode 100644 index 0000000000..1342362629 --- /dev/null +++ b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/OnContingencyStateUsageRuleHelperTest.java @@ -0,0 +1,109 @@ +/* + * 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 com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.remedialaction; + +import com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileConstants; +import com.powsybl.openrao.data.cracimpl.CracImpl; +import com.powsybl.triplestore.api.PropertyBag; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @author Thomas Bouquet + */ +class OnContingencyStateUsageRuleHelperTest { + private final List properties = List.of("mRID", "remedialAction", "contingency", "combinationConstraintKind", "normalEnabled"); + + @Test + void processContingenciesLinkedToRemedialAction() { + CracImpl crac = new CracImpl("crac"); + crac.newContingency().withId("contingency-1").add(); + crac.newContingency().withId("contingency-2").add(); + crac.newContingency().withId("contingency-3").add(); + crac.newContingency().withId("contingency-4").add(); + crac.newContingency().withId("contingency-6").add(); + + PropertyBag co1WithRaPropertyBag = new PropertyBag(properties, true, false); + co1WithRaPropertyBag.put("mRID", "_co1xra"); + co1WithRaPropertyBag.put("remedialAction", "remedial-action"); + co1WithRaPropertyBag.put("contingency", "contingency-1"); + co1WithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.included"); + co1WithRaPropertyBag.put("normalEnabled", "true"); + co1WithRaPropertyBag.setClassPropertyNames(List.of("mRID", "normalEnabled")); + co1WithRaPropertyBag.setResourceNames(List.of("remedialAction", "contingency", "combinationConstraintKind")); + + PropertyBag co2WithRaPropertyBag = new PropertyBag(List.of("mRID", "remedialAction", "contingency", "combinationConstraintKind"), false); + co2WithRaPropertyBag.put("mRID", "_co2xra"); + co2WithRaPropertyBag.put("remedialAction", "remedial-action"); + co2WithRaPropertyBag.put("contingency", "contingency-2"); + co2WithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.considered"); + co2WithRaPropertyBag.setClassPropertyNames(List.of("mRID", "normalEnabled")); + co2WithRaPropertyBag.setResourceNames(List.of("remedialAction", "contingency", "combinationConstraintKind")); + + PropertyBag co3WithRaPropertyBag = new PropertyBag(properties, true, false); + co3WithRaPropertyBag.put("mRID", "_co3xra"); + co3WithRaPropertyBag.put("remedialAction", "remedial-action"); + co3WithRaPropertyBag.put("contingency", "contingency-3"); + co3WithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.included"); + co3WithRaPropertyBag.put("normalEnabled", "false"); + co3WithRaPropertyBag.setClassPropertyNames(List.of("mRID", "normalEnabled")); + co3WithRaPropertyBag.setResourceNames(List.of("remedialAction", "contingency", "combinationConstraintKind")); + + PropertyBag co4WithRaPropertyBag = new PropertyBag(properties, true, false); + co4WithRaPropertyBag.put("mRID", "_co4xra"); + co4WithRaPropertyBag.put("remedialAction", "remedial-action"); + co4WithRaPropertyBag.put("contingency", "contingency-4"); + co4WithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.excluded"); + co4WithRaPropertyBag.put("normalEnabled", "true"); + co4WithRaPropertyBag.setClassPropertyNames(List.of("mRID", "normalEnabled")); + co4WithRaPropertyBag.setResourceNames(List.of("remedialAction", "contingency", "combinationConstraintKind")); + + PropertyBag co5WithRaPropertyBag = new PropertyBag(properties, true, false); + co5WithRaPropertyBag.put("mRID", "_co5xra"); + co5WithRaPropertyBag.put("remedialAction", "remedial-action"); + co5WithRaPropertyBag.put("contingency", "contingency-5"); + co5WithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.included"); + co5WithRaPropertyBag.put("normalEnabled", "true"); + co5WithRaPropertyBag.setClassPropertyNames(List.of("mRID", "normalEnabled")); + co5WithRaPropertyBag.setResourceNames(List.of("remedialAction", "contingency", "combinationConstraintKind")); + + PropertyBag co6IncludedWithRaPropertyBag = new PropertyBag(properties, true, false); + co6IncludedWithRaPropertyBag.put("mRID", "_co6xra-included"); + co6IncludedWithRaPropertyBag.put("remedialAction", "remedial-action"); + co6IncludedWithRaPropertyBag.put("contingency", "contingency-6"); + co6IncludedWithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.included"); + co6IncludedWithRaPropertyBag.put("normalEnabled", "true"); + co6IncludedWithRaPropertyBag.setClassPropertyNames(List.of("mRID", "normalEnabled")); + co6IncludedWithRaPropertyBag.setResourceNames(List.of("remedialAction", "contingency", "combinationConstraintKind")); + + PropertyBag co6ConsideredWithRaPropertyBag = new PropertyBag(List.of("mRID", "remedialAction", "contingency", "combinationConstraintKind"), true, false); + co6ConsideredWithRaPropertyBag.put("mRID", "_co6xra-considered"); + co6ConsideredWithRaPropertyBag.put("remedialAction", "remedial-action"); + co6ConsideredWithRaPropertyBag.put("contingency", "contingency-6"); + co6ConsideredWithRaPropertyBag.put("combinationConstraintKind", "http://entsoe.eu/ns/nc#ElementCombinationConstraintKind.included"); + co6ConsideredWithRaPropertyBag.setClassPropertyNames(List.of("mRID", "normalEnabled")); + co6ConsideredWithRaPropertyBag.setResourceNames(List.of("remedialAction", "contingency", "combinationConstraintKind")); + + Map contingencyStatusMap = OnContingencyStateUsageRuleHelper.processContingenciesLinkedToRemedialAction(crac, "remedial-action", Set.of(co1WithRaPropertyBag, co2WithRaPropertyBag, co3WithRaPropertyBag, co4WithRaPropertyBag, co5WithRaPropertyBag, co6IncludedWithRaPropertyBag, co6ConsideredWithRaPropertyBag)); + assertEquals( + Map.of( + "contingency-1", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.INCLUDED, ""), + "contingency-2", new AssociationStatus(true, CsaProfileConstants.ElementCombinationConstraintKind.CONSIDERED, ""), + "contingency-3", new AssociationStatus(false, null, "OnContingencyState usage rule for remedial action remedial-action with contingency contingency-3 ignored because the association is disabled."), + "contingency-4", new AssociationStatus(false, null, "OnContingencyState usage rule for remedial action remedial-action with contingency contingency-4 ignored because of an illegal combinationConstraintKind."), + "contingency-5", new AssociationStatus(false, null, "OnContingencyState usage rule for remedial action remedial-action with contingency contingency-5 ignored because this contingency does not exist or was not imported by Open RAO."), + "contingency-6", new AssociationStatus(false, null, "OnContingencyState usage rule for remedial action remedial-action with contingency contingency-6 ignored because this contingency has several conflictual links to the remedial action.") + ), + contingencyStatusMap + ); + } +} diff --git a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/RemedialActionCreationTest.java b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/RemedialActionCreationTest.java index ce86fa5485..33d6a546d2 100644 --- a/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/RemedialActionCreationTest.java +++ b/data/crac-creation/crac-creator-csa-profiles/src/test/java/com/powsybl/openrao/data/craccreation/creator/csaprofile/craccreator/remedialaction/RemedialActionCreationTest.java @@ -12,15 +12,18 @@ import java.util.List; import java.util.Optional; +import static com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileCracCreationTestUtil.AUTO_INSTANT_ID; import static com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileCracCreationTestUtil.CURATIVE_INSTANT_ID; import static com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileCracCreationTestUtil.NETWORK; import static com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileCracCreationTestUtil.PREVENTIVE_INSTANT_ID; import static com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileCracCreationTestUtil.assertHasOnContingencyStateUsageRule; +import static com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileCracCreationTestUtil.assertHasOnFlowConstraintUsageRule; import static com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileCracCreationTestUtil.assertHasOnInstantUsageRule; import static com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileCracCreationTestUtil.assertPstRangeActionImported; import static com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileCracCreationTestUtil.assertRaNotImported; import static com.powsybl.openrao.data.craccreation.creator.csaprofile.craccreator.CsaProfileCracCreationTestUtil.getCsaCracCreationContext; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; class RemedialActionCreationTest { @@ -29,7 +32,7 @@ void importRemedialActions() { CsaProfileCracCreationContext cracCreationContext = getCsaCracCreationContext("/profiles/remedialactions/RemedialActions.zip", NETWORK); List> importedRemedialActions = cracCreationContext.getCrac().getRemedialActions().stream().sorted(Comparator.comparing(RemedialAction::getId)).toList(); - assertEquals(6, importedRemedialActions.size()); + assertEquals(7, importedRemedialActions.size()); assertPstRangeActionImported((PstRangeAction) importedRemedialActions.get(0), "remedial-action-1", "remedial-action-1", "BBE2AA1 BBE3AA1 1", null, null, null); assertHasOnInstantUsageRule(cracCreationContext, "remedial-action-1", PREVENTIVE_INSTANT_ID, UsageMethod.AVAILABLE); @@ -52,12 +55,83 @@ void importRemedialActions() { assertHasOnContingencyStateUsageRule(cracCreationContext, "remedial-action-6", "contingency-1", CURATIVE_INSTANT_ID, UsageMethod.AVAILABLE); assertHasOnContingencyStateUsageRule(cracCreationContext, "remedial-action-6", "contingency-2", CURATIVE_INSTANT_ID, UsageMethod.FORCED); - assertEquals(5, cracCreationContext.getRemedialActionCreationContexts().stream().filter(context -> !context.isImported()).toList().size()); + assertPstRangeActionImported((PstRangeAction) importedRemedialActions.get(6), "remedial-action-9", "RTE_RA9", "BBE2AA1 BBE3AA1 1", null, null, "RTE"); + assertEquals(0, importedRemedialActions.get(6).getUsageRules().size()); + + assertEquals(4, cracCreationContext.getRemedialActionCreationContexts().stream().filter(context -> !context.isImported()).toList().size()); assertRaNotImported(cracCreationContext, "remedial-action-7", ImportStatus.NOT_FOR_RAO, "Remedial action remedial-action-7 will not be imported because normalAvailable is set to false"); assertRaNotImported(cracCreationContext, "remedial-action-8", ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action remedial-action-8 will not be imported because it is linked to a contingency but is not curative"); - assertRaNotImported(cracCreationContext, "remedial-action-9", ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action remedial-action-9 will not be imported because the ElementCombinationConstraintKinds that link the remedial action to the contingency contingency-1 are different"); assertRaNotImported(cracCreationContext, "remedial-action-10", ImportStatus.INCONSISTENCY_IN_DATA, "Remedial action remedial-action-10 will not be imported because of an irregular timeToImplement pattern"); assertRaNotImported(cracCreationContext, "remedial-action-11", ImportStatus.NOT_FOR_RAO, "Remedial action remedial-action-11 will not be imported because it has no elementary action"); } + + @Test + void testUsageRulesCreation() { + CsaProfileCracCreationContext cracCreationContext = getCsaCracCreationContext("/profiles/remedialactions/UsageRules.zip", NETWORK); + + List> importedRemedialActions = cracCreationContext.getCrac().getRemedialActions().stream().sorted(Comparator.comparing(RemedialAction::getId)).toList(); + assertEquals(10, importedRemedialActions.size()); + + assertPstRangeActionImported((PstRangeAction) importedRemedialActions.get(0), "remedial-action-1", "RTE_RA1", "BBE2AA1 BBE3AA1 1", null, null, "RTE"); + assertEquals(8, importedRemedialActions.get(0).getUsageRules().size()); + assertHasOnInstantUsageRule(cracCreationContext, "remedial-action-1", PREVENTIVE_INSTANT_ID, UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE1 (assessed-element-1) - preventive", PREVENTIVE_INSTANT_ID, UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE1 (assessed-element-1) - RTE_CO1 - outage - TATL 60", PREVENTIVE_INSTANT_ID, UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE1 (assessed-element-1) - RTE_CO1 - auto - TATL 900", PREVENTIVE_INSTANT_ID, UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE1 (assessed-element-1) - RTE_CO1 - curative", PREVENTIVE_INSTANT_ID, UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE1 (assessed-element-1) - RTE_CO2 - outage - TATL 60", PREVENTIVE_INSTANT_ID, UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE1 (assessed-element-1) - RTE_CO2 - auto - TATL 900", PREVENTIVE_INSTANT_ID, UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-1", "RTE_AE1 (assessed-element-1) - RTE_CO2 - curative", PREVENTIVE_INSTANT_ID, UsageMethod.AVAILABLE); + + assertPstRangeActionImported((PstRangeAction) importedRemedialActions.get(2), "remedial-action-2", "RTE_RA2", "BBE2AA1 BBE3AA1 1", null, null, "RTE"); + assertEquals(3, importedRemedialActions.get(2).getUsageRules().size()); + assertHasOnInstantUsageRule(cracCreationContext, "remedial-action-2", CURATIVE_INSTANT_ID, UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-2", "RTE_AE1 (assessed-element-1) - RTE_CO1 - curative", CURATIVE_INSTANT_ID, UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-2", "RTE_AE1 (assessed-element-1) - RTE_CO2 - curative", CURATIVE_INSTANT_ID, UsageMethod.AVAILABLE); + + assertPstRangeActionImported((PstRangeAction) importedRemedialActions.get(3), "remedial-action-3", "RTE_RA3", "BBE2AA1 BBE3AA1 1", null, null, "RTE"); + assertEquals(4, importedRemedialActions.get(3).getUsageRules().size()); + assertHasOnContingencyStateUsageRule(cracCreationContext, "remedial-action-3", "contingency-1", AUTO_INSTANT_ID, UsageMethod.FORCED); + assertHasOnContingencyStateUsageRule(cracCreationContext, "remedial-action-3", "contingency-2", AUTO_INSTANT_ID, UsageMethod.FORCED); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-3", "RTE_AE1 (assessed-element-1) - RTE_CO1 - auto - TATL 900", AUTO_INSTANT_ID, UsageMethod.FORCED); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-3", "RTE_AE1 (assessed-element-1) - RTE_CO2 - auto - TATL 900", AUTO_INSTANT_ID, UsageMethod.FORCED); + + assertPstRangeActionImported((PstRangeAction) importedRemedialActions.get(4), "remedial-action-4", "RTE_RA4", "BBE2AA1 BBE3AA1 1", null, null, "RTE"); + assertEquals(4, importedRemedialActions.get(4).getUsageRules().size()); + assertHasOnContingencyStateUsageRule(cracCreationContext, "remedial-action-4", "contingency-1", CURATIVE_INSTANT_ID, UsageMethod.FORCED); + assertHasOnContingencyStateUsageRule(cracCreationContext, "remedial-action-4", "contingency-2", CURATIVE_INSTANT_ID, UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-4", "RTE_AE1 (assessed-element-1) - RTE_CO1 - curative", CURATIVE_INSTANT_ID, UsageMethod.FORCED); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-4", "RTE_AE1 (assessed-element-1) - RTE_CO2 - curative", CURATIVE_INSTANT_ID, UsageMethod.AVAILABLE); + + assertPstRangeActionImported((PstRangeAction) importedRemedialActions.get(5), "remedial-action-5", "RTE_RA5", "BBE2AA1 BBE3AA1 1", null, null, "RTE"); + assertEquals(2, importedRemedialActions.get(5).getUsageRules().size()); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-5", "RTE_AE1 (assessed-element-1) - RTE_CO2 - auto - TATL 900", AUTO_INSTANT_ID, UsageMethod.FORCED); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-5", "RTE_AE2 (assessed-element-2) - RTE_CO2 - auto - TATL 900", AUTO_INSTANT_ID, UsageMethod.FORCED); + + assertPstRangeActionImported((PstRangeAction) importedRemedialActions.get(6), "remedial-action-6", "RTE_RA6", "BBE2AA1 BBE3AA1 1", null, null, "RTE"); + assertEquals(2, importedRemedialActions.get(6).getUsageRules().size()); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-6", "RTE_AE1 (assessed-element-1) - RTE_CO2 - curative", CURATIVE_INSTANT_ID, UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-6", "RTE_AE2 (assessed-element-2) - RTE_CO2 - curative", CURATIVE_INSTANT_ID, UsageMethod.AVAILABLE); + + assertPstRangeActionImported((PstRangeAction) importedRemedialActions.get(7), "remedial-action-7", "RTE_RA7", "BBE2AA1 BBE3AA1 1", null, null, "RTE"); + assertEquals(3, importedRemedialActions.get(7).getUsageRules().size()); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-7", "RTE_AE1 (assessed-element-1) - RTE_CO1 - auto - TATL 900", AUTO_INSTANT_ID, UsageMethod.FORCED); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-7", "RTE_AE1 (assessed-element-1) - RTE_CO2 - auto - TATL 900", AUTO_INSTANT_ID, UsageMethod.FORCED); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-7", "RTE_AE2 (assessed-element-2) - RTE_CO2 - auto - TATL 900", AUTO_INSTANT_ID, UsageMethod.FORCED); + + assertPstRangeActionImported((PstRangeAction) importedRemedialActions.get(8), "remedial-action-8", "RTE_RA8", "BBE2AA1 BBE3AA1 1", null, null, "RTE"); + assertEquals(3, importedRemedialActions.get(8).getUsageRules().size()); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-8", "RTE_AE1 (assessed-element-1) - RTE_CO1 - curative", CURATIVE_INSTANT_ID, UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-8", "RTE_AE1 (assessed-element-1) - RTE_CO2 - curative", CURATIVE_INSTANT_ID, UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-8", "RTE_AE2 (assessed-element-2) - RTE_CO2 - curative", CURATIVE_INSTANT_ID, UsageMethod.AVAILABLE); + + assertPstRangeActionImported((PstRangeAction) importedRemedialActions.get(9), "remedial-action-9", "RTE_RA9", "BBE2AA1 BBE3AA1 1", null, null, "RTE"); + assertEquals(2, importedRemedialActions.get(9).getUsageRules().size()); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-9", "RTE_AE1 (assessed-element-1) - RTE_CO1 - curative", CURATIVE_INSTANT_ID, UsageMethod.AVAILABLE); + assertHasOnFlowConstraintUsageRule(cracCreationContext, "remedial-action-9", "RTE_AE1 (assessed-element-1) - RTE_CO2 - curative", CURATIVE_INSTANT_ID, UsageMethod.AVAILABLE); + + assertPstRangeActionImported((PstRangeAction) importedRemedialActions.get(1), "remedial-action-10", "RTE_RA10", "BBE2AA1 BBE3AA1 1", null, null, "RTE"); + assertTrue(importedRemedialActions.get(1).getUsageRules().isEmpty()); + } } diff --git a/data/crac-creation/crac-creator-csa-profiles/src/test/resources/profiles/remedialactions/AutoRemedialActions.zip b/data/crac-creation/crac-creator-csa-profiles/src/test/resources/profiles/remedialactions/AutoRemedialActions.zip index fac5d26d63..63db836c60 100644 Binary files a/data/crac-creation/crac-creator-csa-profiles/src/test/resources/profiles/remedialactions/AutoRemedialActions.zip and b/data/crac-creation/crac-creator-csa-profiles/src/test/resources/profiles/remedialactions/AutoRemedialActions.zip differ diff --git a/data/crac-creation/crac-creator-csa-profiles/src/test/resources/profiles/remedialactions/UsageRules.zip b/data/crac-creation/crac-creator-csa-profiles/src/test/resources/profiles/remedialactions/UsageRules.zip new file mode 100644 index 0000000000..e79f007fd2 Binary files /dev/null and b/data/crac-creation/crac-creator-csa-profiles/src/test/resources/profiles/remedialactions/UsageRules.zip differ