From 89bd79abe5a6da877ee82ac306d6bd773bdd4a3c Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 5 May 2021 08:28:58 +0200 Subject: [PATCH 01/42] Add voltage per reactive power control parameter. Signed-off-by: Anne Tilloy --- .../openloadflow/OpenLoadFlowParameters.java | 14 ++++++++++++++ .../powsybl/openloadflow/OpenLoadFlowProvider.java | 4 +++- .../ac/outerloop/AcLoadFlowParameters.java | 8 +++++++- .../openloadflow/util/ParameterConstants.java | 3 +++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java index 94294063a0..fa8b4e6175 100644 --- a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java +++ b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java @@ -46,6 +46,8 @@ public enum LowImpedanceBranchMode { private double slackBusPMaxMismatch = SLACK_BUS_P_MAX_MISMATCH_DEFAULT_VALUE; + private boolean voltagePerReactivePowerControl = VOLTAGE_PER_REACTIVE_POWER_CONTROL_DEFAULT_VALUE; + @Override public String getName() { return "open-load-flow-parameters"; @@ -144,6 +146,15 @@ public OpenLoadFlowParameters setAddRatioToLinesWithDifferentNominalVoltageAtBot return this; } + public boolean hasVoltagePerReactivePowerControl() { + return voltagePerReactivePowerControl; + } + + public OpenLoadFlowParameters setVoltagePerReactivePowerControl(boolean voltagePerReactivePowerControl) { + this.voltagePerReactivePowerControl = voltagePerReactivePowerControl; + return this; + } + public static OpenLoadFlowParameters load() { return new OpenLoadFlowConfigLoader().load(PlatformConfig.defaultConfig()); } @@ -160,6 +171,8 @@ public String toString() { ", dcUseTransformerRatio=" + dcUseTransformerRatio + ", plausibleActivePowerLimit=" + plausibleActivePowerLimit + ", addRatioToLinesWithDifferentNominalVoltageAtBothEnds=" + addRatioToLinesWithDifferentNominalVoltageAtBothEnds + + ", slackBusPMaxMismatch=" + slackBusPMaxMismatch + + ", voltagePerReactivePowerControl=" + voltagePerReactivePowerControl + ')'; } @@ -184,6 +197,7 @@ public OpenLoadFlowParameters load(PlatformConfig platformConfig) { .setPlausibleActivePowerLimit(config.getDoubleProperty(PLAUSIBLE_ACTIVE_POWER_LIMIT_PARAM_NAME, PLAUSIBLE_ACTIVE_POWER_LIMIT_DEFAULT_VALUE)) .setAddRatioToLinesWithDifferentNominalVoltageAtBothEnds(config.getBooleanProperty(ADD_RATIO_TO_LINES_WITH_DIFFERENT_NOMINAL_VOLTAGE_AT_BOTH_ENDS_NAME, ADD_RATIO_TO_LINES_WITH_DIFFERENT_NOMINAL_VOLTAGE_AT_BOTH_ENDS_DEFAULT_VALUE)) .setSlackBusPMaxMismatch(config.getDoubleProperty(SLACK_BUS_P_MAX_MISMATCH_NAME, SLACK_BUS_P_MAX_MISMATCH_DEFAULT_VALUE)) + .setVoltagePerReactivePowerControl(VOLTAGE_PER_REACTIVE_POWER_CONTROL_DEFAULT_VALUE) ); return parameters; } diff --git a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java index 6cbf057570..e12d4b55ae 100644 --- a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java +++ b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java @@ -147,6 +147,7 @@ public static AcLoadFlowParameters createAcParameters(Network network, MatrixFac LOGGER.info("Plausible active power limit: {}", parametersExt.getPlausibleActivePowerLimit()); LOGGER.info("Add ratio to lines with different nominal voltage at both ends: {}", parametersExt.isAddRatioToLinesWithDifferentNominalVoltageAtBothEnds()); LOGGER.info("Slack bus Pmax mismatch: {}", parametersExt.getSlackBusPMaxMismatch()); + LOGGER.info("Voltage per reactive power control: {}", parametersExt.hasVoltagePerReactivePowerControl()); List outerLoops = new ArrayList<>(); if (parameters.isDistributedSlack()) { @@ -179,7 +180,8 @@ public static AcLoadFlowParameters createAcParameters(Network network, MatrixFac parametersExt.getPlausibleActivePowerLimit(), forceA1Var, parametersExt.isAddRatioToLinesWithDifferentNominalVoltageAtBothEnds(), - branchesWithCurrent); + branchesWithCurrent, + parametersExt.hasVoltagePerReactivePowerControl()); } private LoadFlowResult runAc(Network network, LoadFlowParameters parameters, OpenLoadFlowParameters parametersExt, Reporter reporter) { diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcLoadFlowParameters.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcLoadFlowParameters.java index 7ed16cc259..269b6e937c 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcLoadFlowParameters.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcLoadFlowParameters.java @@ -50,13 +50,15 @@ public class AcLoadFlowParameters { private final Set branchesWithCurrent; + private boolean voltagePerReactivePowerControl; + public AcLoadFlowParameters(SlackBusSelector slackBusSelector, VoltageInitializer voltageInitializer, NewtonRaphsonStoppingCriteria stoppingCriteria, List outerLoops, MatrixFactory matrixFactory, boolean voltageRemoteControl, boolean phaseControl, boolean transformerVoltageControlOn, boolean minImpedance, boolean twtSplitShuntAdmittance, boolean breakers, double plausibleActivePowerLimit, boolean forceA1Var, boolean addRatioToLinesWithDifferentNominalVoltageAtBothEnds, - Set branchesWithCurrent) { + Set branchesWithCurrent, boolean voltagePerReactivePowerControl) { this.slackBusSelector = Objects.requireNonNull(slackBusSelector); this.voltageInitializer = Objects.requireNonNull(voltageInitializer); this.stoppingCriteria = Objects.requireNonNull(stoppingCriteria); @@ -72,6 +74,7 @@ public AcLoadFlowParameters(SlackBusSelector slackBusSelector, VoltageInitialize this.forceA1Var = forceA1Var; this.addRatioToLinesWithDifferentNominalVoltageAtBothEnds = addRatioToLinesWithDifferentNominalVoltageAtBothEnds; this.branchesWithCurrent = branchesWithCurrent; + this.voltagePerReactivePowerControl = voltagePerReactivePowerControl; } public SlackBusSelector getSlackBusSelector() { @@ -138,4 +141,7 @@ public Set getBranchesWithCurrent() { return branchesWithCurrent; } + public boolean isVoltagePerReactivePowerControl() { + return voltagePerReactivePowerControl; + } } diff --git a/src/main/java/com/powsybl/openloadflow/util/ParameterConstants.java b/src/main/java/com/powsybl/openloadflow/util/ParameterConstants.java index ac2c6d2eff..88b3e659e3 100644 --- a/src/main/java/com/powsybl/openloadflow/util/ParameterConstants.java +++ b/src/main/java/com/powsybl/openloadflow/util/ParameterConstants.java @@ -47,6 +47,9 @@ public final class ParameterConstants { public static final String SLACK_BUS_P_MAX_MISMATCH_NAME = "slackBusPMaxMismatch"; public static final double SLACK_BUS_P_MAX_MISMATCH_DEFAULT_VALUE = 1.0; + public static final String VOLTAGE_PER_REACTIVE_POWER_CONTROL_NAME = "voltagePerReactivePowerControl"; + public static final boolean VOLTAGE_PER_REACTIVE_POWER_CONTROL_DEFAULT_VALUE = false; + private ParameterConstants() { } } From fd73a3b1efb3dcf5975b0fa82542147b7ec98c1b Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 5 May 2021 09:14:53 +0200 Subject: [PATCH 02/42] Add slope in generator attributes. Signed-off-by: Anne Tilloy --- .../openloadflow/ac/equations/AcEquationSystem.java | 1 + .../AcEquationSystemCreationParameters.java | 12 ++++++++++-- .../openloadflow/ac/outerloop/AcloadFlowEngine.java | 4 ++-- .../powsybl/openloadflow/network/LfGenerator.java | 2 ++ .../network/impl/LfDanglingLineGenerator.java | 5 +++++ .../openloadflow/network/impl/LfGeneratorImpl.java | 5 +++++ .../network/impl/LfStaticVarCompensatorImpl.java | 11 +++++++++++ .../network/impl/LfVscConverterStationImpl.java | 5 +++++ 8 files changed, 41 insertions(+), 4 deletions(-) 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 096ab519dd..1612ec3af3 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -59,6 +59,7 @@ private static void createBusEquations(LfNetwork network, VariableSet variableSe private static void createVoltageControlEquations(VoltageControl voltageControl, LfBus bus, VariableSet variableSet, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { if (voltageControl.isVoltageControlLocal()) { + // FIXME annetill: slope. EquationTerm vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm); bus.setV(vTerm); diff --git a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java index 50f969d7bf..ea3d9faae7 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java @@ -21,19 +21,23 @@ public class AcEquationSystemCreationParameters { private final Set branchesWithCurrent; + private final boolean voltagePerReactivePowerControl; + public AcEquationSystemCreationParameters(boolean phaseControl, boolean transformerVoltageControl) { this(phaseControl, transformerVoltageControl, false); } public AcEquationSystemCreationParameters(boolean phaseControl, boolean transformerVoltageControl, boolean forceA1Var) { - this(phaseControl, transformerVoltageControl, forceA1Var, null); + this(phaseControl, transformerVoltageControl, forceA1Var, null, false); } - public AcEquationSystemCreationParameters(boolean phaseControl, boolean transformerVoltageControl, boolean forceA1Var, Set branchesWithCurrent) { + public AcEquationSystemCreationParameters(boolean phaseControl, boolean transformerVoltageControl, boolean forceA1Var, + Set branchesWithCurrent, boolean voltagePerReactivePowerControl) { this.phaseControl = phaseControl; this.transformerVoltageControl = transformerVoltageControl; this.forceA1Var = forceA1Var; this.branchesWithCurrent = branchesWithCurrent; + this.voltagePerReactivePowerControl = voltagePerReactivePowerControl; } public boolean isPhaseControl() { @@ -51,4 +55,8 @@ public boolean isForceA1Var() { public Set getBranchesWithCurrent() { return branchesWithCurrent; } + + public boolean isVoltagePerReactivePowerControl() { + return voltagePerReactivePowerControl; + } } diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java index a61883d129..6dd0eb3369 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java @@ -137,8 +137,8 @@ public AcLoadFlowResult run(Reporter reporter) { LOGGER.info("Start AC loadflow on network {}", network.getNum()); variableSet = new VariableSet(); - AcEquationSystemCreationParameters creationParameters = new AcEquationSystemCreationParameters( - parameters.isPhaseControl(), parameters.isTransformerVoltageControlOn(), parameters.isForceA1Var(), parameters.getBranchesWithCurrent()); + AcEquationSystemCreationParameters creationParameters = new AcEquationSystemCreationParameters(parameters.isPhaseControl(), + parameters.isTransformerVoltageControlOn(), parameters.isForceA1Var(), parameters.getBranchesWithCurrent(), parameters.isVoltagePerReactivePowerControl()); equationSystem = AcEquationSystem.create(network, variableSet, creationParameters); j = new JacobianMatrix(equationSystem, parameters.getMatrixFactory()); targetVector = new TargetVector(network, equationSystem); diff --git a/src/main/java/com/powsybl/openloadflow/network/LfGenerator.java b/src/main/java/com/powsybl/openloadflow/network/LfGenerator.java index 2a90154a19..ca13d5b410 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfGenerator.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfGenerator.java @@ -52,4 +52,6 @@ public interface LfGenerator { void updateState(); LfBus getControlledBus(LfNetwork lfNetwork); + + double getSlope(); } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfDanglingLineGenerator.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfDanglingLineGenerator.java index 071fc60a5b..aae8ecd8fe 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfDanglingLineGenerator.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfDanglingLineGenerator.java @@ -78,4 +78,9 @@ protected Optional getReactiveLimits() { public void updateState() { // nothing to update } + + @Override + public double getSlope() { + return 0; + } } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfGeneratorImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfGeneratorImpl.java index 4b3a53d083..151cf0bbd6 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfGeneratorImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfGeneratorImpl.java @@ -134,4 +134,9 @@ public void updateState() { .setP(-targetP) .setQ(Double.isNaN(calculatedQ) ? -generator.getTargetQ() : -calculatedQ); } + + @Override + public double getSlope() { + return 0; + } } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java index 1269372ee6..7f5977af26 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java @@ -7,6 +7,7 @@ package com.powsybl.openloadflow.network.impl; import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.extensions.VoltagePerReactivePowerControl; import com.powsybl.openloadflow.network.PerUnit; import java.util.Objects; @@ -23,6 +24,8 @@ public final class LfStaticVarCompensatorImpl extends AbstractLfGenerator { double nominalV; + private double slope = 0; + private LfStaticVarCompensatorImpl(StaticVarCompensator svc, AbstractLfBus bus, boolean breakers, LfNetworkLoadingReport report) { super(0); this.svc = svc; @@ -60,6 +63,9 @@ public double getMaxQ(double p) { if (svc.getRegulationMode() == StaticVarCompensator.RegulationMode.VOLTAGE) { setVoltageControl(svc.getVoltageSetpoint(), svc.getRegulatingTerminal(), breakers, report); } + if (svc.getExtension(VoltagePerReactivePowerControl.class) != null) { + this.slope = svc.getExtension(VoltagePerReactivePowerControl.class).getSlope() * PerUnit.SB / nominalV; + } } public static LfStaticVarCompensatorImpl create(StaticVarCompensator svc, AbstractLfBus bus, boolean breakers, LfNetworkLoadingReport report) { @@ -108,4 +114,9 @@ public void updateState() { .setP(0) .setQ(Double.isNaN(calculatedQ) ? svc.getReactivePowerSetPoint() : -calculatedQ); } + + @Override + public double getSlope() { + return this.slope; + } } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfVscConverterStationImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfVscConverterStationImpl.java index e9456d5717..fdefc1b833 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfVscConverterStationImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfVscConverterStationImpl.java @@ -86,4 +86,9 @@ public void updateState() { .setP(-targetP) .setQ(Double.isNaN(calculatedQ) ? -station.getReactivePowerSetpoint() : -calculatedQ); } + + @Override + public double getSlope() { + return 0; + } } From 52a076d09e2820406a08618f909697a7b4e0d7ed Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Thu, 6 May 2021 11:31:26 +0200 Subject: [PATCH 03/42] Add GeneratorWithSlopeVoltageEquationTerm. Signed-off-by: Anne Tilloy --- .../ac/equations/AcEquationSystem.java | 12 +- ...GeneratorWithSlopeVoltageEquationTerm.java | 191 ++++++++++++++++++ .../openloadflow/ac/AcLoadFlowSvcTest.java | 23 +++ 3 files changed, 223 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/powsybl/openloadflow/ac/equations/GeneratorWithSlopeVoltageEquationTerm.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 1612ec3af3..9d5ba4b4f1 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -59,9 +59,15 @@ private static void createBusEquations(LfNetwork network, VariableSet variableSe private static void createVoltageControlEquations(VoltageControl voltageControl, LfBus bus, VariableSet variableSet, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { if (voltageControl.isVoltageControlLocal()) { - // FIXME annetill: slope. - EquationTerm vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); - equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm); + EquationTerm vTerm; + List generatorsWithSlope = bus.getGenerators().stream().filter(lfGenerator -> lfGenerator.getSlope() != 0).collect(Collectors.toList()); + if (creationParameters.isVoltagePerReactivePowerControl() && generatorsWithSlope.size() > 0) { + vTerm = new GeneratorWithSlopeVoltageEquationTerm(generatorsWithSlope, bus, variableSet, equationSystem, bus.getVoltageControl().orElse(null).getTargetValue()); + equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm); + } else { + vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); + equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm); + } bus.setV(vTerm); } else if (bus.isVoltageControlled()) { // remote controlled: set voltage equation on this controlled bus diff --git a/src/main/java/com/powsybl/openloadflow/ac/equations/GeneratorWithSlopeVoltageEquationTerm.java b/src/main/java/com/powsybl/openloadflow/ac/equations/GeneratorWithSlopeVoltageEquationTerm.java new file mode 100644 index 0000000000..fb95fb894b --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/GeneratorWithSlopeVoltageEquationTerm.java @@ -0,0 +1,191 @@ +/** + * 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.ac.equations; + +import com.powsybl.commons.PowsyblException; +import com.powsybl.openloadflow.equations.*; +import com.powsybl.openloadflow.network.ElementType; +import com.powsybl.openloadflow.network.LfBus; +import com.powsybl.openloadflow.network.LfGenerator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +/** + * @author Anne Tilloy + */ +public class GeneratorWithSlopeVoltageEquationTerm extends AbstractNamedEquationTerm { + + private static final Logger LOGGER = LoggerFactory.getLogger(GeneratorWithSlopeVoltageEquationTerm.class); + + private final List generators; + + private double slope; //only one generator with slope supported. + + private final LfBus bus; + + private final EquationSystem equationSystem; + + private final Variable vVar; + + private final Variable phiVar; + + private final List variables; + + private double calculatedTargetV; + + private double dcalculatedTargetVdv; + + private double dcalculatedTargetVdph; + + private double sumTargetQGenerators; + + public GeneratorWithSlopeVoltageEquationTerm(List generators, LfBus bus, VariableSet variableSet, EquationSystem equationSystem, double initialCalculatedTargetV) { + this.generators = generators; + this.bus = bus; + this.equationSystem = equationSystem; + + if (generators.size() > 1) { + throw new PowsyblException("Several generators with a non-zero slope are controlling the bus " + bus.getId() + ": not supported yet"); + } else { + slope = generators.get(0).getSlope(); + } + + vVar = variableSet.getVariable(bus.getNum(), VariableType.BUS_V); + phiVar = variableSet.getVariable(bus.getNum(), VariableType.BUS_PHI); + variables = Arrays.asList(vVar, phiVar); + + calculatedTargetV = initialCalculatedTargetV; + + sumTargetQGenerators = getSumTargetQGenerators(); + } + + @Override + protected String getName() { + return null; + } + + @Override + public ElementType getElementType() { + return ElementType.BUS; + } + + @Override + public int getElementNum() { + return bus.getNum(); + } + + @Override + public List getVariables() { + return variables; + } + + @Override + public void update(double[] x) { + Objects.requireNonNull(x); + + // Equation qBus = (Equation) bus.getQ(); + Equation qBus = equationSystem.createEquation(bus.getNum(), EquationType.BUS_Q); + + EvalAndDerOnTermsFromEquationBUSQ evalAndDerOnTermsFromEquationBUSQ = evalAndDerOnTermsFromEquationBUSQ(x, qBus); + + // given : QbusMinusShunts = Qsvcs - QloadsAndBatteries + Qgenerators + // then : Q(U, theta) = Qsvcs = QbusMinusShunts + QloadsAndBatteries - Qgenerators + double qSvc = evalAndDerOnTermsFromEquationBUSQ.qBusMinusShunts + bus.getLoadTargetQ() - sumTargetQGenerators; + // f(U, theta) = U + lambda * Q(U, theta) + calculatedTargetV = x[vVar.getRow()] + slope * qSvc; + // dfdU = 1 + lambda dQdU + // Q remains constant for loads, batteries and generators, then derivative of Q is zero for this items + dcalculatedTargetVdv = 1 + slope * evalAndDerOnTermsFromEquationBUSQ.dQdVbusMinusShunts; + // dfdtheta = lambda * dQdtheta + dcalculatedTargetVdph = slope * evalAndDerOnTermsFromEquationBUSQ.dQdPHbusMinusShunts; + } + + @Override + public double eval() { + return calculatedTargetV; + } + + @Override + public double der(Variable variable) { + Objects.requireNonNull(variable); + if (variable.equals(vVar)) { + return dcalculatedTargetVdv; + } else if (variable.equals(phiVar)) { + return dcalculatedTargetVdph; + } else { + throw new IllegalStateException("Unknown variable: " + variable); + } + } + + @Override + public boolean hasRhs() { + return false; + } + + @Override + public double rhs() { + return 0; + } + + private class EvalAndDerOnTermsFromEquationBUSQ { + private final double qBusMinusShunts; + private final double dQdVbusMinusShunts; + private final double dQdPHbusMinusShunts; + + public EvalAndDerOnTermsFromEquationBUSQ(double qBusMinusShunts, double dQdVbusMinusShunts, double dQdPHbusMinusShunts) { + this.qBusMinusShunts = qBusMinusShunts; + this.dQdVbusMinusShunts = dQdVbusMinusShunts; + this.dQdPHbusMinusShunts = dQdPHbusMinusShunts; + } + } + + private boolean hasToEvalAndDerTerm(EquationTerm equationTerm) { + return equationTerm.isActive() && + (equationTerm instanceof ClosedBranchSide1ReactiveFlowEquationTerm + || equationTerm instanceof ClosedBranchSide2ReactiveFlowEquationTerm + || equationTerm instanceof OpenBranchSide1ReactiveFlowEquationTerm + || equationTerm instanceof OpenBranchSide2ReactiveFlowEquationTerm + || equationTerm instanceof ShuntCompensatorReactiveFlowEquationTerm); + } + + private boolean hasPhiVar(EquationTerm equationTerm) { + return equationTerm instanceof ClosedBranchSide1ReactiveFlowEquationTerm + || equationTerm instanceof ClosedBranchSide2ReactiveFlowEquationTerm; + } + + private EvalAndDerOnTermsFromEquationBUSQ evalAndDerOnTermsFromEquationBUSQ(double[] x, Equation qBus) { + double qBusMinusShunts = 0; + double dQdVbusMinusShunts = 0; + double dQdPHbusMinusShunts = 0; + + for (EquationTerm equationTerm : qBus.getTerms()) { + if (hasToEvalAndDerTerm(equationTerm)) { + equationTerm.update(x); + qBusMinusShunts += equationTerm.eval(); + dQdVbusMinusShunts += equationTerm.der(vVar); + if (hasPhiVar(equationTerm)) { + dQdPHbusMinusShunts += equationTerm.der(phiVar); + } + } + } + return new EvalAndDerOnTermsFromEquationBUSQ(qBusMinusShunts, dQdVbusMinusShunts, dQdPHbusMinusShunts); + } + + private double getSumTargetQGenerators() { + double sumTargetQGenerators = 0; + for (LfGenerator lfGenerator : bus.getGenerators()) { + if (!lfGenerator.hasVoltageControl()) { + sumTargetQGenerators += lfGenerator.getTargetQ(); + } + } + return sumTargetQGenerators; + } +} diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java index 7bc9987faa..154d03b05b 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java @@ -7,6 +7,7 @@ package com.powsybl.openloadflow.ac; import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.extensions.VoltagePerReactivePowerControlAdder; import com.powsybl.loadflow.LoadFlow; import com.powsybl.loadflow.LoadFlowParameters; import com.powsybl.loadflow.LoadFlowResult; @@ -162,4 +163,26 @@ void shouldReachReactiveMaxLimit() { assertTrue(result.isOk()); assertReactivePowerEquals(-svc1.getBmin() * svc1.getVoltageSetpoint() * svc1.getVoltageSetpoint(), svc1.getTerminal()); // min reactive limit has been correctly reached } + + @Test + void testSvcWithSlope() { + svc1.setVoltageSetPoint(385) + .setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE); + svc1.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(0.03).add(); + + parameters.getExtension(OpenLoadFlowParameters.class).setVoltagePerReactivePowerControl(true); + LoadFlowResult result = loadFlowRunner.run(network, parameters); + assertTrue(result.isOk()); + + assertVoltageEquals(390, bus1); + assertAngleEquals(0, bus1); + assertVoltageEquals(385.001, bus2); + assertAngleEquals(-0.022026, bus2); + assertActivePowerEquals(101.467, l1.getTerminal1()); + assertReactivePowerEquals(246.249, l1.getTerminal1()); + assertActivePowerEquals(-101, l1.getTerminal2()); + assertReactivePowerEquals(-244.850, l1.getTerminal2()); + assertActivePowerEquals(0, svc1.getTerminal()); + assertReactivePowerEquals(94.850, svc1.getTerminal()); + } } From d1a5910797adcc31db5e854f575189cc875a2b40 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Fri, 21 May 2021 12:14:26 +0200 Subject: [PATCH 04/42] Introduce new type of bus for equation. --- .../com/powsybl/openloadflow/ac/equations/AcEquationSystem.java | 2 +- src/main/java/com/powsybl/openloadflow/equations/Equation.java | 1 + .../java/com/powsybl/openloadflow/equations/EquationType.java | 1 + .../java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) 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 9d5ba4b4f1..2d7f660070 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -63,7 +63,7 @@ private static void createVoltageControlEquations(VoltageControl voltageControl, List generatorsWithSlope = bus.getGenerators().stream().filter(lfGenerator -> lfGenerator.getSlope() != 0).collect(Collectors.toList()); if (creationParameters.isVoltagePerReactivePowerControl() && generatorsWithSlope.size() > 0) { vTerm = new GeneratorWithSlopeVoltageEquationTerm(generatorsWithSlope, bus, variableSet, equationSystem, bus.getVoltageControl().orElse(null).getTargetValue()); - equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm); + equationSystem.createEquation(bus.getNum(), EquationType.BUS_V_SLOPE).addTerm(vTerm); } else { vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm); diff --git a/src/main/java/com/powsybl/openloadflow/equations/Equation.java b/src/main/java/com/powsybl/openloadflow/equations/Equation.java index 595a4b4ed5..90a840ba62 100644 --- a/src/main/java/com/powsybl/openloadflow/equations/Equation.java +++ b/src/main/java/com/powsybl/openloadflow/equations/Equation.java @@ -182,6 +182,7 @@ void initTarget(LfNetwork network, double[] targets) { break; case BUS_V: + case BUS_V_SLOPE: targets[column] = getBusTargetV(network.getBus(num)); break; diff --git a/src/main/java/com/powsybl/openloadflow/equations/EquationType.java b/src/main/java/com/powsybl/openloadflow/equations/EquationType.java index e719252b8c..47dcd64676 100644 --- a/src/main/java/com/powsybl/openloadflow/equations/EquationType.java +++ b/src/main/java/com/powsybl/openloadflow/equations/EquationType.java @@ -16,6 +16,7 @@ public enum EquationType { BUS_I("b_i", ElementType.BUS), BUS_Q("q", ElementType.BUS), BUS_V("v", ElementType.BUS), + BUS_V_SLOPE("v_slope", ElementType.BUS), BUS_PHI("\u03C6", ElementType.BUS), BRANCH_P("t", ElementType.BRANCH), BRANCH_I("i", ElementType.BRANCH), diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java index 154d03b05b..99d835ab7e 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java @@ -176,7 +176,7 @@ void testSvcWithSlope() { assertVoltageEquals(390, bus1); assertAngleEquals(0, bus1); - assertVoltageEquals(385.001, bus2); + assertVoltageEquals(387.845, bus2); assertAngleEquals(-0.022026, bus2); assertActivePowerEquals(101.467, l1.getTerminal1()); assertReactivePowerEquals(246.249, l1.getTerminal1()); From 48dd622116771f70a8eec7fb01e036ac552c9795 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 25 May 2021 14:44:44 +0200 Subject: [PATCH 05/42] Bug fix. Signed-off-by: Anne Tilloy --- .../com/powsybl/openloadflow/ac/equations/AcEquationSystem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2d7f660070..037cc2c8c7 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -62,7 +62,7 @@ private static void createVoltageControlEquations(VoltageControl voltageControl, EquationTerm vTerm; List generatorsWithSlope = bus.getGenerators().stream().filter(lfGenerator -> lfGenerator.getSlope() != 0).collect(Collectors.toList()); if (creationParameters.isVoltagePerReactivePowerControl() && generatorsWithSlope.size() > 0) { - vTerm = new GeneratorWithSlopeVoltageEquationTerm(generatorsWithSlope, bus, variableSet, equationSystem, bus.getVoltageControl().orElse(null).getTargetValue()); + vTerm = new GeneratorWithSlopeVoltageEquationTerm(generatorsWithSlope, bus, variableSet, equationSystem, bus.getVoltageControl().map(VoltageControl::getTargetValue).orElse(Double.NaN)); equationSystem.createEquation(bus.getNum(), EquationType.BUS_V_SLOPE).addTerm(vTerm); } else { vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); From 9cc07076aad613e1c15dcaf5040ca5d7455a884c Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 26 May 2021 17:58:14 +0200 Subject: [PATCH 06/42] Add unit tests. Add switch PV to PQ. Signed-off-by: Anne Tilloy --- pom.xml | 2 +- .../ac/equations/AcEquationSystem.java | 12 ++- .../ac/equations/AcEquationSystemUpdater.java | 18 +++- ...GeneratorWithSlopeVoltageEquationTerm.java | 3 +- .../openloadflow/ac/AcLoadFlowSvcTest.java | 82 +++++++++++++++++++ src/test/resources/logback-test.xml | 2 +- 6 files changed, 111 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 48604bb1f1..529872d443 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ 5.5.2 1.6.2 - 4.2.0-RC1 + 4.3.0-SNAPSHOT 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 037cc2c8c7..c857a60efd 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -60,9 +60,15 @@ private static void createVoltageControlEquations(VoltageControl voltageControl, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { if (voltageControl.isVoltageControlLocal()) { EquationTerm vTerm; - List generatorsWithSlope = bus.getGenerators().stream().filter(lfGenerator -> lfGenerator.getSlope() != 0).collect(Collectors.toList()); - if (creationParameters.isVoltagePerReactivePowerControl() && generatorsWithSlope.size() > 0) { - vTerm = new GeneratorWithSlopeVoltageEquationTerm(generatorsWithSlope, bus, variableSet, equationSystem, bus.getVoltageControl().map(VoltageControl::getTargetValue).orElse(Double.NaN)); + + List generatorsControllingVoltage = bus.getGenerators().stream() + .filter(lfGenerator -> lfGenerator.hasVoltageControl()) + .collect(Collectors.toList()); + List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); + + if (creationParameters.isVoltagePerReactivePowerControl() && generatorsControllingVoltageWithSlope.size() == 1 && generatorsControllingVoltage.size() == 1) { + // we only support one generator controlling voltage with a non zero slope at a bus. + vTerm = new GeneratorWithSlopeVoltageEquationTerm(generatorsControllingVoltageWithSlope, bus, variableSet, equationSystem, bus.getVoltageControl().map(VoltageControl::getTargetValue).orElse(Double.NaN)); equationSystem.createEquation(bus.getNum(), EquationType.BUS_V_SLOPE).addTerm(vTerm); } else { vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); 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 ae9d7d2f0a..bd866d1dc5 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java @@ -47,7 +47,23 @@ private void updateControlledBus(VoltageControl voltageControl, EquationSystem e List controllerBusesWithVoltageControlOn = controllerBuses.stream() .filter(LfBus::isVoltageControllerEnabled) .collect(Collectors.toList()); - equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V).setActive(!controllerBusesWithVoltageControlOn.isEmpty()); + + // is there one static var compensator with a non-zero slope + boolean hasEquationBusVWithSlope = false; + if (controllerBuses.size() == 1) { + List generatorsControllingVoltage = controllerBuses.iterator().next().getGenerators().stream() + .filter(lfGenerator -> lfGenerator.hasVoltageControl()) + .collect(Collectors.toList()); + List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); + hasEquationBusVWithSlope = (generatorsControllingVoltageWithSlope.size() == 1) && creationParameters.isVoltagePerReactivePowerControl(); + } + + if (!hasEquationBusVWithSlope) { + equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V).setActive(!controllerBusesWithVoltageControlOn.isEmpty()); + } else { + // we only support one controlling static var compensator without any other controlling generators + equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V_SLOPE).setActive(false); + } // create reactive power equations on controller buses that have voltage control on if (!controllerBusesWithVoltageControlOn.isEmpty()) { diff --git a/src/main/java/com/powsybl/openloadflow/ac/equations/GeneratorWithSlopeVoltageEquationTerm.java b/src/main/java/com/powsybl/openloadflow/ac/equations/GeneratorWithSlopeVoltageEquationTerm.java index fb95fb894b..fcd4081e4f 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/GeneratorWithSlopeVoltageEquationTerm.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/GeneratorWithSlopeVoltageEquationTerm.java @@ -91,8 +91,7 @@ public List getVariables() { public void update(double[] x) { Objects.requireNonNull(x); - // Equation qBus = (Equation) bus.getQ(); - Equation qBus = equationSystem.createEquation(bus.getNum(), EquationType.BUS_Q); + Equation qBus = (Equation) bus.getQ(); EvalAndDerOnTermsFromEquationBUSQ evalAndDerOnTermsFromEquationBUSQ = evalAndDerOnTermsFromEquationBUSQ(x, qBus); diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java index 99d835ab7e..0dc1f54a3c 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java @@ -185,4 +185,86 @@ void testSvcWithSlope() { assertActivePowerEquals(0, svc1.getTerminal()); assertReactivePowerEquals(94.850, svc1.getTerminal()); } + + @Test + void testSvcWithSlope2() { + // Test switch PV to PQ + svc1.setVoltageSetPoint(440) + .setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE); + svc1.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(0.03).add(); + + parameters.getExtension(OpenLoadFlowParameters.class).setVoltagePerReactivePowerControl(true); + LoadFlowResult result = loadFlowRunner.run(network, parameters); + assertTrue(result.isOk()); + + assertVoltageEquals(390, bus1); + assertAngleEquals(0, bus1); + assertVoltageEquals(398.190, bus2); + assertAngleEquals(-0.526124, bus2); + assertActivePowerEquals(109.018, l1.getTerminal1()); + assertReactivePowerEquals(-1098.933, l1.getTerminal1()); + assertActivePowerEquals(-101, l1.getTerminal2()); + assertReactivePowerEquals(1122.987, l1.getTerminal2()); + assertActivePowerEquals(0, svc1.getTerminal()); + assertReactivePowerEquals(-1268.445, svc1.getTerminal()); + } + + @Test + void testSvcWithSlope3() { + Generator gen = network.getVoltageLevel("vl2").newGenerator() + .setId("gen") + .setBus("b2") + .setConnectableBus("b2") + .setTargetP(0) + .setTargetV(385) + .setTargetQ(100) + .setMaxP(100) + .setMinP(0) + .setVoltageRegulatorOn(true) + .add(); + + svc1.setVoltageSetPoint(385) + .setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE); + + parameters.getExtension(OpenLoadFlowParameters.class).setVoltagePerReactivePowerControl(true); + LoadFlowResult result = loadFlowRunner.run(network, parameters); + assertTrue(result.isOk()); + + assertVoltageEquals(390, bus1); + assertAngleEquals(0, bus1); + assertVoltageEquals(385, bus2); + assertAngleEquals(0.116345, bus2); + assertReactivePowerEquals(228.948, svc1.getTerminal()); // same behaviour as slope = 0 + assertReactivePowerEquals(228.948, gen.getTerminal()); // same behaviour as slope = 0 + } + + @Test + void testSvcWithSlope4() { + + StaticVarCompensator svc2 = network.getVoltageLevel("vl2").newStaticVarCompensator() + .setId("svc2") + .setConnectableBus("b2") + .setBus("b2") + .setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE) + .setVoltageSetpoint(385) + .setBmin(-0.008) + .setBmax(0.008) + .add(); + + svc1.setVoltageSetPoint(385) + .setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE); + svc2.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(0.03).add(); + svc1.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(0.03).add(); + + parameters.getExtension(OpenLoadFlowParameters.class).setVoltagePerReactivePowerControl(true); + LoadFlowResult result = loadFlowRunner.run(network, parameters); + assertTrue(result.isOk()); + + assertVoltageEquals(390, bus1); + assertAngleEquals(0, bus1); + assertVoltageEquals(385, bus2); + assertAngleEquals(0.116345, bus2); + assertReactivePowerEquals(228.948, svc1.getTerminal()); // same behaviour as slope = 0 + assertReactivePowerEquals(228.948, svc2.getTerminal()); // same behaviour as slope = 0 + } } diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 03f44ff80a..2f5e8aaf22 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -13,7 +13,7 @@ %-5p %d{HH:mm:ss.SSS} %-20C{1} | %m%n - + From 5b1c27fe0a732ebbdf2e3fe23b69d85d4820b50e Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 26 May 2021 18:10:43 +0200 Subject: [PATCH 07/42] Fix pom.xml. Signed-off-by: Anne Tilloy --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 529872d443..48604bb1f1 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ 5.5.2 1.6.2 - 4.3.0-SNAPSHOT + 4.2.0-RC1 From 63fa182b0e53b9202178538605b0c848f9b874ca Mon Sep 17 00:00:00 2001 From: Hadrien Date: Thu, 27 May 2021 16:59:36 +0200 Subject: [PATCH 08/42] Add a test with a generator at bus2 not controlling voltage Signed-off-by: Hadrien --- .../openloadflow/ac/AcLoadFlowSvcTest.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java index 0dc1f54a3c..a995d756e2 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java @@ -267,4 +267,39 @@ void testSvcWithSlope4() { assertReactivePowerEquals(228.948, svc1.getTerminal()); // same behaviour as slope = 0 assertReactivePowerEquals(228.948, svc2.getTerminal()); // same behaviour as slope = 0 } + + @Test + void testSvcWithSlope5() { + // With a generator at bus2 not controlling voltage + svc1.setVoltageSetPoint(385) + .setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE); + svc1.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(0.03).add(); + + Generator gen = network.getVoltageLevel("vl2").newGenerator() + .setId("gen") + .setBus("b2") + .setConnectableBus("b2") + .setTargetP(0) + .setTargetV(385) + .setTargetQ(100) + .setMaxP(100) + .setMinP(0) + .setVoltageRegulatorOn(false) + .add(); + + parameters.getExtension(OpenLoadFlowParameters.class).setVoltagePerReactivePowerControl(true); + LoadFlowResult result = loadFlowRunner.run(network, parameters); + assertTrue(result.isOk()); + + assertVoltageEquals(390, bus1); + assertAngleEquals(0, bus1); + assertVoltageEquals(388.462, bus2); + assertAngleEquals(-0.052035, bus2); + assertActivePowerEquals(101.249, l1.getTerminal1()); + assertReactivePowerEquals(166.157, l1.getTerminal1()); + assertActivePowerEquals(-101, l1.getTerminal2()); + assertReactivePowerEquals(-165.410, l1.getTerminal2()); + assertActivePowerEquals(0, svc1.getTerminal()); + assertReactivePowerEquals(115.410, svc1.getTerminal()); + } } From 911be17cd70647cea496368bb00261bf0271176f Mon Sep 17 00:00:00 2001 From: Hadrien Date: Mon, 31 May 2021 16:33:51 +0200 Subject: [PATCH 09/42] Using already existing Terms instead of GeneratorWithSlopeVoltageEquationTerm Signed-off-by: Hadrien --- .../ac/equations/AcEquationSystem.java | 47 ++++- ...GeneratorWithSlopeVoltageEquationTerm.java | 190 ------------------ .../openloadflow/equations/Equation.java | 17 +- 3 files changed, 62 insertions(+), 192 deletions(-) delete mode 100644 src/main/java/com/powsybl/openloadflow/ac/equations/GeneratorWithSlopeVoltageEquationTerm.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 c857a60efd..f341e60226 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -68,7 +68,9 @@ private static void createVoltageControlEquations(VoltageControl voltageControl, if (creationParameters.isVoltagePerReactivePowerControl() && generatorsControllingVoltageWithSlope.size() == 1 && generatorsControllingVoltage.size() == 1) { // we only support one generator controlling voltage with a non zero slope at a bus. - vTerm = new GeneratorWithSlopeVoltageEquationTerm(generatorsControllingVoltageWithSlope, bus, variableSet, equationSystem, bus.getVoltageControl().map(VoltageControl::getTargetValue).orElse(Double.NaN)); + // Equation is: U + slope * Qsvc = TargetU + // Which is modeled with: U + slope * (sum_lines Qline) = TargetU - slope*loadQ + slope*genQ + vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); equationSystem.createEquation(bus.getNum(), EquationType.BUS_V_SLOPE).addTerm(vTerm); } else { vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); @@ -364,6 +366,15 @@ private static void createImpedantBranch(LfBranch branch, LfBus bus1, LfBus bus2 } sq1.addTerm(q1); branch.setQ1(q1); + // Add term slope * Q for svc + List generatorsControllingVoltage = bus1.getGenerators().stream() + .filter(lfGenerator -> lfGenerator.hasVoltageControl()) + .collect(Collectors.toList()); + List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); + if (creationParameters.isVoltagePerReactivePowerControl() && generatorsControllingVoltageWithSlope.size() == 1 && generatorsControllingVoltage.size() == 1) { + Equation uq1 = equationSystem.createEquation(bus1.getNum(), EquationType.BUS_V_SLOPE); + uq1.addTerm(EquationTerm.multiply(q1, generatorsControllingVoltageWithSlope.get(0).getSlope())); + } } if (p2 != null) { Equation sp2 = equationSystem.createEquation(bus2.getNum(), EquationType.BUS_P); @@ -383,6 +394,15 @@ private static void createImpedantBranch(LfBranch branch, LfBus bus1, LfBus bus2 } sq2.addTerm(q2); branch.setQ2(q2); + // Add term slope * Q for svc + List generatorsControllingVoltage = bus2.getGenerators().stream() + .filter(lfGenerator -> lfGenerator.hasVoltageControl()) + .collect(Collectors.toList()); + List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); + if (creationParameters.isVoltagePerReactivePowerControl() && generatorsControllingVoltageWithSlope.size() == 1 && generatorsControllingVoltage.size() == 1) { + Equation uq2 = equationSystem.createEquation(bus2.getNum(), EquationType.BUS_V_SLOPE); + uq2.addTerm(EquationTerm.multiply(q2, generatorsControllingVoltageWithSlope.get(0).getSlope())); + } } if (creationParameters.isForceA1Var() && branch.hasPhaseControlCapability()) { @@ -445,6 +465,31 @@ public static EquationSystem create(LfNetwork network, VariableSet variableSet, EquationSystem equationSystem = new EquationSystem(network, true); + // Bus with only one generator contralling voltage with a slope and connected to a non impedent branch is not yet supported + List zeroBranches = network.getBranches().stream() + .filter(b -> LfNetwork.isZeroImpedanceBranch(b)) + .collect(Collectors.toList()); + for (LfBranch zeroBranch : zeroBranches) { + List generatorsControllingVoltageat1 = zeroBranch.getBus1().getGenerators().stream() + .filter(lfGenerator -> lfGenerator.hasVoltageControl()) + .collect(Collectors.toList()); + List generatorsControllingVoltageWithSlopeat1 = generatorsControllingVoltageat1.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); + + if (creationParameters.isVoltagePerReactivePowerControl() && generatorsControllingVoltageWithSlopeat1.size() == 1 && generatorsControllingVoltageat1.size() == 1) { + throw new PowsyblException( + "Zero impedance branche that is connected to a bus where only one generator is controling voltage with a slope (buss: " + zeroBranch.getBus1() + ";branch: " + zeroBranch + ")"); + } + List generatorsControllingVoltageat2 = zeroBranch.getBus2().getGenerators().stream() + .filter(lfGenerator -> lfGenerator.hasVoltageControl()) + .collect(Collectors.toList()); + List generatorsControllingVoltageWithSlopeat2 = generatorsControllingVoltageat2.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); + + if (creationParameters.isVoltagePerReactivePowerControl() && generatorsControllingVoltageWithSlopeat2.size() == 1 && generatorsControllingVoltageat2.size() == 1) { + throw new PowsyblException( + "Zero impedance branche that is connected to a bus where only one generator is controling voltage with a slope (buss: " + zeroBranch.getBus2() + ";branch: " + zeroBranch + ")"); + } + } + createBusEquations(network, variableSet, creationParameters, equationSystem); createBranchEquations(network, variableSet, creationParameters, equationSystem); diff --git a/src/main/java/com/powsybl/openloadflow/ac/equations/GeneratorWithSlopeVoltageEquationTerm.java b/src/main/java/com/powsybl/openloadflow/ac/equations/GeneratorWithSlopeVoltageEquationTerm.java deleted file mode 100644 index fcd4081e4f..0000000000 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/GeneratorWithSlopeVoltageEquationTerm.java +++ /dev/null @@ -1,190 +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.ac.equations; - -import com.powsybl.commons.PowsyblException; -import com.powsybl.openloadflow.equations.*; -import com.powsybl.openloadflow.network.ElementType; -import com.powsybl.openloadflow.network.LfBus; -import com.powsybl.openloadflow.network.LfGenerator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -/** - * @author Anne Tilloy - */ -public class GeneratorWithSlopeVoltageEquationTerm extends AbstractNamedEquationTerm { - - private static final Logger LOGGER = LoggerFactory.getLogger(GeneratorWithSlopeVoltageEquationTerm.class); - - private final List generators; - - private double slope; //only one generator with slope supported. - - private final LfBus bus; - - private final EquationSystem equationSystem; - - private final Variable vVar; - - private final Variable phiVar; - - private final List variables; - - private double calculatedTargetV; - - private double dcalculatedTargetVdv; - - private double dcalculatedTargetVdph; - - private double sumTargetQGenerators; - - public GeneratorWithSlopeVoltageEquationTerm(List generators, LfBus bus, VariableSet variableSet, EquationSystem equationSystem, double initialCalculatedTargetV) { - this.generators = generators; - this.bus = bus; - this.equationSystem = equationSystem; - - if (generators.size() > 1) { - throw new PowsyblException("Several generators with a non-zero slope are controlling the bus " + bus.getId() + ": not supported yet"); - } else { - slope = generators.get(0).getSlope(); - } - - vVar = variableSet.getVariable(bus.getNum(), VariableType.BUS_V); - phiVar = variableSet.getVariable(bus.getNum(), VariableType.BUS_PHI); - variables = Arrays.asList(vVar, phiVar); - - calculatedTargetV = initialCalculatedTargetV; - - sumTargetQGenerators = getSumTargetQGenerators(); - } - - @Override - protected String getName() { - return null; - } - - @Override - public ElementType getElementType() { - return ElementType.BUS; - } - - @Override - public int getElementNum() { - return bus.getNum(); - } - - @Override - public List getVariables() { - return variables; - } - - @Override - public void update(double[] x) { - Objects.requireNonNull(x); - - Equation qBus = (Equation) bus.getQ(); - - EvalAndDerOnTermsFromEquationBUSQ evalAndDerOnTermsFromEquationBUSQ = evalAndDerOnTermsFromEquationBUSQ(x, qBus); - - // given : QbusMinusShunts = Qsvcs - QloadsAndBatteries + Qgenerators - // then : Q(U, theta) = Qsvcs = QbusMinusShunts + QloadsAndBatteries - Qgenerators - double qSvc = evalAndDerOnTermsFromEquationBUSQ.qBusMinusShunts + bus.getLoadTargetQ() - sumTargetQGenerators; - // f(U, theta) = U + lambda * Q(U, theta) - calculatedTargetV = x[vVar.getRow()] + slope * qSvc; - // dfdU = 1 + lambda dQdU - // Q remains constant for loads, batteries and generators, then derivative of Q is zero for this items - dcalculatedTargetVdv = 1 + slope * evalAndDerOnTermsFromEquationBUSQ.dQdVbusMinusShunts; - // dfdtheta = lambda * dQdtheta - dcalculatedTargetVdph = slope * evalAndDerOnTermsFromEquationBUSQ.dQdPHbusMinusShunts; - } - - @Override - public double eval() { - return calculatedTargetV; - } - - @Override - public double der(Variable variable) { - Objects.requireNonNull(variable); - if (variable.equals(vVar)) { - return dcalculatedTargetVdv; - } else if (variable.equals(phiVar)) { - return dcalculatedTargetVdph; - } else { - throw new IllegalStateException("Unknown variable: " + variable); - } - } - - @Override - public boolean hasRhs() { - return false; - } - - @Override - public double rhs() { - return 0; - } - - private class EvalAndDerOnTermsFromEquationBUSQ { - private final double qBusMinusShunts; - private final double dQdVbusMinusShunts; - private final double dQdPHbusMinusShunts; - - public EvalAndDerOnTermsFromEquationBUSQ(double qBusMinusShunts, double dQdVbusMinusShunts, double dQdPHbusMinusShunts) { - this.qBusMinusShunts = qBusMinusShunts; - this.dQdVbusMinusShunts = dQdVbusMinusShunts; - this.dQdPHbusMinusShunts = dQdPHbusMinusShunts; - } - } - - private boolean hasToEvalAndDerTerm(EquationTerm equationTerm) { - return equationTerm.isActive() && - (equationTerm instanceof ClosedBranchSide1ReactiveFlowEquationTerm - || equationTerm instanceof ClosedBranchSide2ReactiveFlowEquationTerm - || equationTerm instanceof OpenBranchSide1ReactiveFlowEquationTerm - || equationTerm instanceof OpenBranchSide2ReactiveFlowEquationTerm - || equationTerm instanceof ShuntCompensatorReactiveFlowEquationTerm); - } - - private boolean hasPhiVar(EquationTerm equationTerm) { - return equationTerm instanceof ClosedBranchSide1ReactiveFlowEquationTerm - || equationTerm instanceof ClosedBranchSide2ReactiveFlowEquationTerm; - } - - private EvalAndDerOnTermsFromEquationBUSQ evalAndDerOnTermsFromEquationBUSQ(double[] x, Equation qBus) { - double qBusMinusShunts = 0; - double dQdVbusMinusShunts = 0; - double dQdPHbusMinusShunts = 0; - - for (EquationTerm equationTerm : qBus.getTerms()) { - if (hasToEvalAndDerTerm(equationTerm)) { - equationTerm.update(x); - qBusMinusShunts += equationTerm.eval(); - dQdVbusMinusShunts += equationTerm.der(vVar); - if (hasPhiVar(equationTerm)) { - dQdPHbusMinusShunts += equationTerm.der(phiVar); - } - } - } - return new EvalAndDerOnTermsFromEquationBUSQ(qBusMinusShunts, dQdVbusMinusShunts, dQdPHbusMinusShunts); - } - - private double getSumTargetQGenerators() { - double sumTargetQGenerators = 0; - for (LfGenerator lfGenerator : bus.getGenerators()) { - if (!lfGenerator.hasVoltageControl()) { - sumTargetQGenerators += lfGenerator.getTargetQ(); - } - } - return sumTargetQGenerators; - } -} diff --git a/src/main/java/com/powsybl/openloadflow/equations/Equation.java b/src/main/java/com/powsybl/openloadflow/equations/Equation.java index 90a840ba62..b32c923ee4 100644 --- a/src/main/java/com/powsybl/openloadflow/equations/Equation.java +++ b/src/main/java/com/powsybl/openloadflow/equations/Equation.java @@ -182,9 +182,24 @@ void initTarget(LfNetwork network, double[] targets) { break; case BUS_V: - case BUS_V_SLOPE: targets[column] = getBusTargetV(network.getBus(num)); break; + case BUS_V_SLOPE: + double targetV = getBusTargetV(network.getBus(num)); + double qbusGen = 0; + for (LfGenerator lfGenerator : network.getBus(num).getGenerators()) { + if (!lfGenerator.hasVoltageControl()) { + qbusGen += lfGenerator.getTargetQ(); + } + } + double qbusLoad = network.getBus(num).getLoadTargetQ(); + List generatorsControllingVoltage = network.getBus(num).getGenerators().stream() + .filter(lfGenerator -> lfGenerator.hasVoltageControl()) + .collect(Collectors.toList()); + List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); + double slope = generatorsControllingVoltageWithSlope.get(0).getSlope(); + targets[column] = targetV - slope * (qbusLoad - qbusGen); + break; case BUS_PHI: targets[column] = 0; From 3dcaa3f6da148944f0cea8b3022bbb825afaddd8 Mon Sep 17 00:00:00 2001 From: Hadrien Date: Mon, 31 May 2021 16:34:18 +0200 Subject: [PATCH 10/42] Slightly modifying some test results Signed-off-by: Hadrien --- .../openloadflow/ac/AcLoadFlowSvcTest.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java index a995d756e2..84fae22188 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowSvcTest.java @@ -178,12 +178,12 @@ void testSvcWithSlope() { assertAngleEquals(0, bus1); assertVoltageEquals(387.845, bus2); assertAngleEquals(-0.022026, bus2); - assertActivePowerEquals(101.467, l1.getTerminal1()); - assertReactivePowerEquals(246.249, l1.getTerminal1()); + assertActivePowerEquals(101.466, l1.getTerminal1()); + assertReactivePowerEquals(246.252, l1.getTerminal1()); assertActivePowerEquals(-101, l1.getTerminal2()); - assertReactivePowerEquals(-244.850, l1.getTerminal2()); + assertReactivePowerEquals(-244.853, l1.getTerminal2()); assertActivePowerEquals(0, svc1.getTerminal()); - assertReactivePowerEquals(94.850, svc1.getTerminal()); + assertReactivePowerEquals(94.853, svc1.getTerminal()); } @Test @@ -294,12 +294,12 @@ void testSvcWithSlope5() { assertVoltageEquals(390, bus1); assertAngleEquals(0, bus1); assertVoltageEquals(388.462, bus2); - assertAngleEquals(-0.052035, bus2); + assertAngleEquals(-0.052034, bus2); assertActivePowerEquals(101.249, l1.getTerminal1()); - assertReactivePowerEquals(166.157, l1.getTerminal1()); + assertReactivePowerEquals(166.160, l1.getTerminal1()); assertActivePowerEquals(-101, l1.getTerminal2()); - assertReactivePowerEquals(-165.410, l1.getTerminal2()); + assertReactivePowerEquals(-165.413, l1.getTerminal2()); assertActivePowerEquals(0, svc1.getTerminal()); - assertReactivePowerEquals(115.410, svc1.getTerminal()); + assertReactivePowerEquals(115.413, svc1.getTerminal()); } } From 465b39701dd5fa8b408ace4ca30966c3bcee9ecf Mon Sep 17 00:00:00 2001 From: Hadrien Date: Mon, 31 May 2021 16:34:29 +0200 Subject: [PATCH 11/42] Typo Signed-off-by: Hadrien --- .../powsybl/openloadflow/ac/equations/AcEquationSystem.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 f341e60226..afd87fcc2b 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -222,8 +222,8 @@ private static void createNonImpedantBranch(VariableSet variableSet, EquationSys LfBranch branch, LfBus bus1, LfBus bus2) { Optional v1 = equationSystem.getEquation(bus1.getNum(), EquationType.BUS_V); Optional v2 = equationSystem.getEquation(bus2.getNum(), EquationType.BUS_V); - boolean hasV1 = v1.isPresent() && v1.get().isActive(); // may be inactive is the equation has been created for sensitivity - boolean hasV2 = v2.isPresent() && v2.get().isActive(); // may be inactive is the equation has been created for sensitivity + boolean hasV1 = v1.isPresent() && v1.get().isActive(); // may be inactive if the equation has been created for sensitivity + boolean hasV2 = v2.isPresent() && v2.get().isActive(); // may be inactive if the equation has been created for sensitivity if (!(hasV1 && hasV2)) { // create voltage magnitude coupling equation // 0 = v1 - v2 * rho From c177f0374f930270c896e3ba3a4b674744b8398b Mon Sep 17 00:00:00 2001 From: Hadrien Date: Wed, 2 Jun 2021 15:03:23 +0200 Subject: [PATCH 12/42] Factorization and using of getGenerationTargetQ for initial targets of buses with a single SVC with a slope. Signed-off-by: Hadrien --- .../ac/equations/AcEquationSystem.java | 33 +++++++++---------- .../openloadflow/equations/Equation.java | 30 +++++++++-------- 2 files changed, 31 insertions(+), 32 deletions(-) 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 afd87fcc2b..4cac9582fa 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -296,6 +296,17 @@ private static void createDiscreteVoltageControlEquation(LfBus bus, VariableSet } } + private static void createSlopeQEquationTerm(LfBus bus, AcEquationSystemCreationParameters creationParameters, EquationSystem equationSystem, EquationTerm q) { + List generatorsControllingVoltage = bus.getGenerators().stream() + .filter(lfGenerator -> lfGenerator.hasVoltageControl()) + .collect(Collectors.toList()); + List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); + if (creationParameters.isVoltagePerReactivePowerControl() && generatorsControllingVoltageWithSlope.size() == 1 && generatorsControllingVoltage.size() == 1) { + Equation uq1 = equationSystem.createEquation(bus.getNum(), EquationType.BUS_V_SLOPE); + uq1.addTerm(EquationTerm.multiply(q, generatorsControllingVoltageWithSlope.get(0).getSlope())); + } + } + public static void createR1DistributionEquations(EquationSystem equationSystem, VariableSet variableSet, List controllerBranches) { // we choose first controller bus as reference for reactive power @@ -366,15 +377,8 @@ private static void createImpedantBranch(LfBranch branch, LfBus bus1, LfBus bus2 } sq1.addTerm(q1); branch.setQ1(q1); - // Add term slope * Q for svc - List generatorsControllingVoltage = bus1.getGenerators().stream() - .filter(lfGenerator -> lfGenerator.hasVoltageControl()) - .collect(Collectors.toList()); - List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); - if (creationParameters.isVoltagePerReactivePowerControl() && generatorsControllingVoltageWithSlope.size() == 1 && generatorsControllingVoltage.size() == 1) { - Equation uq1 = equationSystem.createEquation(bus1.getNum(), EquationType.BUS_V_SLOPE); - uq1.addTerm(EquationTerm.multiply(q1, generatorsControllingVoltageWithSlope.get(0).getSlope())); - } + // Add term slope * Q for U+lambdaQ control + createSlopeQEquationTerm(bus1, creationParameters, equationSystem, q1); } if (p2 != null) { Equation sp2 = equationSystem.createEquation(bus2.getNum(), EquationType.BUS_P); @@ -394,15 +398,8 @@ private static void createImpedantBranch(LfBranch branch, LfBus bus1, LfBus bus2 } sq2.addTerm(q2); branch.setQ2(q2); - // Add term slope * Q for svc - List generatorsControllingVoltage = bus2.getGenerators().stream() - .filter(lfGenerator -> lfGenerator.hasVoltageControl()) - .collect(Collectors.toList()); - List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); - if (creationParameters.isVoltagePerReactivePowerControl() && generatorsControllingVoltageWithSlope.size() == 1 && generatorsControllingVoltage.size() == 1) { - Equation uq2 = equationSystem.createEquation(bus2.getNum(), EquationType.BUS_V_SLOPE); - uq2.addTerm(EquationTerm.multiply(q2, generatorsControllingVoltageWithSlope.get(0).getSlope())); - } + // Add term slope * Q for U+lambdaQ control + createSlopeQEquationTerm(bus2, creationParameters, equationSystem, q2); } if (creationParameters.isForceA1Var() && branch.hasPhaseControlCapability()) { diff --git a/src/main/java/com/powsybl/openloadflow/equations/Equation.java b/src/main/java/com/powsybl/openloadflow/equations/Equation.java index b32c923ee4..cd0f3aac58 100644 --- a/src/main/java/com/powsybl/openloadflow/equations/Equation.java +++ b/src/main/java/com/powsybl/openloadflow/equations/Equation.java @@ -171,6 +171,20 @@ private static double getRho1DistributionTarget(LfNetwork network, int num, Dist return controllerBranch.getPiModel().getR1() - firstControllerBranch.getPiModel().getR1(); } + private static double getUPlusLambdaQTarget(LfBus bus) { + double targetV = getBusTargetV(bus); + double qbusGen = bus.getGenerationTargetQ(); + double qbusLoad = bus.getLoadTargetQ(); + List generatorsControllingVoltage = bus.getGenerators().stream() + .filter(lfGenerator -> lfGenerator.hasVoltageControl()) + .collect(Collectors.toList()); + List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); + double slope = generatorsControllingVoltageWithSlope.get(0).getSlope(); + double tmp = targetV - slope * (qbusLoad - qbusGen); + System.out.println("Je passe dans l'initialisation de la target pour un U+lambdaQ avec targetV: " + tmp + " bus: " + bus.getId()); + return targetV - slope * (qbusLoad - qbusGen); + } + void initTarget(LfNetwork network, double[] targets) { switch (type) { case BUS_P: @@ -184,21 +198,9 @@ void initTarget(LfNetwork network, double[] targets) { case BUS_V: targets[column] = getBusTargetV(network.getBus(num)); break; + case BUS_V_SLOPE: - double targetV = getBusTargetV(network.getBus(num)); - double qbusGen = 0; - for (LfGenerator lfGenerator : network.getBus(num).getGenerators()) { - if (!lfGenerator.hasVoltageControl()) { - qbusGen += lfGenerator.getTargetQ(); - } - } - double qbusLoad = network.getBus(num).getLoadTargetQ(); - List generatorsControllingVoltage = network.getBus(num).getGenerators().stream() - .filter(lfGenerator -> lfGenerator.hasVoltageControl()) - .collect(Collectors.toList()); - List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); - double slope = generatorsControllingVoltageWithSlope.get(0).getSlope(); - targets[column] = targetV - slope * (qbusLoad - qbusGen); + targets[column] = getUPlusLambdaQTarget(network.getBus(num)); break; case BUS_PHI: From 3ac6154838ec0ff3a27dbff2f06332ac0604ee5f Mon Sep 17 00:00:00 2001 From: Hadrien Date: Wed, 2 Jun 2021 15:06:16 +0200 Subject: [PATCH 13/42] Remove a custom print for debug Signed-off-by: Hadrien --- src/main/java/com/powsybl/openloadflow/equations/Equation.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/equations/Equation.java b/src/main/java/com/powsybl/openloadflow/equations/Equation.java index cd0f3aac58..02f2cf4280 100644 --- a/src/main/java/com/powsybl/openloadflow/equations/Equation.java +++ b/src/main/java/com/powsybl/openloadflow/equations/Equation.java @@ -180,8 +180,6 @@ private static double getUPlusLambdaQTarget(LfBus bus) { .collect(Collectors.toList()); List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); double slope = generatorsControllingVoltageWithSlope.get(0).getSlope(); - double tmp = targetV - slope * (qbusLoad - qbusGen); - System.out.println("Je passe dans l'initialisation de la target pour un U+lambdaQ avec targetV: " + tmp + " bus: " + bus.getId()); return targetV - slope * (qbusLoad - qbusGen); } From 13560db94f5a034431606e61b3be9bd7e23c720b Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 2 Jun 2021 18:50:18 +0200 Subject: [PATCH 14/42] Introduce method getGeneratorControllingVoltageWithSlope for LfBus. Signed-off-by: Anne Tilloy --- .../ac/equations/AcEquationSystem.java | 21 ++++++------------- .../powsybl/openloadflow/network/LfBus.java | 2 ++ .../network/impl/AbstractLfBus.java | 9 ++++++++ 3 files changed, 17 insertions(+), 15 deletions(-) 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 4cac9582fa..836bd33769 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -60,16 +60,10 @@ private static void createVoltageControlEquations(VoltageControl voltageControl, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { if (voltageControl.isVoltageControlLocal()) { EquationTerm vTerm; - - List generatorsControllingVoltage = bus.getGenerators().stream() - .filter(lfGenerator -> lfGenerator.hasVoltageControl()) - .collect(Collectors.toList()); - List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); - - if (creationParameters.isVoltagePerReactivePowerControl() && generatorsControllingVoltageWithSlope.size() == 1 && generatorsControllingVoltage.size() == 1) { + if (creationParameters.isVoltagePerReactivePowerControl() && bus.getGeneratorControllingVoltageWithSlope() != null) { // we only support one generator controlling voltage with a non zero slope at a bus. - // Equation is: U + slope * Qsvc = TargetU - // Which is modeled with: U + slope * (sum_lines Qline) = TargetU - slope*loadQ + slope*genQ + // equation is: V + slope * qSVC = targetV + // which is modeled here with: V + slope * (sum_branch qBranch) = TargetV - slope * qLoads + slope * qGen vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); equationSystem.createEquation(bus.getNum(), EquationType.BUS_V_SLOPE).addTerm(vTerm); } else { @@ -297,13 +291,10 @@ private static void createDiscreteVoltageControlEquation(LfBus bus, VariableSet } private static void createSlopeQEquationTerm(LfBus bus, AcEquationSystemCreationParameters creationParameters, EquationSystem equationSystem, EquationTerm q) { - List generatorsControllingVoltage = bus.getGenerators().stream() - .filter(lfGenerator -> lfGenerator.hasVoltageControl()) - .collect(Collectors.toList()); - List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); - if (creationParameters.isVoltagePerReactivePowerControl() && generatorsControllingVoltageWithSlope.size() == 1 && generatorsControllingVoltage.size() == 1) { + LfGenerator generator = bus.getGeneratorControllingVoltageWithSlope(); + if (creationParameters.isVoltagePerReactivePowerControl() && generator != null) { Equation uq1 = equationSystem.createEquation(bus.getNum(), EquationType.BUS_V_SLOPE); - uq1.addTerm(EquationTerm.multiply(q, generatorsControllingVoltageWithSlope.get(0).getSlope())); + uq1.addTerm(EquationTerm.multiply(q, generator.getSlope())); } } diff --git a/src/main/java/com/powsybl/openloadflow/network/LfBus.java b/src/main/java/com/powsybl/openloadflow/network/LfBus.java index 95077af162..bfc2a94c7c 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfBus.java @@ -30,6 +30,8 @@ public interface LfBus extends LfElement { boolean isVoltageControlled(); + LfGenerator getGeneratorControllingVoltageWithSlope(); + /** * Get the number of time, voltage control status has be set from true to false. * diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java index 530bfe4bef..ae15fb918a 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java @@ -16,6 +16,7 @@ import java.util.*; import java.util.function.ToDoubleFunction; +import java.util.stream.Collectors; import static com.powsybl.openloadflow.util.EvaluableConstants.NAN; @@ -135,6 +136,14 @@ public boolean isVoltageControlled() { return voltageControl != null && voltageControl.getControlledBus() == this; } + @Override + public LfGenerator getGeneratorControllingVoltageWithSlope() { + List generatorsControllingVoltageWithSlope = generators.stream().filter(gen -> gen.hasVoltageControl() && gen.getSlope() != 0).collect(Collectors.toList()); + // we don't support several generators controlling voltage with slope or a generator controlling voltage with + // slope and other generators controlling voltage, so we return null. + return (generators.stream().filter(gen -> gen.hasVoltageControl()).count() > 1) || generatorsControllingVoltageWithSlope.size() == 0 ? null : generatorsControllingVoltageWithSlope.get(0); + } + @Override public boolean isVoltageControllerEnabled() { return voltageControllerEnabled; From ebdfdfb28d759052fb14bebdbe33954dd24bb9c5 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Thu, 3 Jun 2021 08:48:00 +0200 Subject: [PATCH 15/42] Clean code. Signed-off-by: Anne Tilloy --- pom.xml | 4 +- .../ac/equations/AcEquationSystem.java | 53 +++++-------------- .../ac/equations/AcEquationSystemUpdater.java | 18 ++----- .../openloadflow/equations/Equation.java | 15 ++---- src/test/resources/logback-test.xml | 2 +- 5 files changed, 25 insertions(+), 67 deletions(-) diff --git a/pom.xml b/pom.xml index 48604bb1f1..16120b9a75 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ powsybl-open-loadflow - 0.11.0-SNAPSHOT + 0.12.0-SNAPSHOT powsybl open loadflow An open source loadflow based on PowSyBl @@ -48,7 +48,7 @@ 5.5.2 1.6.2 - 4.2.0-RC1 + 4.2.0 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 836bd33769..0be6ab730a 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -60,12 +60,10 @@ private static void createVoltageControlEquations(VoltageControl voltageControl, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { if (voltageControl.isVoltageControlLocal()) { EquationTerm vTerm; - if (creationParameters.isVoltagePerReactivePowerControl() && bus.getGeneratorControllingVoltageWithSlope() != null) { - // 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 * qGen + if (creationParameters.isVoltagePerReactivePowerControl() && voltageControl.getControllerBuses().size() == 1 && bus.getGeneratorControllingVoltageWithSlope() != null) { vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); - equationSystem.createEquation(bus.getNum(), EquationType.BUS_V_SLOPE).addTerm(vTerm); + createBusWithSlopeEquation(bus, creationParameters, variableSet, equationSystem, vTerm); + } else { vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm); @@ -290,11 +288,16 @@ private static void createDiscreteVoltageControlEquation(LfBus bus, VariableSet } } - private static void createSlopeQEquationTerm(LfBus bus, AcEquationSystemCreationParameters creationParameters, EquationSystem equationSystem, EquationTerm q) { - LfGenerator generator = bus.getGeneratorControllingVoltageWithSlope(); - if (creationParameters.isVoltagePerReactivePowerControl() && generator != null) { - Equation uq1 = equationSystem.createEquation(bus.getNum(), EquationType.BUS_V_SLOPE); - uq1.addTerm(EquationTerm.multiply(q, generator.getSlope())); + private static void createBusWithSlopeEquation(LfBus bus, AcEquationSystemCreationParameters creationParameters, VariableSet variableSet, EquationSystem equationSystem, EquationTerm vTerm) { + // 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 + Equation eq = equationSystem.createEquation(bus.getNum(), EquationType.BUS_V_SLOPE); + eq.addTerm(vTerm); + List controllerBusReactiveTerms = createReactiveTerms(bus, variableSet, creationParameters); + double slope = bus.getGeneratorControllingVoltageWithSlope().getSlope(); + for (EquationTerm eqTerm : controllerBusReactiveTerms) { + eq.addTerm(EquationTerm.multiply(eqTerm, slope)); } } @@ -368,8 +371,6 @@ private static void createImpedantBranch(LfBranch branch, LfBus bus1, LfBus bus2 } sq1.addTerm(q1); branch.setQ1(q1); - // Add term slope * Q for U+lambdaQ control - createSlopeQEquationTerm(bus1, creationParameters, equationSystem, q1); } if (p2 != null) { Equation sp2 = equationSystem.createEquation(bus2.getNum(), EquationType.BUS_P); @@ -389,8 +390,6 @@ private static void createImpedantBranch(LfBranch branch, LfBus bus1, LfBus bus2 } sq2.addTerm(q2); branch.setQ2(q2); - // Add term slope * Q for U+lambdaQ control - createSlopeQEquationTerm(bus2, creationParameters, equationSystem, q2); } if (creationParameters.isForceA1Var() && branch.hasPhaseControlCapability()) { @@ -452,32 +451,6 @@ public static EquationSystem create(LfNetwork network, VariableSet variableSet, Objects.requireNonNull(creationParameters); EquationSystem equationSystem = new EquationSystem(network, true); - - // Bus with only one generator contralling voltage with a slope and connected to a non impedent branch is not yet supported - List zeroBranches = network.getBranches().stream() - .filter(b -> LfNetwork.isZeroImpedanceBranch(b)) - .collect(Collectors.toList()); - for (LfBranch zeroBranch : zeroBranches) { - List generatorsControllingVoltageat1 = zeroBranch.getBus1().getGenerators().stream() - .filter(lfGenerator -> lfGenerator.hasVoltageControl()) - .collect(Collectors.toList()); - List generatorsControllingVoltageWithSlopeat1 = generatorsControllingVoltageat1.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); - - if (creationParameters.isVoltagePerReactivePowerControl() && generatorsControllingVoltageWithSlopeat1.size() == 1 && generatorsControllingVoltageat1.size() == 1) { - throw new PowsyblException( - "Zero impedance branche that is connected to a bus where only one generator is controling voltage with a slope (buss: " + zeroBranch.getBus1() + ";branch: " + zeroBranch + ")"); - } - List generatorsControllingVoltageat2 = zeroBranch.getBus2().getGenerators().stream() - .filter(lfGenerator -> lfGenerator.hasVoltageControl()) - .collect(Collectors.toList()); - List generatorsControllingVoltageWithSlopeat2 = generatorsControllingVoltageat2.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); - - if (creationParameters.isVoltagePerReactivePowerControl() && generatorsControllingVoltageWithSlopeat2.size() == 1 && generatorsControllingVoltageat2.size() == 1) { - throw new PowsyblException( - "Zero impedance branche that is connected to a bus where only one generator is controling voltage with a slope (buss: " + zeroBranch.getBus2() + ";branch: " + zeroBranch + ")"); - } - } - createBusEquations(network, variableSet, creationParameters, equationSystem); createBranchEquations(network, variableSet, creationParameters, equationSystem); 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 bd866d1dc5..cef4ea2fd6 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java @@ -48,21 +48,13 @@ private void updateControlledBus(VoltageControl voltageControl, EquationSystem e .filter(LfBus::isVoltageControllerEnabled) .collect(Collectors.toList()); - // is there one static var compensator with a non-zero slope - boolean hasEquationBusVWithSlope = false; - if (controllerBuses.size() == 1) { - List generatorsControllingVoltage = controllerBuses.iterator().next().getGenerators().stream() - .filter(lfGenerator -> lfGenerator.hasVoltageControl()) - .collect(Collectors.toList()); - List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); - hasEquationBusVWithSlope = (generatorsControllingVoltageWithSlope.size() == 1) && creationParameters.isVoltagePerReactivePowerControl(); - } - - if (!hasEquationBusVWithSlope) { - equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V).setActive(!controllerBusesWithVoltageControlOn.isEmpty()); - } else { + if (creationParameters.isVoltagePerReactivePowerControl() && voltageControl.getControllerBuses().size() == 1 + && voltageControl.isVoltageControlLocal() && controllerBuses.iterator().next().getGeneratorControllingVoltageWithSlope() != null) { // we only support one controlling static var compensator without any other controlling generators equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V_SLOPE).setActive(false); + } else { + // is there one static var compensator with a non-zero slope + equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V).setActive(!controllerBusesWithVoltageControlOn.isEmpty()); } // create reactive power equations on controller buses that have voltage control on diff --git a/src/main/java/com/powsybl/openloadflow/equations/Equation.java b/src/main/java/com/powsybl/openloadflow/equations/Equation.java index 02f2cf4280..43e76a5667 100644 --- a/src/main/java/com/powsybl/openloadflow/equations/Equation.java +++ b/src/main/java/com/powsybl/openloadflow/equations/Equation.java @@ -171,16 +171,9 @@ private static double getRho1DistributionTarget(LfNetwork network, int num, Dist return controllerBranch.getPiModel().getR1() - firstControllerBranch.getPiModel().getR1(); } - private static double getUPlusLambdaQTarget(LfBus bus) { - double targetV = getBusTargetV(bus); - double qbusGen = bus.getGenerationTargetQ(); - double qbusLoad = bus.getLoadTargetQ(); - List generatorsControllingVoltage = bus.getGenerators().stream() - .filter(lfGenerator -> lfGenerator.hasVoltageControl()) - .collect(Collectors.toList()); - List generatorsControllingVoltageWithSlope = generatorsControllingVoltage.stream().filter(gen -> gen.getSlope() != 0).collect(Collectors.toList()); - double slope = generatorsControllingVoltageWithSlope.get(0).getSlope(); - return targetV - slope * (qbusLoad - qbusGen); + private static double createBusWithSlopeTarget(LfBus bus) { + double slope = bus.getGeneratorControllingVoltageWithSlope().getSlope(); + return getBusTargetV(bus) - slope * (bus.getLoadTargetQ() - bus.getGenerationTargetQ()); } void initTarget(LfNetwork network, double[] targets) { @@ -198,7 +191,7 @@ void initTarget(LfNetwork network, double[] targets) { break; case BUS_V_SLOPE: - targets[column] = getUPlusLambdaQTarget(network.getBus(num)); + targets[column] = createBusWithSlopeTarget(network.getBus(num)); break; case BUS_PHI: diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 2f5e8aaf22..03f44ff80a 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -13,7 +13,7 @@ %-5p %d{HH:mm:ss.SSS} %-20C{1} | %m%n - + From 3ff6abb59f35336e0b22ba4cd3962f5c4a4b5900 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Thu, 3 Jun 2021 12:18:01 +0200 Subject: [PATCH 16/42] Switching PQ to PV not supported. Signed-off-by: Anne Tilloy --- .../com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java index 37559ea548..7e6da1bf20 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java @@ -218,7 +218,8 @@ public OuterLoopStatus check(OuterLoopContext context, Reporter reporter) { for (LfBus bus : context.getNetwork().getBuses()) { if (bus.isVoltageControllerEnabled() && !bus.isDisabled()) { checkPvBus(bus, pvToPqBuses, remainingPvBusCount); - } else if (bus.hasVoltageControllerCapability() && !bus.isDisabled()) { + } else if (bus.hasVoltageControllerCapability() && !bus.isDisabled() && bus.getGeneratorControllingVoltageWithSlope() == null) { + // we don't support switching PQ to PV for bus with one controller with slope. checkPqBus(bus, pqToPvBuses); } } From c9a5bd1af44a4940da0f7e9f9166999814121bf0 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Fri, 4 Jun 2021 10:31:13 +0200 Subject: [PATCH 17/42] getGeneratorControllingVoltageWithSlope: lambda changes Signed-off-by: Florian Dupuy --- .../powsybl/openloadflow/network/impl/AbstractLfBus.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java index 99d02c7c98..94cf5c31e9 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java @@ -15,7 +15,6 @@ import java.util.*; import java.util.function.ToDoubleFunction; -import java.util.stream.Collectors; import static com.powsybl.openloadflow.util.EvaluableConstants.NAN; @@ -131,10 +130,10 @@ public boolean isVoltageControlled() { @Override public LfGenerator getGeneratorControllingVoltageWithSlope() { - List generatorsControllingVoltageWithSlope = generators.stream().filter(gen -> gen.hasVoltageControl() && gen.getSlope() != 0).collect(Collectors.toList()); + Optional firstGeneratorControllingVoltageWithSlope = generators.stream().filter(gen -> gen.hasVoltageControl() && gen.getSlope() != 0).findFirst(); // we don't support several generators controlling voltage with slope or a generator controlling voltage with - // slope and other generators controlling voltage, so we return null. - return (generators.stream().filter(gen -> gen.hasVoltageControl()).count() > 1) || generatorsControllingVoltageWithSlope.size() == 0 ? null : generatorsControllingVoltageWithSlope.get(0); + // slope and other generators controlling voltage, so we return null if there is more than one generator controlling voltage. + return (firstGeneratorControllingVoltageWithSlope.isEmpty() || generators.stream().filter(LfGenerator::hasVoltageControl).count() > 1) ? null : firstGeneratorControllingVoltageWithSlope.get(); } @Override From 54591ba1c40eb93e314fb03ab3691d622f21af09 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 8 Jun 2021 10:37:54 +0200 Subject: [PATCH 18/42] Use distribution data. Signed-off-by: Anne Tilloy --- .../powsybl/openloadflow/ac/equations/AcEquationSystem.java | 1 + .../java/com/powsybl/openloadflow/equations/Equation.java | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) 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 0be6ab730a..da42adfcb2 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -296,6 +296,7 @@ private static void createBusWithSlopeEquation(LfBus bus, AcEquationSystemCreati eq.addTerm(vTerm); List controllerBusReactiveTerms = createReactiveTerms(bus, variableSet, creationParameters); double slope = bus.getGeneratorControllingVoltageWithSlope().getSlope(); + eq.setData(new DistributionData(bus.getNum(), slope)); // for later use for (EquationTerm eqTerm : controllerBusReactiveTerms) { eq.addTerm(EquationTerm.multiply(eqTerm, slope)); } diff --git a/src/main/java/com/powsybl/openloadflow/equations/Equation.java b/src/main/java/com/powsybl/openloadflow/equations/Equation.java index 43e76a5667..d3a49b45d7 100644 --- a/src/main/java/com/powsybl/openloadflow/equations/Equation.java +++ b/src/main/java/com/powsybl/openloadflow/equations/Equation.java @@ -171,8 +171,8 @@ private static double getRho1DistributionTarget(LfNetwork network, int num, Dist return controllerBranch.getPiModel().getR1() - firstControllerBranch.getPiModel().getR1(); } - private static double createBusWithSlopeTarget(LfBus bus) { - double slope = bus.getGeneratorControllingVoltageWithSlope().getSlope(); + private static double createBusWithSlopeTarget(LfBus bus, DistributionData data) { + double slope = data.getC(); return getBusTargetV(bus) - slope * (bus.getLoadTargetQ() - bus.getGenerationTargetQ()); } @@ -191,7 +191,7 @@ void initTarget(LfNetwork network, double[] targets) { break; case BUS_V_SLOPE: - targets[column] = createBusWithSlopeTarget(network.getBus(num)); + targets[column] = createBusWithSlopeTarget(network.getBus(num), getData()); break; case BUS_PHI: From 6e1f8ae043a4afda0b006cdf0a96f87c520da07a Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 8 Jun 2021 11:55:02 +0200 Subject: [PATCH 19/42] Add a test for SVC with slope PV -> PQ and blocked. Fix check. Signed-off-by: Anne Tilloy --- .../ac/ReactiveLimitsOuterLoop.java | 6 ++- .../openloadflow/ac/SwitchPqPvTest.java | 50 +++++++++++++++++++ src/test/resources/logback-test.xml | 4 +- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java index 7e6da1bf20..2e5fbb9da9 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java @@ -196,10 +196,12 @@ private void checkPqBus(LfBus controllerCapableBus, List pqToPvBuses) double minQ = controllerCapableBus.getMinQ(); double maxQ = controllerCapableBus.getMaxQ(); double q = controllerCapableBus.getGenerationTargetQ(); - if (Math.abs(q - maxQ) < Q_EPS && controllerCapableBus.getV().eval() > getBusTargetV(controllerCapableBus)) { // bus produce too much reactive power + double distanceToMaxQ = Math.abs(q - maxQ); + double distanceToMinQ = Math.abs(q - minQ); + if ((distanceToMaxQ < Q_EPS || distanceToMaxQ < distanceToMinQ) && controllerCapableBus.getV().eval() > getBusTargetV(controllerCapableBus)) { // bus produce too much reactive power pqToPvBuses.add(new PqToPvBus(controllerCapableBus, ReactiveLimitDirection.MAX)); } - if (Math.abs(q - minQ) < Q_EPS && controllerCapableBus.getV().eval() < getBusTargetV(controllerCapableBus)) { // bus absorb too much reactive power + if ((distanceToMinQ < Q_EPS || distanceToMaxQ > distanceToMinQ) && controllerCapableBus.getV().eval() < getBusTargetV(controllerCapableBus)) { // bus absorb too much reactive power pqToPvBuses.add(new PqToPvBus(controllerCapableBus, ReactiveLimitDirection.MIN)); } } diff --git a/src/test/java/com/powsybl/openloadflow/ac/SwitchPqPvTest.java b/src/test/java/com/powsybl/openloadflow/ac/SwitchPqPvTest.java index 6f80d262f5..bd115b8f1f 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/SwitchPqPvTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/SwitchPqPvTest.java @@ -7,6 +7,7 @@ package com.powsybl.openloadflow.ac; import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.extensions.VoltagePerReactivePowerControlAdder; import com.powsybl.loadflow.LoadFlow; import com.powsybl.loadflow.LoadFlowParameters; import com.powsybl.loadflow.LoadFlowResult; @@ -19,6 +20,7 @@ import org.junit.jupiter.api.Test; import static com.powsybl.openloadflow.util.LoadFlowAssert.assertVoltageEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -202,4 +204,52 @@ void test() { assertVoltageEquals(21, b2); // PV assertVoltageEquals(20, b3); // PV } + + @Test + void testWithSlope() { + g3.remove(); + double value = b3.getVoltageLevel().getNominalV() * b3.getVoltageLevel().getNominalV(); + StaticVarCompensator svc3 = b3.getVoltageLevel() + .newStaticVarCompensator() + .setId("svc3") + .setBus("b3") + .setConnectableBus("b3") + .setVoltageSetpoint(20) + .setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE) + .setBmax(30 / value) + .setBmin(-1000 / value) + .add(); + g3 = b3.getVoltageLevel() + .newGenerator() + .setId("g3") + .setBus("b3") + .setConnectableBus("b3") + .setEnergySource(EnergySource.THERMAL) + .setMinP(0) + .setMaxP(200) + .setTargetP(100) + .setTargetQ(0) + .setVoltageRegulatorOn(false) + .add(); + g3.newMinMaxReactiveLimits() + .setMinQ(0) + .setMaxQ(0) + .add(); + + LoadFlowResult result = loadFlowRunner.run(network, parameters); + assertTrue(result.isOk()); + // bus 1 and 3 switch PQ at first outer loop, then at next outer loop bus 3 go back PV + assertVoltageEquals(17.032769, b1); // PQ => v != 17 + assertVoltageEquals(21, b2); // PV + assertVoltageEquals(20, b3); // PV + System.out.println(b3.getV()); + + svc3.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(0.03).add(); + LoadFlowResult result2 = loadFlowRunner.run(network, parameters); + assertTrue(result2.isOk()); + // bus 1 and 3 switch PQ at first outer loop, then at next outer loop bus 3 does not go back PV + assertVoltageEquals(17.034003, b1); // PQ => v != 17 + assertVoltageEquals(21, b2); // PV + assertEquals(20.00140, b3.getV(), 10E-3); // remains PQ because of slope + } } diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 03f44ff80a..46f4d15785 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -13,10 +13,10 @@ %-5p %d{HH:mm:ss.SSS} %-20C{1} | %m%n - + - + From 0afe0bfede3fc444768a1d93a93e419cef30bd79 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 8 Jun 2021 15:27:49 +0200 Subject: [PATCH 20/42] Fix check. Signed-off-by: Anne Tilloy --- .../com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java index 2e5fbb9da9..3c10d82a63 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java @@ -198,10 +198,10 @@ private void checkPqBus(LfBus controllerCapableBus, List pqToPvBuses) double q = controllerCapableBus.getGenerationTargetQ(); double distanceToMaxQ = Math.abs(q - maxQ); double distanceToMinQ = Math.abs(q - minQ); - if ((distanceToMaxQ < Q_EPS || distanceToMaxQ < distanceToMinQ) && controllerCapableBus.getV().eval() > getBusTargetV(controllerCapableBus)) { // bus produce too much reactive power + if (distanceToMaxQ < distanceToMinQ && controllerCapableBus.getV().eval() > getBusTargetV(controllerCapableBus)) { // bus produce too much reactive power pqToPvBuses.add(new PqToPvBus(controllerCapableBus, ReactiveLimitDirection.MAX)); } - if ((distanceToMinQ < Q_EPS || distanceToMaxQ > distanceToMinQ) && controllerCapableBus.getV().eval() < getBusTargetV(controllerCapableBus)) { // bus absorb too much reactive power + if (distanceToMaxQ > distanceToMinQ && controllerCapableBus.getV().eval() < getBusTargetV(controllerCapableBus)) { // bus absorb too much reactive power pqToPvBuses.add(new PqToPvBus(controllerCapableBus, ReactiveLimitDirection.MIN)); } } From e016a7a1007de56ac354387717a997d560adf9fe Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 8 Jun 2021 16:49:53 +0200 Subject: [PATCH 21/42] Remove useless variable. Signed-off-by: Anne Tilloy --- .../com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java index 3c10d82a63..37a8922401 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java @@ -30,8 +30,6 @@ public class ReactiveLimitsOuterLoop implements OuterLoop { private static final Logger LOGGER = LoggerFactory.getLogger(ReactiveLimitsOuterLoop.class); - private static final double Q_EPS = Math.pow(10, -5); // 10^-5 in p.u => 10^-3 in Mw - private static final Comparator BY_NOMINAL_V_COMPARATOR = Comparator.comparingDouble( pvToPqBus -> pvToPqBus.controllerBus.getVoltageControl() .map(vc -> -vc.getControlledBus().getNominalV()) From 7c16fb030d36e0dcd8f30d31b08f201fe1a6be1c Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Tue, 8 Jun 2021 17:39:00 +0200 Subject: [PATCH 22/42] From nullable to Optional Signed-off-by: Florian Dupuy --- .../powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java | 2 +- .../openloadflow/ac/equations/AcEquationSystem.java | 8 ++++---- .../ac/equations/AcEquationSystemUpdater.java | 2 +- src/main/java/com/powsybl/openloadflow/network/LfBus.java | 2 +- .../powsybl/openloadflow/network/impl/AbstractLfBus.java | 5 +++-- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java index 37a8922401..0064b2ada0 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java @@ -218,7 +218,7 @@ public OuterLoopStatus check(OuterLoopContext context, Reporter reporter) { for (LfBus bus : context.getNetwork().getBuses()) { if (bus.isVoltageControllerEnabled() && !bus.isDisabled()) { checkPvBus(bus, pvToPqBuses, remainingPvBusCount); - } else if (bus.hasVoltageControllerCapability() && !bus.isDisabled() && bus.getGeneratorControllingVoltageWithSlope() == null) { + } else if (bus.hasVoltageControllerCapability() && !bus.isDisabled() && bus.getGeneratorControllingVoltageWithSlope().isEmpty()) { // we don't support switching PQ to PV for bus with one controller with slope. checkPqBus(bus, pqToPvBuses); } 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 2edcae32a6..3ce7aa50c1 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -60,9 +60,10 @@ private static void createVoltageControlEquations(VoltageControl voltageControl, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { if (voltageControl.isVoltageControlLocal()) { EquationTerm vTerm; - if (creationParameters.isVoltagePerReactivePowerControl() && voltageControl.getControllerBuses().size() == 1 && bus.getGeneratorControllingVoltageWithSlope() != null) { + if (creationParameters.isVoltagePerReactivePowerControl() && voltageControl.getControllerBuses().size() == 1 && bus.getGeneratorControllingVoltageWithSlope().isPresent()) { vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); - createBusWithSlopeEquation(bus, creationParameters, variableSet, equationSystem, vTerm); + double slope = bus.getGeneratorControllingVoltageWithSlope().get().getSlope(); + createBusWithSlopeEquation(bus, slope, creationParameters, variableSet, equationSystem, vTerm); } else { vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); @@ -288,14 +289,13 @@ private static void createDiscreteVoltageControlEquation(LfBus bus, VariableSet } } - private static void createBusWithSlopeEquation(LfBus bus, AcEquationSystemCreationParameters creationParameters, VariableSet variableSet, EquationSystem equationSystem, EquationTerm vTerm) { + private static void createBusWithSlopeEquation(LfBus bus, double slope, AcEquationSystemCreationParameters creationParameters, VariableSet variableSet, EquationSystem equationSystem, EquationTerm vTerm) { // 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 Equation eq = equationSystem.createEquation(bus.getNum(), EquationType.BUS_V_SLOPE); eq.addTerm(vTerm); List controllerBusReactiveTerms = createReactiveTerms(bus, variableSet, creationParameters); - double slope = bus.getGeneratorControllingVoltageWithSlope().getSlope(); eq.setData(new DistributionData(bus.getNum(), slope)); // for later use for (EquationTerm eqTerm : controllerBusReactiveTerms) { eq.addTerm(EquationTerm.multiply(eqTerm, slope)); 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 a97636d4f3..9cead0bc7c 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java @@ -46,7 +46,7 @@ private void updateControlledBus(VoltageControl voltageControl, EquationSystem e .collect(Collectors.toList()); if (creationParameters.isVoltagePerReactivePowerControl() && voltageControl.getControllerBuses().size() == 1 - && voltageControl.isVoltageControlLocal() && controllerBuses.iterator().next().getGeneratorControllingVoltageWithSlope() != null) { + && voltageControl.isVoltageControlLocal() && controllerBuses.iterator().next().getGeneratorControllingVoltageWithSlope().isPresent()) { // we only support one controlling static var compensator without any other controlling generators equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V_SLOPE).setActive(false); } else { diff --git a/src/main/java/com/powsybl/openloadflow/network/LfBus.java b/src/main/java/com/powsybl/openloadflow/network/LfBus.java index d9959df6b0..959164caa8 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfBus.java @@ -31,7 +31,7 @@ public interface LfBus extends LfElement { boolean isVoltageControlled(); - LfGenerator getGeneratorControllingVoltageWithSlope(); + Optional getGeneratorControllingVoltageWithSlope(); /** * Get the number of time, voltage control status has be set from true to false. diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java index dfbf39c1bb..68e6ab75b0 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java @@ -130,11 +130,12 @@ public boolean isVoltageControlled() { } @Override - public LfGenerator getGeneratorControllingVoltageWithSlope() { + public Optional getGeneratorControllingVoltageWithSlope() { Optional firstGeneratorControllingVoltageWithSlope = generators.stream().filter(gen -> gen.hasVoltageControl() && gen.getSlope() != 0).findFirst(); // we don't support several generators controlling voltage with slope or a generator controlling voltage with // slope and other generators controlling voltage, so we return null if there is more than one generator controlling voltage. - return (firstGeneratorControllingVoltageWithSlope.isEmpty() || generators.stream().filter(LfGenerator::hasVoltageControl).count() > 1) ? null : firstGeneratorControllingVoltageWithSlope.get(); + return (firstGeneratorControllingVoltageWithSlope.isEmpty() || generators.stream().filter(LfGenerator::hasVoltageControl).count() > 1) ? + Optional.empty() : firstGeneratorControllingVoltageWithSlope; } @Override From cc6cb0729e6367ac4274e26ae8a8a2fcddec79fd Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 9 Jun 2021 10:01:35 +0200 Subject: [PATCH 23/42] Trying to correct bug without ruining the code clarity Signed-off-by: Florian Dupuy --- .../ac/equations/AcEquationSystem.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) 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 3ce7aa50c1..563ed1b1ba 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -59,14 +59,16 @@ private static void createBusEquations(LfNetwork network, VariableSet variableSe private static void createVoltageControlEquations(VoltageControl voltageControl, LfBus bus, VariableSet variableSet, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { if (voltageControl.isVoltageControlLocal()) { - EquationTerm vTerm; - if (creationParameters.isVoltagePerReactivePowerControl() && voltageControl.getControllerBuses().size() == 1 && bus.getGeneratorControllingVoltageWithSlope().isPresent()) { - vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); - double slope = bus.getGeneratorControllingVoltageWithSlope().get().getSlope(); - createBusWithSlopeEquation(bus, slope, creationParameters, variableSet, equationSystem, vTerm); - + EquationTerm vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); + if (creationParameters.isVoltagePerReactivePowerControl() && voltageControl.getControllerBuses().size() == 1) { + Optional generatorControllingVoltageWithSlope = bus.getGeneratorControllingVoltageWithSlope(); + if (generatorControllingVoltageWithSlope.isPresent()) { + double slope = generatorControllingVoltageWithSlope.get().getSlope(); + createBusWithSlopeEquation(bus, slope, creationParameters, variableSet, equationSystem, vTerm); + } else { + equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm); + } } else { - vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm); } bus.setV(vTerm); From ff71ad06c88038e5cac0908f05f8d7fc0bc3fb96 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 9 Jun 2021 11:20:49 +0200 Subject: [PATCH 24/42] Fix logback. Signed-off-by: Anne Tilloy --- src/test/resources/logback-test.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 46f4d15785..03f44ff80a 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -13,10 +13,10 @@ %-5p %d{HH:mm:ss.SSS} %-20C{1} | %m%n - + - + From 121a673bab9db9e95a190f26112c4bc1e7424ac2 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Tue, 15 Jun 2021 11:56:40 +0200 Subject: [PATCH 25/42] Disabling slope when loading if non supported case Signed-off-by: Florian Dupuy --- .../openloadflow/network/LfGenerator.java | 2 ++ .../network/impl/AbstractLfBus.java | 11 ++++++----- .../network/impl/LfNetworkLoaderImpl.java | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfGenerator.java b/src/main/java/com/powsybl/openloadflow/network/LfGenerator.java index ca13d5b410..a1b6ced429 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfGenerator.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfGenerator.java @@ -54,4 +54,6 @@ public interface LfGenerator { LfBus getControlledBus(LfNetwork lfNetwork); double getSlope(); + + void setSlope(double slope); } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java index 615e57906d..3b527e50e3 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java @@ -132,11 +132,7 @@ public boolean isVoltageControlled() { @Override public Optional getGeneratorControllingVoltageWithSlope() { - Optional firstGeneratorControllingVoltageWithSlope = generators.stream().filter(gen -> gen.hasVoltageControl() && gen.getSlope() != 0).findFirst(); - // we don't support several generators controlling voltage with slope or a generator controlling voltage with - // slope and other generators controlling voltage, so we return null if there is more than one generator controlling voltage. - return (firstGeneratorControllingVoltageWithSlope.isEmpty() || generators.stream().filter(LfGenerator::hasVoltageControl).count() > 1) ? - Optional.empty() : firstGeneratorControllingVoltageWithSlope; + return generators.stream().filter(gen -> gen.hasVoltageControl() && gen.getSlope() != 0).findFirst(); } @Override @@ -495,4 +491,9 @@ public BusResults createBusResult() { double scale = getNominalV(); return new BusResults(getVoltageLevelId(), getId(), getV().eval() * scale, getAngle()); } + + @Override + public String toString() { + return getId(); + } } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java index 6055247ca7..454f653154 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java @@ -61,6 +61,8 @@ private static void createVoltageControls(LfNetwork lfNetwork, List lfBus List voltageControlGenerators = controllerBus.getGenerators().stream().filter(LfGenerator::hasVoltageControl).collect(Collectors.toList()); if (!voltageControlGenerators.isEmpty()) { + checkGeneratorsWithSlope(controllerBus, voltageControlGenerators); + LfGenerator lfGenerator0 = voltageControlGenerators.get(0); LfBus controlledBus = lfGenerator0.getControlledBus(lfNetwork); double controllerTargetV = lfGenerator0.getTargetV(); @@ -92,6 +94,22 @@ private static void createVoltageControls(LfNetwork lfNetwork, List lfBus } } + private static void checkGeneratorsWithSlope(LfBus controllerBus, List voltageControlGenerators) { + if (voltageControlGenerators.size() > 1) { + long nbvoltageControlGeneratorsWithSlope = voltageControlGenerators.stream().filter(generator -> generator.getSlope() != 0).count(); + if (nbvoltageControlGeneratorsWithSlope > 0) { + if (nbvoltageControlGeneratorsWithSlope == 1) { + // we don't support a generator controlling voltage with slope and other generators controlling voltage + LOGGER.warn("Non supported: several generators of bus {} control voltage and one controls voltage with slope. Slope is therefore deactivated on those generators.", controllerBus); + } else { + // we don't support several generators controlling voltage with slope + LOGGER.warn("Non supported: several generators of bus {} control voltage with slope. Slope is therefore deactivated on those generators.", controllerBus); + } + voltageControlGenerators.forEach(g -> g.setSlope(0)); + } + } + } + private static void checkUniqueTargetVControlledBus(double controllerTargetV, LfBus controllerBus, VoltageControl vc) { // check if target voltage is consistent with other already existing controller buses double voltageControlTargetV = vc.getTargetValue(); From 2b29386a5ac2a9a19c2d442171a9629c8454b348 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Tue, 15 Jun 2021 12:02:38 +0200 Subject: [PATCH 26/42] Add setSlope to implementations Signed-off-by: Florian Dupuy --- .../openloadflow/network/impl/LfDanglingLineGenerator.java | 5 +++++ .../powsybl/openloadflow/network/impl/LfGeneratorImpl.java | 5 +++++ .../network/impl/LfStaticVarCompensatorImpl.java | 5 +++++ .../openloadflow/network/impl/LfVscConverterStationImpl.java | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfDanglingLineGenerator.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfDanglingLineGenerator.java index aae8ecd8fe..ee13968a33 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfDanglingLineGenerator.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfDanglingLineGenerator.java @@ -83,4 +83,9 @@ public void updateState() { public double getSlope() { return 0; } + + @Override + public void setSlope(double slope) { + // nothing to do + } } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfGeneratorImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfGeneratorImpl.java index 151cf0bbd6..f43280dc0d 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfGeneratorImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfGeneratorImpl.java @@ -139,4 +139,9 @@ public void updateState() { public double getSlope() { return 0; } + + @Override + public void setSlope(double slope) { + // nothing to do + } } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java index 7f5977af26..a592c20b56 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java @@ -119,4 +119,9 @@ public void updateState() { public double getSlope() { return this.slope; } + + @Override + public void setSlope(double slope) { + this.slope = slope; + } } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfVscConverterStationImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfVscConverterStationImpl.java index 44e6136e5a..83410c9c14 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfVscConverterStationImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfVscConverterStationImpl.java @@ -90,4 +90,9 @@ public void updateState() { public double getSlope() { return 0; } + + @Override + public void setSlope(double slope) { + // nothing to do + } } From e8af6f2c12563d1b52ef3361a0210efc8939ba4a Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 15 Jun 2021 14:42:06 +0200 Subject: [PATCH 27/42] Quick fix for bug. Signed-off-by: Anne Tilloy --- .../ac/equations/AcEquationSystemUpdater.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) 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 9cead0bc7c..f3c172b753 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java @@ -45,10 +45,13 @@ private void updateControlledBus(VoltageControl voltageControl, EquationSystem e .filter(LfBus::isVoltageControllerEnabled) .collect(Collectors.toList()); - if (creationParameters.isVoltagePerReactivePowerControl() && voltageControl.getControllerBuses().size() == 1 - && voltageControl.isVoltageControlLocal() && controllerBuses.iterator().next().getGeneratorControllingVoltageWithSlope().isPresent()) { - // we only support one controlling static var compensator without any other controlling generators - equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V_SLOPE).setActive(false); + if (creationParameters.isVoltagePerReactivePowerControl() && voltageControl.getControllerBuses().size() == 1 && voltageControl.isVoltageControlLocal() + && controllerBuses.iterator().next().getGeneratorControllingVoltageWithSlope().isPresent()) { + LfBus controllerBus = voltageControl.getControllerBuses().iterator().next(); + if (!controllerBus.isVoltageControllerEnabled()) { + // we only support one controlling static var compensator without any other controlling generators + equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V_SLOPE).setActive(false); + } } else { // is there one static var compensator with a non-zero slope equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V).setActive(!controllerBusesWithVoltageControlOn.isEmpty()); From d8bfc47336f9112cf8415258854b0e6af8d49cf7 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Thu, 17 Jun 2021 09:50:17 +0200 Subject: [PATCH 28/42] check generators with slope once voltage controls are created Signed-off-by: Florian Dupuy --- .../network/impl/LfNetworkLoaderImpl.java | 67 ++++++++++++------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java index 454f653154..1b55a25a72 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java @@ -55,58 +55,75 @@ private static void createBuses(List buses, LfNetworkParameters parameters, } private static void createVoltageControls(LfNetwork lfNetwork, List lfBuses, boolean voltageRemoteControl) { + List voltageControls = new ArrayList<>(); + // set controller -> controlled link for (LfBus controllerBus : lfBuses) { List voltageControlGenerators = controllerBus.getGenerators().stream().filter(LfGenerator::hasVoltageControl).collect(Collectors.toList()); if (!voltageControlGenerators.isEmpty()) { - checkGeneratorsWithSlope(controllerBus, voltageControlGenerators); - LfGenerator lfGenerator0 = voltageControlGenerators.get(0); LfBus controlledBus = lfGenerator0.getControlledBus(lfNetwork); double controllerTargetV = lfGenerator0.getTargetV(); - LfBus finalControlledBus = controlledBus; voltageControlGenerators.stream().skip(1).forEach(lfGenerator -> { LfBus generatorControlledBus = lfGenerator.getControlledBus(lfNetwork); // check that remote control bus is the same for the generators of current controller bus which have voltage control on - checkUniqueControlledBus(finalControlledBus, generatorControlledBus, controllerBus); + checkUniqueControlledBus(controlledBus, generatorControlledBus, controllerBus); // check that target voltage is the same for the generators of current controller bus which have voltage control on checkUniqueTargetVControllerBus(lfGenerator, controllerTargetV, controllerBus, generatorControlledBus); }); - if (!voltageRemoteControl && controlledBus != controllerBus) { + if (voltageRemoteControl || controlledBus == controllerBus) { + controlledBus.getVoltageControl().ifPresentOrElse( + vc -> updateVoltageControl(vc, controllerBus, controllerTargetV), + () -> createVoltageControl(controlledBus, controllerBus, controllerTargetV, voltageControls)); + } else { // if voltage remote control deactivated and remote control, set local control instead LOGGER.warn("Remote voltage control is not activated. The voltage target of {} with remote control is rescaled from {} to {}", controllerBus.getId(), controllerTargetV, controllerTargetV * controllerBus.getNominalV() / controlledBus.getNominalV()); - controlledBus = controllerBus; + createVoltageControl(controllerBus, controllerBus, controllerTargetV, voltageControls); } - - VoltageControl voltageControl = controlledBus.getVoltageControl().orElse(new VoltageControl(controlledBus, controllerTargetV)); - voltageControl.addControllerBus(controllerBus); - - controlledBus.setVoltageControl(voltageControl); // is set even if already present, for simplicity sake - checkUniqueTargetVControlledBus(controllerTargetV, controllerBus, voltageControl); // check even if voltage control just created, for simplicity sake } } + + voltageControls.forEach(LfNetworkLoaderImpl::checkGeneratorsWithSlope); } - private static void checkGeneratorsWithSlope(LfBus controllerBus, List voltageControlGenerators) { - if (voltageControlGenerators.size() > 1) { - long nbvoltageControlGeneratorsWithSlope = voltageControlGenerators.stream().filter(generator -> generator.getSlope() != 0).count(); - if (nbvoltageControlGeneratorsWithSlope > 0) { - if (nbvoltageControlGeneratorsWithSlope == 1) { - // we don't support a generator controlling voltage with slope and other generators controlling voltage - LOGGER.warn("Non supported: several generators of bus {} control voltage and one controls voltage with slope. Slope is therefore deactivated on those generators.", controllerBus); - } else { - // we don't support several generators controlling voltage with slope - LOGGER.warn("Non supported: several generators of bus {} control voltage with slope. Slope is therefore deactivated on those generators.", controllerBus); - } - voltageControlGenerators.forEach(g -> g.setSlope(0)); - } + private static void createVoltageControl(LfBus controlledBus, LfBus controllerBus, double controllerTargetV, List voltageControls) { + VoltageControl voltageControl = new VoltageControl(controlledBus, controllerTargetV); + voltageControl.addControllerBus(controllerBus); + controlledBus.setVoltageControl(voltageControl); + voltageControls.add(voltageControl); + } + + private static void updateVoltageControl(VoltageControl voltageControl, LfBus controllerBus, double controllerTargetV) { + voltageControl.addControllerBus(controllerBus); + checkUniqueTargetVControlledBus(controllerTargetV, controllerBus, voltageControl); + } + + private static void checkGeneratorsWithSlope(VoltageControl voltageControl) { + + List generatorsWithSlope = voltageControl.getControllerBuses().stream() + .flatMap(lfBus -> lfBus.getGenerators().stream().filter(generator -> generator.hasVoltageControl() && generator.getSlope() != 0)) + .collect(Collectors.toList()); + + if (generatorsWithSlope.size() > 1) { + // we don't support a bus controlled by several generators controlling voltage with slope and other generators controlling voltage + generatorsWithSlope.stream().skip(1).forEach(g -> g.setSlope(0)); + LOGGER.warn("Non supported: {} generators are controlling voltage of bus {} with slope. Slope is kept on first generator {} and deactivated on the others.", + generatorsWithSlope.size(), voltageControl.getControlledBus(), generatorsWithSlope.get(0)); + generatorsWithSlope = Collections.singletonList(generatorsWithSlope.get(0)); + } + + if (generatorsWithSlope.size() == 1 && generatorsWithSlope.get(0).getBus().getGenerators().stream().filter(LfGenerator::hasVoltageControl).count() > 1) { + // we don't support a generator controlling voltage with slope and other generators controlling voltage + generatorsWithSlope.get(0).setSlope(0); + LOGGER.warn("Non supported: several generators of bus {} control voltage and one controls voltage with slope. Slope is therefore deactivated on those generators.", + generatorsWithSlope.get(0).getBus()); } } From a94f812d43195080894f00534ca62cca77b29d93 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 21 Jun 2021 10:38:35 +0200 Subject: [PATCH 29/42] Checking slope only if voltagePerReactivePowerControl is enabled Signed-off-by: Florian Dupuy --- .../openloadflow/OpenLoadFlowParameters.java | 2 +- .../openloadflow/OpenLoadFlowProvider.java | 4 ++-- .../ac/outerloop/AcLoadFlowParameters.java | 2 +- .../ac/outerloop/AcloadFlowEngine.java | 3 ++- .../openloadflow/dc/DcLoadFlowEngine.java | 3 ++- .../network/LfNetworkParameters.java | 12 +++++++++-- .../network/impl/LfNetworkLoaderImpl.java | 20 ++++++++++++------- .../sensi/AcSensitivityAnalysis.java | 3 ++- .../sensi/DcSensitivityAnalysis.java | 3 ++- ...neratorTargetVoltageInconsistencyTest.java | 4 ++-- 10 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java index 9ad96faca3..0fc000f200 100644 --- a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java +++ b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java @@ -135,7 +135,7 @@ public OpenLoadFlowParameters setAddRatioToLinesWithDifferentNominalVoltageAtBot return this; } - public boolean hasVoltagePerReactivePowerControl() { + public boolean isVoltagePerReactivePowerControl() { return voltagePerReactivePowerControl; } diff --git a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java index 1ed99c947e..9bd1092a9d 100644 --- a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java +++ b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java @@ -148,7 +148,7 @@ public static AcLoadFlowParameters createAcParameters(Network network, MatrixFac LOGGER.info("Add ratio to lines with different nominal voltage at both ends: {}", parametersExt.isAddRatioToLinesWithDifferentNominalVoltageAtBothEnds()); LOGGER.info("Slack bus Pmax mismatch: {}", parametersExt.getSlackBusPMaxMismatch()); LOGGER.info("Connected component mode: {}", parameters.getConnectedComponentMode()); - LOGGER.info("Voltage per reactive power control: {}", parametersExt.hasVoltagePerReactivePowerControl()); + LOGGER.info("Voltage per reactive power control: {}", parametersExt.isVoltagePerReactivePowerControl()); List outerLoops = new ArrayList<>(); if (parameters.isDistributedSlack()) { @@ -185,7 +185,7 @@ public static AcLoadFlowParameters createAcParameters(Network network, MatrixFac parameters.getConnectedComponentMode() == LoadFlowParameters.ConnectedComponentMode.MAIN, parameters.getCountriesToBalance(), parameters.isDistributedSlack() && parameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD, - parametersExt.hasVoltagePerReactivePowerControl()); + parametersExt.isVoltagePerReactivePowerControl()); } private LoadFlowResult runAc(Network network, LoadFlowParameters parameters, OpenLoadFlowParameters parametersExt, Reporter reporter) { diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcLoadFlowParameters.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcLoadFlowParameters.java index 6b40f46cef..cd506af648 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcLoadFlowParameters.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcLoadFlowParameters.java @@ -58,7 +58,7 @@ public class AcLoadFlowParameters { private final boolean distributedOnConformLoad; - private boolean voltagePerReactivePowerControl; + private final boolean voltagePerReactivePowerControl; public AcLoadFlowParameters(SlackBusSelector slackBusSelector, VoltageInitializer voltageInitializer, NewtonRaphsonStoppingCriteria stoppingCriteria, List outerLoops, diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java index 7cb5dad247..bad94781cd 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java @@ -58,7 +58,8 @@ public static List createNetworks(Object network, AcLoadFlowParameter parameters.isAddRatioToLinesWithDifferentNominalVoltageAtBothEnds(), parameters.isComputeMainConnectedComponentOnly(), parameters.getCountriesToBalance(), - parameters.isDistributedOnConformLoad()); + parameters.isDistributedOnConformLoad(), + parameters.isVoltagePerReactivePowerControl()); return LfNetwork.load(network, networkParameters, reporter); } diff --git a/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java b/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java index 6808c0ce18..b89a4d60a0 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java +++ b/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java @@ -46,7 +46,8 @@ public DcLoadFlowEngine(LfNetwork network, MatrixFactory matrixFactory, boolean public DcLoadFlowEngine(Object network, DcLoadFlowParameters parameters, Reporter reporter) { LfNetworkParameters lfNetworkParameters = new LfNetworkParameters(parameters.getSlackBusSelector(), false, false, false, false, parameters.getPlausibleActivePowerLimit(), false, parameters.isComputeMainConnectedComponentOnly(), parameters.getCountriesToBalance(), - parameters.isDistributedSlack() && parameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD); + parameters.isDistributedSlack() && parameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD, + false); this.networks = LfNetwork.load(network, lfNetworkParameters, reporter); this.parameters = Objects.requireNonNull(parameters); } diff --git a/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java b/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java index 036dc6a339..17915ae7c2 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java @@ -37,16 +37,19 @@ public class LfNetworkParameters { private boolean distributedOnConformLoad; + private final boolean voltagePerReactivePowerControl; + public LfNetworkParameters(SlackBusSelector slackBusSelector) { this(slackBusSelector, false, false, false, false, ParameterConstants.PLAUSIBLE_ACTIVE_POWER_LIMIT_DEFAULT_VALUE, false, - true, Collections.emptySet(), false); + true, Collections.emptySet(), false, false); } public LfNetworkParameters(SlackBusSelector slackBusSelector, boolean generatorVoltageRemoteControl, boolean minImpedance, boolean twtSplitShuntAdmittance, boolean breakers, double plausibleActivePowerLimit, boolean addRatioToLinesWithDifferentNominalVoltageAtBothEnds, - boolean computeMainConnectedComponentOnly, Set countriesToBalance, boolean distributedOnConformLoad) { + boolean computeMainConnectedComponentOnly, Set countriesToBalance, boolean distributedOnConformLoad, + boolean voltagePerReactivePowerControl) { this.slackBusSelector = slackBusSelector; this.generatorVoltageRemoteControl = generatorVoltageRemoteControl; this.minImpedance = minImpedance; @@ -57,6 +60,7 @@ public LfNetworkParameters(SlackBusSelector slackBusSelector, boolean generatorV this.computeMainConnectedComponentOnly = computeMainConnectedComponentOnly; this.countriesToBalance = countriesToBalance; this.distributedOnConformLoad = distributedOnConformLoad; + this.voltagePerReactivePowerControl = voltagePerReactivePowerControl; } public SlackBusSelector getSlackBusSelector() { @@ -98,4 +102,8 @@ public Set getCountriesToBalance() { public boolean isDistributedOnConformLoad() { return distributedOnConformLoad; } + + public boolean isVoltagePerReactivePowerControl() { + return voltagePerReactivePowerControl; + } } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java index 1b55a25a72..3701bed985 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java @@ -54,7 +54,7 @@ private static void createBuses(List buses, LfNetworkParameters parameters, } } - private static void createVoltageControls(LfNetwork lfNetwork, List lfBuses, boolean voltageRemoteControl) { + private static void createVoltageControls(LfNetwork lfNetwork, List lfBuses, boolean voltageRemoteControl, boolean voltagePerReactivePowerControl) { List voltageControls = new ArrayList<>(); // set controller -> controlled link @@ -80,24 +80,30 @@ private static void createVoltageControls(LfNetwork lfNetwork, List lfBus if (voltageRemoteControl || controlledBus == controllerBus) { controlledBus.getVoltageControl().ifPresentOrElse( vc -> updateVoltageControl(vc, controllerBus, controllerTargetV), - () -> createVoltageControl(controlledBus, controllerBus, controllerTargetV, voltageControls)); + () -> createVoltageControl(controlledBus, controllerBus, controllerTargetV, voltageControls, voltagePerReactivePowerControl)); } else { // if voltage remote control deactivated and remote control, set local control instead LOGGER.warn("Remote voltage control is not activated. The voltage target of {} with remote control is rescaled from {} to {}", controllerBus.getId(), controllerTargetV, controllerTargetV * controllerBus.getNominalV() / controlledBus.getNominalV()); - createVoltageControl(controllerBus, controllerBus, controllerTargetV, voltageControls); + controlledBus.getVoltageControl().ifPresentOrElse( + vc -> updateVoltageControl(vc, controllerBus, controllerTargetV), // updating only to check targetV uniqueness + () -> createVoltageControl(controllerBus, controllerBus, controllerTargetV, voltageControls, voltagePerReactivePowerControl)); } } } - voltageControls.forEach(LfNetworkLoaderImpl::checkGeneratorsWithSlope); + if (voltagePerReactivePowerControl) { + voltageControls.forEach(LfNetworkLoaderImpl::checkGeneratorsWithSlope); + } } - private static void createVoltageControl(LfBus controlledBus, LfBus controllerBus, double controllerTargetV, List voltageControls) { + private static void createVoltageControl(LfBus controlledBus, LfBus controllerBus, double controllerTargetV, List voltageControls, boolean voltagePerReactivePowerControl) { VoltageControl voltageControl = new VoltageControl(controlledBus, controllerTargetV); voltageControl.addControllerBus(controllerBus); controlledBus.setVoltageControl(voltageControl); - voltageControls.add(voltageControl); + if (voltagePerReactivePowerControl) { + voltageControls.add(voltageControl); + } } private static void updateVoltageControl(VoltageControl voltageControl, LfBus controllerBus, double controllerTargetV) { @@ -484,7 +490,7 @@ private static LfNetwork create(int numCC, int numSC, List buses, List lfBuses = new ArrayList<>(); createBuses(buses, parameters, lfNetwork, lfBuses, loadingContext, report); createBranches(lfBuses, lfNetwork, loadingContext, report, parameters); - createVoltageControls(lfNetwork, lfBuses, parameters.isGeneratorVoltageRemoteControl()); + createVoltageControls(lfNetwork, lfBuses, parameters.isGeneratorVoltageRemoteControl(), parameters.isVoltagePerReactivePowerControl()); // Discrete voltage controls need to be created after voltage controls (to test if both generator and transformer voltage control are on) createDiscreteVoltageControls(lfNetwork, parameters.isBreakers(), loadingContext); diff --git a/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java index b11f493239..fabb92ec51 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java @@ -171,7 +171,8 @@ public void analyse(Network network, List contingencies, LfNetworkParameters lfNetworkParameters = new LfNetworkParameters(slackBusSelector, lfParametersExt.hasVoltageRemoteControl(), true, lfParameters.isTwtSplitShuntAdmittance(), false, lfParametersExt.getPlausibleActivePowerLimit(), false, true, lfParameters.getCountriesToBalance(), - lfParameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD); + lfParameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD, + lfParametersExt.isVoltagePerReactivePowerControl()); List lfNetworks = LfNetwork.load(network, lfNetworkParameters, reporter); LfNetwork lfNetwork = lfNetworks.get(0); checkContingencies(network, lfNetwork, contingencies); diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index b9b6ae1a1a..3eb9cc0a7b 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -599,7 +599,8 @@ public void analyse(Network network, List contingencies, SlackBusSelector slackBusSelector = SlackBusSelector.fromMode(lfParametersExt.getSlackBusSelectionMode(), lfParametersExt.getSlackBusId()); LfNetworkParameters lfNetworkParameters = new LfNetworkParameters(slackBusSelector, false, true, lfParameters.isTwtSplitShuntAdmittance(), false, lfParametersExt.getPlausibleActivePowerLimit(), false, true, lfParameters.getCountriesToBalance(), - lfParameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD); + lfParameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD, + lfParametersExt.isVoltagePerReactivePowerControl()); List lfNetworks = LfNetwork.load(network, lfNetworkParameters, reporter); LfNetwork lfNetwork = lfNetworks.get(0); checkContingencies(network, lfNetwork, contingencies); diff --git a/src/test/java/com/powsybl/openloadflow/ac/GeneratorTargetVoltageInconsistencyTest.java b/src/test/java/com/powsybl/openloadflow/ac/GeneratorTargetVoltageInconsistencyTest.java index 0b7d31047d..afad64fb14 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/GeneratorTargetVoltageInconsistencyTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/GeneratorTargetVoltageInconsistencyTest.java @@ -202,7 +202,7 @@ void remoteTest() { FirstSlackBusSelector slackBusSelector = new FirstSlackBusSelector(); LfNetworkParameters parameters = new LfNetworkParameters(slackBusSelector, true, false, false, false, ParameterConstants.PLAUSIBLE_ACTIVE_POWER_LIMIT_DEFAULT_VALUE, false, - true, Collections.emptySet(), false); + true, Collections.emptySet(), false, false); Generator g = network.getGenerator("g2"); assertEquals(0.5625, g.getTargetV() / g.getTerminal().getVoltageLevel().getNominalV()); @@ -313,7 +313,7 @@ void remoteAndLocalTest() { FirstSlackBusSelector slackBusSelector = new FirstSlackBusSelector(); LfNetworkParameters parameters = new LfNetworkParameters(slackBusSelector, true, false, false, false, ParameterConstants.PLAUSIBLE_ACTIVE_POWER_LIMIT_DEFAULT_VALUE, false, - true, Collections.emptySet(), false); + true, Collections.emptySet(), false, false); assertEquals(412, network.getGenerator("g1").getTargetV()); assertEquals(413, g2.getTargetV()); From f4bf98c911eeb5055e8a5fc0c2dde2d4800a9532 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 21 Jun 2021 11:18:21 +0200 Subject: [PATCH 30/42] Update unit test Signed-off-by: Florian Dupuy --- src/test/resources/debug-parameters.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/resources/debug-parameters.json b/src/test/resources/debug-parameters.json index 93a4f2a36f..a852727099 100644 --- a/src/test/resources/debug-parameters.json +++ b/src/test/resources/debug-parameters.json @@ -25,7 +25,8 @@ "loadPowerFactorConstant" : false, "plausibleActivePowerLimit" : 10000.0, "addRatioToLinesWithDifferentNominalVoltageAtBothEnds" : false, - "slackBusPMaxMismatch" : 1.0 + "slackBusPMaxMismatch" : 1.0, + "voltagePerReactivePowerControl" : false } } }, From 92dffda40b9fde6e14d29ce358166a912350254b Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 21 Jun 2021 11:24:49 +0200 Subject: [PATCH 31/42] VoltageControl::isVoltageControlLocal: Correct use and add doc Signed-off-by: Florian Dupuy --- .../powsybl/openloadflow/ac/equations/AcEquationSystem.java | 2 +- .../openloadflow/ac/equations/AcEquationSystemUpdater.java | 2 +- .../java/com/powsybl/openloadflow/network/VoltageControl.java | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) 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 563ed1b1ba..c9dd523f33 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -60,7 +60,7 @@ private static void createVoltageControlEquations(VoltageControl voltageControl, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { if (voltageControl.isVoltageControlLocal()) { EquationTerm vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); - if (creationParameters.isVoltagePerReactivePowerControl() && voltageControl.getControllerBuses().size() == 1) { + if (creationParameters.isVoltagePerReactivePowerControl()) { Optional generatorControllingVoltageWithSlope = bus.getGeneratorControllingVoltageWithSlope(); if (generatorControllingVoltageWithSlope.isPresent()) { double slope = generatorControllingVoltageWithSlope.get().getSlope(); 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 f3c172b753..8cdff5a683 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java @@ -45,7 +45,7 @@ private void updateControlledBus(VoltageControl voltageControl, EquationSystem e .filter(LfBus::isVoltageControllerEnabled) .collect(Collectors.toList()); - if (creationParameters.isVoltagePerReactivePowerControl() && voltageControl.getControllerBuses().size() == 1 && voltageControl.isVoltageControlLocal() + if (creationParameters.isVoltagePerReactivePowerControl() && voltageControl.isVoltageControlLocal() && controllerBuses.iterator().next().getGeneratorControllingVoltageWithSlope().isPresent()) { LfBus controllerBus = voltageControl.getControllerBuses().iterator().next(); if (!controllerBus.isVoltageControllerEnabled()) { diff --git a/src/main/java/com/powsybl/openloadflow/network/VoltageControl.java b/src/main/java/com/powsybl/openloadflow/network/VoltageControl.java index 3108a132e2..fa3da7c550 100644 --- a/src/main/java/com/powsybl/openloadflow/network/VoltageControl.java +++ b/src/main/java/com/powsybl/openloadflow/network/VoltageControl.java @@ -44,6 +44,10 @@ public void addControllerBus(LfBus controllerBus) { controllerBus.setVoltageControl(this); } + /** + * Check if the voltage control is ONLY local + * @return true if the voltage control is ONLY local, false otherwise + */ public boolean isVoltageControlLocal() { return controllers.size() == 1 && controllers.contains(controlled); } From bce9e1272ed25dd6a3f52a941c00e896071f8d9a Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 21 Jun 2021 11:38:20 +0200 Subject: [PATCH 32/42] LfBus::getGeneratorsControllingVoltageWithSlope returns a list Signed-off-by: Florian Dupuy --- .../ac/ReactiveLimitsOuterLoop.java | 2 +- .../ac/equations/AcEquationSystem.java | 28 ++++++++++--------- .../ac/equations/AcEquationSystemUpdater.java | 4 +-- .../powsybl/openloadflow/network/LfBus.java | 2 +- .../network/impl/AbstractLfBus.java | 5 ++-- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java index 0064b2ada0..b3ef4f54f9 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java @@ -218,7 +218,7 @@ public OuterLoopStatus check(OuterLoopContext context, Reporter reporter) { for (LfBus bus : context.getNetwork().getBuses()) { if (bus.isVoltageControllerEnabled() && !bus.isDisabled()) { checkPvBus(bus, pvToPqBuses, remainingPvBusCount); - } else if (bus.hasVoltageControllerCapability() && !bus.isDisabled() && bus.getGeneratorControllingVoltageWithSlope().isEmpty()) { + } else if (bus.hasVoltageControllerCapability() && !bus.isDisabled() && bus.getGeneratorsControllingVoltageWithSlope().isEmpty()) { // we don't support switching PQ to PV for bus with one controller with slope. checkPqBus(bus, pqToPvBuses); } 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 c9dd523f33..261f2c5df1 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -59,19 +59,7 @@ private static void createBusEquations(LfNetwork network, VariableSet variableSe private static void createVoltageControlEquations(VoltageControl voltageControl, LfBus bus, VariableSet variableSet, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { if (voltageControl.isVoltageControlLocal()) { - EquationTerm vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); - if (creationParameters.isVoltagePerReactivePowerControl()) { - Optional generatorControllingVoltageWithSlope = bus.getGeneratorControllingVoltageWithSlope(); - if (generatorControllingVoltageWithSlope.isPresent()) { - double slope = generatorControllingVoltageWithSlope.get().getSlope(); - createBusWithSlopeEquation(bus, slope, creationParameters, variableSet, equationSystem, vTerm); - } else { - equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm); - } - } else { - equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm); - } - bus.setV(vTerm); + createVoltageControlLocalEquation(bus, variableSet, equationSystem, creationParameters); } else if (bus.isVoltageControlled()) { // remote controlled: set voltage equation on this controlled bus createVoltageControlledBusEquations(voltageControl, equationSystem, variableSet, creationParameters); @@ -82,6 +70,20 @@ private static void createVoltageControlEquations(VoltageControl voltageControl, } } + private static void createVoltageControlLocalEquation(LfBus bus, VariableSet variableSet, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { + EquationTerm vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); + bus.setV(vTerm); + if (creationParameters.isVoltagePerReactivePowerControl()) { + List generatorControllingVoltageWithSlope = bus.getGeneratorsControllingVoltageWithSlope(); + if (!generatorControllingVoltageWithSlope.isEmpty()) { + double slope = generatorControllingVoltageWithSlope.get(0).getSlope(); + createBusWithSlopeEquation(bus, slope, creationParameters, variableSet, equationSystem, vTerm); + return; + } + } + equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm); + } + private static void createShuntEquations(VariableSet variableSet, EquationSystem equationSystem, LfBus bus) { for (LfShunt shunt : bus.getShunts()) { ShuntCompensatorReactiveFlowEquationTerm q = new ShuntCompensatorReactiveFlowEquationTerm(shunt, bus, variableSet); 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 8cdff5a683..01da906c88 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java @@ -46,8 +46,8 @@ private void updateControlledBus(VoltageControl voltageControl, EquationSystem e .collect(Collectors.toList()); if (creationParameters.isVoltagePerReactivePowerControl() && voltageControl.isVoltageControlLocal() - && controllerBuses.iterator().next().getGeneratorControllingVoltageWithSlope().isPresent()) { - LfBus controllerBus = voltageControl.getControllerBuses().iterator().next(); + && !controllerBuses.iterator().next().getGeneratorsControllingVoltageWithSlope().isEmpty()) { + LfBus controllerBus = controllerBuses.iterator().next(); if (!controllerBus.isVoltageControllerEnabled()) { // we only support one controlling static var compensator without any other controlling generators equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V_SLOPE).setActive(false); diff --git a/src/main/java/com/powsybl/openloadflow/network/LfBus.java b/src/main/java/com/powsybl/openloadflow/network/LfBus.java index 2493dfe593..671081b788 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfBus.java @@ -32,7 +32,7 @@ public interface LfBus extends LfElement { boolean isVoltageControlled(); - Optional getGeneratorControllingVoltageWithSlope(); + List getGeneratorsControllingVoltageWithSlope(); /** * Get the number of time, voltage control status has be set from true to false. diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java index 3b527e50e3..d19613f699 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java @@ -16,6 +16,7 @@ import java.util.*; import java.util.function.ToDoubleFunction; +import java.util.stream.Collectors; import static com.powsybl.openloadflow.util.EvaluableConstants.NAN; @@ -131,8 +132,8 @@ public boolean isVoltageControlled() { } @Override - public Optional getGeneratorControllingVoltageWithSlope() { - return generators.stream().filter(gen -> gen.hasVoltageControl() && gen.getSlope() != 0).findFirst(); + public List getGeneratorsControllingVoltageWithSlope() { + return generators.stream().filter(gen -> gen.hasVoltageControl() && gen.getSlope() != 0).collect(Collectors.toList()); } @Override From e3144fcccc4f52b952145e4d0894116cc44f102f Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 21 Jun 2021 12:36:22 +0200 Subject: [PATCH 33/42] Simpler LfNetworkLoaderImpl::checkGeneratorsWithSlope Signed-off-by: Florian Dupuy --- .../openloadflow/network/VoltageControl.java | 8 ++++++++ .../network/impl/LfNetworkLoaderImpl.java | 18 ++++-------------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/VoltageControl.java b/src/main/java/com/powsybl/openloadflow/network/VoltageControl.java index fa3da7c550..be5af2e90d 100644 --- a/src/main/java/com/powsybl/openloadflow/network/VoltageControl.java +++ b/src/main/java/com/powsybl/openloadflow/network/VoltageControl.java @@ -51,4 +51,12 @@ public void addControllerBus(LfBus controllerBus) { public boolean isVoltageControlLocal() { return controllers.size() == 1 && controllers.contains(controlled); } + + /** + * Check if the voltage control is shared + * @return true if the voltage control is shared, false otherwise + */ + public boolean isSharedControl() { + return controllers.stream().flatMap(lfBus -> lfBus.getGenerators().stream()).filter(LfGenerator::hasVoltageControl).count() > 1; + } } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java index 3701bed985..a76d791415 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java @@ -112,24 +112,14 @@ private static void updateVoltageControl(VoltageControl voltageControl, LfBus co } private static void checkGeneratorsWithSlope(VoltageControl voltageControl) { - List generatorsWithSlope = voltageControl.getControllerBuses().stream() .flatMap(lfBus -> lfBus.getGenerators().stream().filter(generator -> generator.hasVoltageControl() && generator.getSlope() != 0)) .collect(Collectors.toList()); - if (generatorsWithSlope.size() > 1) { - // we don't support a bus controlled by several generators controlling voltage with slope and other generators controlling voltage - generatorsWithSlope.stream().skip(1).forEach(g -> g.setSlope(0)); - LOGGER.warn("Non supported: {} generators are controlling voltage of bus {} with slope. Slope is kept on first generator {} and deactivated on the others.", - generatorsWithSlope.size(), voltageControl.getControlledBus(), generatorsWithSlope.get(0)); - generatorsWithSlope = Collections.singletonList(generatorsWithSlope.get(0)); - } - - if (generatorsWithSlope.size() == 1 && generatorsWithSlope.get(0).getBus().getGenerators().stream().filter(LfGenerator::hasVoltageControl).count() > 1) { - // we don't support a generator controlling voltage with slope and other generators controlling voltage - generatorsWithSlope.get(0).setSlope(0); - LOGGER.warn("Non supported: several generators of bus {} control voltage and one controls voltage with slope. Slope is therefore deactivated on those generators.", - generatorsWithSlope.get(0).getBus()); + if (!generatorsWithSlope.isEmpty() && voltageControl.isSharedControl()) { + generatorsWithSlope.forEach(generator -> generator.setSlope(0)); + LOGGER.warn("Non supported: shared control on bus {} with {} generator(s) controlling voltage with slope. Slope set to 0 on all those generators.", + voltageControl.getControlledBus(), generatorsWithSlope.size()); } } From e7db88d0fcd81a3ba7c961df0b1587673266a344 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 22 Jun 2021 15:12:45 +0200 Subject: [PATCH 34/42] Add a check to verify that the control is local. Signed-off-by: Anne Tilloy --- .../ac/equations/AcEquationSystem.java | 10 ++++----- .../network/impl/LfNetworkLoaderImpl.java | 22 ++++++++++++------- 2 files changed, 19 insertions(+), 13 deletions(-) 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 2e46543238..ece9932737 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -60,7 +60,7 @@ private static void createBusEquations(LfNetwork network, VariableSet variableSe private static void createVoltageControlEquations(VoltageControl voltageControl, LfBus bus, VariableSet variableSet, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { if (voltageControl.isVoltageControlLocal()) { - createVoltageControlLocalEquation(bus, variableSet, equationSystem, creationParameters); + createLocalVoltageControlEquation(bus, variableSet, equationSystem, creationParameters); } else if (bus.isVoltageControlled()) { // remote controlled: set voltage equation on this controlled bus createVoltageControlledBusEquations(voltageControl, equationSystem, variableSet, creationParameters); @@ -71,13 +71,13 @@ private static void createVoltageControlEquations(VoltageControl voltageControl, } } - private static void createVoltageControlLocalEquation(LfBus bus, VariableSet variableSet, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { + private static void createLocalVoltageControlEquation(LfBus bus, VariableSet variableSet, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { EquationTerm vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); bus.setV(vTerm); if (creationParameters.isVoltagePerReactivePowerControl()) { - List generatorControllingVoltageWithSlope = bus.getGeneratorsControllingVoltageWithSlope(); - if (!generatorControllingVoltageWithSlope.isEmpty()) { - double slope = generatorControllingVoltageWithSlope.get(0).getSlope(); + List generatorsControllingVoltageWithSlope = bus.getGeneratorsControllingVoltageWithSlope(); + if (generatorsControllingVoltageWithSlope.size() == 1) { + double slope = generatorsControllingVoltageWithSlope.get(0).getSlope(); createBusWithSlopeEquation(bus, slope, creationParameters, variableSet, equationSystem, vTerm); return; } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java index 7557149cfd..fd5278ee57 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java @@ -84,7 +84,7 @@ private static void createVoltageControls(LfNetwork lfNetwork, List lfBus } else { // if voltage remote control deactivated and remote control, set local control instead LOGGER.warn("Remote voltage control is not activated. The voltage target of {} with remote control is rescaled from {} to {}", - controllerBus.getId(), controllerTargetV, controllerTargetV * controllerBus.getNominalV() / controlledBus.getNominalV()); + controllerBus.getId(), controllerTargetV, controllerTargetV * controllerBus.getNominalV() / controlledBus.getNominalV()); controlledBus.getVoltageControl().ifPresentOrElse( vc -> updateVoltageControl(vc, controllerBus, controllerTargetV), // updating only to check targetV uniqueness () -> createVoltageControl(controllerBus, controllerBus, controllerTargetV, voltageControls, voltagePerReactivePowerControl)); @@ -113,13 +113,19 @@ private static void updateVoltageControl(VoltageControl voltageControl, LfBus co private static void checkGeneratorsWithSlope(VoltageControl voltageControl) { List generatorsWithSlope = voltageControl.getControllerBuses().stream() - .flatMap(lfBus -> lfBus.getGenerators().stream().filter(generator -> generator.hasVoltageControl() && generator.getSlope() != 0)) - .collect(Collectors.toList()); - - if (!generatorsWithSlope.isEmpty() && voltageControl.isSharedControl()) { - generatorsWithSlope.forEach(generator -> generator.setSlope(0)); - LOGGER.warn("Non supported: shared control on bus {} with {} generator(s) controlling voltage with slope. Slope set to 0 on all those generators.", - voltageControl.getControlledBus(), generatorsWithSlope.size()); + .flatMap(lfBus -> lfBus.getGenerators().stream().filter(generator -> generator.hasVoltageControl() && generator.getSlope() != 0)) + .collect(Collectors.toList()); + + if (!generatorsWithSlope.isEmpty()) { + if (voltageControl.isSharedControl()) { + generatorsWithSlope.forEach(generator -> generator.setSlope(0)); + LOGGER.warn("Non supported: shared control on bus {} with {} generator(s) controlling voltage with slope. Slope set to 0 on all those generators", + voltageControl.getControlledBus(), generatorsWithSlope.size()); + } + if (!voltageControl.isVoltageControlLocal()) { + LOGGER.warn("Non supported: remote control on bus {} with {} generator(s) controlling voltage with slope", + voltageControl.getControlledBus(), generatorsWithSlope.size()); + } } } From 88007556194e92863a478d71105a78614fa9f173 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Fri, 25 Jun 2021 13:43:34 +0200 Subject: [PATCH 35/42] Set slope only if voltagePerReactivePowerControl true Signed-off-by: Florian Dupuy --- .../powsybl/openloadflow/network/impl/AbstractLfBus.java | 4 ++-- .../openloadflow/network/impl/LfNetworkLoaderImpl.java | 2 +- .../network/impl/LfStaticVarCompensatorImpl.java | 8 ++++---- .../powsybl/openloadflow/network/impl/LfBusImplTest.java | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java index c1bb413f02..de9827fec8 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java @@ -224,9 +224,9 @@ void addGenerator(Generator generator, boolean breakers, LfNetworkLoadingReport add(LfGeneratorImpl.create(generator, breakers, report, plausibleActivePowerLimit)); } - void addStaticVarCompensator(StaticVarCompensator staticVarCompensator, boolean breakers, LfNetworkLoadingReport report) { + void addStaticVarCompensator(StaticVarCompensator staticVarCompensator, boolean voltagePerReactivePowerControl, boolean breakers, LfNetworkLoadingReport report) { if (staticVarCompensator.getRegulationMode() != StaticVarCompensator.RegulationMode.OFF) { - add(LfStaticVarCompensatorImpl.create(staticVarCompensator, this, breakers, report)); + add(LfStaticVarCompensatorImpl.create(staticVarCompensator, this, voltagePerReactivePowerControl, breakers, report)); } } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java index fd5278ee57..6d9b656b71 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java @@ -219,7 +219,7 @@ public void visitDanglingLine(DanglingLine danglingLine) { @Override public void visitStaticVarCompensator(StaticVarCompensator staticVarCompensator) { - lfBus.addStaticVarCompensator(staticVarCompensator, parameters.isBreakers(), report); + lfBus.addStaticVarCompensator(staticVarCompensator, parameters.isVoltagePerReactivePowerControl(), parameters.isBreakers(), report); if (staticVarCompensator.getRegulationMode() == StaticVarCompensator.RegulationMode.VOLTAGE) { report.voltageControllerCount++; } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java index a592c20b56..2e8f74d455 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java @@ -26,7 +26,7 @@ public final class LfStaticVarCompensatorImpl extends AbstractLfGenerator { private double slope = 0; - private LfStaticVarCompensatorImpl(StaticVarCompensator svc, AbstractLfBus bus, boolean breakers, LfNetworkLoadingReport report) { + private LfStaticVarCompensatorImpl(StaticVarCompensator svc, AbstractLfBus bus, boolean voltagePerReactivePowerControl, boolean breakers, LfNetworkLoadingReport report) { super(0); this.svc = svc; this.nominalV = svc.getTerminal().getVoltageLevel().getNominalV(); @@ -63,14 +63,14 @@ public double getMaxQ(double p) { if (svc.getRegulationMode() == StaticVarCompensator.RegulationMode.VOLTAGE) { setVoltageControl(svc.getVoltageSetpoint(), svc.getRegulatingTerminal(), breakers, report); } - if (svc.getExtension(VoltagePerReactivePowerControl.class) != null) { + if (voltagePerReactivePowerControl && svc.getExtension(VoltagePerReactivePowerControl.class) != null) { this.slope = svc.getExtension(VoltagePerReactivePowerControl.class).getSlope() * PerUnit.SB / nominalV; } } - public static LfStaticVarCompensatorImpl create(StaticVarCompensator svc, AbstractLfBus bus, boolean breakers, LfNetworkLoadingReport report) { + public static LfStaticVarCompensatorImpl create(StaticVarCompensator svc, AbstractLfBus bus, boolean voltagePerReactivePowerControl, boolean breakers, LfNetworkLoadingReport report) { Objects.requireNonNull(svc); - return new LfStaticVarCompensatorImpl(svc, bus, breakers, report); + return new LfStaticVarCompensatorImpl(svc, bus, voltagePerReactivePowerControl, breakers, report); } @Override diff --git a/src/test/java/com/powsybl/openloadflow/network/impl/LfBusImplTest.java b/src/test/java/com/powsybl/openloadflow/network/impl/LfBusImplTest.java index 88a1172dc7..2dc2b60cc3 100644 --- a/src/test/java/com/powsybl/openloadflow/network/impl/LfBusImplTest.java +++ b/src/test/java/com/powsybl/openloadflow/network/impl/LfBusImplTest.java @@ -131,9 +131,9 @@ void updateGeneratorsStateTest() { LfBusImpl lfBus = new LfBusImpl(bus1, mainNetwork, 385, 0, true); LfNetworkLoadingReport lfNetworkLoadingReport = new LfNetworkLoadingReport(); - lfBus.addStaticVarCompensator(svc1, true, lfNetworkLoadingReport); - lfBus.addStaticVarCompensator(svc2, true, lfNetworkLoadingReport); - lfBus.addStaticVarCompensator(svc3, true, lfNetworkLoadingReport); + lfBus.addStaticVarCompensator(svc1, false, true, lfNetworkLoadingReport); + lfBus.addStaticVarCompensator(svc2, false, true, lfNetworkLoadingReport); + lfBus.addStaticVarCompensator(svc3, false, true, lfNetworkLoadingReport); double generationQ = -6.412103131789854; lfBus.updateGeneratorsState(generationQ * PerUnit.SB, true); double sumQ = 0; From 27a04d3c3ed54a76d3e8f4a16722221948763452 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Mon, 28 Jun 2021 11:38:27 +0200 Subject: [PATCH 36/42] Clean code. Signed-off-by: Anne Tilloy --- .../ac/ReactiveLimitsOuterLoop.java | 10 +++++-- .../ac/equations/AcEquationSystem.java | 12 ++++---- .../AcEquationSystemCreationParameters.java | 10 ++----- .../ac/equations/AcEquationSystemUpdater.java | 29 +++++++++---------- .../ac/outerloop/AcloadFlowEngine.java | 2 +- .../network/impl/LfNetworkLoaderImpl.java | 1 + .../openloadflow/ac/SwitchPqPvTest.java | 4 ++- src/test/resources/logback-test.xml | 2 +- 8 files changed, 33 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java index b3ef4f54f9..4c4141b24d 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java @@ -218,9 +218,13 @@ public OuterLoopStatus check(OuterLoopContext context, Reporter reporter) { for (LfBus bus : context.getNetwork().getBuses()) { if (bus.isVoltageControllerEnabled() && !bus.isDisabled()) { checkPvBus(bus, pvToPqBuses, remainingPvBusCount); - } else if (bus.hasVoltageControllerCapability() && !bus.isDisabled() && bus.getGeneratorsControllingVoltageWithSlope().isEmpty()) { - // we don't support switching PQ to PV for bus with one controller with slope. - checkPqBus(bus, pqToPvBuses); + } else if (bus.hasVoltageControllerCapability() && !bus.isDisabled()) { + if (bus.getGeneratorsControllingVoltageWithSlope().isEmpty()) { + // we don't support switching PQ to PV for bus with one controller with slope. + checkPqBus(bus, pqToPvBuses); + } else { + LOGGER.warn("Controller bus '{}' wants to control back voltage with slope: not supported", bus.getId()); + } } } 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 ece9932737..5b7fd9f9ce 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -74,13 +74,11 @@ private static void createVoltageControlEquations(VoltageControl voltageControl, private static void createLocalVoltageControlEquation(LfBus bus, VariableSet variableSet, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { EquationTerm vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); bus.setV(vTerm); - if (creationParameters.isVoltagePerReactivePowerControl()) { - List generatorsControllingVoltageWithSlope = bus.getGeneratorsControllingVoltageWithSlope(); - if (generatorsControllingVoltageWithSlope.size() == 1) { - double slope = generatorsControllingVoltageWithSlope.get(0).getSlope(); - createBusWithSlopeEquation(bus, slope, creationParameters, variableSet, equationSystem, vTerm); - return; - } + List generatorsControllingVoltageWithSlope = bus.getGeneratorsControllingVoltageWithSlope(); + if (generatorsControllingVoltageWithSlope.size() == 1) { + double slope = generatorsControllingVoltageWithSlope.get(0).getSlope(); + createBusWithSlopeEquation(bus, slope, creationParameters, variableSet, equationSystem, vTerm); + return; } equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm); } diff --git a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java index ea3d9faae7..4655af8be4 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java @@ -21,23 +21,20 @@ public class AcEquationSystemCreationParameters { private final Set branchesWithCurrent; - private final boolean voltagePerReactivePowerControl; - public AcEquationSystemCreationParameters(boolean phaseControl, boolean transformerVoltageControl) { this(phaseControl, transformerVoltageControl, false); } public AcEquationSystemCreationParameters(boolean phaseControl, boolean transformerVoltageControl, boolean forceA1Var) { - this(phaseControl, transformerVoltageControl, forceA1Var, null, false); + this(phaseControl, transformerVoltageControl, forceA1Var, null); } public AcEquationSystemCreationParameters(boolean phaseControl, boolean transformerVoltageControl, boolean forceA1Var, - Set branchesWithCurrent, boolean voltagePerReactivePowerControl) { + Set branchesWithCurrent) { this.phaseControl = phaseControl; this.transformerVoltageControl = transformerVoltageControl; this.forceA1Var = forceA1Var; this.branchesWithCurrent = branchesWithCurrent; - this.voltagePerReactivePowerControl = voltagePerReactivePowerControl; } public boolean isPhaseControl() { @@ -56,7 +53,4 @@ public Set getBranchesWithCurrent() { return branchesWithCurrent; } - public boolean isVoltagePerReactivePowerControl() { - return voltagePerReactivePowerControl; - } } 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 f4144b448e..10d97e19bd 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java @@ -40,29 +40,26 @@ private void updateControlledBus(VoltageControl voltageControl, EquationSystem e LfBus controlledBus = voltageControl.getControlledBus(); Set controllerBuses = voltageControl.getControllerBuses(); - // clean reactive power distribution equations - controllerBuses.forEach(b -> equationSystem.removeEquation(b.getNum(), EquationType.ZERO_Q)); - - // controlled bus has a voltage equation only if one of the controller bus has voltage control on - List controllerBusesWithVoltageControlOn = controllerBuses.stream() - .filter(LfBus::isVoltageControllerEnabled) - .collect(Collectors.toList()); - - if (creationParameters.isVoltagePerReactivePowerControl() && voltageControl.isVoltageControlLocal() - && !controllerBuses.iterator().next().getGeneratorsControllingVoltageWithSlope().isEmpty()) { + if (!controllerBuses.iterator().next().getGeneratorsControllingVoltageWithSlope().isEmpty()) { + // 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. LfBus controllerBus = controllerBuses.iterator().next(); if (!controllerBus.isVoltageControllerEnabled()) { - // we only support one controlling static var compensator without any other controlling generators equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V_SLOPE).setActive(false); } } else { + // controlled bus has a voltage equation only if one of the controller bus has voltage control on + List controllerBusesWithVoltageControlOn = controllerBuses.stream() + .filter(LfBus::isVoltageControllerEnabled) + .collect(Collectors.toList()); + // clean reactive power distribution equations + controllerBuses.forEach(b -> equationSystem.removeEquation(b.getNum(), EquationType.ZERO_Q)); // is there one static var compensator with a non-zero slope equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V).setActive(!controllerBusesWithVoltageControlOn.isEmpty()); - } - - // create reactive power equations on controller buses that have voltage control on - if (!controllerBusesWithVoltageControlOn.isEmpty()) { - AcEquationSystem.createReactivePowerDistributionEquations(equationSystem, variableSet, creationParameters, controllerBusesWithVoltageControlOn); + // create reactive power equations on controller buses that have voltage control on + if (!controllerBusesWithVoltageControlOn.isEmpty()) { + AcEquationSystem.createReactivePowerDistributionEquations(equationSystem, variableSet, creationParameters, controllerBusesWithVoltageControlOn); + } } } diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java index e8cc48cc2b..9b18048f0f 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java @@ -142,7 +142,7 @@ public AcLoadFlowResult run(Reporter reporter) { variableSet = new VariableSet(); AcEquationSystemCreationParameters creationParameters = new AcEquationSystemCreationParameters( parameters.isPhaseControl(), parameters.isTransformerVoltageControlOn(), parameters.isForceA1Var(), - parameters.getBranchesWithCurrent(), parameters.isVoltagePerReactivePowerControl()); + parameters.getBranchesWithCurrent()); equationSystem = AcEquationSystem.create(network, variableSet, creationParameters); j = new JacobianMatrix(equationSystem, parameters.getMatrixFactory()); targetVector = new TargetVector(network, equationSystem); diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java index 6d9b656b71..2dc358a568 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java @@ -123,6 +123,7 @@ private static void checkGeneratorsWithSlope(VoltageControl voltageControl) { voltageControl.getControlledBus(), generatorsWithSlope.size()); } if (!voltageControl.isVoltageControlLocal()) { + generatorsWithSlope.forEach(generator -> generator.setSlope(0)); LOGGER.warn("Non supported: remote control on bus {} with {} generator(s) controlling voltage with slope", voltageControl.getControlledBus(), generatorsWithSlope.size()); } diff --git a/src/test/java/com/powsybl/openloadflow/ac/SwitchPqPvTest.java b/src/test/java/com/powsybl/openloadflow/ac/SwitchPqPvTest.java index bd115b8f1f..496164a03c 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/SwitchPqPvTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/SwitchPqPvTest.java @@ -244,12 +244,14 @@ void testWithSlope() { assertVoltageEquals(20, b3); // PV System.out.println(b3.getV()); - svc3.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(0.03).add(); + parametersExt.setVoltagePerReactivePowerControl(true); + svc3.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(0.00001).add(); LoadFlowResult result2 = loadFlowRunner.run(network, parameters); assertTrue(result2.isOk()); // bus 1 and 3 switch PQ at first outer loop, then at next outer loop bus 3 does not go back PV assertVoltageEquals(17.034003, b1); // PQ => v != 17 assertVoltageEquals(21, b2); // PV + System.out.println(b3.getV()); assertEquals(20.00140, b3.getV(), 10E-3); // remains PQ because of slope } } diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 03f44ff80a..85148fd285 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -13,7 +13,7 @@ %-5p %d{HH:mm:ss.SSS} %-20C{1} | %m%n - + From 2a2d28a35e8e8aee3c0576a082966bf17f13dec0 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Mon, 28 Jun 2021 11:41:50 +0200 Subject: [PATCH 37/42] Remove useless changes. Signed-off-by: Anne Tilloy --- .../ac/equations/AcEquationSystemCreationParameters.java | 3 +-- .../powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java index 4655af8be4..3f6318d98d 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java @@ -29,8 +29,7 @@ public AcEquationSystemCreationParameters(boolean phaseControl, boolean transfor this(phaseControl, transformerVoltageControl, forceA1Var, null); } - public AcEquationSystemCreationParameters(boolean phaseControl, boolean transformerVoltageControl, boolean forceA1Var, - Set branchesWithCurrent) { + public AcEquationSystemCreationParameters(boolean phaseControl, boolean transformerVoltageControl, boolean forceA1Var, Set branchesWithCurrent) { this.phaseControl = phaseControl; this.transformerVoltageControl = transformerVoltageControl; this.forceA1Var = forceA1Var; diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java index 9b18048f0f..b20e0a7e69 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java @@ -141,8 +141,7 @@ public AcLoadFlowResult run(Reporter reporter) { variableSet = new VariableSet(); AcEquationSystemCreationParameters creationParameters = new AcEquationSystemCreationParameters( - parameters.isPhaseControl(), parameters.isTransformerVoltageControlOn(), parameters.isForceA1Var(), - parameters.getBranchesWithCurrent()); + parameters.isPhaseControl(), parameters.isTransformerVoltageControlOn(), parameters.isForceA1Var(), parameters.getBranchesWithCurrent()); equationSystem = AcEquationSystem.create(network, variableSet, creationParameters); j = new JacobianMatrix(equationSystem, parameters.getMatrixFactory()); targetVector = new TargetVector(network, equationSystem); From 70ccc31ff335d4b99c439ccfd080878dc27e2c75 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 28 Jun 2021 14:28:22 +0200 Subject: [PATCH 38/42] Performance: avoid always filtering out generators based on slope Signed-off-by: Florian Dupuy --- .../openloadflow/ac/ReactiveLimitsOuterLoop.java | 4 ++-- .../openloadflow/ac/equations/AcEquationSystem.java | 6 +++--- .../ac/equations/AcEquationSystemUpdater.java | 6 +++--- .../java/com/powsybl/openloadflow/network/LfBus.java | 4 ++++ .../openloadflow/network/impl/AbstractLfBus.java | 12 ++++++++++++ .../network/impl/LfNetworkLoaderImpl.java | 6 ++++-- 6 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java index 4c4141b24d..03c660ab55 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java @@ -219,10 +219,10 @@ public OuterLoopStatus check(OuterLoopContext context, Reporter reporter) { if (bus.isVoltageControllerEnabled() && !bus.isDisabled()) { checkPvBus(bus, pvToPqBuses, remainingPvBusCount); } else if (bus.hasVoltageControllerCapability() && !bus.isDisabled()) { - if (bus.getGeneratorsControllingVoltageWithSlope().isEmpty()) { - // we don't support switching PQ to PV for bus with one controller with slope. + if (!bus.hasGeneratorWithSlope()) { checkPqBus(bus, pqToPvBuses); } else { + // we don't support switching PQ to PV for bus with one controller with slope. LOGGER.warn("Controller bus '{}' wants to control back voltage with slope: not supported", bus.getId()); } } 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 5b7fd9f9ce..8768e82b28 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -74,9 +74,9 @@ private static void createVoltageControlEquations(VoltageControl voltageControl, private static void createLocalVoltageControlEquation(LfBus bus, VariableSet variableSet, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { EquationTerm vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); bus.setV(vTerm); - List generatorsControllingVoltageWithSlope = bus.getGeneratorsControllingVoltageWithSlope(); - if (generatorsControllingVoltageWithSlope.size() == 1) { - double slope = generatorsControllingVoltageWithSlope.get(0).getSlope(); + if (bus.hasGeneratorWithSlope()) { + // 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, creationParameters, variableSet, equationSystem, vTerm); return; } 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 10d97e19bd..3981a1efc8 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java @@ -40,11 +40,11 @@ private void updateControlledBus(VoltageControl voltageControl, EquationSystem e LfBus controlledBus = voltageControl.getControlledBus(); Set controllerBuses = voltageControl.getControllerBuses(); - if (!controllerBuses.iterator().next().getGeneratorsControllingVoltageWithSlope().isEmpty()) { + LfBus firstControllerBus = controllerBuses.iterator().next(); + if (firstControllerBus.hasGeneratorWithSlope()) { // 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. - LfBus controllerBus = controllerBuses.iterator().next(); - if (!controllerBus.isVoltageControllerEnabled()) { + if (!firstControllerBus.isVoltageControllerEnabled()) { equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V_SLOPE).setActive(false); } } else { diff --git a/src/main/java/com/powsybl/openloadflow/network/LfBus.java b/src/main/java/com/powsybl/openloadflow/network/LfBus.java index cf81e25f38..a9c86b5bd7 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfBus.java @@ -34,6 +34,10 @@ public interface LfBus extends LfElement { List getGeneratorsControllingVoltageWithSlope(); + boolean hasGeneratorWithSlope(); + + void setHasGeneratorWithSlope(boolean b); + /** * Get the number of time, voltage control status has be set from true to false. * diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java index de9827fec8..027fb239b6 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java @@ -37,6 +37,8 @@ public abstract class AbstractLfBus extends AbstractElement implements LfBus { protected double calculatedQ = Double.NaN; + private boolean hasGeneratorWithSlope; + protected boolean voltageControllerEnabled = false; protected int voltageControlSwitchOffCount = 0; @@ -136,6 +138,16 @@ public List getGeneratorsControllingVoltageWithSlope() { return generators.stream().filter(gen -> gen.hasVoltageControl() && gen.getSlope() != 0).collect(Collectors.toList()); } + @Override + public boolean hasGeneratorWithSlope() { + return hasGeneratorWithSlope; + } + + @Override + public void setHasGeneratorWithSlope(boolean b) { + hasGeneratorWithSlope = b; + } + @Override public boolean isVoltageControllerEnabled() { return voltageControllerEnabled; diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java index 2dc358a568..ea7f1472e4 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java @@ -121,11 +121,13 @@ private static void checkGeneratorsWithSlope(VoltageControl voltageControl) { generatorsWithSlope.forEach(generator -> generator.setSlope(0)); LOGGER.warn("Non supported: shared control on bus {} with {} generator(s) controlling voltage with slope. Slope set to 0 on all those generators", voltageControl.getControlledBus(), generatorsWithSlope.size()); - } - if (!voltageControl.isVoltageControlLocal()) { + } else if (!voltageControl.isVoltageControlLocal()) { generatorsWithSlope.forEach(generator -> generator.setSlope(0)); LOGGER.warn("Non supported: remote control on bus {} with {} generator(s) controlling voltage with slope", voltageControl.getControlledBus(), generatorsWithSlope.size()); + } else { + // Only one generator with slope with local control + generatorsWithSlope.get(0).getBus().setHasGeneratorWithSlope(true); } } } From 15ae6ccc62b44da22b03e0d194398b2836a41671 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 28 Jun 2021 14:48:59 +0200 Subject: [PATCH 39/42] Small refactor/renaming Signed-off-by: Florian Dupuy --- .../openloadflow/ac/ReactiveLimitsOuterLoop.java | 2 +- .../openloadflow/ac/equations/AcEquationSystem.java | 2 +- .../ac/equations/AcEquationSystemUpdater.java | 2 +- .../com/powsybl/openloadflow/network/LfBus.java | 4 ++-- .../openloadflow/network/impl/AbstractLfBus.java | 13 +++++++++---- .../network/impl/LfNetworkLoaderImpl.java | 10 ++++------ 6 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java index 03c660ab55..15fb777ced 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/ReactiveLimitsOuterLoop.java @@ -219,7 +219,7 @@ public OuterLoopStatus check(OuterLoopContext context, Reporter reporter) { if (bus.isVoltageControllerEnabled() && !bus.isDisabled()) { checkPvBus(bus, pvToPqBuses, remainingPvBusCount); } else if (bus.hasVoltageControllerCapability() && !bus.isDisabled()) { - if (!bus.hasGeneratorWithSlope()) { + if (!bus.hasGeneratorsWithSlope()) { checkPqBus(bus, pqToPvBuses); } else { // we don't support switching PQ to PV for bus with one controller with slope. 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 8768e82b28..b01f3aed60 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -74,7 +74,7 @@ private static void createVoltageControlEquations(VoltageControl voltageControl, private static void createLocalVoltageControlEquation(LfBus bus, VariableSet variableSet, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { EquationTerm vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval()); bus.setV(vTerm); - if (bus.hasGeneratorWithSlope()) { + 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, creationParameters, variableSet, equationSystem, vTerm); 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 3981a1efc8..cadbb2ffaa 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemUpdater.java @@ -41,7 +41,7 @@ private void updateControlledBus(VoltageControl voltageControl, EquationSystem e Set controllerBuses = voltageControl.getControllerBuses(); LfBus firstControllerBus = controllerBuses.iterator().next(); - if (firstControllerBus.hasGeneratorWithSlope()) { + 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. if (!firstControllerBus.isVoltageControllerEnabled()) { diff --git a/src/main/java/com/powsybl/openloadflow/network/LfBus.java b/src/main/java/com/powsybl/openloadflow/network/LfBus.java index a9c86b5bd7..09792ef877 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfBus.java @@ -34,9 +34,9 @@ public interface LfBus extends LfElement { List getGeneratorsControllingVoltageWithSlope(); - boolean hasGeneratorWithSlope(); + boolean hasGeneratorsWithSlope(); - void setHasGeneratorWithSlope(boolean b); + void removeSlopes(); /** * Get the number of time, voltage control status has be set from true to false. diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java index 027fb239b6..d54ec86412 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java @@ -139,13 +139,14 @@ public List getGeneratorsControllingVoltageWithSlope() { } @Override - public boolean hasGeneratorWithSlope() { + public boolean hasGeneratorsWithSlope() { return hasGeneratorWithSlope; } @Override - public void setHasGeneratorWithSlope(boolean b) { - hasGeneratorWithSlope = b; + public void removeSlopes() { + hasGeneratorWithSlope = false; + generators.forEach(g -> g.setSlope(0)); } @Override @@ -238,7 +239,11 @@ void addGenerator(Generator generator, boolean breakers, LfNetworkLoadingReport void addStaticVarCompensator(StaticVarCompensator staticVarCompensator, boolean voltagePerReactivePowerControl, boolean breakers, LfNetworkLoadingReport report) { if (staticVarCompensator.getRegulationMode() != StaticVarCompensator.RegulationMode.OFF) { - add(LfStaticVarCompensatorImpl.create(staticVarCompensator, this, voltagePerReactivePowerControl, breakers, report)); + LfStaticVarCompensatorImpl lfSvc = LfStaticVarCompensatorImpl.create(staticVarCompensator, this, voltagePerReactivePowerControl, breakers, report); + add(lfSvc); + if (lfSvc.getSlope() > 0) { + hasGeneratorWithSlope = true; + } } } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java index ea7f1472e4..6efb29ae9e 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java @@ -113,21 +113,19 @@ private static void updateVoltageControl(VoltageControl voltageControl, LfBus co private static void checkGeneratorsWithSlope(VoltageControl voltageControl) { List generatorsWithSlope = voltageControl.getControllerBuses().stream() - .flatMap(lfBus -> lfBus.getGenerators().stream().filter(generator -> generator.hasVoltageControl() && generator.getSlope() != 0)) + .filter(LfBus::hasGeneratorsWithSlope) + .flatMap(lfBus -> lfBus.getGeneratorsControllingVoltageWithSlope().stream()) .collect(Collectors.toList()); if (!generatorsWithSlope.isEmpty()) { if (voltageControl.isSharedControl()) { - generatorsWithSlope.forEach(generator -> generator.setSlope(0)); + generatorsWithSlope.forEach(generator -> generator.getBus().removeSlopes()); LOGGER.warn("Non supported: shared control on bus {} with {} generator(s) controlling voltage with slope. Slope set to 0 on all those generators", voltageControl.getControlledBus(), generatorsWithSlope.size()); } else if (!voltageControl.isVoltageControlLocal()) { - generatorsWithSlope.forEach(generator -> generator.setSlope(0)); + generatorsWithSlope.forEach(generator -> generator.getBus().removeSlopes()); LOGGER.warn("Non supported: remote control on bus {} with {} generator(s) controlling voltage with slope", voltageControl.getControlledBus(), generatorsWithSlope.size()); - } else { - // Only one generator with slope with local control - generatorsWithSlope.get(0).getBus().setHasGeneratorWithSlope(true); } } } From 39021d875718e000ab6dedf56a9b9430f71f11f7 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Mon, 28 Jun 2021 14:55:04 +0200 Subject: [PATCH 40/42] fix Signed-off-by: Florian Dupuy --- .../java/com/powsybl/openloadflow/network/LfBus.java | 2 +- .../openloadflow/network/impl/AbstractLfBus.java | 12 ++++++------ .../network/impl/LfNetworkLoaderImpl.java | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfBus.java b/src/main/java/com/powsybl/openloadflow/network/LfBus.java index 09792ef877..db2833a39f 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfBus.java @@ -36,7 +36,7 @@ public interface LfBus extends LfElement { boolean hasGeneratorsWithSlope(); - void removeSlopes(); + void removeGeneratorSlopes(); /** * Get the number of time, voltage control status has be set from true to false. diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java index d54ec86412..f5728b8f38 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java @@ -37,7 +37,7 @@ public abstract class AbstractLfBus extends AbstractElement implements LfBus { protected double calculatedQ = Double.NaN; - private boolean hasGeneratorWithSlope; + private boolean hasGeneratorsWithSlope; protected boolean voltageControllerEnabled = false; @@ -140,12 +140,12 @@ public List getGeneratorsControllingVoltageWithSlope() { @Override public boolean hasGeneratorsWithSlope() { - return hasGeneratorWithSlope; + return hasGeneratorsWithSlope; } @Override - public void removeSlopes() { - hasGeneratorWithSlope = false; + public void removeGeneratorSlopes() { + hasGeneratorsWithSlope = false; generators.forEach(g -> g.setSlope(0)); } @@ -241,8 +241,8 @@ void addStaticVarCompensator(StaticVarCompensator staticVarCompensator, boolean if (staticVarCompensator.getRegulationMode() != StaticVarCompensator.RegulationMode.OFF) { LfStaticVarCompensatorImpl lfSvc = LfStaticVarCompensatorImpl.create(staticVarCompensator, this, voltagePerReactivePowerControl, breakers, report); add(lfSvc); - if (lfSvc.getSlope() > 0) { - hasGeneratorWithSlope = true; + if (lfSvc.getSlope() != 0) { + hasGeneratorsWithSlope = true; } } } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java index 6efb29ae9e..fc8cafec1d 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java @@ -119,11 +119,11 @@ private static void checkGeneratorsWithSlope(VoltageControl voltageControl) { if (!generatorsWithSlope.isEmpty()) { if (voltageControl.isSharedControl()) { - generatorsWithSlope.forEach(generator -> generator.getBus().removeSlopes()); + generatorsWithSlope.forEach(generator -> generator.getBus().removeGeneratorSlopes()); LOGGER.warn("Non supported: shared control on bus {} with {} generator(s) controlling voltage with slope. Slope set to 0 on all those generators", voltageControl.getControlledBus(), generatorsWithSlope.size()); } else if (!voltageControl.isVoltageControlLocal()) { - generatorsWithSlope.forEach(generator -> generator.getBus().removeSlopes()); + generatorsWithSlope.forEach(generator -> generator.getBus().removeGeneratorSlopes()); LOGGER.warn("Non supported: remote control on bus {} with {} generator(s) controlling voltage with slope", voltageControl.getControlledBus(), generatorsWithSlope.size()); } From df61d8e3d4db781e9cfe852844464f00a045a3e4 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Mon, 28 Jun 2021 16:39:08 +0200 Subject: [PATCH 41/42] Fix constructor. Signed-off-by: Anne Tilloy --- .../network/impl/LfStaticVarCompensatorImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java index 2e8f74d455..d9e26d8e0b 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfStaticVarCompensatorImpl.java @@ -62,9 +62,9 @@ public double getMaxQ(double p) { if (svc.getRegulationMode() == StaticVarCompensator.RegulationMode.VOLTAGE) { setVoltageControl(svc.getVoltageSetpoint(), svc.getRegulatingTerminal(), breakers, report); - } - if (voltagePerReactivePowerControl && svc.getExtension(VoltagePerReactivePowerControl.class) != null) { - this.slope = svc.getExtension(VoltagePerReactivePowerControl.class).getSlope() * PerUnit.SB / nominalV; + if (voltagePerReactivePowerControl && svc.getExtension(VoltagePerReactivePowerControl.class) != null) { + this.slope = svc.getExtension(VoltagePerReactivePowerControl.class).getSlope() * PerUnit.SB / nominalV; + } } } From 1e6b9531bdb3cbc88da3918e22b3d2c908c7f771 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Mon, 28 Jun 2021 16:46:08 +0200 Subject: [PATCH 42/42] Clean. Signed-off-by: Anne Tilloy --- .../com/powsybl/openloadflow/ac/equations/AcEquationSystem.java | 1 + .../ac/equations/AcEquationSystemCreationParameters.java | 1 - src/test/resources/logback-test.xml | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) 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 b01f3aed60..f825ea8116 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -459,6 +459,7 @@ public static EquationSystem create(LfNetwork network, VariableSet variableSet, Objects.requireNonNull(creationParameters); EquationSystem equationSystem = new EquationSystem(network, true); + createBusEquations(network, variableSet, creationParameters, equationSystem); createBranchEquations(network, variableSet, creationParameters, equationSystem); diff --git a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java index 3f6318d98d..50f969d7bf 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystemCreationParameters.java @@ -51,5 +51,4 @@ public boolean isForceA1Var() { public Set getBranchesWithCurrent() { return branchesWithCurrent; } - } diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 85148fd285..03f44ff80a 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -13,7 +13,7 @@ %-5p %d{HH:mm:ss.SSS} %-20C{1} | %m%n - +