LimitViolationDetectorForThreeWindingsTransformerTest.java
/**
* Copyright (c) 2023, 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.detectors;
import com.powsybl.contingency.Contingency;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.test.ThreeWindingsTransformerNetworkFactory;
import com.powsybl.security.LimitViolation;
import com.powsybl.security.LimitViolationType;
import com.powsybl.security.LimitViolations;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
class LimitViolationDetectorForThreeWindingsTransformerTest {
private Network network;
private ThreeWindingsTransformer threeWindingsTransformer;
private Contingency contingency1;
private Contingency contingency2;
private VoltageLevel genVoltageLevel1;
private VoltageLevel loadVoltageLevel2;
private VoltageLevel loadVoltageLevel3;
private List<LimitViolation> collectedViolations;
private void doCheckCurrent(Contingency contingency, ThreeWindingsTransformer transformer, ThreeSides side, Consumer<LimitViolation> consumer) {
if (transformer == threeWindingsTransformer && side == ThreeSides.TWO) {
consumer.accept(LimitViolations.current()
.subject(transformer.getId())
.duration(1200)
.side(side)
.value(1500)
.limit(1200)
.build());
}
if (contingency == contingency1
&& transformer == threeWindingsTransformer && side == ThreeSides.THREE) {
consumer.accept(LimitViolations.current()
.subject(transformer.getId())
.duration(1200)
.side(side)
.value(1500)
.limit(1200)
.build());
}
}
private void doCheckVoltage(Contingency contingency, Bus bus, Consumer<LimitViolation> consumer) {
if (bus.getVoltageLevel() == loadVoltageLevel2) {
consumer.accept(LimitViolations.highVoltage()
.subject(bus.getVoltageLevel().getId())
.value(500)
.limit(420)
.build());
}
if (bus.getVoltageLevel() == genVoltageLevel1) {
consumer.accept(LimitViolations.lowVoltage()
.subject(bus.getVoltageLevel().getId())
.value(350)
.limit(380)
.build());
}
if (contingency == contingency1 && bus.getVoltageLevel() == loadVoltageLevel3) {
consumer.accept(LimitViolations.highVoltage()
.subject(bus.getVoltageLevel().getId())
.value(500)
.limit(420)
.build());
}
}
private LimitViolationDetector contingencyBlindDetector() {
return new AbstractContingencyBlindDetector() {
@Override
public void checkCurrent(Branch branch, TwoSides side, double currentValue, Consumer<LimitViolation> consumer) {
throw new UnsupportedOperationException("Not used in this test!");
}
@Override
public void checkCurrent(ThreeWindingsTransformer transformer, ThreeSides side, double currentValue, Consumer<LimitViolation> consumer) {
doCheckCurrent(null, transformer, side, consumer);
}
@Override
public void checkVoltage(Bus bus, double voltageValue, Consumer<LimitViolation> consumer) {
doCheckVoltage(null, bus, consumer);
}
@Override
public void checkVoltageAngle(VoltageAngleLimit voltageAngleLimit, double voltageAngleDifference, Consumer<LimitViolation> consumer) {
throw new UnsupportedOperationException("Not used in this test!");
}
@Override
public void checkActivePower(Branch branch, TwoSides side, double currentValue, Consumer<LimitViolation> consumer) {
throw new UnsupportedOperationException("Not used in this test!");
}
@Override
public void checkApparentPower(Branch branch, TwoSides side, double currentValue, Consumer<LimitViolation> consumer) {
throw new UnsupportedOperationException("Not used in this test!");
}
@Override
public void checkActivePower(ThreeWindingsTransformer transformer, ThreeSides side, double currentValue, Consumer<LimitViolation> consumer) {
throw new UnsupportedOperationException("Not used in this test!");
}
@Override
public void checkApparentPower(ThreeWindingsTransformer transformer, ThreeSides side, double currentValue, Consumer<LimitViolation> consumer) {
throw new UnsupportedOperationException("Not used in this test!");
}
};
}
private LimitViolationDetector contingencyBasedDetector() {
return new AbstractLimitViolationDetector() {
@Override
public void checkCurrent(Contingency contingency, Branch branch, TwoSides side, double currentValue, Consumer<LimitViolation> consumer) {
throw new UnsupportedOperationException("Not used in this test!");
}
@Override
public void checkCurrent(Contingency contingency, ThreeWindingsTransformer transformer, ThreeSides side, double currentValue, Consumer<LimitViolation> consumer) {
doCheckCurrent(contingency, transformer, side, consumer);
}
@Override
public void checkVoltage(Contingency contingency, Bus bus, double voltageValue, Consumer<LimitViolation> consumer) {
doCheckVoltage(contingency, bus, consumer);
}
@Override
public void checkVoltageAngle(Contingency contingency, VoltageAngleLimit voltageAngleLimit, double voltageAngleDifference, Consumer<LimitViolation> consumer) {
throw new UnsupportedOperationException("Not used in this test!");
}
@Override
public void checkActivePower(Branch branch, TwoSides side, double currentValue, Consumer<LimitViolation> consumer) {
throw new UnsupportedOperationException("Not used in this test!");
}
@Override
public void checkApparentPower(Branch branch, TwoSides side, double currentValue, Consumer<LimitViolation> consumer) {
throw new UnsupportedOperationException("Not used in this test!");
}
@Override
public void checkActivePower(ThreeWindingsTransformer transformer, ThreeSides side, double currentValue, Consumer<LimitViolation> consumer) {
throw new UnsupportedOperationException("Not used in this test!");
}
@Override
public void checkApparentPower(ThreeWindingsTransformer transformer, ThreeSides side, double currentValue, Consumer<LimitViolation> consumer) {
throw new UnsupportedOperationException("Not used in this test!");
}
@Override
public void checkPermanentLimit(Branch<?> branch, TwoSides side, double limitReductionValue, double value, Consumer<LimitViolation> consumer, LimitType type) {
throw new UnsupportedOperationException("Not used in this test!");
}
};
}
@BeforeEach
void setUp() {
network = ThreeWindingsTransformerNetworkFactory.createWithCurrentLimits();
threeWindingsTransformer = network.getThreeWindingsTransformer("3WT");
genVoltageLevel1 = network.getVoltageLevel("VL_132");
loadVoltageLevel2 = network.getVoltageLevel("VL_33");
loadVoltageLevel3 = network.getVoltageLevel("VL_11");
contingency1 = new Contingency("cont1");
contingency2 = new Contingency("cont2");
collectedViolations = new ArrayList<>();
}
@Test
void networkHas3Violations() {
contingencyBasedDetector().checkAll(network, collectedViolations::add);
assertEquals(3, collectedViolations.size());
assertEquals(1, collectedViolations.stream().filter(l -> l.getLimitType() == LimitViolationType.CURRENT).count());
assertEquals(1, collectedViolations.stream().filter(l -> l.getSubjectId().equals("3WT")).count());
assertEquals(1, collectedViolations.stream().filter(l -> l.getLimitType() == LimitViolationType.LOW_VOLTAGE).count());
assertEquals(1, collectedViolations.stream().filter(l -> l.getLimitType() == LimitViolationType.HIGH_VOLTAGE).count());
}
@Test
void transformerHas1Violations() {
contingencyBasedDetector().checkCurrent(network.getThreeWindingsTransformer("3WT"), collectedViolations::add);
assertEquals(1, collectedViolations.size());
}
@Test
void genVoltageLevel1Has1Violation() {
contingencyBasedDetector().checkVoltage(network.getVoltageLevel("VL_132"), collectedViolations::add);
assertEquals(1, collectedViolations.size());
assertSame(LimitViolationType.LOW_VOLTAGE, collectedViolations.get(0).getLimitType());
}
@Test
void loadVoltageLeve2Has1Violation() {
contingencyBasedDetector().checkVoltage(network.getVoltageLevel("VL_33"), collectedViolations::add);
assertEquals(1, collectedViolations.size());
assertSame(LimitViolationType.HIGH_VOLTAGE, collectedViolations.get(0).getLimitType());
}
@Test
void networkHas5ViolationsOnContingency1() {
contingencyBasedDetector().checkAll(contingency1, network, collectedViolations::add);
assertEquals(5, collectedViolations.size());
assertEquals(2, collectedViolations.stream().filter(l -> l.getLimitType() == LimitViolationType.CURRENT).count());
assertEquals(1, collectedViolations.stream().filter(l -> l.getLimitType() == LimitViolationType.LOW_VOLTAGE).count());
assertEquals(2, collectedViolations.stream().filter(l -> l.getLimitType() == LimitViolationType.HIGH_VOLTAGE).count());
}
@Test
void networkHas6ViolationsOnContingency2() {
contingencyBasedDetector().checkAll(contingency2, network, collectedViolations::add);
assertEquals(3, collectedViolations.size());
assertEquals(1, collectedViolations.stream().filter(l -> l.getLimitType() == LimitViolationType.CURRENT).count());
assertEquals(1, collectedViolations.stream().filter(l -> l.getLimitType() == LimitViolationType.LOW_VOLTAGE).count());
assertEquals(1, collectedViolations.stream().filter(l -> l.getLimitType() == LimitViolationType.HIGH_VOLTAGE).count());
}
@Test
void networkHas6ViolationsOnContingency1WithContingencyBlindDetector() {
contingencyBlindDetector().checkAll(contingency1, network, collectedViolations::add);
assertEquals(3, collectedViolations.size());
assertEquals(1, collectedViolations.stream().filter(l -> l.getLimitType() == LimitViolationType.CURRENT).count());
assertEquals(1, collectedViolations.stream().filter(l -> l.getLimitType() == LimitViolationType.LOW_VOLTAGE).count());
assertEquals(1, collectedViolations.stream().filter(l -> l.getLimitType() == LimitViolationType.HIGH_VOLTAGE).count());
}
@Test
void transformerHas2ViolationOnContingency1() {
contingencyBasedDetector().checkCurrent(contingency1, threeWindingsTransformer, collectedViolations::add);
assertEquals(2, collectedViolations.size());
}
@Test
void transformerSide1HasNoViolationOnContingency1WithContingencyBlindDetector() {
LimitViolationDetector detector = contingencyBlindDetector();
detector.checkCurrent(contingency1, threeWindingsTransformer, ThreeSides.ONE, collectedViolations::add);
assertEquals(0, collectedViolations.size());
detector.checkCurrent(contingency1, threeWindingsTransformer, ThreeSides.ONE, 5000, collectedViolations::add);
assertEquals(0, collectedViolations.size());
detector.checkCurrent(contingency1, threeWindingsTransformer, collectedViolations::add);
assertEquals(0, collectedViolations.stream().filter(l -> l.getSide() == ThreeSides.ONE).count());
}
@Test
void loadVoltageLevelHasNoViolationOnContingency1WithContingencyBlindDetector() {
LimitViolationDetector detector = contingencyBlindDetector();
detector.checkVoltage(contingency1, loadVoltageLevel3, collectedViolations::add);
Bus loadBus = loadVoltageLevel3.getBusView().getBusStream().findFirst().orElseThrow(IllegalStateException::new);
detector.checkVoltage(contingency1, loadBus, collectedViolations::add);
detector.checkVoltage(contingency1, loadBus, 500, collectedViolations::add);
assertEquals(0, collectedViolations.size());
}
}