diff --git a/docs/grid_model/extensions.md b/docs/grid_model/extensions.md index 3c6acde6a6b..35b7490639a 100644 --- a/docs/grid_model/extensions.md +++ b/docs/grid_model/extensions.md @@ -15,11 +15,13 @@ Every extension is considered as serializable unless explicitly specified as non ## Active power control This extension is used to configure the participation factor of the generator, typically in the case of a load flow computation with distributed slack enabled (with [balance type](../simulation/loadflow/configuration.md#generic-parameters) on generator). This extension is attached to a [generator](network_subnetwork.md#generator) or a [battery](network_subnetwork.md#battery). -| Attribute | Type | Unit | Required | Default value | Description | -|----------------------|---------|------------------------|----------|---------------|----------------------------------------------| -| participate | boolean | - | yes | - | The participation status | -| droop | double | None (repartition key) | no | - | The participation factor equals Pmax / droop | -| participation factor | double | None (repartition key) | no | - | Defines the participation factor explicitly | +| Attribute | Type | Unit | Required | Default value | Description | +|----------------------|---------|------------------------|----------|---------------|---------------------------------------------------------------------------------------| +| participate | boolean | - | yes | - | The participation status | +| droop | double | None (repartition key) | no | - | The participation factor equals maxP / droop | +| participation factor | double | None (repartition key) | no | - | Defines the participation factor explicitly | +| maxP override | double | MW | no | - | If defined, this limit is used for slack distribution instead of the generator's maxP | +| minP override | double | MW | no | - | if defined, this limit is used for slack distribution instead of the generator's minP | Here is how to add an active power control extension to a generator: ```java @@ -30,7 +32,7 @@ generator.newExtension(ActivePowerControlAdder.class) .add(); ``` -The participation status and the participation factor are multi-variants: they can vary from one variant to another. +The participation status, the participation factor, the maxP override and the minP override are multi-variants: they can vary from one variant to another. This extension is provided by the `com.powsybl:powsybl-iidm-extensions` module. diff --git a/iidm/iidm-extensions/src/main/java/com/powsybl/iidm/network/extensions/ActivePowerControl.java b/iidm/iidm-extensions/src/main/java/com/powsybl/iidm/network/extensions/ActivePowerControl.java index 0dd18ffb477..af9dc407473 100644 --- a/iidm/iidm-extensions/src/main/java/com/powsybl/iidm/network/extensions/ActivePowerControl.java +++ b/iidm/iidm-extensions/src/main/java/com/powsybl/iidm/network/extensions/ActivePowerControl.java @@ -10,6 +10,8 @@ import com.powsybl.commons.extensions.Extension; import com.powsybl.iidm.network.Injection; +import java.util.OptionalDouble; + /** * @author Ghiles Abdellah {@literal } */ @@ -54,4 +56,25 @@ default String getName() { */ void setParticipationFactor(double participationFactor); + /** + * @return if present, provides the overridden value of minP to be used for active power control operations. + */ + OptionalDouble getMinPOverride(); + + /** + * Sets the overridden minimal active power. + * @param pMinOverride The overridden value of minP. A Nan value removes the override. + */ + void setMinPOverride(double pMinOverride); + + /** + * @return if present, provides the overridden value of maxP to be used for active power control operations. + */ + OptionalDouble getMaxPOverride(); + + /** + * Sets the overridden maximal active power. + * @param pMaxOverride The overridden value of maxP. A Nan value removes the override. + */ + void setMaxPOverride(double pMaxOverride); } diff --git a/iidm/iidm-extensions/src/main/java/com/powsybl/iidm/network/extensions/ActivePowerControlAdder.java b/iidm/iidm-extensions/src/main/java/com/powsybl/iidm/network/extensions/ActivePowerControlAdder.java index 22f64c6200f..b4d6e500b2f 100644 --- a/iidm/iidm-extensions/src/main/java/com/powsybl/iidm/network/extensions/ActivePowerControlAdder.java +++ b/iidm/iidm-extensions/src/main/java/com/powsybl/iidm/network/extensions/ActivePowerControlAdder.java @@ -23,4 +23,8 @@ default Class getExtensionClass() { ActivePowerControlAdder withDroop(double droop); ActivePowerControlAdder withParticipationFactor(double participationFactor); + + ActivePowerControlAdder withMinPOverride(double minPOverride); + + ActivePowerControlAdder withMaxPOverride(double maxPOverride); } diff --git a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/ActivePowerControlAdderImpl.java b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/ActivePowerControlAdderImpl.java index e0fae2e5f70..69235972c9e 100644 --- a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/ActivePowerControlAdderImpl.java +++ b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/ActivePowerControlAdderImpl.java @@ -20,6 +20,8 @@ public class ActivePowerControlAdderImpl> private double droop = Double.NaN; private double participationFactor = Double.NaN; + private double minPOverride = Double.NaN; + private double maxPOverride = Double.NaN; protected ActivePowerControlAdderImpl(I extendable) { super(extendable); @@ -27,7 +29,7 @@ protected ActivePowerControlAdderImpl(I extendable) { @Override protected ActivePowerControlImpl createExtension(I extendable) { - return new ActivePowerControlImpl<>(extendable, participate, droop, participationFactor); + return new ActivePowerControlImpl<>(extendable, participate, droop, participationFactor, minPOverride, maxPOverride); } @Override @@ -48,4 +50,16 @@ public ActivePowerControlAdder withParticipationFactor(double participationFa return this; } + @Override + public ActivePowerControlAdder withMinPOverride(double minPOverride) { + this.minPOverride = minPOverride; + return this; + } + + @Override + public ActivePowerControlAdder withMaxPOverride(double maxPOverride) { + this.maxPOverride = maxPOverride; + return this; + } + } diff --git a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/ActivePowerControlImpl.java b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/ActivePowerControlImpl.java index cd085d0b9dc..c890aabe86e 100644 --- a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/ActivePowerControlImpl.java +++ b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/ActivePowerControlImpl.java @@ -14,6 +14,7 @@ import gnu.trove.list.array.TDoubleArrayList; import java.util.List; +import java.util.OptionalDouble; /** * @author Ghiles Abdellah {@literal } @@ -26,22 +27,38 @@ public class ActivePowerControlImpl> extends AbstractMult private final TDoubleArrayList droop; private final TDoubleArrayList participationFactor; + private final TDoubleArrayList minPOverride; + private final TDoubleArrayList maxPOverride; + private final List allTDoubleArrayLists; public ActivePowerControlImpl(T component, boolean participate, double droop, double participationFactor) { + this(component, participate, droop, participationFactor, Double.NaN, Double.NaN); + } + + public ActivePowerControlImpl(T component, + boolean participate, + double droop, + double participationFactor, + double minPOverride, + double maxPOverride) { super(component); int variantArraySize = getVariantManagerHolder().getVariantManager().getVariantArraySize(); this.participate = new TBooleanArrayList(variantArraySize); this.droop = new TDoubleArrayList(variantArraySize); this.participationFactor = new TDoubleArrayList(variantArraySize); - this.allTDoubleArrayLists = List.of(this.droop, this.participationFactor); + this.minPOverride = new TDoubleArrayList(variantArraySize); + this.maxPOverride = new TDoubleArrayList(variantArraySize); + this.allTDoubleArrayLists = List.of(this.droop, this.participationFactor, this.minPOverride, this.maxPOverride); for (int i = 0; i < variantArraySize; i++) { this.participate.add(participate); this.droop.add(droop); this.participationFactor.add(participationFactor); + this.minPOverride.add(minPOverride); + this.maxPOverride.add(maxPOverride); } } @@ -94,8 +111,29 @@ public void deleteVariantArrayElement(int index) { public void allocateVariantArrayElement(int[] indexes, int sourceIndex) { for (int index : indexes) { participate.set(index, participate.get(sourceIndex)); - droop.set(index, droop.get(sourceIndex)); allTDoubleArrayLists.forEach(dl -> dl.set(index, dl.get(sourceIndex))); } } + + @Override + public OptionalDouble getMinPOverride() { + double result = minPOverride.get(getVariantIndex()); + return Double.isNaN(result) ? OptionalDouble.empty() : OptionalDouble.of(result); + } + + @Override + public void setMinPOverride(double minPOverride) { + this.minPOverride.set(getVariantIndex(), minPOverride); + } + + @Override + public OptionalDouble getMaxPOverride() { + double result = maxPOverride.get(getVariantIndex()); + return Double.isNaN(result) ? OptionalDouble.empty() : OptionalDouble.of(result); + } + + @Override + public void setMaxPOverride(double maxPOverride) { + this.maxPOverride.set(getVariantIndex(), maxPOverride); + } } diff --git a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ActivePowerControlSerDe.java b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ActivePowerControlSerDe.java index d70fad28cee..fc1507962ae 100644 --- a/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ActivePowerControlSerDe.java +++ b/iidm/iidm-serde/src/main/java/com/powsybl/iidm/serde/extensions/ActivePowerControlSerDe.java @@ -45,11 +45,12 @@ public ActivePowerControlSerDe() { .put(IidmVersion.V_1_9, ImmutableSortedSet.of("1.0", "1.1")) .put(IidmVersion.V_1_10, ImmutableSortedSet.of("1.0", "1.1")) .put(IidmVersion.V_1_11, ImmutableSortedSet.of("1.0", "1.1")) - .put(IidmVersion.V_1_12, ImmutableSortedSet.of("1.0", "1.1")) + .put(IidmVersion.V_1_12, ImmutableSortedSet.of("1.0", "1.1", "1.2")) .build(), new ImmutableMap.Builder() .put("1.0", "http://www.itesla_project.eu/schema/iidm/ext/active_power_control/1_0") .put("1.1", "http://www.powsybl.org/schema/iidm/ext/active_power_control/1_1") + .put("1.2", "http://www.powsybl.org/schema/iidm/ext/active_power_control/1_2") .build()); } @@ -63,16 +64,22 @@ public void write(ActivePowerControl activePowerControl, SerializerContext co if ("1.1".compareTo(extVersionStr) <= 0) { context.getWriter().writeDoubleAttribute("participationFactor", activePowerControl.getParticipationFactor()); } + if ("1.2".compareTo(extVersionStr) <= 0) { + // not using writeOptionalDouble and trusting implementation convention: : writeDoubleAttribute does not write NaN values in human-readable formats JSON/XML + context.getWriter().writeDoubleAttribute("maxPOverride", activePowerControl.getMaxPOverride().orElse(Double.NaN)); + context.getWriter().writeDoubleAttribute("minPOverride", activePowerControl.getMinPOverride().orElse(Double.NaN)); + } } @Override public InputStream getXsdAsStream() { - return getClass().getResourceAsStream("/xsd/activePowerControl_V1_1.xsd"); + return getClass().getResourceAsStream("/xsd/activePowerControl_V1_2.xsd"); } @Override public List getXsdAsStreamList() { - return List.of(getClass().getResourceAsStream("/xsd/activePowerControl_V1_1.xsd"), + return List.of(getClass().getResourceAsStream("/xsd/activePowerControl_V1_2.xsd"), + getClass().getResourceAsStream("/xsd/activePowerControl_V1_1.xsd"), getClass().getResourceAsStream("/xsd/activePowerControl_V1_0.xsd")); } @@ -81,16 +88,25 @@ public ActivePowerControl read(T identifiable, DeserializerContext context) { boolean participate = context.getReader().readBooleanAttribute("participate"); double droop = context.getReader().readDoubleAttribute("droop"); double participationFactor = Double.NaN; + double minPOverride = Double.NaN; + double maxPOverride = Double.NaN; NetworkDeserializerContext networkContext = (NetworkDeserializerContext) context; String extVersionStr = networkContext.getExtensionVersion(this).orElseThrow(IllegalStateException::new); if ("1.1".compareTo(extVersionStr) <= 0) { participationFactor = context.getReader().readDoubleAttribute("participationFactor"); } + if ("1.2".compareTo(extVersionStr) <= 0) { + // not using readOptionalDouble and trusting implementation convention: readDoubleAttribute returns Nan if attribute is absent in human-readable formats (JSON / XML) + maxPOverride = context.getReader().readDoubleAttribute("maxPOverride"); + minPOverride = context.getReader().readDoubleAttribute("minPOverride"); + } context.getReader().readEndNode(); ActivePowerControlAdder activePowerControlAdder = identifiable.newExtension(ActivePowerControlAdder.class); return activePowerControlAdder.withParticipate(participate) .withDroop(droop) .withParticipationFactor(participationFactor) + .withMinPOverride(minPOverride) + .withMaxPOverride(maxPOverride) .add(); } } diff --git a/iidm/iidm-serde/src/main/resources/xsd/activePowerControl_V1_2.xsd b/iidm/iidm-serde/src/main/resources/xsd/activePowerControl_V1_2.xsd new file mode 100644 index 00000000000..d53fa4a9ca9 --- /dev/null +++ b/iidm/iidm-serde/src/main/resources/xsd/activePowerControl_V1_2.xsd @@ -0,0 +1,24 @@ + + + + + + + + + + + + + diff --git a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java index 6e24236fe07..3206071a35b 100644 --- a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java +++ b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/EurostagBinaryTest.java @@ -10,9 +10,6 @@ import com.powsybl.commons.io.TreeDataFormat; import com.powsybl.commons.test.ComparisonUtils; import com.powsybl.iidm.network.Network; -import com.powsybl.iidm.network.extensions.ActivePowerControlAdder; -import com.powsybl.iidm.network.extensions.ConnectablePosition; -import com.powsybl.iidm.network.extensions.ConnectablePositionAdder; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; import org.junit.jupiter.api.Test; @@ -47,20 +44,4 @@ void roundTripTest() throws IOException { roundTripVersionedJsonFromMinToCurrentVersionTest(fileName, IidmVersion.V_1_12); } - @Test - void roundTripTestWithExtension() throws IOException { - ExportOptions exportOptions = new ExportOptions().setFormat(TreeDataFormat.BIN); - ImportOptions importOptions = new ImportOptions().setFormat(TreeDataFormat.BIN); - Network network = EurostagTutorialExample1Factory.createWithLFResults(); - network.getGeneratorStream().findFirst().ifPresent(g -> g.newExtension(ActivePowerControlAdder.class).withDroop(2).withParticipate(true).add()); - network.getLoadStream().forEach(l -> l.newExtension(ConnectablePositionAdder.class).newFeeder().withDirection(ConnectablePosition.Direction.BOTTOM).add().add()); - roundTripTest(network, - (n, binFile) -> NetworkSerDe.write(n, exportOptions, binFile), - binFile -> NetworkSerDe.read(binFile, importOptions), - ComparisonUtils::assertBytesEquals, - getVersionedNetworkPath("eurostag-tutorial1-lf-extensions.bin", CURRENT_IIDM_VERSION)); - - //backward compatibility - roundTripVersionedJsonFromMinToCurrentVersionTest("eurostag-tutorial1-lf-extensions.bin", IidmVersion.V_1_12); - } } diff --git a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/extensions/ActivePowerControlXmlTest.java b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/extensions/ActivePowerControlXmlTest.java index 919deb63a95..613e0a6b5f9 100644 --- a/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/extensions/ActivePowerControlXmlTest.java +++ b/iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/extensions/ActivePowerControlXmlTest.java @@ -19,9 +19,12 @@ import org.junit.jupiter.api.Test; import java.io.IOException; +import java.util.OptionalDouble; import static com.powsybl.iidm.serde.IidmSerDeConstants.CURRENT_IIDM_VERSION; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Ghiles Abdellah {@literal } @@ -44,13 +47,36 @@ public void setUp() throws IOException { } @Test - void test() throws IOException { - Network network2 = allFormatsRoundTripTest(network, "/activePowerControlRoundTripRef.xml", CURRENT_IIDM_VERSION); + void testPLimitOverride() throws IOException { + network.getGenerator("GEN").getExtension(ActivePowerControl.class).setMaxPOverride(100.); + network.getBattery("BAT").getExtension(ActivePowerControl.class).setMinPOverride(10.); + Network network2 = allFormatsRoundTripTest(network, "/activePowerControlWithLimitRoundTripRef.xml", CURRENT_IIDM_VERSION); + + Generator gen2 = network2.getGenerator("GEN"); + assertNotNull(gen2); + ActivePowerControl activePowerControl1 = gen2.getExtension(ActivePowerControl.class); + assertNotNull(activePowerControl1); + assertEquals(OptionalDouble.of(100), activePowerControl1.getMaxPOverride()); + assertTrue(activePowerControl1.getMinPOverride().isEmpty()); + + Battery bat2 = network2.getBattery("BAT"); + assertNotNull(bat2); + ActivePowerControl activePowerControl2 = bat2.getExtension(ActivePowerControl.class); + assertNotNull(activePowerControl2); + assertTrue(activePowerControl2.getMaxPOverride().isEmpty()); + assertEquals(OptionalDouble.of(10), activePowerControl2.getMinPOverride()); + } + + @Test + void testIidmV11() throws IOException { + Network network2 = allFormatsRoundTripTest(network, "/activePowerControlRoundTripRef.xml", IidmVersion.V_1_11); Battery bat2 = network2.getBattery("BAT"); assertNotNull(bat2); ActivePowerControl activePowerControl2 = bat2.getExtension(ActivePowerControl.class); assertNotNull(activePowerControl2); + assertTrue(activePowerControl2.getMaxPOverride().isEmpty()); + assertTrue(activePowerControl2.getMinPOverride().isEmpty()); } @Test diff --git a/iidm/iidm-serde/src/test/resources/V1_12/activePowerControlWithLimitRoundTripRef.xml b/iidm/iidm-serde/src/test/resources/V1_12/activePowerControlWithLimitRoundTripRef.xml new file mode 100644 index 00000000000..469356d8c44 --- /dev/null +++ b/iidm/iidm-serde/src/test/resources/V1_12/activePowerControlWithLimitRoundTripRef.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/iidm/iidm-serde/src/test/resources/V1_12/eurostag-tutorial1-lf-extensions.bin b/iidm/iidm-serde/src/test/resources/V1_12/eurostag-tutorial1-lf-extensions.bin deleted file mode 100644 index 192b1c97131..00000000000 Binary files a/iidm/iidm-serde/src/test/resources/V1_12/eurostag-tutorial1-lf-extensions.bin and /dev/null differ diff --git a/iidm/iidm-serde/src/test/resources/V1_12/eurostag-tutorial1-lf-extensions.json b/iidm/iidm-serde/src/test/resources/V1_12/eurostag-tutorial1-lf-extensions.json index e517fec6c07..7fa2484b7ec 100644 --- a/iidm/iidm-serde/src/test/resources/V1_12/eurostag-tutorial1-lf-extensions.json +++ b/iidm/iidm-serde/src/test/resources/V1_12/eurostag-tutorial1-lf-extensions.json @@ -5,7 +5,7 @@ "version" : "1.1" }, { "extensionName" : "activePowerControl", - "version" : "1.1" + "version" : "1.2" } ], "id" : "sim1", "caseDate" : "2013-01-15T18:45:00.000+01:00", diff --git a/iidm/iidm-tck/src/test/java/com/powsybl/iidm/network/tck/extensions/AbstractActivePowerControlTest.java b/iidm/iidm-tck/src/test/java/com/powsybl/iidm/network/tck/extensions/AbstractActivePowerControlTest.java index d5b3e28ae5a..32f2b1e213f 100644 --- a/iidm/iidm-tck/src/test/java/com/powsybl/iidm/network/tck/extensions/AbstractActivePowerControlTest.java +++ b/iidm/iidm-tck/src/test/java/com/powsybl/iidm/network/tck/extensions/AbstractActivePowerControlTest.java @@ -100,15 +100,103 @@ public void variantsCloneTest() { } } + @Test + public void variantsCloneTestWithOverride() { + String variant1 = "variant1"; + String variant2 = "variant2"; + String variant3 = "variant3"; + + Network network = BatteryNetworkFactory.create(); + Battery bat = network.getBattery("BAT"); + assertNotNull(bat); + bat.newExtension(ActivePowerControlAdder.class) + .withDroop(4.0) + .withParticipate(true) + .withParticipationFactor(1.2) + .withMinPOverride(10) + .withMaxPOverride(100) + .add(); + ActivePowerControl activePowerControl = bat.getExtension(ActivePowerControl.class); + assertNotNull(activePowerControl); + + // Testing variant cloning + VariantManager variantManager = network.getVariantManager(); + variantManager.cloneVariant(INITIAL_VARIANT_ID, variant1); + variantManager.cloneVariant(variant1, variant2); + variantManager.setWorkingVariant(variant1); + checkValues3(activePowerControl); + + // Testing setting different values in the cloned variant and going back to the initial one + activePowerControl.setDroop(6.0); + activePowerControl.setParticipate(false); + activePowerControl.setParticipationFactor(3.0); + activePowerControl.setMaxPOverride(110.); + activePowerControl.setMinPOverride(Double.NaN); + checkValues4(activePowerControl); + + activePowerControl.setMinPOverride(11.); + activePowerControl.setMaxPOverride(Double.NaN); + checkValues5(activePowerControl); + + variantManager.setWorkingVariant(INITIAL_VARIANT_ID); + checkValues3(activePowerControl); + + // Removes a variant then adds another variant to test variant recycling (hence calling allocateVariantArrayElement) + variantManager.removeVariant(variant1); + List targetVariantIds = Arrays.asList(variant1, variant3); + variantManager.cloneVariant(INITIAL_VARIANT_ID, targetVariantIds); + variantManager.setWorkingVariant(variant1); + checkValues3(activePowerControl); + variantManager.setWorkingVariant(variant3); + checkValues3(activePowerControl); + + // Test removing current variant + variantManager.removeVariant(variant3); + try { + activePowerControl.getDroop(); + fail(); + } catch (PowsyblException e) { + assertEquals("Variant index not set", e.getMessage()); + } + } + private static void checkValues1(ActivePowerControl activePowerControl) { assertTrue(activePowerControl.isParticipate()); assertEquals(4.0, activePowerControl.getDroop(), 0.0); assertEquals(1.2, activePowerControl.getParticipationFactor(), 0.0); + assertTrue(activePowerControl.getMaxPOverride().isEmpty()); + assertTrue(activePowerControl.getMinPOverride().isEmpty()); } private static void checkValues2(ActivePowerControl activePowerControl) { assertFalse(activePowerControl.isParticipate()); assertEquals(6.0, activePowerControl.getDroop(), 0.0); assertEquals(3.0, activePowerControl.getParticipationFactor(), 0.0); + assertTrue(activePowerControl.getMaxPOverride().isEmpty()); + assertTrue(activePowerControl.getMinPOverride().isEmpty()); + } + + private static void checkValues3(ActivePowerControl activePowerControl) { + assertTrue(activePowerControl.isParticipate()); + assertEquals(4.0, activePowerControl.getDroop(), 0.0); + assertEquals(1.2, activePowerControl.getParticipationFactor(), 0.0); + assertEquals(10, activePowerControl.getMinPOverride().getAsDouble()); + assertEquals(100, activePowerControl.getMaxPOverride().getAsDouble()); + } + + private static void checkValues4(ActivePowerControl activePowerControl) { + assertFalse(activePowerControl.isParticipate()); + assertEquals(6.0, activePowerControl.getDroop(), 0.0); + assertEquals(3.0, activePowerControl.getParticipationFactor(), 0.0); + assertTrue(activePowerControl.getMinPOverride().isEmpty()); + assertEquals(110, activePowerControl.getMaxPOverride().getAsDouble()); + } + + private static void checkValues5(ActivePowerControl activePowerControl) { + assertFalse(activePowerControl.isParticipate()); + assertEquals(6.0, activePowerControl.getDroop(), 0.0); + assertEquals(3.0, activePowerControl.getParticipationFactor(), 0.0); + assertTrue(activePowerControl.getMaxPOverride().isEmpty()); + assertEquals(11, activePowerControl.getMinPOverride().getAsDouble()); } }