Skip to content

Commit

Permalink
Swe cne threshold decimals (#1245)
Browse files Browse the repository at this point in the history
* add decimals for thrsholds in swe cne

Signed-off-by: Philippe Edwards <philippe.edwards@rte-france.com>

* include link fixes in documentation

Signed-off-by: Philippe Edwards <philippe.edwards@rte-france.com>

* make constants final

Signed-off-by: Philippe Edwards <philippe.edwards@rte-france.com>

---------

Signed-off-by: Philippe Edwards <philippe.edwards@rte-france.com>
  • Loading branch information
phiedw authored Dec 19, 2024
1 parent 8663132 commit 02bf7ff
Show file tree
Hide file tree
Showing 17 changed files with 489 additions and 125 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

import static com.powsybl.openrao.commons.MeasurementRounding.roundValueBasedOnMargin;
import static com.powsybl.openrao.commons.logs.OpenRaoLoggerProvider.BUSINESS_WARNS;
import static com.powsybl.openrao.data.raoresult.io.cne.swe.SweCneUtil.DEFAULT_DECIMALS_FOR_ROUNDING;
import static com.powsybl.openrao.data.raoresult.io.cne.swe.SweCneUtil.DEFAULT_DECIMALS_FOR_ROUNDING_ANGLES;

/**
* Generates AdditionalConstraintSeries for SWE CNE format
Expand Down Expand Up @@ -93,6 +93,6 @@ static BigDecimal roundAngleValue(AngleCnec angleCnec, Crac crac, RaoResult raoR
double marginOnLowerBound = angle - angleCnec.getLowerBound(Unit.DEGREE).orElse(Double.NEGATIVE_INFINITY);
double marginOnUpperBound = angleCnec.getUpperBound(Unit.DEGREE).orElse(Double.POSITIVE_INFINITY) - angle;
double margin = Math.min(marginOnLowerBound, marginOnUpperBound);
return roundValueBasedOnMargin(angle, margin, DEFAULT_DECIMALS_FOR_ROUNDING);
return roundValueBasedOnMargin(angle, margin, DEFAULT_DECIMALS_FOR_ROUNDING_ANGLES);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ public final class SweCneUtil {
private SweCneUtil() {
}

public static int DEFAULT_DECIMALS_FOR_ROUNDING = 1;
public static final int DEFAULT_DECIMALS_FOR_ROUNDING_ANGLES = 1;
public static final int DEFAULT_DECIMALS_FOR_ROUNDING_FLOWS = 1;
public static final int DEFAULT_DECIMALS_FOR_ROUNDING_THRESHOLDS = 0;
public static final String SWE_CNE_EXPORT_PROPERTIES_PREFIX = "rao-result.export.swe-cne.";

// Creation of time interval
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
import com.powsybl.openrao.data.raoresult.io.cne.swe.xsd.Analog;
import com.powsybl.openrao.data.raoresult.io.cne.swe.xsd.MonitoredRegisteredResource;
import com.powsybl.openrao.data.raoresult.io.cne.swe.xsd.MonitoredSeries;
import org.apache.commons.lang3.tuple.Pair;

import java.util.*;

import static com.powsybl.openrao.commons.MeasurementRounding.roundValueBasedOnMargin;
import static com.powsybl.openrao.data.raoresult.io.cne.commons.CneConstants.*;
import static com.powsybl.openrao.data.raoresult.io.cne.swe.SweCneUtil.DEFAULT_DECIMALS_FOR_ROUNDING;
import static com.powsybl.openrao.data.raoresult.io.cne.swe.SweCneUtil.DEFAULT_DECIMALS_FOR_ROUNDING_FLOWS;
import static com.powsybl.openrao.data.raoresult.io.cne.swe.SweCneUtil.DEFAULT_DECIMALS_FOR_ROUNDING_THRESHOLDS;

/**
* Generates MonitoredSeries for SWE CNE format
Expand Down Expand Up @@ -84,49 +86,56 @@ public List<MonitoredSeries> generateMonitoredSeries(Contingency contingency) {
return monitoredSeriesList;
}

private double getCnecFlowClosestToThreshold(Instant optimizedInstant, FlowCnec cnec) {
private Pair<Double, Double> getCnecLimitingFlowAndThreshold(Instant optimizedInstant, FlowCnec cnec) {
double flow = 0.0;
double threshold = 0.0;
double margin = Double.POSITIVE_INFINITY;
for (TwoSides side : cnec.getMonitoredSides()) {
double flowOnSide = sweCneHelper.getRaoResult().getFlow(optimizedInstant, cnec, side, Unit.AMPERE);
if (Double.isNaN(flowOnSide)) {
continue;
}
double marginOnSide = cnec.computeMargin(flowOnSide, side, Unit.AMPERE);
if (marginOnSide < margin) {
margin = marginOnSide;
double marginOnLowerBound = flowOnSide - cnec.getLowerBound(side, Unit.AMPERE).orElse(Double.NEGATIVE_INFINITY);
if (marginOnLowerBound < margin) {
margin = marginOnLowerBound;
flow = flowOnSide;
threshold = cnec.getLowerBound(side, Unit.AMPERE).orElse(Double.NEGATIVE_INFINITY);
}
double marginOnUpperBound = cnec.getUpperBound(side, Unit.AMPERE).orElse(Double.POSITIVE_INFINITY) - flowOnSide;
if (marginOnUpperBound < margin) {
margin = marginOnUpperBound;
flow = flowOnSide;
threshold = cnec.getUpperBound(side, Unit.AMPERE).orElse(Double.POSITIVE_INFINITY);
}
}
return roundValueBasedOnMargin(flow, margin, DEFAULT_DECIMALS_FOR_ROUNDING).doubleValue();
return Pair.of(
roundValueBasedOnMargin(flow, margin, DEFAULT_DECIMALS_FOR_ROUNDING_FLOWS).doubleValue(),
roundValueBasedOnMargin(threshold, margin, DEFAULT_DECIMALS_FOR_ROUNDING_THRESHOLDS).doubleValue()
);
}

private List<MonitoredSeries> generateMonitoredSeries(MonitoredSeriesCreationContext monitoredSeriesCreationContext, Set<CnecCreationContext> cnecCreationContexts, boolean includeMeasurements) {
Crac crac = sweCneHelper.getCrac();
Map<Double, MonitoredSeries> monitoredSeriesPerFlowValue = new LinkedHashMap<>();
cnecCreationContexts.forEach(cnecCreationContext -> {
FlowCnec cnec = crac.getFlowCnec(cnecCreationContext.getCreatedCnecId());
double flow = getCnecFlowClosestToThreshold(cnec.getState().getInstant(), cnec);
if (monitoredSeriesPerFlowValue.containsKey(flow) && includeMeasurements) {
mergeSeries(monitoredSeriesPerFlowValue.get(flow), cnec);
} else if (!monitoredSeriesPerFlowValue.containsKey(flow)) {
monitoredSeriesPerFlowValue.put(flow, generateMonitoredSeriesFromScratch(monitoredSeriesCreationContext, cnec, includeMeasurements));
Pair<Double, Double> flowAndThreshold = getCnecLimitingFlowAndThreshold(cnec.getState().getInstant(), cnec);
double flowValue = flowAndThreshold.getLeft();
if (monitoredSeriesPerFlowValue.containsKey(flowValue) && includeMeasurements) {
mergeSeries(monitoredSeriesPerFlowValue.get(flowValue), cnec, flowAndThreshold.getRight());
} else if (!monitoredSeriesPerFlowValue.containsKey(flowValue)) {
monitoredSeriesPerFlowValue.put(flowValue, generateMonitoredSeriesFromScratch(monitoredSeriesCreationContext, cnec, includeMeasurements));
}
});
return new ArrayList<>(monitoredSeriesPerFlowValue.values());
}

private void mergeSeries(MonitoredSeries monitoredSeries, FlowCnec cnec) {
private void mergeSeries(MonitoredSeries monitoredSeries, FlowCnec cnec, double thresholdValue) {
Analog threshold = new Analog();
threshold.setMeasurementType(getThresholdMeasurementType(cnec));
threshold.setUnitSymbol(AMP_UNIT_SYMBOL);
TwoSides side = cnec.getMonitoredSides().contains(TwoSides.ONE) ? TwoSides.ONE : cnec.getMonitoredSides().iterator().next();
float roundedThreshold = Math.round(Math.min(
Math.abs(cnec.getLowerBound(side, Unit.AMPERE).orElse(Double.POSITIVE_INFINITY)),
Math.abs(cnec.getUpperBound(side, Unit.AMPERE).orElse(Double.NEGATIVE_INFINITY))));
threshold.setPositiveFlowIn(getCnecFlowClosestToThreshold(cnec.getState().getInstant(), cnec) >= 0 ?
DIRECT_POSITIVE_FLOW_IN : OPPOSITE_POSITIVE_FLOW_IN);
threshold.setAnalogValuesValue(Math.abs(roundedThreshold));
threshold.setPositiveFlowIn(thresholdValue >= 0 ? DIRECT_POSITIVE_FLOW_IN : OPPOSITE_POSITIVE_FLOW_IN);
threshold.setAnalogValuesValue((float) Math.abs(thresholdValue));

monitoredSeries.getRegisteredResource().get(0).getMeasurements().add(threshold);
}
Expand All @@ -141,23 +150,22 @@ private MonitoredSeries generateMonitoredSeriesFromScratch(MonitoredSeriesCreati
setInOutAggregateNodes(cnec.getNetworkElement().getId(), monitoredSeriesCreationContext.getNativeId(), registeredResource);

if (includeMeasurements) {
Pair<Double, Double> flowAndThreshold = getCnecLimitingFlowAndThreshold(cnec.getState().getInstant(), cnec);

Analog flow = new Analog();
flow.setMeasurementType(FLOW_MEASUREMENT_TYPE);
flow.setUnitSymbol(AMP_UNIT_SYMBOL);
double flowValue = getCnecFlowClosestToThreshold(cnec.getState().getInstant(), cnec);
double flowValue = flowAndThreshold.getLeft();
flow.setPositiveFlowIn(flowValue >= 0 ? DIRECT_POSITIVE_FLOW_IN : OPPOSITE_POSITIVE_FLOW_IN);
flow.setAnalogValuesValue((float) Math.abs(flowValue));
registeredResource.getMeasurements().add(flow);

Analog threshold = new Analog();
threshold.setMeasurementType(getThresholdMeasurementType(cnec));
threshold.setUnitSymbol(AMP_UNIT_SYMBOL);
TwoSides side = cnec.getMonitoredSides().contains(TwoSides.ONE) ? TwoSides.ONE : cnec.getMonitoredSides().iterator().next();
float roundedThreshold = Math.round(Math.min(
Math.abs(cnec.getLowerBound(side, Unit.AMPERE).orElse(Double.POSITIVE_INFINITY)),
Math.abs(cnec.getUpperBound(side, Unit.AMPERE).orElse(Double.NEGATIVE_INFINITY))));
threshold.setPositiveFlowIn(flowValue >= 0 ? DIRECT_POSITIVE_FLOW_IN : OPPOSITE_POSITIVE_FLOW_IN);
threshold.setAnalogValuesValue(Math.abs(roundedThreshold));
double thresholdValue = flowAndThreshold.getRight();
threshold.setPositiveFlowIn(thresholdValue >= 0 ? DIRECT_POSITIVE_FLOW_IN : OPPOSITE_POSITIVE_FLOW_IN);
threshold.setAnalogValuesValue((float) Math.abs(thresholdValue));
registeredResource.getMeasurements().add(threshold);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@
<jxb:javaType name="java.lang.Float"
xmlType="xs:float"
parseMethod="jakarta.xml.bind.DatatypeConverter.parseFloat"
printMethod="com.powsybl.openrao.data.raoresult.io.cne.commons.xmlformatter.NumberFormatter.printFloat" />
printMethod="jakarta.xml.bind.DatatypeConverter.printFloat" />
</jxb:globalBindings>
</jxb:bindings>
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ private void setCnecResult(MonitoredSeriesCreationContext mscc, Instant instant,
Mockito.when(flowCnec.getMonitoredSides()).thenReturn(Set.of(TwoSides.ONE, TwoSides.TWO));
Mockito.when(raoResult.getFlow(instant, flowCnec, TwoSides.ONE, Unit.AMPERE)).thenReturn(flow);
Mockito.when(raoResult.getFlow(instant, flowCnec, TwoSides.TWO, Unit.AMPERE)).thenReturn(flow + 10);
Mockito.when(flowCnec.getUpperBound(TwoSides.ONE, Unit.AMPERE)).thenReturn(Optional.of(1000.));
Mockito.when(flowCnec.getUpperBound(TwoSides.TWO, Unit.AMPERE)).thenReturn(Optional.of(1100.));
Mockito.when(flowCnec.computeMargin(flow, TwoSides.ONE, Unit.AMPERE)).thenReturn(1000 - flow);
Mockito.when(flowCnec.computeMargin(flow, TwoSides.TWO, Unit.AMPERE)).thenReturn(1100 - flow);
}
Expand Down
Loading

0 comments on commit 02bf7ff

Please sign in to comment.