From b01b64262b2e4fbd1580c3538bbc2cdd03104d3b Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Wed, 23 Feb 2022 14:37:34 +0100 Subject: [PATCH] Remove EquationUtil (#447) Signed-off-by: Geoffroy Jamgotchian --- .../ac/equations/AcEquationSystem.java | 177 ++++++++++++------ .../ac/equations/AcEquationSystemUpdater.java | 77 ++++---- .../openloadflow/equations/EquationUtil.java | 108 ----------- .../openloadflow/network/BranchState.java | 4 +- .../openloadflow/network/BusDcState.java | 1 + .../openloadflow/network/BusState.java | 3 - .../openloadflow/network/ElementState.java | 5 +- .../openloadflow/network/LfContingency.java | 12 ++ .../openloadflow/network/NetworkState.java | 37 ++++ .../network/impl/AbstractLfGenerator.java | 5 + .../openloadflow/sa/AcSecurityAnalysis.java | 19 +- .../sensi/AcSensitivityAnalysis.java | 21 +-- 12 files changed, 223 insertions(+), 246 deletions(-) delete mode 100644 src/main/java/com/powsybl/openloadflow/equations/EquationUtil.java create mode 100644 src/main/java/com/powsybl/openloadflow/network/NetworkState.java diff --git a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java index e45684a57c..86b5578c0a 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -48,11 +48,14 @@ private static void createBusEquation(LfBus bus, LfNetworkParameters networkPara if (networkParameters.isShuntVoltageControl()) { createShuntVoltageControlEquations(bus, equationSystem); } - Equation v = equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_V); - if (v.getTerms().isEmpty()) { - v.setActive(false); + + // maybe to fix later, but there is so part of OLF (like sensitivity) that needs a voltage target equation + // deactivated + if (!equationSystem.hasEquation(bus.getNum(), AcEquationType.BUS_TARGET_V)) { EquationTerm vTerm = equationSystem.getVariable(bus.getNum(), AcVariableType.BUS_V).createTerm(); - v.addTerm(vTerm); + equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_V) + .addTerm(vTerm) + .setActive(false); bus.setCalculatedV(vTerm); } } @@ -68,22 +71,17 @@ private static void createBusesEquations(LfNetwork network, LfNetworkParameters private static void createGeneratorControlEquations(LfBus bus, LfNetworkParameters networkParameters, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { - Optional optVoltageControl = bus.getVoltageControl(); - if (optVoltageControl.isPresent()) { - VoltageControl voltageControl = optVoltageControl.get(); - if (voltageControl.isVoltageControlLocal()) { - createLocalVoltageControlEquation(bus, networkParameters, equationSystem, creationParameters); - } else if (bus.isVoltageControlled()) { - createRemoteVoltageControlEquations(voltageControl, networkParameters, equationSystem, creationParameters); - } - - if (bus.isVoltageControlEnabled()) { - equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_Q).setActive(false); - } - } else { // If bus has both voltage and remote reactive power controls, then only voltage control has been kept - bus.getReactivePowerControl() - .ifPresent(rpc -> equationSystem.createEquation(rpc.getControllerBus().getNum(), AcEquationType.BUS_TARGET_Q).setActive(false)); - } + bus.getVoltageControl() + .ifPresent(voltageControl -> { + if (bus.isVoltageControlled()) { + if (voltageControl.isVoltageControlLocal()) { + createLocalVoltageControlEquation(bus, networkParameters, equationSystem, creationParameters); + } else { + createRemoteVoltageControlEquations(voltageControl, networkParameters, equationSystem, creationParameters); + } + updateGeneratorVoltageControl(voltageControl, equationSystem); + } + }); } private static void createLocalVoltageControlEquation(LfBus bus, LfNetworkParameters networkParameters, @@ -95,10 +93,22 @@ private static void createLocalVoltageControlEquation(LfBus bus, LfNetworkParame if (bus.hasGeneratorsWithSlope()) { // take first generator with slope: network loading ensures that there's only one generator with slope double slope = bus.getGeneratorsControllingVoltageWithSlope().get(0).getSlope(); - createBusWithSlopeEquation(bus, slope, networkParameters, equationSystem, vTerm, creationParameters); + + // we only support one generator controlling voltage with a non zero slope at a bus. + // equation is: V + slope * qSVC = targetV + // which is modeled here with: V + slope * (sum_branch qBranch) = TargetV - slope * qLoads + slope * qGenerators + equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_V_WITH_SLOPE) + .addTerm(vTerm) + .addTerms(createReactiveTerms(bus, networkParameters, equationSystem.getVariableSet(), creationParameters) + .stream() + .map(term -> term.multiply(slope)) + .collect(Collectors.toList())); } else { - equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_V).addTerm(vTerm); + equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_V) + .addTerm(vTerm); } + + equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_Q); } private static void createReactivePowerControlBranchEquation(LfBranch branch, LfBus bus1, LfBus bus2, EquationSystem equationSystem, @@ -110,10 +120,25 @@ private static void createReactivePowerControlBranchEquation(LfBranch branch, Lf : new ClosedBranchSide2ReactiveFlowEquationTerm(branch, bus1, bus2, equationSystem.getVariableSet(), deriveA1, deriveR1); equationSystem.createEquation(branch.getNum(), AcEquationType.BRANCH_TARGET_Q) .addTerm(q); + + // if bus has both voltage and remote reactive power controls, then only voltage control has been kept + equationSystem.createEquation(rpc.getControllerBus().getNum(), AcEquationType.BUS_TARGET_Q); + + updateReactivePowerControlBranchEquations(rpc, equationSystem); }); } } + public static void updateReactivePowerControlBranchEquations(ReactivePowerControl reactivePowerControl, EquationSystem equationSystem) { + equationSystem.getEquation(reactivePowerControl.getControlledBranch().getNum(), AcEquationType.BRANCH_TARGET_Q) + .orElseThrow() + .setActive(!reactivePowerControl.getControllerBus().isDisabled() + && !reactivePowerControl.getControlledBranch().isDisabled()); + equationSystem.getEquation(reactivePowerControl.getControllerBus().getNum(), AcEquationType.BUS_TARGET_Q) + .orElseThrow() + .setActive(false); + } + private static void createShuntEquations(LfBus bus, EquationSystem equationSystem) { bus.getShunt().ifPresent(shunt -> { ShuntCompensatorReactiveFlowEquationTerm q = new ShuntCompensatorReactiveFlowEquationTerm(shunt, bus, equationSystem.getVariableSet(), false); @@ -136,10 +161,28 @@ private static void createRemoteVoltageControlEquations(VoltageControl voltageCo .addTerm(vTerm); controlledBus.setCalculatedV(vTerm); - // create reactive power distribution equations at voltage controller buses - createReactivePowerDistributionEquations(voltageControl.getControllerBuses(), networkParameters, equationSystem, creationParameters); + for (LfBus controllerBus : voltageControl.getControllerBuses()) { + equationSystem.createEquation(controllerBus.getNum(), AcEquationType.BUS_TARGET_Q); + + // create reactive power distribution equations at voltage controller buses - updateRemoteVoltageControlEquations(voltageControl, equationSystem); + // reactive power at controller bus i (supposing this voltage control is enabled) + // q_i = qPercent_i * sum_j(q_j) where j are all the voltage controller buses + // 0 = qPercent_i * sum_j(q_j) - q_i + // which can be rewritten in a more simple way + // 0 = (qPercent_i - 1) * q_i + qPercent_i * sum_j(q_j) where j are all the voltage controller buses except i + Equation zero = equationSystem.createEquation(controllerBus.getNum(), AcEquationType.DISTR_Q) + .addTerms(createReactiveTerms(controllerBus, networkParameters, equationSystem.getVariableSet(), creationParameters).stream() + .map(term -> term.multiply(() -> controllerBus.getRemoteVoltageControlReactivePercent() - 1)) + .collect(Collectors.toList())); + for (LfBus otherControllerBus : voltageControl.getControllerBuses()) { + if (otherControllerBus != controllerBus) { + zero.addTerms(createReactiveTerms(otherControllerBus, networkParameters, equationSystem.getVariableSet(), creationParameters).stream() + .map(term -> term.multiply(controllerBus::getRemoteVoltageControlReactivePercent)) + .collect(Collectors.toList())); + } + } + } } static void updateRemoteVoltageControlEquations(VoltageControl voltageControl, EquationSystem equationSystem) { @@ -161,6 +204,9 @@ static void updateRemoteVoltageControlEquations(VoltageControl voltageControl, E equationSystem.getEquation(controllerBus.getNum(), AcEquationType.DISTR_Q) .orElseThrow() .setActive(false); + equationSystem.getEquation(controllerBus.getNum(), AcEquationType.BUS_TARGET_Q) + .orElseThrow() + .setActive(true); } } else { List enabledControllerBuses = controllerBuses.stream() @@ -176,6 +222,9 @@ static void updateRemoteVoltageControlEquations(VoltageControl voltageControl, E equationSystem.getEquation(controllerBus.getNum(), AcEquationType.DISTR_Q) .orElseThrow() .setActive(false); + equationSystem.getEquation(controllerBus.getNum(), AcEquationType.BUS_TARGET_Q) + .orElseThrow() + .setActive(true); } // activate reactive power distribution equation at all enabled controller buses except one (first) @@ -183,7 +232,11 @@ static void updateRemoteVoltageControlEquations(VoltageControl voltageControl, E boolean active = i != 0; LfBus controllerBus = enabledControllerBuses.get(i); equationSystem.getEquation(controllerBus.getNum(), AcEquationType.DISTR_Q) - .ifPresent(qDistrEq -> qDistrEq.setActive(active)); + .orElseThrow() + .setActive(active); + equationSystem.getEquation(controllerBus.getNum(), AcEquationType.BUS_TARGET_Q) + .orElseThrow() + .setActive(false); } } } @@ -229,43 +282,34 @@ private static List> createReactive return terms; } - private static void createReactivePowerDistributionEquations(Collection controllerBuses, LfNetworkParameters networkParameters, - EquationSystem equationSystem, - AcEquationSystemCreationParameters creationParameters) { - for (LfBus controllerBus : controllerBuses) { - // reactive power at controller bus i (supposing this voltage control is enabled) - // q_i = qPercent_i * sum_j(q_j) where j are all the voltage controller buses - // 0 = qPercent_i * sum_j(q_j) - q_i - // which can be rewritten in a more simple way - // 0 = (qPercent_i - 1) * q_i + qPercent_i * sum_j(q_j) where j are all the voltage controller buses except i - Equation zero = equationSystem.createEquation(controllerBus.getNum(), AcEquationType.DISTR_Q) - .addTerms(createReactiveTerms(controllerBus, networkParameters, equationSystem.getVariableSet(), creationParameters).stream() - .map(term -> term.multiply(() -> controllerBus.getRemoteVoltageControlReactivePercent() - 1)) - .collect(Collectors.toList())); - for (LfBus otherControllerBus : controllerBuses) { - if (otherControllerBus != controllerBus) { - zero.addTerms(createReactiveTerms(otherControllerBus, networkParameters, equationSystem.getVariableSet(), creationParameters).stream() - .map(term -> term.multiply(controllerBus::getRemoteVoltageControlReactivePercent)) - .collect(Collectors.toList())); - } + public static void updateGeneratorVoltageControl(VoltageControl voltageControl, EquationSystem equationSystem) { + LfBus controlledBus = voltageControl.getControlledBus(); + Set controllerBuses = voltageControl.getControllerBuses(); + + LfBus firstControllerBus = controllerBuses.iterator().next(); + if (firstControllerBus.hasGeneratorsWithSlope()) { + // we only support one controlling static var compensator without any other controlling generators + // we don't support controller bus that wants to control back voltage with slope. + equationSystem.getEquation(controlledBus.getNum(), AcEquationType.BUS_TARGET_V_WITH_SLOPE) + .orElseThrow() + .setActive(firstControllerBus.isVoltageControlEnabled()); + equationSystem.getEquation(firstControllerBus.getNum(), AcEquationType.BUS_TARGET_Q) + .orElseThrow() + .setActive(!firstControllerBus.isVoltageControlEnabled()); + } else { + if (voltageControl.isVoltageControlLocal()) { + equationSystem.getEquation(controlledBus.getNum(), AcEquationType.BUS_TARGET_V) + .orElseThrow() + .setActive(!controlledBus.isDisabled() && controlledBus.isVoltageControlEnabled()); + equationSystem.getEquation(controlledBus.getNum(), AcEquationType.BUS_TARGET_Q) + .orElseThrow() + .setActive(!controlledBus.isDisabled() && !controlledBus.isVoltageControlEnabled()); + } else { + AcEquationSystem.updateRemoteVoltageControlEquations(voltageControl, equationSystem); } } } - private static void createBusWithSlopeEquation(LfBus bus, double slope, LfNetworkParameters networkParameters, - EquationSystem equationSystem, - EquationTerm vTerm, AcEquationSystemCreationParameters creationParameters) { - // we only support one generator controlling voltage with a non zero slope at a bus. - // equation is: V + slope * qSVC = targetV - // which is modeled here with: V + slope * (sum_branch qBranch) = TargetV - slope * qLoads + slope * qGenerators - equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_V_WITH_SLOPE) - .addTerm(vTerm) - .addTerms(createReactiveTerms(bus, networkParameters, equationSystem.getVariableSet(), creationParameters) - .stream() - .map(term -> term.multiply(slope)) - .collect(Collectors.toList())); - } - private static void createNonImpedantBranch(LfBranch branch, LfBus bus1, LfBus bus2, EquationSystem equationSystem) { Optional> v1 = equationSystem.getEquation(bus1.getNum(), AcEquationType.BUS_TARGET_V); @@ -354,6 +398,21 @@ private static void createBranchActivePowerTargetEquation(LfBranch branch, LfBus } } + public static void updateTransformerPhaseControlEquations(DiscretePhaseControl phaseControl, EquationSystem equationSystem) { + LfBranch controllerBranch = phaseControl.getController(); + LfBranch controlledBranch = phaseControl.getControlled(); + + // activate/de-activate phase control equation + equationSystem.getEquation(controlledBranch.getNum(), AcEquationType.BRANCH_TARGET_P) + .orElseThrow() + .setActive(!controllerBranch.isDisabled() && controllerBranch.isPhaseControlEnabled()); + + // de-activate/activate constant A1 equation + equationSystem.getEquation(controllerBranch.getNum(), AcEquationType.BRANCH_TARGET_ALPHA1) + .orElseThrow() + .setActive(!controllerBranch.isDisabled() && !controllerBranch.isPhaseControlEnabled()); + } + private static void createTransformerVoltageControlEquations(LfBus bus, EquationSystem equationSystem) { bus.getTransformerVoltageControl() .ifPresent(voltageControl -> { diff --git a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java index 8c1697edcf..2a5667870a 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java @@ -11,7 +11,6 @@ import com.powsybl.openloadflow.network.*; import java.util.Objects; -import java.util.Set; /** * @author Geoffroy Jamgotchian @@ -24,54 +23,15 @@ public AcEquationSystemUpdater(EquationSystem eq this.equationSystem = Objects.requireNonNull(equationSystem); } - private void updateVoltageControl(VoltageControl voltageControl) { - LfBus controlledBus = voltageControl.getControlledBus(); - Set controllerBuses = voltageControl.getControllerBuses(); - - LfBus firstControllerBus = controllerBuses.iterator().next(); - if (firstControllerBus.hasGeneratorsWithSlope()) { - // we only support one controlling static var compensator without any other controlling generators - // we don't support controller bus that wants to control back voltage with slope. - equationSystem.getEquation(controlledBus.getNum(), AcEquationType.BUS_TARGET_V_WITH_SLOPE) - .orElseThrow().setActive(firstControllerBus.isVoltageControlEnabled()); - } else { - if (voltageControl.isVoltageControlLocal()) { - equationSystem.getEquation(controlledBus.getNum(), AcEquationType.BUS_TARGET_V) - .orElseThrow() - .setActive(controlledBus.isVoltageControlEnabled()); - } else { - AcEquationSystem.updateRemoteVoltageControlEquations(voltageControl, equationSystem); - } - } - } - - private void updateVoltageControl(LfBus controllerBus, boolean newVoltageControllerEnabled) { - // active/de-activate bus target reactive power equation to switch bus PV or PQ - equationSystem.getEquation(controllerBus.getNum(), AcEquationType.BUS_TARGET_Q) - .orElseThrow() - .setActive(!newVoltageControllerEnabled); - - updateVoltageControl(controllerBus.getVoltageControl().orElseThrow()); - } - @Override public void onVoltageControlChange(LfBus controllerBus, boolean newVoltageControllerEnabled) { - updateVoltageControl(controllerBus, newVoltageControllerEnabled); + controllerBus.getVoltageControl().ifPresent(voltageControl -> AcEquationSystem.updateGeneratorVoltageControl(voltageControl, equationSystem)); + controllerBus.getReactivePowerControl().ifPresent(reactivePowerControl -> AcEquationSystem.updateReactivePowerControlBranchEquations(reactivePowerControl, equationSystem)); } @Override public void onTransformerPhaseControlChange(LfBranch branch, boolean phaseControlEnabled) { - DiscretePhaseControl phaseControl = branch.getDiscretePhaseControl().orElseThrow(); - - // activate/de-activate phase control equation - equationSystem.getEquation(phaseControl.getControlled().getNum(), AcEquationType.BRANCH_TARGET_P) - .orElseThrow() - .setActive(!branch.isDisabled() && branch.isPhaseControlEnabled()); - - // de-activate/activate constant A1 equation - equationSystem.getEquation(phaseControl.getController().getNum(), AcEquationType.BRANCH_TARGET_ALPHA1) - .orElseThrow() - .setActive(!branch.isDisabled() && !branch.isPhaseControlEnabled()); + AcEquationSystem.updateTransformerPhaseControlEquations(branch.getDiscretePhaseControl().orElseThrow(), equationSystem); } @Override @@ -84,22 +44,49 @@ public void onShuntVoltageControlChange(LfShunt controllerShunt, boolean newVolt AcEquationSystem.updateShuntVoltageControlEquations(controllerShunt.getVoltageControl().orElseThrow(), equationSystem); } + private void updateElementEquations(LfElement element, boolean enable) { + // update all equations related to the element + for (var equation : equationSystem.getEquations(element.getType(), element.getNum())) { + if (equation.isActive() != enable) { + equation.setActive(enable); + } + } + + // update all equation terms related to the element + for (var equationTerm : equationSystem.getEquationTerms(element.getType(), element.getNum())) { + if (equationTerm.isActive() != enable) { + equationTerm.setActive(enable); + } + } + } + @Override public void onDisableChange(LfElement element, boolean disabled) { + updateElementEquations(element, !disabled); switch (element.getType()) { case BUS: LfBus bus = (LfBus) element; if (disabled && bus.isSlack()) { throw new PowsyblException("Slack bus '" + bus.getId() + "' disabling is not supported"); } - bus.getVoltageControl().ifPresent(this::updateVoltageControl); + equationSystem.getEquation(bus.getNum(), AcEquationType.BUS_TARGET_PHI) + .ifPresent(eq -> eq.setActive(!bus.isDisabled())); + equationSystem.getEquation(bus.getNum(), AcEquationType.BUS_TARGET_P) + .ifPresent(eq -> eq.setActive(!bus.isDisabled() && !bus.isSlack())); + // set voltage target equation inactive, various voltage control will set next to the correct value + equationSystem.getEquation(bus.getNum(), AcEquationType.BUS_TARGET_V) + .orElseThrow() + .setActive(false); + bus.getVoltageControl().ifPresent(voltageControl -> AcEquationSystem.updateGeneratorVoltageControl(voltageControl, equationSystem)); bus.getTransformerVoltageControl().ifPresent(voltageControl -> AcEquationSystem.updateTransformerVoltageControlEquations(voltageControl, equationSystem)); bus.getShuntVoltageControl().ifPresent(voltageControl -> AcEquationSystem.updateShuntVoltageControlEquations(voltageControl, equationSystem)); + bus.getReactivePowerControl().ifPresent(reactivePowerControl -> AcEquationSystem.updateReactivePowerControlBranchEquations(reactivePowerControl, equationSystem)); break; case BRANCH: LfBranch branch = (LfBranch) element; branch.getVoltageControl().ifPresent(voltageControl -> AcEquationSystem.updateTransformerVoltageControlEquations(voltageControl, equationSystem)); - branch.getDiscretePhaseControl().ifPresent(phaseControl -> onTransformerPhaseControlChange(branch, branch.isPhaseControlEnabled())); + branch.getDiscretePhaseControl().ifPresent(phaseControl -> AcEquationSystem.updateTransformerPhaseControlEquations(phaseControl, equationSystem)); + branch.getReactivePowerControl().ifPresent(reactivePowerControl -> AcEquationSystem.updateReactivePowerControlBranchEquations(reactivePowerControl, equationSystem)); break; case SHUNT_COMPENSATOR: LfShunt shunt = (LfShunt) element; diff --git a/src/main/java/com/powsybl/openloadflow/equations/EquationUtil.java b/src/main/java/com/powsybl/openloadflow/equations/EquationUtil.java deleted file mode 100644 index a7dce23296..0000000000 --- a/src/main/java/com/powsybl/openloadflow/equations/EquationUtil.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Copyright (c) 2021, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -package com.powsybl.openloadflow.equations; - -import com.powsybl.openloadflow.network.ElementType; -import com.powsybl.openloadflow.network.LfBranch; -import com.powsybl.openloadflow.network.LfBus; -import com.powsybl.openloadflow.network.LfShunt; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * @author Geoffroy Jamgotchian - */ -public final class EquationUtil { - - private static final Logger LOGGER = LoggerFactory.getLogger(EquationUtil.class); - - private EquationUtil() { - } - - public static & Quantity, E extends Enum & Quantity> void deactivateEquations(Collection branches, Collection buses, EquationSystem equationSystem, List> deactivatedEquations, List> deactivatedEquationTerms) { - for (LfBranch branch : branches) { - LOGGER.trace("Remove equations and equations terms related to branch '{}'", branch.getId()); - - // deactivate all equations related to a branch - for (Equation equation : equationSystem.getEquations(ElementType.BRANCH, branch.getNum())) { - if (equation.isActive()) { - equation.setActive(false); - deactivatedEquations.add(equation); - } - } - - // deactivate all equation terms related to a branch - for (EquationTerm equationTerm : equationSystem.getEquationTerms(ElementType.BRANCH, branch.getNum())) { - if (equationTerm.isActive()) { - equationTerm.setActive(false); - deactivatedEquationTerms.add(equationTerm); - } - } - } - - for (LfBus bus : buses) { - LOGGER.trace("Remove equations and equation terms related to bus '{}'", bus.getId()); - - // deactivate all equations related to a bus - for (Equation equation : equationSystem.getEquations(ElementType.BUS, bus.getNum())) { - if (equation.isActive()) { - equation.setActive(false); - deactivatedEquations.add(equation); - } - } - - // deactivate all equation terms related to a bus - for (EquationTerm equationTerm : equationSystem.getEquationTerms(ElementType.BUS, bus.getNum())) { - if (equationTerm.isActive()) { - equationTerm.setActive(false); - deactivatedEquationTerms.add(equationTerm); - } - } - - List shunts = new ArrayList<>(2); - bus.getShunt().ifPresent(shunts::add); - bus.getControllerShunt().ifPresent(shunts::add); - for (LfShunt shunt : shunts) { - // deactivate all equations related to a shunt - for (Equation equation : equationSystem.getEquations(ElementType.SHUNT_COMPENSATOR, shunt.getNum())) { - if (equation.isActive()) { - equation.setActive(false); - deactivatedEquations.add(equation); - } - } - - // deactivate all equation terms related to a shunt - for (EquationTerm equationTerm : equationSystem.getEquationTerms(ElementType.SHUNT_COMPENSATOR, shunt.getNum())) { - if (equationTerm.isActive()) { - equationTerm.setActive(false); - deactivatedEquationTerms.add(equationTerm); - } - } - } - } - } - - public static & Quantity, E extends Enum & Quantity> void reactivateEquations(List> deactivatedEquations, List> deactivatedEquationTerms) { - // restore deactivated equations and equations terms from previous contingency - if (!deactivatedEquations.isEmpty()) { - for (Equation equation : deactivatedEquations) { - equation.setActive(true); - } - deactivatedEquations.clear(); - } - if (!deactivatedEquationTerms.isEmpty()) { - for (EquationTerm equationTerm : deactivatedEquationTerms) { - equationTerm.setActive(true); - } - deactivatedEquationTerms.clear(); - } - } -} diff --git a/src/main/java/com/powsybl/openloadflow/network/BranchState.java b/src/main/java/com/powsybl/openloadflow/network/BranchState.java index 1884652290..fb841f45e0 100644 --- a/src/main/java/com/powsybl/openloadflow/network/BranchState.java +++ b/src/main/java/com/powsybl/openloadflow/network/BranchState.java @@ -15,7 +15,6 @@ public class BranchState extends ElementState { private final double r1; private final boolean phaseControlEnabled; private final boolean voltageControlEnabled; - private final boolean disabled; public BranchState(LfBranch branch) { super(branch); @@ -24,17 +23,16 @@ public BranchState(LfBranch branch) { r1 = piModel.getR1(); phaseControlEnabled = branch.isPhaseControlEnabled(); voltageControlEnabled = branch.isVoltageControlEnabled(); - disabled = branch.isDisabled(); } @Override public void restore() { + super.restore(); PiModel piModel = element.getPiModel(); piModel.setA1(a1); piModel.setR1(r1); element.setPhaseControlEnabled(phaseControlEnabled); element.setVoltageControlEnabled(voltageControlEnabled); - element.setDisabled(disabled); } public static BranchState save(LfBranch branch) { diff --git a/src/main/java/com/powsybl/openloadflow/network/BusDcState.java b/src/main/java/com/powsybl/openloadflow/network/BusDcState.java index bf02fd1cbe..066998fc00 100644 --- a/src/main/java/com/powsybl/openloadflow/network/BusDcState.java +++ b/src/main/java/com/powsybl/openloadflow/network/BusDcState.java @@ -29,6 +29,7 @@ public BusDcState(LfBus bus) { @Override public void restore() { + super.restore(); element.setLoadTargetP(loadTargetP); element.getGenerators().forEach(g -> g.setTargetP(generatorsTargetP.get(g.getId()))); element.getGenerators().forEach(g -> g.setParticipating(participatingGenerators.get(g.getId()))); diff --git a/src/main/java/com/powsybl/openloadflow/network/BusState.java b/src/main/java/com/powsybl/openloadflow/network/BusState.java index a9aa67577c..35fef24682 100644 --- a/src/main/java/com/powsybl/openloadflow/network/BusState.java +++ b/src/main/java/com/powsybl/openloadflow/network/BusState.java @@ -20,7 +20,6 @@ public class BusState extends BusDcState { private final double generationTargetQ; private final boolean voltageControlEnabled; private final Boolean shuntVoltageControlEnabled; - private final boolean disabled; private final double shuntB; private final double controllerShuntB; private final Map generatorsControlType; @@ -37,7 +36,6 @@ public BusState(LfBus bus) { controllerShuntB = controllerShunt != null ? controllerShunt.getB() : Double.NaN; LfShunt shunt = bus.getShunt().orElse(null); shuntB = shunt != null ? shunt.getB() : Double.NaN; - this.disabled = bus.isDisabled(); this.generatorsControlType = bus.getGenerators().stream().collect(Collectors.toMap(LfGenerator::getId, LfGenerator::getGeneratorControlType)); } @@ -59,7 +57,6 @@ public void restore() { if (!Double.isNaN(shuntB)) { element.getShunt().orElseThrow().setB(shuntB); } - element.setDisabled(disabled); element.getGenerators().forEach(g -> g.setGeneratorControlType(generatorsControlType.get(g.getId()))); } diff --git a/src/main/java/com/powsybl/openloadflow/network/ElementState.java b/src/main/java/com/powsybl/openloadflow/network/ElementState.java index 34289db666..e81d2e86a8 100644 --- a/src/main/java/com/powsybl/openloadflow/network/ElementState.java +++ b/src/main/java/com/powsybl/openloadflow/network/ElementState.java @@ -19,12 +19,15 @@ public class ElementState { protected final T element; + protected final boolean disabled; + public ElementState(T element) { this.element = Objects.requireNonNull(element); + disabled = element.isDisabled(); } public void restore() { - // nothing to restore + element.setDisabled(disabled); } public static > List save(Collection elements, Function save) { diff --git a/src/main/java/com/powsybl/openloadflow/network/LfContingency.java b/src/main/java/com/powsybl/openloadflow/network/LfContingency.java index d88b45549b..760512a1b3 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfContingency.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfContingency.java @@ -75,6 +75,18 @@ public Set getBranches() { return branches; } + public Map getShuntsShift() { + return shuntsShift; + } + + public Map getBusesLoadShift() { + return busesLoadShift; + } + + public Set getGenerators() { + return generators; + } + public double getActivePowerLoss() { return activePowerLoss; } diff --git a/src/main/java/com/powsybl/openloadflow/network/NetworkState.java b/src/main/java/com/powsybl/openloadflow/network/NetworkState.java new file mode 100644 index 0000000000..b2afd62c26 --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/NetworkState.java @@ -0,0 +1,37 @@ +/** + * 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/. + */ +package com.powsybl.openloadflow.network; + +import java.util.List; +import java.util.Objects; + +/** + * @author Geoffroy Jamgotchian + */ +public class NetworkState { + + private final List busStates; + + private final List branchStates; + + protected NetworkState(List busStates, List branchStates) { + this.busStates = Objects.requireNonNull(busStates); + this.branchStates = Objects.requireNonNull(branchStates); + } + + public static NetworkState save(LfNetwork network) { + Objects.requireNonNull(network); + List busStates = ElementState.save(network.getBuses(), BusState::save); + List branchStates = ElementState.save(network.getBranches(), BranchState::save); + return new NetworkState(busStates, branchStates); + } + + public void restore() { + ElementState.restore(busStates); + ElementState.restore(branchStates); + } +} diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfGenerator.java b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfGenerator.java index c1783c1a0b..e7e25fae2d 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfGenerator.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfGenerator.java @@ -313,4 +313,9 @@ protected boolean checkActivePowerControl(double targetP, double minP, double ma } return participating; } + + @Override + public String toString() { + return getId(); + } } diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index 70c6985547..535f23a66c 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -19,16 +19,11 @@ import com.powsybl.loadflow.LoadFlowParameters; import com.powsybl.math.matrix.MatrixFactory; import com.powsybl.openloadflow.OpenLoadFlowParameters; -import com.powsybl.openloadflow.ac.equations.AcEquationType; -import com.powsybl.openloadflow.ac.equations.AcVariableType; import com.powsybl.openloadflow.ac.nr.NewtonRaphsonStatus; import com.powsybl.openloadflow.ac.outerloop.AcLoadFlowContext; import com.powsybl.openloadflow.ac.outerloop.AcLoadFlowParameters; import com.powsybl.openloadflow.ac.outerloop.AcLoadFlowResult; import com.powsybl.openloadflow.ac.outerloop.AcloadFlowEngine; -import com.powsybl.openloadflow.equations.Equation; -import com.powsybl.openloadflow.equations.EquationTerm; -import com.powsybl.openloadflow.equations.EquationUtil; import com.powsybl.openloadflow.graph.GraphDecrementalConnectivity; import com.powsybl.openloadflow.network.*; import com.powsybl.openloadflow.network.impl.Networks; @@ -134,8 +129,7 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List busStates = ElementState.save(network.getBuses(), BusState::save); - List branchStates = ElementState.save(network.getBranches(), BranchState::save); + NetworkState networkState = NetworkState.save(network); // start a simulation for each of the contingency Iterator contingencyIt = propagatedContingencies.iterator(); @@ -155,8 +149,7 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List, LimitViolation> preContingencyLimitViolations, Map preContingencyBranchResults) { LOGGER.info("Start post contingency '{}' simulation", lfContingency.getId()); + LOGGER.debug("Contingency '{}' impact: remove {} buses, remove {} branches, remove {} generators, shift {} shunts, shift load of {} buses", + lfContingency.getId(), lfContingency.getBuses(), lfContingency.getBranches(), lfContingency.getGenerators(), + lfContingency.getShuntsShift(), lfContingency.getBusesLoadShift()); Stopwatch stopwatch = Stopwatch.createStarted(); - List> deactivatedEquations = new ArrayList<>(); - List> deactivatedEquationTerms = new ArrayList<>(); List branchResults = new ArrayList<>(); List busResults = new ArrayList<>(); List threeWindingsTransformerResults = new ArrayList<>(); - EquationUtil.deactivateEquations(lfContingency.getBranches(), lfContingency.getBuses(), context.getEquationSystem(), deactivatedEquations, deactivatedEquationTerms); // restart LF on post contingency equation system context.getParameters().getNewtonRaphsonParameters().setVoltageInitializer(new PreviousValueVoltageInitializer()); @@ -209,8 +202,6 @@ private PostContingencyResult runPostContingencySimulation(LfNetwork network, Ac } }); - EquationUtil.reactivateEquations(deactivatedEquations, deactivatedEquationTerms); - stopwatch.stop(); LOGGER.info("Post contingency '{}' simulation done in {} ms", lfContingency.getId(), stopwatch.elapsed(TimeUnit.MILLISECONDS)); diff --git a/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java index f2850de39d..0a639bf031 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java @@ -18,9 +18,6 @@ import com.powsybl.openloadflow.ac.outerloop.AcLoadFlowContext; import com.powsybl.openloadflow.ac.outerloop.AcLoadFlowParameters; import com.powsybl.openloadflow.ac.outerloop.AcloadFlowEngine; -import com.powsybl.openloadflow.equations.Equation; -import com.powsybl.openloadflow.equations.EquationTerm; -import com.powsybl.openloadflow.equations.EquationUtil; import com.powsybl.openloadflow.equations.Variable; import com.powsybl.openloadflow.graph.GraphDecrementalConnectivity; import com.powsybl.openloadflow.network.*; @@ -114,6 +111,9 @@ private void calculatePostContingencySensitivityValues(List> deactivatedEquations = new ArrayList<>(); - List> deactivatedEquationTerms = new ArrayList<>(); - - EquationUtil.deactivateEquations(lfContingency.getBranches(), lfContingency.getBuses(), context.getEquationSystem(), deactivatedEquations, deactivatedEquationTerms); - context.getParameters().getNewtonRaphsonParameters().setVoltageInitializer(new PreviousValueVoltageInitializer()); new AcloadFlowEngine(context) .run(reporter); @@ -149,8 +144,6 @@ private void calculatePostContingencySensitivityValues(List contingencies, .flatMap(contingency -> contingency.toLfContingency(lfNetwork, connectivity, false).stream()) .collect(Collectors.toList()); - List busStates = ElementState.save(lfNetwork.getBuses(), BusState::save); + NetworkState networkState = NetworkState.save(lfNetwork); // Contingency not breaking connectivity for (LfContingency lfContingency : lfContingencies.stream().filter(lfContingency -> lfContingency.getBuses().isEmpty()).collect(Collectors.toSet())) { @@ -290,7 +283,8 @@ public void analyse(Network network, List contingencies, }); calculatePostContingencySensitivityValues(contingencyFactors, lfContingency, lfNetwork, context, factorGroups, slackParticipationByBus, lfParameters, lfParametersExt, lfContingency.getIndex(), valueWriter, reporter, hasTransformerBusTargetVoltage); - ElementState.restore(busStates); + + networkState.restore(); } // Contingency breaking connectivity @@ -327,7 +321,8 @@ public void analyse(Network network, List contingencies, calculatePostContingencySensitivityValues(contingencyFactors, lfContingency, lfNetwork, context, factorGroups, slackParticipationByBusForThisConnectivity, lfParameters, lfParametersExt, lfContingency.getIndex(), valueWriter, reporter, hasTransformerBusTargetVoltage); - ElementState.restore(busStates); + + networkState.restore(); connectivity.reset(); }