diff --git a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/BusBreakerTopologyModel.java b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/BusBreakerTopologyModel.java index dabc6fafa03..85644bcd7f5 100644 --- a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/BusBreakerTopologyModel.java +++ b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/BusBreakerTopologyModel.java @@ -389,6 +389,12 @@ static PowsyblException createNotSupportedBusBreakerTopologyException() { } private final VoltageLevelExt.NodeBreakerViewExt nodeBreakerView = new VoltageLevelExt.NodeBreakerViewExt() { + + @Override + public boolean hasFictitiousP0() { + throw createNotSupportedBusBreakerTopologyException(); + } + @Override public double getFictitiousP0(int node) { throw createNotSupportedBusBreakerTopologyException(); @@ -399,6 +405,11 @@ public VoltageLevel.NodeBreakerView setFictitiousP0(int node, double p0) { throw createNotSupportedBusBreakerTopologyException(); } + @Override + public boolean hasFictitiousQ0() { + throw createNotSupportedBusBreakerTopologyException(); + } + @Override public double getFictitiousQ0(int node) { throw createNotSupportedBusBreakerTopologyException(); diff --git a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/CalculatedBusImpl.java b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/CalculatedBusImpl.java index 60907282a5b..9b72fb2daee 100644 --- a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/CalculatedBusImpl.java +++ b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/CalculatedBusImpl.java @@ -146,6 +146,9 @@ public double getQ() { @Override public double getFictitiousP0() { checkValidity(); + if (!voltageLevel.getNodeBreakerView().hasFictitiousP0()) { + return 0.0; + } return Networks.getNodes(id, voltageLevel, getBusFromTerminal) .mapToDouble(n -> voltageLevel.getNodeBreakerView().getFictitiousP0(n)) .reduce(0.0, Double::sum); @@ -165,6 +168,9 @@ public Bus setFictitiousP0(double p0) { @Override public double getFictitiousQ0() { checkValidity(); + if (!voltageLevel.getNodeBreakerView().hasFictitiousQ0()) { + return 0.0; + } return Networks.getNodes(id, voltageLevel, getBusFromTerminal) .mapToDouble(n -> voltageLevel.getNodeBreakerView().getFictitiousQ0(n)) .reduce(0.0, Double::sum); diff --git a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/NodeBreakerTopologyModel.java b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/NodeBreakerTopologyModel.java index ba1360ac5dd..8f3ac5f9b3d 100644 --- a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/NodeBreakerTopologyModel.java +++ b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/NodeBreakerTopologyModel.java @@ -645,6 +645,25 @@ void removeSwitchFromTopology(String switchId, boolean notify) { private final TIntObjectMap fictitiousP0ByNode = TCollections.synchronizedMap(new TIntObjectHashMap<>()); private final TIntObjectMap fictitiousQ0ByNode = TCollections.synchronizedMap(new TIntObjectHashMap<>()); + private boolean hasFictitiousInjection(TIntObjectMap fictitiousInjectionsByNode) { + if (fictitiousInjectionsByNode.isEmpty()) { + return false; + } + int variantIndex = getNetwork().getVariantIndex(); + for (int node : fictitiousInjectionsByNode.keys()) { + TDoubleArrayList fictitiousInjectionByVariant = fictitiousInjectionsByNode.get(node); + if (fictitiousInjectionByVariant != null && fictitiousInjectionByVariant.get(variantIndex) != 0.0) { + return true; + } + } + return false; + } + + @Override + public boolean hasFictitiousP0() { + return hasFictitiousInjection(fictitiousP0ByNode); + } + @Override public double getFictitiousP0(int node) { TDoubleArrayList fictP0 = fictitiousP0ByNode.get(node); @@ -684,6 +703,11 @@ public VoltageLevel.NodeBreakerView setFictitiousP0(int node, double p0) { return this; } + @Override + public boolean hasFictitiousQ0() { + return hasFictitiousInjection(fictitiousQ0ByNode); + } + @Override public double getFictitiousQ0(int node) { TDoubleArrayList fictQ0 = fictitiousQ0ByNode.get(node); diff --git a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/VoltageLevelExt.java b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/VoltageLevelExt.java index 7c9d1636688..4d2f8238094 100644 --- a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/VoltageLevelExt.java +++ b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/VoltageLevelExt.java @@ -19,6 +19,16 @@ interface VoltageLevelExt extends VoltageLevel, MultiVariantObject, Validable { interface NodeBreakerViewExt extends NodeBreakerView { + /** + * Returns true if any node has a non-zero fictitious active power injection. + */ + boolean hasFictitiousP0(); + + /** + * Returns true if any node has a non-zero fictitious reactive power injection. + */ + boolean hasFictitiousQ0(); + } interface BusBreakerViewExt extends BusBreakerView { diff --git a/iidm/iidm-impl/src/test/java/com/powsybl/iidm/network/impl/NodeBreakerFictitiousInjectionTest.java b/iidm/iidm-impl/src/test/java/com/powsybl/iidm/network/impl/NodeBreakerFictitiousInjectionTest.java new file mode 100644 index 00000000000..6d8a4fa0e38 --- /dev/null +++ b/iidm/iidm-impl/src/test/java/com/powsybl/iidm/network/impl/NodeBreakerFictitiousInjectionTest.java @@ -0,0 +1,32 @@ +package com.powsybl.iidm.network.impl; + +import com.powsybl.iidm.network.Bus; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.test.NetworkTest1Factory; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class NodeBreakerFictitiousInjectionTest { + + @Test + void testHasFictitiousP0AndFictitiousQ0() { + Network network = NetworkTest1Factory.create(); + Bus bus = network.getVoltageLevel("voltageLevel1").getBusBreakerView().getBus("voltageLevel1_0"); + + bus.setFictitiousP0(10); + bus.setFictitiousQ0(20); + VoltageLevelImpl vl = (VoltageLevelImpl) network.getVoltageLevel("voltageLevel1"); + assertTrue(vl.getNodeBreakerView().hasFictitiousP0()); + assertTrue(vl.getNodeBreakerView().hasFictitiousQ0()); + assertEquals(10, bus.getFictitiousP0()); + assertEquals(20, bus.getFictitiousQ0()); + + bus.setFictitiousP0(0.0); + bus.setFictitiousQ0(0.0); + assertFalse(vl.getNodeBreakerView().hasFictitiousP0()); + assertFalse(vl.getNodeBreakerView().hasFictitiousQ0()); + assertEquals(0, bus.getFictitiousP0()); + assertEquals(0, bus.getFictitiousQ0()); + } +}