Skip to content

Commit

Permalink
Voltage angle limit (#2657)
Browse files Browse the repository at this point in the history
Signed-off-by: Bertrand Rix <bertrand.rix@artelys.com>
Co-authored-by: José Antonio Marqués <marquesja@aia.es>
Co-authored-by: Luma <zamarrenolm@aia.es>
Co-authored-by: Anne Tilloy <anne.tilloy@rte-france.com>
Co-authored-by: Geoffroy Jamgotchian <geoffroy.jamgotchian@rte-france.com>
  • Loading branch information
5 people authored Sep 14, 2023
1 parent 101549a commit 67216f4
Show file tree
Hide file tree
Showing 43 changed files with 1,284 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ private void readBoundariesAndTerminals(NetworkXmlReaderContext networkContext,
case "terminal":
id = networkContext.getAnonymizer().deanonymizeString(networkContext.getReader().getAttributeValue(null, "id"));
side = networkContext.getReader().getAttributeValue(null, "side");
cgmesControlArea.add(TerminalRefXml.readTerminalRef(network, id, side));
cgmesControlArea.add(TerminalRefXml.resolve(id, side, network));
break;
default:
throw new PowsyblException("Unknown element name <" + reader.getLocalName() + "> in <controlArea>");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ public enum LimitType {
ACTIVE_POWER,
APPARENT_POWER,
CURRENT,
VOLTAGE
VOLTAGE,
VOLTAGE_ANGLE
}
21 changes: 21 additions & 0 deletions iidm/iidm-api/src/main/java/com/powsybl/iidm/network/Network.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.powsybl.commons.reporter.Reporter;
import com.powsybl.computation.ComputationManager;
import com.powsybl.computation.local.LocalComputationManager;

import org.joda.time.DateTime;

import java.io.IOException;
Expand Down Expand Up @@ -1168,6 +1169,26 @@ default int getConnectableCount() {
*/
BusView getBusView();

/**
* Get a builder to create a new VoltageAngleLimit.
*/
VoltageAngleLimitAdder newVoltageAngleLimit();

/**
* Get all voltageAngleLimits.
*/
Iterable<VoltageAngleLimit> getVoltageAngleLimits();

/**
* Get all voltageAngleLimits.
*/
Stream<VoltageAngleLimit> getVoltageAngleLimitsStream();

/**
* Get voltage angle limit with id
*/
VoltageAngleLimit getVoltageAngleLimit(String id);

/**
* Merge with an other network. At the end of the merge the other network
* is empty.
Expand Down
51 changes: 51 additions & 0 deletions iidm/iidm-api/src/main/java/com/powsybl/iidm/network/Terminal.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
*/
package com.powsybl.iidm.network;

import com.powsybl.commons.PowsyblException;
import com.powsybl.math.graph.TraversalType;
import com.powsybl.math.graph.TraverseResult;

import java.util.Optional;

/**
* An equipment connection point in a substation topology.
*
Expand Down Expand Up @@ -207,4 +210,52 @@ interface TopologyTraverser {
TraverseResult traverse(Switch aSwitch);

}

static Optional<ThreeSides> getConnectableSide(Terminal terminal) {
Connectable<?> c = terminal.getConnectable();
if (c instanceof Injection) {
return Optional.empty();
} else if (c instanceof Branch<?> branch) {
return Optional.of(toSide(branch.getSide(terminal)));
} else if (c instanceof ThreeWindingsTransformer transformer) {
return Optional.of(toSide(transformer.getSide(terminal)));
} else {
throw new IllegalStateException("Unexpected Connectable instance: " + c.getClass());
}
}

private static ThreeSides toSide(Branch.Side side) {
return switch (side) {
case ONE -> ThreeSides.ONE;
case TWO -> ThreeSides.TWO;
};
}

private static ThreeSides toSide(ThreeWindingsTransformer.Side side) {
return switch (side) {
case ONE -> ThreeSides.ONE;
case TWO -> ThreeSides.TWO;
case THREE -> ThreeSides.THREE;
};
}

static Terminal getTerminal(Connectable<?> connectable, ThreeSides side) {
if (connectable instanceof Injection<?> injection) {
return injection.getTerminal();
} else if (connectable instanceof Branch<?> branch) {
return switch (side) {
case ONE -> branch.getTerminal1();
case TWO -> branch.getTerminal2();
case THREE -> throw new IllegalStateException("Unexpected Branch side: " + side.name());
};
} else if (connectable instanceof ThreeWindingsTransformer transformer) {
return switch (side) {
case ONE -> transformer.getLeg1().getTerminal();
case TWO -> transformer.getLeg2().getTerminal();
case THREE -> transformer.getLeg3().getTerminal();
};
} else {
throw new PowsyblException("Unexpected terminal reference identifiable instance: " + connectable.getClass());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* 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.iidm.network;

/*
@author Bertrand Rix <bertrand.rix at artelys.com>
*/
public enum ThreeSides {
ONE,
TWO,
THREE
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* 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.iidm.network;

import java.util.OptionalDouble;

/**
* @author Luma Zamarreño <zamarrenolm at aia.es>
* @author José Antonio Marqués <marquesja at aia.es>
* @author Bertrand Rix <bertrand.rix at artelys.com>
*/
public interface VoltageAngleLimit extends OperationalLimits {

@Override
default LimitType getLimitType() {
return LimitType.VOLTAGE_ANGLE;
}

/**
* Return the mandatory name.
*/
String getId();

/**
* A voltage angle limit is compared to the difference between the bus angle associated to the terminal from and
* the bus angle associated to the terminal to. Difference = to - from.
*/
Terminal getTerminalFrom();

/**
* A voltage angle limit is compared to the difference between the bus angle associated to the terminal from and
* the bus angle associated to the terminal to. Difference = to - from.
*/
Terminal getTerminalTo();

/**
* Get the low voltage angle limit value
*/
OptionalDouble getLowLimit();

/**
* Get the high voltage angle limit value
*/
OptionalDouble getHighLimit();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* 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.iidm.network;

/**
* @author Luma Zamarreño <zamarrenolm at aia.es>
* @author José Antonio Marqués <marquesja at aia.es>
*/

public interface VoltageAngleLimitAdder extends OperationalLimitsAdder<VoltageAngleLimit, VoltageAngleLimitAdder> {

VoltageAngleLimitAdder setId(String name);

VoltageAngleLimitAdder from(Terminal from);

VoltageAngleLimitAdder to(Terminal to);

VoltageAngleLimitAdder setLowLimit(double lowLimit);

VoltageAngleLimitAdder setHighLimit(double highLimit);
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class NetworkImpl extends AbstractIdentifiable<Network> implements Network, Vari

private final NetworkIndex index = new NetworkIndex();

private final Map<String, VoltageAngleLimit> voltageAngleLimitsIndex = new LinkedHashMap<>();

private final VariantManagerImpl variantManager;

private final NetworkListenerList listeners = new NetworkListenerList();
Expand Down Expand Up @@ -197,6 +199,25 @@ public NetworkIndex getIndex() {
return index;
}

public Map<String, VoltageAngleLimit> getVoltageAngleLimitsIndex() {
return voltageAngleLimitsIndex;
}

@Override
public VoltageAngleLimit getVoltageAngleLimit(String id) {
return voltageAngleLimitsIndex.get(id);
}

@Override
public Stream<VoltageAngleLimit> getVoltageAngleLimitsStream() {
return voltageAngleLimitsIndex.values().stream();
}

@Override
public Iterable<VoltageAngleLimit> getVoltageAngleLimits() {
return voltageAngleLimitsIndex.values();
}

@Override
public NetworkImpl getNetwork() {
return this;
Expand Down Expand Up @@ -708,6 +729,11 @@ public int getConnectableCount() {
return Ints.checkedCast(getConnectableStream().count());
}

@Override
public VoltageAngleLimitAdder newVoltageAngleLimit() {
return new VoltageAngleLimitAdderImpl(ref);
}

@Override
public BusBreakerViewImpl getBusBreakerView() {
return busBreakerView;
Expand Down Expand Up @@ -903,6 +929,15 @@ public void merge(Network other) {
}
}

//Check mergeability of voltage angle limits
Set<String> intersectionVoltageAngleLimits = getVoltageAngleLimitsIndex().keySet().stream()
.filter(otherNetwork.getVoltageAngleLimitsIndex()::containsKey)
.collect(Collectors.toSet());
if (!intersectionVoltageAngleLimits.isEmpty()) {
throw new PowsyblException("The following voltage angle limit(s) exist(s) in both networks: "
+ intersectionVoltageAngleLimits);
}

// try to find dangling lines couples
List<DanglingLinePair> lines = new ArrayList<>();
Map<String, List<DanglingLine>> dl1byXnodeCode = new HashMap<>();
Expand All @@ -927,6 +962,8 @@ public void merge(Network other) {

replaceDanglingLineByLine(lines);

other.getVoltageAngleLimits().forEach(l -> getVoltageAngleLimitsIndex().put(l.getId(), l));

// update the source format
if (!sourceFormat.equals(otherNetwork.sourceFormat)) {
sourceFormat = "hybrid";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* 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.iidm.network.impl;

import com.powsybl.commons.PowsyblException;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.impl.util.Ref;

/**
*
* @author Luma Zamarreño <zamarrenolm at aia.es>
* @author José Antonio Marqués <marquesja at aia.es>
*/
class VoltageAngleLimitAdderImpl implements VoltageAngleLimitAdder {

private final Ref<NetworkImpl> networkRef;
private String id;
private Terminal from;
private Terminal to;
private double lowLimit = Double.NaN;

private double highLimit = Double.NaN;

VoltageAngleLimitAdderImpl(Ref<NetworkImpl> networkRef) {
this.networkRef = networkRef;
}

@Override
public VoltageAngleLimitAdderImpl setId(String id) {
this.id = id;
return this;
}

@Override
public VoltageAngleLimitAdderImpl from(Terminal from) {
this.from = from;
return this;
}

@Override
public VoltageAngleLimitAdderImpl to(Terminal to) {
this.to = to;
return this;
}

@Override
public VoltageAngleLimitAdderImpl setLowLimit(double lowLimit) {
this.lowLimit = lowLimit;
return this;
}

@Override
public VoltageAngleLimitAdderImpl setHighLimit(double highLimit) {
this.highLimit = highLimit;
return this;
}

@Override
public VoltageAngleLimit add() {
if (id == null) {
throw new IllegalStateException("Voltage angle limit id is mandatory.");
}
if (networkRef.get().getVoltageAngleLimitsIndex().containsKey(id)) {
throw new PowsyblException("The network " + networkRef.get().getId()
+ " already contains a voltage angle limit with the id '" + id + "'");
}
if (!Double.isNaN(lowLimit) && !Double.isNaN(highLimit) && lowLimit >= highLimit) {
throw new IllegalStateException("Voltage angle low limit must be lower than the high limit.");
}

VoltageAngleLimit voltageAngleLimit = new VoltageAngleLimitImpl(id, from, to, lowLimit, highLimit);
networkRef.get().getVoltageAngleLimitsIndex().put(id, voltageAngleLimit);
return voltageAngleLimit;
}
}
Loading

0 comments on commit 67216f4

Please sign in to comment.