From 63c0019087be2b7902293d9130bbd2c37502d253 Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Tue, 14 Jan 2025 15:54:07 +0100 Subject: [PATCH 01/16] Area interchange target action support. Signed-off-by: Bertrand Rix --- .../openloadflow/network/LfAction.java | 46 +++++++++++++++---- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index f6f55330b6..4a27673a46 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -39,6 +39,9 @@ private record GeneratorChange(LfGenerator generator, double activePowerValue, b private record SectionChange(LfShunt shunt, String controllerId, int value) { } + private record AreaInterchangeTargetChange(LfArea area, double interchangeTarget) { + } + private final String id; private final LfBranch disabledBranch; // switch to open @@ -55,8 +58,11 @@ private record SectionChange(LfShunt shunt, String controllerId, int value) { private final SectionChange sectionChange; + private final AreaInterchangeTargetChange areaInterchangeTargetChange; + private LfAction(String id, LfBranch disabledBranch, LfBranch enabledBranch, TapPositionChange tapPositionChange, - LoadShift loadShift, GeneratorChange generatorChange, LfHvdc hvdc, SectionChange sectionChange) { + LoadShift loadShift, GeneratorChange generatorChange, LfHvdc hvdc, SectionChange sectionChange, + AreaInterchangeTargetChange areaInterchangeTargetChange) { this.id = Objects.requireNonNull(id); this.disabledBranch = disabledBranch; this.enabledBranch = enabledBranch; @@ -65,6 +71,7 @@ private LfAction(String id, LfBranch disabledBranch, LfBranch enabledBranch, Tap this.generatorChange = generatorChange; this.hvdc = hvdc; this.sectionChange = sectionChange; + this.areaInterchangeTargetChange = areaInterchangeTargetChange; } public static Optional create(Action action, LfNetwork lfNetwork, Network network, boolean breakers) { @@ -95,6 +102,9 @@ public static Optional create(Action action, LfNetwork lfNetwork, Netw case ShuntCompensatorPositionAction.NAME: return create((ShuntCompensatorPositionAction) action, lfNetwork); + case AreaInterchangeTargetAction.NAME: + return create((AreaInterchangeTargetAction) action, lfNetwork); + default: throw new UnsupportedOperationException("Unsupported action type: " + action.getType()); } @@ -107,7 +117,7 @@ private static Optional create(ShuntCompensatorPositionAction action, LOGGER.warn("Shunt compensator position action: voltage control is present on the shunt, section could be overridden."); } var sectionChange = new SectionChange(shunt, action.getShuntCompensatorId(), action.getSectionCount()); - return Optional.of(new LfAction(action.getId(), null, null, null, null, null, null, sectionChange)); + return Optional.of(new LfAction(action.getId(), null, null, null, null, null, null, sectionChange, null)); } return Optional.empty(); // could be in another component } @@ -121,7 +131,7 @@ private static Optional create(HvdcAction action, LfNetwork lfNetwork) if (acEmulationEnabled.get().equals(Boolean.TRUE)) { // the operation mode remains AC emulation. throw new UnsupportedOperationException("Hvdc action: line is already in AC emulation, not supported yet."); } else { // the operation mode changes from AC emulation to fixed active power set point. - return Optional.of(new LfAction(action.getId(), null, null, null, null, null, lfHvdc, null)); + return Optional.of(new LfAction(action.getId(), null, null, null, null, null, lfHvdc, null, null)); } } LOGGER.warn("Hvdc action {}: not supported", action.getId()); @@ -136,7 +146,7 @@ private static Optional create(LoadAction action, LfNetwork lfNetwork, LfLoad lfLoad = lfNetwork.getLoadById(load.getId()); if (lfLoad != null) { PowerShift powerShift = PowerShift.createPowerShift(load, action); - return Optional.of(new LfAction(action.getId(), null, null, null, new LoadShift(load.getId(), lfLoad, powerShift), null, null, null)); + return Optional.of(new LfAction(action.getId(), null, null, null, new LoadShift(load.getId(), lfLoad, powerShift), null, null, null, null)); } } return Optional.empty(); // could be in another component or in contingency. @@ -166,7 +176,7 @@ private static Optional create(LfBranch branch, String actionId, boole throw new UnsupportedOperationException("Tap position action: only one tap in branch " + branch.getId()); } else { var tapPositionChange = new TapPositionChange(branch, tapPosition, isRelative); - return Optional.of(new LfAction(actionId, null, null, tapPositionChange, null, null, null, null)); + return Optional.of(new LfAction(actionId, null, null, tapPositionChange, null, null, null, null, null)); } } return Optional.empty(); // could be in another component @@ -177,9 +187,9 @@ private static Optional create(TerminalsConnectionAction action, LfNet if (branch != null && branch.getBus1() != null && branch.getBus2() != null) { if (action.getSide().isEmpty()) { if (action.isOpen()) { - return Optional.of(new LfAction(action.getId(), branch, null, null, null, null, null, null)); + return Optional.of(new LfAction(action.getId(), branch, null, null, null, null, null, null, null)); } else { - return Optional.of(new LfAction(action.getId(), null, branch, null, null, null, null, null)); + return Optional.of(new LfAction(action.getId(), null, branch, null, null, null, null, null, null)); } } else { throw new UnsupportedOperationException("Terminals connection action: only open or close branch at both sides is supported yet."); @@ -198,7 +208,7 @@ private static Optional create(SwitchAction action, LfNetwork lfNetwor } else { enabledBranch = branch; } - return Optional.of(new LfAction(action.getId(), disabledBranch, enabledBranch, null, null, null, null, null)); + return Optional.of(new LfAction(action.getId(), disabledBranch, enabledBranch, null, null, null, null, null, null)); } return Optional.empty(); // could be in another component } @@ -210,7 +220,7 @@ private static Optional create(GeneratorAction action, LfNetwork lfNet Optional relativeValue = action.isActivePowerRelativeValue(); if (relativeValue.isPresent() && activePowerValue.isPresent()) { var generatorChange = new GeneratorChange(generator, activePowerValue.getAsDouble() / PerUnit.SB, relativeValue.get()); - return Optional.of(new LfAction(action.getId(), null, null, null, null, generatorChange, null, null)); + return Optional.of(new LfAction(action.getId(), null, null, null, null, generatorChange, null, null, null)); } else { throw new UnsupportedOperationException("Generator action on " + action.getGeneratorId() + " : configuration not supported yet."); } @@ -218,6 +228,15 @@ private static Optional create(GeneratorAction action, LfNetwork lfNet return Optional.empty(); } + private static Optional create(AreaInterchangeTargetAction action, LfNetwork lfNetwork) { + LfArea area = lfNetwork.getAreaById(action.getId()); + if (area != null) { + AreaInterchangeTargetChange change = new AreaInterchangeTargetChange(area, action.getInterchangeTarget()); + return Optional.of(new LfAction(action.getId(), null, null, null, null, null, null, null, change)); + } + return Optional.empty(); + } + public String getId() { return id; } @@ -339,6 +358,11 @@ private void applySectionChange() { () -> LOGGER.warn("No section change: shunt {} not present", sectionChange.controllerId)); } + private void applyAreaInterchangeTargetChange() { + LfArea area = areaInterchangeTargetChange.area(); + area.setInterchangeTarget(areaInterchangeTargetChange.interchangeTarget); + } + public void apply(LfNetworkParameters networkParameters) { if (tapPositionChange != null) { applyTapPositionChange(); @@ -359,5 +383,9 @@ public void apply(LfNetworkParameters networkParameters) { if (sectionChange != null) { applySectionChange(); } + + if (areaInterchangeTargetChange != null) { + applyAreaInterchangeTargetChange(); + } } } From eff560e48ae243cd14c254f0966f617e6ed6c605 Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Thu, 16 Jan 2025 16:25:12 +0100 Subject: [PATCH 02/16] Full refacto of LfAction. Signed-off-by: Bertrand Rix --- .../powsybl/openloadflow/NetworkCache.java | 3 +- .../outerloop/AutomationSystemOuterLoop.java | 3 +- .../dc/fastdc/WoodburyEngine.java | 7 +- .../openloadflow/network/LfAction.java | 391 ------------------ .../network/action/AbstractLfAction.java | 23 ++ .../action/AbstractLfBranchAction.java | 97 +++++ .../action/AbstractLfTapChangerAction.java | 28 ++ .../network/action/LfActionUtils.java | 75 ++++ .../action/LfAreaInterchangeTargetAction.java | 22 + .../network/action/LfGeneratorAction.java | 38 ++ .../network/action/LfHvdcAction.java | 40 ++ .../network/action/LfLoadAction.java | 43 ++ .../action/LfPhaseTapChangerAction.java | 32 ++ .../action/LfRatioTapChangerAction.java | 32 ++ .../LfShuntCompensatorPositionAction.java | 32 ++ .../network/action/LfSwitchAction.java | 32 ++ .../action/LfTerminalsConnectionAction.java | 36 ++ .../sa/AbstractSecurityAnalysis.java | 19 +- .../sa/WoodburyDcSecurityAnalysis.java | 36 +- .../powsybl/openloadflow/sa/LfActionTest.java | 56 ++- 20 files changed, 610 insertions(+), 435 deletions(-) delete mode 100644 src/main/java/com/powsybl/openloadflow/network/LfAction.java create mode 100644 src/main/java/com/powsybl/openloadflow/network/action/AbstractLfAction.java create mode 100644 src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java create mode 100644 src/main/java/com/powsybl/openloadflow/network/action/AbstractLfTapChangerAction.java create mode 100644 src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java create mode 100644 src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java create mode 100644 src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java create mode 100644 src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java create mode 100644 src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java create mode 100644 src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java create mode 100644 src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java create mode 100644 src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java create mode 100644 src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java create mode 100644 src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java diff --git a/src/main/java/com/powsybl/openloadflow/NetworkCache.java b/src/main/java/com/powsybl/openloadflow/NetworkCache.java index b2de5fcb6e..d6f7198b0c 100644 --- a/src/main/java/com/powsybl/openloadflow/NetworkCache.java +++ b/src/main/java/com/powsybl/openloadflow/NetworkCache.java @@ -18,6 +18,7 @@ import com.powsybl.openloadflow.ac.AcLoadFlowResult; import com.powsybl.openloadflow.ac.solver.AcSolverStatus; import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.network.action.AbstractLfBranchAction; import com.powsybl.openloadflow.network.impl.AbstractLfGenerator; import com.powsybl.openloadflow.network.impl.LfLegBranch; import com.powsybl.openloadflow.network.util.PreviousValueVoltageInitializer; @@ -239,7 +240,7 @@ private static void updateSwitch(boolean open, LfNetwork lfNetwork, LfBranch lfB } else { connectivity.addEdge(lfBranch.getBus1(), lfBranch.getBus2(), lfBranch); } - LfAction.updateBusesAndBranchStatus(connectivity); + AbstractLfBranchAction.updateBusesAndBranchStatus(connectivity); } finally { connectivity.undoTemporaryChanges(); } diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AutomationSystemOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AutomationSystemOuterLoop.java index 39e94dd0aa..49a0b23b2f 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AutomationSystemOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AutomationSystemOuterLoop.java @@ -14,6 +14,7 @@ import com.powsybl.openloadflow.lf.outerloop.OuterLoopResult; import com.powsybl.openloadflow.lf.outerloop.OuterLoopStatus; import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.network.action.AbstractLfBranchAction; import com.powsybl.openloadflow.util.PerUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -81,7 +82,7 @@ public OuterLoopResult check(AcOuterLoopContext context, ReportNode reportNode) GraphConnectivity connectivity = network.getConnectivity(); branchesToOpen.forEach(connectivity::removeEdge); branchesToClose.forEach(branch -> connectivity.addEdge(branch.getBus1(), branch.getBus2(), branch)); - LfAction.updateBusesAndBranchStatus(connectivity); + AbstractLfBranchAction.updateBusesAndBranchStatus(connectivity); network.getConnectivity().undoTemporaryChanges(); // we have now to really change the network connectivity. branchesToOpen.forEach(connectivity::removeEdge); diff --git a/src/main/java/com/powsybl/openloadflow/dc/fastdc/WoodburyEngine.java b/src/main/java/com/powsybl/openloadflow/dc/fastdc/WoodburyEngine.java index bc090d1e21..35295c75b7 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/fastdc/WoodburyEngine.java +++ b/src/main/java/com/powsybl/openloadflow/dc/fastdc/WoodburyEngine.java @@ -19,6 +19,8 @@ import com.powsybl.openloadflow.dc.equations.DcEquationType; import com.powsybl.openloadflow.equations.Equation; import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.network.action.AbstractLfAction; +import com.powsybl.openloadflow.network.action.AbstractLfTapChangerAction; import java.util.*; @@ -72,7 +74,7 @@ public static double[] runDcLoadFlowWithModifiedTargetVector(DcLoadFlowContext l * A simplified version of DcLoadFlowEngine that supports on the fly bus and branch disabling, and pst actions. * Note that it does not update the state vector and the network at the end (because we don't need it to just evaluate a few equations). */ - public static double[] runDcLoadFlowWithModifiedTargetVector(DcLoadFlowContext loadFlowContext, DisabledNetwork disabledNetwork, ReportNode reportNode, List pstActions) { + public static double[] runDcLoadFlowWithModifiedTargetVector(DcLoadFlowContext loadFlowContext, DisabledNetwork disabledNetwork, ReportNode reportNode, List> pstActions) { Collection remainingBuses; if (disabledNetwork.getBuses().isEmpty()) { remainingBuses = loadFlowContext.getNetwork().getBuses(); @@ -112,7 +114,8 @@ public static double[] runDcLoadFlowWithModifiedTargetVector(DcLoadFlowContext l if (!pstActions.isEmpty()) { // set transformer phase shift to new shifting value pstActions.stream() - .map(LfAction::getTapPositionChange) + .filter(AbstractLfTapChangerAction.class::isInstance) + .map(action -> ((AbstractLfTapChangerAction) action).getChange()) .filter(Objects::nonNull) .forEach(tapPositionChange -> { LfBranch lfBranch = tapPositionChange.getBranch(); diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java deleted file mode 100644 index 4a27673a46..0000000000 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ /dev/null @@ -1,391 +0,0 @@ -/** - * Copyright (c) 2022, 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/. - * SPDX-License-Identifier: MPL-2.0 - */ -package com.powsybl.openloadflow.network; - -import com.powsybl.action.*; -import com.powsybl.iidm.network.Bus; -import com.powsybl.iidm.network.Load; -import com.powsybl.iidm.network.Network; -import com.powsybl.iidm.network.Terminal; -import com.powsybl.openloadflow.graph.GraphConnectivity; -import com.powsybl.openloadflow.network.impl.LfLegBranch; -import com.powsybl.openloadflow.network.impl.LfShuntImpl; -import com.powsybl.openloadflow.network.impl.Networks; -import com.powsybl.openloadflow.util.PerUnit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.*; - -/** - * @author Anne Tilloy {@literal } - * @author Jean-Luc Bouchot (Artelys) {@literal } - */ -public final class LfAction { - - private static final Logger LOGGER = LoggerFactory.getLogger(LfAction.class); - - private record LoadShift(String loadId, LfLoad lfLoad, PowerShift powerShift) { - } - - private record GeneratorChange(LfGenerator generator, double activePowerValue, boolean isRelative) { - } - - private record SectionChange(LfShunt shunt, String controllerId, int value) { - } - - private record AreaInterchangeTargetChange(LfArea area, double interchangeTarget) { - } - - private final String id; - - private final LfBranch disabledBranch; // switch to open - - private final LfBranch enabledBranch; // switch to close - - private final TapPositionChange tapPositionChange; - - private final LoadShift loadShift; - - private final GeneratorChange generatorChange; - - private final LfHvdc hvdc; - - private final SectionChange sectionChange; - - private final AreaInterchangeTargetChange areaInterchangeTargetChange; - - private LfAction(String id, LfBranch disabledBranch, LfBranch enabledBranch, TapPositionChange tapPositionChange, - LoadShift loadShift, GeneratorChange generatorChange, LfHvdc hvdc, SectionChange sectionChange, - AreaInterchangeTargetChange areaInterchangeTargetChange) { - this.id = Objects.requireNonNull(id); - this.disabledBranch = disabledBranch; - this.enabledBranch = enabledBranch; - this.tapPositionChange = tapPositionChange; - this.loadShift = loadShift; - this.generatorChange = generatorChange; - this.hvdc = hvdc; - this.sectionChange = sectionChange; - this.areaInterchangeTargetChange = areaInterchangeTargetChange; - } - - public static Optional create(Action action, LfNetwork lfNetwork, Network network, boolean breakers) { - Objects.requireNonNull(action); - Objects.requireNonNull(network); - switch (action.getType()) { - case SwitchAction.NAME: - return create((SwitchAction) action, lfNetwork); - - case TerminalsConnectionAction.NAME: - return create((TerminalsConnectionAction) action, lfNetwork); - - case PhaseTapChangerTapPositionAction.NAME: - return create((PhaseTapChangerTapPositionAction) action, lfNetwork); - - case RatioTapChangerTapPositionAction.NAME: - return create((RatioTapChangerTapPositionAction) action, lfNetwork); - - case LoadAction.NAME: - return create((LoadAction) action, lfNetwork, network, breakers); - - case GeneratorAction.NAME: - return create((GeneratorAction) action, lfNetwork); - - case HvdcAction.NAME: - return create((HvdcAction) action, lfNetwork); - - case ShuntCompensatorPositionAction.NAME: - return create((ShuntCompensatorPositionAction) action, lfNetwork); - - case AreaInterchangeTargetAction.NAME: - return create((AreaInterchangeTargetAction) action, lfNetwork); - - default: - throw new UnsupportedOperationException("Unsupported action type: " + action.getType()); - } - } - - private static Optional create(ShuntCompensatorPositionAction action, LfNetwork lfNetwork) { - LfShunt shunt = lfNetwork.getShuntById(action.getShuntCompensatorId()); - if (shunt instanceof LfShuntImpl) { // no svc here - if (shunt.getVoltageControl().isPresent()) { - LOGGER.warn("Shunt compensator position action: voltage control is present on the shunt, section could be overridden."); - } - var sectionChange = new SectionChange(shunt, action.getShuntCompensatorId(), action.getSectionCount()); - return Optional.of(new LfAction(action.getId(), null, null, null, null, null, null, sectionChange, null)); - } - return Optional.empty(); // could be in another component - } - - private static Optional create(HvdcAction action, LfNetwork lfNetwork) { - // as a first approach, we only support an action that switches an hvdc operated in AC emulation into an active power - // set point operation mode. - LfHvdc lfHvdc = lfNetwork.getHvdcById(action.getHvdcId()); - Optional acEmulationEnabled = action.isAcEmulationEnabled(); - if (lfHvdc != null && acEmulationEnabled.isPresent()) { - if (acEmulationEnabled.get().equals(Boolean.TRUE)) { // the operation mode remains AC emulation. - throw new UnsupportedOperationException("Hvdc action: line is already in AC emulation, not supported yet."); - } else { // the operation mode changes from AC emulation to fixed active power set point. - return Optional.of(new LfAction(action.getId(), null, null, null, null, null, lfHvdc, null, null)); - } - } - LOGGER.warn("Hvdc action {}: not supported", action.getId()); - return Optional.empty(); // could be in another component or not operated in AC emulation - } - - private static Optional create(LoadAction action, LfNetwork lfNetwork, Network network, boolean breakers) { - Load load = network.getLoad(action.getLoadId()); - Terminal terminal = load.getTerminal(); - Bus bus = Networks.getBus(terminal, breakers); - if (bus != null) { - LfLoad lfLoad = lfNetwork.getLoadById(load.getId()); - if (lfLoad != null) { - PowerShift powerShift = PowerShift.createPowerShift(load, action); - return Optional.of(new LfAction(action.getId(), null, null, null, new LoadShift(load.getId(), lfLoad, powerShift), null, null, null, null)); - } - } - return Optional.empty(); // could be in another component or in contingency. - } - - private static Optional create(PhaseTapChangerTapPositionAction action, LfNetwork lfNetwork) { - String branchId = action.getSide().map(side -> LfLegBranch.getId(side, action.getTransformerId())).orElseGet(action::getTransformerId); - LfBranch branch = lfNetwork.getBranchById(branchId); - if (branch != null && branch.getPhaseControl().isPresent()) { - LOGGER.warn("Phase tap changer tap position action: phase control is present on the tap changer, tap position could be overriden."); - } - return create(branch, action.getId(), action.isRelativeValue(), action.getTapPosition(), lfNetwork); - } - - private static Optional create(RatioTapChangerTapPositionAction action, LfNetwork lfNetwork) { - String branchId = action.getSide().map(side -> LfLegBranch.getId(side, action.getTransformerId())).orElseGet(action::getTransformerId); - LfBranch branch = lfNetwork.getBranchById(branchId); - if (branch != null && branch.getVoltageControl().isPresent()) { - LOGGER.warn("Ratio tap changer tap position action: voltage control is present on the tap changer, tap position could be overriden."); - } - return create(branch, action.getId(), action.isRelativeValue(), action.getTapPosition(), lfNetwork); - } - - private static Optional create(LfBranch branch, String actionId, boolean isRelative, int tapPosition, LfNetwork lfNetwork) { - if (branch != null) { - if (branch.getPiModel() instanceof SimplePiModel) { - throw new UnsupportedOperationException("Tap position action: only one tap in branch " + branch.getId()); - } else { - var tapPositionChange = new TapPositionChange(branch, tapPosition, isRelative); - return Optional.of(new LfAction(actionId, null, null, tapPositionChange, null, null, null, null, null)); - } - } - return Optional.empty(); // could be in another component - } - - private static Optional create(TerminalsConnectionAction action, LfNetwork lfNetwork) { - LfBranch branch = lfNetwork.getBranchById(action.getElementId()); - if (branch != null && branch.getBus1() != null && branch.getBus2() != null) { - if (action.getSide().isEmpty()) { - if (action.isOpen()) { - return Optional.of(new LfAction(action.getId(), branch, null, null, null, null, null, null, null)); - } else { - return Optional.of(new LfAction(action.getId(), null, branch, null, null, null, null, null, null)); - } - } else { - throw new UnsupportedOperationException("Terminals connection action: only open or close branch at both sides is supported yet."); - } - } - return Optional.empty(); // could be in another component - } - - private static Optional create(SwitchAction action, LfNetwork lfNetwork) { - LfBranch branch = lfNetwork.getBranchById(action.getSwitchId()); - if (branch != null) { - LfBranch disabledBranch = null; - LfBranch enabledBranch = null; - if (action.isOpen()) { - disabledBranch = branch; - } else { - enabledBranch = branch; - } - return Optional.of(new LfAction(action.getId(), disabledBranch, enabledBranch, null, null, null, null, null, null)); - } - return Optional.empty(); // could be in another component - } - - private static Optional create(GeneratorAction action, LfNetwork lfNetwork) { - LfGenerator generator = lfNetwork.getGeneratorById(action.getGeneratorId()); - if (generator != null) { - OptionalDouble activePowerValue = action.getActivePowerValue(); - Optional relativeValue = action.isActivePowerRelativeValue(); - if (relativeValue.isPresent() && activePowerValue.isPresent()) { - var generatorChange = new GeneratorChange(generator, activePowerValue.getAsDouble() / PerUnit.SB, relativeValue.get()); - return Optional.of(new LfAction(action.getId(), null, null, null, null, generatorChange, null, null, null)); - } else { - throw new UnsupportedOperationException("Generator action on " + action.getGeneratorId() + " : configuration not supported yet."); - } - } - return Optional.empty(); - } - - private static Optional create(AreaInterchangeTargetAction action, LfNetwork lfNetwork) { - LfArea area = lfNetwork.getAreaById(action.getId()); - if (area != null) { - AreaInterchangeTargetChange change = new AreaInterchangeTargetChange(area, action.getInterchangeTarget()); - return Optional.of(new LfAction(action.getId(), null, null, null, null, null, null, null, change)); - } - return Optional.empty(); - } - - public String getId() { - return id; - } - - public LfBranch getDisabledBranch() { - return disabledBranch; - } - - public LfBranch getEnabledBranch() { - return enabledBranch; - } - - public TapPositionChange getTapPositionChange() { - return tapPositionChange; - } - - public static void apply(List actions, LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { - Objects.requireNonNull(actions); - Objects.requireNonNull(network); - - // first process connectivity part of actions - updateConnectivity(actions, network, contingency); - - // then process remaining changes of actions - for (LfAction action : actions) { - action.apply(networkParameters); - } - } - - private static void updateConnectivity(List actions, LfNetwork network, LfContingency contingency) { - GraphConnectivity connectivity = network.getConnectivity(); - - // re-update connectivity according to post contingency state (revert after LfContingency apply) - connectivity.startTemporaryChanges(); - contingency.getDisabledNetwork().getBranches().forEach(connectivity::removeEdge); - - // update connectivity according to post action state - connectivity.startTemporaryChanges(); - for (LfAction action : actions) { - action.updateConnectivity(connectivity); - } - - updateBusesAndBranchStatus(connectivity); - - // reset connectivity to discard post contingency connectivity and post action connectivity - connectivity.undoTemporaryChanges(); - connectivity.undoTemporaryChanges(); - } - - public static void updateBusesAndBranchStatus(GraphConnectivity connectivity) { - // disable buses and branches that won't be part of the main connected component - Set removedBuses = connectivity.getVerticesRemovedFromMainComponent(); - removedBuses.forEach(bus -> bus.setDisabled(true)); - Set removedBranches = new HashSet<>(connectivity.getEdgesRemovedFromMainComponent()); - // we should manage branches open at one side. - for (LfBus bus : removedBuses) { - bus.getBranches().stream().filter(b -> !b.isConnectedAtBothSides()).forEach(removedBranches::add); - } - removedBranches.forEach(branch -> branch.setDisabled(true)); - - // enable buses and branches that will be part of the main connected component - Set addedBuses = connectivity.getVerticesAddedToMainComponent(); - addedBuses.forEach(bus -> bus.setDisabled(false)); - Set addedBranches = new HashSet<>(connectivity.getEdgesAddedToMainComponent()); - // we should manage branches open at one side. - for (LfBus bus : addedBuses) { - bus.getBranches().stream().filter(b -> !b.isConnectedAtBothSides()).forEach(addedBranches::add); - } - addedBranches.forEach(branch -> branch.setDisabled(false)); - } - - public void updateConnectivity(GraphConnectivity connectivity) { - if (disabledBranch != null && disabledBranch.getBus1() != null && disabledBranch.getBus2() != null) { - connectivity.removeEdge(disabledBranch); - } - if (enabledBranch != null) { - connectivity.addEdge(enabledBranch.getBus1(), enabledBranch.getBus2(), enabledBranch); - } - } - - private void applyTapPositionChange() { - LfBranch branch = tapPositionChange.getBranch(); - int newTapPosition = tapPositionChange.getNewTapPosition(); - branch.getPiModel().setTapPosition(newTapPosition); - } - - private void applyLoadShift() { - String loadId = loadShift.loadId(); - LfLoad lfLoad = loadShift.lfLoad(); - if (!lfLoad.isOriginalLoadDisabled(loadId)) { - PowerShift shift = loadShift.powerShift(); - lfLoad.setTargetP(lfLoad.getTargetP() + shift.getActive()); - lfLoad.setTargetQ(lfLoad.getTargetQ() + shift.getReactive()); - lfLoad.setAbsVariableTargetP(lfLoad.getAbsVariableTargetP() + Math.signum(shift.getActive()) * Math.abs(shift.getVariableActive())); - } - } - - private void applyGeneratorChange(LfNetworkParameters networkParameters) { - LfGenerator generator = generatorChange.generator(); - if (!generator.isDisabled()) { - double newTargetP = generatorChange.isRelative() ? generator.getTargetP() + generatorChange.activePowerValue() : generatorChange.activePowerValue(); - generator.setTargetP(newTargetP); - generator.setInitialTargetP(newTargetP); - generator.reApplyActivePowerControlChecks(networkParameters, null); - } - } - - private void applyHvdcAction() { - hvdc.setAcEmulation(false); - hvdc.setDisabled(true); // for equations only, but should be hidden - hvdc.getConverterStation1().setTargetP(-hvdc.getP1().eval()); // override - hvdc.getConverterStation2().setTargetP(-hvdc.getP2().eval()); // override - } - - private void applySectionChange() { - LfShunt shunt = sectionChange.shunt(); - shunt.getControllers().stream().filter(controller -> controller.getId().equals(sectionChange.controllerId())).findAny() - .ifPresentOrElse(controller -> controller.updateSectionB(sectionChange.value()), - () -> LOGGER.warn("No section change: shunt {} not present", sectionChange.controllerId)); - } - - private void applyAreaInterchangeTargetChange() { - LfArea area = areaInterchangeTargetChange.area(); - area.setInterchangeTarget(areaInterchangeTargetChange.interchangeTarget); - } - - public void apply(LfNetworkParameters networkParameters) { - if (tapPositionChange != null) { - applyTapPositionChange(); - } - - if (loadShift != null) { - applyLoadShift(); - } - - if (generatorChange != null) { - applyGeneratorChange(networkParameters); - } - - if (hvdc != null) { - applyHvdcAction(); - } - - if (sectionChange != null) { - applySectionChange(); - } - - if (areaInterchangeTargetChange != null) { - applyAreaInterchangeTargetChange(); - } - } -} diff --git a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfAction.java b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfAction.java new file mode 100644 index 0000000000..930896a24c --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfAction.java @@ -0,0 +1,23 @@ +package com.powsybl.openloadflow.network.action; + +import com.powsybl.action.Action; +import com.powsybl.openloadflow.graph.GraphConnectivity; +import com.powsybl.openloadflow.network.*; + +public abstract class AbstractLfAction { + + protected final String id; + + protected final A action; + + AbstractLfAction(String id, A action) { + this.id = id; + this.action = action; + } + + public String getId() { + return id; + } + + public abstract boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity); +} diff --git a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java new file mode 100644 index 0000000000..f8fae61774 --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java @@ -0,0 +1,97 @@ +package com.powsybl.openloadflow.network.action; + +import com.powsybl.action.Action; +import com.powsybl.openloadflow.graph.GraphConnectivity; +import com.powsybl.openloadflow.network.*; + +import java.util.HashSet; +import java.util.Set; + +public abstract class AbstractLfBranchAction extends AbstractLfAction { + + private LfBranch disabledBranch = null; // switch to open + + private LfBranch enabledBranch = null; // switch to close + + AbstractLfBranchAction(String id, A action) { + super(id, action); + } + + protected void setDisabledBranch(LfBranch disabledBranch) { + this.disabledBranch = disabledBranch; + } + + protected void setEnabledBranch(LfBranch enabledBranch) { + this.enabledBranch = enabledBranch; + } + + public LfBranch getDisabledBranch() { + return this.disabledBranch; + } + + public LfBranch getEnabledBranch() { + return this.enabledBranch; + } + + abstract boolean findEnabledDisabledBranches(LfNetwork lfNetwork); + + /** + * Standalone apply + */ + @Override + public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + boolean found = findEnabledDisabledBranches(network); + GraphConnectivity connectivityTmp = network.getConnectivity(); + + // re-update connectivity according to post contingency state (revert after LfContingency apply) + connectivityTmp.startTemporaryChanges(); + if (contingency != null) { + contingency.getDisabledNetwork().getBranches().forEach(connectivityTmp::removeEdge); + } + + // update connectivity according to post action state + connectivityTmp.startTemporaryChanges(); + + applyOnConnectivity(connectivityTmp); + updateBusesAndBranchStatus(connectivityTmp); + + // reset connectivity to discard post contingency connectivity and post action connectivity + connectivityTmp.undoTemporaryChanges(); + connectivityTmp.undoTemporaryChanges(); + return found; + } + + /** + * Optimized apply on an existing connectivity (to apply several branch actions together) + */ + public void applyOnConnectivity(GraphConnectivity connectivity) { + if (disabledBranch != null && disabledBranch.getBus1() != null && disabledBranch.getBus2() != null) { + connectivity.removeEdge(disabledBranch); + } + if (enabledBranch != null) { + connectivity.addEdge(enabledBranch.getBus1(), enabledBranch.getBus2(), enabledBranch); + } + } + + public static void updateBusesAndBranchStatus(GraphConnectivity connectivity) { + // disable buses and branches that won't be part of the main connected component + Set removedBuses = connectivity.getVerticesRemovedFromMainComponent(); + removedBuses.forEach(bus -> bus.setDisabled(true)); + Set removedBranches = new HashSet<>(connectivity.getEdgesRemovedFromMainComponent()); + // we should manage branches open at one side. + for (LfBus bus : removedBuses) { + bus.getBranches().stream().filter(b -> !b.isConnectedAtBothSides()).forEach(removedBranches::add); + } + removedBranches.forEach(branch -> branch.setDisabled(true)); + + // enable buses and branches that will be part of the main connected component + Set addedBuses = connectivity.getVerticesAddedToMainComponent(); + addedBuses.forEach(bus -> bus.setDisabled(false)); + Set addedBranches = new HashSet<>(connectivity.getEdgesAddedToMainComponent()); + // we should manage branches open at one side. + for (LfBus bus : addedBuses) { + bus.getBranches().stream().filter(b -> !b.isConnectedAtBothSides()).forEach(addedBranches::add); + } + addedBranches.forEach(branch -> branch.setDisabled(false)); + } +} diff --git a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfTapChangerAction.java b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfTapChangerAction.java new file mode 100644 index 0000000000..2e8812db28 --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfTapChangerAction.java @@ -0,0 +1,28 @@ +package com.powsybl.openloadflow.network.action; + +import com.powsybl.action.AbstractTapChangerTapPositionAction; +import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.network.impl.LfLegBranch; + +public abstract class AbstractLfTapChangerAction extends AbstractLfAction { + + protected TapPositionChange change; + + protected LfBranch branch; + + AbstractLfTapChangerAction(String id, A action, LfNetwork network) { + super(id, action); + String branchId = action.getSide().map(side -> LfLegBranch.getId(side, action.getTransformerId())).orElseGet(action::getTransformerId); + this.branch = network.getBranchById(branchId); + if (this.branch != null) { + if (branch.getPiModel() instanceof SimplePiModel) { + throw new UnsupportedOperationException("Tap position action: only one tap in branch " + branch.getId()); + } + this.change = new TapPositionChange(branch, action.getTapPosition(), action.isRelativeValue()); + } + } + + public TapPositionChange getChange() { + return change; + } +} diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java new file mode 100644 index 0000000000..e012b18aaf --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java @@ -0,0 +1,75 @@ +package com.powsybl.openloadflow.network.action; + +import com.powsybl.action.*; +import com.powsybl.iidm.network.Network; +import com.powsybl.openloadflow.graph.GraphConnectivity; +import com.powsybl.openloadflow.network.*; + +import java.util.*; + +import static com.powsybl.openloadflow.network.action.AbstractLfBranchAction.updateBusesAndBranchStatus; + +public final class LfActionUtils { + + private LfActionUtils() { + } + + public static AbstractLfAction createLfAction(Action action, Network network, boolean breakers, LfNetwork lfNetwork) { + Objects.requireNonNull(action); + Objects.requireNonNull(network); + return switch (action.getType()) { + case SwitchAction.NAME -> new LfSwitchAction(action.getId(), (SwitchAction) action); + case TerminalsConnectionAction.NAME -> + new LfTerminalsConnectionAction(action.getId(), (TerminalsConnectionAction) action); + case PhaseTapChangerTapPositionAction.NAME -> + new LfPhaseTapChangerAction(action.getId(), (PhaseTapChangerTapPositionAction) action, lfNetwork); + case RatioTapChangerTapPositionAction.NAME -> + new LfRatioTapChangerAction(action.getId(), (RatioTapChangerTapPositionAction) action, lfNetwork); + case LoadAction.NAME -> + new LfLoadAction(action.getId(), (LoadAction) action, network, breakers); + case GeneratorAction.NAME -> new LfGeneratorAction(action.getId(), (GeneratorAction) action); + case HvdcAction.NAME -> new LfHvdcAction(action.getId(), (HvdcAction) action); + case ShuntCompensatorPositionAction.NAME -> + new LfShuntCompensatorPositionAction(action.getId(), (ShuntCompensatorPositionAction) action); + case AreaInterchangeTargetAction.NAME -> + new LfAreaInterchangeTargetAction(action.getId(), (AreaInterchangeTargetAction) action); + default -> throw new UnsupportedOperationException("Unsupported action type: " + action.getType()); + }; + } + + public static void applyListOfActions(List> actions, LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { + Objects.requireNonNull(actions); + Objects.requireNonNull(network); + + // first apply action modifying connectivity + List> branchActions = actions.stream() + .filter(action -> action instanceof AbstractLfBranchAction) + .toList(); + updateConnectivity(branchActions, network, contingency, networkParameters); + + // then process remaining changes of actions + actions.stream() + .filter(action -> !(action instanceof AbstractLfBranchAction)) + .forEach(action -> action.apply(network, contingency, networkParameters, network.getConnectivity())); + } + + private static void updateConnectivity(List> branchActions, LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { + GraphConnectivity connectivity = network.getConnectivity(); + + // re-update connectivity according to post contingency state (revert after LfContingency apply) + connectivity.startTemporaryChanges(); + contingency.getDisabledNetwork().getBranches().forEach(connectivity::removeEdge); + + // update connectivity according to post action state + connectivity.startTemporaryChanges(); + + branchActions.forEach(action -> ((AbstractLfBranchAction) action).applyOnConnectivity(connectivity)); + + updateBusesAndBranchStatus(connectivity); + + // reset connectivity to discard post contingency connectivity and post action connectivity + connectivity.undoTemporaryChanges(); + connectivity.undoTemporaryChanges(); + } + +} diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java new file mode 100644 index 0000000000..03924f2804 --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java @@ -0,0 +1,22 @@ +package com.powsybl.openloadflow.network.action; + +import com.powsybl.action.AreaInterchangeTargetAction; +import com.powsybl.openloadflow.graph.GraphConnectivity; +import com.powsybl.openloadflow.network.*; + +public class LfAreaInterchangeTargetAction extends AbstractLfAction { + + public LfAreaInterchangeTargetAction(String id, AreaInterchangeTargetAction action) { + super(id, action); + } + + @Override + public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + LfArea area = network.getAreaById(action.getId()); + if (area != null) { + area.setInterchangeTarget(action.getInterchangeTarget()); + return true; + } + return false; + } +} diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java new file mode 100644 index 0000000000..b1ee2a5d8e --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java @@ -0,0 +1,38 @@ +package com.powsybl.openloadflow.network.action; + +import com.powsybl.action.GeneratorAction; +import com.powsybl.openloadflow.graph.GraphConnectivity; +import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.util.PerUnit; + +import java.util.Optional; +import java.util.OptionalDouble; + +public class LfGeneratorAction extends AbstractLfAction { + + public LfGeneratorAction(String id, GeneratorAction action) { + super(id, action); + } + + @Override + public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + LfGenerator generator = network.getGeneratorById(action.getGeneratorId()); + if (generator != null) { + OptionalDouble activePowerValue = action.getActivePowerValue(); + Optional relativeValue = action.isActivePowerRelativeValue(); + if (relativeValue.isPresent() && activePowerValue.isPresent()) { + if (!generator.isDisabled()) { + double change = activePowerValue.getAsDouble() / PerUnit.SB; + double newTargetP = Boolean.TRUE.equals(relativeValue.get()) ? generator.getTargetP() + change : change; + generator.setTargetP(newTargetP); + generator.setInitialTargetP(newTargetP); + generator.reApplyActivePowerControlChecks(networkParameters, null); + return true; + } + } else { + throw new UnsupportedOperationException("Generator action on " + action.getGeneratorId() + " : configuration not supported yet."); + } + } + return false; + } +} diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java new file mode 100644 index 0000000000..7d3a16bf92 --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java @@ -0,0 +1,40 @@ +package com.powsybl.openloadflow.network.action; + +import com.powsybl.action.HvdcAction; +import com.powsybl.openloadflow.graph.GraphConnectivity; +import com.powsybl.openloadflow.network.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Optional; + +public class LfHvdcAction extends AbstractLfAction { + + private static final Logger LOGGER = LoggerFactory.getLogger(LfHvdcAction.class); + + public LfHvdcAction(String id, HvdcAction action) { + super(id, action); + } + + @Override + public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + LfHvdc lfHvdc = network.getHvdcById(action.getHvdcId()); + Optional acEmulationEnabled = action.isAcEmulationEnabled(); + if (lfHvdc != null && acEmulationEnabled.isPresent()) { + if (acEmulationEnabled.get().equals(Boolean.TRUE)) { // the operation mode remains AC emulation. + throw new UnsupportedOperationException("Hvdc action: line is already in AC emulation, not supported yet."); + } else { // the operation mode changes from AC emulation to fixed active power set point. + lfHvdc.setAcEmulation(false); + lfHvdc.setDisabled(true); // for equations only, but should be hidden + lfHvdc.getConverterStation1().setTargetP(-lfHvdc.getP1().eval()); // override + lfHvdc.getConverterStation2().setTargetP(-lfHvdc.getP2().eval()); // override + return true; + } + } else if (lfHvdc != null) { + LOGGER.warn("Hvdc action {}: hvdc is already in active power setpoint mode, action not supported.", action.getId()); + } else { + LOGGER.warn("Hvdc action {}: hvdc line not found", action.getId()); + } + return false; + } +} diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java new file mode 100644 index 0000000000..43f8fc549f --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java @@ -0,0 +1,43 @@ +package com.powsybl.openloadflow.network.action; + +import com.powsybl.action.LoadAction; +import com.powsybl.iidm.network.Bus; +import com.powsybl.iidm.network.Load; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.Terminal; +import com.powsybl.openloadflow.graph.GraphConnectivity; +import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.network.impl.Networks; + +public class LfLoadAction extends AbstractLfAction { + + private final Network network; + + private final boolean breakers; + + public LfLoadAction(String id, LoadAction action, Network network, boolean breakers) { + super(id, action); + this.network = network; + this.breakers = breakers; + } + + @Override + public boolean apply(LfNetwork lfNetwork, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + Load load = network.getLoad(action.getLoadId()); + Terminal terminal = load.getTerminal(); + Bus bus = Networks.getBus(terminal, breakers); + if (bus != null) { + LfLoad lfLoad = lfNetwork.getLoadById(load.getId()); + if (lfLoad != null) { + PowerShift powerShift = PowerShift.createPowerShift(load, action); + if (!lfLoad.isOriginalLoadDisabled(load.getId())) { + lfLoad.setTargetP(lfLoad.getTargetP() + powerShift.getActive()); + lfLoad.setTargetQ(lfLoad.getTargetQ() + powerShift.getReactive()); + lfLoad.setAbsVariableTargetP(lfLoad.getAbsVariableTargetP() + Math.signum(powerShift.getActive()) * Math.abs(powerShift.getVariableActive())); + return true; + } + } + } + return false; + } +} diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java new file mode 100644 index 0000000000..1f409ffa0f --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java @@ -0,0 +1,32 @@ +package com.powsybl.openloadflow.network.action; + +import com.powsybl.action.PhaseTapChangerTapPositionAction; +import com.powsybl.openloadflow.graph.GraphConnectivity; +import com.powsybl.openloadflow.network.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LfPhaseTapChangerAction extends AbstractLfTapChangerAction { + + private static final Logger LOGGER = LoggerFactory.getLogger(LfPhaseTapChangerAction.class); + + public LfPhaseTapChangerAction(String id, PhaseTapChangerTapPositionAction action, LfNetwork network) { + super(id, action, network); + } + + @Override + public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + if (branch != null) { + if (branch.getPhaseControl().isPresent()) { + LOGGER.warn("Phase tap changer tap position action: phase control is present on the tap changer, tap position could be overriden."); + } + if (branch.getPiModel() instanceof SimplePiModel) { + throw new UnsupportedOperationException("Tap position action: only one tap in branch " + branch.getId()); + } else { + branch.getPiModel().setTapPosition(this.change.getNewTapPosition()); + return true; + } + } + return false; + } +} diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java new file mode 100644 index 0000000000..bdf4a60c10 --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java @@ -0,0 +1,32 @@ +package com.powsybl.openloadflow.network.action; + +import com.powsybl.action.RatioTapChangerTapPositionAction; +import com.powsybl.openloadflow.graph.GraphConnectivity; +import com.powsybl.openloadflow.network.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LfRatioTapChangerAction extends AbstractLfTapChangerAction { + + private static final Logger LOGGER = LoggerFactory.getLogger(LfRatioTapChangerAction.class); + + public LfRatioTapChangerAction(String id, RatioTapChangerTapPositionAction action, LfNetwork network) { + super(id, action, network); + } + + @Override + public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + if (this.branch != null) { + if (branch.getVoltageControl().isPresent()) { + LOGGER.warn("Ratio tap changer tap position action: voltage control is present on the tap changer, tap position could be overriden."); + } + if (branch.getPiModel() instanceof SimplePiModel) { + throw new UnsupportedOperationException("Tap position action: only one tap in branch " + branch.getId()); + } else { + branch.getPiModel().setTapPosition(this.change.getNewTapPosition()); + return true; + } + } + return false; + } +} diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java new file mode 100644 index 0000000000..0968de1377 --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java @@ -0,0 +1,32 @@ +package com.powsybl.openloadflow.network.action; + +import com.powsybl.action.ShuntCompensatorPositionAction; +import com.powsybl.openloadflow.graph.GraphConnectivity; +import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.network.impl.LfShuntImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LfShuntCompensatorPositionAction extends AbstractLfAction { + + private static final Logger LOGGER = LoggerFactory.getLogger(LfShuntCompensatorPositionAction.class); + + public LfShuntCompensatorPositionAction(String id, ShuntCompensatorPositionAction action) { + super(id, action); + } + + @Override + public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + LfShunt shunt = network.getShuntById(action.getShuntCompensatorId()); + if (shunt instanceof LfShuntImpl) { // no svc here + if (shunt.getVoltageControl().isPresent()) { + LOGGER.warn("Shunt compensator position action: voltage control is present on the shunt, section could be overridden."); + } + shunt.getControllers().stream().filter(controller -> controller.getId().equals(action.getShuntCompensatorId())).findAny() + .ifPresentOrElse(controller -> controller.updateSectionB(action.getSectionCount()), + () -> LOGGER.warn("No section change: shunt {} not present", action.getShuntCompensatorId())); + return true; + } + return false; + } +} diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java new file mode 100644 index 0000000000..68b67cc757 --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java @@ -0,0 +1,32 @@ +package com.powsybl.openloadflow.network.action; + +import com.powsybl.action.SwitchAction; +import com.powsybl.openloadflow.network.LfBranch; +import com.powsybl.openloadflow.network.LfNetwork; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LfSwitchAction extends AbstractLfBranchAction { + + private static final Logger LOGGER = LoggerFactory.getLogger(LfSwitchAction.class); + + public LfSwitchAction(String id, SwitchAction action) { + super(id, action); + } + + @Override + boolean findEnabledDisabledBranches(LfNetwork lfNetwork) { + LfBranch branch = lfNetwork.getBranchById(action.getSwitchId()); + if (branch != null) { + if (action.isOpen()) { + setDisabledBranch(branch); + } else { + setEnabledBranch(branch); + } + return true; + } else { + LOGGER.warn("Switch action {} : branch matching switch id {} not found", action.getId(), action.getSwitchId()); + return false; + } + } +} diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java new file mode 100644 index 0000000000..f872e45964 --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java @@ -0,0 +1,36 @@ +package com.powsybl.openloadflow.network.action; + +import com.powsybl.action.TerminalsConnectionAction; +import com.powsybl.openloadflow.network.LfBranch; +import com.powsybl.openloadflow.network.LfNetwork; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LfTerminalsConnectionAction extends AbstractLfBranchAction { + + private static final Logger LOGGER = LoggerFactory.getLogger(LfTerminalsConnectionAction.class); + + public LfTerminalsConnectionAction(String id, TerminalsConnectionAction action) { + super(id, action); + } + + @Override + boolean findEnabledDisabledBranches(LfNetwork lfNetwork) { + LfBranch branch = lfNetwork.getBranchById(action.getElementId()); + if (branch != null && branch.getBus1() != null && branch.getBus2() != null) { + if (action.getSide().isEmpty()) { + if (action.isOpen()) { + setDisabledBranch(branch); + } else { + setEnabledBranch(branch); + } + } else { + throw new UnsupportedOperationException("Terminals connection action: only open or close branch at both sides is supported yet."); + } + return true; + } else { + LOGGER.warn("TerminalsConnectionAction action {} : branch matching element id {} not found", action.getId(), action.getElementId()); + return false; + } + } +} diff --git a/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java index 57d634ffc2..59199f5d25 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java @@ -26,6 +26,8 @@ import com.powsybl.openloadflow.lf.LoadFlowContext; import com.powsybl.openloadflow.lf.LoadFlowEngine; import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.network.action.AbstractLfAction; +import com.powsybl.openloadflow.network.action.LfActionUtils; import com.powsybl.openloadflow.network.impl.*; import com.powsybl.openloadflow.network.util.ActivePowerDistribution; import com.powsybl.openloadflow.util.Lists2; @@ -456,11 +458,10 @@ protected static void checkActions(Network network, List actions) { } } - protected static Map createLfActions(LfNetwork lfNetwork, Set actions, Network network, LfNetworkParameters parameters) { + protected static Map> createLfActions(LfNetwork lfNetwork, Set actions, Network network, LfNetworkParameters parameters) { return actions.stream() - .map(action -> LfAction.create(action, lfNetwork, network, parameters.isBreakers())) - .flatMap(Optional::stream) - .collect(Collectors.toMap(LfAction::getId, Function.identity())); + .map(action -> LfActionUtils.createLfAction(action, network, parameters.isBreakers(), lfNetwork)) + .collect(Collectors.toMap(AbstractLfAction::getId, Function.identity())); } protected static Map indexActionsById(List actions) { @@ -625,7 +626,7 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List actionsById = indexActionsById(actions); Set neededActions = new HashSet<>(actionsById.size()); Map> operatorStrategiesByContingencyId = indexOperatorStrategiesByContingencyId(propagatedContingencies, operatorStrategies, actionsById, neededActions); - Map lfActionById = createLfActions(lfNetwork, neededActions, network, acParameters.getNetworkParameters()); // only convert needed actions + Map> lfActionById = createLfActions(lfNetwork, neededActions, network, acParameters.getNetworkParameters()); // only convert needed actions LoadFlowParameters loadFlowParameters = securityAnalysisParameters.getLoadFlowParameters(); OpenLoadFlowParameters openLoadFlowParameters = OpenLoadFlowParameters.get(loadFlowParameters); @@ -735,7 +736,7 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List runActionSimulation(LfNetwork network, C context, OperatorStrategy operatorStrategy, LimitViolationManager preContingencyLimitViolationManager, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, - Map lfActionById, boolean createResultExtension, LfContingency contingency, + Map> lfActionById, boolean createResultExtension, LfContingency contingency, LimitViolationsResult postContingencyLimitViolations, LfNetworkParameters networkParameters, List limitReductions) { OperatorStrategyResult operatorStrategyResult = null; @@ -803,19 +804,19 @@ protected OperatorStrategyResult runActionSimulation(LfNetwork network, C contex List actionsIds, LimitViolationManager preContingencyLimitViolationManager, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, - Map lfActionById, boolean createResultExtension, LfContingency contingency, + Map> lfActionById, boolean createResultExtension, LfContingency contingency, LfNetworkParameters networkParameters, List limitReductions) { logActionStart(network, operatorStrategy); // get LF action for this operator strategy, as all actions have been previously checked against IIDM // network, an empty LF action means it is for another component (so another LF network) so we can // skip it - List operatorStrategyLfActions = actionsIds.stream() + List> operatorStrategyLfActions = actionsIds.stream() .map(lfActionById::get) .filter(Objects::nonNull) .toList(); - LfAction.apply(operatorStrategyLfActions, network, contingency, networkParameters); + LfActionUtils.applyListOfActions((List>) operatorStrategyLfActions, network, contingency, networkParameters); Stopwatch stopwatch = Stopwatch.createStarted(); diff --git a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java index 4f812249fb..3f555a7c1f 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java @@ -26,6 +26,7 @@ import com.powsybl.openloadflow.equations.EquationSystem; import com.powsybl.openloadflow.graph.GraphConnectivityFactory; import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.network.action.*; import com.powsybl.openloadflow.network.impl.Networks; import com.powsybl.openloadflow.network.impl.PropagatedContingency; import com.powsybl.openloadflow.dc.fastdc.ComputedContingencyElement; @@ -98,14 +99,15 @@ private double[] calculatePostContingencyStates(DcLoadFlowContext loadFlowContex private double[] calculatePostContingencyAndOperatorStrategyStates(DcLoadFlowContext loadFlowContext, DenseMatrix contingenciesStates, double[] flowStates, PropagatedContingency contingency, Map contingencyElementByBranch, Set disabledBuses, Set elementsToReconnect, Set partialDisabledBranches, - List operatorStrategyLfActions, Map tapPositionChangeElementByBranch, + List> operatorStrategyLfActions, Map tapPositionChangeElementByBranch, DenseMatrix actionsStates, ReportNode reportNode) { List contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() .filter(element -> !elementsToReconnect.contains(element)) .map(contingencyElementByBranch::get) .collect(Collectors.toList()); List actionElements = operatorStrategyLfActions.stream() - .map(lfAction -> lfAction.getTapPositionChange().getBranch().getId()) + .filter(AbstractLfTapChangerAction.class::isInstance) + .map(lfAction -> ((AbstractLfTapChangerAction) lfAction).getChange().getBranch().getId()) .map(tapPositionChangeElementByBranch::get) .collect(Collectors.toList()); @@ -162,7 +164,7 @@ private double[] calculatePostContingencyStatesForAContingencyBreakingConnectivi */ private double[] calculatePostContingencyAndOperatorStrategyStatesForAContingencyBreakingConnectivity(ConnectivityBreakAnalysis.ConnectivityAnalysisResult connectivityAnalysisResult, DcLoadFlowContext loadFlowContext, Map contingencyElementByBranch, double[] flowStates, DenseMatrix contingenciesStates, - List operatorStrategyLfActions, Map tapPositionChangeElementByBranch, DenseMatrix actionsStates, ReportNode reportNode) { + List> operatorStrategyLfActions, Map tapPositionChangeElementByBranch, DenseMatrix actionsStates, ReportNode reportNode) { PropagatedContingency contingency = connectivityAnalysisResult.getPropagatedContingency(); Set disabledBuses = connectivityAnalysisResult.getDisabledBuses(); @@ -254,7 +256,7 @@ private PostContingencyResult processPostContingencyResult(DcLoadFlowContext con * Returns the operator strategy result associated to the given post contingency and post operator strategy states. */ private OperatorStrategyResult computeOperatorStrategyResultFromPostContingencyAndOperatorStrategyStates(DcLoadFlowContext loadFlowContext, LfContingency lfContingency, OperatorStrategy operatorStrategy, - List operatorStrategyLfActions, LimitViolationManager preContingencyLimitViolationManager, + List> operatorStrategyLfActions, LimitViolationManager preContingencyLimitViolationManager, boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, double[] postContingencyAndOperatorStrategyStates, List limitReductions) { // update network state with post contingency and post operator strategy states @@ -264,7 +266,7 @@ private OperatorStrategyResult computeOperatorStrategyResultFromPostContingencyA // apply modifications to compute results lfContingency.apply(loadFlowContext.getParameters().getBalanceType()); - LfAction.apply(operatorStrategyLfActions, lfNetwork, lfContingency, loadFlowContext.getParameters().getNetworkParameters()); + LfActionUtils.applyListOfActions(operatorStrategyLfActions, lfNetwork, lfContingency, loadFlowContext.getParameters().getNetworkParameters()); // update network result var postActionsNetworkResult = new PreContingencyNetworkResult(lfNetwork, monitorIndex, createResultExtension); @@ -285,13 +287,13 @@ private OperatorStrategyResult computeOperatorStrategyResultFromPostContingencyA * Returns operator strategy result associated to the given operator strategy, with given supplier of post contingency and post operator strategy states. */ private OperatorStrategyResult processOperatorStrategyResult(DcLoadFlowContext context, LfContingency contingency, OperatorStrategy operatorStrategy, - Function, double[]> postContingencyAndOperatorStrategyStatesSupplier, + Function>, double[]> postContingencyAndOperatorStrategyStatesSupplier, LimitViolationManager preContingencyLimitViolationManager, PostContingencyResult postContingencyResult, - Map lfActionById, boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, + Map> lfActionById, boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, List limitReductions) { // get the actions associated to the operator strategy List actionIds = checkCondition(operatorStrategy, postContingencyResult.getLimitViolationsResult()); - List operatorStrategyLfActions = actionIds.stream() + List> operatorStrategyLfActions = actionIds.stream() .map(lfActionById::get) .filter(Objects::nonNull) .toList(); @@ -299,8 +301,8 @@ private OperatorStrategyResult processOperatorStrategyResult(DcLoadFlowContext c logActionStart(context.getNetwork(), operatorStrategy); Stopwatch stopwatch = Stopwatch.createStarted(); - double[] postContingencyAndOperatorStrategyStates = postContingencyAndOperatorStrategyStatesSupplier.apply(operatorStrategyLfActions); - OperatorStrategyResult operatorStrategyResult = computeOperatorStrategyResultFromPostContingencyAndOperatorStrategyStates(context, contingency, operatorStrategy, operatorStrategyLfActions, + double[] postContingencyAndOperatorStrategyStates = postContingencyAndOperatorStrategyStatesSupplier.apply((List>) operatorStrategyLfActions); + OperatorStrategyResult operatorStrategyResult = computeOperatorStrategyResultFromPostContingencyAndOperatorStrategyStates(context, contingency, operatorStrategy, (List>) operatorStrategyLfActions, preContingencyLimitViolationManager, createResultExtension, violationsParameters, postContingencyAndOperatorStrategyStates, limitReductions); stopwatch.stop(); @@ -313,7 +315,7 @@ private OperatorStrategyResult processOperatorStrategyResult(DcLoadFlowContext c * The post contingency and post operator strategy states are computed with given supplier and function. */ private void addPostContingencyAndOperatorStrategyResults(DcLoadFlowContext context, PropagatedContingency contingency, Map> operatorStrategiesByContingencyId, - Map lfActionById, Supplier toPostContingencyStates, Function, double[]> toPostContingencyAndOperatorStrategyStates, + Map> lfActionById, Supplier toPostContingencyStates, Function>, double[]> toPostContingencyAndOperatorStrategyStates, Runnable restorePreContingencyStates, LimitViolationManager preContingencyLimitViolationManager, PreContingencyNetworkResult preContingencyNetworkResult, boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, List limitReductions, List postContingencyResults, List operatorStrategyResults) { @@ -349,10 +351,10 @@ private void addPostContingencyAndOperatorStrategyResults(DcLoadFlowContext cont }); } - private static Map createTapPositionChangeElementsIndexByBranchId(Map lfActionById, EquationSystem equationSystem) { + private static Map createTapPositionChangeElementsIndexByBranchId(Map> lfActionById, EquationSystem equationSystem) { Map computedTapPositionChangeElements = lfActionById.values().stream() - .filter(lfAction -> lfAction.getTapPositionChange() != null) - .map(lfAction -> new ComputedTapPositionChangeElement(lfAction.getTapPositionChange(), equationSystem)) + .filter(AbstractLfTapChangerAction.class::isInstance) + .map(lfAction -> new ComputedTapPositionChangeElement(((AbstractLfTapChangerAction) lfAction).getChange(), equationSystem)) .filter(computedTapPositionChangeElement -> computedTapPositionChangeElement.getLfBranchEquation() != null) .collect(Collectors.toMap( computedTapPositionChangeElement -> computedTapPositionChangeElement.getLfBranch().getId(), @@ -373,7 +375,7 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List actionsById = indexActionsById(actions); Set neededActions = new HashSet<>(actionsById.size()); Map> operatorStrategiesByContingencyId = indexOperatorStrategiesByContingencyId(propagatedContingencies, operatorStrategies, actionsById, neededActions); - Map lfActionById = createLfActions(lfNetwork, neededActions, network, dcParameters.getNetworkParameters()); // only convert needed actions + Map> lfActionById = createLfActions(lfNetwork, neededActions, network, dcParameters.getNetworkParameters()); // only convert needed actions OpenSecurityAnalysisParameters openSecurityAnalysisParameters = OpenSecurityAnalysisParameters.getOrDefault(securityAnalysisParameters); boolean createResultExtension = openSecurityAnalysisParameters.isCreateResultExtension(); @@ -432,7 +434,7 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List toPostContingencyStates = () -> calculatePostContingencyStates(context, connectivityBreakAnalysisResults.contingenciesStates(), workingContingencyStates, nonBreakingConnectivityContingency, connectivityBreakAnalysisResults.contingencyElementByBranch(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), reportNode); // function to compute post contingency and post operator strategy states - Function, double[]> toPostContingencyAndOperatorStrategyStates = operatorStrategyLfActions -> calculatePostContingencyAndOperatorStrategyStates(context, connectivityBreakAnalysisResults.contingenciesStates(), workingContingencyStates, + Function>, double[]> toPostContingencyAndOperatorStrategyStates = operatorStrategyLfActions -> calculatePostContingencyAndOperatorStrategyStates(context, connectivityBreakAnalysisResults.contingenciesStates(), workingContingencyStates, nonBreakingConnectivityContingency, connectivityBreakAnalysisResults.contingencyElementByBranch(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), operatorStrategyLfActions, tapPositionChangeElementsByBranchId, actionsStates, reportNode); // runnable to restore pre contingency states, after modifications applied to the lfNetwork @@ -457,7 +459,7 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List toPostContingencyStates = () -> calculatePostContingencyStatesForAContingencyBreakingConnectivity(connectivityAnalysisResult, context, connectivityBreakAnalysisResults.contingencyElementByBranch(), workingContingencyStates, connectivityBreakAnalysisResults.contingenciesStates(), reportNode); // function to compute post contingency and post operator strategy states - Function, double[]> toPostContingencyAndOperatorStrategyStates = operatorStrategyLfActions -> calculatePostContingencyAndOperatorStrategyStatesForAContingencyBreakingConnectivity(connectivityAnalysisResult, context, + Function>, double[]> toPostContingencyAndOperatorStrategyStates = operatorStrategyLfActions -> calculatePostContingencyAndOperatorStrategyStatesForAContingencyBreakingConnectivity(connectivityAnalysisResult, context, connectivityBreakAnalysisResults.contingencyElementByBranch(), workingContingencyStates, connectivityBreakAnalysisResults.contingenciesStates(), operatorStrategyLfActions, tapPositionChangeElementsByBranchId, actionsStates, reportNode); // runnable to restore pre contingency states, after modifications applied to the lfNetwork diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index da9cf927e8..0052c6c1a7 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -22,6 +22,9 @@ import com.powsybl.openloadflow.ac.AcLoadFlowParameters; import com.powsybl.openloadflow.graph.NaiveGraphConnectivityFactory; import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.network.action.AbstractLfAction; +import com.powsybl.openloadflow.network.action.LfActionUtils; +import com.powsybl.openloadflow.network.action.LfSwitchAction; import com.powsybl.openloadflow.network.impl.LfNetworkList; import com.powsybl.openloadflow.network.impl.Networks; import com.powsybl.openloadflow.network.impl.PropagatedContingency; @@ -33,7 +36,6 @@ import java.io.IOException; import java.util.Collections; -import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -67,7 +69,7 @@ void test() { topoConfig.getSwitchesToOpen().add(network.getSwitch("C")); try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), topoConfig, ReportNode.NO_OP)) { LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); - LfAction lfAction = LfAction.create(switchAction, lfNetwork, network, acParameters.getNetworkParameters().isBreakers()).orElseThrow(); + AbstractLfAction lfAction = LfActionUtils.createLfAction(switchAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); String loadId = "LOAD"; Contingency contingency = new Contingency(loadId, new LoadContingency("LD")); PropagatedContingencyCreationParameters creationParameters = new PropagatedContingencyCreationParameters() @@ -75,17 +77,28 @@ void test() { PropagatedContingency propagatedContingency = PropagatedContingency.createList(network, Collections.singletonList(contingency), new LfTopoConfig(), creationParameters).get(0); propagatedContingency.toLfContingency(lfNetwork).ifPresent(lfContingency -> { - LfAction.apply(List.of(lfAction), lfNetwork, lfContingency, acParameters.getNetworkParameters()); + lfAction.apply(lfNetwork, lfContingency, acParameters.getNetworkParameters(), lfNetwork.getConnectivity()); assertTrue(lfNetwork.getBranchById("C").isDisabled()); - assertEquals("C", lfAction.getDisabledBranch().getId()); - assertNull(lfAction.getEnabledBranch()); + LfSwitchAction lfSwitchAction = (LfSwitchAction) lfAction; + assertEquals("C", lfSwitchAction.getDisabledBranch().getId()); + assertNull(lfSwitchAction.getEnabledBranch()); }); - assertTrue(LfAction.create(new SwitchAction("switchAction", "S", true), lfNetwork, network, acParameters.getNetworkParameters().isBreakers()).isEmpty()); - assertTrue(LfAction.create(new TerminalsConnectionAction("A line action", "x", true), lfNetwork, network, acParameters.getNetworkParameters().isBreakers()).isEmpty()); - assertTrue(LfAction.create(new PhaseTapChangerTapPositionAction("A phase tap change action", "y", false, 3), lfNetwork, network, acParameters.getNetworkParameters().isBreakers()).isEmpty()); + AbstractLfAction lfSwitchAction = LfActionUtils.createLfAction(new SwitchAction("switchAction", "S", true), + network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + AbstractLfAction lfTerminalsConnectionAction = LfActionUtils.createLfAction(new TerminalsConnectionAction("A line action", "x", true), + network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + AbstractLfAction lfPhaseTapChangerTapPositionAction = LfActionUtils.createLfAction(new PhaseTapChangerTapPositionAction("A phase tap change action", "y", false, 3), + network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + + assertFalse(lfSwitchAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())); + assertFalse(lfTerminalsConnectionAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())); + assertFalse(lfPhaseTapChangerTapPositionAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())); + var lineAction = new TerminalsConnectionAction("A line action", "L1", ThreeSides.ONE, false); - assertEquals("Terminals connection action: only open or close branch at both sides is supported yet.", assertThrows(UnsupportedOperationException.class, () -> LfAction.create(lineAction, lfNetwork, network, acParameters.getNetworkParameters().isBreakers())).getMessage()); + AbstractLfAction lfTerminalAction = LfActionUtils.createLfAction(lineAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + assertEquals("Terminals connection action: only open or close branch at both sides is supported yet.", + assertThrows(UnsupportedOperationException.class, () -> lfTerminalAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())).getMessage()); } } @@ -103,7 +116,8 @@ void testUnsupportedGeneratorAction() { new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new NaiveGraphConnectivityFactory<>(LfBus::getNum), true, false); try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), new LfTopoConfig(), ReportNode.NO_OP)) { LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); - UnsupportedOperationException e = assertThrows(UnsupportedOperationException.class, () -> LfAction.create(generatorAction, lfNetwork, network, acParameters.getNetworkParameters().isBreakers())); + AbstractLfAction lfGeneratorAction = LfActionUtils.createLfAction(generatorAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + UnsupportedOperationException e = assertThrows(UnsupportedOperationException.class, () -> lfGeneratorAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())); assertEquals("Generator action on G : configuration not supported yet.", e.getMessage()); } } @@ -127,8 +141,8 @@ void testGeneratorActionWithRelativeActivePowerValue() { new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new NaiveGraphConnectivityFactory<>(LfBus::getNum), true, false); try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), new LfTopoConfig(), ReportNode.NO_OP)) { LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); - LfAction lfAction = LfAction.create(generatorAction, lfNetwork, network, acParameters.getNetworkParameters().isBreakers()).orElseThrow(); - lfAction.apply(acParameters.getNetworkParameters()); + AbstractLfAction lfAction = LfActionUtils.createLfAction(generatorAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + lfAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity()); assertEquals(newTargetP / PerUnit.SB, lfNetwork.getGeneratorById(genId).getTargetP()); assertEquals(genId, generatorAction.getGeneratorId()); assertEquals(oldTargetP, network.getGenerator(genId).getTargetP()); @@ -156,7 +170,8 @@ void testHvdcAction() { new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new NaiveGraphConnectivityFactory<>(LfBus::getNum), true, false); try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), new LfTopoConfig(), ReportNode.NO_OP)) { LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); - UnsupportedOperationException e = assertThrows(UnsupportedOperationException.class, () -> LfAction.create(hvdcAction, lfNetwork, network, acParameters.getNetworkParameters().isBreakers())); + AbstractLfAction lfAction = LfActionUtils.createLfAction(hvdcAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + UnsupportedOperationException e = assertThrows(UnsupportedOperationException.class, () -> lfAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())); assertEquals("Hvdc action: line is already in AC emulation, not supported yet.", e.getMessage()); } } @@ -172,12 +187,25 @@ void testHvdcAction2() { .withP0(200.0) .withDroop(90.0) .build(); + + HvdcAction hvdcAction2 = new HvdcActionBuilder() + .withId("action") + .withHvdcId("dummy") + .withAcEmulationEnabled(true) + .withP0(200.0) + .withDroop(90.0) + .build(); var matrixFactory = new DenseMatrixFactory(); AcLoadFlowParameters acParameters = OpenLoadFlowParameters.createAcParameters(network, new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new NaiveGraphConnectivityFactory<>(LfBus::getNum), true, false); try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), new LfTopoConfig(), ReportNode.NO_OP)) { LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); - assertTrue(LfAction.create(hvdcAction, lfNetwork, network, acParameters.getNetworkParameters().isBreakers()).isEmpty()); + + AbstractLfAction lfAction = LfActionUtils.createLfAction(hvdcAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + assertFalse(lfAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())); + + AbstractLfAction lfAction2 = LfActionUtils.createLfAction(hvdcAction2, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + assertFalse(lfAction2.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())); } } } From fead01e6aa7672acbe07575300749b89eac928ff Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Thu, 16 Jan 2025 16:28:55 +0100 Subject: [PATCH 03/16] Author and copyrights. Signed-off-by: Bertrand Rix --- .../openloadflow/network/action/AbstractLfAction.java | 10 ++++++++++ .../network/action/AbstractLfBranchAction.java | 10 ++++++++++ .../network/action/AbstractLfTapChangerAction.java | 10 ++++++++++ .../openloadflow/network/action/LfActionUtils.java | 10 ++++++++++ .../network/action/LfAreaInterchangeTargetAction.java | 10 ++++++++++ .../openloadflow/network/action/LfGeneratorAction.java | 10 ++++++++++ .../openloadflow/network/action/LfHvdcAction.java | 10 ++++++++++ .../openloadflow/network/action/LfLoadAction.java | 10 ++++++++++ .../network/action/LfPhaseTapChangerAction.java | 10 ++++++++++ .../network/action/LfRatioTapChangerAction.java | 10 ++++++++++ .../action/LfShuntCompensatorPositionAction.java | 10 ++++++++++ .../openloadflow/network/action/LfSwitchAction.java | 10 ++++++++++ .../network/action/LfTerminalsConnectionAction.java | 10 ++++++++++ 13 files changed, 130 insertions(+) diff --git a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfAction.java b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfAction.java index 930896a24c..6a8e8eaec8 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfAction.java @@ -1,9 +1,19 @@ +/** + * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.network.action; import com.powsybl.action.Action; import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.openloadflow.network.*; +/** + * @author Bertrand Rix {@literal } + */ public abstract class AbstractLfAction { protected final String id; diff --git a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java index f8fae61774..deb1bd3bc2 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.network.action; import com.powsybl.action.Action; @@ -7,6 +14,9 @@ import java.util.HashSet; import java.util.Set; +/** + * @author Bertrand Rix {@literal } + */ public abstract class AbstractLfBranchAction extends AbstractLfAction { private LfBranch disabledBranch = null; // switch to open diff --git a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfTapChangerAction.java b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfTapChangerAction.java index 2e8812db28..4c95a7fec4 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfTapChangerAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfTapChangerAction.java @@ -1,9 +1,19 @@ +/** + * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.network.action; import com.powsybl.action.AbstractTapChangerTapPositionAction; import com.powsybl.openloadflow.network.*; import com.powsybl.openloadflow.network.impl.LfLegBranch; +/** + * @author Bertrand Rix {@literal } + */ public abstract class AbstractLfTapChangerAction extends AbstractLfAction { protected TapPositionChange change; diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java index e012b18aaf..ced1f47200 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.network.action; import com.powsybl.action.*; @@ -9,6 +16,9 @@ import static com.powsybl.openloadflow.network.action.AbstractLfBranchAction.updateBusesAndBranchStatus; +/** + * @author Bertrand Rix {@literal } + */ public final class LfActionUtils { private LfActionUtils() { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java index 03924f2804..5140166523 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java @@ -1,9 +1,19 @@ +/** + * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.network.action; import com.powsybl.action.AreaInterchangeTargetAction; import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.openloadflow.network.*; +/** + * @author Bertrand Rix {@literal } + */ public class LfAreaInterchangeTargetAction extends AbstractLfAction { public LfAreaInterchangeTargetAction(String id, AreaInterchangeTargetAction action) { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java index b1ee2a5d8e..d0ef54989f 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.network.action; import com.powsybl.action.GeneratorAction; @@ -8,6 +15,9 @@ import java.util.Optional; import java.util.OptionalDouble; +/** + * @author Bertrand Rix {@literal } + */ public class LfGeneratorAction extends AbstractLfAction { public LfGeneratorAction(String id, GeneratorAction action) { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java index 7d3a16bf92..7edc94eff9 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.network.action; import com.powsybl.action.HvdcAction; @@ -8,6 +15,9 @@ import java.util.Optional; +/** + * @author Bertrand Rix {@literal } + */ public class LfHvdcAction extends AbstractLfAction { private static final Logger LOGGER = LoggerFactory.getLogger(LfHvdcAction.class); diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java index 43f8fc549f..5a227f6de7 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.network.action; import com.powsybl.action.LoadAction; @@ -9,6 +16,9 @@ import com.powsybl.openloadflow.network.*; import com.powsybl.openloadflow.network.impl.Networks; +/** + * @author Bertrand Rix {@literal } + */ public class LfLoadAction extends AbstractLfAction { private final Network network; diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java index 1f409ffa0f..32e33eea27 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.network.action; import com.powsybl.action.PhaseTapChangerTapPositionAction; @@ -6,6 +13,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * @author Bertrand Rix {@literal } + */ public class LfPhaseTapChangerAction extends AbstractLfTapChangerAction { private static final Logger LOGGER = LoggerFactory.getLogger(LfPhaseTapChangerAction.class); diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java index bdf4a60c10..cbaec0100c 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.network.action; import com.powsybl.action.RatioTapChangerTapPositionAction; @@ -6,6 +13,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * @author Bertrand Rix {@literal } + */ public class LfRatioTapChangerAction extends AbstractLfTapChangerAction { private static final Logger LOGGER = LoggerFactory.getLogger(LfRatioTapChangerAction.class); diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java index 0968de1377..dc626abc7c 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.network.action; import com.powsybl.action.ShuntCompensatorPositionAction; @@ -7,6 +14,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * @author Bertrand Rix {@literal } + */ public class LfShuntCompensatorPositionAction extends AbstractLfAction { private static final Logger LOGGER = LoggerFactory.getLogger(LfShuntCompensatorPositionAction.class); diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java index 68b67cc757..eb4b26d152 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.network.action; import com.powsybl.action.SwitchAction; @@ -6,6 +13,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * @author Bertrand Rix {@literal } + */ public class LfSwitchAction extends AbstractLfBranchAction { private static final Logger LOGGER = LoggerFactory.getLogger(LfSwitchAction.class); diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java index f872e45964..76ccaa9030 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.network.action; import com.powsybl.action.TerminalsConnectionAction; @@ -6,6 +13,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * @author Bertrand Rix {@literal } + */ public class LfTerminalsConnectionAction extends AbstractLfBranchAction { private static final Logger LOGGER = LoggerFactory.getLogger(LfTerminalsConnectionAction.class); From fafd78cac812ebf87814f5787bcda1ca430494c6 Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Thu, 16 Jan 2025 16:58:24 +0100 Subject: [PATCH 04/16] LfAction interface on top. Signed-off-by: Bertrand Rix --- .../dc/fastdc/WoodburyEngine.java | 4 +- .../network/action/AbstractLfAction.java | 7 +-- .../action/AbstractLfBranchAction.java | 28 ++++++----- .../openloadflow/network/action/LfAction.java | 10 ++++ .../network/action/LfActionUtils.java | 14 +++--- .../action/LfAreaInterchangeTargetAction.java | 3 +- .../network/action/LfGeneratorAction.java | 3 +- .../network/action/LfHvdcAction.java | 3 +- .../network/action/LfLoadAction.java | 3 +- .../action/LfPhaseTapChangerAction.java | 3 +- .../action/LfRatioTapChangerAction.java | 3 +- .../LfShuntCompensatorPositionAction.java | 3 +- .../sa/AbstractSecurityAnalysis.java | 16 +++---- .../sa/WoodburyDcSecurityAnalysis.java | 26 +++++----- .../powsybl/openloadflow/sa/LfActionTest.java | 47 +++++++++---------- 15 files changed, 89 insertions(+), 84 deletions(-) create mode 100644 src/main/java/com/powsybl/openloadflow/network/action/LfAction.java diff --git a/src/main/java/com/powsybl/openloadflow/dc/fastdc/WoodburyEngine.java b/src/main/java/com/powsybl/openloadflow/dc/fastdc/WoodburyEngine.java index 35295c75b7..74267f9c57 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/fastdc/WoodburyEngine.java +++ b/src/main/java/com/powsybl/openloadflow/dc/fastdc/WoodburyEngine.java @@ -19,8 +19,8 @@ import com.powsybl.openloadflow.dc.equations.DcEquationType; import com.powsybl.openloadflow.equations.Equation; import com.powsybl.openloadflow.network.*; -import com.powsybl.openloadflow.network.action.AbstractLfAction; import com.powsybl.openloadflow.network.action.AbstractLfTapChangerAction; +import com.powsybl.openloadflow.network.action.LfAction; import java.util.*; @@ -74,7 +74,7 @@ public static double[] runDcLoadFlowWithModifiedTargetVector(DcLoadFlowContext l * A simplified version of DcLoadFlowEngine that supports on the fly bus and branch disabling, and pst actions. * Note that it does not update the state vector and the network at the end (because we don't need it to just evaluate a few equations). */ - public static double[] runDcLoadFlowWithModifiedTargetVector(DcLoadFlowContext loadFlowContext, DisabledNetwork disabledNetwork, ReportNode reportNode, List> pstActions) { + public static double[] runDcLoadFlowWithModifiedTargetVector(DcLoadFlowContext loadFlowContext, DisabledNetwork disabledNetwork, ReportNode reportNode, List pstActions) { Collection remainingBuses; if (disabledNetwork.getBuses().isEmpty()) { remainingBuses = loadFlowContext.getNetwork().getBuses(); diff --git a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfAction.java b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfAction.java index 6a8e8eaec8..a548f12b56 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfAction.java @@ -8,13 +8,11 @@ package com.powsybl.openloadflow.network.action; import com.powsybl.action.Action; -import com.powsybl.openloadflow.graph.GraphConnectivity; -import com.powsybl.openloadflow.network.*; /** * @author Bertrand Rix {@literal } */ -public abstract class AbstractLfAction { +public abstract class AbstractLfAction implements LfAction { protected final String id; @@ -25,9 +23,8 @@ public abstract class AbstractLfAction { this.action = action; } + @Override public String getId() { return id; } - - public abstract boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity); } diff --git a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java index deb1bd3bc2..dc973c4918 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java @@ -49,32 +49,38 @@ public LfBranch getEnabledBranch() { * Standalone apply */ @Override - public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { boolean found = findEnabledDisabledBranches(network); - GraphConnectivity connectivityTmp = network.getConnectivity(); + GraphConnectivity connectivity = network.getConnectivity(); // re-update connectivity according to post contingency state (revert after LfContingency apply) - connectivityTmp.startTemporaryChanges(); + connectivity.startTemporaryChanges(); if (contingency != null) { - contingency.getDisabledNetwork().getBranches().forEach(connectivityTmp::removeEdge); + contingency.getDisabledNetwork().getBranches().forEach(connectivity::removeEdge); } // update connectivity according to post action state - connectivityTmp.startTemporaryChanges(); + connectivity.startTemporaryChanges(); - applyOnConnectivity(connectivityTmp); - updateBusesAndBranchStatus(connectivityTmp); + applyOnConnectivity(network, connectivity); + updateBusesAndBranchStatus(connectivity); // reset connectivity to discard post contingency connectivity and post action connectivity - connectivityTmp.undoTemporaryChanges(); - connectivityTmp.undoTemporaryChanges(); + connectivity.undoTemporaryChanges(); + connectivity.undoTemporaryChanges(); return found; } /** - * Optimized apply on an existing connectivity (to apply several branch actions together) + * Optimized apply on an existing connectivity (to apply several branch actions at the same time) */ - public void applyOnConnectivity(GraphConnectivity connectivity) { + public boolean applyOnConnectivity(LfNetwork network, GraphConnectivity connectivity) { + boolean found = findEnabledDisabledBranches(network); + updateConnectivity(connectivity); + return found; + } + + private void updateConnectivity(GraphConnectivity connectivity) { if (disabledBranch != null && disabledBranch.getBus1() != null && disabledBranch.getBus2() != null) { connectivity.removeEdge(disabledBranch); } diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfAction.java new file mode 100644 index 0000000000..40cd17694a --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfAction.java @@ -0,0 +1,10 @@ +package com.powsybl.openloadflow.network.action; + +import com.powsybl.openloadflow.network.*; + +public interface LfAction { + + String getId(); + + boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters); +} diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java index ced1f47200..1fcaeeb0bf 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java @@ -24,7 +24,7 @@ public final class LfActionUtils { private LfActionUtils() { } - public static AbstractLfAction createLfAction(Action action, Network network, boolean breakers, LfNetwork lfNetwork) { + public static LfAction createLfAction(Action action, Network network, boolean breakers, LfNetwork lfNetwork) { Objects.requireNonNull(action); Objects.requireNonNull(network); return switch (action.getType()) { @@ -47,23 +47,23 @@ public static AbstractLfAction createLfAction(Action action, Network network, }; } - public static void applyListOfActions(List> actions, LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { + public static void applyListOfActions(List actions, LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { Objects.requireNonNull(actions); Objects.requireNonNull(network); // first apply action modifying connectivity - List> branchActions = actions.stream() + List branchActions = actions.stream() .filter(action -> action instanceof AbstractLfBranchAction) .toList(); - updateConnectivity(branchActions, network, contingency, networkParameters); + updateConnectivity(branchActions, network, contingency); // then process remaining changes of actions actions.stream() .filter(action -> !(action instanceof AbstractLfBranchAction)) - .forEach(action -> action.apply(network, contingency, networkParameters, network.getConnectivity())); + .forEach(action -> action.apply(network, contingency, networkParameters)); } - private static void updateConnectivity(List> branchActions, LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { + private static void updateConnectivity(List branchActions, LfNetwork network, LfContingency contingency) { GraphConnectivity connectivity = network.getConnectivity(); // re-update connectivity according to post contingency state (revert after LfContingency apply) @@ -73,7 +73,7 @@ private static void updateConnectivity(List> branchActions, // update connectivity according to post action state connectivity.startTemporaryChanges(); - branchActions.forEach(action -> ((AbstractLfBranchAction) action).applyOnConnectivity(connectivity)); + branchActions.forEach(action -> ((AbstractLfBranchAction) action).applyOnConnectivity(network, connectivity)); updateBusesAndBranchStatus(connectivity); diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java index 5140166523..cb7fd65035 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java @@ -8,7 +8,6 @@ package com.powsybl.openloadflow.network.action; import com.powsybl.action.AreaInterchangeTargetAction; -import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.openloadflow.network.*; /** @@ -21,7 +20,7 @@ public LfAreaInterchangeTargetAction(String id, AreaInterchangeTargetAction acti } @Override - public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { LfArea area = network.getAreaById(action.getId()); if (area != null) { area.setInterchangeTarget(action.getInterchangeTarget()); diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java index d0ef54989f..74c8085604 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java @@ -8,7 +8,6 @@ package com.powsybl.openloadflow.network.action; import com.powsybl.action.GeneratorAction; -import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.openloadflow.network.*; import com.powsybl.openloadflow.util.PerUnit; @@ -25,7 +24,7 @@ public LfGeneratorAction(String id, GeneratorAction action) { } @Override - public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { LfGenerator generator = network.getGeneratorById(action.getGeneratorId()); if (generator != null) { OptionalDouble activePowerValue = action.getActivePowerValue(); diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java index 7edc94eff9..e3ba3e4b70 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java @@ -8,7 +8,6 @@ package com.powsybl.openloadflow.network.action; import com.powsybl.action.HvdcAction; -import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.openloadflow.network.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,7 +26,7 @@ public LfHvdcAction(String id, HvdcAction action) { } @Override - public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { LfHvdc lfHvdc = network.getHvdcById(action.getHvdcId()); Optional acEmulationEnabled = action.isAcEmulationEnabled(); if (lfHvdc != null && acEmulationEnabled.isPresent()) { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java index 5a227f6de7..0f0d4502dd 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java @@ -12,7 +12,6 @@ import com.powsybl.iidm.network.Load; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.Terminal; -import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.openloadflow.network.*; import com.powsybl.openloadflow.network.impl.Networks; @@ -32,7 +31,7 @@ public LfLoadAction(String id, LoadAction action, Network network, boolean break } @Override - public boolean apply(LfNetwork lfNetwork, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + public boolean apply(LfNetwork lfNetwork, LfContingency contingency, LfNetworkParameters networkParameters) { Load load = network.getLoad(action.getLoadId()); Terminal terminal = load.getTerminal(); Bus bus = Networks.getBus(terminal, breakers); diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java index 32e33eea27..b2396d587f 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java @@ -8,7 +8,6 @@ package com.powsybl.openloadflow.network.action; import com.powsybl.action.PhaseTapChangerTapPositionAction; -import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.openloadflow.network.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,7 +24,7 @@ public LfPhaseTapChangerAction(String id, PhaseTapChangerTapPositionAction actio } @Override - public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { if (branch != null) { if (branch.getPhaseControl().isPresent()) { LOGGER.warn("Phase tap changer tap position action: phase control is present on the tap changer, tap position could be overriden."); diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java index cbaec0100c..c59a024ef3 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java @@ -8,7 +8,6 @@ package com.powsybl.openloadflow.network.action; import com.powsybl.action.RatioTapChangerTapPositionAction; -import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.openloadflow.network.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,7 +24,7 @@ public LfRatioTapChangerAction(String id, RatioTapChangerTapPositionAction actio } @Override - public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { if (this.branch != null) { if (branch.getVoltageControl().isPresent()) { LOGGER.warn("Ratio tap changer tap position action: voltage control is present on the tap changer, tap position could be overriden."); diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java index dc626abc7c..c63ee90c46 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java @@ -8,7 +8,6 @@ package com.powsybl.openloadflow.network.action; import com.powsybl.action.ShuntCompensatorPositionAction; -import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.openloadflow.network.*; import com.powsybl.openloadflow.network.impl.LfShuntImpl; import org.slf4j.Logger; @@ -26,7 +25,7 @@ public LfShuntCompensatorPositionAction(String id, ShuntCompensatorPositionActio } @Override - public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, GraphConnectivity connectivity) { + public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { LfShunt shunt = network.getShuntById(action.getShuntCompensatorId()); if (shunt instanceof LfShuntImpl) { // no svc here if (shunt.getVoltageControl().isPresent()) { diff --git a/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java index 59199f5d25..59f63c5895 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java @@ -26,7 +26,7 @@ import com.powsybl.openloadflow.lf.LoadFlowContext; import com.powsybl.openloadflow.lf.LoadFlowEngine; import com.powsybl.openloadflow.network.*; -import com.powsybl.openloadflow.network.action.AbstractLfAction; +import com.powsybl.openloadflow.network.action.LfAction; import com.powsybl.openloadflow.network.action.LfActionUtils; import com.powsybl.openloadflow.network.impl.*; import com.powsybl.openloadflow.network.util.ActivePowerDistribution; @@ -458,10 +458,10 @@ protected static void checkActions(Network network, List actions) { } } - protected static Map> createLfActions(LfNetwork lfNetwork, Set actions, Network network, LfNetworkParameters parameters) { + protected static Map createLfActions(LfNetwork lfNetwork, Set actions, Network network, LfNetworkParameters parameters) { return actions.stream() .map(action -> LfActionUtils.createLfAction(action, network, parameters.isBreakers(), lfNetwork)) - .collect(Collectors.toMap(AbstractLfAction::getId, Function.identity())); + .collect(Collectors.toMap(LfAction::getId, Function.identity())); } protected static Map indexActionsById(List actions) { @@ -626,7 +626,7 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List actionsById = indexActionsById(actions); Set neededActions = new HashSet<>(actionsById.size()); Map> operatorStrategiesByContingencyId = indexOperatorStrategiesByContingencyId(propagatedContingencies, operatorStrategies, actionsById, neededActions); - Map> lfActionById = createLfActions(lfNetwork, neededActions, network, acParameters.getNetworkParameters()); // only convert needed actions + Map lfActionById = createLfActions(lfNetwork, neededActions, network, acParameters.getNetworkParameters()); // only convert needed actions LoadFlowParameters loadFlowParameters = securityAnalysisParameters.getLoadFlowParameters(); OpenLoadFlowParameters openLoadFlowParameters = OpenLoadFlowParameters.get(loadFlowParameters); @@ -736,7 +736,7 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List runActionSimulation(LfNetwork network, C context, OperatorStrategy operatorStrategy, LimitViolationManager preContingencyLimitViolationManager, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, - Map> lfActionById, boolean createResultExtension, LfContingency contingency, + Map lfActionById, boolean createResultExtension, LfContingency contingency, LimitViolationsResult postContingencyLimitViolations, LfNetworkParameters networkParameters, List limitReductions) { OperatorStrategyResult operatorStrategyResult = null; @@ -804,19 +804,19 @@ protected OperatorStrategyResult runActionSimulation(LfNetwork network, C contex List actionsIds, LimitViolationManager preContingencyLimitViolationManager, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, - Map> lfActionById, boolean createResultExtension, LfContingency contingency, + Map lfActionById, boolean createResultExtension, LfContingency contingency, LfNetworkParameters networkParameters, List limitReductions) { logActionStart(network, operatorStrategy); // get LF action for this operator strategy, as all actions have been previously checked against IIDM // network, an empty LF action means it is for another component (so another LF network) so we can // skip it - List> operatorStrategyLfActions = actionsIds.stream() + List operatorStrategyLfActions = actionsIds.stream() .map(lfActionById::get) .filter(Objects::nonNull) .toList(); - LfActionUtils.applyListOfActions((List>) operatorStrategyLfActions, network, contingency, networkParameters); + LfActionUtils.applyListOfActions(operatorStrategyLfActions, network, contingency, networkParameters); Stopwatch stopwatch = Stopwatch.createStarted(); diff --git a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java index 3f555a7c1f..66258effa5 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java @@ -99,7 +99,7 @@ private double[] calculatePostContingencyStates(DcLoadFlowContext loadFlowContex private double[] calculatePostContingencyAndOperatorStrategyStates(DcLoadFlowContext loadFlowContext, DenseMatrix contingenciesStates, double[] flowStates, PropagatedContingency contingency, Map contingencyElementByBranch, Set disabledBuses, Set elementsToReconnect, Set partialDisabledBranches, - List> operatorStrategyLfActions, Map tapPositionChangeElementByBranch, + List operatorStrategyLfActions, Map tapPositionChangeElementByBranch, DenseMatrix actionsStates, ReportNode reportNode) { List contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() .filter(element -> !elementsToReconnect.contains(element)) @@ -164,7 +164,7 @@ private double[] calculatePostContingencyStatesForAContingencyBreakingConnectivi */ private double[] calculatePostContingencyAndOperatorStrategyStatesForAContingencyBreakingConnectivity(ConnectivityBreakAnalysis.ConnectivityAnalysisResult connectivityAnalysisResult, DcLoadFlowContext loadFlowContext, Map contingencyElementByBranch, double[] flowStates, DenseMatrix contingenciesStates, - List> operatorStrategyLfActions, Map tapPositionChangeElementByBranch, DenseMatrix actionsStates, ReportNode reportNode) { + List operatorStrategyLfActions, Map tapPositionChangeElementByBranch, DenseMatrix actionsStates, ReportNode reportNode) { PropagatedContingency contingency = connectivityAnalysisResult.getPropagatedContingency(); Set disabledBuses = connectivityAnalysisResult.getDisabledBuses(); @@ -256,7 +256,7 @@ private PostContingencyResult processPostContingencyResult(DcLoadFlowContext con * Returns the operator strategy result associated to the given post contingency and post operator strategy states. */ private OperatorStrategyResult computeOperatorStrategyResultFromPostContingencyAndOperatorStrategyStates(DcLoadFlowContext loadFlowContext, LfContingency lfContingency, OperatorStrategy operatorStrategy, - List> operatorStrategyLfActions, LimitViolationManager preContingencyLimitViolationManager, + List operatorStrategyLfActions, LimitViolationManager preContingencyLimitViolationManager, boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, double[] postContingencyAndOperatorStrategyStates, List limitReductions) { // update network state with post contingency and post operator strategy states @@ -287,13 +287,13 @@ private OperatorStrategyResult computeOperatorStrategyResultFromPostContingencyA * Returns operator strategy result associated to the given operator strategy, with given supplier of post contingency and post operator strategy states. */ private OperatorStrategyResult processOperatorStrategyResult(DcLoadFlowContext context, LfContingency contingency, OperatorStrategy operatorStrategy, - Function>, double[]> postContingencyAndOperatorStrategyStatesSupplier, + Function, double[]> postContingencyAndOperatorStrategyStatesSupplier, LimitViolationManager preContingencyLimitViolationManager, PostContingencyResult postContingencyResult, - Map> lfActionById, boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, + Map lfActionById, boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, List limitReductions) { // get the actions associated to the operator strategy List actionIds = checkCondition(operatorStrategy, postContingencyResult.getLimitViolationsResult()); - List> operatorStrategyLfActions = actionIds.stream() + List operatorStrategyLfActions = actionIds.stream() .map(lfActionById::get) .filter(Objects::nonNull) .toList(); @@ -301,8 +301,8 @@ private OperatorStrategyResult processOperatorStrategyResult(DcLoadFlowContext c logActionStart(context.getNetwork(), operatorStrategy); Stopwatch stopwatch = Stopwatch.createStarted(); - double[] postContingencyAndOperatorStrategyStates = postContingencyAndOperatorStrategyStatesSupplier.apply((List>) operatorStrategyLfActions); - OperatorStrategyResult operatorStrategyResult = computeOperatorStrategyResultFromPostContingencyAndOperatorStrategyStates(context, contingency, operatorStrategy, (List>) operatorStrategyLfActions, + double[] postContingencyAndOperatorStrategyStates = postContingencyAndOperatorStrategyStatesSupplier.apply(operatorStrategyLfActions); + OperatorStrategyResult operatorStrategyResult = computeOperatorStrategyResultFromPostContingencyAndOperatorStrategyStates(context, contingency, operatorStrategy, operatorStrategyLfActions, preContingencyLimitViolationManager, createResultExtension, violationsParameters, postContingencyAndOperatorStrategyStates, limitReductions); stopwatch.stop(); @@ -315,7 +315,7 @@ private OperatorStrategyResult processOperatorStrategyResult(DcLoadFlowContext c * The post contingency and post operator strategy states are computed with given supplier and function. */ private void addPostContingencyAndOperatorStrategyResults(DcLoadFlowContext context, PropagatedContingency contingency, Map> operatorStrategiesByContingencyId, - Map> lfActionById, Supplier toPostContingencyStates, Function>, double[]> toPostContingencyAndOperatorStrategyStates, + Map lfActionById, Supplier toPostContingencyStates, Function, double[]> toPostContingencyAndOperatorStrategyStates, Runnable restorePreContingencyStates, LimitViolationManager preContingencyLimitViolationManager, PreContingencyNetworkResult preContingencyNetworkResult, boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, List limitReductions, List postContingencyResults, List operatorStrategyResults) { @@ -351,7 +351,7 @@ private void addPostContingencyAndOperatorStrategyResults(DcLoadFlowContext cont }); } - private static Map createTapPositionChangeElementsIndexByBranchId(Map> lfActionById, EquationSystem equationSystem) { + private static Map createTapPositionChangeElementsIndexByBranchId(Map lfActionById, EquationSystem equationSystem) { Map computedTapPositionChangeElements = lfActionById.values().stream() .filter(AbstractLfTapChangerAction.class::isInstance) .map(lfAction -> new ComputedTapPositionChangeElement(((AbstractLfTapChangerAction) lfAction).getChange(), equationSystem)) @@ -375,7 +375,7 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List actionsById = indexActionsById(actions); Set neededActions = new HashSet<>(actionsById.size()); Map> operatorStrategiesByContingencyId = indexOperatorStrategiesByContingencyId(propagatedContingencies, operatorStrategies, actionsById, neededActions); - Map> lfActionById = createLfActions(lfNetwork, neededActions, network, dcParameters.getNetworkParameters()); // only convert needed actions + Map lfActionById = createLfActions(lfNetwork, neededActions, network, dcParameters.getNetworkParameters()); // only convert needed actions OpenSecurityAnalysisParameters openSecurityAnalysisParameters = OpenSecurityAnalysisParameters.getOrDefault(securityAnalysisParameters); boolean createResultExtension = openSecurityAnalysisParameters.isCreateResultExtension(); @@ -434,7 +434,7 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List toPostContingencyStates = () -> calculatePostContingencyStates(context, connectivityBreakAnalysisResults.contingenciesStates(), workingContingencyStates, nonBreakingConnectivityContingency, connectivityBreakAnalysisResults.contingencyElementByBranch(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), reportNode); // function to compute post contingency and post operator strategy states - Function>, double[]> toPostContingencyAndOperatorStrategyStates = operatorStrategyLfActions -> calculatePostContingencyAndOperatorStrategyStates(context, connectivityBreakAnalysisResults.contingenciesStates(), workingContingencyStates, + Function, double[]> toPostContingencyAndOperatorStrategyStates = operatorStrategyLfActions -> calculatePostContingencyAndOperatorStrategyStates(context, connectivityBreakAnalysisResults.contingenciesStates(), workingContingencyStates, nonBreakingConnectivityContingency, connectivityBreakAnalysisResults.contingencyElementByBranch(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), operatorStrategyLfActions, tapPositionChangeElementsByBranchId, actionsStates, reportNode); // runnable to restore pre contingency states, after modifications applied to the lfNetwork @@ -459,7 +459,7 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List toPostContingencyStates = () -> calculatePostContingencyStatesForAContingencyBreakingConnectivity(connectivityAnalysisResult, context, connectivityBreakAnalysisResults.contingencyElementByBranch(), workingContingencyStates, connectivityBreakAnalysisResults.contingenciesStates(), reportNode); // function to compute post contingency and post operator strategy states - Function>, double[]> toPostContingencyAndOperatorStrategyStates = operatorStrategyLfActions -> calculatePostContingencyAndOperatorStrategyStatesForAContingencyBreakingConnectivity(connectivityAnalysisResult, context, + Function, double[]> toPostContingencyAndOperatorStrategyStates = operatorStrategyLfActions -> calculatePostContingencyAndOperatorStrategyStatesForAContingencyBreakingConnectivity(connectivityAnalysisResult, context, connectivityBreakAnalysisResults.contingencyElementByBranch(), workingContingencyStates, connectivityBreakAnalysisResults.contingenciesStates(), operatorStrategyLfActions, tapPositionChangeElementsByBranchId, actionsStates, reportNode); // runnable to restore pre contingency states, after modifications applied to the lfNetwork diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index 0052c6c1a7..dc3c1d2b29 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -22,7 +22,7 @@ import com.powsybl.openloadflow.ac.AcLoadFlowParameters; import com.powsybl.openloadflow.graph.NaiveGraphConnectivityFactory; import com.powsybl.openloadflow.network.*; -import com.powsybl.openloadflow.network.action.AbstractLfAction; +import com.powsybl.openloadflow.network.action.LfAction; import com.powsybl.openloadflow.network.action.LfActionUtils; import com.powsybl.openloadflow.network.action.LfSwitchAction; import com.powsybl.openloadflow.network.impl.LfNetworkList; @@ -69,7 +69,7 @@ void test() { topoConfig.getSwitchesToOpen().add(network.getSwitch("C")); try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), topoConfig, ReportNode.NO_OP)) { LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); - AbstractLfAction lfAction = LfActionUtils.createLfAction(switchAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + LfAction lfSwitchAction = LfActionUtils.createLfAction(switchAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); String loadId = "LOAD"; Contingency contingency = new Contingency(loadId, new LoadContingency("LD")); PropagatedContingencyCreationParameters creationParameters = new PropagatedContingencyCreationParameters() @@ -77,28 +77,27 @@ void test() { PropagatedContingency propagatedContingency = PropagatedContingency.createList(network, Collections.singletonList(contingency), new LfTopoConfig(), creationParameters).get(0); propagatedContingency.toLfContingency(lfNetwork).ifPresent(lfContingency -> { - lfAction.apply(lfNetwork, lfContingency, acParameters.getNetworkParameters(), lfNetwork.getConnectivity()); + lfSwitchAction.apply(lfNetwork, lfContingency, acParameters.getNetworkParameters()); assertTrue(lfNetwork.getBranchById("C").isDisabled()); - LfSwitchAction lfSwitchAction = (LfSwitchAction) lfAction; - assertEquals("C", lfSwitchAction.getDisabledBranch().getId()); - assertNull(lfSwitchAction.getEnabledBranch()); + assertEquals("C", ((LfSwitchAction) lfSwitchAction).getDisabledBranch().getId()); + assertNull(((LfSwitchAction) lfSwitchAction).getEnabledBranch()); }); - AbstractLfAction lfSwitchAction = LfActionUtils.createLfAction(new SwitchAction("switchAction", "S", true), + LfAction lfInvalidSwitchAction = LfActionUtils.createLfAction(new SwitchAction("switchAction", "S", true), network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); - AbstractLfAction lfTerminalsConnectionAction = LfActionUtils.createLfAction(new TerminalsConnectionAction("A line action", "x", true), + LfAction lfInvalidTerminalsConnectionAction = LfActionUtils.createLfAction(new TerminalsConnectionAction("A line action", "x", true), network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); - AbstractLfAction lfPhaseTapChangerTapPositionAction = LfActionUtils.createLfAction(new PhaseTapChangerTapPositionAction("A phase tap change action", "y", false, 3), + LfAction lfInvalidPhaseTapChangerTapPositionAction = LfActionUtils.createLfAction(new PhaseTapChangerTapPositionAction("A phase tap change action", "y", false, 3), network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); - assertFalse(lfSwitchAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())); - assertFalse(lfTerminalsConnectionAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())); - assertFalse(lfPhaseTapChangerTapPositionAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())); + assertFalse(lfInvalidSwitchAction.apply(lfNetwork, null, acParameters.getNetworkParameters())); + assertFalse(lfInvalidTerminalsConnectionAction.apply(lfNetwork, null, acParameters.getNetworkParameters())); + assertFalse(lfInvalidPhaseTapChangerTapPositionAction.apply(lfNetwork, null, acParameters.getNetworkParameters())); var lineAction = new TerminalsConnectionAction("A line action", "L1", ThreeSides.ONE, false); - AbstractLfAction lfTerminalAction = LfActionUtils.createLfAction(lineAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + LfAction lfTerminalAction = LfActionUtils.createLfAction(lineAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); assertEquals("Terminals connection action: only open or close branch at both sides is supported yet.", - assertThrows(UnsupportedOperationException.class, () -> lfTerminalAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())).getMessage()); + assertThrows(UnsupportedOperationException.class, () -> lfTerminalAction.apply(lfNetwork, null, acParameters.getNetworkParameters())).getMessage()); } } @@ -116,8 +115,8 @@ void testUnsupportedGeneratorAction() { new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new NaiveGraphConnectivityFactory<>(LfBus::getNum), true, false); try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), new LfTopoConfig(), ReportNode.NO_OP)) { LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); - AbstractLfAction lfGeneratorAction = LfActionUtils.createLfAction(generatorAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); - UnsupportedOperationException e = assertThrows(UnsupportedOperationException.class, () -> lfGeneratorAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())); + LfAction lfGeneratorAction = LfActionUtils.createLfAction(generatorAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + UnsupportedOperationException e = assertThrows(UnsupportedOperationException.class, () -> lfGeneratorAction.apply(lfNetwork, null, acParameters.getNetworkParameters())); assertEquals("Generator action on G : configuration not supported yet.", e.getMessage()); } } @@ -141,8 +140,8 @@ void testGeneratorActionWithRelativeActivePowerValue() { new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new NaiveGraphConnectivityFactory<>(LfBus::getNum), true, false); try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), new LfTopoConfig(), ReportNode.NO_OP)) { LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); - AbstractLfAction lfAction = LfActionUtils.createLfAction(generatorAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); - lfAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity()); + LfAction lfAction = LfActionUtils.createLfAction(generatorAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + lfAction.apply(lfNetwork, null, acParameters.getNetworkParameters()); assertEquals(newTargetP / PerUnit.SB, lfNetwork.getGeneratorById(genId).getTargetP()); assertEquals(genId, generatorAction.getGeneratorId()); assertEquals(oldTargetP, network.getGenerator(genId).getTargetP()); @@ -170,8 +169,8 @@ void testHvdcAction() { new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new NaiveGraphConnectivityFactory<>(LfBus::getNum), true, false); try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), new LfTopoConfig(), ReportNode.NO_OP)) { LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); - AbstractLfAction lfAction = LfActionUtils.createLfAction(hvdcAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); - UnsupportedOperationException e = assertThrows(UnsupportedOperationException.class, () -> lfAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())); + LfAction lfAction = LfActionUtils.createLfAction(hvdcAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + UnsupportedOperationException e = assertThrows(UnsupportedOperationException.class, () -> lfAction.apply(lfNetwork, null, acParameters.getNetworkParameters())); assertEquals("Hvdc action: line is already in AC emulation, not supported yet.", e.getMessage()); } } @@ -201,11 +200,11 @@ void testHvdcAction2() { try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), new LfTopoConfig(), ReportNode.NO_OP)) { LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); - AbstractLfAction lfAction = LfActionUtils.createLfAction(hvdcAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); - assertFalse(lfAction.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())); + LfAction lfHvdcAction = LfActionUtils.createLfAction(hvdcAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + assertFalse(lfHvdcAction.apply(lfNetwork, null, acParameters.getNetworkParameters())); - AbstractLfAction lfAction2 = LfActionUtils.createLfAction(hvdcAction2, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); - assertFalse(lfAction2.apply(lfNetwork, null, acParameters.getNetworkParameters(), lfNetwork.getConnectivity())); + LfAction lfHvdcAction2 = LfActionUtils.createLfAction(hvdcAction2, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + assertFalse(lfHvdcAction2.apply(lfNetwork, null, acParameters.getNetworkParameters())); } } } From 7e8f94510b1a0c82774bd4cac26658ce18b4fffb Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Thu, 16 Jan 2025 17:02:50 +0100 Subject: [PATCH 05/16] Clean. Signed-off-by: Bertrand Rix --- .../powsybl/openloadflow/network/action/LfAction.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfAction.java index 40cd17694a..b4c014243c 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfAction.java @@ -1,7 +1,17 @@ +/** + * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * 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/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.network.action; import com.powsybl.openloadflow.network.*; +/** + * @author Bertrand Rix {@literal } + */ public interface LfAction { String getId(); From ffc79819a06e52d085373e9edc31f5243ad6f648 Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Thu, 16 Jan 2025 17:33:22 +0100 Subject: [PATCH 06/16] Basic test for LfAreaInterchangeTargetAction. Signed-off-by: Bertrand Rix --- .../action/LfAreaInterchangeTargetAction.java | 9 +++- .../powsybl/openloadflow/sa/LfActionTest.java | 44 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java index cb7fd65035..6acd9dc86a 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java @@ -9,19 +9,26 @@ import com.powsybl.action.AreaInterchangeTargetAction; import com.powsybl.openloadflow.network.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author Bertrand Rix {@literal } */ public class LfAreaInterchangeTargetAction extends AbstractLfAction { + private static final Logger LOGGER = LoggerFactory.getLogger(AreaInterchangeTargetAction.class); + public LfAreaInterchangeTargetAction(String id, AreaInterchangeTargetAction action) { super(id, action); } @Override public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { - LfArea area = network.getAreaById(action.getId()); + if (!networkParameters.isAreaInterchangeControl()) { + LOGGER.warn("AreaInterchangeTargetAction action {} : area interchange control is disabled", action.getId()); + } + LfArea area = network.getAreaById(action.getAreaId()); if (area != null) { area.setInterchangeTarget(action.getInterchangeTarget()); return true; diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index dc3c1d2b29..60fbd9c44d 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -207,4 +207,48 @@ void testHvdcAction2() { assertFalse(lfHvdcAction2.apply(lfNetwork, null, acParameters.getNetworkParameters())); } } + + @Test + void testLfAreaInterchangeTargetAction() { + + AreaInterchangeTargetAction targetAction = new AreaInterchangeTargetActionBuilder() + .withId("action") + .withAreaId("a1") + .withTarget(20.0) + .build(); + + AreaInterchangeTargetAction invalidTargetAction = new AreaInterchangeTargetActionBuilder() + .withId("action") + .withAreaId("DUMMMY") + .withTarget(20.0) + .build(); + + Network network = MultiAreaNetworkFactory.createTwoAreasWithXNode(); + + var matrixFactory = new DenseMatrixFactory(); + + // With area interchange target control enabled + AcLoadFlowParameters acParameters = OpenLoadFlowParameters.createAcParameters(network, + new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new NaiveGraphConnectivityFactory<>(LfBus::getNum), true, false); + acParameters.getNetworkParameters().setAreaInterchangeControl(true); + try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), new LfTopoConfig(), ReportNode.NO_OP)) { + LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); + + LfAction lfAreaTargetAction = LfActionUtils.createLfAction(targetAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + assertTrue(lfAreaTargetAction.apply(lfNetwork, null, acParameters.getNetworkParameters())); + + LfAction lfAreaTargetAction2 = LfActionUtils.createLfAction(invalidTargetAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + assertFalse(lfAreaTargetAction2.apply(lfNetwork, null, acParameters.getNetworkParameters())); + } + + // With area interchange target control disabled + acParameters.getNetworkParameters().setAreaInterchangeControl(false); + try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), new LfTopoConfig(), ReportNode.NO_OP)) { + LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); + acParameters.getNetworkParameters().setAreaInterchangeControl(false); + + LfAction lfAreaTargetAction = LfActionUtils.createLfAction(targetAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + assertFalse(lfAreaTargetAction.apply(lfNetwork, null, acParameters.getNetworkParameters())); + } + } } From 517baf6a7194eba70a4812270a23e79eab5d4cb4 Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Fri, 17 Jan 2025 09:36:24 +0100 Subject: [PATCH 07/16] Rework copyright and author to reflect history. Signed-off-by: Bertrand Rix --- .../openloadflow/network/action/AbstractLfBranchAction.java | 3 +++ .../network/action/AbstractLfTapChangerAction.java | 3 +++ .../com/powsybl/openloadflow/network/action/LfActionUtils.java | 3 +++ .../powsybl/openloadflow/network/action/LfGeneratorAction.java | 3 +++ .../com/powsybl/openloadflow/network/action/LfHvdcAction.java | 3 +++ .../com/powsybl/openloadflow/network/action/LfLoadAction.java | 3 +++ .../openloadflow/network/action/LfPhaseTapChangerAction.java | 3 +++ .../openloadflow/network/action/LfRatioTapChangerAction.java | 3 +++ .../network/action/LfShuntCompensatorPositionAction.java | 3 +++ .../powsybl/openloadflow/network/action/LfSwitchAction.java | 3 +++ .../network/action/LfTerminalsConnectionAction.java | 3 +++ 11 files changed, 33 insertions(+) diff --git a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java index dc973c4918..44a0ffa4f9 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfBranchAction.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * Copyright (c) 2022, 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/. @@ -16,6 +17,8 @@ /** * @author Bertrand Rix {@literal } + * @author Anne Tilloy {@literal } + * @author Jean-Luc Bouchot {@literal } */ public abstract class AbstractLfBranchAction extends AbstractLfAction { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfTapChangerAction.java b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfTapChangerAction.java index 4c95a7fec4..e885b8eaff 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfTapChangerAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/AbstractLfTapChangerAction.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * Copyright (c) 2022, 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/. @@ -13,6 +14,8 @@ /** * @author Bertrand Rix {@literal } + * @author Anne Tilloy {@literal } + * @author Jean-Luc Bouchot {@literal } */ public abstract class AbstractLfTapChangerAction extends AbstractLfAction { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java index 1fcaeeb0bf..b1feffae18 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * Copyright (c) 2022, 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/. @@ -18,6 +19,8 @@ /** * @author Bertrand Rix {@literal } + * @author Anne Tilloy {@literal } + * @author Jean-Luc Bouchot {@literal } */ public final class LfActionUtils { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java index 74c8085604..f811684eab 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfGeneratorAction.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * Copyright (c) 2022, 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/. @@ -16,6 +17,8 @@ /** * @author Bertrand Rix {@literal } + * @author Anne Tilloy {@literal } + * @author Jean-Luc Bouchot {@literal } */ public class LfGeneratorAction extends AbstractLfAction { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java index e3ba3e4b70..bfad88aea0 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfHvdcAction.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * Copyright (c) 2022, 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/. @@ -16,6 +17,8 @@ /** * @author Bertrand Rix {@literal } + * @author Anne Tilloy {@literal } + * @author Jean-Luc Bouchot {@literal } */ public class LfHvdcAction extends AbstractLfAction { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java index 0f0d4502dd..62ba0334ab 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfLoadAction.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * Copyright (c) 2022, 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/. @@ -17,6 +18,8 @@ /** * @author Bertrand Rix {@literal } + * @author Anne Tilloy {@literal } + * @author Jean-Luc Bouchot {@literal } */ public class LfLoadAction extends AbstractLfAction { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java index b2396d587f..697fb07dc3 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * Copyright (c) 2022, 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/. @@ -14,6 +15,8 @@ /** * @author Bertrand Rix {@literal } + * @author Anne Tilloy {@literal } + * @author Jean-Luc Bouchot {@literal } */ public class LfPhaseTapChangerAction extends AbstractLfTapChangerAction { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java index c59a024ef3..2ae787b0db 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * Copyright (c) 2022, 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/. @@ -14,6 +15,8 @@ /** * @author Bertrand Rix {@literal } + * @author Anne Tilloy {@literal } + * @author Jean-Luc Bouchot {@literal } */ public class LfRatioTapChangerAction extends AbstractLfTapChangerAction { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java index c63ee90c46..994ab55d46 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfShuntCompensatorPositionAction.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * Copyright (c) 2022, 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/. @@ -15,6 +16,8 @@ /** * @author Bertrand Rix {@literal } + * @author Anne Tilloy {@literal } + * @author Jean-Luc Bouchot {@literal } */ public class LfShuntCompensatorPositionAction extends AbstractLfAction { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java index eb4b26d152..b3d59b69e8 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * Copyright (c) 2022, 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/. @@ -15,6 +16,8 @@ /** * @author Bertrand Rix {@literal } + * @author Anne Tilloy {@literal } + * @author Jean-Luc Bouchot {@literal } */ public class LfSwitchAction extends AbstractLfBranchAction { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java index 76ccaa9030..771024d26a 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * Copyright (c) 2022, 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/. @@ -15,6 +16,8 @@ /** * @author Bertrand Rix {@literal } + * @author Anne Tilloy {@literal } + * @author Jean-Luc Bouchot {@literal } */ public class LfTerminalsConnectionAction extends AbstractLfBranchAction { From 33f1a453c86f04ca3d4093a21eba7b067f432909 Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Fri, 17 Jan 2025 14:54:06 +0100 Subject: [PATCH 08/16] Add test for AreaInterchangeTargetAction usage within the security analysis. Signed-off-by: Bertrand Rix --- .../action/LfAreaInterchangeTargetAction.java | 3 +- .../sa/AbstractSecurityAnalysis.java | 8 +++ .../OpenSecurityAnalysisWithActionsTest.java | 57 +++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java index 6acd9dc86a..cf80525c7e 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java @@ -9,6 +9,7 @@ import com.powsybl.action.AreaInterchangeTargetAction; import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.util.PerUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,7 +31,7 @@ public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkPara } LfArea area = network.getAreaById(action.getAreaId()); if (area != null) { - area.setInterchangeTarget(action.getInterchangeTarget()); + area.setInterchangeTarget(action.getInterchangeTarget() / PerUnit.SB); return true; } return false; diff --git a/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java index 59f63c5895..a434cbfa1f 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java @@ -452,6 +452,14 @@ protected static void checkActions(Network network, List actions) { break; } + case AreaInterchangeTargetAction.NAME: { + AreaInterchangeTargetAction areaInterchangeAction = (AreaInterchangeTargetAction) action; + if (network.getArea(areaInterchangeAction.getAreaId()) == null) { + throw new PowsyblException("Area '" + areaInterchangeAction.getAreaId() + "' not found"); + } + break; + } + default: throw new UnsupportedOperationException("Unsupported action type: " + action.getType()); } diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisWithActionsTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisWithActionsTest.java index ba9f4c15ba..cbd00225c2 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisWithActionsTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisWithActionsTest.java @@ -1671,4 +1671,61 @@ void testOperatorStrategyNoMoreBusVoltageControlled() throws IOException { assertReportEquals("/saReportOperatorStrategyNoVoltageControl.txt", reportNode); } + + @Test + void testAreaInterchangeTargetAction() { + + Network network = MultiAreaNetworkFactory.createTwoAreasWithTwoXNodes(); + + Area area1 = network.getArea("a1"); + Area area2 = network.getArea("a2"); + area1.setInterchangeTarget(-15.0); + area2.setInterchangeTarget(15.0); + + Contingency lineContingency = new Contingency("l23_A1_1", new BranchContingency("l23_A1_1")); + List contingencies = List.of(lineContingency); + AreaInterchangeTargetAction actionArea1 = new AreaInterchangeTargetActionBuilder() + .withId("ActionArea1") + .withAreaId("a1") + .withTarget(-10.0) + .build(); + + AreaInterchangeTargetAction actionArea2 = new AreaInterchangeTargetActionBuilder() + .withId("ActionArea2") + .withAreaId("a2") + .withTarget(10.0) + .build(); + + List actions = List.of(actionArea1, actionArea2); + List operatorStrategies = List.of(new OperatorStrategy("strategy1", + ContingencyContext.specificContingency(lineContingency.getId()), new TrueCondition(), List.of(actionArea1.getId(), actionArea2.getId()))); + ReportNode reportNode = ReportNode.newRootReportNode() + .withMessageTemplate("testSaReport", "Test report of security analysis") + .build(); + + double areaInterchangePMaxMismatch = 1e-3; + + SecurityAnalysisParameters parameters = new SecurityAnalysisParameters(); + OpenLoadFlowParameters.create(parameters.getLoadFlowParameters()) + .setAreaInterchangeControl(true) + .setSlackBusPMaxMismatch(1e-3) + .setAreaInterchangePMaxMismatch(areaInterchangePMaxMismatch); + + List monitors = createAllBranchesMonitors(network); + SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, parameters, operatorStrategies, actions, reportNode); + + // Respect of targets in the base case (at 15.0) + assertEquals(15.0, result.getPreContingencyResult().getNetworkResult().getBranchResult("l23_A1").getP1(), areaInterchangePMaxMismatch); + assertEquals(-15.0, result.getPreContingencyResult().getNetworkResult().getBranchResult("l23_A2").getP2(), areaInterchangePMaxMismatch); + + // Respect of targets in post contingency state (at 15.0) + assertEquals(15.0, result.getPostContingencyResults().get(0).getNetworkResult().getBranchResult("l23_A1").getP1(), areaInterchangePMaxMismatch); + assertEquals(-15.0, result.getPostContingencyResults().get(0).getNetworkResult().getBranchResult("l23_A2").getP2(), areaInterchangePMaxMismatch); + + // Respect of targets after remedial actions (now at 10.0) + assertNotNull(result.getOperatorStrategyResults()); + assertEquals(10.0, result.getOperatorStrategyResults().get(0).getNetworkResult().getBranchResult("l23_A1").getP1(), areaInterchangePMaxMismatch); + assertEquals(-10.0, result.getOperatorStrategyResults().get(0).getNetworkResult().getBranchResult("l23_A2").getP2(), areaInterchangePMaxMismatch); + + } } From bc36fa5dc9c50b931cf2cca07a0d3b9e62d36e7f Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Fri, 17 Jan 2025 15:16:29 +0100 Subject: [PATCH 09/16] Fix sonar issue and use apply return boolean to warn about potential failure of applying an action. Signed-off-by: Bertrand Rix --- .../network/action/LfActionUtils.java | 16 ++++++++-- .../action/LfAreaInterchangeTargetAction.java | 2 +- .../powsybl/openloadflow/sa/LfActionTest.java | 29 ++++++++++--------- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java index b1feffae18..da1b6dba0d 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java @@ -12,6 +12,8 @@ import com.powsybl.iidm.network.Network; import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.openloadflow.network.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.*; @@ -24,6 +26,8 @@ */ public final class LfActionUtils { + private static final Logger LOGGER = LoggerFactory.getLogger(LfActionUtils.class); + private LfActionUtils() { } @@ -63,7 +67,11 @@ public static void applyListOfActions(List actions, LfNetwork network, // then process remaining changes of actions actions.stream() .filter(action -> !(action instanceof AbstractLfBranchAction)) - .forEach(action -> action.apply(network, contingency, networkParameters)); + .forEach(action -> { + if (!action.apply(network, contingency, networkParameters)) { + LOGGER.warn("Action {} : may not have been applied successfully.", action.getId()); + } + }); } private static void updateConnectivity(List branchActions, LfNetwork network, LfContingency contingency) { @@ -76,7 +84,11 @@ private static void updateConnectivity(List branchActions, LfNetwork n // update connectivity according to post action state connectivity.startTemporaryChanges(); - branchActions.forEach(action -> ((AbstractLfBranchAction) action).applyOnConnectivity(network, connectivity)); + branchActions.forEach(action -> { + if (((AbstractLfBranchAction) action).applyOnConnectivity(network, connectivity)) { + LOGGER.warn("Action {} : may not have been applied successfully.", action.getId()); + } + }); updateBusesAndBranchStatus(connectivity); diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java index cf80525c7e..fe9e42ed12 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java @@ -18,7 +18,7 @@ */ public class LfAreaInterchangeTargetAction extends AbstractLfAction { - private static final Logger LOGGER = LoggerFactory.getLogger(AreaInterchangeTargetAction.class); + private static final Logger LOGGER = LoggerFactory.getLogger(LfAreaInterchangeTargetAction.class); public LfAreaInterchangeTargetAction(String id, AreaInterchangeTargetAction action) { super(id, action); diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index 60fbd9c44d..04656e44eb 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -66,10 +66,11 @@ void test() { AcLoadFlowParameters acParameters = OpenLoadFlowParameters.createAcParameters(network, loadFlowParameters, new OpenLoadFlowParameters(), matrixFactory, new NaiveGraphConnectivityFactory<>(LfBus::getNum), true, false); LfTopoConfig topoConfig = new LfTopoConfig(); + LfNetworkParameters networkParameters = acParameters.getNetworkParameters(); topoConfig.getSwitchesToOpen().add(network.getSwitch("C")); - try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), topoConfig, ReportNode.NO_OP)) { + try (LfNetworkList lfNetworks = Networks.load(network, networkParameters, topoConfig, ReportNode.NO_OP)) { LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); - LfAction lfSwitchAction = LfActionUtils.createLfAction(switchAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + LfAction lfSwitchAction = LfActionUtils.createLfAction(switchAction, network, networkParameters.isBreakers(), lfNetwork); String loadId = "LOAD"; Contingency contingency = new Contingency(loadId, new LoadContingency("LD")); PropagatedContingencyCreationParameters creationParameters = new PropagatedContingencyCreationParameters() @@ -77,27 +78,27 @@ void test() { PropagatedContingency propagatedContingency = PropagatedContingency.createList(network, Collections.singletonList(contingency), new LfTopoConfig(), creationParameters).get(0); propagatedContingency.toLfContingency(lfNetwork).ifPresent(lfContingency -> { - lfSwitchAction.apply(lfNetwork, lfContingency, acParameters.getNetworkParameters()); + lfSwitchAction.apply(lfNetwork, lfContingency, networkParameters); assertTrue(lfNetwork.getBranchById("C").isDisabled()); assertEquals("C", ((LfSwitchAction) lfSwitchAction).getDisabledBranch().getId()); assertNull(((LfSwitchAction) lfSwitchAction).getEnabledBranch()); }); LfAction lfInvalidSwitchAction = LfActionUtils.createLfAction(new SwitchAction("switchAction", "S", true), - network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + network, networkParameters.isBreakers(), lfNetwork); LfAction lfInvalidTerminalsConnectionAction = LfActionUtils.createLfAction(new TerminalsConnectionAction("A line action", "x", true), - network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + network, networkParameters.isBreakers(), lfNetwork); LfAction lfInvalidPhaseTapChangerTapPositionAction = LfActionUtils.createLfAction(new PhaseTapChangerTapPositionAction("A phase tap change action", "y", false, 3), - network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + network, networkParameters.isBreakers(), lfNetwork); - assertFalse(lfInvalidSwitchAction.apply(lfNetwork, null, acParameters.getNetworkParameters())); - assertFalse(lfInvalidTerminalsConnectionAction.apply(lfNetwork, null, acParameters.getNetworkParameters())); - assertFalse(lfInvalidPhaseTapChangerTapPositionAction.apply(lfNetwork, null, acParameters.getNetworkParameters())); + assertFalse(lfInvalidSwitchAction.apply(lfNetwork, null, networkParameters)); + assertFalse(lfInvalidTerminalsConnectionAction.apply(lfNetwork, null, networkParameters)); + assertFalse(lfInvalidPhaseTapChangerTapPositionAction.apply(lfNetwork, null, networkParameters)); var lineAction = new TerminalsConnectionAction("A line action", "L1", ThreeSides.ONE, false); - LfAction lfTerminalAction = LfActionUtils.createLfAction(lineAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); + LfAction lfTerminalAction = LfActionUtils.createLfAction(lineAction, network, networkParameters.isBreakers(), lfNetwork); assertEquals("Terminals connection action: only open or close branch at both sides is supported yet.", - assertThrows(UnsupportedOperationException.class, () -> lfTerminalAction.apply(lfNetwork, null, acParameters.getNetworkParameters())).getMessage()); + assertThrows(UnsupportedOperationException.class, () -> lfTerminalAction.apply(lfNetwork, null, networkParameters)).getMessage()); } } @@ -113,10 +114,11 @@ void testUnsupportedGeneratorAction() { var matrixFactory = new DenseMatrixFactory(); AcLoadFlowParameters acParameters = OpenLoadFlowParameters.createAcParameters(network, new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new NaiveGraphConnectivityFactory<>(LfBus::getNum), true, false); + LfNetworkParameters networkParameters = acParameters.getNetworkParameters(); try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), new LfTopoConfig(), ReportNode.NO_OP)) { LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); LfAction lfGeneratorAction = LfActionUtils.createLfAction(generatorAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); - UnsupportedOperationException e = assertThrows(UnsupportedOperationException.class, () -> lfGeneratorAction.apply(lfNetwork, null, acParameters.getNetworkParameters())); + UnsupportedOperationException e = assertThrows(UnsupportedOperationException.class, () -> lfGeneratorAction.apply(lfNetwork, null, networkParameters)); assertEquals("Generator action on G : configuration not supported yet.", e.getMessage()); } } @@ -167,10 +169,11 @@ void testHvdcAction() { var matrixFactory = new DenseMatrixFactory(); AcLoadFlowParameters acParameters = OpenLoadFlowParameters.createAcParameters(network, new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new NaiveGraphConnectivityFactory<>(LfBus::getNum), true, false); + LfNetworkParameters networkParameters = acParameters.getNetworkParameters(); try (LfNetworkList lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), new LfTopoConfig(), ReportNode.NO_OP)) { LfNetwork lfNetwork = lfNetworks.getLargest().orElseThrow(); LfAction lfAction = LfActionUtils.createLfAction(hvdcAction, network, acParameters.getNetworkParameters().isBreakers(), lfNetwork); - UnsupportedOperationException e = assertThrows(UnsupportedOperationException.class, () -> lfAction.apply(lfNetwork, null, acParameters.getNetworkParameters())); + UnsupportedOperationException e = assertThrows(UnsupportedOperationException.class, () -> lfAction.apply(lfNetwork, null, networkParameters)); assertEquals("Hvdc action: line is already in AC emulation, not supported yet.", e.getMessage()); } } From 2f71d8a33c0f1840c6a6214f48551671746f7324 Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Fri, 17 Jan 2025 15:17:12 +0100 Subject: [PATCH 10/16] Oops. Signed-off-by: Bertrand Rix --- .../com/powsybl/openloadflow/network/action/LfActionUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java index da1b6dba0d..124d0c20fe 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java @@ -85,7 +85,7 @@ private static void updateConnectivity(List branchActions, LfNetwork n connectivity.startTemporaryChanges(); branchActions.forEach(action -> { - if (((AbstractLfBranchAction) action).applyOnConnectivity(network, connectivity)) { + if (!((AbstractLfBranchAction) action).applyOnConnectivity(network, connectivity)) { LOGGER.warn("Action {} : may not have been applied successfully.", action.getId()); } }); From e5db242f66915b36d3e0fe500da243f515736db8 Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Tue, 21 Jan 2025 11:22:12 +0100 Subject: [PATCH 11/16] Ref to new supported action. Signed-off-by: Bertrand Rix --- docs/security/inputs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/security/inputs.md b/docs/security/inputs.md index ece9e22ee2..2c5704345c 100644 --- a/docs/security/inputs.md +++ b/docs/security/inputs.md @@ -14,5 +14,6 @@ With Open Load Flow only the following remedial actions are currently implemente - `ShuntCompensatorPositionAction` - `GeneratorAction` - `HvdcAction` +- `AreaInterchangeTargetAction` Note: Some limitations in the use of these actions exist, please read the documentation about the [security analysis specific parameters](parameters). From 91da360fa069b50fd3192e267cd93655f5a3c9fa Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Tue, 21 Jan 2025 14:23:37 +0100 Subject: [PATCH 12/16] Remove space. Signed-off-by: Bertrand Rix --- .../powsybl/openloadflow/network/action/LfActionUtils.java | 4 ++-- .../network/action/LfAreaInterchangeTargetAction.java | 2 +- .../powsybl/openloadflow/network/action/LfSwitchAction.java | 2 +- .../network/action/LfTerminalsConnectionAction.java | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java index 124d0c20fe..b75dc8893e 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java @@ -69,7 +69,7 @@ public static void applyListOfActions(List actions, LfNetwork network, .filter(action -> !(action instanceof AbstractLfBranchAction)) .forEach(action -> { if (!action.apply(network, contingency, networkParameters)) { - LOGGER.warn("Action {} : may not have been applied successfully.", action.getId()); + LOGGER.warn("Action {}: may not have been applied successfully.", action.getId()); } }); } @@ -86,7 +86,7 @@ private static void updateConnectivity(List branchActions, LfNetwork n branchActions.forEach(action -> { if (!((AbstractLfBranchAction) action).applyOnConnectivity(network, connectivity)) { - LOGGER.warn("Action {} : may not have been applied successfully.", action.getId()); + LOGGER.warn("Action {}: may not have been applied successfully.", action.getId()); } }); diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java index fe9e42ed12..4ef627f945 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfAreaInterchangeTargetAction.java @@ -27,7 +27,7 @@ public LfAreaInterchangeTargetAction(String id, AreaInterchangeTargetAction acti @Override public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { if (!networkParameters.isAreaInterchangeControl()) { - LOGGER.warn("AreaInterchangeTargetAction action {} : area interchange control is disabled", action.getId()); + LOGGER.warn("AreaInterchangeTargetAction action {}: area interchange control is disabled", action.getId()); } LfArea area = network.getAreaById(action.getAreaId()); if (area != null) { diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java index b3d59b69e8..d3c0c95dc8 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfSwitchAction.java @@ -38,7 +38,7 @@ boolean findEnabledDisabledBranches(LfNetwork lfNetwork) { } return true; } else { - LOGGER.warn("Switch action {} : branch matching switch id {} not found", action.getId(), action.getSwitchId()); + LOGGER.warn("Switch action {}: branch matching switch id {} not found", action.getId(), action.getSwitchId()); return false; } } diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java index 771024d26a..13b8453669 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfTerminalsConnectionAction.java @@ -42,7 +42,7 @@ boolean findEnabledDisabledBranches(LfNetwork lfNetwork) { } return true; } else { - LOGGER.warn("TerminalsConnectionAction action {} : branch matching element id {} not found", action.getId(), action.getElementId()); + LOGGER.warn("TerminalsConnectionAction action {}: branch matching element id {} not found", action.getId(), action.getElementId()); return false; } } From 579f2e995c730c14f597c9374d388fc401980d96 Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Tue, 21 Jan 2025 15:27:30 +0100 Subject: [PATCH 13/16] PiModel already tested at construction. Signed-off-by: Bertrand Rix --- .../network/action/LfPhaseTapChangerAction.java | 8 ++------ .../network/action/LfRatioTapChangerAction.java | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java index 697fb07dc3..3361706d71 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfPhaseTapChangerAction.java @@ -32,12 +32,8 @@ public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkPara if (branch.getPhaseControl().isPresent()) { LOGGER.warn("Phase tap changer tap position action: phase control is present on the tap changer, tap position could be overriden."); } - if (branch.getPiModel() instanceof SimplePiModel) { - throw new UnsupportedOperationException("Tap position action: only one tap in branch " + branch.getId()); - } else { - branch.getPiModel().setTapPosition(this.change.getNewTapPosition()); - return true; - } + branch.getPiModel().setTapPosition(this.change.getNewTapPosition()); + return true; } return false; } diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java b/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java index 2ae787b0db..442fd631bb 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfRatioTapChangerAction.java @@ -32,12 +32,8 @@ public boolean apply(LfNetwork network, LfContingency contingency, LfNetworkPara if (branch.getVoltageControl().isPresent()) { LOGGER.warn("Ratio tap changer tap position action: voltage control is present on the tap changer, tap position could be overriden."); } - if (branch.getPiModel() instanceof SimplePiModel) { - throw new UnsupportedOperationException("Tap position action: only one tap in branch " + branch.getId()); - } else { - branch.getPiModel().setTapPosition(this.change.getNewTapPosition()); - return true; - } + branch.getPiModel().setTapPosition(this.change.getNewTapPosition()); + return true; } return false; } From 9eb11690d6b86d3083ccc57e6d2cdc9ac8aa02a8 Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Mon, 27 Jan 2025 14:24:36 +0100 Subject: [PATCH 14/16] Report instead of warn the failure of application of an action. Signed-off-by: Bertrand Rix --- .../network/action/LfActionUtils.java | 23 +++++++++++++++---- .../sa/AbstractSecurityAnalysis.java | 2 +- .../sa/WoodburyDcSecurityAnalysis.java | 2 +- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java index b75dc8893e..94e6eadd5b 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java @@ -9,6 +9,7 @@ package com.powsybl.openloadflow.network.action; import com.powsybl.action.*; +import com.powsybl.commons.report.ReportNode; import com.powsybl.iidm.network.Network; import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.openloadflow.network.*; @@ -28,6 +29,10 @@ public final class LfActionUtils { private static final Logger LOGGER = LoggerFactory.getLogger(LfActionUtils.class); + private static final String ACTION_ID = "actionId"; + + private static final String CONTINGENCY_ID = "contingencyId"; + private LfActionUtils() { } @@ -54,7 +59,7 @@ public static LfAction createLfAction(Action action, Network network, boolean br }; } - public static void applyListOfActions(List actions, LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters) { + public static void applyListOfActions(List actions, LfNetwork network, LfContingency contingency, LfNetworkParameters networkParameters, ReportNode node) { Objects.requireNonNull(actions); Objects.requireNonNull(network); @@ -62,19 +67,19 @@ public static void applyListOfActions(List actions, LfNetwork network, List branchActions = actions.stream() .filter(action -> action instanceof AbstractLfBranchAction) .toList(); - updateConnectivity(branchActions, network, contingency); + updateConnectivity(branchActions, network, contingency, node); // then process remaining changes of actions actions.stream() .filter(action -> !(action instanceof AbstractLfBranchAction)) .forEach(action -> { if (!action.apply(network, contingency, networkParameters)) { - LOGGER.warn("Action {}: may not have been applied successfully.", action.getId()); + reportActionApplicationFailure(action.getId(), contingency.getId(), node); } }); } - private static void updateConnectivity(List branchActions, LfNetwork network, LfContingency contingency) { + private static void updateConnectivity(List branchActions, LfNetwork network, LfContingency contingency, ReportNode node) { GraphConnectivity connectivity = network.getConnectivity(); // re-update connectivity according to post contingency state (revert after LfContingency apply) @@ -86,7 +91,7 @@ private static void updateConnectivity(List branchActions, LfNetwork n branchActions.forEach(action -> { if (!((AbstractLfBranchAction) action).applyOnConnectivity(network, connectivity)) { - LOGGER.warn("Action {}: may not have been applied successfully.", action.getId()); + reportActionApplicationFailure(action.getId(), contingency.getId(), node); } }); @@ -97,4 +102,12 @@ private static void updateConnectivity(List branchActions, LfNetwork n connectivity.undoTemporaryChanges(); } + private static void reportActionApplicationFailure(String actionId, String contingencyId, ReportNode node) { + node.newReportNode() + .withMessageTemplate("LfActionUtils", "Action '${actionId}': may not have been applied successfully on contingency '${contingencyId}'") + .withUntypedValue(ACTION_ID, actionId) + .withUntypedValue(CONTINGENCY_ID, contingencyId) + .add(); + } + } diff --git a/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java index a434cbfa1f..e5e37b814d 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java @@ -824,7 +824,7 @@ protected OperatorStrategyResult runActionSimulation(LfNetwork network, C contex .filter(Objects::nonNull) .toList(); - LfActionUtils.applyListOfActions(operatorStrategyLfActions, network, contingency, networkParameters); + LfActionUtils.applyListOfActions(operatorStrategyLfActions, network, contingency, networkParameters, reportNode); Stopwatch stopwatch = Stopwatch.createStarted(); diff --git a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java index 66258effa5..64cbd290d4 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java @@ -266,7 +266,7 @@ private OperatorStrategyResult computeOperatorStrategyResultFromPostContingencyA // apply modifications to compute results lfContingency.apply(loadFlowContext.getParameters().getBalanceType()); - LfActionUtils.applyListOfActions(operatorStrategyLfActions, lfNetwork, lfContingency, loadFlowContext.getParameters().getNetworkParameters()); + LfActionUtils.applyListOfActions(operatorStrategyLfActions, lfNetwork, lfContingency, loadFlowContext.getParameters().getNetworkParameters(), reportNode); // update network result var postActionsNetworkResult = new PreContingencyNetworkResult(lfNetwork, monitorIndex, createResultExtension); From bed482089d7cc6d465cc2564994fbb767a362133 Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Mon, 27 Jan 2025 14:28:15 +0100 Subject: [PATCH 15/16] Unused logger. Signed-off-by: Bertrand Rix --- .../com/powsybl/openloadflow/network/action/LfActionUtils.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java index 94e6eadd5b..7cce155c43 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java @@ -27,8 +27,6 @@ */ public final class LfActionUtils { - private static final Logger LOGGER = LoggerFactory.getLogger(LfActionUtils.class); - private static final String ACTION_ID = "actionId"; private static final String CONTINGENCY_ID = "contingencyId"; From 3ec6d4659289ec5a03ba3f4efd6837be0505a43c Mon Sep 17 00:00:00 2001 From: Bertrand Rix Date: Mon, 27 Jan 2025 14:40:57 +0100 Subject: [PATCH 16/16] Clean. Signed-off-by: Bertrand Rix --- .../com/powsybl/openloadflow/network/action/LfActionUtils.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java index 7cce155c43..05b984e0b5 100644 --- a/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java +++ b/src/main/java/com/powsybl/openloadflow/network/action/LfActionUtils.java @@ -13,8 +13,6 @@ import com.powsybl.iidm.network.Network; import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.openloadflow.network.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.*;