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 syncv #460

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 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 @@ -6,14 +6,18 @@
*/
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.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.jgrapht.Graph;
import org.jgrapht.alg.connectivity.ConnectivityInspector;
import org.jgrapht.graph.DirectedPseudograph;

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

/**
Expand Down Expand Up @@ -358,18 +362,77 @@ private void setCalculatedBuses(Resource<VoltageLevelAttributes> voltageLevelRes
}
}

private void getVAndAngleFromConfiguredBus(NetworkObjectIndex index,
Resource<VoltageLevelAttributes> voltageLevelResource,
ConnectedSetResult<T> connectedSet,
AtomicDouble v,
AtomicDouble angle) {
AtomicReference<ConfiguredBusImpl> foundConfiguredBus = new AtomicReference<>();
index.getConfiguredBuses(voltageLevelResource.getId()).forEach(bus -> {
if (foundConfiguredBus.get() == null) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

break early instead of checking if found in the loop

ConfiguredBusImpl configuredBus = (ConfiguredBusImpl) bus;
configuredBus.getAllTerminals().stream()
.filter(Terminal::isConnected)
.forEach(t -> {
if (foundConfiguredBus.get() == null) {
connectedSet.getConnectedVertices().stream().filter(vertex ->
vertex.getId().equals(t.getConnectable().getId())
).findFirst().ifPresent(vertex -> foundConfiguredBus.set(configuredBus));
}
});
}
});
if (foundConfiguredBus.get() != null) {
v.set(foundConfiguredBus.get().getResource().getAttributes().getV());
angle.set(foundConfiguredBus.get().getResource().getAttributes().getAngle());
}
}

private void getVAndAngleFromOtherView(NetworkObjectIndex index,
Resource<VoltageLevelAttributes> voltageLevelResource,
ConnectedSetResult<T> connectedSet,
AtomicDouble v,
AtomicDouble angle,
boolean isBusView) {
if (voltageLevelResource.getAttributes().getTopologyKind() == TopologyKind.NODE_BREAKER) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we use if (isCalculatedBusesValid(voltageLevelResource, !isBusView)) {
like in getCalculatedBusAttributesList ?

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());
}
}
}
}
} else {
// get V and Angle values from configured buses
getVAndAngleFromConfiguredBus(index, voltageLevelResource, connectedSet, v, angle);
}
}

private CalculationResult<T> getCalculatedBusAttributesList(NetworkObjectIndex index, Resource<VoltageLevelAttributes> voltageLevelResource, boolean isBusView) {
List<CalculatedBusAttributes> calculatedBusAttributesList;
Map<T, Integer> nodeOrBusToCalculatedBusNum;
if (isCalculatedBusesValid(voltageLevelResource, isBusView)) {
calculatedBusAttributesList = isBusView ? voltageLevelResource.getAttributes().getCalculatedBusesForBusView() : voltageLevelResource.getAttributes().getCalculatedBusesForBusBreakerView();
nodeOrBusToCalculatedBusNum = getNodeOrBusToCalculatedBusNum(voltageLevelResource, isBusView);
} else {
// calculate buses
List<ConnectedSetResult<T>> connectedSetList = findConnectedSetList(index, voltageLevelResource, isBusView);
calculatedBusAttributesList = connectedSetList
.stream()
.map(connectedSet -> new CalculatedBusAttributes(connectedSet.getConnectedVertices(), null, null, Double.NaN, Double.NaN))
.map(connectedSet -> {
AtomicDouble v = new AtomicDouble(Double.NaN);
AtomicDouble angle = new AtomicDouble(Double.NaN);
// 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());
})
.collect(Collectors.toList());
setCalculatedBuses(voltageLevelResource, isBusView, calculatedBusAttributesList);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@
import com.powsybl.iidm.network.util.Networks;
import com.powsybl.network.store.model.*;
import lombok.EqualsAndHashCode;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;

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;

Expand Down Expand Up @@ -48,6 +52,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);
Expand Down Expand Up @@ -131,13 +138,101 @@ 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, VOLTAGE, this::getVInBus, this::setVInConfiguredBus);
} else {
// update V for buses in the other view (busView/busBreakerView)
updateBusesAttributes(v, this::setVInCalculatedBus);
}
return this;
}

private void updateBusesAttributes(double value, ObjDoubleConsumer<CalculatedBusAttributes> setValue) {
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)) {
int busNumInOtherView = nodesToCalculatedBusesInOtherView.get(node);
List<CalculatedBusAttributes> calculatedBusAttributes = isBusView
? vlAttributes.getCalculatedBusesForBusBreakerView()
: vlAttributes.getCalculatedBusesForBusView();
if (!CollectionUtils.isEmpty(calculatedBusAttributes)) {
setValue.accept(calculatedBusAttributes.get(busNumInOtherView), value);
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())
);
}

@Override
public double getAngle() {
return getAttributes().getAngle();
Expand All @@ -147,6 +242,14 @@ 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, ANGLE, this::getAngleInBus, this::setAngleInConfiguredBus);
} else {
// update angle for buses in the other view (busView/busBreakerView)
updateBusesAttributes(angle, this::setAngleInCalculatedBus);
}
return this;
}

Expand Down Expand Up @@ -423,6 +526,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");
Expand Down Expand Up @@ -467,8 +574,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
Expand Up @@ -25,11 +25,16 @@
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.MapUtils;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.ObjDoubleConsumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -77,6 +82,30 @@ 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) {
index.getVoltageLevel(voltageLevelId).ifPresent(voltageLevel -> {
Map<String, Integer> calculatedBuses = voltageLevel.getResource().getAttributes().getBusToCalculatedBusForBusView();
if (!MapUtils.isEmpty(calculatedBuses)) {
Integer busviewnum = calculatedBuses.get(getId());
if (busviewnum != null) {
CalculatedBusAttributes busviewattributes = voltageLevel.getResource().getAttributes().getCalculatedBusesForBusView().get(busviewnum);
setValue.accept(busviewattributes, newValue);
index.updateVoltageLevelResource(voltageLevel.getResource(), AttributeFilter.SV);
}
}
});
}

@Override
public Bus setV(double v) {
if (v < 0) {
Expand All @@ -87,6 +116,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;
}
Expand All @@ -98,6 +130,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;
}
Expand Down
Loading
Loading