Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Voltage level topology model conversion #3199

Merged
merged 60 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
65d8a01
Refactor voltage level topology implementation
geofjamg Nov 5, 2024
5272a31
Wip
geofjamg Nov 5, 2024
0cdc075
Voltage level topology model conversion
geofjamg Nov 5, 2024
706c9eb
Fix
geofjamg Nov 5, 2024
8684af9
Wip
geofjamg Nov 6, 2024
06b2f03
Merge branch 'main' into topology_model_conversion
geofjamg Nov 7, 2024
6275991
Clean
geofjamg Nov 7, 2024
fde8da4
Add network events to IIDM API
geofjamg Nov 7, 2024
c380bfa
Add unit tests
geofjamg Nov 8, 2024
3dd4c87
Clean
geofjamg Nov 8, 2024
bd56b88
Wip
geofjamg Nov 8, 2024
4d5ff02
Clean all deprecated methods and remame element to property
geofjamg Nov 8, 2024
1f8f266
Clean
geofjamg Nov 8, 2024
43defb6
Clean
geofjamg Nov 8, 2024
7ae843d
Merge branch 'main' into network_events
geofjamg Nov 12, 2024
9ac7c91
Rename attribute to key and Property to Properties
geofjamg Nov 12, 2024
e9c698a
Clean
geofjamg Nov 12, 2024
44eccdd
Merge branch 'network_events' into topology_model_conversion
geofjamg Nov 12, 2024
65b8f55
Merge
geofjamg Nov 12, 2024
cbd28a4
Clean
geofjamg Nov 12, 2024
96ffd8a
Merge branch 'network_events' into topology_model_conversion
geofjamg Nov 12, 2024
32f6b9e
Merge branch 'main' into topology_model_conversion
geofjamg Nov 12, 2024
3646956
Fix regulating terminals
geofjamg Nov 12, 2024
f6ed9a3
Fix busbar section
geofjamg Nov 14, 2024
21ff2ed
Fix
geofjamg Nov 14, 2024
4d6d159
Merge branch 'main' into topology_model_conversion
geofjamg Nov 20, 2024
6bc9f0c
Fix extensions dangling terminal references because
geofjamg Nov 21, 2024
431ac2d
Migrate ReferenceTerminals extension
geofjamg Nov 21, 2024
c5ff06f
Fix
geofjamg Nov 21, 2024
1e11d50
Add network check
geofjamg Nov 21, 2024
7d47478
Wip
geofjamg Nov 21, 2024
fde3d8f
Wip
geofjamg Nov 21, 2024
3b41432
Use in areas
geofjamg Nov 22, 2024
fb1c9ef
Wip
geofjamg Nov 22, 2024
1a9a32f
Wip
geofjamg Nov 22, 2024
7261241
Wip
geofjamg Nov 22, 2024
8e16bf6
Merge branch 'main' into fix_dangling_terminal_references
geofjamg Nov 25, 2024
e4e3082
Fix
geofjamg Nov 25, 2024
1887035
Add warning
geofjamg Nov 25, 2024
b2bb7e5
Fix RemoteReactivePowerControl
geofjamg Nov 25, 2024
ead898e
Fix Sonar issue
geofjamg Nov 25, 2024
1208d0e
Rename dependant to referrer
geofjamg Nov 27, 2024
929c7ea
Merge branch 'main' into fix_dangling_terminal_references
geofjamg Nov 27, 2024
01c2aff
Merge branch 'fix_dangling_terminal_references' into topology_model_c…
geofjamg Nov 27, 2024
7d67cc5
Merge
geofjamg Nov 27, 2024
074852a
Merge branch 'main' into topology_model_conversion
geofjamg Nov 28, 2024
c2af5cf
Fix merge
geofjamg Nov 28, 2024
a797b15
Fix
geofjamg Nov 28, 2024
0241fe5
Merge branch 'main' into topology_model_conversion
geofjamg Dec 3, 2024
44af0c6
Review fixes
geofjamg Dec 4, 2024
39a6a9c
Simplify
geofjamg Dec 4, 2024
44d8e42
Simplify
geofjamg Dec 4, 2024
11b9ea1
Refactoring
geofjamg Dec 4, 2024
11a93f0
Merge branch 'main' into topology_model_conversion
geofjamg Dec 4, 2024
f28112a
Add unit test
geofjamg Dec 4, 2024
bd6e5eb
Add unit test
geofjamg Dec 4, 2024
a9e6430
Clean
geofjamg Dec 4, 2024
9f486bd
Clean
geofjamg Dec 4, 2024
6ea6dfc
Add unit test
geofjamg Dec 4, 2024
1571d78
Add unit test
geofjamg Dec 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1355,6 +1355,15 @@ default void remove() {
*/
BusView getBusView();

/**
* Convert the topology model to another one. Notice that when converting from a
* node/breaker model to a bus/breaker model, we definitely lost some information as
* we are converting to a simpler topology model.
*
* @param newTopologyKind the new topology model kind
*/
void convertToTopology(TopologyKind newTopologyKind);

/**
* Print an ASCII representation of the topology on the standard ouput.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public void allocateVariantArrayElement(int[] indexes, int sourceIndex) {
}
}

protected void move(TerminalExt oldTerminal, TopologyPoint oldTopologyPoint, int node, String voltageLevelId) {
protected void move(TerminalExt oldTerminal, int node, String voltageLevelId) {
VoltageLevelExt voltageLevel = getNetwork().getVoltageLevel(voltageLevelId);
if (voltageLevel == null) {
throw new PowsyblException("Voltage level '" + voltageLevelId + "' not found");
Expand All @@ -152,10 +152,10 @@ protected void move(TerminalExt oldTerminal, TopologyPoint oldTopologyPoint, int
.build();

// detach the terminal from its previous voltage level
attachTerminal(oldTerminal, oldTopologyPoint, voltageLevel, terminalExt);
replaceTerminal(oldTerminal, voltageLevel.getTopologyModel(), terminalExt, true);
}

protected void move(TerminalExt oldTerminal, TopologyPoint oldTopologyPoint, String busId, boolean connected) {
protected void move(TerminalExt oldTerminal, String busId, boolean connected) {
Bus bus = getNetwork().getBusBreakerView().getBus(busId);
if (bus == null) {
throw new PowsyblException("Bus '" + busId + "' not found");
Expand All @@ -175,22 +175,43 @@ protected void move(TerminalExt oldTerminal, TopologyPoint oldTopologyPoint, Str
.build();

// detach the terminal from its previous voltage level
attachTerminal(oldTerminal, oldTopologyPoint, (VoltageLevelExt) bus.getVoltageLevel(), terminalExt);
replaceTerminal(oldTerminal, ((VoltageLevelExt) bus.getVoltageLevel()).getTopologyModel(), terminalExt, true);
}

private void attachTerminal(TerminalExt oldTerminal, TopologyPoint oldTopologyPoint, VoltageLevelExt voltageLevel, TerminalExt terminalExt) {
void replaceTerminal(TerminalExt oldTerminal, TopologyPoint oldTopologyPoint, TerminalExt newTerminalExt, boolean notify) {
flo-dup marked this conversation as resolved.
Show resolved Hide resolved
Objects.requireNonNull(oldTerminal);
Objects.requireNonNull(newTerminalExt);
int iSide = terminals.indexOf(oldTerminal);
if (iSide == -1) {
throw new PowsyblException("Terminal to replace not found");
}
terminals.set(iSide, newTerminalExt);

if (notify) {
notifyUpdate("terminal" + (iSide + 1), oldTopologyPoint, newTerminalExt.getTopologyPoint());
}
}

void replaceTerminal(TerminalExt oldTerminal, TopologyModel newTopologyModel, TerminalExt newTerminalExt, boolean notify) {
Objects.requireNonNull(oldTerminal);
Objects.requireNonNull(newTopologyModel);
Objects.requireNonNull(newTerminalExt);

// first, attach new terminal to connectable and to voltage level of destination, to ensure that the new terminal is valid
terminalExt.setConnectable(this);
voltageLevel.getTopologyModel().attach(terminalExt, false);
newTerminalExt.setConnectable(this);
newTopologyModel.attach(newTerminalExt, false);

// then we can detach the old terminal, as we now know that the new terminal is valid
TopologyPoint oldTopologyPoint = oldTerminal.getTopologyPoint();
oldTerminal.getVoltageLevel().getTopologyModel().detach(oldTerminal);

// replace the old terminal by the new terminal in the connectable
int iSide = terminals.indexOf(oldTerminal);
terminals.set(iSide, terminalExt);
replaceTerminal(oldTerminal, oldTopologyPoint, newTerminalExt, notify);

notifyUpdate("terminal" + (iSide + 1), oldTopologyPoint, terminalExt.getTopologyPoint());
// also update terminal referrers
for (Referrer<Terminal> referrer : oldTerminal.getReferrerManager().getReferrers()) {
referrer.onReferencedReplacement(oldTerminal, newTerminalExt);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@ public void onReferencedRemoval(Terminal removedTerminal) {
// nothing by default
// this is the place for terminal reference cleanup
}

@Override
public void onReferencedReplacement(Terminal oldReferenced, Terminal newReferenced) {
// nothing by default
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@

public class AreaBoundaryImpl implements AreaBoundary {

final Area area;
private final Area area;

final Terminal terminal;
private Terminal terminal;

final Boundary boundary;
private final Boundary boundary;

final boolean ac;
private final boolean ac;

AreaBoundaryImpl(Area area, Terminal terminal, boolean ac) {
this.area = Objects.requireNonNull(area);
Expand Down Expand Up @@ -68,4 +68,12 @@ public double getP() {
public double getQ() {
return boundary != null ? boundary.getQ() : terminal.getQ();
}

void replaceTerminal(Terminal oldTerminal, Terminal newTerminal) {
Objects.requireNonNull(oldTerminal);
Objects.requireNonNull(newTerminal);
if (terminal == oldTerminal) {
terminal = newTerminal;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,31 @@ public class AreaImpl extends AbstractIdentifiable<Area> implements Area {

private final TDoubleArrayList interchangeTarget;

private final Referrer<Terminal> terminalReferrer = this::removeAreaBoundary;
private final Referrer<Terminal> terminalReferrer = new Referrer<>() {
@Override
public void onReferencedRemoval(Terminal terminal) {
removeAreaBoundary(terminal);
}

@Override
public void onReferencedReplacement(Terminal oldTerminal, Terminal newTerminal) {
for (AreaBoundary areaBoundary : areaBoundaries) {
((AreaBoundaryImpl) areaBoundary).replaceTerminal(oldTerminal, newTerminal);
}
}
};

private final Referrer<Boundary> boundaryReferrer = this::removeAreaBoundary;
private final Referrer<Boundary> boundaryReferrer = new Referrer<>() {
@Override
public void onReferencedRemoval(Boundary boundary) {
removeAreaBoundary(boundary);
}

@Override
public void onReferencedReplacement(Boundary oldBoundary, Boundary newBoundary) {
// cannot happen
}
};

AreaImpl(Ref<NetworkImpl> ref, Ref<SubnetworkImpl> subnetworkRef, String id, String name, boolean fictitious, String areaType,
double interchangeTarget) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ public Switch add() {
}

SwitchImpl aSwitch = new SwitchImpl(voltageLevel, id, getName(), isFictitious(), SwitchKind.BREAKER, open, true);
addSwitch(aSwitch, busId1, busId2);
getNetwork().getIndex().checkAndAdd(aSwitch);
addSwitchToTopology(aSwitch, busId1, busId2);
getNetwork().getListeners().notifyCreation(aSwitch);
return aSwitch;
}
Expand Down Expand Up @@ -797,10 +798,9 @@ private void removeAllBuses() {
removedBusesIds.forEach(id -> network.getListeners().notifyAfterRemoval(id));
}

private void addSwitch(SwitchImpl aSwitch, String busId1, String busId2) {
void addSwitchToTopology(SwitchImpl aSwitch, String busId1, String busId2) {
int v1 = getVertex(busId1, true);
int v2 = getVertex(busId2, true);
getNetwork().getIndex().checkAndAdd(aSwitch);
int e = graph.addEdge(v1, v2, aSwitch);
switches.put(aSwitch.getId(), e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void moveConnectable(int node, String voltageLevelId) {
if (removed) {
throw new PowsyblException(UNMODIFIABLE_REMOVED_EQUIPMENT + connectable.id);
}
getConnectable().move(BusTerminal.this, getTopologyPoint(), node, voltageLevelId);
getConnectable().move(BusTerminal.this, node, voltageLevelId);
}
};

Expand Down Expand Up @@ -87,7 +87,7 @@ public void moveConnectable(String busId, boolean connected) {
if (removed) {
throw new PowsyblException(UNMODIFIABLE_REMOVED_EQUIPMENT + connectable.id);
}
getConnectable().move(BusTerminal.this, getTopologyPoint(), busId, connected);
getConnectable().move(BusTerminal.this, busId, connected);
}

};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,16 @@ CalculatedBusTopology getCalculatedBusTopology() {
return variants.get().calculatedBusTopology;
}

void removeSwitchFromTopology(String switchId, boolean notify) {
Integer e = switches.get(switchId);
if (e == null) {
throw new PowsyblException("Switch '" + switchId
+ "' not found in voltage level '" + voltageLevel.getId() + "'");
}
graph.removeEdge(e, notify);
graph.removeIsolatedVertices(notify);
}

private final VoltageLevelExt.NodeBreakerViewExt nodeBreakerView = new VoltageLevelExt.NodeBreakerViewExt() {

private final TIntObjectMap<TDoubleArrayList> fictitiousP0ByNode = TCollections.synchronizedMap(new TIntObjectHashMap<>());
Expand Down Expand Up @@ -873,13 +883,7 @@ public int getSwitchCount() {

@Override
public void removeSwitch(String switchId) {
Integer e = switches.get(switchId);
if (e == null) {
throw new PowsyblException("Switch '" + switchId
+ "' not found in voltage level '" + voltageLevel.getId() + "'");
}
graph.removeEdge(e);
graph.removeIsolatedVertices();
NodeBreakerTopologyModel.this.removeSwitchFromTopology(switchId, true);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void moveConnectable(int node, String voltageLevelId) {
if (removed) {
throw new PowsyblException(UNMODIFIABLE_REMOVED_EQUIPMENT + connectable.id);
}
getConnectable().move(NodeTerminal.this, getTopologyPoint(), node, voltageLevelId);
getConnectable().move(NodeTerminal.this, node, voltageLevelId);
}
};

Expand Down Expand Up @@ -89,7 +89,7 @@ public void moveConnectable(String busId, boolean connected) {
if (removed) {
throw new PowsyblException(UNMODIFIABLE_REMOVED_EQUIPMENT + connectable.id);
}
getConnectable().move(NodeTerminal.this, getTopologyPoint(), busId, connected);
getConnectable().move(NodeTerminal.this, busId, connected);
}

};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,14 @@ public interface Referrer<T> {
* @param removedReferenced The referenced that has been removed from the network.
*/
void onReferencedRemoval(T removedReferenced);

/**
* Called when a referenced object is replaced with another one. Implementations of this method
* should handle any required updates or transfers necessary when the referenced object is
* replaced.
*
* @param oldReferenced The original referenced object that is being replaced.
* @param newReferenced The new referenced object that is taking the place of the old one.
*/
void onReferencedReplacement(T oldReferenced, T newReferenced);
}
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,11 @@ public void onReferencedRemoval(Terminal removedTerminal) {
regulationMode.fill(0, regulationMode.size(), StaticVarCompensator.RegulationMode.OFF.ordinal());
}
}

