RevertConnectVoltageLevelOnLine.java
/**
* Copyright (c) 2022, 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.iidm.modification.topology;
import com.powsybl.commons.report.ReportNode;
import com.powsybl.computation.ComputationManager;
import com.powsybl.iidm.modification.AbstractNetworkModification;
import com.powsybl.iidm.modification.NetworkModificationImpact;
import com.powsybl.iidm.network.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import static com.powsybl.iidm.modification.topology.TopologyModificationUtils.*;
import static com.powsybl.iidm.modification.util.ModificationLogs.logOrThrow;
import static com.powsybl.iidm.modification.util.ModificationReports.*;
/**
* This method reverses the action done in the ConnectVoltageLevelOnLine class :
* it replaces 2 existing lines (with the same voltage level at one of their side) with a new line,
* and eventually removes the voltage level in common (switching voltage level), if it contains no equipments anymore, except bus or bus bar section
* <p>
* Before modification:
* <pre>
* VL1 ----------- switching voltage level ----------- VL2
* (line1) (line2)</pre>
* After modification:
* <pre>
* VL1 ------------------------- VL2
* (line)</pre>
* @author Franck Lecuyer {@literal <franck.lecuyer at rte-france.com>}
*/
public class RevertConnectVoltageLevelOnLine extends AbstractNetworkModification {
private static final Logger LOG = LoggerFactory.getLogger(RevertConnectVoltageLevelOnLine.class);
private final String line1Id;
private final String line2Id;
private final String lineId;
private final String lineName;
/**
* Constructor.
* <p>
* NB: This constructor is package-private, Please use {@link RevertConnectVoltageLevelOnLineBuilder} instead.
*/
RevertConnectVoltageLevelOnLine(String line1Id, String line2Id, String lineId, String lineName) {
this.line1Id = Objects.requireNonNull(line1Id);
this.line2Id = Objects.requireNonNull(line2Id);
this.lineId = Objects.requireNonNull(lineId);
this.lineName = lineName;
}
@Override
public String getName() {
return "RevertConnectVoltageLevelOnLine";
}
private static Line checkAndGetLine(Network network, String lineId, ReportNode reportNode, boolean throwException) {
Line line = network.getLine(lineId);
if (line == null) {
notFoundLineReport(reportNode, lineId);
logOrThrow(throwException, String.format("Line %s is not found", lineId));
return null;
}
return line;
}
@Override
public void apply(Network network, NamingStrategy namingStrategy, boolean throwException,
ComputationManager computationManager, ReportNode reportNode) {
Line line1 = checkAndGetLine(network, line1Id, reportNode, throwException);
Line line2 = checkAndGetLine(network, line2Id, reportNode, throwException);
if (line1 == null || line2 == null) {
return;
}
// Check and find the voltage level in common
Set<String> vlIds = new HashSet<>();
String line1VlId1 = line1.getTerminal1().getVoltageLevel().getId();
String line1VlId2 = line1.getTerminal2().getVoltageLevel().getId();
String line2VlId1 = line2.getTerminal1().getVoltageLevel().getId();
String line2VlId2 = line2.getTerminal2().getVoltageLevel().getId();
String commonVlId = "";
vlIds.add(line1VlId1);
if (!vlIds.add(line1VlId2)) {
commonVlId = line1VlId2;
}
if (!vlIds.add(line2VlId1)) {
commonVlId = line2VlId1;
}
if (!vlIds.add(line2VlId2)) {
commonVlId = line2VlId2;
}
if (vlIds.size() != 3) {
noVoltageLevelInCommonReport(reportNode, line1Id, line2Id);
logOrThrow(throwException, String.format("Lines %s and %s should have one and only one voltage level in common at their extremities", line1Id, line2Id));
return;
}
VoltageLevel commonVl = network.getVoltageLevel(commonVlId);
TwoSides line1Side1 = line1VlId1.equals(commonVlId) ? TwoSides.TWO : TwoSides.ONE;
TwoSides line1Side2 = line1Side1 == TwoSides.ONE ? TwoSides.TWO : TwoSides.ONE;
TwoSides line2Side2 = line2VlId1.equals(commonVlId) ? TwoSides.TWO : TwoSides.ONE;
TwoSides line2Side1 = line2Side2 == TwoSides.ONE ? TwoSides.TWO : TwoSides.ONE;
// Set parameters of the new line replacing the two existing lines
LineAdder lineAdder = createLineAdder(lineId, lineName, line1Side1 == TwoSides.TWO ? line1VlId2 : line1VlId1,
line2Side2 == TwoSides.TWO ? line2VlId2 : line2VlId1, network, line1, line2);
attachLine(line1.getTerminal(line1Side1), lineAdder, (bus, adder) -> adder.setConnectableBus1(bus.getId()), (bus, adder) -> adder.setBus1(bus.getId()), (node, adder) -> adder.setNode1(node));
attachLine(line2.getTerminal(line2Side2), lineAdder, (bus, adder) -> adder.setConnectableBus2(bus.getId()), (bus, adder) -> adder.setBus2(bus.getId()), (node, adder) -> adder.setNode2(node));
// get line1 limits
LoadingLimitsBags limitsLine1Side1 = new LoadingLimitsBags(() -> line1.getActivePowerLimits(line1Side1), () -> line1.getApparentPowerLimits(line1Side1), () -> line1.getCurrentLimits(line1Side1));
LoadingLimitsBags limitsLine1Side2 = new LoadingLimitsBags(() -> line1.getActivePowerLimits(line1Side2), () -> line1.getApparentPowerLimits(line1Side2), () -> line1.getCurrentLimits(line1Side2));
// get line2 limits
LoadingLimitsBags limitsLine2Side1 = new LoadingLimitsBags(() -> line2.getActivePowerLimits(line2Side1), () -> line2.getApparentPowerLimits(line2Side1), () -> line2.getCurrentLimits(line2Side1));
LoadingLimitsBags limitsLine2Side2 = new LoadingLimitsBags(() -> line2.getActivePowerLimits(line2Side2), () -> line2.getApparentPowerLimits(line2Side2), () -> line2.getCurrentLimits(line2Side2));
// Remove the two existing lines
line1.remove();
removedLineReport(reportNode, line1Id);
LOG.info("Line {} removed", line1Id);
line2.remove();
removedLineReport(reportNode, line2Id);
LOG.info("Line {} removed", line2Id);
// Create the new line
Line line = lineAdder.add();
LoadingLimitsBags limitsSide1 = mergeLimits(line1Id, limitsLine1Side1, limitsLine1Side2, reportNode);
LoadingLimitsBags limitsSide2 = mergeLimits(line2Id, limitsLine2Side2, limitsLine2Side1, reportNode);
addLoadingLimits(line, limitsSide1, TwoSides.ONE);
addLoadingLimits(line, limitsSide2, TwoSides.TWO);
createdLineReport(reportNode, lineId);
LOG.info("New line {} created, replacing lines {} and {}", lineId, line1Id, line2Id);
// remove voltage level and substation in common, if necessary
removeVoltageLevelAndSubstation(commonVl, reportNode);
}
@Override
public NetworkModificationImpact hasImpactOnNetwork(Network network) {
impact = DEFAULT_IMPACT;
Line line1 = network.getLine(line1Id);
Line line2 = network.getLine(line2Id);
if (line1 == null || line2 == null) {
impact = NetworkModificationImpact.CANNOT_BE_APPLIED;
} else {
Set<String> vlIds = new HashSet<>();
vlIds.add(line1.getTerminal1().getVoltageLevel().getId());
vlIds.add(line1.getTerminal2().getVoltageLevel().getId());
vlIds.add(line2.getTerminal1().getVoltageLevel().getId());
vlIds.add(line2.getTerminal2().getVoltageLevel().getId());
impact = vlIds.size() == 3 ? NetworkModificationImpact.HAS_IMPACT_ON_NETWORK : NetworkModificationImpact.CANNOT_BE_APPLIED;
}
return impact;
}
public String getLine1Id() {
return line1Id;
}
public String getLine2Id() {
return line2Id;
}
public String getLineId() {
return lineId;
}
public String getLineName() {
return lineName;
}
}