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

Fix area boundary auto-removal with merged and detached Networks #3081

Merged
merged 1 commit into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -48,9 +48,19 @@ public void beforeRemoval(Identifiable<?> identifiable) {
}
}

/**
* Must be called whenever the Area is moved to a different root Network when merging and detaching.
* @param fromNetwork previous root network
* @param toNetwork new root network
*/
void moveListener(NetworkImpl fromNetwork, NetworkImpl toNetwork) {
fromNetwork.removeListener(this.areaListener);
toNetwork.addListener(this.areaListener);
}

private final NetworkListener areaListener;

public AreaImpl(Ref<NetworkImpl> ref, Ref<SubnetworkImpl> subnetworkRef, String id, String name, boolean fictitious, String areaType,
AreaImpl(Ref<NetworkImpl> ref, Ref<SubnetworkImpl> subnetworkRef, String id, String name, boolean fictitious, String areaType,
olperr1 marked this conversation as resolved.
Show resolved Hide resolved
double acInterchangeTarget) {
super(id, name, fictitious);
this.networkRef = Objects.requireNonNull(ref);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,11 @@ private void merge(Network other) {

checkMergeability(otherNetwork);

otherNetwork.getAreaStream().forEach(a -> {
AreaImpl area = (AreaImpl) a;
area.moveListener(otherNetwork, this);
});

// try to find dangling lines couples
List<DanglingLinePair> lines = new ArrayList<>();
Map<String, List<DanglingLine>> dl1byPairingKey = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,7 @@ public Network detach() {
transferExtensions(this, detachedNetwork);
transferProperties(this, detachedNetwork);

// Memorize the network identifiables/voltageAngleLimits before moving references (to use them latter)
// Memorize the network identifiables/voltageAngleLimits before moving references (to use them later)
Collection<Identifiable<?>> identifiables = getIdentifiables();
Iterable<VoltageAngleLimit> vals = getVoltageAngleLimits();

Expand All @@ -831,6 +831,11 @@ public Network detach() {
detachedNetwork.getVoltageAngleLimitsIndex().put(val.getId(), val);
}

detachedNetwork.getAreaStream().forEach(a -> {
AreaImpl area = (AreaImpl) a;
area.moveListener(previousRootNetwork, detachedNetwork);
});

// We don't control that regulating terminals and phase/ratio regulation terminals are in the same subnetwork
// as their network elements (generators, PSTs, ...). It is unlikely that those terminals and their elements
// are in different subnetworks but nothing prevents it. For now, we ignore this case, but it may be necessary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.powsybl.commons.PowsyblException;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
import com.powsybl.iidm.network.test.FourSubstationsNodeBreakerFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
Expand Down Expand Up @@ -424,6 +425,41 @@ public void removeEquipmentRemovesAreaBoundary() {
assertEquals(2, controlAreaB.getAreaBoundaryStream().count());
}

@Test
public void removeEquipmentRemovesAreaBoundaryMergeAndDetach() {
// do a merge
Network fourBus = FourSubstationsNodeBreakerFactory.create();
Network merged = Network.merge(network, fourBus);
network = merged.getSubnetwork("sim1");
controlAreaA = network.getArea("ControlArea_A");
controlAreaB = network.getArea("ControlArea_B");
dlXnode1A = network.getDanglingLine("NHV1_XNODE1");
tieLine1 = network.getTieLine("NHV1_NHV2_1");
assertEquals(2, controlAreaA.getAreaBoundaryStream().count());
assertEquals(2, controlAreaB.getAreaBoundaryStream().count());

// Verify the cleanup listener is now effective on the merged network
tieLine1.remove();
dlXnode1A.remove();

assertEquals(1, controlAreaA.getAreaBoundaryStream().count());
assertEquals(2, controlAreaB.getAreaBoundaryStream().count());

// now detach
network = network.detach();
controlAreaA = network.getArea("ControlArea_A");
controlAreaB = network.getArea("ControlArea_B");
dlXnode2A = network.getDanglingLine("NVH1_XNODE2");
tieLine2 = network.getTieLine("NHV1_NHV2_2");

// Verify the cleanup listener is now effective on the detached network
tieLine2.remove();
dlXnode2A.remove();

assertEquals(0, controlAreaA.getAreaBoundaryStream().count());
assertEquals(2, controlAreaB.getAreaBoundaryStream().count());
}

@Test
public void throwBoundaryOtherNetwork() {
Network subnetwork = network.createSubnetwork("subnetwork_id", "Subnetwork", "json");
Expand Down