diff --git a/iidm/iidm-extensions/src/main/java/com/powsybl/iidm/network/extensions/StandbyAutomaton.java b/iidm/iidm-extensions/src/main/java/com/powsybl/iidm/network/extensions/StandbyAutomaton.java new file mode 100644 index 00000000000..1771b153d70 --- /dev/null +++ b/iidm/iidm-extensions/src/main/java/com/powsybl/iidm/network/extensions/StandbyAutomaton.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2022, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package com.powsybl.iidm.network.extensions; + +import com.powsybl.commons.extensions.Extension; +import com.powsybl.iidm.network.StaticVarCompensator; + +/** + * @author Geoffroy Jamgotchian + */ +public interface StandbyAutomaton extends Extension { + + String NAME = "standbyAutomaton"; + + @Override + default String getName() { + return NAME; + } + + /** + * Get the status of the automaton. Use true if in service, false otherwise. + */ + boolean isStandby(); + + StandbyAutomaton setStandby(boolean standby); + + /** + * Get the fix part of the susceptance (in S) used when the static var compensator is in stand by. Should be between the mininal + * and the maximal susceptance of the static var compensator. + */ + double getB0(); + + /** + * Set the fix part of the susceptance (in S) used when the static var compensator is in stand by. Should be between the mininal + * and the maximal susceptance of the static var compensator. + */ + StandbyAutomaton setB0(double b0); + + /** + * Get the voltage setpoint (in kV) used when the high voltage threshold is reached. + */ + double getHighVoltageSetpoint(); + + /** + * @deprecated Use {@link #getHighVoltageSetpoint()} instead. + */ + @Deprecated(since = "4.11.0") + default float getHighVoltageSetPoint() { + return (float) getHighVoltageSetpoint(); + } + + /** + * Set the voltage setpoint (in kV) used when the high voltage threshold is reached. + */ + StandbyAutomaton setHighVoltageSetpoint(double highVoltageSetpoint); + + /** + * @deprecated Use {@link #setHighVoltageSetpoint(double)} instead. + */ + @Deprecated(since = "4.11.0") + default StandbyAutomaton setHighVoltageSetPoint(float highVoltageSetpoint) { + return setHighVoltageSetpoint(highVoltageSetpoint); + } + + /** + * Get the high voltage threshold (in kV). Above this value, the static var compensator controls voltage at high voltage setpoint. + */ + double getHighVoltageThreshold(); + + /** + * Set the high voltage threshold (in kV). Above this value, the static var compensator controls voltage at high voltage setpoint. + */ + StandbyAutomaton setHighVoltageThreshold(double highVoltageThreshold); + + /** + * Get the voltage setpoint (in kV) used when the low voltage threshold is reached. + */ + double getLowVoltageSetpoint(); + + /** + * @deprecated Use {@link #getLowVoltageSetpoint()} instead. + */ + @Deprecated(since = "4.11.0") + default float getLowVoltageSetPoint() { + return (float) getLowVoltageSetpoint(); + } + + /** + * Set the voltage setpoint (in kV) used when the low voltage threshold is reached. + */ + StandbyAutomaton setLowVoltageSetpoint(double lowVoltageSetpoint); + + /** + * @deprecated Use {@link #setLowVoltageSetpoint(double)} instead. + */ + @Deprecated(since = "4.11.0") + default StandbyAutomaton setLowVoltageSetPoint(float lowVoltageSetpoint) { + return setLowVoltageSetpoint(lowVoltageSetpoint); + } + + /** + * Get the low voltage threshold (in kV). Under this value, the static var compensator controls voltage at low voltage setpoint. + */ + double getLowVoltageThreshold(); + + /** + * Set the low voltage threshold (in kV). Under this value, the static var compensator controls voltage at low voltage setpoint. + */ + StandbyAutomaton setLowVoltageThreshold(double lowVoltageThreshold); +} diff --git a/iidm/iidm-extensions/src/main/java/com/powsybl/iidm/network/extensions/StandbyAutomatonAdder.java b/iidm/iidm-extensions/src/main/java/com/powsybl/iidm/network/extensions/StandbyAutomatonAdder.java new file mode 100644 index 00000000000..88a13144810 --- /dev/null +++ b/iidm/iidm-extensions/src/main/java/com/powsybl/iidm/network/extensions/StandbyAutomatonAdder.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2022, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package com.powsybl.iidm.network.extensions; + +import com.powsybl.commons.extensions.ExtensionAdder; +import com.powsybl.iidm.network.StaticVarCompensator; + +/** + * @author Jérémy Labous + */ +public interface StandbyAutomatonAdder extends ExtensionAdder { + + @Override + default Class getExtensionClass() { + return StandbyAutomaton.class; + } + + /** + * Define the status of the automaton. Use true if in service, false otherwise. + */ + StandbyAutomatonAdder withStandbyStatus(boolean standby); + + /** + * Define the fix part of the susceptance (in S) used when the static var compensator is in stand by. Should be between the mininal + * and the maximal susceptance of the static var compensator. + */ + StandbyAutomatonAdder withB0(double b0); + + /** + * Define the voltage setpoint (in kV) used when the high voltage threshold is reached. + */ + StandbyAutomatonAdder withHighVoltageSetpoint(double highVoltageSetpoint); + + /** + * @deprecated Use {@link #withHighVoltageSetpoint(double)} instead. + */ + @Deprecated(since = "4.11.0") + default StandbyAutomatonAdder withHighVoltageSetPoint(float highVoltageSetpoint) { + return withHighVoltageSetpoint(highVoltageSetpoint); + } + + /** + * Define the high voltage threshold (in kV). Above this value, the static var compensator controls voltage at high voltage setpoint. + */ + StandbyAutomatonAdder withHighVoltageThreshold(double highVoltageThreshold); + + /** + * Define the voltage setpoint (in kV) used when the low voltage threshold is reached. + */ + StandbyAutomatonAdder withLowVoltageSetpoint(double lowVoltageSetpoint); + + /** + * @deprecated Use {@link #withLowVoltageSetpoint(double)} instead. + */ + @Deprecated(since = "4.11.0") + default StandbyAutomatonAdder withLowVoltageSetPoint(float lowVoltageSetpoint) { + return withHighVoltageSetpoint(lowVoltageSetpoint); + } + + /** + * Define the low voltage threshold (in kV). Under this value, the static var compensator controls voltage at low voltage setpoint. + */ + StandbyAutomatonAdder withLowVoltageThreshold(double lowVoltageThreshold); +} diff --git a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/StandbyAutomatonAdderImpl.java b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/StandbyAutomatonAdderImpl.java new file mode 100644 index 00000000000..4e63ad4b960 --- /dev/null +++ b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/StandbyAutomatonAdderImpl.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2022, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package com.powsybl.iidm.network.impl.extensions; + +import com.powsybl.commons.extensions.AbstractExtensionAdder; +import com.powsybl.iidm.network.StaticVarCompensator; +import com.powsybl.iidm.network.extensions.StandbyAutomaton; +import com.powsybl.iidm.network.extensions.StandbyAutomatonAdder; + +/** + * @author Jérémy Labous + */ +public class StandbyAutomatonAdderImpl extends AbstractExtensionAdder + implements StandbyAutomatonAdder { + + private double b0; + + private boolean standby; + + private double lowVoltageSetpoint; + + private double highVoltageSetpoint; + + private double lowVoltageThreshold; + + private double highVoltageThreshold; + + public StandbyAutomatonAdderImpl(StaticVarCompensator svc) { + super(svc); + } + + @Override + protected StandbyAutomaton createExtension(StaticVarCompensator staticVarCompensator) { + return new StandbyAutomatonImpl(staticVarCompensator, b0, standby, + lowVoltageSetpoint, highVoltageSetpoint, lowVoltageThreshold, highVoltageThreshold); + } + + @Override + public StandbyAutomatonAdderImpl withStandbyStatus(boolean standby) { + this.standby = standby; + return this; + } + + @Override + public StandbyAutomatonAdderImpl withB0(double b0) { + this.b0 = b0; + return this; + } + + @Override + public StandbyAutomatonAdderImpl withHighVoltageSetpoint(double highVoltageSetpoint) { + this.highVoltageSetpoint = highVoltageSetpoint; + return this; + } + + @Override + public StandbyAutomatonAdderImpl withHighVoltageThreshold(double highVoltageThreshold) { + this.highVoltageThreshold = highVoltageThreshold; + return this; + } + + @Override + public StandbyAutomatonAdderImpl withLowVoltageSetpoint(double lowVoltageSetpoint) { + this.lowVoltageSetpoint = lowVoltageSetpoint; + return this; + } + + @Override + public StandbyAutomatonAdderImpl withLowVoltageThreshold(double lowVoltageThreshold) { + this.lowVoltageThreshold = lowVoltageThreshold; + return this; + } +} diff --git a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/StandbyAutomatonAdderImplProvider.java b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/StandbyAutomatonAdderImplProvider.java new file mode 100644 index 00000000000..0a56c062c76 --- /dev/null +++ b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/StandbyAutomatonAdderImplProvider.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2022, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package com.powsybl.iidm.network.impl.extensions; + +import com.google.auto.service.AutoService; +import com.powsybl.commons.extensions.ExtensionAdderProvider; +import com.powsybl.iidm.network.StaticVarCompensator; +import com.powsybl.iidm.network.extensions.StandbyAutomaton; + +/** + * @author Jérémy Labous + */ +@AutoService(ExtensionAdderProvider.class) +public class StandbyAutomatonAdderImplProvider + implements ExtensionAdderProvider { + + @Override + public String getImplementationName() { + return "Default"; + } + + @Override + public String getExtensionName() { + return StandbyAutomaton.NAME; + } + + @Override + public Class getAdderClass() { + return StandbyAutomatonAdderImpl.class; + } + + @Override + public StandbyAutomatonAdderImpl newAdder(StaticVarCompensator extendable) { + return new StandbyAutomatonAdderImpl(extendable); + } +} diff --git a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/StandbyAutomatonImpl.java b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/StandbyAutomatonImpl.java new file mode 100644 index 00000000000..c54a4626b88 --- /dev/null +++ b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/extensions/StandbyAutomatonImpl.java @@ -0,0 +1,197 @@ +/** + * Copyright (c) 2022, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package com.powsybl.iidm.network.impl.extensions; + +import com.powsybl.commons.util.trove.TBooleanArrayList; +import com.powsybl.iidm.network.StaticVarCompensator; +import com.powsybl.iidm.network.extensions.StandbyAutomaton; +import com.powsybl.iidm.network.impl.AbstractMultiVariantIdentifiableExtension; +import gnu.trove.list.array.TDoubleArrayList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Jérémy Labous + */ +public class StandbyAutomatonImpl extends AbstractMultiVariantIdentifiableExtension implements StandbyAutomaton { + + private static final Logger LOGGER = LoggerFactory.getLogger(StandbyAutomatonImpl.class); + + private double b0; + private final TBooleanArrayList standby; + private final TDoubleArrayList lowVoltageSetpoint; + private final TDoubleArrayList highVoltageSetpoint; + private final TDoubleArrayList lowVoltageThreshold; + private final TDoubleArrayList highVoltageThreshold; + + private static double checkB0(double b0) { + if (Double.isNaN(b0)) { + throw new IllegalArgumentException("b0 is invalid"); + } + return b0; + } + + private static void checkVoltageConfig(double lowVoltageSetpoint, double highVoltageSetpoint, + double lowVoltageThreshold, double highVoltageThreshold) { + if (Double.isNaN(lowVoltageSetpoint)) { + throw new IllegalArgumentException("lowVoltageSetpoint is invalid"); + } + if (Double.isNaN(highVoltageSetpoint)) { + throw new IllegalArgumentException("highVoltageSetpoint is invalid"); + } + if (Double.isNaN(lowVoltageThreshold)) { + throw new IllegalArgumentException("lowVoltageThreshold is invalid"); + } + if (Double.isNaN(highVoltageThreshold)) { + throw new IllegalArgumentException("highVoltageThreshold is invalid"); + } + if (lowVoltageThreshold >= highVoltageThreshold) { + throw new IllegalArgumentException("Inconsistent low (" + lowVoltageThreshold + ") and high (" + highVoltageThreshold + ") voltage thresholds"); + } + if (lowVoltageSetpoint < lowVoltageThreshold) { + LOGGER.warn("Invalid low voltage setpoint {} < threshold {}", lowVoltageSetpoint, lowVoltageThreshold); + } + if (highVoltageSetpoint > highVoltageThreshold) { + LOGGER.warn("Invalid high voltage setpoint {} > threshold {}", highVoltageSetpoint, highVoltageThreshold); + } + } + + public StandbyAutomatonImpl(StaticVarCompensator svc, double b0, boolean standby, double lowVoltageSetpoint, double highVoltageSetpoint, + double lowVoltageThreshold, double highVoltageThreshold) { + super(svc); + int variantArraySize = getVariantManagerHolder().getVariantManager().getVariantArraySize(); + checkVoltageConfig(lowVoltageSetpoint, highVoltageSetpoint, lowVoltageThreshold, highVoltageThreshold); + this.b0 = checkB0(b0); + this.standby = new TBooleanArrayList(variantArraySize); + this.lowVoltageSetpoint = new TDoubleArrayList(variantArraySize); + this.highVoltageSetpoint = new TDoubleArrayList(variantArraySize); + this.lowVoltageThreshold = new TDoubleArrayList(variantArraySize); + this.highVoltageThreshold = new TDoubleArrayList(variantArraySize); + for (int i = 0; i < variantArraySize; i++) { + this.standby.add(standby); + this.lowVoltageSetpoint.add(lowVoltageSetpoint); + this.highVoltageSetpoint.add(highVoltageSetpoint); + this.lowVoltageThreshold.add(lowVoltageThreshold); + this.highVoltageThreshold.add(highVoltageThreshold); + } + } + + @Override + public boolean isStandby() { + return standby.get(getVariantIndex()); + } + + @Override + public StandbyAutomatonImpl setStandby(boolean standby) { + this.standby.set(getVariantIndex(), standby); + return this; + } + + @Override + public double getB0() { + return b0; + } + + @Override + public StandbyAutomatonImpl setB0(double b0) { + this.b0 = checkB0(b0); + return this; + } + + @Override + public double getHighVoltageSetpoint() { + return highVoltageSetpoint.get(getVariantIndex()); + } + + @Override + public StandbyAutomatonImpl setHighVoltageSetpoint(double highVoltageSetpoint) { + checkVoltageConfig(lowVoltageSetpoint.get(getVariantIndex()), highVoltageSetpoint, + lowVoltageThreshold.get(getVariantIndex()), highVoltageThreshold.get(getVariantIndex())); + this.highVoltageSetpoint.set(getVariantIndex(), highVoltageSetpoint); + return this; + } + + @Override + public double getHighVoltageThreshold() { + return highVoltageThreshold.get(getVariantIndex()); + } + + @Override + public StandbyAutomatonImpl setHighVoltageThreshold(double highVoltageThreshold) { + checkVoltageConfig(lowVoltageSetpoint.get(getVariantIndex()), highVoltageSetpoint.get(getVariantIndex()), + lowVoltageThreshold.get(getVariantIndex()), highVoltageThreshold); + this.highVoltageThreshold.set(getVariantIndex(), highVoltageThreshold); + return this; + } + + @Override + public double getLowVoltageSetpoint() { + return lowVoltageSetpoint.get(getVariantIndex()); + } + + @Override + public StandbyAutomatonImpl setLowVoltageSetpoint(double lowVoltageSetpoint) { + checkVoltageConfig(lowVoltageSetpoint, highVoltageSetpoint.get(getVariantIndex()), + lowVoltageThreshold.get(getVariantIndex()), highVoltageThreshold.get(getVariantIndex())); + this.lowVoltageSetpoint.set(getVariantIndex(), lowVoltageSetpoint); + return this; + } + + @Override + public double getLowVoltageThreshold() { + return lowVoltageThreshold.get(getVariantIndex()); + } + + @Override + public StandbyAutomatonImpl setLowVoltageThreshold(double lowVoltageThreshold) { + checkVoltageConfig(lowVoltageSetpoint.get(getVariantIndex()), highVoltageSetpoint.get(getVariantIndex()), + lowVoltageThreshold, highVoltageThreshold.get(getVariantIndex())); + this.lowVoltageThreshold.set(getVariantIndex(), lowVoltageThreshold); + return this; + } + + @Override + public void extendVariantArraySize(int initVariantArraySize, int number, int sourceIndex) { + standby.ensureCapacity(standby.size() + number); + lowVoltageSetpoint.ensureCapacity(lowVoltageSetpoint.size() + number); + highVoltageSetpoint.ensureCapacity(highVoltageSetpoint.size() + number); + lowVoltageThreshold.ensureCapacity(lowVoltageThreshold.size() + number); + highVoltageThreshold.ensureCapacity(highVoltageThreshold.size() + number); + for (int i = 0; i < number; i++) { + standby.add(standby.get(sourceIndex)); + lowVoltageSetpoint.add(lowVoltageSetpoint.get(sourceIndex)); + highVoltageSetpoint.add(highVoltageSetpoint.get(sourceIndex)); + lowVoltageThreshold.add(lowVoltageThreshold.get(sourceIndex)); + highVoltageThreshold.add(highVoltageThreshold.get(sourceIndex)); + } + } + + @Override + public void reduceVariantArraySize(int number) { + standby.remove(standby.size() - number, number); + lowVoltageSetpoint.remove(lowVoltageSetpoint.size() - number, number); + highVoltageSetpoint.remove(highVoltageSetpoint.size() - number, number); + lowVoltageThreshold.remove(lowVoltageThreshold.size() - number, number); + highVoltageThreshold.remove(highVoltageThreshold.size() - number, number); + } + + @Override + public void deleteVariantArrayElement(int i) { + // Does nothing + } + + @Override + public void allocateVariantArrayElement(int[] indexes, int sourceIndex) { + for (int index : indexes) { + standby.set(index, standby.get(sourceIndex)); + lowVoltageSetpoint.set(index, lowVoltageSetpoint.get(sourceIndex)); + highVoltageSetpoint.set(index, highVoltageSetpoint.get(sourceIndex)); + lowVoltageThreshold.set(index, lowVoltageThreshold.get(sourceIndex)); + highVoltageThreshold.set(index, highVoltageThreshold.get(sourceIndex)); + } + } +} diff --git a/iidm/iidm-impl/src/test/java/com/powsybl/iidm/network/impl/tck/extensions/StandbyAutomatonTest.java b/iidm/iidm-impl/src/test/java/com/powsybl/iidm/network/impl/tck/extensions/StandbyAutomatonTest.java new file mode 100644 index 00000000000..b167b98f924 --- /dev/null +++ b/iidm/iidm-impl/src/test/java/com/powsybl/iidm/network/impl/tck/extensions/StandbyAutomatonTest.java @@ -0,0 +1,15 @@ +/** + * Copyright (c) 2022, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package com.powsybl.iidm.network.impl.tck.extensions; + +import com.powsybl.iidm.network.tck.extensions.AbstractStandbyAutomatonTest; + +/** + * @author Anne Tilloy + */ +public class StandbyAutomatonTest extends AbstractStandbyAutomatonTest { +} diff --git a/iidm/iidm-tck/src/test/java/com/powsybl/iidm/network/tck/extensions/AbstractStandbyAutomatonTest.java b/iidm/iidm-tck/src/test/java/com/powsybl/iidm/network/tck/extensions/AbstractStandbyAutomatonTest.java new file mode 100644 index 00000000000..d7ce70a0585 --- /dev/null +++ b/iidm/iidm-tck/src/test/java/com/powsybl/iidm/network/tck/extensions/AbstractStandbyAutomatonTest.java @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2022, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package com.powsybl.iidm.network.tck.extensions; + +import com.powsybl.commons.PowsyblException; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.StaticVarCompensator; +import com.powsybl.iidm.network.VariantManager; +import com.powsybl.iidm.network.extensions.StandbyAutomaton; +import com.powsybl.iidm.network.extensions.StandbyAutomatonAdder; +import com.powsybl.iidm.network.test.SvcTestCaseFactory; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static com.powsybl.iidm.network.VariantManagerConstants.INITIAL_VARIANT_ID; +import static org.junit.Assert.*; + +/** + * @author Geoffroy Jamgotchian + */ +public abstract class AbstractStandbyAutomatonTest { + + @Test + public void test() { + Network network = SvcTestCaseFactory.create(); + StaticVarCompensator svc = network.getStaticVarCompensator("SVC2"); + svc.newExtension(StandbyAutomatonAdder.class) + .withB0(0.0001f) + .withStandbyStatus(true) + .withLowVoltageSetpoint(390f) + .withHighVoltageSetpoint(400f) + .withLowVoltageThreshold(385f) + .withHighVoltageThreshold(405f) + .add(); + StandbyAutomaton standbyAutomaton = svc.getExtension(StandbyAutomaton.class); + assertEquals(0.0001f, standbyAutomaton.getB0(), 0.0); + assertTrue(standbyAutomaton.isStandby()); + assertEquals(390, standbyAutomaton.getLowVoltageSetpoint(), 0.0); + assertEquals(400, standbyAutomaton.getHighVoltageSetpoint(), 0.0); + assertEquals(385, standbyAutomaton.getLowVoltageThreshold(), 0.0); + assertEquals(405, standbyAutomaton.getHighVoltageThreshold(), 0.0); + standbyAutomaton.setB0(0.0002f); + assertEquals(0.0002f, standbyAutomaton.getB0(), 0.0); + standbyAutomaton.setStandby(false); + assertFalse(standbyAutomaton.isStandby()); + standbyAutomaton.setLowVoltageSetpoint(391f); + assertEquals(391, standbyAutomaton.getLowVoltageSetpoint(), 0.0); + standbyAutomaton.setHighVoltageSetpoint(401f); + assertEquals(401, standbyAutomaton.getHighVoltageSetpoint(), 0.0); + standbyAutomaton.setLowVoltageThreshold(386f); + assertEquals(386, standbyAutomaton.getLowVoltageThreshold(), 0.0); + standbyAutomaton.setHighVoltageThreshold(406f); + assertEquals(406, standbyAutomaton.getHighVoltageThreshold(), 0.0); + try { + standbyAutomaton.setB0(Float.NaN); + fail(); + } catch (Exception ignored) { + } + try { + standbyAutomaton.setHighVoltageThreshold(200f); + fail(); + } catch (Exception ignored) { + } + } + + @Test + public void variantsCloneTest() { + String variant1 = "variant1"; + String variant2 = "variant2"; + String variant3 = "variant3"; + + Network network = SvcTestCaseFactory.create(); + StaticVarCompensator svc = network.getStaticVarCompensator("SVC2"); + assertNotNull(svc); + svc.newExtension(StandbyAutomatonAdder.class) + .withB0(0.0001f) + .withStandbyStatus(true) + .withLowVoltageSetpoint(390f) + .withHighVoltageSetpoint(400f) + .withLowVoltageThreshold(385f) + .withHighVoltageThreshold(405f) + .add(); + StandbyAutomaton standbyAutomaton = svc.getExtension(StandbyAutomaton.class); + assertNotNull(standbyAutomaton); + + // Testing variant cloning + VariantManager variantManager = network.getVariantManager(); + variantManager.cloneVariant(INITIAL_VARIANT_ID, variant1); + variantManager.cloneVariant(variant1, variant2); + variantManager.setWorkingVariant(variant1); + assertTrue(standbyAutomaton.isStandby()); + assertEquals(0.0001f, standbyAutomaton.getB0(), 0f); + assertEquals(390f, standbyAutomaton.getLowVoltageSetpoint(), 0f); + assertEquals(400f, standbyAutomaton.getHighVoltageSetpoint(), 0f); + assertEquals(385f, standbyAutomaton.getLowVoltageThreshold(), 0f); + assertEquals(405f, standbyAutomaton.getHighVoltageThreshold(), 0f); + + // Testing setting different values in the cloned variant and going back to the initial one + standbyAutomaton.setB0(0.0004f) + .setStandby(false) + .setLowVoltageSetpoint(392f) + .setHighVoltageSetpoint(403f) + .setLowVoltageThreshold(390f) + .setHighVoltageThreshold(410f); + + assertFalse(standbyAutomaton.isStandby()); + assertEquals(0.0004f, standbyAutomaton.getB0(), 0f); + assertEquals(392f, standbyAutomaton.getLowVoltageSetpoint(), 0f); + assertEquals(403f, standbyAutomaton.getHighVoltageSetpoint(), 0f); + assertEquals(390f, standbyAutomaton.getLowVoltageThreshold(), 0f); + assertEquals(410f, standbyAutomaton.getHighVoltageThreshold(), 0f); + variantManager.setWorkingVariant(INITIAL_VARIANT_ID); + + assertTrue(standbyAutomaton.isStandby()); + assertEquals(0.0004f, standbyAutomaton.getB0(), 0f); // not modify by variant change + assertEquals(390f, standbyAutomaton.getLowVoltageSetpoint(), 0f); + assertEquals(400f, standbyAutomaton.getHighVoltageSetpoint(), 0f); + assertEquals(385f, standbyAutomaton.getLowVoltageThreshold(), 0f); + assertEquals(405f, standbyAutomaton.getHighVoltageThreshold(), 0f); + + // 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); + assertTrue(standbyAutomaton.isStandby()); + assertEquals(0.0004f, standbyAutomaton.getB0(), 0f); + assertEquals(390f, standbyAutomaton.getLowVoltageSetpoint(), 0f); + assertEquals(400f, standbyAutomaton.getHighVoltageSetpoint(), 0f); + assertEquals(385f, standbyAutomaton.getLowVoltageThreshold(), 0f); + assertEquals(405f, standbyAutomaton.getHighVoltageThreshold(), 0f); + variantManager.setWorkingVariant(variant3); + assertTrue(standbyAutomaton.isStandby()); + assertEquals(0.0004f, standbyAutomaton.getB0(), 0f); + assertEquals(390f, standbyAutomaton.getLowVoltageSetpoint(), 0f); + assertEquals(400f, standbyAutomaton.getHighVoltageSetpoint(), 0f); + assertEquals(385f, standbyAutomaton.getLowVoltageThreshold(), 0f); + assertEquals(405f, standbyAutomaton.getHighVoltageThreshold(), 0f); + + // Test removing current variant + variantManager.removeVariant(variant3); + try { + standbyAutomaton.getLowVoltageSetpoint(); + fail(); + } catch (PowsyblException e) { + assertEquals("Variant index not set", e.getMessage()); + } + } + +} diff --git a/iidm/iidm-xml-converter/src/main/java/com/powsybl/iidm/xml/extensions/StandbyAutomatonXmlSerializer.java b/iidm/iidm-xml-converter/src/main/java/com/powsybl/iidm/xml/extensions/StandbyAutomatonXmlSerializer.java new file mode 100644 index 00000000000..027d441c24c --- /dev/null +++ b/iidm/iidm-xml-converter/src/main/java/com/powsybl/iidm/xml/extensions/StandbyAutomatonXmlSerializer.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2022, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package com.powsybl.iidm.xml.extensions; + +import com.google.auto.service.AutoService; +import com.powsybl.commons.extensions.AbstractExtensionXmlSerializer; +import com.powsybl.commons.extensions.ExtensionXmlSerializer; +import com.powsybl.commons.xml.XmlReaderContext; +import com.powsybl.commons.xml.XmlUtil; +import com.powsybl.commons.xml.XmlWriterContext; +import com.powsybl.iidm.network.StaticVarCompensator; +import com.powsybl.iidm.network.extensions.StandbyAutomaton; +import com.powsybl.iidm.network.extensions.StandbyAutomatonAdder; + +import javax.xml.stream.XMLStreamException; + +/** + * @author Geoffroy Jamgotchian + */ +@AutoService(ExtensionXmlSerializer.class) +public class StandbyAutomatonXmlSerializer extends AbstractExtensionXmlSerializer { + + // TODO make this serializer versionable to fix lowVoltageSetpoint/highVoltageSetpoint + public StandbyAutomatonXmlSerializer() { + super("standbyAutomaton", "network", StandbyAutomaton.class, false, "standbyAutomaton.xsd", + "http://www.itesla_project.eu/schema/iidm/ext/standby_automaton/1_0", "sa"); + } + + @Override + public void write(StandbyAutomaton standbyAutomaton, XmlWriterContext context) throws XMLStreamException { + XmlUtil.writeDouble("b0", standbyAutomaton.getB0(), context.getWriter()); + context.getWriter().writeAttribute("standby", Boolean.toString(standbyAutomaton.isStandby())); + XmlUtil.writeDouble("lowVoltageSetPoint", standbyAutomaton.getLowVoltageSetpoint(), context.getWriter()); + XmlUtil.writeDouble("highVoltageSetPoint", standbyAutomaton.getHighVoltageSetpoint(), context.getWriter()); + XmlUtil.writeDouble("lowVoltageThreshold", standbyAutomaton.getLowVoltageThreshold(), context.getWriter()); + XmlUtil.writeDouble("highVoltageThreshold", standbyAutomaton.getHighVoltageThreshold(), context.getWriter()); + } + + @Override + public StandbyAutomaton read(StaticVarCompensator svc, XmlReaderContext context) { + double b0 = XmlUtil.readDoubleAttribute(context.getReader(), "b0"); + boolean standby = XmlUtil.readBoolAttribute(context.getReader(), "standby"); + double lowVoltageSetpoint = XmlUtil.readDoubleAttribute(context.getReader(), "lowVoltageSetPoint"); + double highVoltageSetpoint = XmlUtil.readDoubleAttribute(context.getReader(), "highVoltageSetPoint"); + double lowVoltageThreshold = XmlUtil.readDoubleAttribute(context.getReader(), "lowVoltageThreshold"); + double highVoltageThreshold = XmlUtil.readDoubleAttribute(context.getReader(), "highVoltageThreshold"); + svc.newExtension(StandbyAutomatonAdder.class) + .withB0(b0) + .withStandbyStatus(standby) + .withLowVoltageSetpoint(lowVoltageSetpoint) + .withHighVoltageSetpoint(highVoltageSetpoint) + .withLowVoltageThreshold(lowVoltageThreshold) + .withHighVoltageThreshold(highVoltageThreshold) + .add(); + return svc.getExtension(StandbyAutomaton.class); + } +} diff --git a/iidm/iidm-xml-converter/src/main/resources/xsd/standbyAutomaton.xsd b/iidm/iidm-xml-converter/src/main/resources/xsd/standbyAutomaton.xsd new file mode 100644 index 00000000000..17b26e17ea9 --- /dev/null +++ b/iidm/iidm-xml-converter/src/main/resources/xsd/standbyAutomaton.xsd @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/iidm/iidm-xml-converter/src/test/java/com/powsybl/iidm/xml/extensions/StandbyAutomatonXmlTest.java b/iidm/iidm-xml-converter/src/test/java/com/powsybl/iidm/xml/extensions/StandbyAutomatonXmlTest.java new file mode 100644 index 00000000000..d03e929ded5 --- /dev/null +++ b/iidm/iidm-xml-converter/src/test/java/com/powsybl/iidm/xml/extensions/StandbyAutomatonXmlTest.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2022, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package com.powsybl.iidm.xml.extensions; + +import com.powsybl.commons.AbstractConverterTest; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.StaticVarCompensator; +import com.powsybl.iidm.network.extensions.StandbyAutomaton; +import com.powsybl.iidm.network.extensions.StandbyAutomatonAdder; +import com.powsybl.iidm.network.test.SvcTestCaseFactory; +import com.powsybl.iidm.xml.NetworkXml; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.*; + +/** + * @author Geoffroy Jamgotchian + */ +public class StandbyAutomatonXmlTest extends AbstractConverterTest { + + @Test + public void test() throws IOException { + Network network = SvcTestCaseFactory.create(); + StaticVarCompensator svc = network.getStaticVarCompensator("SVC2"); + svc.newExtension(StandbyAutomatonAdder.class) + .withB0(0.0001) + .withStandbyStatus(true) + .withLowVoltageSetpoint(390) + .withHighVoltageSetpoint(400) + .withLowVoltageThreshold(385) + .withHighVoltageThreshold(405) + .add(); + StandbyAutomaton standbyAutomaton = svc.getExtension(StandbyAutomaton.class); + + Network network2 = roundTripXmlTest(network, + NetworkXml::writeAndValidate, + NetworkXml::read, + "/standbyAutomatonRoundTripRef.xml"); + + StaticVarCompensator svc2 = network2.getStaticVarCompensator("SVC2"); + StandbyAutomaton standbyAutomaton2 = svc2.getExtension(StandbyAutomaton.class); + assertNotNull(standbyAutomaton2); + assertEquals(standbyAutomaton.getB0(), standbyAutomaton2.getB0(), 0.0); + assertEquals(standbyAutomaton.isStandby(), standbyAutomaton2.isStandby()); + assertEquals(standbyAutomaton.getLowVoltageSetpoint(), standbyAutomaton2.getLowVoltageSetpoint(), 0.0); + assertEquals(standbyAutomaton.getHighVoltageSetpoint(), standbyAutomaton2.getHighVoltageSetpoint(), 0.0); + assertEquals(standbyAutomaton.getLowVoltageThreshold(), standbyAutomaton2.getLowVoltageThreshold(), 0.0); + assertEquals(standbyAutomaton.getHighVoltageThreshold(), standbyAutomaton2.getHighVoltageThreshold(), 0.0); + } +} diff --git a/iidm/iidm-xml-converter/src/test/resources/standbyAutomatonRoundTripRef.xml b/iidm/iidm-xml-converter/src/test/resources/standbyAutomatonRoundTripRef.xml new file mode 100644 index 00000000000..da95882f5b4 --- /dev/null +++ b/iidm/iidm-xml-converter/src/test/resources/standbyAutomatonRoundTripRef.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +