Skip to content

Commit

Permalink
Add the violation location in voltage LimitViolations (#3153)
Browse files Browse the repository at this point in the history
* allow to get the bus id or the bus bar ids as limitViolation Id
* refactor and add tests

Signed-off-by: Etienne LESOT <[email protected]>
  • Loading branch information
EtienneLt authored Sep 30, 2024
1 parent 0e6097b commit 5eefd6c
Show file tree
Hide file tree
Showing 30 changed files with 729 additions and 56 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* 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.security;

import java.util.Objects;
import java.util.Optional;

/**
* @author Étienne Lesot {@literal <etienne.lesot at rte-france.com>}
*/
public class BusBreakerViolationLocation implements ViolationLocation {
private final String voltageLevelId;
private final String busId;

public BusBreakerViolationLocation(String voltageLevelId, String busId) {
Objects.requireNonNull(voltageLevelId, "voltageLevelId");
this.voltageLevelId = voltageLevelId;
this.busId = busId;
}

@Override
public String getVoltageLevelId() {
return voltageLevelId;
}

@Override
public Optional<String> getBusId() {
return Optional.ofNullable(busId);
}

@Override
public String getId() {
return busId == null ? voltageLevelId : busId;
}

@Override
public Type getType() {
return Type.BUS_BREAKER;
}

@Override
public String toString() {
return "BusBreakerViolationLocation{" +
"voltageLevelId='" + voltageLevelId + '\'' +
", busId='" + busId + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import javax.annotation.Nullable;
import java.util.Objects;
import java.util.Optional;

/**
* A generic representation of a violation of a network equipment security limit.
Expand Down Expand Up @@ -40,6 +41,8 @@ public class LimitViolation extends AbstractExtendable<LimitViolation> {

private final ThreeSides side;

private final ViolationLocation voltageLocation;

/**
* Create a new LimitViolation.
*
Expand All @@ -56,7 +59,7 @@ public class LimitViolation extends AbstractExtendable<LimitViolation> {
* @param side The side of the equipment where the violation occurred. May be {@code null} for non-branch, non-three windings transformer equipments.
*/
public LimitViolation(String subjectId, @Nullable String subjectName, LimitViolationType limitType, @Nullable String limitName, int acceptableDuration,
double limit, double limitReduction, double value, @Nullable ThreeSides side) {
double limit, double limitReduction, double value, @Nullable ThreeSides side, @Nullable ViolationLocation voltageLocation) {
this.subjectId = Objects.requireNonNull(subjectId);
this.subjectName = subjectName;
this.limitType = Objects.requireNonNull(limitType);
Expand All @@ -66,6 +69,27 @@ public LimitViolation(String subjectId, @Nullable String subjectName, LimitViola
this.limitReduction = limitReduction;
this.value = value;
this.side = checkSide(limitType, side);
this.voltageLocation = voltageLocation;
}

/**
* Create a new LimitViolation.
*
* <p>According to the violation type, all parameters may not be mandatory. See constructor overloads for particular types.
*
* @param subjectId The identifier of the network equipment on which the violation occurred.
* @param subjectName An optional name of the network equipment on which the violation occurred.
* @param limitType The type of limit which has been violated.
* @param limitName An optional name for the limit which has been violated.
* @param acceptableDuration The acceptable duration, in seconds, associated to the current violation value. Only relevant for current limits.
* @param limit The value of the limit which has been violated.
* @param limitReduction The limit reduction factor used for violation detection.
* @param value The actual value of the physical value which triggered the detection of a violation.
* @param side The side of the equipment where the violation occurred. May be {@code null} for non-branch, non-three windings transformer equipments.
*/
public LimitViolation(String subjectId, @Nullable String subjectName, LimitViolationType limitType, @Nullable String limitName, int acceptableDuration,
double limit, double limitReduction, double value, @Nullable ThreeSides side) {
this(subjectId, subjectName, limitType, limitName, acceptableDuration, limit, limitReduction, value, side, null);
}

/**
Expand Down Expand Up @@ -145,6 +169,22 @@ public LimitViolation(String subjectId, LimitViolationType limitType, String lim
this(subjectId, null, limitType, limitName, acceptableDuration, limit, limitReduction, value, (ThreeSides) null);
}

/**
* Create a new LimitViolation, for types other than current limits.
*
* <p>According to the violation type, all parameters may not be mandatory. See constructor overloads for particular types.
*
* @param subjectId The identifier of the network equipment on which the violation occurred.
* @param limitType The type of limit which has been violated.
* @param limit The value of the limit which has been violated.
* @param limitReduction The limit reduction factor used for violation detection.
* @param value The actual value of the physical value which triggered the detection of a violation.
* @param voltageLocation Detailed information about the location of the violation.
*/
public LimitViolation(String subjectId, LimitViolationType limitType, double limit, double limitReduction, double value, ViolationLocation voltageLocation) {
this(subjectId, null, limitType, null, Integer.MAX_VALUE, limit, limitReduction, value, null, voltageLocation);
}

/**
* Create a new LimitViolation, for types other than current limits.
*
Expand All @@ -158,7 +198,24 @@ public LimitViolation(String subjectId, LimitViolationType limitType, String lim
* @param value The actual value of the physical value which triggered the detection of a violation.
*/
public LimitViolation(String subjectId, String subjectName, LimitViolationType limitType, double limit, double limitReduction, double value) {
this(subjectId, subjectName, limitType, null, Integer.MAX_VALUE, limit, limitReduction, value, (ThreeSides) null);
this(subjectId, subjectName, limitType, null, Integer.MAX_VALUE, limit, limitReduction, value, null, null);
}

/**
* Create a new LimitViolation, for types other than current limits.
*
* <p>According to the violation type, all parameters may not be mandatory. See constructor overloads for particular types.
*
* @param subjectId The identifier of the network equipment on which the violation occurred.
* @param subjectName An optional name of the network equipment on which the violation occurred.
* @param limitType The type of limit which has been violated.
* @param limit The value of the limit which has been violated.
* @param limitReduction The limit reduction factor used for violation detection.
* @param value The actual value of the physical value which triggered the detection of a violation.
* @param voltageLocation Detailed information about the location of the violation.
*/
public LimitViolation(String subjectId, String subjectName, LimitViolationType limitType, double limit, double limitReduction, double value, ViolationLocation voltageLocation) {
this(subjectId, subjectName, limitType, null, Integer.MAX_VALUE, limit, limitReduction, value, null, voltageLocation);
}

/**
Expand All @@ -173,7 +230,7 @@ public LimitViolation(String subjectId, String subjectName, LimitViolationType l
* @param value The actual value of the physical value which triggered the detection of a violation.
*/
public LimitViolation(String subjectId, LimitViolationType limitType, double limit, double limitReduction, double value) {
this(subjectId, null, limitType, null, Integer.MAX_VALUE, limit, limitReduction, value, (ThreeSides) null);
this(subjectId, null, limitType, null, Integer.MAX_VALUE, limit, limitReduction, value, null, null);
}

/**
Expand All @@ -185,6 +242,15 @@ public String getSubjectId() {
return subjectId;
}

/**
* The identifier of the network equipment on which the violation occurred.
*
* @return the identifier of the network equipment on which the violation occurred.
*/
public Optional<ViolationLocation> getViolationLocation() {
return Optional.ofNullable(voltageLocation);
}

/**
* The name of the network equipment on which the violation occurred.
* May be {@code null}.
Expand Down Expand Up @@ -288,6 +354,6 @@ public String toString() {
return "Subject id: " + this.subjectId + ", Subject name: " + this.subjectName + ", limitType: " +
this.limitType + ", limit: " + this.limit + ", limitName: " + this.limitName +
", acceptableDuration: " + this.acceptableDuration + ", limitReduction: " + this.limitReduction +
", value: " + this.value + ", side: " + this.side;
", value: " + this.value + ", side: " + this.side + ", voltageLocation: " + this.voltageLocation;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.powsybl.iidm.network.util.PermanentLimitCheckResult;
import com.powsybl.security.detectors.LoadingLimitType;

import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

Expand All @@ -30,10 +31,10 @@ private LimitViolationDetection() {
* of the specified {@link Network} should be considered as {@link LimitViolation}s.
* In case it should, feeds the consumer with it.
*
* @param network The network on which physical values must be checked.
* @param currentLimitTypes The current limit type to consider.
* @param limitsComputer The computer of the limit reductions to apply.
* @param consumer Will be fed with possibly created limit violations.
* @param network The network on which physical values must be checked.
* @param currentLimitTypes The current limit type to consider.
* @param limitsComputer The computer of the limit reductions to apply.
* @param consumer Will be fed with possibly created limit violations.
*/
public static void checkAll(Network network, Set<LoadingLimitType> currentLimitTypes,
LimitsComputer<Identifiable<?>, LoadingLimits> limitsComputer, Consumer<LimitViolation> consumer) {
Expand Down Expand Up @@ -205,14 +206,15 @@ private static void checkVoltage(Bus bus, Consumer<LimitViolation> consumer) {

static void checkVoltage(Bus bus, double value, Consumer<LimitViolation> consumer) {
VoltageLevel vl = bus.getVoltageLevel();
ViolationLocation voltageViolationLocation = createViolationLocation(bus);
if (!Double.isNaN(vl.getLowVoltageLimit()) && value <= vl.getLowVoltageLimit()) {
consumer.accept(new LimitViolation(vl.getId(), vl.getOptionalName().orElse(null), LimitViolationType.LOW_VOLTAGE,
vl.getLowVoltageLimit(), 1., value));
vl.getLowVoltageLimit(), 1., value, voltageViolationLocation));
}

if (!Double.isNaN(vl.getHighVoltageLimit()) && value >= vl.getHighVoltageLimit()) {
consumer.accept(new LimitViolation(vl.getId(), vl.getOptionalName().orElse(null), LimitViolationType.HIGH_VOLTAGE,
vl.getHighVoltageLimit(), 1., value));
vl.getHighVoltageLimit(), 1., value, voltageViolationLocation));
}
}

Expand Down Expand Up @@ -262,4 +264,18 @@ static void checkVoltageAngle(VoltageAngleLimit voltageAngleLimit, double value,
}
});
}

