Skip to content

Commit

Permalink
Create adders from existing objects: ReactiveCapabilityCurve, PhaseTa…
Browse files Browse the repository at this point in the history
…pChanger, RatioTapChanger (#3130)

* add reactive capability curve builder using existing reactive capability curve as template
* add way to build tap changers by copying existing ones

Signed-off-by: CHIQUET Benoit <benoit.chiquet@rte-france.com>
  • Loading branch information
bc-rte authored Dec 2, 2024
1 parent 710047c commit 94abfaa
Show file tree
Hide file tree
Showing 6 changed files with 315 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import java.util.Optional;

/**
*
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
public interface PhaseTapChangerHolder {
Expand All @@ -21,6 +20,33 @@ public interface PhaseTapChangerHolder {
*/
PhaseTapChangerAdder newPhaseTapChanger();

/**
* Get a builder to create and associate a phase tap changer to the
* transformer, initialized with the values of an existing ratio tap changer.
*/
default PhaseTapChangerAdder newPhaseTapChanger(PhaseTapChanger phaseTapChanger) {
PhaseTapChangerAdder adder = this.newPhaseTapChanger()
.setRegulationTerminal(phaseTapChanger.getRegulationTerminal())
.setRegulationMode(phaseTapChanger.getRegulationMode())
.setRegulationValue(phaseTapChanger.getRegulationValue())
.setLowTapPosition(phaseTapChanger.getLowTapPosition())
.setTapPosition(phaseTapChanger.getTapPosition())
.setRegulating(phaseTapChanger.isRegulating())
.setTargetDeadband(phaseTapChanger.getTargetDeadband());
for (int tapPosition = phaseTapChanger.getLowTapPosition(); tapPosition <= phaseTapChanger.getHighTapPosition(); tapPosition++) {
PhaseTapChangerStep step = phaseTapChanger.getStep(tapPosition);
adder.beginStep()
.setAlpha(step.getAlpha())
.setRho(step.getRho())
.setB(step.getB())
.setG(step.getG())
.setX(step.getX())
.setR(step.getR())
.endStep();
}
return adder;
}

/**
* Get the phase tap changer.
* <p>Could return <code>null</code> if the transfomer is not associated to
Expand All @@ -36,7 +62,7 @@ default Optional<PhaseTapChanger> getOptionalPhaseTapChanger() {
}

/**
* Check if a phase tap changer is present
* Check if a phase tap changer is present
*/
default boolean hasPhaseTapChanger() {
return getPhaseTapChanger() != null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,34 @@ public interface RatioTapChangerHolder {
*/
RatioTapChangerAdder newRatioTapChanger();

/**
* Get a builder to create and associate a ratio tap changer to the
* transformer, initialized with the values of an existing ratio tap changer.
*/
default RatioTapChangerAdder newRatioTapChanger(RatioTapChanger ratioTapChanger) {
RatioTapChangerAdder adder = this.newRatioTapChanger()
.setRegulationTerminal(ratioTapChanger.getRegulationTerminal())
.setRegulationMode(ratioTapChanger.getRegulationMode())
.setRegulationValue(ratioTapChanger.getRegulationValue())
.setLoadTapChangingCapabilities(ratioTapChanger.hasLoadTapChangingCapabilities())
.setTargetV(ratioTapChanger.getTargetV())
.setLowTapPosition(ratioTapChanger.getLowTapPosition())
.setTapPosition(ratioTapChanger.getTapPosition())
.setRegulating(ratioTapChanger.isRegulating())
.setTargetDeadband(ratioTapChanger.getTargetDeadband());
for (int tapPosition = ratioTapChanger.getLowTapPosition(); tapPosition <= ratioTapChanger.getHighTapPosition(); tapPosition++) {
RatioTapChangerStep step = ratioTapChanger.getStep(tapPosition);
adder.beginStep()
.setRho(step.getRho())
.setB(step.getB())
.setG(step.getG())
.setX(step.getX())
.setR(step.getR())
.endStep();
}
return adder;
}

/**
* Get the ratio tap changer.
* <p>Could return <code>null</code> if the leg is not associated to a ratio
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,19 @@ public interface ReactiveLimitsHolder {
* to this generator.
*/
MinMaxReactiveLimitsAdder newMinMaxReactiveLimits();

/**
* Get a builder to create and associate a new reactive capability curve
* to this generator based on an existing curve.
*/
default ReactiveCapabilityCurveAdder newReactiveCapabilityCurve(ReactiveCapabilityCurve copiedCurve) {
ReactiveCapabilityCurveAdder adder = newReactiveCapabilityCurve();
copiedCurve.getPoints().forEach(copiedPoint ->
adder.beginPoint()
.setP(copiedPoint.getP())
.setMinQ(copiedPoint.getMinQ())
.setMaxQ(copiedPoint.getMaxQ())
.endPoint());
return adder;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Copyright (c) 2024, 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/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.iidm.network.impl.tck;

import com.powsybl.iidm.network.tck.AbstractTapChangerHolderTest;

/**
* @author Benoît Chiquet {@literal <benoit.chiquet at rte-france.com>}
*/
public class TapChangerHolderTest extends AbstractTapChangerHolderTest {
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@
import com.powsybl.iidm.network.Generator;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.ReactiveCapabilityCurve;
import com.powsybl.iidm.network.ReactiveLimitsKind;
import com.powsybl.iidm.network.ValidationException;
import com.powsybl.iidm.network.test.FictitiousSwitchFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import java.util.Optional;

import static com.powsybl.iidm.network.ReactiveLimitsKind.CURVE;
import static org.junit.jupiter.api.Assertions.*;

public abstract class AbstractReactiveCapabilityCurveTest {
Expand Down Expand Up @@ -48,7 +50,7 @@ public void testAdder() {
.setMinQ(2.0)
.endPoint()
.add();
assertEquals(ReactiveLimitsKind.CURVE, reactiveCapabilityCurve.getKind());
assertEquals(CURVE, reactiveCapabilityCurve.getKind());
assertEquals(100.0, reactiveCapabilityCurve.getMaxP(), 0.0);
assertEquals(1.0, reactiveCapabilityCurve.getMinP(), 0.0);
assertEquals(3, reactiveCapabilityCurve.getPoints().size());
Expand Down Expand Up @@ -134,4 +136,33 @@ public void invalidMinQGreaterThanMaxQ() {
assertTrue(e.getMessage().contains("maximum reactive power is expected to be greater than or equal to minimum reactive power"));
}

@Test
void shouldCopyDataWhenCreatingReactiveCapabilityCurveFromTemplate() {
ReactiveCapabilityCurve copiedCurve = generator.newReactiveCapabilityCurve()
.beginPoint()
.setP(1)
.setMinQ(5)
.setMaxQ(50)
.endPoint()
.beginPoint()
.setP(2)
.setMinQ(7)
.setMaxQ(70)
.endPoint()
.add();
Generator anotherGenerator = generator.getNetwork().getGenerator("CC");

anotherGenerator.newReactiveCapabilityCurve(copiedCurve)
.add();

copiedCurve.getPoints().forEach(copiedPoint -> {
Optional<ReactiveCapabilityCurve.Point> pastedPoint = anotherGenerator.getReactiveLimits(ReactiveCapabilityCurve.class).getPoints().stream()
.filter(point -> point.getP() == copiedPoint.getP())
.findFirst();
assertTrue(pastedPoint.isPresent());
assertEquals(copiedPoint.getMinQ(), pastedPoint.get().getMinQ());
assertEquals(copiedPoint.getMaxQ(), pastedPoint.get().getMaxQ());
});

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
/**
* Copyright (c) 2024, 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/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.iidm.network.tck;

import com.powsybl.iidm.network.*;
import org.junit.jupiter.api.Test;

import static com.powsybl.iidm.network.PhaseTapChanger.RegulationMode.FIXED_TAP;
import static com.powsybl.iidm.network.RatioTapChanger.RegulationMode.VOLTAGE;
import static com.powsybl.iidm.network.TopologyKind.BUS_BREAKER;
import static com.powsybl.iidm.network.TwoSides.ONE;
import static org.junit.jupiter.api.Assertions.assertEquals;

/**
* @author Benoît Chiquet {@literal <benoit.chiquet at rte-france.com>}
*/
public abstract class AbstractTapChangerHolderTest {

@Test
void shouldReuseCopiedPhaseTapChangerPropertiesFixedTapExample() {
Network network = exampleNetwork();
PhaseTapChanger existingPhaseTapChanger = network.getTwoWindingsTransformer("transformer")
.newPhaseTapChanger()
.setTapPosition(1)
.setRegulationValue(12)
.setRegulationMode(FIXED_TAP)
.setLowTapPosition(0)
.setRegulating(false)
.setTargetDeadband(3)
.beginStep().setAlpha(1).setRho(2).setR(3).setG(4).setB(5).setX(6)
.endStep()
.beginStep().setAlpha(2).setRho(3).setR(4).setG(5).setB(6).setX(7)
.endStep()
.beginStep().setAlpha(3).setRho(4).setR(5).setG(6).setB(7).setX(8)
.endStep()
.add();

PhaseTapChanger newPhaseTapChanger = network.getTwoWindingsTransformer("transformer2")
.newPhaseTapChanger(existingPhaseTapChanger)
.add();

assertEquals(existingPhaseTapChanger.getTapPosition(), newPhaseTapChanger.getTapPosition());
assertEquals(existingPhaseTapChanger.getLowTapPosition(), newPhaseTapChanger.getLowTapPosition());
assertEquals(existingPhaseTapChanger.getRegulationValue(), newPhaseTapChanger.getRegulationValue());
assertEquals(existingPhaseTapChanger.getRegulationMode(), newPhaseTapChanger.getRegulationMode());
assertEquals(existingPhaseTapChanger.isRegulating(), newPhaseTapChanger.isRegulating());
assertEquals(existingPhaseTapChanger.getTargetDeadband(), newPhaseTapChanger.getTargetDeadband());

newPhaseTapChanger.getAllSteps().forEach((tap, newStep) -> {
PhaseTapChangerStep existingStep = existingPhaseTapChanger.getStep(tap);
assertEquals(existingStep.getAlpha(), newStep.getAlpha());
assertEquals(existingStep.getRho(), newStep.getRho());
assertEquals(existingStep.getR(), newStep.getR());
assertEquals(existingStep.getG(), newStep.getG());
assertEquals(existingStep.getB(), newStep.getB());
assertEquals(existingStep.getX(), newStep.getX());
});
}

@Test
void shouldReuseCopiedPhaseTapChangerPropertiesActivePowerControlExample() {
Network network = exampleNetwork();
PhaseTapChanger existingPhaseTapChanger = network.getTwoWindingsTransformer("transformer")
.newPhaseTapChanger()
.setTapPosition(1)
.setRegulationValue(12)
.setRegulationMode(PhaseTapChanger.RegulationMode.ACTIVE_POWER_CONTROL)
.setRegulationTerminal(network.getTwoWindingsTransformer("transformer").getTerminal(ONE))
.setLowTapPosition(0)
.setRegulating(false)
.setTargetDeadband(3)
.beginStep().setAlpha(1).setRho(2).setR(3).setG(4).setB(5).setX(6)
.endStep()
.beginStep().setAlpha(2).setRho(3).setR(4).setG(5).setB(6).setX(7)
.endStep()
.beginStep().setAlpha(3).setRho(4).setR(5).setG(6).setB(7).setX(8)
.endStep()
.add();

PhaseTapChanger newPhaseTapChanger = network.getTwoWindingsTransformer("transformer2")
.newPhaseTapChanger(existingPhaseTapChanger)
.add();

assertEquals(existingPhaseTapChanger.getTapPosition(), newPhaseTapChanger.getTapPosition());
assertEquals(existingPhaseTapChanger.getLowTapPosition(), newPhaseTapChanger.getLowTapPosition());
assertEquals(existingPhaseTapChanger.getRegulationValue(), newPhaseTapChanger.getRegulationValue());
assertEquals(existingPhaseTapChanger.getRegulationMode(), newPhaseTapChanger.getRegulationMode());
assertEquals(existingPhaseTapChanger.isRegulating(), newPhaseTapChanger.isRegulating());
assertEquals(existingPhaseTapChanger.getTargetDeadband(), newPhaseTapChanger.getTargetDeadband());
assertEquals(existingPhaseTapChanger.getRegulationTerminal(), newPhaseTapChanger.getRegulationTerminal());

newPhaseTapChanger.getAllSteps().forEach((tap, newStep) -> {
PhaseTapChangerStep existingStep = existingPhaseTapChanger.getStep(tap);
assertEquals(existingStep.getAlpha(), newStep.getAlpha());
assertEquals(existingStep.getRho(), newStep.getRho());
assertEquals(existingStep.getR(), newStep.getR());
assertEquals(existingStep.getG(), newStep.getG());
assertEquals(existingStep.getB(), newStep.getB());
assertEquals(existingStep.getX(), newStep.getX());
});
}

@Test
void shouldReuseCopiedRatioTapChangerProperties() {
Network network = exampleNetwork();
RatioTapChanger existingRatioTapChanger = network.getTwoWindingsTransformer("transformer").newRatioTapChanger()
.setTapPosition(1)
.setTargetV(400)
.setRegulationValue(12)
.setRegulationMode(VOLTAGE)
.setLowTapPosition(0)
.setRegulating(false)
.setLoadTapChangingCapabilities(true)
.setTargetDeadband(3)
.beginStep().setRho(2).setR(3).setG(4).setB(5).setX(6)
.endStep()
.beginStep().setRho(3).setR(4).setG(5).setB(6).setX(7)
.endStep()
.beginStep().setRho(4).setR(5).setG(6).setB(7).setX(8)
.endStep()
.add();

RatioTapChanger newRatioTapChanger = network.getTwoWindingsTransformer("transformer2")
.newRatioTapChanger(existingRatioTapChanger)
.add();

assertEquals(existingRatioTapChanger.getTapPosition(), newRatioTapChanger.getTapPosition());
assertEquals(existingRatioTapChanger.getLowTapPosition(), newRatioTapChanger.getLowTapPosition());
assertEquals(existingRatioTapChanger.getRegulationValue(), newRatioTapChanger.getRegulationValue());
assertEquals(existingRatioTapChanger.getRegulationMode(), newRatioTapChanger.getRegulationMode());
assertEquals(existingRatioTapChanger.isRegulating(), newRatioTapChanger.isRegulating());
assertEquals(existingRatioTapChanger.getTargetDeadband(), newRatioTapChanger.getTargetDeadband());
assertEquals(existingRatioTapChanger.getRegulationTerminal(), newRatioTapChanger.getRegulationTerminal());
assertEquals(existingRatioTapChanger.getTargetV(), newRatioTapChanger.getTargetV());
assertEquals(existingRatioTapChanger.hasLoadTapChangingCapabilities(), newRatioTapChanger.hasLoadTapChangingCapabilities());

newRatioTapChanger.getAllSteps().forEach((tap, newStep) -> {
RatioTapChangerStep existingStep = existingRatioTapChanger.getStep(tap);
assertEquals(existingStep.getRho(), newStep.getRho());
assertEquals(existingStep.getR(), newStep.getR());
assertEquals(existingStep.getG(), newStep.getG());
assertEquals(existingStep.getB(), newStep.getB());
assertEquals(existingStep.getX(), newStep.getX());
});
}

Network exampleNetwork() {
Network network = Network.create("test", "test");
Substation substation = network.newSubstation()
.setId("substation")
.setCountry(Country.AD)
.add();
VoltageLevel vl1 = substation.newVoltageLevel()
.setId("vl1")
.setTopologyKind(BUS_BREAKER)
.setName("name")
.setNominalV(225)
.setLowVoltageLimit(200)
.setHighVoltageLimit(250)
.add();
vl1.getBusBreakerView().newBus().setId("bus1").add();
VoltageLevel vl2 = substation.newVoltageLevel()
.setId("vl2")
.setTopologyKind(BUS_BREAKER)
.setName("name")
.setNominalV(90)
.setLowVoltageLimit(80)
.setHighVoltageLimit(100)
.add();
vl2.getBusBreakerView().newBus().setId("bus2").add();

substation.newTwoWindingsTransformer()
.setId("transformer")
.setR(17)
.setX(10)
.setBus1("bus1")
.setBus2("bus2")
.add();

substation.newTwoWindingsTransformer()
.setId("transformer2")
.setR(12)
.setX(15)
.setBus1("bus1")
.setBus2("bus2")
.add();

return network;
}
}

0 comments on commit 94abfaa

Please sign in to comment.