-
Notifications
You must be signed in to change notification settings - Fork 6
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
Synchronization between views for v and angle bus values. #452
base: main
Are you sure you want to change the base?
Changes from 3 commits
a43f002
8492ef9
3afafdd
9ce5cb7
6661c1f
3b26409
98bf508
4c2dffb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -15,10 +15,13 @@ | |||||
import com.powsybl.iidm.network.util.Networks; | ||||||
import com.powsybl.network.store.model.*; | ||||||
import lombok.EqualsAndHashCode; | ||||||
import org.apache.commons.collections4.CollectionUtils; | ||||||
|
||||||
import java.util.*; | ||||||
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; | ||||||
|
||||||
|
@@ -48,6 +51,9 @@ 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); | ||||||
|
@@ -131,13 +137,94 @@ public double getV() { | |||||
return getAttributes().getV(); | ||||||
} | ||||||
|
||||||
private void setVInCalculatedBus(CalculatedBusAttributes calculatedBusAttributes, double value) { | ||||||
calculatedBusAttributes.setV(value); | ||||||
} | ||||||
|
||||||
private void setVInConfiguredBus(ConfiguredBusAttributes configuredBusAttributes, double value) { | ||||||
configuredBusAttributes.setV(value); | ||||||
} | ||||||
|
||||||
private double getVInBus(Bus bus) { | ||||||
return bus.getV(); | ||||||
} | ||||||
|
||||||
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(); | ||||||
} | ||||||
|
||||||
@Override | ||||||
public Bus setV(double v) { | ||||||
getAttributes().setV(v); | ||||||
index.updateVoltageLevelResource(voltageLevelResource, AttributeFilter.SV); | ||||||
|
||||||
if (getVoltageLevel().getTopologyKind() == TopologyKind.BUS_BREAKER) { | ||||||
// update V in configured buses | ||||||
updateConfiguredBuses(v, getAttributes(), VOLTAGE, this::getVInBus, this::setVInConfiguredBus); | ||||||
} else { | ||||||
if (isBusView) { | ||||||
// update V for buses in BusBreakerView | ||||||
updateBusesAttributes(v, voltageLevelResource.getAttributes().getCalculatedBusesForBusBreakerView(), getAttributes(), this::setVInCalculatedBus); | ||||||
} else { | ||||||
// update V for buses in BusView | ||||||
updateBusesAttributes(v, voltageLevelResource.getAttributes().getCalculatedBusesForBusView(), getAttributes(), this::setVInCalculatedBus); | ||||||
} | ||||||
} | ||||||
return this; | ||||||
} | ||||||
|
||||||
private void updateBusesAttributes(double value, | ||||||
List<CalculatedBusAttributes> calculatedBusAttributesList, | ||||||
CalculatedBusAttributes sourceBusAttributes, | ||||||
ObjDoubleConsumer<CalculatedBusAttributes> setValue) { | ||||||
if (!CollectionUtils.isEmpty(calculatedBusAttributesList)) { | ||||||
calculatedBusAttributesList.forEach(busToUpdate -> busToUpdate.getVertices().forEach(vertex1 -> | ||||||
sourceBusAttributes.getVertices().stream().filter(v -> v.getId().equals(vertex1.getId())).findFirst().ifPresent(vertex2 -> { | ||||||
setValue.accept(busToUpdate, value); | ||||||
index.updateVoltageLevelResource(voltageLevelResource, AttributeFilter.SV); | ||||||
}) | ||||||
)); | ||||||
} | ||||||
} | ||||||
|
||||||
private void updateConfiguredBuses(double newValue, | ||||||
CalculatedBusAttributes calculatedBusAttributesBus, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||
String attributeName, | ||||||
ToDoubleFunction<Bus> getValue, | ||||||
ObjDoubleConsumer<ConfiguredBusAttributes> setValue) { | ||||||
List<String> busesIds = calculatedBusAttributesBus.getVertices().stream() | ||||||
.map(Vertex::getBus) | ||||||
.toList(); | ||||||
|
||||||
List<Bus> buses = index.getConfiguredBuses().stream() | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. all configured bus of the network ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right. |
||||||
.filter(bus -> busesIds.contains(bus.getId()) && !Objects.equals(getValue.applyAsDouble(bus), newValue)) | ||||||
.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()) | ||||||
); | ||||||
} | ||||||
|
||||||
@Override | ||||||
public double getAngle() { | ||||||
return getAttributes().getAngle(); | ||||||
|
@@ -147,6 +234,19 @@ public double getAngle() { | |||||
public Bus setAngle(double angle) { | ||||||
getAttributes().setAngle(angle); | ||||||
index.updateVoltageLevelResource(voltageLevelResource, AttributeFilter.SV); | ||||||
|
||||||
if (getVoltageLevel().getTopologyKind() == TopologyKind.BUS_BREAKER) { | ||||||
// update angle in configuredBus | ||||||
updateConfiguredBuses(angle, getAttributes(), ANGLE, this::getAngleInBus, this::setAngleInConfiguredBus); | ||||||
} else { | ||||||
if (isBusView) { | ||||||
// update angle for Bus in BusBreakerView | ||||||
updateBusesAttributes(angle, voltageLevelResource.getAttributes().getCalculatedBusesForBusBreakerView(), getAttributes(), this::setAngleInCalculatedBus); | ||||||
} else { | ||||||
// update angle for Bus in BusView | ||||||
updateBusesAttributes(angle, voltageLevelResource.getAttributes().getCalculatedBusesForBusView(), getAttributes(), this::setAngleInCalculatedBus); | ||||||
} | ||||||
} | ||||||
return this; | ||||||
} | ||||||
|
||||||
|
@@ -423,6 +523,10 @@ public Stream<Terminal> getAllTerminalsStream() { | |||||
.filter(t -> t.getVoltageLevel().getId().equals(getVoltageLevel().getId()) && pred.test(t)); | ||||||
} | ||||||
|
||||||
public int getCalculatedBusNum() { | ||||||
return calculatedBusNum; | ||||||
} | ||||||
|
||||||
@Override | ||||||
public <E extends Extension<Bus>> void addExtension(Class<? super E> aClass, E e) { | ||||||
throw new UnsupportedOperationException("Adding an extension on calculated bus is not authorized"); | ||||||
|
@@ -467,8 +571,4 @@ public <E extends Extension<Bus>, B extends ExtensionAdder<Bus, E>> B newExtensi | |||||
ExtensionAdderProvider provider = ExtensionAdderProviders.findCachedProvider(getImplementationName(), type); | ||||||
return (B) provider.newAdder(this); | ||||||
} | ||||||
|
||||||
public int getCalculatedBusNum() { | ||||||
return calculatedBusNum; | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,13 +25,18 @@ | |
import com.powsybl.iidm.network.ValidationException; | ||
import com.powsybl.iidm.network.VoltageLevel; | ||
import com.powsybl.iidm.network.VscConverterStation; | ||
import com.powsybl.network.store.model.AttributeFilter; | ||
import com.powsybl.network.store.model.CalculatedBusAttributes; | ||
import com.powsybl.network.store.model.ConfiguredBusAttributes; | ||
import com.powsybl.network.store.model.Resource; | ||
import org.apache.commons.collections4.CollectionUtils; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
import java.util.function.ObjDoubleConsumer; | ||
import java.util.function.Predicate; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.IntStream; | ||
import java.util.stream.Stream; | ||
|
||
/** | ||
|
@@ -77,6 +82,40 @@ public double getAngle() { | |
return getResource().getAttributes().getAngle(); | ||
} | ||
|
||
private void setVInCalculatedBus(CalculatedBusAttributes calculatedBusAttributes, double value) { | ||
calculatedBusAttributes.setV(value); | ||
} | ||
|
||
private void setAngleInCalculatedBus(CalculatedBusAttributes calculatedBusAttributes, double value) { | ||
calculatedBusAttributes.setAngle(value); | ||
} | ||
|
||
private void updateCalculatedBusAttributes(double newValue, | ||
String voltageLevelId, | ||
ObjDoubleConsumer<CalculatedBusAttributes> setValue) { | ||
Optional<VoltageLevelImpl> voltageLevelOpt = index.getVoltageLevel(voltageLevelId); | ||
|
||
voltageLevelOpt.ifPresent(voltageLevel -> { | ||
List<CalculatedBusAttributes> calculatedBusAttributesList = voltageLevel.getResource() | ||
.getAttributes() | ||
.getCalculatedBusesForBusView(); | ||
|
||
if (CollectionUtils.isNotEmpty(calculatedBusAttributesList)) { | ||
List<Integer> calculatedBusesNum = getAllTerminals().stream() | ||
.filter(Terminal::isConnected) | ||
.map(t -> ((CalculatedBus) t.getBusView().getBus()).getCalculatedBusNum()).distinct().toList(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. all terminals in one configured bus always map to the same busviewbus no ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right. |
||
List<CalculatedBusAttributes> busesToUpdateList = IntStream.range(0, calculatedBusAttributesList.size()) | ||
.filter(calculatedBusesNum::contains) | ||
.mapToObj(calculatedBusAttributesList::get) | ||
.toList(); | ||
if (CollectionUtils.isNotEmpty(busesToUpdateList)) { | ||
busesToUpdateList.forEach(b -> setValue.accept(b, newValue)); | ||
index.updateVoltageLevelResource(voltageLevel.getResource(), AttributeFilter.SV); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
@Override | ||
public Bus setV(double v) { | ||
if (v < 0) { | ||
|
@@ -87,6 +126,9 @@ public Bus setV(double v) { | |
updateResource(res -> res.getAttributes().setV(v)); | ||
String variantId = index.getNetwork().getVariantManager().getWorkingVariantId(); | ||
index.notifyUpdate(this, "v", variantId, oldValue, v); | ||
|
||
// update V for bus in BusView | ||
updateCalculatedBusAttributes(v, getResource().getAttributes().getVoltageLevelId(), this::setVInCalculatedBus); | ||
} | ||
return this; | ||
} | ||
|
@@ -98,6 +140,9 @@ public Bus setAngle(double angle) { | |
updateResource(res -> res.getAttributes().setAngle(angle)); | ||
String variantId = index.getNetwork().getVariantManager().getWorkingVariantId(); | ||
index.notifyUpdate(this, "angle", variantId, oldValue, angle); | ||
|
||
// update angle for bus in BusView | ||
updateCalculatedBusAttributes(angle, getResource().getAttributes().getVoltageLevelId(), this::setAngleInCalculatedBus); | ||
} | ||
return this; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
v set in all remaining buses
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see this bug made the AbstractMainConnectedComponentWithSwitchTest work because there is a bus without any vertex which would be unset, but since it's setting v in all remaining buses it sets it anyway.
This is all to do with the fact that we can not use the equipment Vertex (=non switch equipment) to match buses, we need to use the topology vertex (nodes/configuredbus)