@Override
public void onReferencedReplacement(Terminal oldReferenced, Terminal newReferenced) {
if (regulatingTerminal == oldReferenced) {
regulatingTerminal = (TerminalExt) newReferenced;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import com.google.common.collect.Lists;
import com.google.common.primitives.Ints;
import com.powsybl.commons.PowsyblException;
import com.powsybl.iidm.network.*;
import com.powsybl.commons.ref.Ref;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.util.ShortIdDictionary;

import java.io.IOException;
Expand Down Expand Up @@ -39,7 +39,7 @@ class VoltageLevelImpl extends AbstractIdentifiable<VoltageLevel> implements Vol

private double highVoltageLimit;

private final AbstractTopologyModel topologyModel;
private AbstractTopologyModel topologyModel;

/** Areas associated to this VoltageLevel, with at most one area for each area type */
private final Set<Area> areas = new LinkedHashSet<>();
Expand Down Expand Up @@ -618,4 +618,83 @@ public void allocateVariantArrayElement(int[] indexes, int sourceIndex) {
super.allocateVariantArrayElement(indexes, sourceIndex);
topologyModel.allocateVariantArrayElement(indexes, sourceIndex);
}

private void convertToBusBreakerModel() {
BusBreakerTopologyModel newTopologyModel = new BusBreakerTopologyModel(this);

// remove busbar sections because not needed in a bus/breaker topology
for (BusbarSection bbs : topologyModel.getNodeBreakerView().getBusbarSections()) {
bbs.remove();
}

for (Bus bus : topologyModel.getBusBreakerView().getBuses()) {
// no notification, this is just a mutation of a calculation bus to a configured bus
ConfiguredBusImpl configuredBus = new ConfiguredBusImpl(bus.getId(), bus.getOptionalName().orElse(null), bus.isFictitious(), this);
newTopologyModel.addBus(configuredBus);
}

// transfer retained switches
for (Switch sw : topologyModel.getBusBreakerView().getSwitchStream().toList()) {
String busId1 = topologyModel.getBusBreakerView().getBus1(sw.getId()).getId();
String busId2 = topologyModel.getBusBreakerView().getBus2(sw.getId()).getId();
// no notification, this is just a transfer
((NodeBreakerTopologyModel) topologyModel).removeSwitchFromTopology(sw.getId(), false);
newTopologyModel.addSwitchToTopology((SwitchImpl) sw, busId1, busId2);
}

// reconnect all connectable to new topology model
// first store all bus/breaker topological infos associated to this terminal because we will start moving
// terminal from old mode to new one, it will modify the old topology model
record TopologyModelInfos(TerminalExt terminal, String connectableBusId, boolean connected) {
}
List<TopologyModelInfos> oldTopologyModelInfos = new ArrayList<>();
for (Terminal oldTerminal : topologyModel.getTerminals()) {
Bus connectableBus = oldTerminal.getBusBreakerView().getConnectableBus();
String connectableBusId = connectableBus == null ? null : connectableBus.getId();
boolean connected = oldTerminal.isConnected();
oldTopologyModelInfos.add(new TopologyModelInfos((TerminalExt) oldTerminal, connectableBusId, connected));
}

for (var infos : oldTopologyModelInfos) {
TerminalExt oldTerminalExt = infos.terminal();

// if there is no way to find a connectable bus, remove the connectable
// an alternative would be to connect them all to a new trash configured bus
if (infos.connectableBusId() == null) {
// here keep the removal notification
oldTerminalExt.getConnectable().remove();
continue;
}

AbstractConnectable<?> connectable = oldTerminalExt.getConnectable();

// create the new terminal with new type
TerminalExt newTerminalExt = new TerminalBuilder(networkRef, this, oldTerminalExt.getSide())
.setBus(infos.connected ? infos.connectableBusId() : null)
.setConnectableBus(infos.connectableBusId())
.build();

connectable.replaceTerminal(oldTerminalExt, newTopologyModel, newTerminalExt, false);
}

// also here keep the notification for remaining switches removal
topologyModel.removeTopology();

TopologyKind oldTopologyKind = topologyModel.getTopologyKind();
topologyModel = newTopologyModel;

notifyUpdate("topologyKind", oldTopologyKind, TopologyKind.BUS_BREAKER);
}

@Override
public void convertToTopology(TopologyKind newTopologyKind) {
Objects.requireNonNull(newTopologyKind);
if (newTopologyKind != topologyModel.getTopologyKind()) {
if (newTopologyKind == TopologyKind.NODE_BREAKER) {
throw new PowsyblException("Topology model conversion from bus/breaker to node/breaker not yet supported");
flo-dup marked this conversation as resolved.
Show resolved Hide resolved
} else if (newTopologyKind == TopologyKind.BUS_BREAKER) {
convertToBusBreakerModel();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ public void onReferencedRemoval(Terminal removedTerminal) {
getExtendable().removeExtension(RemoteReactivePowerControl.class);
}

@Override
public void onReferencedReplacement(Terminal oldReferenced, Terminal newReferenced) {
if (regulatingTerminal == oldReferenced) {
regulatingTerminal = newReferenced;
}
}

@Override
public void cleanup() {
if (regulatingTerminal != null) {
Expand Down
Loading
Loading