Skip to content

Commit

Permalink
Disable switch without removing variables (#455)
Browse files Browse the repository at this point in the history
Signed-off-by: Geoffroy Jamgotchian <[email protected]>
  • Loading branch information
geofjamg authored Mar 10, 2022
1 parent 07bb2e5 commit 2a60fac
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -331,14 +331,21 @@ private static void createNonImpedantBranch(LfBranch branch, LfBus bus1, LfBus b
bus1.setCalculatedV(vTerm);
// add a dummy reactive power variable to both sides of the non impedant branch and with an opposite sign
// to ensure we have the same number of equation and variables
var dummyQ = equationSystem.getVariable(branch.getNum(), AcVariableType.DUMMY_Q);
equationSystem.getEquation(bus1.getNum(), AcEquationType.BUS_TARGET_Q)
.orElseThrow()
.addTerm(equationSystem.getVariable(branch.getNum(), AcVariableType.DUMMY_Q).createTerm());
.addTerm(dummyQ.createTerm());

equationSystem.getEquation(bus2.getNum(), AcEquationType.BUS_TARGET_Q)
.orElseThrow()
.addTerm(equationSystem.getVariable(branch.getNum(), AcVariableType.DUMMY_Q).<AcEquationType>createTerm()
.addTerm(dummyQ.<AcEquationType>createTerm()
.minus());

// create an inactive dummy reactive power target equation set to zero that could be activated
// on case of switch opening
equationSystem.createEquation(branch.getNum(), AcEquationType.DUMMY_TARGET_Q)
.addTerm(dummyQ.createTerm())
.setActive(false);
} else {
// nothing to do in case of v1 and v2 are found, we just have to ensure
// target v are equals.
Expand All @@ -356,14 +363,21 @@ private static void createNonImpedantBranch(LfBranch branch, LfBus bus1, LfBus b

// add a dummy active power variable to both sides of the non impedant branch and with an opposite sign
// to ensure we have the same number of equation and variables
var dummyP = equationSystem.getVariable(branch.getNum(), AcVariableType.DUMMY_P);
equationSystem.getEquation(bus1.getNum(), AcEquationType.BUS_TARGET_P)
.orElseThrow()
.addTerm(equationSystem.getVariable(branch.getNum(), AcVariableType.DUMMY_P).createTerm());
.addTerm(dummyP.createTerm());

equationSystem.getEquation(bus2.getNum(), AcEquationType.BUS_TARGET_P)
.orElseThrow()
.addTerm(equationSystem.getVariable(branch.getNum(), AcVariableType.DUMMY_P).<AcEquationType>createTerm()
.addTerm(dummyP.<AcEquationType>createTerm()
.minus());

// create an inactive dummy active power target equation set to zero that could be activated
// on case of switch opening
equationSystem.createEquation(branch.getNum(), AcEquationType.DUMMY_TARGET_P)
.addTerm(dummyP.createTerm())
.setActive(false);
} else {
throw new IllegalStateException("Cannot happen because only there is one slack bus per model");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,38 @@ public void onShuntVoltageControlChange(LfShunt controllerShunt, boolean newVolt
}

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);
if (element instanceof LfBranch && ((LfBranch) element).isZeroImpedanceBranch(false)) {
LfBranch branch = (LfBranch) element;
if (branch.isSpanningTreeEdge()) {
// depending on the switch status, we activate either v1 = v2, ph1 = ph2 equations
// or equations that set dummy p and q variable to zero
equationSystem.getEquation(element.getNum(), AcEquationType.ZERO_PHI)
.orElseThrow()
.setActive(enable);
equationSystem.getEquation(element.getNum(), AcEquationType.DUMMY_TARGET_P)
.orElseThrow()
.setActive(!enable);

equationSystem.getEquation(element.getNum(), AcEquationType.ZERO_V)
.orElseThrow()
.setActive(enable);
equationSystem.getEquation(element.getNum(), AcEquationType.DUMMY_TARGET_Q)
.orElseThrow()
.setActive(!enable);
}
} else {
// 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);
// update all equation terms related to the element
for (var equationTerm : equationSystem.getEquationTerms(element.getType(), element.getNum())) {
if (equationTerm.isActive() != enable) {
equationTerm.setActive(enable);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ public enum AcEquationType implements Quantity {
ZERO_V("zero_v", ElementType.BRANCH), // zero impedance branch, voltage magnitude equality
ZERO_PHI("zero_\u03C6", ElementType.BRANCH), // zero impedance branch, voltage angle equality
DISTR_RHO("distr_\u03C1", ElementType.BRANCH), // remote transformer voltage control ratio distribution
DISTR_SHUNT_B("distr_b", ElementType.SHUNT_COMPENSATOR); // shunt remote voltage control susceptance distribution
DISTR_SHUNT_B("distr_b", ElementType.SHUNT_COMPENSATOR), // shunt remote voltage control susceptance distribution
DUMMY_TARGET_P("dummy_target_p", ElementType.BRANCH),
DUMMY_TARGET_Q("dummy_target_q", ElementType.BRANCH);

private final String symbol;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ public static void init(Equation<AcVariableType, AcEquationType> equation, LfNet

case DISTR_RHO:
case DISTR_SHUNT_B:
case DUMMY_TARGET_P:
case DUMMY_TARGET_Q:
targets[equation.getColumn()] = 0;
break;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* 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.ac;

import com.powsybl.commons.reporter.Reporter;
import com.powsybl.iidm.network.Network;
import com.powsybl.loadflow.LoadFlowParameters;
import com.powsybl.math.matrix.DenseMatrixFactory;
import com.powsybl.openloadflow.OpenLoadFlowParameters;
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.graph.EvenShiloachGraphDecrementalConnectivityFactory;
import com.powsybl.openloadflow.network.LfNetwork;
import com.powsybl.openloadflow.network.NameSlackBusSelector;
import com.powsybl.openloadflow.network.NodeBreakerNetworkFactory;
import com.powsybl.openloadflow.network.impl.LfNetworkLoaderImpl;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

/**
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
*/
class NonImpedantBranchDisablingTest {

@Test
void test() {
Network network = NodeBreakerNetworkFactory.create();
network.getSwitch("B3").setRetained(false);
network.getSwitch("C").setRetained(true);
AcLoadFlowParameters parameters = OpenLoadFlowParameters.createAcParameters(new LoadFlowParameters(),
new OpenLoadFlowParameters(),
new DenseMatrixFactory(),
new EvenShiloachGraphDecrementalConnectivityFactory<>(),
Reporter.NO_OP,
true,
false);
parameters.getNetworkParameters().setSlackBusSelector(new NameSlackBusSelector("VL1_1"));
LfNetwork lfNetwork = LfNetwork.load(network, new LfNetworkLoaderImpl(), parameters.getNetworkParameters()).get(0);

try (AcLoadFlowContext context = new AcLoadFlowContext(lfNetwork, parameters)) {
var engine = new AcloadFlowEngine(context);
engine.run();
assertEquals(8, context.getEquationSystem().getSortedVariablesToFind().size());
var l1 = lfNetwork.getBranchById("L1");
var l2 = lfNetwork.getBranchById("L2");
assertEquals(3.01884, l1.getP1().eval(), 10e-5);
assertEquals(3.01884, l2.getP1().eval(), 10e-5);

lfNetwork.getBranchById("C").setDisabled(true);

engine.run();
assertEquals(8, context.getEquationSystem().getSortedVariablesToFind().size()); // we have kept same variables!!!
assertEquals(0, l1.getP1().eval(), 10e-5);
assertEquals(6.07782, l2.getP1().eval(), 10e-5);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import com.powsybl.computation.ComputationManager;
import com.powsybl.contingency.*;
import com.powsybl.ieeecdf.converter.IeeeCdfNetworkFactory;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.extensions.LoadDetailAdder;
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
Expand Down Expand Up @@ -1261,4 +1262,18 @@ void testPhaseShifterNecessaryForConnectivity() {
assertEquals(100.3689, l1ContingencyResult.getBranchResult("PS1").getP1(), LoadFlowAssert.DELTA_POWER);
assertEquals(-100.1844, l1ContingencyResult.getBranchResult("PS1").getP2(), LoadFlowAssert.DELTA_POWER);
}

@Test
void testWithNonImpedantLineConnectedToSlackBus() {
Network network = IeeeCdfNetworkFactory.create14();
network.getLine("L1-2-1").setR(0).setX(0);
network.getLine("L4-5-1").setR(0).setX(0);

List<Contingency> contingencies = allBranches(network);

List<StateMonitor> monitors = Collections.emptyList();

SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors);
assertEquals(20, result.getPostContingencyResults().size()); // assert there is no contingency simulation failure
}
}

0 comments on commit 2a60fac

Please sign in to comment.