From a2cf4579b4230365ef27f95d8faf21ff394ebd13 Mon Sep 17 00:00:00 2001 From: Pauline Jean-Marie Date: Fri, 9 Aug 2024 15:16:05 +0200 Subject: [PATCH 1/2] POC update core and open-loadflow version to have feature 'rewrite operational limits for securty analysis' --- .github/workflows/maven.yml | 18 +++++++++++++++ .github/workflows/run_cucumber_tests.yml | 28 ++++++++++++++++++++++++ pom.xml | 4 ++-- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index f60f9c2413..748bc8ad60 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -19,6 +19,24 @@ jobs: with: java-version: 17 + - name: Checkout powsybl-core sources + uses: actions/checkout@v1 + with: + repository: powsybl/powsybl-core + ref: refs/heads/security_analysis_rewrite_operational_limits + + - name: Build and install powsybl-core with Maven + run: mvn --batch-mode -DskipTests=true --file ../powsybl-core/pom.xml install + + - name: Checkout powsybl-open-loadflow sources + uses: actions/checkout@v1 + with: + repository: powsybl/powsybl-open-loadflow + ref: refs/heads/security_analysis_rewrite_operational_limits + + - name: Build and install powsybl-open-loadflow with Maven + run: mvn --batch-mode -DskipTests=true --file ../powsybl-open-loadflow/pom.xml install + - name: Build with Maven if: matrix.os == 'ubuntu-latest' run: mvn --batch-mode -Pjacoco install -DskipCucumberTests=true diff --git a/.github/workflows/run_cucumber_tests.yml b/.github/workflows/run_cucumber_tests.yml index f6ef4a85a6..9498d59923 100644 --- a/.github/workflows/run_cucumber_tests.yml +++ b/.github/workflows/run_cucumber_tests.yml @@ -13,6 +13,20 @@ jobs: uses: actions/setup-java@v1 with: java-version: 17 + - name: Checkout powsybl-core sources + uses: actions/checkout@v1 + with: + repository: powsybl/powsybl-core + ref: refs/heads/security_analysis_rewrite_operational_limits + - name: Build and install powsybl-core with Maven + run: mvn --batch-mode -DskipTests=true --file ../powsybl-core/pom.xml install + - name: Checkout powsybl-open-loadflow sources + uses: actions/checkout@v1 + with: + repository: powsybl/powsybl-open-loadflow + ref: refs/heads/security_analysis_rewrite_operational_limits + - name: Build and install powsybl-open-loadflow with Maven + run: mvn --batch-mode -DskipTests=true --file ../powsybl-open-loadflow/pom.xml install - name: Install OpenRAO with Maven run: mvn --batch-mode install -DskipTests=true - name: Run cucumber tests with Maven @@ -28,6 +42,20 @@ jobs: uses: actions/setup-java@v1 with: java-version: 17 + - name: Checkout powsybl-core sources + uses: actions/checkout@v1 + with: + repository: powsybl/powsybl-core + ref: refs/heads/security_analysis_rewrite_operational_limits + - name: Build and install powsybl-core with Maven + run: mvn --batch-mode -DskipTests=true --file ../powsybl-core/pom.xml install + - name: Checkout powsybl-open-loadflow sources + uses: actions/checkout@v1 + with: + repository: powsybl/powsybl-open-loadflow + ref: refs/heads/security_analysis_rewrite_operational_limits + - name: Build and install powsybl-open-loadflow with Maven + run: mvn --batch-mode -DskipTests=true --file ../powsybl-open-loadflow/pom.xml install - name: Install OpenRAO with Maven run: mvn --batch-mode install -DskipTests=true - name: Run cucumber tests with Maven diff --git a/pom.xml b/pom.xml index 2778222c78..9d4c122771 100644 --- a/pom.xml +++ b/pom.xml @@ -116,9 +116,9 @@ 3.2.1 1.0.0 5.2.0 - 6.4.1 + 6.5.0-SNAPSHOT 2.10.1 - 1.12.2 + 1.13.0-SNAPSHOT 1.7.36 2.8.1 From 9f023c2665eeeae3e4feeced180d7e410b7ecd51 Mon Sep 17 00:00:00 2001 From: Pauline Jean-Marie Date: Mon, 17 Jun 2024 11:45:32 +0200 Subject: [PATCH 2/2] POC launch open load flow security analysis with rao results using limits override --- data/rao-result/rao-result-impl/pom.xml | 11 ++ .../RaoResultForSecurityAnalysisTest.java | 130 ++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 data/rao-result/rao-result-impl/src/test/java/com/powsybl/openrao/data/raoresultimpl/RaoResultForSecurityAnalysisTest.java diff --git a/data/rao-result/rao-result-impl/pom.xml b/data/rao-result/rao-result-impl/pom.xml index 50216e5d94..a259dc6ad7 100644 --- a/data/rao-result/rao-result-impl/pom.xml +++ b/data/rao-result/rao-result-impl/pom.xml @@ -90,6 +90,17 @@ 5.5.0 test + + com.powsybl + powsybl-security-analysis-api + ${powsybl.core.version} + test + + + com.powsybl + powsybl-open-loadflow + test + \ No newline at end of file diff --git a/data/rao-result/rao-result-impl/src/test/java/com/powsybl/openrao/data/raoresultimpl/RaoResultForSecurityAnalysisTest.java b/data/rao-result/rao-result-impl/src/test/java/com/powsybl/openrao/data/raoresultimpl/RaoResultForSecurityAnalysisTest.java new file mode 100644 index 0000000000..438bdb6160 --- /dev/null +++ b/data/rao-result/rao-result-impl/src/test/java/com/powsybl/openrao/data/raoresultimpl/RaoResultForSecurityAnalysisTest.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2021, 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.raoresultimpl; + +import com.powsybl.action.Action; +import com.powsybl.contingency.ContingenciesProvider; +import com.powsybl.contingency.Contingency; +import com.powsybl.contingency.ContingencyContext; +import com.powsybl.iidm.network.*; +import com.powsybl.math.matrix.DenseMatrixFactory; +import com.powsybl.openloadflow.graph.EvenShiloachGraphDecrementalConnectivityFactory; +import com.powsybl.openloadflow.sa.OpenSecurityAnalysisProvider; +import com.powsybl.openrao.commons.Unit; +import com.powsybl.openrao.data.cracapi.Crac; +import com.powsybl.openrao.data.cracapi.State; +import com.powsybl.openrao.data.cracapi.cnec.FlowCnec; +import com.powsybl.openrao.data.cracapi.networkaction.ActionType; +import com.powsybl.openrao.data.cracapi.threshold.BranchThreshold; +import com.powsybl.openrao.data.cracapi.usagerule.UsageMethod; +import com.powsybl.openrao.data.cracimpl.utils.CommonCracCreation; +import com.powsybl.openrao.data.cracimpl.utils.NetworkImportsUtil; +import com.powsybl.security.*; +import com.powsybl.security.condition.TrueCondition; +import com.powsybl.security.strategy.ConditionalActions; +import com.powsybl.security.strategy.OperatorStrategy; +import com.powsybl.security.strategy.OperationalLimitOverride; +import org.junit.jupiter.api.Test; + +import java.util.*; + +/** + * @author Peter Mitri {@literal } + */ +class RaoResultForSecurityAnalysisTest { + private static final double DOUBLE_TOLERANCE = 1e-6; + private static final String PREVENTIVE_INSTANT_ID = "preventive"; + private static final String AUTO_INSTANT_ID = "auto"; + private static final String CURATIVE_INSTANT_ID = "curative"; + + private RaoResultImpl raoResult; + private Crac crac; + private Network network; + + private void initializeCracAndItsRaoResult() { + network = NetworkImportsUtil.import12NodesNetwork(); + crac = CommonCracCreation.createWithPreventiveAndCurativePstRange(); + crac.newNetworkAction().withId("na-id") + .newSwitchAction().withNetworkElement("any").withActionType(ActionType.OPEN).add() + .newOnInstantUsageRule().withInstant(PREVENTIVE_INSTANT_ID).withUsageMethod(UsageMethod.AVAILABLE).add() + .newOnContingencyStateUsageRule().withContingency("Contingency FR1 FR3").withInstant(AUTO_INSTANT_ID).withUsageMethod(UsageMethod.FORCED).add() + .newOnContingencyStateUsageRule().withContingency("Contingency FR1 FR2").withInstant(AUTO_INSTANT_ID).withUsageMethod(UsageMethod.UNAVAILABLE).add() + .newOnInstantUsageRule().withInstant(CURATIVE_INSTANT_ID).withUsageMethod(UsageMethod.AVAILABLE).add() + .add(); + + raoResult = new RaoResultImpl(crac); + } + + @Test + void testCreateSecurityAnalysisFromRaoResult() { + initializeCracAndItsRaoResult(); + //TODO: only network actions here, range actions to add + // PREVENTIVE: + List preventiveActions = raoResult.getActivatedNetworkActionsDuringState(crac.getPreventiveState()).stream().flatMap(networkAction -> networkAction.getElementaryActions().stream()).toList(); + // operator strategy with ContingencyContext.none() will not be taken into account in actual load flow but limitsToOverride with ContingencyContext.none() will be + //OperatorStrategy preventiveOp = new OperatorStrategy(crac.getPreventiveState().getId(), ContingencyContext.none(), new TrueCondition(), preventiveActionIds); + List limitsToOverride = new ArrayList<>(getNetworkLimits(crac.getPreventiveState(), ContingencyContext.none(), null)); + //POST CONTINGENCIES: + // do the rao have scenarios with multiple contingencies? + List strategies = new ArrayList<>(); + List actions = new ArrayList<>(); + for (Contingency contingency : crac.getContingencies()) { + ContingencyContext contingencyContext = ContingencyContext.specificContingency(contingency.getId()); + List conditionalActionsList = new ArrayList<>(); + SortedSet stateChronologicallyOrderedByInstant = crac.getStates(contingency); + for (State state : stateChronologicallyOrderedByInstant) { + List instantActions = raoResult.getActivatedNetworkActionsDuringState(state).stream().flatMap(networkAction -> networkAction.getElementaryActions().stream()).toList(); + ConditionalActions conditionalActions = new ConditionalActions(state.getId(), new TrueCondition(), instantActions.stream().map(Action::getId).toList()); + conditionalActionsList.add(conditionalActions); + actions.addAll(instantActions); + limitsToOverride.addAll(getNetworkLimits(state, contingencyContext, conditionalActions.getId())); + } + strategies.add(new OperatorStrategy(contingency.getId(), contingencyContext, conditionalActionsList)); + } + // TODO: we cannot add actions on preventive state on actua open load flow, + // so we should play preventive actions on the newtork before the security analysis + runSecurityAnalysis(strategies, actions, limitsToOverride); + } + + private void runSecurityAnalysis(List strategies, List actions, List limitsToOverride) { + SecurityAnalysisRunParameters runParameters = new SecurityAnalysisRunParameters() + //.setFilter(new LimitViolationFilter()) + //.setComputationManager(computationManager) + //.setSecurityAnalysisParameters(saParameters) + //.setMonitors(monitors) + //.setLimitReductions(limitReductions) + .setOperatorStrategies(strategies) + .setActions(actions) + .setLimitsToOverride(limitsToOverride); + OpenSecurityAnalysisProvider securityAnalysisProvider = new OpenSecurityAnalysisProvider(new DenseMatrixFactory(), new EvenShiloachGraphDecrementalConnectivityFactory<>()); + ContingenciesProvider provider = n -> crac.getContingencies().stream().toList(); + SecurityAnalysisReport report = securityAnalysisProvider.run(network, + network.getVariantManager().getWorkingVariantId(), + provider, + runParameters) + .join(); + SecurityAnalysisResult result = report.getResult(); + System.out.println(result); + } + + private List getNetworkLimits(State state, ContingencyContext contingencyContext, String conditionalActionsId) { + List limitsToOverride = new ArrayList<>(); + for (FlowCnec flowCnec : crac.getFlowCnecs(state)) { + for (BranchThreshold threshold : flowCnec.getThresholds()) { + if (threshold.limitsByMax()) { + if (threshold.getUnit() == Unit.AMPERE) { + limitsToOverride.add(new OperationalLimitOverride(flowCnec.getNetworkElement().getId(), threshold.getSide().toThreeSides(), LimitType.CURRENT, threshold.max().get(), contingencyContext, conditionalActionsId)); + } + // TODO: MEGAWATT PERCENT_IMAX + } + } + } + // TODO AngleCnec angleCnec : crac.getAngleCnecs(state) Threshold threshold: angleCnec.getThresholds() + // TODO VoltageCnec voltageCnec : crac.getVoltageCnecs(state) Threshold threshold: voltageCnec.getThresholds() + return limitsToOverride; + } +}