Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check too far generator voltage remote control #1119

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7dbba4b
Added check
SylvestreSakti Nov 7, 2024
18db0ad
Added test
SylvestreSakti Nov 8, 2024
04fd630
BusDistance modification
SylvestreSakti Nov 8, 2024
1b61b80
Added parameter
SylvestreSakti Nov 8, 2024
ecacea0
Simplified BusDistance algorithm
SylvestreSakti Nov 8, 2024
37bc4c6
Modified tests for parameters
SylvestreSakti Nov 8, 2024
3fede3d
Modified tests and parameters
SylvestreSakti Nov 8, 2024
936cc66
Modified algorithm to avoid too long for loop
SylvestreSakti Nov 8, 2024
df97ff4
Modified parameters and tests
SylvestreSakti Nov 8, 2024
d4e082d
Clean code
SylvestreSakti Nov 8, 2024
084eccb
Typo
SylvestreSakti Nov 8, 2024
0625c7d
Added documentation
SylvestreSakti Nov 8, 2024
73ff722
Switched remote voltage control to voltage remote control
SylvestreSakti Nov 8, 2024
f1ea70b
typo
SylvestreSakti Nov 8, 2024
60ad03a
Modified test report
SylvestreSakti Nov 8, 2024
8553815
Added handling of null buses in BusDistance
SylvestreSakti Nov 15, 2024
e6ba659
Added tests and changed parameter default value and checking
SylvestreSakti Nov 25, 2024
cd3e1c0
Tests update
SylvestreSakti Nov 25, 2024
f0a45dc
Modified log message
SylvestreSakti Nov 25, 2024
8247d88
Merge branch 'main' into check_too_far_voltage_remote_control
SylvestreSakti Nov 25, 2024
fbbf0ed
remove public
SylvestreSakti Nov 25, 2024
1f1141d
Corrections from review
SylvestreSakti Nov 27, 2024
bc4bb8c
Added assertVoltageEquals in tests
SylvestreSakti Dec 3, 2024
68e2d10
Added more assertVoltageEquals and commenting expected values
SylvestreSakti Dec 3, 2024
6e566fd
Changed parameter name to maxGeneratorVoltageRemoteControl
SylvestreSakti Dec 3, 2024
9c8c5b2
small doc fix
SylvestreSakti Dec 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/loadflow/parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ If set to false, any existing voltage remote control is converted to a local con
according to the nominal voltage ratio between the remote regulated bus and the equipment terminal bus.
The default value is `true`.

**maxVoltageRemoteControlDistance**
Defines the maximum distance allowed between the remote regulated bus and the voltage controller (requires `voltageRemoteControl` to be set to `true`).
This distance is measured in number of branches separating the two buses. If the distance is higher than this parameter, then the voltage remote control is converted to a local control, rescaling the target voltage according to the nominal voltage ratio between the remote regulated bus and the equipment terminal bus.
If `maxVoltageRemoteControlDistance` is set to `0` (or a negative value), there is no distance checking.
The default value is `2`.

