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

Support of static var compensator with VoltagePerReactivePowerControl extension #304

Merged
merged 48 commits into from
Jun 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
89bd79a
Add voltage per reactive power control parameter.
annetill May 5, 2021
fd73a3b
Add slope in generator attributes.
annetill May 5, 2021
52a076d
Add GeneratorWithSlopeVoltageEquationTerm.
annetill May 6, 2021
d1a5910
Introduce new type of bus for equation.
annetill May 21, 2021
d796f3f
Merge.
annetill May 25, 2021
48dd622
Bug fix.
annetill May 25, 2021
9cc0707
Add unit tests.
annetill May 26, 2021
5b1c27f
Fix pom.xml.
annetill May 26, 2021
63fa182
Add a test with a generator at bus2 not controlling voltage
Hadrien-Godard May 27, 2021
911be17
Using already existing Terms instead of GeneratorWithSlopeVoltageEqua…
Hadrien-Godard May 31, 2021
3dcaa3f
Slightly modifying some test results
Hadrien-Godard May 31, 2021
465b397
Typo
Hadrien-Godard May 31, 2021
c177f03
Factorization and using of getGenerationTargetQ for initial targets o…
Hadrien-Godard Jun 2, 2021
3ac6154
Remove a custom print for debug
Hadrien-Godard Jun 2, 2021
13560db
Introduce method getGeneratorControllingVoltageWithSlope for LfBus.
annetill Jun 2, 2021
ebdfdfb
Clean code.
annetill Jun 3, 2021
74c622b
Merge.
annetill Jun 3, 2021
3ff6abb
Switching PQ to PV not supported.
annetill Jun 3, 2021
c9a5bd1
getGeneratorControllingVoltageWithSlope: lambda changes
flo-dup Jun 4, 2021
54591ba
Use distribution data.
annetill Jun 8, 2021
6e1f8ae
Add a test for SVC with slope PV -> PQ and blocked.
annetill Jun 8, 2021
9e17ff7
Merge branch 'master' into svc-slope
annetill Jun 8, 2021
0afe0bf
Fix check.
annetill Jun 8, 2021
e016a7a
Remove useless variable.
annetill Jun 8, 2021
7c16fb0
From nullable to Optional
flo-dup Jun 8, 2021
cc6cb07
Trying to correct bug without ruining the code clarity
flo-dup Jun 9, 2021
ff71ad0
Fix logback.
annetill Jun 9, 2021
e4bf470
Merge branch 'master' into svc-slope
annetill Jun 15, 2021
121a673
Disabling slope when loading if non supported case
flo-dup Jun 15, 2021
2b29386
Add setSlope to implementations
flo-dup Jun 15, 2021
e8af6f2
Quick fix for bug.
annetill Jun 15, 2021
612ab6c
Merge branch 'master' into svc-slope
annetill Jun 17, 2021
d8bfc47
check generators with slope once voltage controls are created
flo-dup Jun 17, 2021
a94f812
Checking slope only if voltagePerReactivePowerControl is enabled
flo-dup Jun 21, 2021
f4bf98c
Update unit test
flo-dup Jun 21, 2021
92dffda
VoltageControl::isVoltageControlLocal: Correct use and add doc
flo-dup Jun 21, 2021
bce9e12
LfBus::getGeneratorsControllingVoltageWithSlope returns a list
flo-dup Jun 21, 2021
e3144fc
Simpler LfNetworkLoaderImpl::checkGeneratorsWithSlope
flo-dup Jun 21, 2021
34a660c
Merge.
annetill Jun 22, 2021
e7db88d
Add a check to verify that the control is local.
annetill Jun 22, 2021
8800755
Set slope only if voltagePerReactivePowerControl true
flo-dup Jun 25, 2021
27a04d3
Clean code.
annetill Jun 28, 2021
2a2d28a
Remove useless changes.
annetill Jun 28, 2021
70ccc31
Performance: avoid always filtering out generators based on slope
flo-dup Jun 28, 2021
15ae6cc
Small refactor/renaming
flo-dup Jun 28, 2021
39021d8
fix
flo-dup Jun 28, 2021
df61d8e
Fix constructor.
annetill Jun 28, 2021
1e6b953
Clean.
annetill Jun 28, 2021
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
13 changes: 13 additions & 0 deletions src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public enum LowImpedanceBranchMode {

private double slackBusPMaxMismatch = SLACK_BUS_P_MAX_MISMATCH_DEFAULT_VALUE;

private boolean voltagePerReactivePowerControl = VOLTAGE_PER_REACTIVE_POWER_CONTROL_DEFAULT_VALUE;

@Override
public String getName() {
return "open-load-flow-parameters";
Expand Down Expand Up @@ -133,6 +135,15 @@ public OpenLoadFlowParameters setAddRatioToLinesWithDifferentNominalVoltageAtBot
return this;
}

public boolean isVoltagePerReactivePowerControl() {
return voltagePerReactivePowerControl;
}

public OpenLoadFlowParameters setVoltagePerReactivePowerControl(boolean voltagePerReactivePowerControl) {
this.voltagePerReactivePowerControl = voltagePerReactivePowerControl;
return this;
}

public static OpenLoadFlowParameters load() {
return new OpenLoadFlowConfigLoader().load(PlatformConfig.defaultConfig());
}
Expand All @@ -149,6 +160,7 @@ public String toString() {
", plausibleActivePowerLimit=" + plausibleActivePowerLimit +
", addRatioToLinesWithDifferentNominalVoltageAtBothEnds=" + addRatioToLinesWithDifferentNominalVoltageAtBothEnds +
", slackBusPMaxMismatch=" + slackBusPMaxMismatch +
", voltagePerReactivePowerControl=" + voltagePerReactivePowerControl +
')';
}

Expand All @@ -172,6 +184,7 @@ public OpenLoadFlowParameters load(PlatformConfig platformConfig) {
.setPlausibleActivePowerLimit(config.getDoubleProperty(PLAUSIBLE_ACTIVE_POWER_LIMIT_PARAM_NAME, PLAUSIBLE_ACTIVE_POWER_LIMIT_DEFAULT_VALUE))
.setAddRatioToLinesWithDifferentNominalVoltageAtBothEnds(config.getBooleanProperty(ADD_RATIO_TO_LINES_WITH_DIFFERENT_NOMINAL_VOLTAGE_AT_BOTH_ENDS_NAME, ADD_RATIO_TO_LINES_WITH_DIFFERENT_NOMINAL_VOLTAGE_AT_BOTH_ENDS_DEFAULT_VALUE))
.setSlackBusPMaxMismatch(config.getDoubleProperty(SLACK_BUS_P_MAX_MISMATCH_NAME, SLACK_BUS_P_MAX_MISMATCH_DEFAULT_VALUE))
.setVoltagePerReactivePowerControl(VOLTAGE_PER_REACTIVE_POWER_CONTROL_DEFAULT_VALUE)
);
return parameters;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ public static AcLoadFlowParameters createAcParameters(Network network, MatrixFac
LOGGER.info("Add ratio to lines with different nominal voltage at both ends: {}", parametersExt.isAddRatioToLinesWithDifferentNominalVoltageAtBothEnds());
LOGGER.info("Slack bus Pmax mismatch: {}", parametersExt.getSlackBusPMaxMismatch());
LOGGER.info("Connected component mode: {}", parameters.getConnectedComponentMode());
LOGGER.info("Voltage per reactive power control: {}", parametersExt.isVoltagePerReactivePowerControl());

List<OuterLoop> outerLoops = new ArrayList<>();
if (parameters.isDistributedSlack()) {
Expand Down Expand Up @@ -183,7 +184,8 @@ public static AcLoadFlowParameters createAcParameters(Network network, MatrixFac
branchesWithCurrent,
parameters.getConnectedComponentMode() == LoadFlowParameters.ConnectedComponentMode.MAIN,
parameters.getCountriesToBalance(),
parameters.isDistributedSlack() && parameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD);
parameters.isDistributedSlack() && parameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD,
parametersExt.isVoltagePerReactivePowerControl());
}

private LoadFlowResult runAc(Network network, LoadFlowParameters parameters, OpenLoadFlowParameters parametersExt, Reporter reporter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ public class ReactiveLimitsOuterLoop implements OuterLoop {

private static final Logger LOGGER = LoggerFactory.getLogger(ReactiveLimitsOuterLoop.class);

private static final double Q_EPS = Math.pow(10, -5); // 10^-5 in p.u => 10^-3 in Mw

private static final Comparator<PvToPqBus> BY_NOMINAL_V_COMPARATOR = Comparator.comparingDouble(
pvToPqBus -> pvToPqBus.controllerBus.getVoltageControl()
.map(vc -> -vc.getControlledBus().getNominalV())
Expand Down Expand Up @@ -196,10 +194,12 @@ private void checkPqBus(LfBus controllerCapableBus, List<PqToPvBus> pqToPvBuses)
double minQ = controllerCapableBus.getMinQ();
double maxQ = controllerCapableBus.getMaxQ();
double q = controllerCapableBus.getGenerationTargetQ();
if (Math.abs(q - maxQ) < Q_EPS && controllerCapableBus.getV().eval() > getBusTargetV(controllerCapableBus)) { // bus produce too much reactive power
double distanceToMaxQ = Math.abs(q - maxQ);
double distanceToMinQ = Math.abs(q - minQ);
if (distanceToMaxQ < distanceToMinQ && controllerCapableBus.getV().eval() > getBusTargetV(controllerCapableBus)) { // bus produce too much reactive power
Copy link
Member Author

Choose a reason for hiding this comment

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

@geofjamg can you please validate these new lines. For me, it works because we are sure that the bus checked is a PQ bus that where previously PV. Do you agree?

Copy link
Member

Choose a reason for hiding this comment

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

Yes because hasVoltageControllerCapability has been check before calling this method. You should add a comment on this, because this is not obvious and I add to re-read the code several times to be sure.
What was the purpose of this change, why the actual check does not work?

pqToPvBuses.add(new PqToPvBus(controllerCapableBus, ReactiveLimitDirection.MAX));
}
if (Math.abs(q - minQ) < Q_EPS && controllerCapableBus.getV().eval() < getBusTargetV(controllerCapableBus)) { // bus absorb too much reactive power
if (distanceToMaxQ > distanceToMinQ && controllerCapableBus.getV().eval() < getBusTargetV(controllerCapableBus)) { // bus absorb too much reactive power
pqToPvBuses.add(new PqToPvBus(controllerCapableBus, ReactiveLimitDirection.MIN));
}
}
Expand All @@ -219,7 +219,12 @@ public OuterLoopStatus check(OuterLoopContext context, Reporter reporter) {
if (bus.isVoltageControllerEnabled() && !bus.isDisabled()) {
checkPvBus(bus, pvToPqBuses, remainingPvBusCount);
} else if (bus.hasVoltageControllerCapability() && !bus.isDisabled()) {
checkPqBus(bus, pqToPvBuses);
if (!bus.hasGeneratorsWithSlope()) {
checkPqBus(bus, pqToPvBuses);
} else {
// we don't support switching PQ to PV for bus with one controller with slope.
LOGGER.warn("Controller bus '{}' wants to control back voltage with slope: not supported", bus.getId());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ private static void createBusEquations(LfNetwork network, VariableSet variableSe
private static void createVoltageControlEquations(VoltageControl voltageControl, LfBus bus, VariableSet variableSet,
EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) {
if (voltageControl.isVoltageControlLocal()) {
EquationTerm vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval());
equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm);
bus.setV(vTerm);
createLocalVoltageControlEquation(bus, variableSet, equationSystem, creationParameters);
} else if (bus.isVoltageControlled()) {
// remote controlled: set voltage equation on this controlled bus
createVoltageControlledBusEquations(voltageControl, equationSystem, variableSet, creationParameters);
Expand All @@ -73,6 +71,18 @@ private static void createVoltageControlEquations(VoltageControl voltageControl,
}
}

private static void createLocalVoltageControlEquation(LfBus bus, VariableSet variableSet, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) {
EquationTerm vTerm = EquationTerm.createVariableTerm(bus, VariableType.BUS_V, variableSet, bus.getV().eval());
bus.setV(vTerm);
if (bus.hasGeneratorsWithSlope()) {
// take first generator with slope: network loading ensures that there's only one generator with slope
double slope = bus.getGeneratorsControllingVoltageWithSlope().get(0).getSlope();
createBusWithSlopeEquation(bus, slope, creationParameters, variableSet, equationSystem, vTerm);
return;
}
equationSystem.createEquation(bus.getNum(), EquationType.BUS_V).addTerm(vTerm);
}

private static void createShuntEquations(VariableSet variableSet, EquationSystem equationSystem, LfBus bus) {
for (LfShunt shunt : bus.getShunts()) {
ShuntCompensatorReactiveFlowEquationTerm q = new ShuntCompensatorReactiveFlowEquationTerm(shunt, bus, variableSet);
Expand Down Expand Up @@ -208,8 +218,8 @@ private static void createNonImpedantBranch(VariableSet variableSet, EquationSys
LfBranch branch, LfBus bus1, LfBus bus2) {
Optional<Equation> v1 = equationSystem.getEquation(bus1.getNum(), EquationType.BUS_V);
Optional<Equation> v2 = equationSystem.getEquation(bus2.getNum(), EquationType.BUS_V);
boolean hasV1 = v1.isPresent() && v1.get().isActive(); // may be inactive is the equation has been created for sensitivity
boolean hasV2 = v2.isPresent() && v2.get().isActive(); // may be inactive is the equation has been created for sensitivity
boolean hasV1 = v1.isPresent() && v1.get().isActive(); // may be inactive if the equation has been created for sensitivity
boolean hasV2 = v2.isPresent() && v2.get().isActive(); // may be inactive if the equation has been created for sensitivity
if (!(hasV1 && hasV2)) {
// create voltage magnitude coupling equation
// 0 = v1 - v2 * rho
Expand Down Expand Up @@ -284,6 +294,19 @@ private static void createDiscreteVoltageControlEquation(LfBus bus, VariableSet
});
}

private static void createBusWithSlopeEquation(LfBus bus, double slope, AcEquationSystemCreationParameters creationParameters, VariableSet variableSet, EquationSystem equationSystem, EquationTerm vTerm) {
// we only support one generator controlling voltage with a non zero slope at a bus.
// equation is: V + slope * qSVC = targetV
// which is modeled here with: V + slope * (sum_branch qBranch) = TargetV - slope * qLoads + slope * qGenerators
Equation eq = equationSystem.createEquation(bus.getNum(), EquationType.BUS_V_SLOPE);
eq.addTerm(vTerm);
List<EquationTerm> controllerBusReactiveTerms = createReactiveTerms(bus, variableSet, creationParameters);
eq.setData(new DistributionData(bus.getNum(), slope)); // for later use
for (EquationTerm eqTerm : controllerBusReactiveTerms) {
eq.addTerm(EquationTerm.multiply(eqTerm, slope));
}
}

public static void createR1DistributionEquations(EquationSystem equationSystem, VariableSet variableSet,
List<LfBranch> controllerBranches) {
if (controllerBranches.size() > 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,26 @@ private void updateControlledBus(VoltageControl voltageControl, EquationSystem e
LfBus controlledBus = voltageControl.getControlledBus();
Set<LfBus> controllerBuses = voltageControl.getControllerBuses();

// clean reactive power distribution equations
controllerBuses.forEach(b -> equationSystem.removeEquation(b.getNum(), EquationType.ZERO_Q));

// controlled bus has a voltage equation only if one of the controller bus has voltage control on
List<LfBus> controllerBusesWithVoltageControlOn = controllerBuses.stream()
.filter(LfBus::isVoltageControllerEnabled)
.collect(Collectors.toList());
equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V).setActive(!controllerBusesWithVoltageControlOn.isEmpty());

// create reactive power equations on controller buses that have voltage control on
if (!controllerBusesWithVoltageControlOn.isEmpty()) {
AcEquationSystem.createReactivePowerDistributionEquations(equationSystem, variableSet, creationParameters, controllerBusesWithVoltageControlOn);
LfBus firstControllerBus = controllerBuses.iterator().next();
if (firstControllerBus.hasGeneratorsWithSlope()) {
// we only support one controlling static var compensator without any other controlling generators
// we don't support controller bus that wants to control back voltage with slope.
if (!firstControllerBus.isVoltageControllerEnabled()) {
equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V_SLOPE).setActive(false);
Copy link
Member

Choose a reason for hiding this comment

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

There is no criteria to switch it on?

}
} else {
// controlled bus has a voltage equation only if one of the controller bus has voltage control on
List<LfBus> controllerBusesWithVoltageControlOn = controllerBuses.stream()
.filter(LfBus::isVoltageControllerEnabled)
.collect(Collectors.toList());
// clean reactive power distribution equations
controllerBuses.forEach(b -> equationSystem.removeEquation(b.getNum(), EquationType.ZERO_Q));
// is there one static var compensator with a non-zero slope
equationSystem.createEquation(controlledBus.getNum(), EquationType.BUS_V).setActive(!controllerBusesWithVoltageControlOn.isEmpty());
// create reactive power equations on controller buses that have voltage control on
if (!controllerBusesWithVoltageControlOn.isEmpty()) {
AcEquationSystem.createReactivePowerDistributionEquations(equationSystem, variableSet, creationParameters, controllerBusesWithVoltageControlOn);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,17 @@ public class AcLoadFlowParameters {

private final boolean distributedOnConformLoad;

private final boolean voltagePerReactivePowerControl;

public AcLoadFlowParameters(SlackBusSelector slackBusSelector, VoltageInitializer voltageInitializer,
NewtonRaphsonStoppingCriteria stoppingCriteria, List<OuterLoop> outerLoops,
MatrixFactory matrixFactory, boolean voltageRemoteControl,
boolean phaseControl, boolean transformerVoltageControlOn, boolean minImpedance,
boolean twtSplitShuntAdmittance, boolean breakers, double plausibleActivePowerLimit,
boolean forceA1Var, boolean addRatioToLinesWithDifferentNominalVoltageAtBothEnds,
Set<String> branchesWithCurrent, boolean computeMainConnectedComponentOnly,
Set<Country> countriesToBalance, boolean distributedOnConformLoad) {
Set<Country> countriesToBalance, boolean distributedOnConformLoad,
boolean voltagePerReactivePowerControl) {
this.slackBusSelector = Objects.requireNonNull(slackBusSelector);
this.voltageInitializer = Objects.requireNonNull(voltageInitializer);
this.stoppingCriteria = Objects.requireNonNull(stoppingCriteria);
Expand All @@ -84,6 +87,7 @@ public AcLoadFlowParameters(SlackBusSelector slackBusSelector, VoltageInitialize
this.computeMainConnectedComponentOnly = computeMainConnectedComponentOnly;
this.countriesToBalance = countriesToBalance;
this.distributedOnConformLoad = distributedOnConformLoad;
this.voltagePerReactivePowerControl = voltagePerReactivePowerControl;
}

public SlackBusSelector getSlackBusSelector() {
Expand Down Expand Up @@ -161,4 +165,8 @@ public Set<Country> getCountriesToBalance() {
public boolean isDistributedOnConformLoad() {
return distributedOnConformLoad;
}

public boolean isVoltagePerReactivePowerControl() {
return voltagePerReactivePowerControl;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ public static List<LfNetwork> createNetworks(Object network, AcLoadFlowParameter
parameters.getCountriesToBalance(),
parameters.isDistributedOnConformLoad(),
parameters.isPhaseControl(),
parameters.isVoltageRemoteControl());
parameters.isVoltageRemoteControl(),
parameters.isVoltagePerReactivePowerControl());
return LfNetwork.load(network, networkParameters, reporter);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ public DcLoadFlowEngine(LfNetwork network, MatrixFactory matrixFactory, boolean
public DcLoadFlowEngine(Object network, DcLoadFlowParameters parameters, Reporter reporter) {
LfNetworkParameters lfNetworkParameters = new LfNetworkParameters(parameters.getSlackBusSelector(), false, false, false, false,
parameters.getPlausibleActivePowerLimit(), false, parameters.isComputeMainConnectedComponentOnly(), parameters.getCountriesToBalance(),
parameters.isDistributedSlack() && parameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD, false, false);
parameters.isDistributedSlack() && parameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD,
false, false, false);
this.networks = LfNetwork.load(network, lfNetworkParameters, reporter);
this.parameters = Objects.requireNonNull(parameters);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ private static double getRho1DistributionTarget(LfNetwork network, int num, Dist
return controllerBranch.getPiModel().getR1() - firstControllerBranch.getPiModel().getR1();
}

private static double createBusWithSlopeTarget(LfBus bus, DistributionData data) {
double slope = data.getC();
return getBusTargetV(bus) - slope * (bus.getLoadTargetQ() - bus.getGenerationTargetQ());
}

void initTarget(LfNetwork network, double[] targets) {
switch (type) {
case BUS_P:
Expand All @@ -184,6 +189,10 @@ void initTarget(LfNetwork network, double[] targets) {
targets[column] = getBusTargetV(network.getBus(num));
break;

case BUS_V_SLOPE:
targets[column] = createBusWithSlopeTarget(network.getBus(num), getData());
break;

case BUS_PHI:
targets[column] = 0;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public enum EquationType {
BUS_I("b_i", ElementType.BUS),
BUS_Q("q", ElementType.BUS),
BUS_V("v", ElementType.BUS),
BUS_V_SLOPE("v_slope", ElementType.BUS),
BUS_PHI("\u03C6", ElementType.BUS),
BRANCH_P("t", ElementType.BRANCH),
BRANCH_I("i", ElementType.BRANCH),
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/com/powsybl/openloadflow/network/LfBus.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ public interface LfBus extends LfElement {

boolean isVoltageControlled();

List<LfGenerator> getGeneratorsControllingVoltageWithSlope();

boolean hasGeneratorsWithSlope();

void removeGeneratorSlopes();

/**
* Get the number of time, voltage control status has be set from true to false.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,8 @@ public interface LfGenerator {
void updateState();

LfBus getControlledBus(LfNetwork lfNetwork);

double getSlope();

void setSlope(double slope);
}
Loading