public static ViolationLocation createViolationLocation(Bus bus) {
VoltageLevel vl = bus.getVoltageLevel();
if (vl.getTopologyKind() == TopologyKind.NODE_BREAKER) {
List<String> busbarIds = bus.getConnectedTerminalStream()
.map(Terminal::getConnectable)
.filter(BusbarSection.class::isInstance)
.map(Connectable::getId)
.toList();
return new NodeBreakerViolationLocation(vl.getId(), busbarIds);
} else {
return new BusBreakerViolationLocation(vl.getId(), bus.getId());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* 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.security;

import java.util.List;
import java.util.Objects;

/**
* @author Étienne Lesot {@literal <etienne.lesot at rte-france.com>}
*/
public class NodeBreakerViolationLocation implements ViolationLocation {
private final String voltageLevelId;
private final List<String> busBarIds;

public NodeBreakerViolationLocation(String voltageLevelId, List<String> busBarIds) {
Objects.requireNonNull(voltageLevelId, "voltageLevelId");
this.voltageLevelId = voltageLevelId;
this.busBarIds = busBarIds;
}

@Override
public String getVoltageLevelId() {
return voltageLevelId;
}

@Override
public List<String> getBusBarIds() {
return busBarIds;
}

@Override
public String getId() {
return busBarIds.isEmpty() ? voltageLevelId : busBarIds.get(0);
}

@Override
public Type getType() {
return Type.NODE_BREAKER;
}

@Override
public String toString() {
return "NodeBreakerVoltageLocation{" +
"voltageLevelId='" + voltageLevelId + '\'' +
", busBarIds=" + busBarIds +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* 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.security;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
* @author Étienne Lesot {@literal <etienne.lesot at rte-france.com>}
*/
public interface ViolationLocation {

enum Type {
NODE_BREAKER,
BUS_BREAKER
}

String getId();

Type getType();

String getVoltageLevelId();

default Optional<String> getBusId() {
return Optional.empty();
}

default List<String> getBusBarIds() {
return Collections.emptyList();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@
package com.powsybl.security.detectors;

import com.powsybl.iidm.network.*;
import com.powsybl.security.LimitViolation;
import com.powsybl.security.LimitViolationType;
import com.powsybl.security.*;

import java.util.Collection;
import java.util.EnumSet;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.function.Consumer;

import static com.powsybl.security.LimitViolationDetection.createViolationLocation;

/**
* Implements the default behaviour for limit violation detection.
*
Expand Down Expand Up @@ -80,14 +78,15 @@ public void checkApparentPower(ThreeWindingsTransformer transformer, ThreeSides
@Override
public void checkVoltage(Bus bus, double value, Consumer<LimitViolation> consumer) {
VoltageLevel vl = bus.getVoltageLevel();
ViolationLocation voltageViolationLocation = createViolationLocation(bus);
if (!Double.isNaN(vl.getLowVoltageLimit()) && value <= vl.getLowVoltageLimit()) {
consumer.accept(new LimitViolation(vl.getId(), vl.getOptionalName().orElse(null), LimitViolationType.LOW_VOLTAGE,
vl.getLowVoltageLimit(), limitReductionValue, value));
vl.getLowVoltageLimit(), limitReductionValue, value, voltageViolationLocation));
}

if (!Double.isNaN(vl.getHighVoltageLimit()) && value >= vl.getHighVoltageLimit()) {
consumer.accept(new LimitViolation(vl.getId(), vl.getOptionalName().orElse(null), LimitViolationType.HIGH_VOLTAGE,
vl.getHighVoltageLimit(), limitReductionValue, value));
vl.getHighVoltageLimit(), limitReductionValue, value, voltageViolationLocation));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ protected AbstractSecurityAnalysisJsonModule(Collection<SecurityAnalysisJsonPlug
addSerializer(PostContingencyResult.class, new PostContingencyResultSerializer());
addSerializer(LimitViolationsResult.class, new LimitViolationsResultSerializer());
addSerializer(LimitViolation.class, new LimitViolationSerializer());
addSerializer(ViolationLocation.class, new ViolationLocationSerializer());
addSerializer(PreContingencyResult.class, new PreContingencyResultSerializer());
addSerializer(BusResult.class, new BusResultSerializer());
addSerializer(BranchResult.class, new BranchResultSerializer());
Expand All @@ -58,6 +59,7 @@ protected AbstractSecurityAnalysisJsonModule(Collection<SecurityAnalysisJsonPlug
addDeserializer(PostContingencyResult.class, new PostContingencyResultDeserializer());
addDeserializer(LimitViolationsResult.class, new LimitViolationResultDeserializer());
addDeserializer(LimitViolation.class, new LimitViolationDeserializer());
addDeserializer(ViolationLocation.class, new ViolationLocationDeserializer());
addDeserializer(PreContingencyResult.class, new PreContingencyResultDeserializer());
addDeserializer(BusResult.class, new BusResultDeserializer());
addDeserializer(BranchResult.class, new BranchResultDeserializer());
Expand Down
Loading

0 comments on commit 5eefd6c

Please sign in to comment.