Skip to content

Commit

Permalink
Implement getMinQ and getMaxQ for reactive capability curve with extr…
Browse files Browse the repository at this point in the history
…apolation of reactive limit slope

Signed-off-by: PRABAKARAN Sylvestre <[email protected]>
  • Loading branch information
SylvestreSakti committed Dec 10, 2024
1 parent be489a8 commit 1e04177
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,15 @@ public interface Point {
*/
double getMaxP();

/**
* Get the reactive power minimum value of the curve (with the possibility of extrapolating slope of reactive
* limits outside active limits)
*/
double getMinQ(double p, boolean extrapolateReactiveLimitSlope);

/**
* Get the reactive power maximum value of the curve (with the possibility of extrapolating slope of reactive
* limits outside active limits)
*/
double getMaxQ(double p, boolean extrapolateReactiveLimitSlope);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import java.util.TreeMap;

/**
*
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
class ReactiveCapabilityCurveImpl implements ReactiveCapabilityCurve {
Expand Down Expand Up @@ -135,4 +134,58 @@ public double getMaxQ(double p) {
}
}
}

@Override
public double getMinQ(double p, boolean extrapolateReactiveLimitSlope) {
if (points.size() < 2) {
throw new IllegalStateException("points size should be >= 2");
}
if (!extrapolateReactiveLimitSlope || p >= points.firstKey() && p <= points.lastKey()) {
return getMinQ(p);
}
Map.Entry<Double, Point> e1 = points.floorEntry(p);
Map.Entry<Double, Point> e2 = points.ceilingEntry(p);
if (e1 == null && e2 != null) {
// Extrapolate min reactive limit slope below min active power limit p2
Point p2 = e2.getValue();
Point p2bis = points.higherEntry(e2.getKey()).getValue(); // p < p2 < p2bis
double slope = (p2bis.getMinQ() - p2.getMinQ()) / (p2bis.getP() - p2.getP());
return p2.getMinQ() + slope * (p - p2.getP());
} else if (e1 != null && e2 == null) {
// Extrapolate min reactive limit slope above max active power limit p1
Point p1 = e1.getValue();
Point p1bis = points.lowerEntry(e1.getKey()).getValue(); // p1bis < p1 < p
double slope = (p1.getMinQ() - p1bis.getMinQ()) / (p1.getP() - p1bis.getP());
return p1.getMinQ() + slope * (p - p1.getP());
} else {
throw new IllegalStateException();
}
}

@Override
public double getMaxQ(double p, boolean extrapolateReactiveLimitSlope) {
if (points.size() < 2) {
throw new IllegalStateException("points size should be >= 2");
}
if (!extrapolateReactiveLimitSlope || p >= points.firstKey() && p <= points.lastKey()) {
return getMaxQ(p);
}
Map.Entry<Double, Point> e1 = points.floorEntry(p);
Map.Entry<Double, Point> e2 = points.ceilingEntry(p);
if (e1 == null && e2 != null) {
// Extrapolate max reactive limit slope below min active power limit p2
Point p2 = e2.getValue();
Point p2bis = points.higherEntry(e2.getKey()).getValue(); // p < p2 < p2bis
double slope = (p2bis.getMaxQ() - p2.getMaxQ()) / (p2bis.getP() - p2.getP());
return p2.getMaxQ() + slope * (p - p2.getP());
} else if (e1 != null && e2 == null) {
// Extrapolate max reactive limit slope above max active power limit p1
Point p1 = e1.getValue();
Point p1bis = points.lowerEntry(e1.getKey()).getValue(); // p1bis < p1 < p
double slope = (p1.getMaxQ() - p1bis.getMaxQ()) / (p1.getP() - p1bis.getP());
return p1.getMaxQ() + slope * (p - p1.getP());
} else {
throw new IllegalStateException();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ private ReactiveCapabilityCurveImpl createCurve(Point... points) {
}

@Test
void testInterpolation() {
void testReactiveCapabilityCurve() {
ReactiveCapabilityCurveImpl curve = createCurve(new PointImpl(100.0, 200.0, 300.0),
new PointImpl(200.0, 300.0, 400.0));
// bounds test
Expand All @@ -51,4 +51,34 @@ void testInterpolation() {
assertEquals(400.0, curve.getMaxQ(1000.0), 0.0);
}

private void testReactiveCapabilityCurveWithReactiveLimitsExtrapolation(boolean extrapolate) {
ReactiveCapabilityCurveImpl curve = createCurve(new PointImpl(100.0, 200.0, 300.0),
new PointImpl(200.0, 300.0, 400.0),
new PointImpl(300.0, 300.0, 400.0),
new PointImpl(400.0, 100.0, 500.0));
// bounds test
assertEquals(200.0, curve.getMinQ(100.0, extrapolate), 0.0);
assertEquals(300.0, curve.getMaxQ(100.0, extrapolate), 0.0);
assertEquals(300.0, curve.getMinQ(200.0, extrapolate), 0.0);
assertEquals(400.0, curve.getMaxQ(200.0, extrapolate), 0.0);

// interpolation test
assertEquals(250.0, curve.getMinQ(150.0, extrapolate), 0.0);
assertEquals(350.0, curve.getMaxQ(150.0, extrapolate), 0.0);
assertEquals(210.0, curve.getMinQ(110.0, extrapolate), 0.0);
assertEquals(310.0, curve.getMaxQ(110.0, extrapolate), 0.0);

// out of bounds test
assertEquals(extrapolate ? 100.0 : 200.0, curve.getMinQ(0.0, extrapolate), 0.0);
assertEquals(extrapolate ? 200.0 : 300.0, curve.getMaxQ(0.0, extrapolate), 0.0);
assertEquals(extrapolate ? -100.0 : 100.0, curve.getMinQ(500.0, extrapolate), 0.0);
assertEquals(extrapolate ? 600.0 : 500.0, curve.getMaxQ(500.0, extrapolate), 0.0);
}

@Test
void testReactiveCapabilityCurveWithReactiveLimitsExtrapolation() {
testReactiveCapabilityCurveWithReactiveLimitsExtrapolation(false);
testReactiveCapabilityCurveWithReactiveLimitsExtrapolation(true);
}

}

0 comments on commit 1e04177

Please sign in to comment.