Skip to content

Commit

Permalink
looks good
Browse files Browse the repository at this point in the history
  • Loading branch information
jonenst committed Dec 4, 2024
1 parent 6a5cec7 commit a984abb
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 132 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/
package com.powsybl.network.store.iidm.impl;

import com.google.common.util.concurrent.AtomicDouble;
import com.powsybl.commons.config.PlatformConfig;
import com.powsybl.iidm.network.*;
import com.powsybl.network.store.model.*;
Expand All @@ -17,7 +16,6 @@
import org.jgrapht.graph.DirectedPseudograph;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -362,63 +360,50 @@ private void setCalculatedBuses(Resource<VoltageLevelAttributes> voltageLevelRes
}
}

private void getVAndAngleFromConfiguredBus(NetworkObjectIndex index,
Resource<VoltageLevelAttributes> voltageLevelResource,
ConnectedSetResult<T> connectedSet,
AtomicDouble v,
AtomicDouble angle) {
// Search with early return for a first configured bus with a connected terminal matching a vertex in the connectedSet of this bus
for (Bus bus: index.getConfiguredBuses(voltageLevelResource.getId())) {
ConfiguredBusImpl configuredBus = (ConfiguredBusImpl) bus;
for (Terminal t: configuredBus.getAllTerminals()) {
if (t.isConnected()) {
for (Vertex vertex: connectedSet.getConnectedVertices()) {
if (vertex.getId().equals(t.getConnectable().getId())) {
v.set(configuredBus.getResource().getAttributes().getV());
angle.set(configuredBus.getResource().getAttributes().getAngle());
return;
}
private CalculatedBusAttributes findFirstMatchingNodeBreakerCalculatedBusAttributes(Resource<VoltageLevelAttributes> voltageLevelResource,
ConnectedSetResult<T> connectedSet, boolean isBusView) {
// TODO Some day we may decide to start preserving values in nodebreaker topology after invalidating the views,
// so we could remove this check for isCalculatedBusesValid. Here it controls preserving
// the value accross the other view, we have it to be consistent with preserving values
// from the same view (currently not preserved)
if (voltageLevelResource.getAttributes().isCalculatedBusesValid()) {
List<CalculatedBusAttributes> calculatedBusAttributes = isBusView ? voltageLevelResource.getAttributes().getCalculatedBusesForBusBreakerView() : voltageLevelResource.getAttributes().getCalculatedBusesForBusView();
if (!CollectionUtils.isEmpty(calculatedBusAttributes)) {
Map<Integer, Integer> nodesToCalculatedBuses = isBusView ? voltageLevelResource.getAttributes().getNodeToCalculatedBusForBusBreakerView() : voltageLevelResource.getAttributes().getNodeToCalculatedBusForBusView();
if (!MapUtils.isEmpty(nodesToCalculatedBuses)) {
Integer node = (Integer) connectedSet.getConnectedNodesOrBuses().iterator().next(); // non deterministic
Integer busNum = nodesToCalculatedBuses.get(node);
if (busNum != null) {
return calculatedBusAttributes.get(busNum);
}
}
}
}
return null;
}

private void getVAndAngleFromOtherView(NetworkObjectIndex index,
private CalculatedBusAttributes createCalculatedBusAttributesWithVAndAngle(NetworkObjectIndex index,
Resource<VoltageLevelAttributes> voltageLevelResource,
ConnectedSetResult<T> connectedSet,
AtomicDouble v,
AtomicDouble angle,
boolean isBusView) {
double v = Double.NaN;
double angle = Double.NaN;
if (voltageLevelResource.getAttributes().getTopologyKind() == TopologyKind.NODE_BREAKER) {
if (!voltageLevelResource.getAttributes().isCalculatedBusesValid()) {
// TODO Some day we may decide to start preserving values in nodebreaker topology after invalidating the views,
// so we could remove this check for isCalculatedBusesValid. Here it controls preserving
// the value accross the other view, we have it to be consistent with preserving values
// from the same view (currently not preserved)
return;
}
List<CalculatedBusAttributes> calculatedBusAttributes = isBusView ? voltageLevelResource.getAttributes().getCalculatedBusesForBusBreakerView() : voltageLevelResource.getAttributes().getCalculatedBusesForBusView();
if (!CollectionUtils.isEmpty(calculatedBusAttributes)) {
Map<Integer, Integer> nodesToCalculatedBuses = isBusView ? voltageLevelResource.getAttributes().getNodeToCalculatedBusForBusBreakerView() : voltageLevelResource.getAttributes().getNodeToCalculatedBusForBusView();
if (!MapUtils.isEmpty(nodesToCalculatedBuses)) {
Integer node = (Integer) connectedSet.getConnectedNodesOrBuses().iterator().next();
Integer busNum = nodesToCalculatedBuses.get(node);
if (busNum != null) {
CalculatedBusAttributes busAttributes = calculatedBusAttributes.get(busNum);
if (busAttributes != null) {
v.set(busAttributes.getV());
angle.set(busAttributes.getAngle());
}
}
}
CalculatedBusAttributes busAttributes = findFirstMatchingNodeBreakerCalculatedBusAttributes(voltageLevelResource, connectedSet, isBusView);
if (busAttributes != null) {
v = busAttributes.getV();
angle = busAttributes.getAngle();
}
} else {
} else { // BUS_BREAKER
// currently for busbreakertopology the values are always preserved
// when using only the busbreakerview. So mimic the behavior and always preserve them
// when using the busview: get V and Angle values from configured buses
getVAndAngleFromConfiguredBus(index, voltageLevelResource, connectedSet, v, angle);
String configuredBusId = ((ConnectedSetResult<String>) connectedSet).getConnectedNodesOrBuses().iterator().next(); // nondeterministic
Bus b = index.getConfiguredBus(configuredBusId).orElseThrow();
v = b.getV();
angle = b.getAngle();
}
return new CalculatedBusAttributes(connectedSet.getConnectedVertices(), null, null, v, angle);
}

private CalculationResult<T> getCalculatedBusAttributesList(NetworkObjectIndex index, Resource<VoltageLevelAttributes> voltageLevelResource, boolean isBusView) {
Expand All @@ -432,18 +417,13 @@ private CalculationResult<T> getCalculatedBusAttributesList(NetworkObjectIndex i
List<ConnectedSetResult<T>> connectedSetList = findConnectedSetList(index, voltageLevelResource, isBusView);
calculatedBusAttributesList = connectedSetList
.stream()
.map(connectedSet -> {
AtomicDouble v = new AtomicDouble(Double.NaN);
AtomicDouble angle = new AtomicDouble(Double.NaN);
//TODO in this case in nodebreaker topology we currently don't preserve any values from
//the same view if it was already computed but is invalidated.
//we could do it some day (we need to define good heuristics to
//match previous values to new buses).
//NOTE: We chose to have the same behavior when getting the values from the other view
// get V and Angle values from other view if available
getVAndAngleFromOtherView(index, voltageLevelResource, connectedSet, v, angle, isBusView);
return new CalculatedBusAttributes(connectedSet.getConnectedVertices(), null, null, v.get(), angle.get());
})
//TODO in this case in nodebreaker topology we currently don't preserve any values from
//the same view if it was already computed but is invalidated.
//we could do it some day (we need to define good heuristics to
//match previous values to new buses).
//NOTE: We chose to have the same behavior when getting the values from the other view
// get V and Angle values from other view if available
.map(connectedSet -> createCalculatedBusAttributesWithVAndAngle(index, voltageLevelResource, connectedSet, isBusView))
.collect(Collectors.toList());
setCalculatedBuses(voltageLevelResource, isBusView, calculatedBusAttributesList);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
import org.apache.commons.collections4.MapUtils;

import java.util.*;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.function.ObjDoubleConsumer;
import java.util.function.Predicate;
import java.util.function.ToDoubleFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand Down Expand Up @@ -52,9 +52,6 @@ public final class CalculatedBus implements BaseBus {

private final Function<Terminal, Bus> getBusFromTerminal;

private static final String VOLTAGE = "v";
private static final String ANGLE = "angle";

CalculatedBus(NetworkObjectIndex index, String voltageLevelId, String id, String name, Resource<VoltageLevelAttributes> voltageLevelResource,
int calculatedBusNum, boolean isBusView) {
this.index = Objects.requireNonNull(index);
Expand Down Expand Up @@ -142,24 +139,16 @@ private void setVInCalculatedBus(CalculatedBusAttributes calculatedBusAttributes
calculatedBusAttributes.setV(value);
}

private void setVInConfiguredBus(ConfiguredBusAttributes configuredBusAttributes, double value) {
configuredBusAttributes.setV(value);
}

private double getVInBus(Bus bus) {
return bus.getV();
private void setVInConfiguredBus(ConfiguredBusImpl configuredBus, double value) {
configuredBus.setConfiguredBusV(value);
}

private void setAngleInCalculatedBus(CalculatedBusAttributes calculatedBusAttributes, double value) {
calculatedBusAttributes.setAngle(value);
}

private void setAngleInConfiguredBus(ConfiguredBusAttributes configuredBusAttributes, double value) {
configuredBusAttributes.setAngle(value);
}

private double getAngleInBus(Bus bus) {
return bus.getAngle();
private void setAngleInConfiguredBus(ConfiguredBusImpl configuredBus, double value) {
configuredBus.setConfiguredBusAngle(value);
}

@Override
Expand All @@ -169,7 +158,8 @@ public Bus setV(double v) {

if (getVoltageLevel().getTopologyKind() == TopologyKind.BUS_BREAKER) {
// update V in configured buses
updateConfiguredBuses(v, VOLTAGE, this::getVInBus, this::setVInConfiguredBus);
// this triggers network notifications for 'v' for each configured bus
updateConfiguredBuses(v, this::setVInConfiguredBus);
} else {
// update V for buses in the other view (busView/busBreakerView)
updateBusesAttributes(v, this::setVInCalculatedBus);
Expand All @@ -189,7 +179,8 @@ public Bus setAngle(double angle) {

if (getVoltageLevel().getTopologyKind() == TopologyKind.BUS_BREAKER) {
// update angle in configuredBus
updateConfiguredBuses(angle, ANGLE, this::getAngleInBus, this::setAngleInConfiguredBus);
// this triggers network notifications for 'angle' for each configured bus
updateConfiguredBuses(angle, this::setAngleInConfiguredBus);
} else {
// update angle for buses in the other view (busView/busBreakerView)
updateBusesAttributes(angle, this::setAngleInCalculatedBus);
Expand Down Expand Up @@ -520,20 +511,19 @@ public int getCalculatedBusNum() {
}

private void updateBusesAttributes(double value, ObjDoubleConsumer<CalculatedBusAttributes> setValue) {
// busnum of this bus -> nodes in this bus -> busnums in the other view -> buses of the other view
VoltageLevelAttributes vlAttributes = ((VoltageLevelImpl) getVoltageLevel()).getResource().getAttributes();
Map<Integer, Integer> nodesToCalculatedBuses = isBusView
? vlAttributes.getNodeToCalculatedBusForBusView()
: vlAttributes.getNodeToCalculatedBusForBusBreakerView();
if (!MapUtils.isEmpty(nodesToCalculatedBuses)) {
nodesToCalculatedBuses.entrySet().stream()
.filter(entry -> getCalculatedBusNum() == entry.getValue())
.map(Map.Entry::getKey)
.forEach(node -> {
Map<Integer, Integer> nodesToCalculatedBusesInOtherView = isBusView
? vlAttributes.getNodeToCalculatedBusForBusBreakerView()
: vlAttributes.getNodeToCalculatedBusForBusView();
if (!MapUtils.isEmpty(nodesToCalculatedBusesInOtherView) &&
nodesToCalculatedBusesInOtherView.containsKey(node)) {
Map<Integer, Integer> nodesToCalculatedBusesInOtherView = isBusView
? vlAttributes.getNodeToCalculatedBusForBusBreakerView()
: vlAttributes.getNodeToCalculatedBusForBusView();
if (!MapUtils.isEmpty(nodesToCalculatedBuses) && !MapUtils.isEmpty(nodesToCalculatedBusesInOtherView)) {
for (Entry<Integer, Integer> entry : nodesToCalculatedBuses.entrySet()) {
if (getCalculatedBusNum() == entry.getValue()) {
int node = entry.getKey();
if (nodesToCalculatedBusesInOtherView.containsKey(node)) {
int busNumInOtherView = nodesToCalculatedBusesInOtherView.get(node);
List<CalculatedBusAttributes> calculatedBusAttributes = isBusView
? vlAttributes.getCalculatedBusesForBusBreakerView()
Expand All @@ -543,35 +533,19 @@ private void updateBusesAttributes(double value, ObjDoubleConsumer<CalculatedBus
index.updateVoltageLevelResource(voltageLevelResource, AttributeFilter.SV);
}
}
});
}
}
}
}

private void updateConfiguredBuses(double newValue,
String attributeName,
ToDoubleFunction<Bus> getValue,
ObjDoubleConsumer<ConfiguredBusAttributes> setValue) {
List<Bus> buses = ((VoltageLevelImpl) getVoltageLevel()).getResource().getAttributes()
.getBusToCalculatedBusForBusView().entrySet().stream()
.filter(entry -> getCalculatedBusNum() == entry.getValue())
.map(Map.Entry::getKey)
.map(getVoltageLevel().getBusBreakerView()::getBus)
.toList();

Map<Bus, Map.Entry<Double, Double>> oldNewValues = buses.stream()
.collect(Collectors.toMap(
bus -> bus,
bus -> new AbstractMap.SimpleEntry<>(getValue.applyAsDouble(bus), newValue)
));

buses.forEach(bus -> {
setValue.accept(((ConfiguredBusImpl) bus).getResource().getAttributes(), newValue);
index.updateConfiguredBusResource(((ConfiguredBusImpl) bus).getResource(), null);
});

String variantId = index.getNetwork().getVariantManager().getWorkingVariantId();
oldNewValues.forEach((bus, oldNewValue) ->
index.notifyUpdate(bus, attributeName, variantId, oldNewValue.getKey(), oldNewValue.getValue())
);
ObjDoubleConsumer<ConfiguredBusImpl> setValue) {
VoltageLevelAttributes vlAttributes = ((VoltageLevelImpl) getVoltageLevel()).getResource().getAttributes();
for (Entry<String, Integer> entry : vlAttributes.getBusToCalculatedBusForBusView().entrySet()) {
if (getCalculatedBusNum() == entry.getValue()) {
Bus bus = getVoltageLevel().getBusBreakerView().getBus(entry.getKey());
setValue.accept((ConfiguredBusImpl) bus, newValue);
}
}
}
}
Loading

0 comments on commit a984abb

Please sign in to comment.