Skip to content

Commit ab057bb

Browse files
Refactor access to branch limits when detecting limit violations (#1197)
Signed-off-by: p-arvy <[email protected]> Co-authored-by: Hadrien <[email protected]>
1 parent c0138fa commit ab057bb

File tree

5 files changed

+126
-51
lines changed

5 files changed

+126
-51
lines changed

src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBranch.java

+78-14
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,17 @@ public abstract class AbstractLfBranch extends AbstractElement implements LfBran
3030

3131
protected final LfBus bus2;
3232

33-
private final Map<LimitType, List<LfLimit>> limits1 = new EnumMap<>(LimitType.class);
33+
private List<LfLimit> currentLimits1;
3434

35-
private final Map<LimitType, List<LfLimit>> limits2 = new EnumMap<>(LimitType.class);
35+
private List<LfLimit> activePowerLimits1;
36+
37+
private List<LfLimit> apparentPowerLimits1;
38+
39+
private List<LfLimit> currentLimits2;
40+
41+
private List<LfLimit> activePowerLimits2;
42+
43+
private List<LfLimit> apparentPowerLimits2;
3644

3745
protected final PiModel piModel;
3846

@@ -61,6 +69,8 @@ static class ZeroImpedanceContext {
6169

6270
protected LfAsymLine asymLine;
6371

72+
private static final String LIMIT_TYPE_UNSUPPORTED_TEMPLATE = "Getting %s limits is not supported.";
73+
6474
protected AbstractLfBranch(LfNetwork network, LfBus bus1, LfBus bus2, PiModel piModel, LfNetworkParameters parameters) {
6575
super(network);
6676
this.bus1 = bus1;
@@ -87,7 +97,7 @@ public Optional<ThreeSides> getOriginalSide() {
8797
* The resulting list will contain the permanent limit
8898
*/
8999
protected static List<LfLimit> createSortedLimitsList(LoadingLimits loadingLimits, LfBus bus, double[] limitReductions) {
90-
LinkedList<LfLimit> sortedLimits = new LinkedList<>();
100+
List<LfLimit> sortedLimits = new ArrayList<>(3);
91101
if (loadingLimits != null) {
92102
double toPerUnit = getScaleForLimitType(loadingLimits.getLimitType(), bus);
93103

@@ -99,21 +109,21 @@ protected static List<LfLimit> createSortedLimitsList(LoadingLimits loadingLimit
99109
// https://javadoc.io/doc/com.powsybl/powsybl-core/latest/com/powsybl/iidm/network/CurrentLimits.html
100110
double reduction = limitReductions.length == 0 ? 1d : limitReductions[i + 1]; // Temporary limit's reductions are stored starting from index 1 in `limitReductions`
101111
double originalValuePerUnit = temporaryLimit.getValue() * toPerUnit;
102-
sortedLimits.addFirst(LfLimit.createTemporaryLimit(temporaryLimit.getName(), temporaryLimit.getAcceptableDuration(),
112+
sortedLimits.add(0, LfLimit.createTemporaryLimit(temporaryLimit.getName(), temporaryLimit.getAcceptableDuration(),
103113
originalValuePerUnit, reduction));
104114
}
105115
i++;
106116
}
107117
double reduction = limitReductions.length == 0 ? 1d : limitReductions[0];
108-
sortedLimits.addLast(LfLimit.createPermanentLimit(loadingLimits.getPermanentLimit() * toPerUnit, reduction));
118+
sortedLimits.add(LfLimit.createPermanentLimit(loadingLimits.getPermanentLimit() * toPerUnit, reduction));
109119
}
110120
if (sortedLimits.size() > 1) {
111121
// we only make that fix if there is more than a permanent limit attached to the branch.
112122
for (int i = sortedLimits.size() - 1; i > 0; i--) {
113123
// From the permanent limit to the most serious temporary limit.
114124
sortedLimits.get(i).setAcceptableDuration(sortedLimits.get(i - 1).getAcceptableDuration());
115125
}
116-
sortedLimits.getFirst().setAcceptableDuration(0);
126+
sortedLimits.get(0).setAcceptableDuration(0);
117127
}
118128
return sortedLimits;
119129
}
@@ -133,22 +143,76 @@ public LfBus getBus2() {
133143
return bus2;
134144
}
135145

146+
private List<LfLimit> getLimits1(LimitType type) {
147+
switch (type) {
148+
case ACTIVE_POWER -> {
149+
return activePowerLimits1;
150+
}
151+
case APPARENT_POWER -> {
152+
return apparentPowerLimits1;
153+
}
154+
case CURRENT -> {
155+
return currentLimits1;
156+
}
157+
default -> throw new UnsupportedOperationException(String.format(LIMIT_TYPE_UNSUPPORTED_TEMPLATE, type.name()));
158+
}
159+
}
160+
161+
private void setLimits1(LimitType type, List<LfLimit> limits) {
162+
switch (type) {
163+
case ACTIVE_POWER -> activePowerLimits1 = limits;
164+
case APPARENT_POWER -> apparentPowerLimits1 = limits;
165+
case CURRENT -> currentLimits1 = limits;
166+
default -> throw new UnsupportedOperationException(String.format(LIMIT_TYPE_UNSUPPORTED_TEMPLATE, type.name()));
167+
}
168+
}
169+
136170
public <T extends LoadingLimits> List<LfLimit> getLimits1(LimitType type, Supplier<Optional<T>> loadingLimitsSupplier, LimitReductionManager limitReductionManager) {
137-
// It is possible to apply the reductions here since the only supported ContingencyContext for LimitReduction is ALL.
138-
return limits1.computeIfAbsent(type, v -> {
171+
var limits = getLimits1(type);
172+
if (limits == null) {
173+
// It is possible to apply the reductions here since the only supported ContingencyContext for LimitReduction is ALL.
139174
var loadingLimits = loadingLimitsSupplier.get().orElse(null);
140-
return createSortedLimitsList(loadingLimits, bus1,
175+
limits = createSortedLimitsList(loadingLimits, bus1,
141176
getLimitReductions(TwoSides.ONE, limitReductionManager, loadingLimits));
142-
});
177+
setLimits1(type, limits);
178+
}
179+
return limits;
180+
}
181+
182+
private List<LfLimit> getLimits2(LimitType type) {
183+
switch (type) {
184+
case ACTIVE_POWER -> {
185+
return activePowerLimits2;
186+
}
187+
case APPARENT_POWER -> {
188+
return apparentPowerLimits2;
189+
}
190+
case CURRENT -> {
191+
return currentLimits2;
192+
}
193+
default -> throw new UnsupportedOperationException(String.format(LIMIT_TYPE_UNSUPPORTED_TEMPLATE, type.name()));
194+
}
195+
}
196+
197+
private void setLimits2(LimitType type, List<LfLimit> limits) {
198+
switch (type) {
199+
case ACTIVE_POWER -> activePowerLimits2 = limits;
200+
case APPARENT_POWER -> apparentPowerLimits2 = limits;
201+
case CURRENT -> currentLimits2 = limits;
202+
default -> throw new UnsupportedOperationException(String.format(LIMIT_TYPE_UNSUPPORTED_TEMPLATE, type.name()));
203+
}
143204
}
144205

145206
public <T extends LoadingLimits> List<LfLimit> getLimits2(LimitType type, Supplier<Optional<T>> loadingLimitsSupplier, LimitReductionManager limitReductionManager) {
146-
// It is possible to apply the reductions here since the only supported ContingencyContext for LimitReduction is ALL.
147-
return limits2.computeIfAbsent(type, v -> {
207+
var limits = getLimits2(type);
208+
if (limits == null) {
209+
// It is possible to apply the reductions here since the only supported ContingencyContext for LimitReduction is ALL.
148210
var loadingLimits = loadingLimitsSupplier.get().orElse(null);
149-
return createSortedLimitsList(loadingLimits, bus2,
211+
limits = createSortedLimitsList(loadingLimits, bus2,
150212
getLimitReductions(TwoSides.TWO, limitReductionManager, loadingLimits));
151-
});
213+
setLimits2(type, limits);
214+
}
215+
return limits;
152216
}
153217

154218
@Override

src/main/java/com/powsybl/openloadflow/network/impl/LfBranchImpl.java

+6-8
Original file line numberDiff line numberDiff line change
@@ -234,14 +234,13 @@ public List<BranchResult> createBranchResult(double preContingencyBranchP1, doub
234234

235235
@Override
236236
public List<LfLimit> getLimits1(final LimitType type, LimitReductionManager limitReductionManager) {
237-
var branch = getBranch();
238237
switch (type) {
239238
case ACTIVE_POWER:
240-
return getLimits1(type, branch::getActivePowerLimits1, limitReductionManager);
239+
return getLimits1(type, () -> getBranch().getActivePowerLimits1(), limitReductionManager);
241240
case APPARENT_POWER:
242-
return getLimits1(type, branch::getApparentPowerLimits1, limitReductionManager);
241+
return getLimits1(type, () -> getBranch().getApparentPowerLimits1(), limitReductionManager);
243242
case CURRENT:
244-
return getLimits1(type, branch::getCurrentLimits1, limitReductionManager);
243+
return getLimits1(type, () -> getBranch().getCurrentLimits1(), limitReductionManager);
245244
case VOLTAGE:
246245
default:
247246
throw new UnsupportedOperationException(String.format("Getting %s limits is not supported.", type.name()));
@@ -250,14 +249,13 @@ public List<LfLimit> getLimits1(final LimitType type, LimitReductionManager limi
250249

251250
@Override
252251
public List<LfLimit> getLimits2(final LimitType type, LimitReductionManager limitReductionManager) {
253-
var branch = getBranch();
254252
switch (type) {
255253
case ACTIVE_POWER:
256-
return getLimits2(type, branch::getActivePowerLimits2, limitReductionManager);
254+
return getLimits2(type, () -> getBranch().getActivePowerLimits2(), limitReductionManager);
257255
case APPARENT_POWER:
258-
return getLimits2(type, branch::getApparentPowerLimits2, limitReductionManager);
256+
return getLimits2(type, () -> getBranch().getApparentPowerLimits2(), limitReductionManager);
259257
case CURRENT:
260-
return getLimits2(type, branch::getCurrentLimits2, limitReductionManager);
258+
return getLimits2(type, () -> getBranch().getCurrentLimits2(), limitReductionManager);
261259
case VOLTAGE:
262260
default:
263261
throw new UnsupportedOperationException(String.format("Getting %s limits is not supported.", type.name()));

src/main/java/com/powsybl/openloadflow/network/impl/LfDanglingLineBranch.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,13 @@ public List<BranchResult> createBranchResult(double preContingencyBranchP1, doub
8080

8181
@Override
8282
public List<LfLimit> getLimits1(final LimitType type, LimitReductionManager limitReductionManager) {
83-
var danglingLine = getDanglingLine();
8483
switch (type) {
8584
case ACTIVE_POWER:
86-
return getLimits1(type, danglingLine::getActivePowerLimits, limitReductionManager);
85+
return getLimits1(type, () -> getDanglingLine().getActivePowerLimits(), limitReductionManager);
8786
case APPARENT_POWER:
88-
return getLimits1(type, danglingLine::getApparentPowerLimits, limitReductionManager);
87+
return getLimits1(type, () -> getDanglingLine().getApparentPowerLimits(), limitReductionManager);
8988
case CURRENT:
90-
return getLimits1(type, danglingLine::getCurrentLimits, limitReductionManager);
89+
return getLimits1(type, () -> getDanglingLine().getCurrentLimits(), limitReductionManager);
9190
case VOLTAGE:
9291
default:
9392
throw new UnsupportedOperationException(String.format("Getting %s limits is not supported.", type.name()));

src/main/java/com/powsybl/openloadflow/network/impl/LfLegBranch.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,13 @@ public List<BranchResult> createBranchResult(double preContingencyBranchP1, doub
147147

148148
@Override
149149
public List<LfLimit> getLimits1(final LimitType type, LimitReductionManager limitReductionManager) {
150-
var leg = getLeg();
151150
switch (type) {
152151
case ACTIVE_POWER:
153-
return getLimits1(type, leg::getActivePowerLimits, limitReductionManager);
152+
return getLimits1(type, () -> getLeg().getActivePowerLimits(), limitReductionManager);
154153
case APPARENT_POWER:
155-
return getLimits1(type, leg::getApparentPowerLimits, limitReductionManager);
154+
return getLimits1(type, () -> getLeg().getApparentPowerLimits(), limitReductionManager);
156155
case CURRENT:
157-
return getLimits1(type, leg::getCurrentLimits, limitReductionManager);
156+
return getLimits1(type, () -> getLeg().getCurrentLimits(), limitReductionManager);
158157
case VOLTAGE:
159158
default:
160159
throw new UnsupportedOperationException(String.format("Getting %s limits is not supported.", type.name()));

src/main/java/com/powsybl/openloadflow/sa/LimitViolationManager.java

+36-21
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,39 @@ private void addVoltageAngleLimitViolation(LimitViolation limitViolation, LfNetw
112112
addLimitViolation(limitViolation, voltageAngleLimit.getId());
113113
}
114114

115+
private void detectBranchCurrentViolations(LfBranch branch, LfBus bus, Function<LfBranch, Evaluable> iGetter, List<LfBranch.LfLimit> limits, TwoSides side) {
116+
double i = iGetter.apply(branch).eval();
117+
for (LfBranch.LfLimit temporaryLimit : limits) {
118+
if (i > temporaryLimit.getReducedValue()) {
119+
addBranchLimitViolation(createLimitViolation(branch, temporaryLimit, LimitViolationType.CURRENT, PerUnit.ib(bus.getNominalV()), i, side));
120+
break;
121+
}
122+
}
123+
}
124+
125+
private void detectBranchActivePowerViolations(LfBranch branch, Function<LfBranch, Evaluable> pGetter, List<LfBranch.LfLimit> limits, TwoSides side) {
126+
double p = pGetter.apply(branch).eval();
127+
for (LfBranch.LfLimit temporaryLimit : limits) {
128+
if (Math.abs(p) > temporaryLimit.getReducedValue()) {
129+
addBranchLimitViolation(createLimitViolation(branch, temporaryLimit, LimitViolationType.ACTIVE_POWER, PerUnit.SB, p, side));
130+
break;
131+
}
132+
}
133+
}
134+
135+
private void detectBranchApparentPowerViolations(LfBranch branch, ToDoubleFunction<LfBranch> sGetter, List<LfBranch.LfLimit> limits, TwoSides side) {
136+
//Apparent power is not relevant for fictitious branches and may be NaN
137+
double s = sGetter.applyAsDouble(branch);
138+
if (!Double.isNaN(s)) {
139+
for (LfBranch.LfLimit temporaryLimit : limits) {
140+
if (s > temporaryLimit.getReducedValue()) {
141+
addBranchLimitViolation(createLimitViolation(branch, temporaryLimit, LimitViolationType.APPARENT_POWER, PerUnit.SB, s, side));
142+
break;
143+
}
144+
}
145+
}
146+
}
147+
115148
private void detectBranchSideViolations(LfBranch branch, LfBus bus,
116149
TriFunction<LfBranch, LimitType, LimitReductionManager, List<LfBranch.LfLimit>> limitsGetter,
117150
Function<LfBranch, Evaluable> iGetter,
@@ -120,35 +153,17 @@ private void detectBranchSideViolations(LfBranch branch, LfBus bus,
120153
TwoSides side) {
121154
List<LfBranch.LfLimit> limits = limitsGetter.apply(branch, LimitType.CURRENT, limitReductionManager);
122155
if (!limits.isEmpty()) {
123-
double i = iGetter.apply(branch).eval();
124-
limits.stream()
125-
.filter(temporaryLimit -> i > temporaryLimit.getReducedValue())
126-
.findFirst()
127-
.map(temporaryLimit -> createLimitViolation(branch, temporaryLimit, LimitViolationType.CURRENT, PerUnit.ib(bus.getNominalV()), i, side))
128-
.ifPresent(this::addBranchLimitViolation);
156+
detectBranchCurrentViolations(branch, bus, iGetter, limits, side);
129157
}
130158

131159
limits = limitsGetter.apply(branch, LimitType.ACTIVE_POWER, limitReductionManager);
132160
if (!limits.isEmpty()) {
133-
double p = pGetter.apply(branch).eval();
134-
limits.stream()
135-
.filter(temporaryLimit -> Math.abs(p) > temporaryLimit.getReducedValue())
136-
.findFirst()
137-
.map(temporaryLimit -> createLimitViolation(branch, temporaryLimit, LimitViolationType.ACTIVE_POWER, PerUnit.SB, p, side))
138-
.ifPresent(this::addBranchLimitViolation);
161+
detectBranchActivePowerViolations(branch, pGetter, limits, side);
139162
}
140163

141164
limits = limitsGetter.apply(branch, LimitType.APPARENT_POWER, limitReductionManager);
142165
if (!limits.isEmpty()) {
143-
//Apparent power is not relevant for fictitious branches and may be NaN
144-
double s = sGetter.applyAsDouble(branch);
145-
if (!Double.isNaN(s)) {
146-
limits.stream()
147-
.filter(temporaryLimit -> s > temporaryLimit.getReducedValue())
148-
.findFirst()
149-
.map(temporaryLimit -> createLimitViolation(branch, temporaryLimit, LimitViolationType.APPARENT_POWER, PerUnit.SB, s, side))
150-
.ifPresent(this::addBranchLimitViolation);
151-
}
166+
detectBranchApparentPowerViolations(branch, sGetter, limits, side);
152167
}
153168
}
154169

0 commit comments

Comments
 (0)