From 8619fd0816358a9d43c42ead76f0bd67b2caa4cc Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 17 May 2024 11:01:58 +0200 Subject: [PATCH 01/30] Initial backport from investigation branch - before working on code coverage of new code Signed-off-by: VIDAL Didier (Externe) --- .../AbstractAcOuterLoopConfig.java | 9 +- .../ExplicitAcOuterLoopConfig.java | 6 + .../openloadflow/OpenLoadFlowParameters.java | 59 ++++++- ...actTransformerVoltageControlOuterLoop.java | 6 +- ...pleTransformerVoltageControlOuterLoop.java | 4 +- .../TransformerVoltageControlOuterLoop.java | 157 +++++++++++------- .../tap/GroupVoltageControlManager.java | 82 +++++++++ .../tap/TransformerRatioManager.java | 147 ++++++++++++++++ .../openloadflow/network/LfNetwork.java | 6 +- .../network/LfNetworkParameters.java | 4 + .../powsybl/openloadflow/network/PiModel.java | 4 + .../openloadflow/network/PiModelArray.java | 16 ++ .../openloadflow/network/SimplePiModel.java | 10 ++ .../sensi/AcSensitivityAnalysis.java | 4 +- .../OpenLoadFlowParametersTest.java | 2 +- .../OpenLoadFlowProviderTest.java | 4 +- src/test/resources/debug-parameters.json | 4 +- 17 files changed, 441 insertions(+), 83 deletions(-) create mode 100644 src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java create mode 100644 src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java diff --git a/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java b/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java index 5e537f7a7b..60aaa40a42 100644 --- a/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java +++ b/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java @@ -55,12 +55,15 @@ protected static Optional createMonitoringVoltageOuterLoop(OpenLoad return Optional.empty(); } - protected static Optional createTransformerVoltageControlOuterLoop(LoadFlowParameters parameters, OpenLoadFlowParameters.TransformerVoltageControlMode controlMode, + protected static Optional createTransformerVoltageControlOuterLoop(LoadFlowParameters parameters, + boolean isTransformerVoltageControlStable, + int transformerVoltageControlThtLimit, + OpenLoadFlowParameters.TransformerVoltageControlMode controlMode, int incrementalTransformerVoltageControlOuterLoopMaxTapShift) { if (parameters.isTransformerVoltageControlOn()) { AcOuterLoop outerLoop = switch (controlMode) { case WITH_GENERATOR_VOLTAGE_CONTROL -> new SimpleTransformerVoltageControlOuterLoop(); - case AFTER_GENERATOR_VOLTAGE_CONTROL -> new TransformerVoltageControlOuterLoop(); + case AFTER_GENERATOR_VOLTAGE_CONTROL -> new TransformerVoltageControlOuterLoop(isTransformerVoltageControlStable, transformerVoltageControlThtLimit); case INCREMENTAL_VOLTAGE_CONTROL -> new IncrementalTransformerVoltageControlOuterLoop(incrementalTransformerVoltageControlOuterLoopMaxTapShift); }; return Optional.of(outerLoop); @@ -70,6 +73,8 @@ protected static Optional createTransformerVoltageControlOuterLoop( protected static Optional createTransformerVoltageControlOuterLoop(LoadFlowParameters parameters, OpenLoadFlowParameters parametersExt) { return createTransformerVoltageControlOuterLoop(parameters, + parametersExt.isTransformerVoltageControlStable(), + parametersExt.getTransformerVoltageControlThtLimit(), parametersExt.getTransformerVoltageControlMode(), parametersExt.getIncrementalTransformerRatioTapControlOuterLoopMaxTapShift()); } diff --git a/src/main/java/com/powsybl/openloadflow/ExplicitAcOuterLoopConfig.java b/src/main/java/com/powsybl/openloadflow/ExplicitAcOuterLoopConfig.java index 5766f2c67a..b642bbada0 100644 --- a/src/main/java/com/powsybl/openloadflow/ExplicitAcOuterLoopConfig.java +++ b/src/main/java/com/powsybl/openloadflow/ExplicitAcOuterLoopConfig.java @@ -45,6 +45,8 @@ private static Optional createOuterLoop(String name, LoadFlowParame case IncrementalShuntVoltageControlOuterLoop.NAME -> createShuntVoltageControlOuterLoop(parameters, OpenLoadFlowParameters.ShuntVoltageControlMode.INCREMENTAL_VOLTAGE_CONTROL); case IncrementalTransformerVoltageControlOuterLoop.NAME -> createTransformerVoltageControlOuterLoop(parameters, + parametersExt.isTransformerVoltageControlStable(), + parametersExt.getTransformerVoltageControlThtLimit(), OpenLoadFlowParameters.TransformerVoltageControlMode.INCREMENTAL_VOLTAGE_CONTROL, parametersExt.getIncrementalTransformerRatioTapControlOuterLoopMaxTapShift()); case MonitoringVoltageOuterLoop.NAME -> createMonitoringVoltageOuterLoop(parametersExt); @@ -55,9 +57,13 @@ private static Optional createOuterLoop(String name, LoadFlowParame case ShuntVoltageControlOuterLoop.NAME -> createShuntVoltageControlOuterLoop(parameters, OpenLoadFlowParameters.ShuntVoltageControlMode.WITH_GENERATOR_VOLTAGE_CONTROL); case SimpleTransformerVoltageControlOuterLoop.NAME -> createTransformerVoltageControlOuterLoop(parameters, + parametersExt.isTransformerVoltageControlStable(), + parametersExt.getTransformerVoltageControlThtLimit(), OpenLoadFlowParameters.TransformerVoltageControlMode.WITH_GENERATOR_VOLTAGE_CONTROL, parametersExt.getIncrementalTransformerRatioTapControlOuterLoopMaxTapShift()); case TransformerVoltageControlOuterLoop.NAME -> createTransformerVoltageControlOuterLoop(parameters, + parametersExt.isTransformerVoltageControlStable(), + parametersExt.getTransformerVoltageControlThtLimit(), OpenLoadFlowParameters.TransformerVoltageControlMode.AFTER_GENERATOR_VOLTAGE_CONTROL, parametersExt.getIncrementalTransformerRatioTapControlOuterLoopMaxTapShift()); case AutomationSystemOuterLoop.NAME -> createAutomationSystemOuterLoop(parametersExt); diff --git a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java index 882c6f2c1f..2ad3ba22b6 100644 --- a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java +++ b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java @@ -248,6 +248,10 @@ public enum SlackDistributionFailureBehavior { public static final String VOLTAGE_TARGET_PRIORITIES_PARAM_NAME = "voltageTargetPriorities"; + public static final String TRANSFORMER_VOLTAGE_CONTROL_STABLE_PARAM_NAME = "transformerVoltageControlStable"; + + public static final String TRANSFORMER_VOLTAGE_CONTROL_THT_LIMIT_PARAM_NAME = "transformerVoltageControlTHTLimit"; + private static > List getEnumPossibleValues(Class enumClass) { return EnumSet.allOf(enumClass).stream().map(Enum::name).collect(Collectors.toList()); } @@ -317,7 +321,9 @@ private static > List getEnumPossibleValues(Class e new Parameter(NEWTON_KRYLOV_LINE_SEARCH_PARAM_NAME, ParameterType.BOOLEAN, "Newton Krylov line search activation", NewtonKrylovParameters.LINE_SEARCH_DEFAULT_VALUE), new Parameter(REFERENCE_BUS_SELECTION_MODE_PARAM_NAME, ParameterType.STRING, "Reference bus selection mode", ReferenceBusSelector.DEFAULT_MODE.name(), getEnumPossibleValues(ReferenceBusSelectionMode.class)), new Parameter(WRITE_REFERENCE_TERMINALS_PARAM_NAME, ParameterType.BOOLEAN, "Write Reference Terminals", WRITE_REFERENCE_TERMINALS_DEFAULT_VALUE), - new Parameter(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME, ParameterType.STRING_LIST, "Voltage target priorities for voltage controls", LfNetworkParameters.VOLTAGE_CONTROL_PRIORITIES_DEFAULT_VALUE, getEnumPossibleValues(VoltageControl.Type.class)) + new Parameter(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME, ParameterType.STRING_LIST, "Voltage target priorities for voltage controls", LfNetworkParameters.VOLTAGE_CONTROL_PRIORITIES_DEFAULT_VALUE, getEnumPossibleValues(VoltageControl.Type.class)), + new Parameter(TRANSFORMER_VOLTAGE_CONTROL_STABLE_PARAM_NAME, ParameterType.BOOLEAN, "Maintain initial tap position if possible", LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_STABLE_DEFAULT_VALUE), + new Parameter(TRANSFORMER_VOLTAGE_CONTROL_THT_LIMIT_PARAM_NAME, ParameterType.INTEGER, "Limit in KV below wich group stop controlling tension during tap computation. -1 - the default - for automatic determination.", LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_THT_LIMIT_DEFAULT_VALUE) ); public enum VoltageInitModeOverride { @@ -489,6 +495,10 @@ public enum ReactiveRangeCheckMode { private List voltageTargetPriorities = LfNetworkParameters.VOLTAGE_CONTROL_PRIORITIES_DEFAULT_VALUE; + private boolean transformerVoltageControlStable = LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_STABLE_DEFAULT_VALUE; + + private int transformerVoltageControlThtLimit = LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_THT_LIMIT_DEFAULT_VALUE; + public static double checkParameterValue(double parameterValue, boolean condition, String parameterName) { if (!condition) { throw new IllegalArgumentException("Invalid value for parameter " + parameterName + ": " + parameterValue); @@ -1153,6 +1163,35 @@ public OpenLoadFlowParameters setVoltageTargetPriorities(List voltageTar return this; } + public boolean isTransformerVoltageControlStable() { + return transformerVoltageControlStable; + } + + public OpenLoadFlowParameters setTransformerVoltageControlStable(boolean transformerVoltageControlStable) { + this.transformerVoltageControlStable = transformerVoltageControlStable; + return this; + } + + /** + * Returns in KV the tension below wich groups controlling tension are forced to PQ + * during tap computation. + * @return The HT limit or -1 if the limit is determined automatically + */ + public int getTransformerVoltageControlThtLimit() { + return transformerVoltageControlThtLimit; + } + + /** + * Sets the tension below wich groups controlling tension are forced to PQ + * during tap computation. + * @param transformerVoltageControlThtLimit the limit in KV or -1 the limit + * shoud be determined automatically. + */ + public OpenLoadFlowParameters setTransformerVoltageControlThtLimit(int transformerVoltageControlThtLimit) { + this.transformerVoltageControlThtLimit = transformerVoltageControlThtLimit; + return this; + } + public static OpenLoadFlowParameters load() { return load(PlatformConfig.defaultConfig()); } @@ -1226,7 +1265,9 @@ public static OpenLoadFlowParameters load(PlatformConfig platformConfig) { .setNewtonKrylovLineSearch(config.getBooleanProperty(NEWTON_KRYLOV_LINE_SEARCH_PARAM_NAME, NewtonKrylovParameters.LINE_SEARCH_DEFAULT_VALUE)) .setReferenceBusSelectionMode(config.getEnumProperty(REFERENCE_BUS_SELECTION_MODE_PARAM_NAME, ReferenceBusSelectionMode.class, ReferenceBusSelector.DEFAULT_MODE)) .setWriteReferenceTerminals(config.getBooleanProperty(WRITE_REFERENCE_TERMINALS_PARAM_NAME, WRITE_REFERENCE_TERMINALS_DEFAULT_VALUE)) - .setVoltageTargetPriorities(config.getStringListProperty(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME, LfNetworkParameters.VOLTAGE_CONTROL_PRIORITIES_DEFAULT_VALUE))); + .setVoltageTargetPriorities(config.getStringListProperty(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME, LfNetworkParameters.VOLTAGE_CONTROL_PRIORITIES_DEFAULT_VALUE)) + .setTransformerVoltageControlStable(config.getBooleanProperty(TRANSFORMER_VOLTAGE_CONTROL_STABLE_PARAM_NAME, LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_STABLE_DEFAULT_VALUE)) + .setTransformerVoltageControlThtLimit(config.getIntProperty(TRANSFORMER_VOLTAGE_CONTROL_THT_LIMIT_PARAM_NAME, LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_THT_LIMIT_DEFAULT_VALUE))); return parameters; } @@ -1375,6 +1416,10 @@ public OpenLoadFlowParameters update(Map properties) { .ifPresent(prop -> this.setWriteReferenceTerminals(Boolean.parseBoolean(prop))); Optional.ofNullable(properties.get(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME)) .ifPresent(prop -> this.setVoltageTargetPriorities(parseStringListProp(prop))); + Optional.ofNullable(properties.get(TRANSFORMER_VOLTAGE_CONTROL_STABLE_PARAM_NAME)) + .ifPresent(prop -> this.setTransformerVoltageControlStable(Boolean.parseBoolean(prop))); + Optional.ofNullable(properties.get(TRANSFORMER_VOLTAGE_CONTROL_THT_LIMIT_PARAM_NAME)) + .ifPresent(prop -> this.setTransformerVoltageControlThtLimit(Integer.parseInt(prop))); return this; } @@ -1445,6 +1490,8 @@ public Map toMap() { map.put(REFERENCE_BUS_SELECTION_MODE_PARAM_NAME, referenceBusSelectionMode); map.put(WRITE_REFERENCE_TERMINALS_PARAM_NAME, writeReferenceTerminals); map.put(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME, voltageTargetPriorities); + map.put(TRANSFORMER_VOLTAGE_CONTROL_STABLE_PARAM_NAME, transformerVoltageControlStable); + map.put(TRANSFORMER_VOLTAGE_CONTROL_THT_LIMIT_PARAM_NAME, transformerVoltageControlThtLimit); return map; } @@ -1819,7 +1866,9 @@ public static boolean equals(LoadFlowParameters parameters1, LoadFlowParameters extension1.getMaxRatioMismatch() == extension2.getMaxRatioMismatch() && extension1.getMaxSusceptanceMismatch() == extension2.getMaxSusceptanceMismatch() && extension1.getNewtonRaphsonStoppingCriteriaType() == extension2.getNewtonRaphsonStoppingCriteriaType() && - Objects.equals(extension1.getVoltageTargetPriorities(), extension2.getVoltageTargetPriorities()); + Objects.equals(extension1.getVoltageTargetPriorities(), extension2.getVoltageTargetPriorities()) && + extension1.isTransformerVoltageControlStable() == extension2.isTransformerVoltageControlStable() && + extension1.getTransformerVoltageControlThtLimit() == extension2.getTransformerVoltageControlThtLimit(); } public static LoadFlowParameters clone(LoadFlowParameters parameters) { @@ -1909,7 +1958,9 @@ public static LoadFlowParameters clone(LoadFlowParameters parameters) { .setMaxSusceptanceMismatch(extension.getMaxSusceptanceMismatch()) .setNewtonRaphsonStoppingCriteriaType(extension.getNewtonRaphsonStoppingCriteriaType()) .setReferenceBusSelectionMode(extension.getReferenceBusSelectionMode()) - .setVoltageTargetPriorities(extension.getVoltageTargetPriorities()); + .setVoltageTargetPriorities(extension.getVoltageTargetPriorities()) + .setTransformerVoltageControlStable(extension.isTransformerVoltageControlStable()) + .setTransformerVoltageControlThtLimit(extension.getTransformerVoltageControlThtLimit()); if (extension2 != null) { parameters2.addExtension(OpenLoadFlowParameters.class, extension2); diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AbstractTransformerVoltageControlOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AbstractTransformerVoltageControlOuterLoop.java index a521ad8691..a23df8655c 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AbstractTransformerVoltageControlOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AbstractTransformerVoltageControlOuterLoop.java @@ -7,9 +7,9 @@ */ package com.powsybl.openloadflow.ac.outerloop; -import com.powsybl.openloadflow.ac.AcOuterLoopContext; import com.powsybl.openloadflow.lf.outerloop.OuterLoopStatus; import com.powsybl.openloadflow.network.LfBranch; +import com.powsybl.openloadflow.network.LfNetwork; import com.powsybl.openloadflow.network.PiModel; import com.powsybl.openloadflow.network.TransformerVoltageControl; import com.powsybl.openloadflow.network.VoltageControl; @@ -32,9 +32,9 @@ public String getType() { return TYPE; } - protected OuterLoopStatus roundVoltageRatios(AcOuterLoopContext context) { + protected OuterLoopStatus roundVoltageRatios(LfNetwork network) { OuterLoopStatus status = OuterLoopStatus.STABLE; - for (LfBranch controllerBranch : context.getNetwork().getControllerElements(VoltageControl.Type.TRANSFORMER)) { + for (LfBranch controllerBranch : network.getControllerElements(VoltageControl.Type.TRANSFORMER)) { controllerBranch.setVoltageControlEnabled(false); // round the rho shift to the closest tap diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/SimpleTransformerVoltageControlOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/SimpleTransformerVoltageControlOuterLoop.java index 21b177089c..a3f2e3eea5 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/SimpleTransformerVoltageControlOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/SimpleTransformerVoltageControlOuterLoop.java @@ -33,14 +33,14 @@ public void initialize(AcOuterLoopContext context) { controllerBranch.setVoltageControlEnabled(true); } } - context.getNetwork().fixTransformerVoltageControls(); + context.getNetwork().fixTransformerVoltageControls(true); } @Override public OuterLoopResult check(AcOuterLoopContext context, ReportNode reportNode) { OuterLoopStatus status = OuterLoopStatus.STABLE; if (context.getIteration() == 0) { - status = roundVoltageRatios(context); + status = roundVoltageRatios(context.getNetwork()); } return new OuterLoopResult(this, status); } diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java index f4b149e19d..68674df5ac 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java @@ -9,15 +9,15 @@ import com.powsybl.commons.report.ReportNode; import com.powsybl.openloadflow.ac.AcOuterLoopContext; +import com.powsybl.openloadflow.ac.outerloop.tap.GroupVoltageControlManager; +import com.powsybl.openloadflow.ac.outerloop.tap.TransformerRatioManager; import com.powsybl.openloadflow.lf.outerloop.OuterLoopResult; import com.powsybl.openloadflow.lf.outerloop.OuterLoopStatus; import com.powsybl.openloadflow.network.LfBranch; import com.powsybl.openloadflow.network.LfBus; +import com.powsybl.openloadflow.network.LfNetwork; +import com.powsybl.openloadflow.network.TransformerVoltageControl; import com.powsybl.openloadflow.network.VoltageControl; -import org.apache.commons.lang3.mutable.MutableObject; - -import java.util.ArrayList; -import java.util.List; /** * @author Anne Tilloy {@literal } @@ -26,42 +26,41 @@ public class TransformerVoltageControlOuterLoop extends AbstractTransformerVolta public static final String NAME = "TransformerVoltageControl"; + private enum Step { + NOT_STARTED, + TUNING, + DISCRETIZED + } + private static final class ContextData { - private double maxControlledNominalVoltage = Double.MIN_VALUE; + private TransformerRatioManager transformerRatioManager; - private final List busesWithVoltageControlDisabled = new ArrayList<>(); + private GroupVoltageControlManager groupVoltageControlManager; - private double getMaxControlledNominalVoltage() { - return maxControlledNominalVoltage; - } + private Step step = Step.NOT_STARTED; - private void setMaxControlledNominalVoltage(double maxControlledNominalVoltage) { - this.maxControlledNominalVoltage = maxControlledNominalVoltage; - } + } - private List getBusesWithVoltageControlDisabled() { - return busesWithVoltageControlDisabled; - } + private final boolean stable; + private final int thtLimit; + + public TransformerVoltageControlOuterLoop(boolean stable, int thtLimit) { + this.stable = stable; + this.thtLimit = thtLimit; } @Override public void initialize(AcOuterLoopContext context) { - context.setData(new ContextData()); + ContextData contextData = new ContextData(); + context.setData(contextData); for (LfBranch controllerBranch : context.getNetwork().getControllerElements(VoltageControl.Type.TRANSFORMER)) { controllerBranch.setVoltageControlEnabled(false); } // All transformer voltage control are disabled for the first equation system resolution. - double[] maxControlledNominalVoltage = new double[1]; - maxControlledNominalVoltage[0] = Double.MIN_VALUE; - for (LfBus bus : context.getNetwork().getBuses()) { - if (!bus.isDisabled() && bus.isTransformerVoltageControlled()) { - maxControlledNominalVoltage[0] = Math.max(maxControlledNominalVoltage[0], bus.getNominalV()); - } - } - ((ContextData) context.getData()).setMaxControlledNominalVoltage(maxControlledNominalVoltage[0]); + contextData.groupVoltageControlManager = new GroupVoltageControlManager(context.getNetwork(), thtLimit); } @Override @@ -71,62 +70,92 @@ public String getName() { @Override public OuterLoopResult check(AcOuterLoopContext context, ReportNode reportNode) { - final MutableObject status = new MutableObject<>(OuterLoopStatus.STABLE); var contextData = (ContextData) context.getData(); - // At first outer loop iteration, the voltage control of generators that controlled at nominal voltage of - // the set controlledNominalVoltages are disabled. - // The transformer voltage controls are enabled. - if (context.getIteration() == 0) { - firstOuterLoop(context, contextData, status); - } - - // At second outer loop iteration, the transformers are rounded. The generator voltage controls that were - // disabled previously are enabled. - if (context.getIteration() == 1) { - secondOuterLoop(context, status, contextData); - } + return switch (contextData.step) { + case NOT_STARTED -> initStep(context.getNetwork(), contextData); + case TUNING -> tuningStep(context.getNetwork(), contextData); + case DISCRETIZED -> new OuterLoopResult(this, OuterLoopStatus.STABLE); + }; - return new OuterLoopResult(this, status.getValue()); } - private static void firstOuterLoop(AcOuterLoopContext context, ContextData contextData, MutableObject status) { - double maxControlledNominalVoltage = contextData.getMaxControlledNominalVoltage(); - for (LfBus bus : context.getNetwork().getControlledBuses(VoltageControl.Type.GENERATOR)) { - if (bus.getNominalV() <= maxControlledNominalVoltage) { - var voltageControl = bus.getGeneratorVoltageControl().orElseThrow(); - voltageControl.getMergedControllerElements().forEach(controllerBus -> { - if (controllerBus.isGeneratorVoltageControlEnabled()) { - controllerBus.setGenerationTargetQ(controllerBus.getQ().eval()); - controllerBus.setGeneratorVoltageControlEnabled(false); - contextData.getBusesWithVoltageControlDisabled().add(controllerBus); - } - }); - status.setValue(OuterLoopStatus.UNSTABLE); - } - } - for (LfBranch branch : context.getNetwork().getControllerElements(VoltageControl.Type.TRANSFORMER)) { - branch.getVoltageControl().ifPresent(voltageControl -> { + /** + * At first outer loop iteration, the voltage control of generators that controlled at nominal voltage of + * the set controlledNominalVoltages are disabled. + * The transformer voltage controls are enabled ant their continuous ratio is computed$ + * @return a stable status if all taps are already tuned for tension control, unstable otherwise + */ + private OuterLoopResult initStep(LfNetwork network, ContextData contextData) { + boolean needRun = false; + for (LfBranch branch : network.getControllerElements(VoltageControl.Type.TRANSFORMER)) { + if (branch.getVoltageControl().isPresent()) { + TransformerVoltageControl voltageControl = branch.getVoltageControl().orElseThrow(); double targetV = voltageControl.getTargetValue(); double v = voltageControl.getControlledBus().getV(); double diffV = targetV - v; double halfTargetDeadband = getHalfTargetDeadband(voltageControl); if (Math.abs(diffV) > halfTargetDeadband && branch.isConnectedAtBothSides()) { branch.setVoltageControlEnabled(true); - status.setValue(OuterLoopStatus.UNSTABLE); + needRun = true; } - }); + } } - context.getNetwork().fixTransformerVoltageControls(); + + contextData.transformerRatioManager = new TransformerRatioManager(network, stable); + + if (!needRun) { + contextData.step = Step.DISCRETIZED; + return new OuterLoopResult(this, OuterLoopStatus.STABLE); + } + contextData.groupVoltageControlManager.stopHTGroupTensionControl(network); + + // In stable mode, Group maintaining tension but in PQ mode are ignored + network.fixTransformerVoltageControls(!stable); + + contextData.step = Step.TUNING; + return new OuterLoopResult(this, OuterLoopStatus.UNSTABLE); } - private void secondOuterLoop(AcOuterLoopContext context, MutableObject status, ContextData contextData) { - status.setValue(roundVoltageRatios(context)); - for (LfBus controllerBus : contextData.getBusesWithVoltageControlDisabled()) { - controllerBus.setGenerationTargetQ(0); - controllerBus.setGeneratorVoltageControlEnabled(true); - status.setValue(OuterLoopStatus.UNSTABLE); + /** + * During tuning step, transformers with ratio outside of range are discretized. Iterate until all transformers + * with continuous ratio are within their operating range , discretize then then switch to DISCTERIZED state + */ + private OuterLoopResult tuningStep(LfNetwork network, ContextData contextData) { + boolean outOfBoundTap = false; + + for (LfBranch controllerBranch : network.getControllerElements(VoltageControl.Type.TRANSFORMER)) { + if (contextData.transformerRatioManager.freezeIfGroupAtBounds(controllerBranch)) { + outOfBoundTap = true; + } } + + if (!outOfBoundTap) { + // No out of bound tap - descretize + updateContinuousRatio(network, contextData); + + roundVoltageRatios(network); + contextData.groupVoltageControlManager.restartHTGroupTensionControl(); + + contextData.step = Step.DISCRETIZED; + } + // In any case the loop must run again + return new OuterLoopResult(this, OuterLoopStatus.UNSTABLE); } + + private void updateContinuousRatio(LfNetwork network, ContextData contextData) { + for (LfBus bus : network.getControlledBuses(VoltageControl.Type.TRANSFORMER)) { + bus.getTransformerVoltageControl() + .filter(voltageControl -> voltageControl.getMergeStatus() == VoltageControl.MergeStatus.MAIN) + .ifPresent(voltageControl -> { + System.out.println(bus.getId()); + voltageControl.getMergedControllerElements().stream() + .filter(b -> !b.isDisabled()) + .filter(LfBranch::isVoltageControlEnabled) + .forEach(b -> contextData.transformerRatioManager.updateContinuousRatio(b)); + }); + } + } + } diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java new file mode 100644 index 0000000000..22429a27e5 --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java @@ -0,0 +1,82 @@ +package com.powsybl.openloadflow.ac.outerloop.tap; + +import com.powsybl.openloadflow.network.LfBranch; +import com.powsybl.openloadflow.network.LfBus; +import com.powsybl.openloadflow.network.LfNetwork; +import com.powsybl.openloadflow.network.LfVscConverterStation; +import com.powsybl.openloadflow.network.VoltageControl; + +import java.util.ArrayList; +import java.util.List; + +public class GroupVoltageControlManager { + + private final double thtLimit; + private final List busesWithVoltageControlDisabled = new ArrayList<>(); + + public GroupVoltageControlManager(LfNetwork network, double thtLimit) { + double myThtLimit = thtLimit; + if (myThtLimit < 0) { + // Automatic mode + for (LfBus bus : network.getBuses()) { + if (!bus.isDisabled() && bus.isTransformerVoltageControlled()) { + myThtLimit = Math.max(thtLimit, bus.getNominalV()); + } + } + } + this.thtLimit = myThtLimit; + } + + public double getThtLimit() { + return thtLimit; + } + + /** + * Disables the voltage control of generators with nominal voltage below the tht limit + * @return true if at least one generator is disabled. False if the model is not modified + */ + public boolean stopHTGroupTensionControl(LfNetwork network) { + + boolean result = false; + + for (LfBus bus : network.getControlledBuses(VoltageControl.Type.GENERATOR)) { + if (bus.getNominalV() < thtLimit) { + var voltageControl = bus.getGeneratorVoltageControl().orElseThrow(); + for (LfBus controllerBus : voltageControl.getMergedControllerElements()) { + if (controllerBus.isGeneratorVoltageControlEnabled()) { + if (!isBusBehindTHTTransfo(controllerBus, thtLimit)) { + controllerBus.setGenerationTargetQ(controllerBus.getQ().eval()); + controllerBus.setGeneratorVoltageControlEnabled(false); + busesWithVoltageControlDisabled.add(controllerBus); + result = true; + } + } + } + } + } + return result; + } + + public void restartHTGroupTensionControl() { + for (LfBus controllerBus : busesWithVoltageControlDisabled) { + controllerBus.setGenerationTargetQ(0); + controllerBus.setGeneratorVoltageControlEnabled(true); + } + } + + private boolean isBusBehindTHTTransfo(LfBus bus, double thtLimit) { + if (bus.getBranches().size() != 1) { + return false; + } + LfBranch b = bus.getBranches().get(0); + if (!b.isConnectedAtBothSides()) { + return false; + } + // Always keep VSC stations + if (bus.getGenerators().stream().anyMatch(g -> g instanceof LfVscConverterStation)) { + return true; + } + + return Math.max(b.getBus1().getNominalV(), b.getBus2().getNominalV()) >= thtLimit; + } +} diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java new file mode 100644 index 0000000000..be959a2a9e --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java @@ -0,0 +1,147 @@ +package com.powsybl.openloadflow.ac.outerloop.tap; + +import com.powsybl.openloadflow.network.LfBranch; +import com.powsybl.openloadflow.network.LfBus; +import com.powsybl.openloadflow.network.LfNetwork; +import com.powsybl.openloadflow.network.PiModel; +import com.powsybl.openloadflow.network.VoltageControl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Didier Vidal {@literal } + */ +public class TransformerRatioManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(TransformerRatioManager.class); + + private final boolean stable; + + public record ParallelRatioInfo(double rMax, double rMin, double rIni) { + public ParallelRatioInfo(PiModel piModel) { + this(piModel.getMaxR1(), piModel.getMinR1(), piModel.getR1()); + } + + public ParallelRatioInfo(double rMax, double rMin, double coefA, double coefB, int count) { + this(rMax, rMin, (rMin * coefA + rMax * coefB) / count); + } + } + + public record TransfoRatioInfo(double rIni, ParallelRatioInfo groupeInfo) { + } + + private final Map transfoRatioInfoMap = new HashMap<>(); + + /** + * Initializes the ratio states. In particular rMax, rMin and rIni. + * If 'stable' is true then tMax, rMin and rIni are the average valus of the transformers in parallel + * otherwise the transformer individual values. + */ + public TransformerRatioManager(LfNetwork network, boolean stable) { + this.stable = stable; + for (LfBus bus : network.getControlledBuses(VoltageControl.Type.TRANSFORMER)) { + bus.getTransformerVoltageControl() + .filter(voltageControl -> voltageControl.getMergeStatus() == VoltageControl.MergeStatus.MAIN) + .ifPresent(voltageControl -> { + var controllerBranches = voltageControl.getMergedControllerElements().stream() + .filter(b -> !b.isDisabled()) + .filter(LfBranch::isVoltageControlEnabled) + .toList(); + if (!controllerBranches.isEmpty()) { // If transformers in parallel control tension + if (stable) { + // parallel info + double coefA = 0; + double coefB = 0; + for (LfBranch transfo : controllerBranches) { + PiModel piModel = transfo.getPiModel(); + double r1 = piModel.getR1(); + double r1Max = piModel.getMaxR1(); + double r1Min = piModel.getMinR1(); + if (r1Max != r1Min) { + coefA += (r1Max - r1) / (r1Max - r1Min); + coefB += (r1 - r1Min) / (r1Max - r1Min); + } else { + coefA += 1; + coefB += 1; + } + } + ParallelRatioInfo parallelRatioInfo = new ParallelRatioInfo( + controllerBranches.stream().mapToDouble(b -> b.getPiModel().getMaxR1()).average().orElseThrow(), + controllerBranches.stream().mapToDouble(b -> b.getPiModel().getMinR1()).average().orElseThrow(), + coefA, + coefB, + controllerBranches.size()); + controllerBranches.forEach(b -> transfoRatioInfoMap.put(b.getId(), new TransfoRatioInfo(b.getPiModel().getR1(), parallelRatioInfo))); + } else { + // individual info + controllerBranches.forEach(b -> transfoRatioInfoMap.put(b.getId(), + new TransfoRatioInfo(b.getPiModel().getR1(), new ParallelRatioInfo(b.getPiModel())))); + } + + } + }); + } + } + + public TransfoRatioInfo getInfo(LfBranch transformer) { + return transfoRatioInfoMap.get(transformer.getId()); + } + + /** + * If stable is true, for tranformers in parallel, try to keep the initial difference between individual ratio + * This algorithm maintains the individual tap positions if the tension is correct with initial settings. + * It can also be seen as an approximate simulation of transformers acting with independent automates. + * Assumes that all transformers in parallel have the same ratio (should be maintained by + * ACEquationSystemCreator.createR1DistributionEquations) + * If stable is false, the transformer is not modified and keeps its computed ratio. + * @return the updated transormer's ratio + */ + public double updateContinuousRatio(LfBranch transfo) { + if (stable) { + TransformerRatioManager.TransfoRatioInfo transfoRatioInfo = transfoRatioInfoMap.get(transfo.getId()); + double r1GroupMax = transfoRatioInfo.groupeInfo().rMax(); + double r1GroupMin = transfoRatioInfo.groupeInfo().rMin(); + double r1GroupIni = transfoRatioInfo.groupeInfo().rIni(); + double computedR = transfo.getPiModel().getR1(); // equations provide the same R for all branches + double r1Ini = transfoRatioInfo.rIni(); + double updatedR = computedR >= r1GroupIni ? + r1Ini + (computedR - r1GroupIni) * (transfo.getPiModel().getMaxR1() - r1Ini) / (r1GroupMax - r1GroupIni) + : + r1Ini - (r1GroupIni - computedR) * (r1Ini - transfo.getPiModel().getMinR1()) / (r1GroupIni - r1GroupMin); + transfo.getPiModel().setR1(updatedR); + return updatedR; + } else { + // Do Nothing - keep computed R1 + return transfo.getPiModel().getR1(); + } + } + + /** + * freezes the transformer to its limit if the ratio of a group of parallel transformers is above the max + * (or below the min) of the group + * If stable mode is false, considers the max of the individual transformer. + * @return true if the transformer has been frozen and false it voltage control remains disabled + */ + public boolean freezeIfGroupAtBounds(LfBranch transfo) { + if (transfo.isVoltageControlEnabled() && !transfo.isDisabled()) { + // round the rho shift to the closest tap + PiModel piModel = transfo.getPiModel(); + double r1 = piModel.getR1(); + TransformerRatioManager.TransfoRatioInfo transfoRatioInfo = getInfo(transfo); + double r1GroupMin = transfoRatioInfo.groupeInfo().rMin(); + double r1GroupMax = transfoRatioInfo.groupeInfo().rMax(); + if (r1 < r1GroupMin || r1 > r1GroupMax) { + LOGGER.info("Transformer " + transfo.getId() + " tap frozen"); + piModel.setR1(r1 > r1GroupMax ? r1GroupMax : r1GroupMin); + piModel.roundR1ToClosestTap(); + transfo.setVoltageControlEnabled(false); + return true; + } + } + return false; + } + +} diff --git a/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java b/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java index e41809eb26..6b9ee125e4 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java @@ -733,8 +733,9 @@ public Validity getValidity() { /** * Disable transformer voltage control when there is no generator controlling voltage on the connected component * that belong to the not controlled side of the transformer. + * @param includePQBus if true, generators with voltage control but currently excluded are accepted */ - public void fixTransformerVoltageControls() { + public void fixTransformerVoltageControls(boolean includePQBus) { List controllerBranches = new ArrayList<>(1); getConnectivity().startTemporaryChanges(); for (LfBranch branch : branches) { @@ -762,7 +763,8 @@ public void fixTransformerVoltageControls() { continue; } boolean noPvBusesInComponent = componentNoPVBusesMap.computeIfAbsent(getConnectivity().getComponentNumber(notControlledSide), - k -> getConnectivity().getConnectedComponent(notControlledSide).stream().noneMatch(LfBus::isGeneratorVoltageControlled)); + k -> getConnectivity().getConnectedComponent(notControlledSide).stream() + .noneMatch(b -> b.isGeneratorVoltageControlled() && (includePQBus ? true : b.isGeneratorVoltageControlEnabled()))); if (noPvBusesInComponent) { branch.setVoltageControlEnabled(false); LOGGER.trace("Transformer {} voltage control has been disabled because no PV buses on not controlled side connected component", diff --git a/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java b/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java index cdb1500147..ac1f4e8d10 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java @@ -64,6 +64,10 @@ public class LfNetworkParameters { public static final List VOLTAGE_CONTROL_PRIORITIES_DEFAULT_VALUE = VoltageControl.VOLTAGE_CONTROL_PRIORITIES; + public static final boolean TRANSFORMER_VOLTAGE_CONTROL_STABLE_DEFAULT_VALUE = false; + + public static final int TRANSFORMER_VOLTAGE_CONTROL_THT_LIMIT_DEFAULT_VALUE = -1; + private boolean generatorVoltageRemoteControl = true; private boolean minImpedance = false; diff --git a/src/main/java/com/powsybl/openloadflow/network/PiModel.java b/src/main/java/com/powsybl/openloadflow/network/PiModel.java index fda71a76e5..4d430f6d1b 100644 --- a/src/main/java/com/powsybl/openloadflow/network/PiModel.java +++ b/src/main/java/com/powsybl/openloadflow/network/PiModel.java @@ -44,6 +44,10 @@ public interface PiModel { double getR1(); + double getMinR1(); + + double getMaxR1(); + double getContinuousR1(); double getA1(); diff --git a/src/main/java/com/powsybl/openloadflow/network/PiModelArray.java b/src/main/java/com/powsybl/openloadflow/network/PiModelArray.java index 8dfffa517e..56b6ada3db 100644 --- a/src/main/java/com/powsybl/openloadflow/network/PiModelArray.java +++ b/src/main/java/com/powsybl/openloadflow/network/PiModelArray.java @@ -33,10 +33,16 @@ public class PiModelArray implements PiModel { private LfBranch branch; + private final double minR1; + + private final double maxR1; + public PiModelArray(List models, int lowTapPosition, int tapPosition) { this.models = Objects.requireNonNull(models); this.lowTapPosition = lowTapPosition; tapPositionIndex = tapPosition - lowTapPosition; + minR1 = this.models.stream().mapToDouble(PiModel::getMinR1).min().orElseThrow(); + maxR1 = this.models.stream().mapToDouble(PiModel::getMaxR1).max().orElseThrow(); } List getModels() { @@ -390,6 +396,16 @@ public PiModel setTapPosition(int tapPosition) { return this; } + @Override + public double getMinR1() { + return minR1; + } + + @Override + public double getMaxR1() { + return maxR1; + } + @Override public Range getTapPositionRange() { return Range.of(lowTapPosition, lowTapPosition + models.size() - 1); diff --git a/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java b/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java index 510481599d..9d4376a616 100644 --- a/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java +++ b/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java @@ -110,6 +110,16 @@ public double getR1() { return r1; } + @Override + public double getMinR1() { + return getR1(); + } + + @Override + public double getMaxR1() { + return getR1(); + } + @Override public double getContinuousR1() { return getR1(); diff --git a/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java index df909b6d7c..1e3d8dd456 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java @@ -125,7 +125,7 @@ private void calculatePostContingencySensitivityValues(List branch.setVoltageControlEnabled(true)); } - lfNetwork.fixTransformerVoltageControls(); + lfNetwork.fixTransformerVoltageControls(true); } if (factorGroups.hasMultiVariables() && (!lfContingency.getLostLoads().isEmpty() || !lfContingency.getLostGenerators().isEmpty())) { @@ -275,7 +275,7 @@ public void analyse(Network network, List contingencies, for (LfBranch branch : lfNetwork.getBranches()) { branch.getVoltageControl().ifPresent(vc -> branch.setVoltageControlEnabled(true)); } - lfNetwork.fixTransformerVoltageControls(); + lfNetwork.fixTransformerVoltageControls(true); } // we make the assumption that we ran a loadflow before, and thus this jacobian is the right one diff --git a/src/test/java/com/powsybl/openloadflow/OpenLoadFlowParametersTest.java b/src/test/java/com/powsybl/openloadflow/OpenLoadFlowParametersTest.java index e139c0a56c..6409d372b1 100644 --- a/src/test/java/com/powsybl/openloadflow/OpenLoadFlowParametersTest.java +++ b/src/test/java/com/powsybl/openloadflow/OpenLoadFlowParametersTest.java @@ -384,7 +384,7 @@ void testCloneParameters() { @Test void testToString() { OpenLoadFlowParameters parameters = new OpenLoadFlowParameters(); - assertEquals("OpenLoadFlowParameters(slackBusSelectionMode=MOST_MESHED, slackBusesIds=[], slackDistributionFailureBehavior=LEAVE_ON_SLACK_BUS, voltageRemoteControl=true, lowImpedanceBranchMode=REPLACE_BY_ZERO_IMPEDANCE_LINE, loadPowerFactorConstant=false, plausibleActivePowerLimit=5000.0, newtonRaphsonStoppingCriteriaType=UNIFORM_CRITERIA, slackBusPMaxMismatch=1.0, maxActivePowerMismatch=0.01, maxReactivePowerMismatch=0.01, maxVoltageMismatch=1.0E-4, maxAngleMismatch=1.0E-5, maxRatioMismatch=1.0E-5, maxSusceptanceMismatch=1.0E-4, voltagePerReactivePowerControl=false, generatorReactivePowerRemoteControl=false, transformerReactivePowerControl=false, maxNewtonRaphsonIterations=15, maxOuterLoopIterations=20, newtonRaphsonConvEpsPerEq=1.0E-4, voltageInitModeOverride=NONE, transformerVoltageControlMode=WITH_GENERATOR_VOLTAGE_CONTROL, shuntVoltageControlMode=WITH_GENERATOR_VOLTAGE_CONTROL, minPlausibleTargetVoltage=0.8, maxPlausibleTargetVoltage=1.2, minRealisticVoltage=0.5, maxRealisticVoltage=2.0, reactiveRangeCheckMode=MAX, lowImpedanceThreshold=1.0E-8, networkCacheEnabled=false, svcVoltageMonitoring=true, stateVectorScalingMode=NONE, maxSlackBusCount=1, debugDir=null, incrementalTransformerRatioTapControlOuterLoopMaxTapShift=3, secondaryVoltageControl=false, reactiveLimitsMaxPqPvSwitch=3, phaseShifterControlMode=CONTINUOUS_WITH_DISCRETISATION, alwaysUpdateNetwork=false, mostMeshedSlackBusSelectorMaxNominalVoltagePercentile=95.0, reportedFeatures=[], slackBusCountryFilter=[], actionableSwitchesIds=[], actionableTransformersIds=[], asymmetrical=false, minNominalVoltageTargetVoltageCheck=20.0, reactivePowerDispatchMode=Q_EQUAL_PROPORTION, outerLoopNames=null, useActiveLimits=true, disableVoltageControlOfGeneratorsOutsideActivePowerLimits=false, lineSearchStateVectorScalingMaxIteration=10, lineSearchStateVectorScalingStepFold=1.3333333333333333, maxVoltageChangeStateVectorScalingMaxDv=0.1, maxVoltageChangeStateVectorScalingMaxDphi=0.17453292519943295, linePerUnitMode=IMPEDANCE, useLoadModel=false, dcApproximationType=IGNORE_R, simulateAutomationSystems=false, acSolverType=NEWTON_RAPHSON, maxNewtonKrylovIterations=100, newtonKrylovLineSearch=false, referenceBusSelectionMode=FIRST_SLACK, writeReferenceTerminals=true, voltageTargetPriorities=[GENERATOR, TRANSFORMER, SHUNT])", + assertEquals("OpenLoadFlowParameters(slackBusSelectionMode=MOST_MESHED, slackBusesIds=[], slackDistributionFailureBehavior=LEAVE_ON_SLACK_BUS, voltageRemoteControl=true, lowImpedanceBranchMode=REPLACE_BY_ZERO_IMPEDANCE_LINE, loadPowerFactorConstant=false, plausibleActivePowerLimit=5000.0, newtonRaphsonStoppingCriteriaType=UNIFORM_CRITERIA, slackBusPMaxMismatch=1.0, maxActivePowerMismatch=0.01, maxReactivePowerMismatch=0.01, maxVoltageMismatch=1.0E-4, maxAngleMismatch=1.0E-5, maxRatioMismatch=1.0E-5, maxSusceptanceMismatch=1.0E-4, voltagePerReactivePowerControl=false, generatorReactivePowerRemoteControl=false, transformerReactivePowerControl=false, maxNewtonRaphsonIterations=15, maxOuterLoopIterations=20, newtonRaphsonConvEpsPerEq=1.0E-4, voltageInitModeOverride=NONE, transformerVoltageControlMode=WITH_GENERATOR_VOLTAGE_CONTROL, shuntVoltageControlMode=WITH_GENERATOR_VOLTAGE_CONTROL, minPlausibleTargetVoltage=0.8, maxPlausibleTargetVoltage=1.2, minRealisticVoltage=0.5, maxRealisticVoltage=2.0, reactiveRangeCheckMode=MAX, lowImpedanceThreshold=1.0E-8, networkCacheEnabled=false, svcVoltageMonitoring=true, stateVectorScalingMode=NONE, maxSlackBusCount=1, debugDir=null, incrementalTransformerRatioTapControlOuterLoopMaxTapShift=3, secondaryVoltageControl=false, reactiveLimitsMaxPqPvSwitch=3, phaseShifterControlMode=CONTINUOUS_WITH_DISCRETISATION, alwaysUpdateNetwork=false, mostMeshedSlackBusSelectorMaxNominalVoltagePercentile=95.0, reportedFeatures=[], slackBusCountryFilter=[], actionableSwitchesIds=[], actionableTransformersIds=[], asymmetrical=false, minNominalVoltageTargetVoltageCheck=20.0, reactivePowerDispatchMode=Q_EQUAL_PROPORTION, outerLoopNames=null, useActiveLimits=true, disableVoltageControlOfGeneratorsOutsideActivePowerLimits=false, lineSearchStateVectorScalingMaxIteration=10, lineSearchStateVectorScalingStepFold=1.3333333333333333, maxVoltageChangeStateVectorScalingMaxDv=0.1, maxVoltageChangeStateVectorScalingMaxDphi=0.17453292519943295, linePerUnitMode=IMPEDANCE, useLoadModel=false, dcApproximationType=IGNORE_R, simulateAutomationSystems=false, acSolverType=NEWTON_RAPHSON, maxNewtonKrylovIterations=100, newtonKrylovLineSearch=false, referenceBusSelectionMode=FIRST_SLACK, writeReferenceTerminals=true, voltageTargetPriorities=[GENERATOR, TRANSFORMER, SHUNT], transformerVoltageControlStable=false, transformerVoltageControlTHTLimit=-1)", parameters.toString()); } diff --git a/src/test/java/com/powsybl/openloadflow/OpenLoadFlowProviderTest.java b/src/test/java/com/powsybl/openloadflow/OpenLoadFlowProviderTest.java index caaa333e83..259ea63d11 100644 --- a/src/test/java/com/powsybl/openloadflow/OpenLoadFlowProviderTest.java +++ b/src/test/java/com/powsybl/openloadflow/OpenLoadFlowProviderTest.java @@ -87,7 +87,7 @@ void testGetExtendedVoltageInitializer() { @Test void specificParametersTest() { OpenLoadFlowProvider provider = new OpenLoadFlowProvider(); - assertEquals(65, provider.getSpecificParameters().size()); + assertEquals(67, provider.getSpecificParameters().size()); LoadFlowParameters parameters = new LoadFlowParameters(); provider.loadSpecificParameters(Collections.emptyMap()) @@ -110,7 +110,7 @@ void testCreateMapFromSpecificParameters() { OpenLoadFlowParameters parametersExt = new OpenLoadFlowParameters(); OpenLoadFlowProvider provider = new OpenLoadFlowProvider(); Map map = provider.createMapFromSpecificParameters(parametersExt); - assertEquals(65, map.size()); + assertEquals(67, map.size()); assertEquals(provider.getSpecificParameters().size(), map.size()); } diff --git a/src/test/resources/debug-parameters.json b/src/test/resources/debug-parameters.json index d10095b706..d9e08f7677 100644 --- a/src/test/resources/debug-parameters.json +++ b/src/test/resources/debug-parameters.json @@ -84,7 +84,9 @@ "newtonKrylovLineSearch" : false, "referenceBusSelectionMode" : "FIRST_SLACK", "writeReferenceTerminals" : true, - "voltageTargetPriorities" : [ "GENERATOR", "TRANSFORMER", "SHUNT" ] + "voltageTargetPriorities" : [ "GENERATOR", "TRANSFORMER", "SHUNT" ], + "transformerVoltageControlStable" : false, + "transformerVoltageControlThtLimit" : -1 } } }, From cbf33bbed51e1c34522d2db40d78e1b5de677bc3 Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 17 May 2024 15:40:52 +0200 Subject: [PATCH 02/30] add a test in stable mode Signed-off-by: VIDAL Didier (Externe) --- ...LoadFlowTransformerVoltageControlTest.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java index 2184802889..b3d5e351a3 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java @@ -185,6 +185,52 @@ void voltageControlT2wtTest5() { assertVoltageEquals(33.989, t2wt.getTerminal2().getBusView().getBus()); assertEquals(2, t2wt.getRatioTapChanger().getTapPosition()); assertEquals(2, t2wt2.getRatioTapChanger().getTapPosition()); + + // Now test in stable mode with AfterVoltageControl + // dealign transformers + t2wt.getRatioTapChanger() + .setTargetDeadband(0) + .setRegulating(true) + .setTapPosition(3) + .setRegulationTerminal(t2wt.getTerminal2()) + .setTargetV(34.0); + t2wt2.getRatioTapChanger() + .setTargetDeadband(0) + .setRegulating(true) + .setTapPosition(1) + .setRegulationTerminal(t2wt2.getTerminal2()) + .setTargetV(34.0); + LoadFlowParameters stableParams = parameters.copy(); + stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlStable(true); + stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlMode(OpenLoadFlowParameters.TransformerVoltageControlMode.AFTER_GENERATOR_VOLTAGE_CONTROL); + result = loadFlowRunner.run(network, stableParams); + assertTrue(result.isFullyConverged()); + assertVoltageEquals(134.267, bus2); + assertVoltageEquals(33.989, t2wt.getTerminal2().getBusView().getBus()); + assertEquals(3, t2wt.getRatioTapChanger().getTapPosition()); + assertEquals(1, t2wt2.getRatioTapChanger().getTapPosition()); + + // still stable mode but with movement needed + t2wt.getRatioTapChanger() + .setTargetDeadband(0) + .setRegulating(true) + .setTapPosition(3) + .setRegulationTerminal(t2wt.getTerminal2()) + .setTargetV(34.0); + t2wt2.getRatioTapChanger() + .setTargetDeadband(0) + .setRegulating(true) + .setTapPosition(0) + .setRegulationTerminal(t2wt2.getTerminal2()) + .setTargetV(34.0); + + result = loadFlowRunner.run(network, stableParams); + assertTrue(result.isFullyConverged()); + assertVoltageEquals(134.267, bus2); + assertVoltageEquals(33.989, t2wt.getTerminal2().getBusView().getBus()); + assertEquals(3, t2wt.getRatioTapChanger().getTapPosition()); + assertEquals(1, t2wt2.getRatioTapChanger().getTapPosition()); + } @Test From b4efbc09b7e0b5b481ec865b12d3ceb128dbe407 Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 17 May 2024 16:00:17 +0200 Subject: [PATCH 03/30] add a test for tht limit Signed-off-by: VIDAL Didier (Externe) --- ...LoadFlowTransformerVoltageControlTest.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java index b3d5e351a3..70b5fadb38 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java @@ -231,6 +231,51 @@ void voltageControlT2wtTest5() { assertEquals(3, t2wt.getRatioTapChanger().getTapPosition()); assertEquals(1, t2wt2.getRatioTapChanger().getTapPosition()); + // stable mode but transfo removed fromtuning because of tht limit + t2wt.getRatioTapChanger() + .setTargetDeadband(0) + .setRegulating(true) + .setTapPosition(3) + .setRegulationTerminal(t2wt.getTerminal2()) + .setTargetV(34.0); + t2wt2.getRatioTapChanger() + .setTargetDeadband(0) + .setRegulating(true) + .setTapPosition(0) + .setRegulationTerminal(t2wt2.getTerminal2()) + .setTargetV(34.0); + + stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlThtLimit(150); // Above G1 voltage level + result = loadFlowRunner.run(network, stableParams); + assertTrue(result.isFullyConverged()); + assertVoltageEquals(134.223, bus2); + assertVoltageEquals(32.228, t2wt.getTerminal2().getBusView().getBus()); // no voltage control + assertEquals(3, t2wt.getRatioTapChanger().getTapPosition()); + assertEquals(0, t2wt2.getRatioTapChanger().getTapPosition()); // No change expected + + + // generator now included in tht limit + t2wt.getRatioTapChanger() + .setTargetDeadband(0) + .setRegulating(true) + .setTapPosition(3) + .setRegulationTerminal(t2wt.getTerminal2()) + .setTargetV(34.0); + t2wt2.getRatioTapChanger() + .setTargetDeadband(0) + .setRegulating(true) + .setTapPosition(0) + .setRegulationTerminal(t2wt2.getTerminal2()) + .setTargetV(34.0); + + stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlThtLimit(90); // Below G1 voltage level + result = loadFlowRunner.run(network, stableParams); + assertTrue(result.isFullyConverged()); + assertVoltageEquals(134.267, bus2); + assertVoltageEquals(33.989, t2wt.getTerminal2().getBusView().getBus()); + assertEquals(3, t2wt.getRatioTapChanger().getTapPosition()); + assertEquals(1, t2wt2.getRatioTapChanger().getTapPosition()); + } @Test From 4d6e6a8a54b6ecf3a64ce5e4cc161d408f36e9bf Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 17 May 2024 16:19:28 +0200 Subject: [PATCH 04/30] remove a line to prevent checker style from striking Signed-off-by: VIDAL Didier (Externe) --- .../openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java index 70b5fadb38..9077494af9 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java @@ -253,7 +253,6 @@ void voltageControlT2wtTest5() { assertEquals(3, t2wt.getRatioTapChanger().getTapPosition()); assertEquals(0, t2wt2.getRatioTapChanger().getTapPosition()); // No change expected - // generator now included in tht limit t2wt.getRatioTapChanger() .setTargetDeadband(0) From 1b69e973305e6d7fccb217e387f9a39f2455e69f Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 17 May 2024 16:27:21 +0200 Subject: [PATCH 05/30] remove some sonar issues Signed-off-by: VIDAL Didier (Externe) --- .../TransformerVoltageControlOuterLoop.java | 1 - .../outerloop/tap/GroupVoltageControlManager.java | 14 ++++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java index 68674df5ac..4a127c4f8a 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java @@ -149,7 +149,6 @@ private void updateContinuousRatio(LfNetwork network, ContextData contextData) { bus.getTransformerVoltageControl() .filter(voltageControl -> voltageControl.getMergeStatus() == VoltageControl.MergeStatus.MAIN) .ifPresent(voltageControl -> { - System.out.println(bus.getId()); voltageControl.getMergedControllerElements().stream() .filter(b -> !b.isDisabled()) .filter(LfBranch::isVoltageControlEnabled) diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java index 22429a27e5..a8922772fe 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java @@ -43,13 +43,11 @@ public boolean stopHTGroupTensionControl(LfNetwork network) { if (bus.getNominalV() < thtLimit) { var voltageControl = bus.getGeneratorVoltageControl().orElseThrow(); for (LfBus controllerBus : voltageControl.getMergedControllerElements()) { - if (controllerBus.isGeneratorVoltageControlEnabled()) { - if (!isBusBehindTHTTransfo(controllerBus, thtLimit)) { - controllerBus.setGenerationTargetQ(controllerBus.getQ().eval()); - controllerBus.setGeneratorVoltageControlEnabled(false); - busesWithVoltageControlDisabled.add(controllerBus); - result = true; - } + if (controllerBus.isGeneratorVoltageControlEnabled() && !isBusBehindTHTTransfo(controllerBus, thtLimit)) { + controllerBus.setGenerationTargetQ(controllerBus.getQ().eval()); + controllerBus.setGeneratorVoltageControlEnabled(false); + busesWithVoltageControlDisabled.add(controllerBus); + result = true; } } } @@ -73,7 +71,7 @@ private boolean isBusBehindTHTTransfo(LfBus bus, double thtLimit) { return false; } // Always keep VSC stations - if (bus.getGenerators().stream().anyMatch(g -> g instanceof LfVscConverterStation)) { + if (bus.getGenerators().stream().anyMatch(LfVscConverterStation.class::isInstance)) { return true; } From c5ca6dcb38cc9ba7c1fdee0c9a012e8bacc37372 Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 17 May 2024 16:37:47 +0200 Subject: [PATCH 06/30] test outofbound tap Signed-off-by: VIDAL Didier (Externe) --- .../ac/AcLoadFlowTransformerVoltageControlTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java index 9077494af9..12503fda52 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java @@ -275,6 +275,18 @@ void voltageControlT2wtTest5() { assertEquals(3, t2wt.getRatioTapChanger().getTapPosition()); assertEquals(1, t2wt2.getRatioTapChanger().getTapPosition()); + // Move group to its limit + t2wt.getRatioTapChanger().setTargetV(26); + t2wt2.getRatioTapChanger().setTargetV(26); + + result = loadFlowRunner.run(network, stableParams); + assertTrue(result.isFullyConverged()); + assertVoltageEquals(134.283, bus2); + assertVoltageEquals(28.71, t2wt.getTerminal2().getBusView().getBus()); + assertEquals(0, t2wt.getRatioTapChanger().getTapPosition()); + assertEquals(0, t2wt2.getRatioTapChanger().getTapPosition()); + + } @Test From e72da3bd1216062a52afca72e6e6463af22ea7c6 Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 17 May 2024 16:41:16 +0200 Subject: [PATCH 07/30] another MAJOR problem to fix from style checker perspective. Signed-off-by: VIDAL Didier (Externe) --- .../openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java index 12503fda52..04eab211ec 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java @@ -286,7 +286,6 @@ void voltageControlT2wtTest5() { assertEquals(0, t2wt.getRatioTapChanger().getTapPosition()); assertEquals(0, t2wt2.getRatioTapChanger().getTapPosition()); - } @Test From 74064e72ea1538dc35ad2353013a127f01169667 Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 17 May 2024 17:10:09 +0200 Subject: [PATCH 08/30] troubleshoot test issue on server Signed-off-by: VIDAL Didier (Externe) --- .../ac/AcLoadFlowTransformerVoltageControlTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java index 04eab211ec..b43037797d 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java @@ -276,9 +276,11 @@ void voltageControlT2wtTest5() { assertEquals(1, t2wt2.getRatioTapChanger().getTapPosition()); // Move group to its limit + selectNetwork2(VoltageControlNetworkFactory.createNetworkWith2T2wt()); // recreate the network (strange bug in server built otherwise) t2wt.getRatioTapChanger().setTargetV(26); t2wt2.getRatioTapChanger().setTargetV(26); + stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlThtLimit(90); // Below G1 voltage level result = loadFlowRunner.run(network, stableParams); assertTrue(result.isFullyConverged()); assertVoltageEquals(134.283, bus2); From 26201d8243ba79b6082a57722b02b27da0903926 Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 17 May 2024 17:21:55 +0200 Subject: [PATCH 09/30] correct network copy to ensure voltage controlis active Signed-off-by: VIDAL Didier (Externe) --- .../AcLoadFlowTransformerVoltageControlTest.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java index b43037797d..3859c8cbf9 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java @@ -277,8 +277,18 @@ void voltageControlT2wtTest5() { // Move group to its limit selectNetwork2(VoltageControlNetworkFactory.createNetworkWith2T2wt()); // recreate the network (strange bug in server built otherwise) - t2wt.getRatioTapChanger().setTargetV(26); - t2wt2.getRatioTapChanger().setTargetV(26); + t2wt.getRatioTapChanger() + .setTargetDeadband(0) + .setRegulating(true) + .setTapPosition(3) + .setRegulationTerminal(t2wt.getTerminal2()) + .setTargetV(26.0); + t2wt2.getRatioTapChanger() + .setTargetDeadband(0) + .setRegulating(true) + .setTapPosition(0) + .setRegulationTerminal(t2wt2.getTerminal2()) + .setTargetV(26.0); stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlThtLimit(90); // Below G1 voltage level result = loadFlowRunner.run(network, stableParams); From ffe1725f7e3156750b74cae78562504d7d8f0fc5 Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 17 May 2024 17:33:04 +0200 Subject: [PATCH 10/30] isolate test ith different results locally and on server for troubleshooting Signed-off-by: VIDAL Didier (Externe) --- .../ac/AcLoadFlowTransformerVoltageControlTest.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java index 3859c8cbf9..1503ed5b35 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java @@ -275,6 +275,15 @@ void voltageControlT2wtTest5() { assertEquals(3, t2wt.getRatioTapChanger().getTapPosition()); assertEquals(1, t2wt2.getRatioTapChanger().getTapPosition()); + } + + @Test + void voltageControlT2wtTestRationAtLimit() { + LoadFlowParameters stableParams = parameters.copy(); + stableParams.setTransformerVoltageControlOn(true); + stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlStable(true); + stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlMode(OpenLoadFlowParameters.TransformerVoltageControlMode.AFTER_GENERATOR_VOLTAGE_CONTROL); + // Move group to its limit selectNetwork2(VoltageControlNetworkFactory.createNetworkWith2T2wt()); // recreate the network (strange bug in server built otherwise) t2wt.getRatioTapChanger() @@ -290,14 +299,12 @@ void voltageControlT2wtTest5() { .setRegulationTerminal(t2wt2.getTerminal2()) .setTargetV(26.0); - stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlThtLimit(90); // Below G1 voltage level - result = loadFlowRunner.run(network, stableParams); + LoadFlowResult result = loadFlowRunner.run(network, stableParams); assertTrue(result.isFullyConverged()); assertVoltageEquals(134.283, bus2); assertVoltageEquals(28.71, t2wt.getTerminal2().getBusView().getBus()); assertEquals(0, t2wt.getRatioTapChanger().getTapPosition()); assertEquals(0, t2wt2.getRatioTapChanger().getTapPosition()); - } @Test From e2d22de190bc215663b7f205788398f4607f6742 Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 17 May 2024 17:39:14 +0200 Subject: [PATCH 11/30] add a paranoid trace to troubleshoot build issue Signed-off-by: VIDAL Didier (Externe) --- .../openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java index 1503ed5b35..52ff29df78 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java @@ -300,6 +300,7 @@ void voltageControlT2wtTestRationAtLimit() { .setTargetV(26.0); LoadFlowResult result = loadFlowRunner.run(network, stableParams); + System.out.println("This fails on the git build !"); // A trace to identify in the logs assertTrue(result.isFullyConverged()); assertVoltageEquals(134.283, bus2); assertVoltageEquals(28.71, t2wt.getTerminal2().getBusView().getBus()); From 90fae0d56589cff5fd73c4820ab32eb2ce7eba82 Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 17 May 2024 17:54:26 +0200 Subject: [PATCH 12/30] black magic discovered ? Signed-off-by: VIDAL Didier (Externe) --- .../ac/AcLoadFlowTransformerVoltageControlTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java index 52ff29df78..da978150a5 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java @@ -283,6 +283,7 @@ void voltageControlT2wtTestRationAtLimit() { stableParams.setTransformerVoltageControlOn(true); stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlStable(true); stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlMode(OpenLoadFlowParameters.TransformerVoltageControlMode.AFTER_GENERATOR_VOLTAGE_CONTROL); + stableParams.getExtension(OpenLoadFlowParameters.class).setMinRealisticVoltage(0.5); // please, code not merged yet, do not remove transfomers from voltage control // Move group to its limit selectNetwork2(VoltageControlNetworkFactory.createNetworkWith2T2wt()); // recreate the network (strange bug in server built otherwise) @@ -300,7 +301,6 @@ void voltageControlT2wtTestRationAtLimit() { .setTargetV(26.0); LoadFlowResult result = loadFlowRunner.run(network, stableParams); - System.out.println("This fails on the git build !"); // A trace to identify in the logs assertTrue(result.isFullyConverged()); assertVoltageEquals(134.283, bus2); assertVoltageEquals(28.71, t2wt.getTerminal2().getBusView().getBus()); From 40502c1266c15a4b8469945c6f2ee36e32fbcbe4 Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 17 May 2024 18:02:16 +0200 Subject: [PATCH 13/30] restore paranoic trace Signed-off-by: VIDAL Didier (Externe) --- .../openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java index da978150a5..c962903b9e 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java @@ -300,6 +300,7 @@ void voltageControlT2wtTestRationAtLimit() { .setRegulationTerminal(t2wt2.getTerminal2()) .setTargetV(26.0); + System.out.println("build on server fails here"); LoadFlowResult result = loadFlowRunner.run(network, stableParams); assertTrue(result.isFullyConverged()); assertVoltageEquals(134.283, bus2); From 26fe4071fae8c6c526c5f4e34d8aa3dbdaf9eba8 Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 17 May 2024 18:12:13 +0200 Subject: [PATCH 14/30] last try this week Signed-off-by: VIDAL Didier (Externe) --- .../ac/AcLoadFlowTransformerVoltageControlTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java index c962903b9e..5ff6e34a5b 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java @@ -283,7 +283,7 @@ void voltageControlT2wtTestRationAtLimit() { stableParams.setTransformerVoltageControlOn(true); stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlStable(true); stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlMode(OpenLoadFlowParameters.TransformerVoltageControlMode.AFTER_GENERATOR_VOLTAGE_CONTROL); - stableParams.getExtension(OpenLoadFlowParameters.class).setMinRealisticVoltage(0.5); // please, code not merged yet, do not remove transfomers from voltage control + stableParams.getExtension(OpenLoadFlowParameters.class).setMinPlausibleTargetVoltage(0.5); // please, code not merged yet, do not remove transfomers from voltage control // Move group to its limit selectNetwork2(VoltageControlNetworkFactory.createNetworkWith2T2wt()); // recreate the network (strange bug in server built otherwise) From cff1ea89b54f5770571a2fd1103f874ac264672e Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 31 May 2024 16:30:18 +0200 Subject: [PATCH 15/30] Add header and author on new files Signed-off-by: VIDAL Didier (Externe) --- .../ac/outerloop/tap/GroupVoltageControlManager.java | 10 ++++++++++ .../ac/outerloop/tap/TransformerRatioManager.java | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java index a8922772fe..999e9a7427 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.ac.outerloop.tap; import com.powsybl.openloadflow.network.LfBranch; @@ -9,6 +16,9 @@ import java.util.ArrayList; import java.util.List; +/** + * @author Didier Vidal {@literal } + */ public class GroupVoltageControlManager { private final double thtLimit; diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java index be959a2a9e..baee202583 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ package com.powsybl.openloadflow.ac.outerloop.tap; import com.powsybl.openloadflow.network.LfBranch; From 350a48c8e2ca5f1e0bec1d5c6ebd024cf3c323b2 Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Fri, 31 May 2024 17:30:38 +0200 Subject: [PATCH 16/30] Remove a THT that escaped previous cleaning Signed-off-by: VIDAL Didier (Externe) --- .../com/powsybl/openloadflow/network/LfNetworkParameters.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java b/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java index ac1f4e8d10..2ebcffd034 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java @@ -66,8 +66,6 @@ public class LfNetworkParameters { public static final boolean TRANSFORMER_VOLTAGE_CONTROL_STABLE_DEFAULT_VALUE = false; - public static final int TRANSFORMER_VOLTAGE_CONTROL_THT_LIMIT_DEFAULT_VALUE = -1; - private boolean generatorVoltageRemoteControl = true; private boolean minImpedance = false; From 217445b35aac3a734bccdec6d62dac4d48ab8ec0 Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Tue, 11 Jun 2024 17:52:23 +0200 Subject: [PATCH 17/30] some renaming after review of merged PR Signed-off-by: VIDAL Didier (Externe) --- .../AbstractAcOuterLoopConfig.java | 6 +-- .../ExplicitAcOuterLoopConfig.java | 6 +-- .../openloadflow/OpenLoadFlowParameters.java | 26 +++++------ .../TransformerVoltageControlOuterLoop.java | 44 +++++++++---------- ...va => GeneratorVoltageControlManager.java} | 4 +- .../tap/TransformerRatioManager.java | 12 ++--- .../network/LfNetworkParameters.java | 2 +- .../OpenLoadFlowParametersTest.java | 2 +- ...LoadFlowTransformerVoltageControlTest.java | 4 +- src/test/resources/debug-parameters.json | 2 +- 10 files changed, 54 insertions(+), 54 deletions(-) rename src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/{GroupVoltageControlManager.java => GeneratorVoltageControlManager.java} (97%) diff --git a/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java b/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java index 4e75648505..83b2779f07 100644 --- a/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java +++ b/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java @@ -56,14 +56,14 @@ protected static Optional createMonitoringVoltageOuterLoop(OpenLoad } protected static Optional createTransformerVoltageControlOuterLoop(LoadFlowParameters parameters, - boolean isTransformerVoltageControlStable, + boolean useInitialTapePosition, OpenLoadFlowParameters.TransformerVoltageControlMode controlMode, int incrementalTransformerVoltageControlOuterLoopMaxTapShift, double generatorVoltageControlMinNominalVoltage) { if (parameters.isTransformerVoltageControlOn()) { AcOuterLoop outerLoop = switch (controlMode) { case WITH_GENERATOR_VOLTAGE_CONTROL -> new SimpleTransformerVoltageControlOuterLoop(); - case AFTER_GENERATOR_VOLTAGE_CONTROL -> new TransformerVoltageControlOuterLoop(isTransformerVoltageControlStable, generatorVoltageControlMinNominalVoltage); + case AFTER_GENERATOR_VOLTAGE_CONTROL -> new TransformerVoltageControlOuterLoop(useInitialTapePosition, generatorVoltageControlMinNominalVoltage); case INCREMENTAL_VOLTAGE_CONTROL -> new IncrementalTransformerVoltageControlOuterLoop(incrementalTransformerVoltageControlOuterLoopMaxTapShift); }; return Optional.of(outerLoop); @@ -73,7 +73,7 @@ protected static Optional createTransformerVoltageControlOuterLoop( protected static Optional createTransformerVoltageControlOuterLoop(LoadFlowParameters parameters, OpenLoadFlowParameters parametersExt) { return createTransformerVoltageControlOuterLoop(parameters, - parametersExt.isTransformerVoltageControlStable(), + parametersExt.isUseInitialTapPosition(), parametersExt.getTransformerVoltageControlMode(), parametersExt.getIncrementalTransformerRatioTapControlOuterLoopMaxTapShift(), parametersExt.getGeneratorVoltageControlMinNominalVoltage()); diff --git a/src/main/java/com/powsybl/openloadflow/ExplicitAcOuterLoopConfig.java b/src/main/java/com/powsybl/openloadflow/ExplicitAcOuterLoopConfig.java index 1a37edf4c1..9462660779 100644 --- a/src/main/java/com/powsybl/openloadflow/ExplicitAcOuterLoopConfig.java +++ b/src/main/java/com/powsybl/openloadflow/ExplicitAcOuterLoopConfig.java @@ -45,7 +45,7 @@ private static Optional createOuterLoop(String name, LoadFlowParame case IncrementalShuntVoltageControlOuterLoop.NAME -> createShuntVoltageControlOuterLoop(parameters, OpenLoadFlowParameters.ShuntVoltageControlMode.INCREMENTAL_VOLTAGE_CONTROL); case IncrementalTransformerVoltageControlOuterLoop.NAME -> createTransformerVoltageControlOuterLoop(parameters, - parametersExt.isTransformerVoltageControlStable(), + parametersExt.isUseInitialTapPosition(), OpenLoadFlowParameters.TransformerVoltageControlMode.INCREMENTAL_VOLTAGE_CONTROL, parametersExt.getIncrementalTransformerRatioTapControlOuterLoopMaxTapShift(), parametersExt.getGeneratorVoltageControlMinNominalVoltage()); @@ -57,12 +57,12 @@ private static Optional createOuterLoop(String name, LoadFlowParame case ShuntVoltageControlOuterLoop.NAME -> createShuntVoltageControlOuterLoop(parameters, OpenLoadFlowParameters.ShuntVoltageControlMode.WITH_GENERATOR_VOLTAGE_CONTROL); case SimpleTransformerVoltageControlOuterLoop.NAME -> createTransformerVoltageControlOuterLoop(parameters, - parametersExt.isTransformerVoltageControlStable(), + parametersExt.isUseInitialTapPosition(), OpenLoadFlowParameters.TransformerVoltageControlMode.WITH_GENERATOR_VOLTAGE_CONTROL, parametersExt.getIncrementalTransformerRatioTapControlOuterLoopMaxTapShift(), parametersExt.getGeneratorVoltageControlMinNominalVoltage()); case TransformerVoltageControlOuterLoop.NAME -> createTransformerVoltageControlOuterLoop(parameters, - parametersExt.isTransformerVoltageControlStable(), + parametersExt.isUseInitialTapPosition(), OpenLoadFlowParameters.TransformerVoltageControlMode.AFTER_GENERATOR_VOLTAGE_CONTROL, parametersExt.getIncrementalTransformerRatioTapControlOuterLoopMaxTapShift(), parametersExt.getGeneratorVoltageControlMinNominalVoltage()); diff --git a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java index 389ad55180..48a4e74c20 100644 --- a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java +++ b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java @@ -250,7 +250,7 @@ public enum SlackDistributionFailureBehavior { public static final String VOLTAGE_TARGET_PRIORITIES_PARAM_NAME = "voltageTargetPriorities"; - public static final String TRANSFORMER_VOLTAGE_CONTROL_STABLE_PARAM_NAME = "transformerVoltageControlStable"; + public static final String TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_PARAM_NAME = "transformerVoltageControlUseInitialTapPosition"; public static final String GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_PARAM_NAME = "generatorVoltageControlMinNominalVoltage"; @@ -324,7 +324,7 @@ private static > List getEnumPossibleValues(Class e new Parameter(REFERENCE_BUS_SELECTION_MODE_PARAM_NAME, ParameterType.STRING, "Reference bus selection mode", ReferenceBusSelector.DEFAULT_MODE.name(), getEnumPossibleValues(ReferenceBusSelectionMode.class)), new Parameter(WRITE_REFERENCE_TERMINALS_PARAM_NAME, ParameterType.BOOLEAN, "Write Reference Terminals", WRITE_REFERENCE_TERMINALS_DEFAULT_VALUE), new Parameter(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME, ParameterType.STRING_LIST, "Voltage target priorities for voltage controls", LfNetworkParameters.VOLTAGE_CONTROL_PRIORITIES_DEFAULT_VALUE, getEnumPossibleValues(VoltageControl.Type.class)), - new Parameter(TRANSFORMER_VOLTAGE_CONTROL_STABLE_PARAM_NAME, ParameterType.BOOLEAN, "Maintain initial tap position if possible", LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_STABLE_DEFAULT_VALUE), + new Parameter(TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_PARAM_NAME, ParameterType.BOOLEAN, "Maintain initial tap position if possible", LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_DEFAULT_VALUE), new Parameter(GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_PARAM_NAME, ParameterType.DOUBLE, "Nominal voltage under which generator voltage controls are disabled during transformer voltage control outer loop of mode AFTER_GENERATOR_VOLTAGE_CONTROL, < 0 means automatic detection", OpenLoadFlowParameters.GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_DEFAULT_VALUE) ); @@ -497,7 +497,7 @@ public enum ReactiveRangeCheckMode { private List voltageTargetPriorities = LfNetworkParameters.VOLTAGE_CONTROL_PRIORITIES_DEFAULT_VALUE; - private boolean transformerVoltageControlStable = LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_STABLE_DEFAULT_VALUE; + private boolean useInitialTapPosition = LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_DEFAULT_VALUE; private double generatorVoltageControlMinNominalVoltage = GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_DEFAULT_VALUE; @@ -1165,12 +1165,12 @@ public OpenLoadFlowParameters setVoltageTargetPriorities(List voltageTar return this; } - public boolean isTransformerVoltageControlStable() { - return transformerVoltageControlStable; + public boolean isUseInitialTapPosition() { + return useInitialTapPosition; } - public OpenLoadFlowParameters setTransformerVoltageControlStable(boolean transformerVoltageControlStable) { - this.transformerVoltageControlStable = transformerVoltageControlStable; + public OpenLoadFlowParameters setUseInitialTapPosition(boolean useInitialTapPosition) { + this.useInitialTapPosition = useInitialTapPosition; return this; } @@ -1262,7 +1262,7 @@ public static OpenLoadFlowParameters load(PlatformConfig platformConfig) { .setReferenceBusSelectionMode(config.getEnumProperty(REFERENCE_BUS_SELECTION_MODE_PARAM_NAME, ReferenceBusSelectionMode.class, ReferenceBusSelector.DEFAULT_MODE)) .setWriteReferenceTerminals(config.getBooleanProperty(WRITE_REFERENCE_TERMINALS_PARAM_NAME, WRITE_REFERENCE_TERMINALS_DEFAULT_VALUE)) .setVoltageTargetPriorities(config.getStringListProperty(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME, LfNetworkParameters.VOLTAGE_CONTROL_PRIORITIES_DEFAULT_VALUE)) - .setTransformerVoltageControlStable(config.getBooleanProperty(TRANSFORMER_VOLTAGE_CONTROL_STABLE_PARAM_NAME, LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_STABLE_DEFAULT_VALUE)) + .setUseInitialTapPosition(config.getBooleanProperty(TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_PARAM_NAME, LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_DEFAULT_VALUE)) .setGeneratorVoltageControlMinNominalVoltage(config.getDoubleProperty(GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_PARAM_NAME, GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_DEFAULT_VALUE))); return parameters; } @@ -1412,8 +1412,8 @@ public OpenLoadFlowParameters update(Map properties) { .ifPresent(prop -> this.setWriteReferenceTerminals(Boolean.parseBoolean(prop))); Optional.ofNullable(properties.get(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME)) .ifPresent(prop -> this.setVoltageTargetPriorities(parseStringListProp(prop))); - Optional.ofNullable(properties.get(TRANSFORMER_VOLTAGE_CONTROL_STABLE_PARAM_NAME)) - .ifPresent(prop -> this.setTransformerVoltageControlStable(Boolean.parseBoolean(prop))); + Optional.ofNullable(properties.get(TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_PARAM_NAME)) + .ifPresent(prop -> this.setUseInitialTapPosition(Boolean.parseBoolean(prop))); Optional.ofNullable(properties.get(GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_PARAM_NAME)) .ifPresent(prop -> this.setGeneratorVoltageControlMinNominalVoltage(Double.parseDouble(prop))); return this; @@ -1486,7 +1486,7 @@ public Map toMap() { map.put(REFERENCE_BUS_SELECTION_MODE_PARAM_NAME, referenceBusSelectionMode); map.put(WRITE_REFERENCE_TERMINALS_PARAM_NAME, writeReferenceTerminals); map.put(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME, voltageTargetPriorities); - map.put(TRANSFORMER_VOLTAGE_CONTROL_STABLE_PARAM_NAME, transformerVoltageControlStable); + map.put(TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_PARAM_NAME, useInitialTapPosition); map.put(GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_PARAM_NAME, generatorVoltageControlMinNominalVoltage); return map; } @@ -1863,7 +1863,7 @@ public static boolean equals(LoadFlowParameters parameters1, LoadFlowParameters extension1.getMaxSusceptanceMismatch() == extension2.getMaxSusceptanceMismatch() && extension1.getNewtonRaphsonStoppingCriteriaType() == extension2.getNewtonRaphsonStoppingCriteriaType() && Objects.equals(extension1.getVoltageTargetPriorities(), extension2.getVoltageTargetPriorities()) && - extension1.isTransformerVoltageControlStable() == extension2.isTransformerVoltageControlStable() && + extension1.isUseInitialTapPosition() == extension2.isUseInitialTapPosition() && extension1.getGeneratorVoltageControlMinNominalVoltage() == extension2.getGeneratorVoltageControlMinNominalVoltage(); } @@ -1955,7 +1955,7 @@ public static LoadFlowParameters clone(LoadFlowParameters parameters) { .setNewtonRaphsonStoppingCriteriaType(extension.getNewtonRaphsonStoppingCriteriaType()) .setReferenceBusSelectionMode(extension.getReferenceBusSelectionMode()) .setVoltageTargetPriorities(extension.getVoltageTargetPriorities()) - .setTransformerVoltageControlStable(extension.isTransformerVoltageControlStable()) + .setUseInitialTapPosition(extension.isUseInitialTapPosition()) .setGeneratorVoltageControlMinNominalVoltage(extension.getGeneratorVoltageControlMinNominalVoltage()); if (extension2 != null) { diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java index 8e884d84aa..11d0b61a10 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java @@ -9,7 +9,7 @@ import com.powsybl.commons.report.ReportNode; import com.powsybl.openloadflow.ac.AcOuterLoopContext; -import com.powsybl.openloadflow.ac.outerloop.tap.GroupVoltageControlManager; +import com.powsybl.openloadflow.ac.outerloop.tap.GeneratorVoltageControlManager; import com.powsybl.openloadflow.ac.outerloop.tap.TransformerRatioManager; import com.powsybl.openloadflow.lf.outerloop.OuterLoopResult; import com.powsybl.openloadflow.lf.outerloop.OuterLoopStatus; @@ -27,9 +27,9 @@ public class TransformerVoltageControlOuterLoop extends AbstractTransformerVolta public static final String NAME = "TransformerVoltageControl"; private enum Step { - NOT_STARTED, - TUNING, - DISCRETIZED + INITIAL, + CONTROL, + COMPLETE } private final double maxControlledNominalVoltageOverride; @@ -38,16 +38,16 @@ private static final class ContextData { private TransformerRatioManager transformerRatioManager; - private GroupVoltageControlManager groupVoltageControlManager; + private GeneratorVoltageControlManager generatorVoltageControlManager; - private Step step = Step.NOT_STARTED; + private Step step = Step.INITIAL; } - private final boolean stable; + private final boolean useInitialTapePosition; - public TransformerVoltageControlOuterLoop(boolean stable, double maxControlledNominalVoltageOverride) { - this.stable = stable; + public TransformerVoltageControlOuterLoop(boolean useInitialTapePosition, double maxControlledNominalVoltageOverride) { + this.useInitialTapePosition = useInitialTapePosition; this.maxControlledNominalVoltageOverride = maxControlledNominalVoltageOverride; } @@ -61,7 +61,7 @@ public void initialize(AcOuterLoopContext context) { } // All transformer voltage control are disabled for the first equation system resolution. - contextData.groupVoltageControlManager = new GroupVoltageControlManager(context.getNetwork(), maxControlledNominalVoltageOverride); + contextData.generatorVoltageControlManager = new GeneratorVoltageControlManager(context.getNetwork(), maxControlledNominalVoltageOverride); } @Override @@ -75,9 +75,9 @@ public OuterLoopResult check(AcOuterLoopContext context, ReportNode reportNode) var contextData = (ContextData) context.getData(); return switch (contextData.step) { - case NOT_STARTED -> initStep(context.getNetwork(), contextData); - case TUNING -> tuningStep(context.getNetwork(), contextData); - case DISCRETIZED -> new OuterLoopResult(this, OuterLoopStatus.STABLE); + case INITIAL -> initStep(context.getNetwork(), contextData); + case CONTROL -> controlStep(context.getNetwork(), contextData); + case COMPLETE -> new OuterLoopResult(this, OuterLoopStatus.STABLE); }; } @@ -104,26 +104,26 @@ private OuterLoopResult initStep(LfNetwork network, ContextData contextData) { } } - contextData.transformerRatioManager = new TransformerRatioManager(network, stable); + contextData.transformerRatioManager = new TransformerRatioManager(network, useInitialTapePosition); if (!needRun) { - contextData.step = Step.DISCRETIZED; + contextData.step = Step.COMPLETE; return new OuterLoopResult(this, OuterLoopStatus.STABLE); } - contextData.groupVoltageControlManager.stopTensionControlBelowLimit(network); + contextData.generatorVoltageControlManager.stopTensionControlBelowLimit(network); // In stable mode, Group maintaining tension but in PQ mode are ignored network.fixTransformerVoltageControls(); - contextData.step = Step.TUNING; + contextData.step = Step.CONTROL; return new OuterLoopResult(this, OuterLoopStatus.UNSTABLE); } /** - * During tuning step, transformers with ratio outside of range are discretized. Iterate until all transformers - * with continuous ratio are within their operating range , discretize then then switch to DISCTERIZED state + * During control step, transformers with ratio outside of range are discretized. Iterate until all transformers + * with continuous ratio are within their operating range , discretize then switch to COMPLETE state */ - private OuterLoopResult tuningStep(LfNetwork network, ContextData contextData) { + private OuterLoopResult controlStep(LfNetwork network, ContextData contextData) { boolean outOfBoundTap = false; for (LfBranch controllerBranch : network.getControllerElements(VoltageControl.Type.TRANSFORMER)) { @@ -137,9 +137,9 @@ private OuterLoopResult tuningStep(LfNetwork network, ContextData contextData) { updateContinuousRatio(network, contextData); roundVoltageRatios(network); - contextData.groupVoltageControlManager.restartGroupTensionControl(); + contextData.generatorVoltageControlManager.restartGroupTensionControl(); - contextData.step = Step.DISCRETIZED; + contextData.step = Step.COMPLETE; } // In any case the loop must run again return new OuterLoopResult(this, OuterLoopStatus.UNSTABLE); diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java similarity index 97% rename from src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java rename to src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java index e19388d80d..a70330cc0b 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GroupVoltageControlManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java @@ -20,12 +20,12 @@ /** * @author Didier Vidal {@literal } */ -public class GroupVoltageControlManager { +public class GeneratorVoltageControlManager { private final double minVoltageLimit; private final List busesWithVoltageControlDisabled = new ArrayList<>(); - public GroupVoltageControlManager(LfNetwork network, double limitOverride) { + public GeneratorVoltageControlManager(LfNetwork network, double limitOverride) { this.minVoltageLimit = limitOverride < 0 ? calculateMaxControlledNominalVoltage(network) : limitOverride; } diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java index baee202583..0a279448b8 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java @@ -25,7 +25,7 @@ public class TransformerRatioManager { private static final Logger LOGGER = LoggerFactory.getLogger(TransformerRatioManager.class); - private final boolean stable; + private final boolean useInitialTapePosition; public record ParallelRatioInfo(double rMax, double rMin, double rIni) { public ParallelRatioInfo(PiModel piModel) { @@ -47,8 +47,8 @@ public record TransfoRatioInfo(double rIni, ParallelRatioInfo groupeInfo) { * If 'stable' is true then tMax, rMin and rIni are the average valus of the transformers in parallel * otherwise the transformer individual values. */ - public TransformerRatioManager(LfNetwork network, boolean stable) { - this.stable = stable; + public TransformerRatioManager(LfNetwork network, boolean useInitialTapePosition) { + this.useInitialTapePosition = useInitialTapePosition; for (LfBus bus : network.getControlledBuses(VoltageControl.Type.TRANSFORMER)) { bus.getTransformerVoltageControl() .filter(voltageControl -> voltageControl.getMergeStatus() == VoltageControl.MergeStatus.MAIN) @@ -58,7 +58,7 @@ public TransformerRatioManager(LfNetwork network, boolean stable) { .filter(LfBranch::isVoltageControlEnabled) .toList(); if (!controllerBranches.isEmpty()) { // If transformers in parallel control tension - if (stable) { + if (useInitialTapePosition) { // parallel info double coefA = 0; double coefB = 0; @@ -98,7 +98,7 @@ public TransfoRatioInfo getInfo(LfBranch transformer) { } /** - * If stable is true, for tranformers in parallel, try to keep the initial difference between individual ratio + * If useInitialTapePosition is true, for tranformers in parallel, try to keep the initial difference between individual ratio * This algorithm maintains the individual tap positions if the tension is correct with initial settings. * It can also be seen as an approximate simulation of transformers acting with independent automates. * Assumes that all transformers in parallel have the same ratio (should be maintained by @@ -107,7 +107,7 @@ public TransfoRatioInfo getInfo(LfBranch transformer) { * @return the updated transormer's ratio */ public double updateContinuousRatio(LfBranch transfo) { - if (stable) { + if (useInitialTapePosition) { TransformerRatioManager.TransfoRatioInfo transfoRatioInfo = transfoRatioInfoMap.get(transfo.getId()); double r1GroupMax = transfoRatioInfo.groupeInfo().rMax(); double r1GroupMin = transfoRatioInfo.groupeInfo().rMin(); diff --git a/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java b/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java index 2ebcffd034..6b522b23b0 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java @@ -64,7 +64,7 @@ public class LfNetworkParameters { public static final List VOLTAGE_CONTROL_PRIORITIES_DEFAULT_VALUE = VoltageControl.VOLTAGE_CONTROL_PRIORITIES; - public static final boolean TRANSFORMER_VOLTAGE_CONTROL_STABLE_DEFAULT_VALUE = false; + public static final boolean TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_DEFAULT_VALUE = false; private boolean generatorVoltageRemoteControl = true; diff --git a/src/test/java/com/powsybl/openloadflow/OpenLoadFlowParametersTest.java b/src/test/java/com/powsybl/openloadflow/OpenLoadFlowParametersTest.java index 184393bbc2..8b5a5004a6 100644 --- a/src/test/java/com/powsybl/openloadflow/OpenLoadFlowParametersTest.java +++ b/src/test/java/com/powsybl/openloadflow/OpenLoadFlowParametersTest.java @@ -384,7 +384,7 @@ void testCloneParameters() { @Test void testToString() { OpenLoadFlowParameters parameters = new OpenLoadFlowParameters(); - assertEquals("OpenLoadFlowParameters(slackBusSelectionMode=MOST_MESHED, slackBusesIds=[], slackDistributionFailureBehavior=LEAVE_ON_SLACK_BUS, voltageRemoteControl=true, lowImpedanceBranchMode=REPLACE_BY_ZERO_IMPEDANCE_LINE, loadPowerFactorConstant=false, plausibleActivePowerLimit=5000.0, newtonRaphsonStoppingCriteriaType=UNIFORM_CRITERIA, slackBusPMaxMismatch=1.0, maxActivePowerMismatch=0.01, maxReactivePowerMismatch=0.01, maxVoltageMismatch=1.0E-4, maxAngleMismatch=1.0E-5, maxRatioMismatch=1.0E-5, maxSusceptanceMismatch=1.0E-4, voltagePerReactivePowerControl=false, generatorReactivePowerRemoteControl=false, transformerReactivePowerControl=false, maxNewtonRaphsonIterations=15, maxOuterLoopIterations=20, newtonRaphsonConvEpsPerEq=1.0E-4, voltageInitModeOverride=NONE, transformerVoltageControlMode=WITH_GENERATOR_VOLTAGE_CONTROL, shuntVoltageControlMode=WITH_GENERATOR_VOLTAGE_CONTROL, minPlausibleTargetVoltage=0.8, maxPlausibleTargetVoltage=1.2, minRealisticVoltage=0.5, maxRealisticVoltage=2.0, reactiveRangeCheckMode=MAX, lowImpedanceThreshold=1.0E-8, networkCacheEnabled=false, svcVoltageMonitoring=true, stateVectorScalingMode=NONE, maxSlackBusCount=1, debugDir=null, incrementalTransformerRatioTapControlOuterLoopMaxTapShift=3, secondaryVoltageControl=false, reactiveLimitsMaxPqPvSwitch=3, phaseShifterControlMode=CONTINUOUS_WITH_DISCRETISATION, alwaysUpdateNetwork=false, mostMeshedSlackBusSelectorMaxNominalVoltagePercentile=95.0, reportedFeatures=[], slackBusCountryFilter=[], actionableSwitchesIds=[], actionableTransformersIds=[], asymmetrical=false, minNominalVoltageTargetVoltageCheck=20.0, reactivePowerDispatchMode=Q_EQUAL_PROPORTION, outerLoopNames=null, useActiveLimits=true, disableVoltageControlOfGeneratorsOutsideActivePowerLimits=false, lineSearchStateVectorScalingMaxIteration=10, lineSearchStateVectorScalingStepFold=1.3333333333333333, maxVoltageChangeStateVectorScalingMaxDv=0.1, maxVoltageChangeStateVectorScalingMaxDphi=0.17453292519943295, linePerUnitMode=IMPEDANCE, useLoadModel=false, dcApproximationType=IGNORE_R, simulateAutomationSystems=false, acSolverType=NEWTON_RAPHSON, maxNewtonKrylovIterations=100, newtonKrylovLineSearch=false, referenceBusSelectionMode=FIRST_SLACK, writeReferenceTerminals=true, voltageTargetPriorities=[GENERATOR, TRANSFORMER, SHUNT], transformerVoltageControlStable=false, generatorVoltageControlMinNominalVoltage=-1.0)", + assertEquals("OpenLoadFlowParameters(slackBusSelectionMode=MOST_MESHED, slackBusesIds=[], slackDistributionFailureBehavior=LEAVE_ON_SLACK_BUS, voltageRemoteControl=true, lowImpedanceBranchMode=REPLACE_BY_ZERO_IMPEDANCE_LINE, loadPowerFactorConstant=false, plausibleActivePowerLimit=5000.0, newtonRaphsonStoppingCriteriaType=UNIFORM_CRITERIA, slackBusPMaxMismatch=1.0, maxActivePowerMismatch=0.01, maxReactivePowerMismatch=0.01, maxVoltageMismatch=1.0E-4, maxAngleMismatch=1.0E-5, maxRatioMismatch=1.0E-5, maxSusceptanceMismatch=1.0E-4, voltagePerReactivePowerControl=false, generatorReactivePowerRemoteControl=false, transformerReactivePowerControl=false, maxNewtonRaphsonIterations=15, maxOuterLoopIterations=20, newtonRaphsonConvEpsPerEq=1.0E-4, voltageInitModeOverride=NONE, transformerVoltageControlMode=WITH_GENERATOR_VOLTAGE_CONTROL, shuntVoltageControlMode=WITH_GENERATOR_VOLTAGE_CONTROL, minPlausibleTargetVoltage=0.8, maxPlausibleTargetVoltage=1.2, minRealisticVoltage=0.5, maxRealisticVoltage=2.0, reactiveRangeCheckMode=MAX, lowImpedanceThreshold=1.0E-8, networkCacheEnabled=false, svcVoltageMonitoring=true, stateVectorScalingMode=NONE, maxSlackBusCount=1, debugDir=null, incrementalTransformerRatioTapControlOuterLoopMaxTapShift=3, secondaryVoltageControl=false, reactiveLimitsMaxPqPvSwitch=3, phaseShifterControlMode=CONTINUOUS_WITH_DISCRETISATION, alwaysUpdateNetwork=false, mostMeshedSlackBusSelectorMaxNominalVoltagePercentile=95.0, reportedFeatures=[], slackBusCountryFilter=[], actionableSwitchesIds=[], actionableTransformersIds=[], asymmetrical=false, minNominalVoltageTargetVoltageCheck=20.0, reactivePowerDispatchMode=Q_EQUAL_PROPORTION, outerLoopNames=null, useActiveLimits=true, disableVoltageControlOfGeneratorsOutsideActivePowerLimits=false, lineSearchStateVectorScalingMaxIteration=10, lineSearchStateVectorScalingStepFold=1.3333333333333333, maxVoltageChangeStateVectorScalingMaxDv=0.1, maxVoltageChangeStateVectorScalingMaxDphi=0.17453292519943295, linePerUnitMode=IMPEDANCE, useLoadModel=false, dcApproximationType=IGNORE_R, simulateAutomationSystems=false, acSolverType=NEWTON_RAPHSON, maxNewtonKrylovIterations=100, newtonKrylovLineSearch=false, referenceBusSelectionMode=FIRST_SLACK, writeReferenceTerminals=true, voltageTargetPriorities=[GENERATOR, TRANSFORMER, SHUNT], transformerVoltageControlUseInitialTapPosition=false, generatorVoltageControlMinNominalVoltage=-1.0)", parameters.toString()); } diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java index 09f30fb161..79d0e7aacb 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java @@ -202,7 +202,7 @@ void voltageControlT2wtTest5() { .setRegulationTerminal(t2wt2.getTerminal2()) .setTargetV(34.0); LoadFlowParameters stableParams = parameters.copy(); - stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlStable(true); + stableParams.getExtension(OpenLoadFlowParameters.class).setUseInitialTapPosition(true); stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlMode(OpenLoadFlowParameters.TransformerVoltageControlMode.AFTER_GENERATOR_VOLTAGE_CONTROL); result = loadFlowRunner.run(network, stableParams); assertTrue(result.isFullyConverged()); @@ -282,7 +282,7 @@ void voltageControlT2wtTest5() { void voltageControlT2wtTestRationAtLimit() { LoadFlowParameters stableParams = parameters.copy(); stableParams.setTransformerVoltageControlOn(true); - stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlStable(true); + stableParams.getExtension(OpenLoadFlowParameters.class).setUseInitialTapPosition(true); stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlMode(OpenLoadFlowParameters.TransformerVoltageControlMode.AFTER_GENERATOR_VOLTAGE_CONTROL); stableParams.getExtension(OpenLoadFlowParameters.class).setMinPlausibleTargetVoltage(0.5); // Keep unusual voltage target to force ratio to tap changer limit diff --git a/src/test/resources/debug-parameters.json b/src/test/resources/debug-parameters.json index 3e6645b9a3..5393ff434e 100644 --- a/src/test/resources/debug-parameters.json +++ b/src/test/resources/debug-parameters.json @@ -85,7 +85,7 @@ "referenceBusSelectionMode" : "FIRST_SLACK", "writeReferenceTerminals" : true, "voltageTargetPriorities" : [ "GENERATOR", "TRANSFORMER", "SHUNT" ], - "transformerVoltageControlStable" : false, + "useInitialTapPosition" : false, "generatorVoltageControlMinNominalVoltage" : -1.0 } } From 31b5990515bd471ba5830858d69784d2e8e0d2d2 Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Tue, 11 Jun 2024 17:59:07 +0200 Subject: [PATCH 18/30] one more renaming Signed-off-by: VIDAL Didier (Externe) --- .../outerloop/TransformerVoltageControlOuterLoop.java | 2 +- .../outerloop/tap/GeneratorVoltageControlManager.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java index 11d0b61a10..6c8d7867ff 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java @@ -137,7 +137,7 @@ private OuterLoopResult controlStep(LfNetwork network, ContextData contextData) updateContinuousRatio(network, contextData); roundVoltageRatios(network); - contextData.generatorVoltageControlManager.restartGroupTensionControl(); + contextData.generatorVoltageControlManager.restartGeneratorTensionControl(); contextData.step = Step.COMPLETE; } diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java index a70330cc0b..71c51edd42 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java @@ -22,11 +22,11 @@ */ public class GeneratorVoltageControlManager { - private final double minVoltageLimit; + private final double minNominalVoltageLimit; private final List busesWithVoltageControlDisabled = new ArrayList<>(); public GeneratorVoltageControlManager(LfNetwork network, double limitOverride) { - this.minVoltageLimit = limitOverride < 0 ? calculateMaxControlledNominalVoltage(network) : limitOverride; + this.minNominalVoltageLimit = limitOverride < 0 ? calculateMaxControlledNominalVoltage(network) : limitOverride; } private static double calculateMaxControlledNominalVoltage(LfNetwork network) { @@ -65,10 +65,10 @@ public boolean stopTensionControlBelowLimit(LfNetwork network) { boolean result = false; for (LfBus bus : network.getControlledBuses(VoltageControl.Type.GENERATOR)) { - if (bus.getNominalV() < minVoltageLimit) { + if (bus.getNominalV() < minNominalVoltageLimit) { var voltageControl = bus.getGeneratorVoltageControl().orElseThrow(); for (LfBus controllerBus : voltageControl.getMergedControllerElements()) { - if (controllerBus.isGeneratorVoltageControlEnabled() && !isBusBehindVeryHighVoltageTransfo(controllerBus, minVoltageLimit)) { + if (controllerBus.isGeneratorVoltageControlEnabled() && !isBusBehindVeryHighVoltageTransfo(controllerBus, minNominalVoltageLimit)) { controllerBus.setGenerationTargetQ(controllerBus.getQ().eval()); controllerBus.setGeneratorVoltageControlEnabled(false); busesWithVoltageControlDisabled.add(controllerBus); @@ -80,7 +80,7 @@ public boolean stopTensionControlBelowLimit(LfNetwork network) { return result; } - public void restartGroupTensionControl() { + public void restartGeneratorTensionControl() { for (LfBus controllerBus : busesWithVoltageControlDisabled) { controllerBus.setGenerationTargetQ(0); controllerBus.setGeneratorVoltageControlEnabled(true); From 2aed9eca834ad95e2ac26df7ad5a41908116ec14 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 12 Jun 2024 09:22:45 +0200 Subject: [PATCH 19/30] Small renaming and clean. Signed-off-by: Anne Tilloy --- .../TransformerVoltageControlOuterLoop.java | 30 ++++++++----------- .../tap/GeneratorVoltageControlManager.java | 21 ++++++------- .../tap/TransformerRatioManager.java | 21 +++++++------ 3 files changed, 32 insertions(+), 40 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java index 6c8d7867ff..d53d15a12f 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java @@ -41,13 +41,12 @@ private static final class ContextData { private GeneratorVoltageControlManager generatorVoltageControlManager; private Step step = Step.INITIAL; - } - private final boolean useInitialTapePosition; + private final boolean useInitialTapPosition; - public TransformerVoltageControlOuterLoop(boolean useInitialTapePosition, double maxControlledNominalVoltageOverride) { - this.useInitialTapePosition = useInitialTapePosition; + public TransformerVoltageControlOuterLoop(boolean useInitialTapPosition, double maxControlledNominalVoltageOverride) { + this.useInitialTapPosition = useInitialTapPosition; this.maxControlledNominalVoltageOverride = maxControlledNominalVoltageOverride; } @@ -56,11 +55,11 @@ public void initialize(AcOuterLoopContext context) { ContextData contextData = new ContextData(); context.setData(contextData); + // All transformer voltage control are disabled for the first equation system resolution. for (LfBranch controllerBranch : context.getNetwork().getControllerElements(VoltageControl.Type.TRANSFORMER)) { controllerBranch.setVoltageControlEnabled(false); } - // All transformer voltage control are disabled for the first equation system resolution. contextData.generatorVoltageControlManager = new GeneratorVoltageControlManager(context.getNetwork(), maxControlledNominalVoltageOverride); } @@ -83,9 +82,9 @@ public OuterLoopResult check(AcOuterLoopContext context, ReportNode reportNode) } /** - * At first outer loop iteration, the voltage control of generators that controlled at nominal voltage of - * the set controlledNominalVoltages are disabled. - * The transformer voltage controls are enabled ant their continuous ratio is computed$ + * At first outer loop iteration, the voltage control of generators that controlled under the max controlled nominal + * voltage are disabled (automatic detection or parameter). + * The transformer voltage controls are enabled and their continuous ratio is computed. * @return a stable status if all taps are already tuned for tension control, unstable otherwise */ private OuterLoopResult initStep(LfNetwork network, ContextData contextData) { @@ -104,15 +103,14 @@ private OuterLoopResult initStep(LfNetwork network, ContextData contextData) { } } - contextData.transformerRatioManager = new TransformerRatioManager(network, useInitialTapePosition); + contextData.transformerRatioManager = new TransformerRatioManager(network, useInitialTapPosition); if (!needRun) { contextData.step = Step.COMPLETE; return new OuterLoopResult(this, OuterLoopStatus.STABLE); } - contextData.generatorVoltageControlManager.stopTensionControlBelowLimit(network); + contextData.generatorVoltageControlManager.disableGeneratorVoltageControlsUnderMaxControlledNominalVoltage(network); - // In stable mode, Group maintaining tension but in PQ mode are ignored network.fixTransformerVoltageControls(); contextData.step = Step.CONTROL; @@ -120,8 +118,8 @@ private OuterLoopResult initStep(LfNetwork network, ContextData contextData) { } /** - * During control step, transformers with ratio outside of range are discretized. Iterate until all transformers - * with continuous ratio are within their operating range , discretize then switch to COMPLETE state + * During control step, transformers with ratio outside of range are rounded. We iterate until all transformers + * with continuous ratio are within their operating range, rounded then and switch them to COMPLETE. */ private OuterLoopResult controlStep(LfNetwork network, ContextData contextData) { boolean outOfBoundTap = false; @@ -133,15 +131,14 @@ private OuterLoopResult controlStep(LfNetwork network, ContextData contextData) } if (!outOfBoundTap) { - // No out of bound tap - descretize updateContinuousRatio(network, contextData); roundVoltageRatios(network); - contextData.generatorVoltageControlManager.restartGeneratorTensionControl(); + contextData.generatorVoltageControlManager.enableGeneratorVoltageControlsUnderMaxControlledNominalVoltage(); contextData.step = Step.COMPLETE; } - // In any case the loop must run again + // In any case, the loop must run again. return new OuterLoopResult(this, OuterLoopStatus.UNSTABLE); } @@ -157,5 +154,4 @@ private void updateContinuousRatio(LfNetwork network, ContextData contextData) { }); } } - } diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java index 71c51edd42..374368d40c 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java @@ -23,7 +23,7 @@ public class GeneratorVoltageControlManager { private final double minNominalVoltageLimit; - private final List busesWithVoltageControlDisabled = new ArrayList<>(); + private final List disabledControllerBuses = new ArrayList<>(); public GeneratorVoltageControlManager(LfNetwork network, double limitOverride) { this.minNominalVoltageLimit = limitOverride < 0 ? calculateMaxControlledNominalVoltage(network) : limitOverride; @@ -57,13 +57,9 @@ private static boolean isTransformerVoltageControlsValidForMaxControlledNominalV } /** - * Disables the voltage control of generators with nominal voltage below the limit - * @return true if at least one generator is disabled. False if the model is not modified + * Disables the voltage control of generators if controlled bus nominal voltage is under the limit. */ - public boolean stopTensionControlBelowLimit(LfNetwork network) { - - boolean result = false; - + public void disableGeneratorVoltageControlsUnderMaxControlledNominalVoltage(LfNetwork network) { for (LfBus bus : network.getControlledBuses(VoltageControl.Type.GENERATOR)) { if (bus.getNominalV() < minNominalVoltageLimit) { var voltageControl = bus.getGeneratorVoltageControl().orElseThrow(); @@ -71,17 +67,18 @@ public boolean stopTensionControlBelowLimit(LfNetwork network) { if (controllerBus.isGeneratorVoltageControlEnabled() && !isBusBehindVeryHighVoltageTransfo(controllerBus, minNominalVoltageLimit)) { controllerBus.setGenerationTargetQ(controllerBus.getQ().eval()); controllerBus.setGeneratorVoltageControlEnabled(false); - busesWithVoltageControlDisabled.add(controllerBus); - result = true; + disabledControllerBuses.add(controllerBus); } } } } - return result; } - public void restartGeneratorTensionControl() { - for (LfBus controllerBus : busesWithVoltageControlDisabled) { + /** + * Enables the voltage control of generators if controlled bus nominal voltage is under the limit. + */ + public void enableGeneratorVoltageControlsUnderMaxControlledNominalVoltage() { + for (LfBus controllerBus : disabledControllerBuses) { controllerBus.setGenerationTargetQ(0); controllerBus.setGeneratorVoltageControlEnabled(true); } diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java index 0a279448b8..7155ff82f2 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java @@ -25,7 +25,7 @@ public class TransformerRatioManager { private static final Logger LOGGER = LoggerFactory.getLogger(TransformerRatioManager.class); - private final boolean useInitialTapePosition; + private final boolean useInitialTapPosition; public record ParallelRatioInfo(double rMax, double rMin, double rIni) { public ParallelRatioInfo(PiModel piModel) { @@ -48,7 +48,7 @@ public record TransfoRatioInfo(double rIni, ParallelRatioInfo groupeInfo) { * otherwise the transformer individual values. */ public TransformerRatioManager(LfNetwork network, boolean useInitialTapePosition) { - this.useInitialTapePosition = useInitialTapePosition; + this.useInitialTapPosition = useInitialTapePosition; for (LfBus bus : network.getControlledBuses(VoltageControl.Type.TRANSFORMER)) { bus.getTransformerVoltageControl() .filter(voltageControl -> voltageControl.getMergeStatus() == VoltageControl.MergeStatus.MAIN) @@ -106,23 +106,23 @@ public TransfoRatioInfo getInfo(LfBranch transformer) { * If stable is false, the transformer is not modified and keeps its computed ratio. * @return the updated transormer's ratio */ - public double updateContinuousRatio(LfBranch transfo) { - if (useInitialTapePosition) { - TransformerRatioManager.TransfoRatioInfo transfoRatioInfo = transfoRatioInfoMap.get(transfo.getId()); + public double updateContinuousRatio(LfBranch branch) { + if (useInitialTapPosition) { + TransformerRatioManager.TransfoRatioInfo transfoRatioInfo = transfoRatioInfoMap.get(branch.getId()); double r1GroupMax = transfoRatioInfo.groupeInfo().rMax(); double r1GroupMin = transfoRatioInfo.groupeInfo().rMin(); double r1GroupIni = transfoRatioInfo.groupeInfo().rIni(); - double computedR = transfo.getPiModel().getR1(); // equations provide the same R for all branches + double computedR = branch.getPiModel().getR1(); // equations provide the same R for all branches double r1Ini = transfoRatioInfo.rIni(); double updatedR = computedR >= r1GroupIni ? - r1Ini + (computedR - r1GroupIni) * (transfo.getPiModel().getMaxR1() - r1Ini) / (r1GroupMax - r1GroupIni) + r1Ini + (computedR - r1GroupIni) * (branch.getPiModel().getMaxR1() - r1Ini) / (r1GroupMax - r1GroupIni) : - r1Ini - (r1GroupIni - computedR) * (r1Ini - transfo.getPiModel().getMinR1()) / (r1GroupIni - r1GroupMin); - transfo.getPiModel().setR1(updatedR); + r1Ini - (r1GroupIni - computedR) * (r1Ini - branch.getPiModel().getMinR1()) / (r1GroupIni - r1GroupMin); + branch.getPiModel().setR1(updatedR); return updatedR; } else { // Do Nothing - keep computed R1 - return transfo.getPiModel().getR1(); + return branch.getPiModel().getR1(); } } @@ -150,5 +150,4 @@ public boolean freezeIfGroupAtBounds(LfBranch transfo) { } return false; } - } From 84b22e78c6825587215dcf520a50c4b40fee6e5e Mon Sep 17 00:00:00 2001 From: "VIDAL Didier (Externe)" Date: Wed, 12 Jun 2024 10:56:21 +0200 Subject: [PATCH 20/30] rename parameter getter and setters to eactly match declared parameter name and enable json serde Signed-off-by: VIDAL Didier (Externe) --- .../AbstractAcOuterLoopConfig.java | 2 +- .../ExplicitAcOuterLoopConfig.java | 6 +++--- .../openloadflow/OpenLoadFlowParameters.java | 20 +++++++++---------- ...LoadFlowTransformerVoltageControlTest.java | 4 ++-- src/test/resources/debug-parameters.json | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java b/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java index 83b2779f07..cad918cdbe 100644 --- a/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java +++ b/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java @@ -73,7 +73,7 @@ protected static Optional createTransformerVoltageControlOuterLoop( protected static Optional createTransformerVoltageControlOuterLoop(LoadFlowParameters parameters, OpenLoadFlowParameters parametersExt) { return createTransformerVoltageControlOuterLoop(parameters, - parametersExt.isUseInitialTapPosition(), + parametersExt.isTransformerVoltageControlUseInitialTapPosition(), parametersExt.getTransformerVoltageControlMode(), parametersExt.getIncrementalTransformerRatioTapControlOuterLoopMaxTapShift(), parametersExt.getGeneratorVoltageControlMinNominalVoltage()); diff --git a/src/main/java/com/powsybl/openloadflow/ExplicitAcOuterLoopConfig.java b/src/main/java/com/powsybl/openloadflow/ExplicitAcOuterLoopConfig.java index 9462660779..294a2227b2 100644 --- a/src/main/java/com/powsybl/openloadflow/ExplicitAcOuterLoopConfig.java +++ b/src/main/java/com/powsybl/openloadflow/ExplicitAcOuterLoopConfig.java @@ -45,7 +45,7 @@ private static Optional createOuterLoop(String name, LoadFlowParame case IncrementalShuntVoltageControlOuterLoop.NAME -> createShuntVoltageControlOuterLoop(parameters, OpenLoadFlowParameters.ShuntVoltageControlMode.INCREMENTAL_VOLTAGE_CONTROL); case IncrementalTransformerVoltageControlOuterLoop.NAME -> createTransformerVoltageControlOuterLoop(parameters, - parametersExt.isUseInitialTapPosition(), + parametersExt.isTransformerVoltageControlUseInitialTapPosition(), OpenLoadFlowParameters.TransformerVoltageControlMode.INCREMENTAL_VOLTAGE_CONTROL, parametersExt.getIncrementalTransformerRatioTapControlOuterLoopMaxTapShift(), parametersExt.getGeneratorVoltageControlMinNominalVoltage()); @@ -57,12 +57,12 @@ private static Optional createOuterLoop(String name, LoadFlowParame case ShuntVoltageControlOuterLoop.NAME -> createShuntVoltageControlOuterLoop(parameters, OpenLoadFlowParameters.ShuntVoltageControlMode.WITH_GENERATOR_VOLTAGE_CONTROL); case SimpleTransformerVoltageControlOuterLoop.NAME -> createTransformerVoltageControlOuterLoop(parameters, - parametersExt.isUseInitialTapPosition(), + parametersExt.isTransformerVoltageControlUseInitialTapPosition(), OpenLoadFlowParameters.TransformerVoltageControlMode.WITH_GENERATOR_VOLTAGE_CONTROL, parametersExt.getIncrementalTransformerRatioTapControlOuterLoopMaxTapShift(), parametersExt.getGeneratorVoltageControlMinNominalVoltage()); case TransformerVoltageControlOuterLoop.NAME -> createTransformerVoltageControlOuterLoop(parameters, - parametersExt.isUseInitialTapPosition(), + parametersExt.isTransformerVoltageControlUseInitialTapPosition(), OpenLoadFlowParameters.TransformerVoltageControlMode.AFTER_GENERATOR_VOLTAGE_CONTROL, parametersExt.getIncrementalTransformerRatioTapControlOuterLoopMaxTapShift(), parametersExt.getGeneratorVoltageControlMinNominalVoltage()); diff --git a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java index 48a4e74c20..b48216bb43 100644 --- a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java +++ b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java @@ -497,7 +497,7 @@ public enum ReactiveRangeCheckMode { private List voltageTargetPriorities = LfNetworkParameters.VOLTAGE_CONTROL_PRIORITIES_DEFAULT_VALUE; - private boolean useInitialTapPosition = LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_DEFAULT_VALUE; + private boolean transformerVoltageControlUseInitialTapPosition = LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_DEFAULT_VALUE; private double generatorVoltageControlMinNominalVoltage = GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_DEFAULT_VALUE; @@ -1165,12 +1165,12 @@ public OpenLoadFlowParameters setVoltageTargetPriorities(List voltageTar return this; } - public boolean isUseInitialTapPosition() { - return useInitialTapPosition; + public boolean isTransformerVoltageControlUseInitialTapPosition() { + return transformerVoltageControlUseInitialTapPosition; } - public OpenLoadFlowParameters setUseInitialTapPosition(boolean useInitialTapPosition) { - this.useInitialTapPosition = useInitialTapPosition; + public OpenLoadFlowParameters setTransformerVoltageControlUseInitialTapPosition(boolean transformerVoltageControlUseInitialTapPosition) { + this.transformerVoltageControlUseInitialTapPosition = transformerVoltageControlUseInitialTapPosition; return this; } @@ -1262,7 +1262,7 @@ public static OpenLoadFlowParameters load(PlatformConfig platformConfig) { .setReferenceBusSelectionMode(config.getEnumProperty(REFERENCE_BUS_SELECTION_MODE_PARAM_NAME, ReferenceBusSelectionMode.class, ReferenceBusSelector.DEFAULT_MODE)) .setWriteReferenceTerminals(config.getBooleanProperty(WRITE_REFERENCE_TERMINALS_PARAM_NAME, WRITE_REFERENCE_TERMINALS_DEFAULT_VALUE)) .setVoltageTargetPriorities(config.getStringListProperty(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME, LfNetworkParameters.VOLTAGE_CONTROL_PRIORITIES_DEFAULT_VALUE)) - .setUseInitialTapPosition(config.getBooleanProperty(TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_PARAM_NAME, LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_DEFAULT_VALUE)) + .setTransformerVoltageControlUseInitialTapPosition(config.getBooleanProperty(TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_PARAM_NAME, LfNetworkParameters.TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_DEFAULT_VALUE)) .setGeneratorVoltageControlMinNominalVoltage(config.getDoubleProperty(GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_PARAM_NAME, GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_DEFAULT_VALUE))); return parameters; } @@ -1413,7 +1413,7 @@ public OpenLoadFlowParameters update(Map properties) { Optional.ofNullable(properties.get(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME)) .ifPresent(prop -> this.setVoltageTargetPriorities(parseStringListProp(prop))); Optional.ofNullable(properties.get(TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_PARAM_NAME)) - .ifPresent(prop -> this.setUseInitialTapPosition(Boolean.parseBoolean(prop))); + .ifPresent(prop -> this.setTransformerVoltageControlUseInitialTapPosition(Boolean.parseBoolean(prop))); Optional.ofNullable(properties.get(GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_PARAM_NAME)) .ifPresent(prop -> this.setGeneratorVoltageControlMinNominalVoltage(Double.parseDouble(prop))); return this; @@ -1486,7 +1486,7 @@ public Map toMap() { map.put(REFERENCE_BUS_SELECTION_MODE_PARAM_NAME, referenceBusSelectionMode); map.put(WRITE_REFERENCE_TERMINALS_PARAM_NAME, writeReferenceTerminals); map.put(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME, voltageTargetPriorities); - map.put(TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_PARAM_NAME, useInitialTapPosition); + map.put(TRANSFORMER_VOLTAGE_CONTROL_USE_INITIAL_TAP_POSITION_PARAM_NAME, transformerVoltageControlUseInitialTapPosition); map.put(GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_PARAM_NAME, generatorVoltageControlMinNominalVoltage); return map; } @@ -1863,7 +1863,7 @@ public static boolean equals(LoadFlowParameters parameters1, LoadFlowParameters extension1.getMaxSusceptanceMismatch() == extension2.getMaxSusceptanceMismatch() && extension1.getNewtonRaphsonStoppingCriteriaType() == extension2.getNewtonRaphsonStoppingCriteriaType() && Objects.equals(extension1.getVoltageTargetPriorities(), extension2.getVoltageTargetPriorities()) && - extension1.isUseInitialTapPosition() == extension2.isUseInitialTapPosition() && + extension1.isTransformerVoltageControlUseInitialTapPosition() == extension2.isTransformerVoltageControlUseInitialTapPosition() && extension1.getGeneratorVoltageControlMinNominalVoltage() == extension2.getGeneratorVoltageControlMinNominalVoltage(); } @@ -1955,7 +1955,7 @@ public static LoadFlowParameters clone(LoadFlowParameters parameters) { .setNewtonRaphsonStoppingCriteriaType(extension.getNewtonRaphsonStoppingCriteriaType()) .setReferenceBusSelectionMode(extension.getReferenceBusSelectionMode()) .setVoltageTargetPriorities(extension.getVoltageTargetPriorities()) - .setUseInitialTapPosition(extension.isUseInitialTapPosition()) + .setTransformerVoltageControlUseInitialTapPosition(extension.isTransformerVoltageControlUseInitialTapPosition()) .setGeneratorVoltageControlMinNominalVoltage(extension.getGeneratorVoltageControlMinNominalVoltage()); if (extension2 != null) { diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java index 79d0e7aacb..1eb15fe68a 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowTransformerVoltageControlTest.java @@ -202,7 +202,7 @@ void voltageControlT2wtTest5() { .setRegulationTerminal(t2wt2.getTerminal2()) .setTargetV(34.0); LoadFlowParameters stableParams = parameters.copy(); - stableParams.getExtension(OpenLoadFlowParameters.class).setUseInitialTapPosition(true); + stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlUseInitialTapPosition(true); stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlMode(OpenLoadFlowParameters.TransformerVoltageControlMode.AFTER_GENERATOR_VOLTAGE_CONTROL); result = loadFlowRunner.run(network, stableParams); assertTrue(result.isFullyConverged()); @@ -282,7 +282,7 @@ void voltageControlT2wtTest5() { void voltageControlT2wtTestRationAtLimit() { LoadFlowParameters stableParams = parameters.copy(); stableParams.setTransformerVoltageControlOn(true); - stableParams.getExtension(OpenLoadFlowParameters.class).setUseInitialTapPosition(true); + stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlUseInitialTapPosition(true); stableParams.getExtension(OpenLoadFlowParameters.class).setTransformerVoltageControlMode(OpenLoadFlowParameters.TransformerVoltageControlMode.AFTER_GENERATOR_VOLTAGE_CONTROL); stableParams.getExtension(OpenLoadFlowParameters.class).setMinPlausibleTargetVoltage(0.5); // Keep unusual voltage target to force ratio to tap changer limit diff --git a/src/test/resources/debug-parameters.json b/src/test/resources/debug-parameters.json index 5393ff434e..8be490c618 100644 --- a/src/test/resources/debug-parameters.json +++ b/src/test/resources/debug-parameters.json @@ -85,7 +85,7 @@ "referenceBusSelectionMode" : "FIRST_SLACK", "writeReferenceTerminals" : true, "voltageTargetPriorities" : [ "GENERATOR", "TRANSFORMER", "SHUNT" ], - "useInitialTapPosition" : false, + "transformerVoltageControlUseInitialTapPosition" : false, "generatorVoltageControlMinNominalVoltage" : -1.0 } } From 7da2a7c4d3db309e0b19fb1c8dbc8d2abfb88200 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Fri, 14 Jun 2024 15:36:54 +0200 Subject: [PATCH 21/30] Clean TransformerRatioManager. Signed-off-by: Anne Tilloy --- .../TransformerVoltageControlOuterLoop.java | 7 +- .../tap/TransformerRatioManager.java | 139 ++++++++---------- 2 files changed, 66 insertions(+), 80 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java index d53d15a12f..8cede2b1d5 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java @@ -125,7 +125,7 @@ private OuterLoopResult controlStep(LfNetwork network, ContextData contextData) boolean outOfBoundTap = false; for (LfBranch controllerBranch : network.getControllerElements(VoltageControl.Type.TRANSFORMER)) { - if (contextData.transformerRatioManager.freezeIfGroupAtBounds(controllerBranch)) { + if (contextData.transformerRatioManager.freezeAtExtremeTapPosition(controllerBranch)) { outOfBoundTap = true; } } @@ -146,12 +146,11 @@ private void updateContinuousRatio(LfNetwork network, ContextData contextData) { for (LfBus bus : network.getControlledBuses(VoltageControl.Type.TRANSFORMER)) { bus.getTransformerVoltageControl() .filter(voltageControl -> voltageControl.getMergeStatus() == VoltageControl.MergeStatus.MAIN) - .ifPresent(voltageControl -> { + .ifPresent(voltageControl -> voltageControl.getMergedControllerElements().stream() .filter(b -> !b.isDisabled()) .filter(LfBranch::isVoltageControlEnabled) - .forEach(b -> contextData.transformerRatioManager.updateContinuousRatio(b)); - }); + .forEach(b -> contextData.transformerRatioManager.updateContinuousRatio(b))); } } } diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java index 7155ff82f2..1717affadd 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java @@ -12,6 +12,7 @@ import com.powsybl.openloadflow.network.LfNetwork; import com.powsybl.openloadflow.network.PiModel; import com.powsybl.openloadflow.network.VoltageControl; +import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,28 +28,26 @@ public class TransformerRatioManager { private final boolean useInitialTapPosition; - public record ParallelRatioInfo(double rMax, double rMin, double rIni) { - public ParallelRatioInfo(PiModel piModel) { + public record SharedControl(double maxR1, double minR1, double initialR1) { + + public SharedControl(PiModel piModel) { this(piModel.getMaxR1(), piModel.getMinR1(), piModel.getR1()); } - public ParallelRatioInfo(double rMax, double rMin, double coefA, double coefB, int count) { - this(rMax, rMin, (rMin * coefA + rMax * coefB) / count); + public SharedControl(double maxR1, double minR1, double a, double b, int count) { + this(maxR1, minR1, (minR1 * a + maxR1 * b) / count); } } - public record TransfoRatioInfo(double rIni, ParallelRatioInfo groupeInfo) { - } - - private final Map transfoRatioInfoMap = new HashMap<>(); + private final Map> sharedControlByBranchId = new HashMap<>(); /** - * Initializes the ratio states. In particular rMax, rMin and rIni. - * If 'stable' is true then tMax, rMin and rIni are the average valus of the transformers in parallel - * otherwise the transformer individual values. + * Initializes the ratios. In particular maxR1, minR1 and initialR1. + * If 'useInitialTapPosition' is true then maxR1, minR1 and initialR1 are the average value of the transformers of the same + * control otherwise the transformer individual values. */ - public TransformerRatioManager(LfNetwork network, boolean useInitialTapePosition) { - this.useInitialTapPosition = useInitialTapePosition; + public TransformerRatioManager(LfNetwork network, boolean useInitialTapPosition) { + this.useInitialTapPosition = useInitialTapPosition; for (LfBus bus : network.getControlledBuses(VoltageControl.Type.TRANSFORMER)) { bus.getTransformerVoltageControl() .filter(voltageControl -> voltageControl.getMergeStatus() == VoltageControl.MergeStatus.MAIN) @@ -57,94 +56,82 @@ public TransformerRatioManager(LfNetwork network, boolean useInitialTapePosition .filter(b -> !b.isDisabled()) .filter(LfBranch::isVoltageControlEnabled) .toList(); - if (!controllerBranches.isEmpty()) { // If transformers in parallel control tension - if (useInitialTapePosition) { - // parallel info - double coefA = 0; - double coefB = 0; - for (LfBranch transfo : controllerBranches) { - PiModel piModel = transfo.getPiModel(); + if (!controllerBranches.isEmpty()) { + if (useInitialTapPosition) { + // shared behavior + double a = 0; + double b = 0; + for (LfBranch branch : controllerBranches) { + PiModel piModel = branch.getPiModel(); double r1 = piModel.getR1(); - double r1Max = piModel.getMaxR1(); - double r1Min = piModel.getMinR1(); - if (r1Max != r1Min) { - coefA += (r1Max - r1) / (r1Max - r1Min); - coefB += (r1 - r1Min) / (r1Max - r1Min); + double maxR1 = piModel.getMaxR1(); + double minR1 = piModel.getMinR1(); + if (maxR1 != minR1) { + a += (maxR1 - r1) / (maxR1 - minR1); + b += (r1 - minR1) / (maxR1 - minR1); } else { - coefA += 1; - coefB += 1; + a += 1; + b += 1; } } - ParallelRatioInfo parallelRatioInfo = new ParallelRatioInfo( - controllerBranches.stream().mapToDouble(b -> b.getPiModel().getMaxR1()).average().orElseThrow(), - controllerBranches.stream().mapToDouble(b -> b.getPiModel().getMinR1()).average().orElseThrow(), - coefA, - coefB, + SharedControl sharedControl = new SharedControl( + controllerBranches.stream().mapToDouble(branch -> branch.getPiModel().getMaxR1()).average().orElseThrow(), + controllerBranches.stream().mapToDouble(branch -> branch.getPiModel().getMinR1()).average().orElseThrow(), + a, + b, controllerBranches.size()); - controllerBranches.forEach(b -> transfoRatioInfoMap.put(b.getId(), new TransfoRatioInfo(b.getPiModel().getR1(), parallelRatioInfo))); + controllerBranches.forEach(branch -> sharedControlByBranchId.put(branch.getId(), Pair.of(branch.getPiModel().getR1(), sharedControl))); } else { - // individual info - controllerBranches.forEach(b -> transfoRatioInfoMap.put(b.getId(), - new TransfoRatioInfo(b.getPiModel().getR1(), new ParallelRatioInfo(b.getPiModel())))); + // individual behavior + controllerBranches.forEach(branch -> sharedControlByBranchId.put(branch.getId(), Pair.of(branch.getPiModel().getR1(), new SharedControl(branch.getPiModel())))); } - } }); } } - public TransfoRatioInfo getInfo(LfBranch transformer) { - return transfoRatioInfoMap.get(transformer.getId()); - } - /** - * If useInitialTapePosition is true, for tranformers in parallel, try to keep the initial difference between individual ratio - * This algorithm maintains the individual tap positions if the tension is correct with initial settings. - * It can also be seen as an approximate simulation of transformers acting with independent automates. - * Assumes that all transformers in parallel have the same ratio (should be maintained by - * ACEquationSystemCreator.createR1DistributionEquations) - * If stable is false, the transformer is not modified and keeps its computed ratio. - * @return the updated transormer's ratio + * If 'useInitialTapePosition' is true, for transformers of the same control, we try to keep the initial difference + * between individual ratios. This algorithm maintains the individual tap positions if the voltage is correct with initial + * state. It can also be seen as an approximate simulation of transformers acting with independent automation systems. + * Assumes that all transformers of the same control have the same ratio (should be maintained by + * ACEquationSystemCreator.createR1DistributionEquations). + * If 'useInitialTapePosition' is false, the transformer is not modified and keeps its computed R1. */ - public double updateContinuousRatio(LfBranch branch) { + public void updateContinuousRatio(LfBranch branch) { if (useInitialTapPosition) { - TransformerRatioManager.TransfoRatioInfo transfoRatioInfo = transfoRatioInfoMap.get(branch.getId()); - double r1GroupMax = transfoRatioInfo.groupeInfo().rMax(); - double r1GroupMin = transfoRatioInfo.groupeInfo().rMin(); - double r1GroupIni = transfoRatioInfo.groupeInfo().rIni(); - double computedR = branch.getPiModel().getR1(); // equations provide the same R for all branches - double r1Ini = transfoRatioInfo.rIni(); - double updatedR = computedR >= r1GroupIni ? - r1Ini + (computedR - r1GroupIni) * (branch.getPiModel().getMaxR1() - r1Ini) / (r1GroupMax - r1GroupIni) + double individualInitialR1 = sharedControlByBranchId.get(branch.getId()).getLeft(); + SharedControl sharedControl = sharedControlByBranchId.get(branch.getId()).getRight(); + double maxR1 = sharedControl.maxR1(); + double minR1 = sharedControl.minR1(); + double initialR1 = sharedControl.initialR1(); + double computedR1 = branch.getPiModel().getR1(); // equations provide the same R1 for all branches + double updatedR1 = computedR1 >= initialR1 ? + individualInitialR1 + (computedR1 - initialR1) * (branch.getPiModel().getMaxR1() - individualInitialR1) / (maxR1 - individualInitialR1) : - r1Ini - (r1GroupIni - computedR) * (r1Ini - branch.getPiModel().getMinR1()) / (r1GroupIni - r1GroupMin); - branch.getPiModel().setR1(updatedR); - return updatedR; - } else { - // Do Nothing - keep computed R1 - return branch.getPiModel().getR1(); + individualInitialR1 - (initialR1 - computedR1) * (individualInitialR1 - branch.getPiModel().getMinR1()) / (individualInitialR1 - minR1); + branch.getPiModel().setR1(updatedR1); } } /** - * freezes the transformer to its limit if the ratio of a group of parallel transformers is above the max - * (or below the min) of the group - * If stable mode is false, considers the max of the individual transformer. + * Freezes the transformer to its limit if the common ratio of transformers of the same shared control is above the max + * (or below the min) of the group. * @return true if the transformer has been frozen and false it voltage control remains disabled */ - public boolean freezeIfGroupAtBounds(LfBranch transfo) { - if (transfo.isVoltageControlEnabled() && !transfo.isDisabled()) { + public boolean freezeAtExtremeTapPosition(LfBranch branch) { + if (branch.isVoltageControlEnabled() && !branch.isDisabled()) { // round the rho shift to the closest tap - PiModel piModel = transfo.getPiModel(); + PiModel piModel = branch.getPiModel(); double r1 = piModel.getR1(); - TransformerRatioManager.TransfoRatioInfo transfoRatioInfo = getInfo(transfo); - double r1GroupMin = transfoRatioInfo.groupeInfo().rMin(); - double r1GroupMax = transfoRatioInfo.groupeInfo().rMax(); - if (r1 < r1GroupMin || r1 > r1GroupMax) { - LOGGER.info("Transformer " + transfo.getId() + " tap frozen"); - piModel.setR1(r1 > r1GroupMax ? r1GroupMax : r1GroupMin); + SharedControl sharedControl = sharedControlByBranchId.get(branch.getId()).getRight(); + double minR1 = sharedControl.minR1(); + double maxR1 = sharedControl.maxR1(); + if (r1 < minR1 || r1 > maxR1) { + LOGGER.info("Transformer {} with voltage control frozen: rounded at extreme tap position", branch.getId()); + piModel.setR1(r1 > maxR1 ? maxR1 : minR1); piModel.roundR1ToClosestTap(); - transfo.setVoltageControlEnabled(false); + branch.setVoltageControlEnabled(false); return true; } } From ce4897f080f81c681fa10af3e8c14ef22daec61e Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Thu, 20 Jun 2024 18:35:57 +0200 Subject: [PATCH 22/30] Fix rewriting. Signed-off-by: Anne Tilloy --- .../ac/outerloop/tap/TransformerRatioManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java index 1717affadd..06b42d35eb 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java @@ -107,9 +107,9 @@ public void updateContinuousRatio(LfBranch branch) { double initialR1 = sharedControl.initialR1(); double computedR1 = branch.getPiModel().getR1(); // equations provide the same R1 for all branches double updatedR1 = computedR1 >= initialR1 ? - individualInitialR1 + (computedR1 - initialR1) * (branch.getPiModel().getMaxR1() - individualInitialR1) / (maxR1 - individualInitialR1) + individualInitialR1 + (computedR1 - initialR1) * (branch.getPiModel().getMaxR1() - individualInitialR1) / (maxR1 - initialR1) : - individualInitialR1 - (initialR1 - computedR1) * (individualInitialR1 - branch.getPiModel().getMinR1()) / (individualInitialR1 - minR1); + individualInitialR1 - (initialR1 - computedR1) * (individualInitialR1 - branch.getPiModel().getMinR1()) / (initialR1 - minR1); branch.getPiModel().setR1(updatedR1); } } From 17f103448e395323b73b6864a4c56c7fa93d218c Mon Sep 17 00:00:00 2001 From: Didier Vidal Date: Fri, 21 Jun 2024 12:12:28 +0200 Subject: [PATCH 23/30] review remark on naming consistency Signed-off-by: Didier Vidal --- .../outerloop/tap/GeneratorVoltageControlManager.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java index 374368d40c..b7d04f7559 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java @@ -26,19 +26,19 @@ public class GeneratorVoltageControlManager { private final List disabledControllerBuses = new ArrayList<>(); public GeneratorVoltageControlManager(LfNetwork network, double limitOverride) { - this.minNominalVoltageLimit = limitOverride < 0 ? calculateMaxControlledNominalVoltage(network) : limitOverride; + this.minNominalVoltageLimit = limitOverride < 0 ? computeDefaultMinNominalVoltageLimit(network) : limitOverride; } - private static double calculateMaxControlledNominalVoltage(LfNetwork network) { - double maxControlledNominalVoltage = Double.MIN_VALUE; + private static double computeDefaultMinNominalVoltageLimit(LfNetwork network) { + double defaultMinNominalVoltage = Double.MIN_VALUE; for (LfBus bus : network.getBuses()) { if (!bus.isDisabled() && bus.isTransformerVoltageControlled() && isTransformerVoltageControlsValidForMaxControlledNominalVoltageCalculation(bus.getTransformerVoltageControl().orElse(null))) { - maxControlledNominalVoltage = Math.max(maxControlledNominalVoltage, bus.getNominalV()); + defaultMinNominalVoltage = Math.max(defaultMinNominalVoltage, bus.getNominalV()); } } - return maxControlledNominalVoltage; + return defaultMinNominalVoltage; } private static boolean isTransformerVoltageControlsValidForMaxControlledNominalVoltageCalculation(TransformerVoltageControl transformerVoltageControl) { From 9dcf65191ec43f77a37e393164f30998b21e4d4a Mon Sep 17 00:00:00 2001 From: Didier Vidal Date: Fri, 21 Jun 2024 12:27:49 +0200 Subject: [PATCH 24/30] protect class against unanticipated usages Signed-off-by: Didier Vidal --- .../ac/outerloop/tap/GeneratorVoltageControlManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java index b7d04f7559..b5682440dd 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java @@ -60,6 +60,8 @@ private static boolean isTransformerVoltageControlsValidForMaxControlledNominalV * Disables the voltage control of generators if controlled bus nominal voltage is under the limit. */ public void disableGeneratorVoltageControlsUnderMaxControlledNominalVoltage(LfNetwork network) { + disabledControllerBuses.clear(); // (in case someone wants to call this multiple time in instance lifecycle + // although this class as not designed nor tested with this use case in mind) for (LfBus bus : network.getControlledBuses(VoltageControl.Type.GENERATOR)) { if (bus.getNominalV() < minNominalVoltageLimit) { var voltageControl = bus.getGeneratorVoltageControl().orElseThrow(); From a64509278eba564398351cf564d0da36258c0663 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Fri, 21 Jun 2024 13:28:29 +0200 Subject: [PATCH 25/30] Fix parameter name. Signed-off-by: Anne Tilloy --- .../com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java | 4 ++-- .../ac/outerloop/tap/TransformerRatioManager.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java b/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java index cad918cdbe..a18c41551e 100644 --- a/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java +++ b/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java @@ -56,14 +56,14 @@ protected static Optional createMonitoringVoltageOuterLoop(OpenLoad } protected static Optional createTransformerVoltageControlOuterLoop(LoadFlowParameters parameters, - boolean useInitialTapePosition, + boolean useInitialTapPosition, OpenLoadFlowParameters.TransformerVoltageControlMode controlMode, int incrementalTransformerVoltageControlOuterLoopMaxTapShift, double generatorVoltageControlMinNominalVoltage) { if (parameters.isTransformerVoltageControlOn()) { AcOuterLoop outerLoop = switch (controlMode) { case WITH_GENERATOR_VOLTAGE_CONTROL -> new SimpleTransformerVoltageControlOuterLoop(); - case AFTER_GENERATOR_VOLTAGE_CONTROL -> new TransformerVoltageControlOuterLoop(useInitialTapePosition, generatorVoltageControlMinNominalVoltage); + case AFTER_GENERATOR_VOLTAGE_CONTROL -> new TransformerVoltageControlOuterLoop(useInitialTapPosition, generatorVoltageControlMinNominalVoltage); case INCREMENTAL_VOLTAGE_CONTROL -> new IncrementalTransformerVoltageControlOuterLoop(incrementalTransformerVoltageControlOuterLoopMaxTapShift); }; return Optional.of(outerLoop); diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java index 06b42d35eb..a602a8a705 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java @@ -91,12 +91,12 @@ public TransformerRatioManager(LfNetwork network, boolean useInitialTapPosition) } /** - * If 'useInitialTapePosition' is true, for transformers of the same control, we try to keep the initial difference + * If 'useInitialTapPosition' is true, for transformers of the same control, we try to keep the initial difference * between individual ratios. This algorithm maintains the individual tap positions if the voltage is correct with initial * state. It can also be seen as an approximate simulation of transformers acting with independent automation systems. * Assumes that all transformers of the same control have the same ratio (should be maintained by * ACEquationSystemCreator.createR1DistributionEquations). - * If 'useInitialTapePosition' is false, the transformer is not modified and keeps its computed R1. + * If 'useInitialTapPosition' is false, the transformer is not modified and keeps its computed R1. */ public void updateContinuousRatio(LfBranch branch) { if (useInitialTapPosition) { From 650d43617a64472c859df3c48f3495d8595cdf90 Mon Sep 17 00:00:00 2001 From: Didier Vidal Date: Fri, 21 Jun 2024 14:36:52 +0200 Subject: [PATCH 26/30] code review - improve criteria to detect group behind VHV transformer(s) Signed-off-by: Didier Vidal --- .../tap/GeneratorVoltageControlManager.java | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java index b5682440dd..b0bec57fd3 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java @@ -34,14 +34,14 @@ private static double computeDefaultMinNominalVoltageLimit(LfNetwork network) { for (LfBus bus : network.getBuses()) { if (!bus.isDisabled() && bus.isTransformerVoltageControlled() - && isTransformerVoltageControlsValidForMaxControlledNominalVoltageCalculation(bus.getTransformerVoltageControl().orElse(null))) { + && isVoltageControllingTransformerChangingVoltageLevel(bus.getTransformerVoltageControl().orElse(null))) { defaultMinNominalVoltage = Math.max(defaultMinNominalVoltage, bus.getNominalV()); } } return defaultMinNominalVoltage; } - private static boolean isTransformerVoltageControlsValidForMaxControlledNominalVoltageCalculation(TransformerVoltageControl transformerVoltageControl) { + private static boolean isVoltageControllingTransformerChangingVoltageLevel(TransformerVoltageControl transformerVoltageControl) { // are removed from this automatic algorithm the transformer voltage control that are between two nominal // voltages equivalents. if (transformerVoltageControl != null) { @@ -87,18 +87,31 @@ public void enableGeneratorVoltageControlsUnderMaxControlledNominalVoltage() { } private boolean isBusBehindVeryHighVoltageTransfo(LfBus bus, double limit) { - if (bus.getBranches().size() != 1) { - return false; - } - LfBranch b = bus.getBranches().get(0); - if (!b.isConnectedAtBothSides()) { + // The criteria detects the following cases at this point + // The bus is connected to a VSC station + // or + // the bus is connected to a generator and to transfomers that all step up to a tension above nominal voltage + // + + if (bus.getGenerators().isEmpty()) { return false; } + // Always keep VSC stations if (bus.getGenerators().stream().anyMatch(LfVscConverterStation.class::isInstance)) { return true; } - return Math.max(b.getBus1().getNominalV(), b.getBus2().getNominalV()) >= limit; + double startingNominalVoltage = bus.getNominalV(); + + double minConnectedVoltageLevel = bus.getBranches().stream() + .filter(b -> b.isConnectedAtBothSides()) + .mapToDouble(b -> Math.max(b.getBus1().getNominalV(), b.getBus2().getNominalV())) + .min() + .orElse(-1); + + // ALl branches should be step up transformers arriving to a voltage higher than limit + return minConnectedVoltageLevel > startingNominalVoltage && minConnectedVoltageLevel > limit; + } } From 61e8a8397ac311338db21beb390d4f5dc9b23fd4 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Fri, 21 Jun 2024 13:28:29 +0200 Subject: [PATCH 27/30] Fix parameter name. Signed-off-by: Anne Tilloy Signed-off-by: Didier Vidal --- .../com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java | 4 ++-- .../ac/outerloop/tap/TransformerRatioManager.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java b/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java index cad918cdbe..a18c41551e 100644 --- a/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java +++ b/src/main/java/com/powsybl/openloadflow/AbstractAcOuterLoopConfig.java @@ -56,14 +56,14 @@ protected static Optional createMonitoringVoltageOuterLoop(OpenLoad } protected static Optional createTransformerVoltageControlOuterLoop(LoadFlowParameters parameters, - boolean useInitialTapePosition, + boolean useInitialTapPosition, OpenLoadFlowParameters.TransformerVoltageControlMode controlMode, int incrementalTransformerVoltageControlOuterLoopMaxTapShift, double generatorVoltageControlMinNominalVoltage) { if (parameters.isTransformerVoltageControlOn()) { AcOuterLoop outerLoop = switch (controlMode) { case WITH_GENERATOR_VOLTAGE_CONTROL -> new SimpleTransformerVoltageControlOuterLoop(); - case AFTER_GENERATOR_VOLTAGE_CONTROL -> new TransformerVoltageControlOuterLoop(useInitialTapePosition, generatorVoltageControlMinNominalVoltage); + case AFTER_GENERATOR_VOLTAGE_CONTROL -> new TransformerVoltageControlOuterLoop(useInitialTapPosition, generatorVoltageControlMinNominalVoltage); case INCREMENTAL_VOLTAGE_CONTROL -> new IncrementalTransformerVoltageControlOuterLoop(incrementalTransformerVoltageControlOuterLoopMaxTapShift); }; return Optional.of(outerLoop); diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java index 06b42d35eb..a602a8a705 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java @@ -91,12 +91,12 @@ public TransformerRatioManager(LfNetwork network, boolean useInitialTapPosition) } /** - * If 'useInitialTapePosition' is true, for transformers of the same control, we try to keep the initial difference + * If 'useInitialTapPosition' is true, for transformers of the same control, we try to keep the initial difference * between individual ratios. This algorithm maintains the individual tap positions if the voltage is correct with initial * state. It can also be seen as an approximate simulation of transformers acting with independent automation systems. * Assumes that all transformers of the same control have the same ratio (should be maintained by * ACEquationSystemCreator.createR1DistributionEquations). - * If 'useInitialTapePosition' is false, the transformer is not modified and keeps its computed R1. + * If 'useInitialTapPosition' is false, the transformer is not modified and keeps its computed R1. */ public void updateContinuousRatio(LfBranch branch) { if (useInitialTapPosition) { From b5e623aecc0ba6b9197006af5a13f0defe25d2c8 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Fri, 21 Jun 2024 15:47:22 +0200 Subject: [PATCH 28/30] Add documentation + add load tap changing capabilities in criteria. Signed-off-by: Anne Tilloy --- docs/loadflow/parameters.md | 16 ++++++++ .../tap/GeneratorVoltageControlManager.java | 38 +++++++++---------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/docs/loadflow/parameters.md b/docs/loadflow/parameters.md index 39643a2c53..c5235cabd7 100644 --- a/docs/loadflow/parameters.md +++ b/docs/loadflow/parameters.md @@ -386,6 +386,22 @@ If the user specifies only a sub-list of priorities, this sub-list is completed order defined by default. Thus, if the user specifies only `["TRANSFORMER"]`, it will be completed to `["TRANSFORMER", "GENERATOR", "SHUNT"]`. +**transformerVoltageControlUseInitialTapPosition** +This parameter is only used if the transformer voltage control is enabled and of mode `AFTER_GENERATOR_VOLTAGE_CONTROL`. +If this parameter is set to `true`, transformers of the same voltage control (meaning controlling the same bus) are merged +and the algorithm tries to maintain the initial difference between rhos. If the voltage at controlled bus is closed to the +target voltage at initial step of the outer loop, the algorithm blocks transformers at their initial tap positions. +The default value of this parameter is `false`. + +**generatorVoltageControlMinNominalVoltage** +This parameter is only used if the transformer voltage control is enabled and of mode `AFTER_GENERATOR_VOLTAGE_CONTROL`. +In this mode, at the first step of the outer loop, the transformers that controlled voltage are disabled, only generators +are participating to voltage control. At second step, generators controlling voltage at a controlled bus above +`generatorVoltageControlMinNominalVoltage` have their voltage control disabled. This parameter overrides an automatic +detection of the minimal nominal voltage based on an analysis of nominal voltages controlled by transformers. The default +value of this parameter is $-1$: with this value the parameter is ignored and the outer loop relies only on the automatic +detection. + ## Configuration file example See below an extract of a config file that could help: diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java index b0bec57fd3..03344e5e20 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java @@ -34,14 +34,14 @@ private static double computeDefaultMinNominalVoltageLimit(LfNetwork network) { for (LfBus bus : network.getBuses()) { if (!bus.isDisabled() && bus.isTransformerVoltageControlled() - && isVoltageControllingTransformerChangingVoltageLevel(bus.getTransformerVoltageControl().orElse(null))) { + && isTransformerVoltageControlsValidForMaxControlledNominalVoltageCalculation(bus.getTransformerVoltageControl().orElse(null))) { defaultMinNominalVoltage = Math.max(defaultMinNominalVoltage, bus.getNominalV()); } } return defaultMinNominalVoltage; } - private static boolean isVoltageControllingTransformerChangingVoltageLevel(TransformerVoltageControl transformerVoltageControl) { + private static boolean isTransformerVoltageControlsValidForMaxControlledNominalVoltageCalculation(TransformerVoltageControl transformerVoltageControl) { // are removed from this automatic algorithm the transformer voltage control that are between two nominal // voltages equivalents. if (transformerVoltageControl != null) { @@ -60,13 +60,14 @@ private static boolean isVoltageControllingTransformerChangingVoltageLevel(Trans * Disables the voltage control of generators if controlled bus nominal voltage is under the limit. */ public void disableGeneratorVoltageControlsUnderMaxControlledNominalVoltage(LfNetwork network) { - disabledControllerBuses.clear(); // (in case someone wants to call this multiple time in instance lifecycle - // although this class as not designed nor tested with this use case in mind) + // Clear in case someone wants to call this multiple time in instance lifecycle + // although this class as not designed nor tested with this use case in mind. + disabledControllerBuses.clear(); for (LfBus bus : network.getControlledBuses(VoltageControl.Type.GENERATOR)) { if (bus.getNominalV() < minNominalVoltageLimit) { var voltageControl = bus.getGeneratorVoltageControl().orElseThrow(); for (LfBus controllerBus : voltageControl.getMergedControllerElements()) { - if (controllerBus.isGeneratorVoltageControlEnabled() && !isBusBehindVeryHighVoltageTransfo(controllerBus, minNominalVoltageLimit)) { + if (controllerBus.isGeneratorVoltageControlEnabled() && !hasStepUpTransformers(controllerBus, minNominalVoltageLimit)) { controllerBus.setGenerationTargetQ(controllerBus.getQ().eval()); controllerBus.setGeneratorVoltageControlEnabled(false); disabledControllerBuses.add(controllerBus); @@ -86,32 +87,27 @@ public void enableGeneratorVoltageControlsUnderMaxControlledNominalVoltage() { } } - private boolean isBusBehindVeryHighVoltageTransfo(LfBus bus, double limit) { - // The criteria detects the following cases at this point - // The bus is connected to a VSC station - // or - // the bus is connected to a generator and to transfomers that all step up to a tension above nominal voltage - // - - if (bus.getGenerators().isEmpty()) { - return false; - } - - // Always keep VSC stations + /** + * True if a controller bus: + * - has a VSC converter station; + * - has step-up transformers converting voltage to a bus with nominal voltage higher than the voltage limit. A step-up + * transformer has no tap changing capabilities. + */ + private boolean hasStepUpTransformers(LfBus bus, double limit) { if (bus.getGenerators().stream().anyMatch(LfVscConverterStation.class::isInstance)) { return true; } + if (bus.getBranches().stream().anyMatch(b -> b.getVoltageControl().isPresent())) { + return false; + } double startingNominalVoltage = bus.getNominalV(); - double minConnectedVoltageLevel = bus.getBranches().stream() .filter(b -> b.isConnectedAtBothSides()) .mapToDouble(b -> Math.max(b.getBus1().getNominalV(), b.getBus2().getNominalV())) .min() .orElse(-1); - - // ALl branches should be step up transformers arriving to a voltage higher than limit + // All branches should be step-up transformers arriving to a voltage higher than limit return minConnectedVoltageLevel > startingNominalVoltage && minConnectedVoltageLevel > limit; - } } From ca2c7bfedcfd80c914ab0b50974fde83f6e7e9cb Mon Sep 17 00:00:00 2001 From: Didier Vidal Date: Fri, 28 Jun 2024 15:12:09 +0200 Subject: [PATCH 29/30] fix regression Signed-off-by: Didier Vidal --- .../ac/outerloop/tap/GeneratorVoltageControlManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java index 03344e5e20..e5e10a82a0 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/GeneratorVoltageControlManager.java @@ -64,7 +64,7 @@ public void disableGeneratorVoltageControlsUnderMaxControlledNominalVoltage(LfNe // although this class as not designed nor tested with this use case in mind. disabledControllerBuses.clear(); for (LfBus bus : network.getControlledBuses(VoltageControl.Type.GENERATOR)) { - if (bus.getNominalV() < minNominalVoltageLimit) { + if (bus.getNominalV() <= minNominalVoltageLimit) { var voltageControl = bus.getGeneratorVoltageControl().orElseThrow(); for (LfBus controllerBus : voltageControl.getMergedControllerElements()) { if (controllerBus.isGeneratorVoltageControlEnabled() && !hasStepUpTransformers(controllerBus, minNominalVoltageLimit)) { From 5323f520f182edb412634141a1e86bf37772b6d9 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 2 Jul 2024 09:45:31 +0200 Subject: [PATCH 30/30] Change method name. Signed-off-by: Anne Tilloy --- .../ac/outerloop/TransformerVoltageControlOuterLoop.java | 2 +- .../ac/outerloop/tap/TransformerRatioManager.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java index 8cede2b1d5..42c069e97d 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/TransformerVoltageControlOuterLoop.java @@ -125,7 +125,7 @@ private OuterLoopResult controlStep(LfNetwork network, ContextData contextData) boolean outOfBoundTap = false; for (LfBranch controllerBranch : network.getControllerElements(VoltageControl.Type.TRANSFORMER)) { - if (contextData.transformerRatioManager.freezeAtExtremeTapPosition(controllerBranch)) { + if (contextData.transformerRatioManager.roundR1ToExtremeTapPosition(controllerBranch)) { outOfBoundTap = true; } } diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java index a602a8a705..2884464bdf 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/tap/TransformerRatioManager.java @@ -115,11 +115,11 @@ public void updateContinuousRatio(LfBranch branch) { } /** - * Freezes the transformer to its limit if the common ratio of transformers of the same shared control is above the max + * Rounds the transformer at min or max tap position if the ratio of transformers of the same shared control is above the max * (or below the min) of the group. * @return true if the transformer has been frozen and false it voltage control remains disabled */ - public boolean freezeAtExtremeTapPosition(LfBranch branch) { + public boolean roundR1ToExtremeTapPosition(LfBranch branch) { if (branch.isVoltageControlEnabled() && !branch.isDisabled()) { // round the rho shift to the closest tap PiModel piModel = branch.getPiModel();