SylvestreSakti marked this conversation as resolved.
Show resolved Hide resolved
**voltagePerReactivePowerControl**
Whether simulation of static VAR compensators with voltage control enabled and a slope defined should be enabled
(See [voltage per reactive power control extension](inv:powsyblcore:*:*:#voltage-per-reactive-power-control-extension)).
Expand Down
31 changes: 26 additions & 5 deletions src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ public enum FictitiousGeneratorVoltageControlCheckMode {

public static final String AREA_INTERCHANGE_P_MAX_MISMATCH_PARAM_NAME = "areaInterchangePMaxMismatch";

public static final String MAX_VOLTAGE_REMOTE_CONTROL_DISTANCE_PARAM_NAME = "maxVoltageRemoteControlDistance";

public static <E extends Enum<E>> List<Object> getEnumPossibleValues(Class<E> enumClass) {
return EnumSet.allOf(enumClass).stream().map(Enum::name).collect(Collectors.toList());
}
Expand Down Expand Up @@ -413,7 +415,8 @@ public static <E extends Enum<E>> List<Object> getEnumPossibleValues(Class<E> en
new Parameter(FICTITIOUS_GENERATOR_VOLTAGE_CONTROL_CHECK_MODE, ParameterType.STRING, "Specifies fictitious generators active power checks exemption for voltage control", OpenLoadFlowParameters.FICTITIOUS_GENERATOR_VOLTAGE_CONTROL_CHECK_MODE_DEFAULT_VALUE.name(), getEnumPossibleValues(FictitiousGeneratorVoltageControlCheckMode.class), ParameterScope.FUNCTIONAL, GENERATOR_VOLTAGE_CONTROL_CATEGORY_KEY),
new Parameter(AREA_INTERCHANGE_CONTROL_PARAM_NAME, ParameterType.BOOLEAN, "Area interchange control", AREA_INTERCHANGE_CONTROL_DEFAULT_VALUE, ParameterScope.FUNCTIONAL, SLACK_DISTRIBUTION_CATEGORY_KEY),
new Parameter(AREA_INTERCHANGE_CONTROL_AREA_TYPE_PARAM_NAME, ParameterType.STRING, "Area type for area interchange control", LfNetworkParameters.AREA_INTERCHANGE_CONTROL_AREA_TYPE_DEFAULT_VALUE, ParameterScope.FUNCTIONAL, SLACK_DISTRIBUTION_CATEGORY_KEY),
new Parameter(AREA_INTERCHANGE_P_MAX_MISMATCH_PARAM_NAME, ParameterType.DOUBLE, "Area interchange max active power mismatch", AREA_INTERCHANGE_P_MAX_MISMATCH_DEFAULT_VALUE, ParameterScope.FUNCTIONAL, SLACK_DISTRIBUTION_CATEGORY_KEY)
new Parameter(AREA_INTERCHANGE_P_MAX_MISMATCH_PARAM_NAME, ParameterType.DOUBLE, "Area interchange max active power mismatch", AREA_INTERCHANGE_P_MAX_MISMATCH_DEFAULT_VALUE, ParameterScope.FUNCTIONAL, SLACK_DISTRIBUTION_CATEGORY_KEY),
new Parameter(MAX_VOLTAGE_REMOTE_CONTROL_DISTANCE_PARAM_NAME, ParameterType.INTEGER, "Maximum voltage remote control distance", LfNetworkParameters.MAX_VOLTAGE_REMOTE_CONTROL_DISTANCE_DEFAULT_VALUE, ParameterScope.FUNCTIONAL, GENERATOR_VOLTAGE_CONTROL_CATEGORY_KEY)
);

public enum VoltageInitModeOverride {
Expand Down Expand Up @@ -597,6 +600,8 @@ public enum ReactiveRangeCheckMode {

private double areaInterchangePMaxMismatch = AREA_INTERCHANGE_P_MAX_MISMATCH_DEFAULT_VALUE;

private int maxVoltageRemoteControlDistance = LfNetworkParameters.MAX_VOLTAGE_REMOTE_CONTROL_DISTANCE_DEFAULT_VALUE;

public static double checkParameterValue(double parameterValue, boolean condition, String parameterName) {
if (!condition) {
throw new IllegalArgumentException("Invalid value for parameter " + parameterName + ": " + parameterValue);
Expand Down Expand Up @@ -1322,6 +1327,15 @@ public OpenLoadFlowParameters setAreaInterchangePMaxMismatch(double areaIntercha
return this;
}

public int getMaxVoltageRemoteControlDistance() {
return maxVoltageRemoteControlDistance;
}

public OpenLoadFlowParameters setMaxVoltageRemoteControlDistance(int maxVoltageRemoteControlDistance) {
this.maxVoltageRemoteControlDistance = maxVoltageRemoteControlDistance;
return this;
}

public static OpenLoadFlowParameters load() {
return load(PlatformConfig.defaultConfig());
}
Expand Down Expand Up @@ -1400,7 +1414,8 @@ public static OpenLoadFlowParameters load(PlatformConfig platformConfig) {
.setGeneratorVoltageControlMinNominalVoltage(config.getDoubleProperty(GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_PARAM_NAME, GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_DEFAULT_VALUE))
.setAreaInterchangeControl(config.getBooleanProperty(AREA_INTERCHANGE_CONTROL_PARAM_NAME, AREA_INTERCHANGE_CONTROL_DEFAULT_VALUE))
.setAreaInterchangeControlAreaType(config.getStringProperty(AREA_INTERCHANGE_CONTROL_AREA_TYPE_PARAM_NAME, LfNetworkParameters.AREA_INTERCHANGE_CONTROL_AREA_TYPE_DEFAULT_VALUE))
.setAreaInterchangePMaxMismatch(config.getDoubleProperty(AREA_INTERCHANGE_P_MAX_MISMATCH_PARAM_NAME, AREA_INTERCHANGE_P_MAX_MISMATCH_DEFAULT_VALUE)));
.setAreaInterchangePMaxMismatch(config.getDoubleProperty(AREA_INTERCHANGE_P_MAX_MISMATCH_PARAM_NAME, AREA_INTERCHANGE_P_MAX_MISMATCH_DEFAULT_VALUE))
.setMaxVoltageRemoteControlDistance(config.getIntProperty(MAX_VOLTAGE_REMOTE_CONTROL_DISTANCE_PARAM_NAME, LfNetworkParameters.MAX_VOLTAGE_REMOTE_CONTROL_DISTANCE_DEFAULT_VALUE)));
return parameters;
}

Expand Down Expand Up @@ -1561,6 +1576,8 @@ public OpenLoadFlowParameters update(Map<String, String> properties) {
.ifPresent(this::setAreaInterchangeControlAreaType);
Optional.ofNullable(properties.get(AREA_INTERCHANGE_P_MAX_MISMATCH_PARAM_NAME))
.ifPresent(prop -> this.setAreaInterchangePMaxMismatch(Double.parseDouble(prop)));
Optional.ofNullable(properties.get(MAX_VOLTAGE_REMOTE_CONTROL_DISTANCE_PARAM_NAME))
.ifPresent(prop -> this.setMaxVoltageRemoteControlDistance(Integer.parseInt(prop)));
return this;
}

Expand Down Expand Up @@ -1637,6 +1654,7 @@ public Map<String, Object> toMap() {
map.put(AREA_INTERCHANGE_CONTROL_PARAM_NAME, areaInterchangeControl);
map.put(AREA_INTERCHANGE_CONTROL_AREA_TYPE_PARAM_NAME, areaInterchangeControlAreaType);
map.put(AREA_INTERCHANGE_P_MAX_MISMATCH_PARAM_NAME, areaInterchangePMaxMismatch);
map.put(MAX_VOLTAGE_REMOTE_CONTROL_DISTANCE_PARAM_NAME, maxVoltageRemoteControlDistance);
return map;
}

Expand Down Expand Up @@ -1793,7 +1811,8 @@ static LfNetworkParameters getNetworkParameters(LoadFlowParameters parameters, O
.setVoltageTargetPriorities(parametersExt.getVoltageTargetPriorities())
.setFictitiousGeneratorVoltageControlCheckMode(parametersExt.getFictitiousGeneratorVoltageControlCheckMode())
.setAreaInterchangeControl(parametersExt.isAreaInterchangeControl())
.setAreaInterchangeControlAreaType(parametersExt.getAreaInterchangeControlAreaType());
.setAreaInterchangeControlAreaType(parametersExt.getAreaInterchangeControlAreaType())
.setMaxVoltageRemoteControlDistance(parametersExt.getMaxVoltageRemoteControlDistance());
}

public static AcLoadFlowParameters createAcParameters(Network network, LoadFlowParameters parameters, OpenLoadFlowParameters parametersExt,
Expand Down Expand Up @@ -2046,7 +2065,8 @@ public static boolean equals(LoadFlowParameters parameters1, LoadFlowParameters
extension1.getFictitiousGeneratorVoltageControlCheckMode() == extension2.getFictitiousGeneratorVoltageControlCheckMode() &&
extension1.isAreaInterchangeControl() == extension2.isAreaInterchangeControl() &&
Objects.equals(extension1.getAreaInterchangeControlAreaType(), extension2.getAreaInterchangeControlAreaType()) &&
extension1.getAreaInterchangePMaxMismatch() == extension2.getAreaInterchangePMaxMismatch();
extension1.getAreaInterchangePMaxMismatch() == extension2.getAreaInterchangePMaxMismatch() &&
extension1.getMaxVoltageRemoteControlDistance() == extension2.getMaxVoltageRemoteControlDistance();
}

public static LoadFlowParameters clone(LoadFlowParameters parameters) {
Expand Down Expand Up @@ -2142,7 +2162,8 @@ public static LoadFlowParameters clone(LoadFlowParameters parameters) {
.setFictitiousGeneratorVoltageControlCheckMode(extension.getFictitiousGeneratorVoltageControlCheckMode())
.setAreaInterchangeControl(extension.isAreaInterchangeControl())
.setAreaInterchangeControlAreaType(extension.getAreaInterchangeControlAreaType())
.setAreaInterchangePMaxMismatch(extension.getAreaInterchangePMaxMismatch());
.setAreaInterchangePMaxMismatch(extension.getAreaInterchangePMaxMismatch())
.setMaxVoltageRemoteControlDistance(extension.getMaxVoltageRemoteControlDistance());

if (extension2 != null) {
parameters2.addExtension(OpenLoadFlowParameters.class, extension2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ public class LfNetworkParameters {

public static final String AREA_INTERCHANGE_CONTROL_AREA_TYPE_DEFAULT_VALUE = "ControlArea";

public static final int MAX_VOLTAGE_REMOTE_CONTROL_DISTANCE_DEFAULT_VALUE = 2;

private SlackBusSelector slackBusSelector = new FirstSlackBusSelector(SLACK_BUS_COUNTRY_FILTER_DEFAULT_VALUE);

private GraphConnectivityFactory<LfBus, LfBranch> connectivityFactory = new EvenShiloachGraphDecrementalConnectivityFactory<>();
Expand Down Expand Up @@ -148,6 +150,8 @@ public class LfNetworkParameters {

private String areaInterchangeControlAreaType = AREA_INTERCHANGE_CONTROL_AREA_TYPE_DEFAULT_VALUE;

private int maxVoltageRemoteControlDistance = MAX_VOLTAGE_REMOTE_CONTROL_DISTANCE_DEFAULT_VALUE;

public LfNetworkParameters() {
}

Expand Down Expand Up @@ -194,6 +198,7 @@ public LfNetworkParameters(LfNetworkParameters other) {
this.fictitiousGeneratorVoltageControlCheckMode = other.fictitiousGeneratorVoltageControlCheckMode;
this.areaInterchangeControl = other.areaInterchangeControl;
this.areaInterchangeControlAreaType = other.areaInterchangeControlAreaType;
this.maxVoltageRemoteControlDistance = other.maxVoltageRemoteControlDistance;
}

public SlackBusSelector getSlackBusSelector() {
Expand Down Expand Up @@ -597,6 +602,15 @@ public LfNetworkParameters setAreaInterchangeControlAreaType(String areaIntercha
return this;
}

public int getMaxVoltageRemoteControlDistance() {
return maxVoltageRemoteControlDistance;
}

public LfNetworkParameters setMaxVoltageRemoteControlDistance(int maxVoltageRemoteControlDistance) {
this.maxVoltageRemoteControlDistance = maxVoltageRemoteControlDistance;
return this;
}

@Override
public String toString() {
return "LfNetworkParameters(" +
Expand Down Expand Up @@ -638,6 +652,7 @@ public String toString() {
", fictitiousGeneratorVoltageControlCheckMode=" + fictitiousGeneratorVoltageControlCheckMode +
", areaInterchangeControl=" + areaInterchangeControl +
", areaInterchangeControlAreaType=" + areaInterchangeControlAreaType +
", maxVoltageRemoteControlDistance=" + maxVoltageRemoteControlDistance +
')';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.powsybl.openloadflow.util.BusDistance.distanceBetweenBuses;
import static com.powsybl.openloadflow.util.DebugUtil.DATE_TIME_FORMAT;
import static com.powsybl.openloadflow.util.Markers.PERFORMANCE_MARKER;

Expand Down Expand Up @@ -127,14 +128,24 @@ private static void createVoltageControls(List<LfBus> lfBuses, LfNetworkParamete
}
});

if (parameters.isGeneratorVoltageRemoteControl() || controlledBus == controllerBus) {
boolean keepVoltageRemoteControl = false;
if (!parameters.isGeneratorVoltageRemoteControl() && controlledBus != controllerBus) {
LOGGER.warn("Remote voltage control is not activated. The voltage target of {} with remote control is rescaled from {} to {}",
controllerBus.getId(), controllerTargetV, controllerTargetV * controllerBus.getNominalV() / controlledBus.getNominalV());
} else if (parameters.getMaxVoltageRemoteControlDistance() > 0 && distanceBetweenBuses(controlledBus, controllerBus, parameters.getMaxVoltageRemoteControlDistance()) > parameters.getMaxVoltageRemoteControlDistance()) {
LOGGER.warn("Voltage controlled bus '{}' is too far from controller bus '{}' (maximumVoltageRemoteControlDistance is set to {}). The bus switches to local voltage control and target voltage is rescaled from {} to {}",
controlledBus.getId(), controllerBus.getId(), parameters.getMaxVoltageRemoteControlDistance(), controllerTargetV, controllerTargetV * controllerBus.getNominalV() / controlledBus.getNominalV());
Reports.reportTooFarControlledBus(controlledBus.getNetwork().getReportNode(), controllerBus.getId(), controlledBus.getId(), parameters.getMaxVoltageRemoteControlDistance());
} else {
keepVoltageRemoteControl = true;
}

if (keepVoltageRemoteControl) {
controlledBus.getGeneratorVoltageControl().ifPresentOrElse(
vc -> updateGeneratorVoltageControl(vc, controllerBus, controllerTargetV),
() -> createGeneratorVoltageControl(controlledBus, controllerBus, controllerTargetV, voltageControls, parameters));
} else {
// if voltage remote control deactivated and remote control, set local control instead
LOGGER.warn("Remote voltage control is not activated. The voltage target of {} with remote control is rescaled from {} to {}",
controllerBus.getId(), controllerTargetV, controllerTargetV * controllerBus.getNominalV() / controlledBus.getNominalV());
controlledBus.getGeneratorVoltageControl().ifPresentOrElse(
vc -> updateGeneratorVoltageControl(vc, controllerBus, controllerTargetV), // updating only to check targetV uniqueness
() -> createGeneratorVoltageControl(controllerBus, controllerBus, controllerTargetV, voltageControls, parameters));
Expand Down
57 changes: 57 additions & 0 deletions src/main/java/com/powsybl/openloadflow/util/BusDistance.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* 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.util;

import com.powsybl.openloadflow.network.LfBus;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @author Sylvestre Prabakaran {@literal <sylvestre.prabakaran at rte-france.com>}
*/
public final class BusDistance {

private BusDistance() {
}

/**
* Breadth first search algorithm to compute distance between two LfBus in a network
* @param bus1 first LfBus (from which the breadth first search starts)
SylvestreSakti marked this conversation as resolved.
Show resolved Hide resolved
* @param bus2 second LfBus (searched bus)
* @param maxDistanceSearch the algorithm searches until this range and stops after this limit (or if every bus have been checked)
* @return measured distance (number of branches) or Integer.MAX_VALUE if bus2 is not found
SylvestreSakti marked this conversation as resolved.
Show resolved Hide resolved
*/
public static int distanceBetweenBuses(LfBus bus1, LfBus bus2, int maxDistanceSearch) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an unusual way to implement a BFS. We can do it much simpler without these kind of set manipulation (busesToCheck.removeAll(checkedBuses)). Also we should take care for a BFS to have an orderer neighbors traversal (be careful with HashSets)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a unit test for the method with various cases (exected distance, farther than maxDistance etc..)

Copy link
Contributor Author

@SylvestreSakti SylvestreSakti Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an unusual way to implement a BFS. We can do it much simpler without these kind of set manipulation (busesToCheck.removeAll(checkedBuses)). Also we should take care for a BFS to have an orderer neighbors traversal (be careful with HashSets)

Reading again more conventional ways to implement breadth First Search (e.g. https://www.baeldung.com/java-breadth-first-search), I don't know (or I don't find) simpler ways to implement this. Here I chose this way of using sets for multiple reasons :

  • Instead of iterating over LfBus (in a classical Queue), I prefered to iterate over levels of distance to easily keep track of this growing distance which is the main output
  • This way of iterating goes well with the findNeighbors() method of LfBus that returns a map and its keySet listing all the neighbors

With this way of iteration (levels of distance) is it important to have an ordered neighbors traversal ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

Objects.requireNonNull(bus1);
Objects.requireNonNull(bus2);
if (bus1.equals(bus2)) {
return 0;
}
Set<LfBus> busesToCheck = new HashSet<>();
Set<LfBus> checkedBuses = new HashSet<>();
busesToCheck.add(bus1);
checkedBuses.add(bus1);
for (int distance = 1; distance <= maxDistanceSearch; distance++) {
busesToCheck = busesToCheck.stream()
.flatMap(bus -> bus.findNeighbors().keySet().stream())
.collect(Collectors.toSet());
busesToCheck.removeAll(checkedBuses);
if (busesToCheck.contains(bus2)) {
return distance;
} else if (busesToCheck.isEmpty()) {
return Integer.MAX_VALUE;
}
checkedBuses.addAll(busesToCheck);
}
return Integer.MAX_VALUE;
}
}
10 changes: 10 additions & 0 deletions src/main/java/com/powsybl/openloadflow/util/Reports.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ public static void reportNotUniqueControlledBus(ReportNode reportNode, String ge
.add();
}

public static void reportTooFarControlledBus(ReportNode reportNode, String controllerBusId, String controlledBusId, int maxVoltageRemoteControlDistance) {
reportNode.newReportNode()
.withMessageTemplate("tooFarControllerBus", "Remote voltage controlled bus ${controlledBusId} is too far from controller bus ${controllerBusId} (maxVoltageRemoteControlDistance is set to ${maxVoltageRemoteControlDistance}). Switching to local voltage control")
.withUntypedValue(CONTROLLED_BUS_ID, controlledBusId)
.withUntypedValue(CONTROLLER_BUS_ID, controllerBusId)
.withUntypedValue("maxVoltageRemoteControlDistance", maxVoltageRemoteControlDistance)
.withSeverity(TypedValue.WARN_SEVERITY)
.add();
SylvestreSakti marked this conversation as resolved.
Show resolved Hide resolved
}

public static void reportNotUniqueTargetVControllerBus(ReportNode reportNode, String generatorIds, String controllerBusId, Double keptTargetV, Double rejectedTargetV) {
reportNode.newReportNode()
.withMessageTemplate("notUniqueTargetVControllerBus", "Generators [${generatorIds}] are connected to the same bus ${controllerBusId} with different target voltages: ${keptTargetV} kV (kept) and ${rejectedTargetV} kV (rejected)")
Expand Down
Loading
Loading