Skip to content

Commit 977754d

Browse files
marifunfrolnico
andauthored
Generator, load and losses post processing (#192)
* [IMG-2474] Branch postprocessing refactoring Signed-off-by: marifunf <[email protected]> * [IMG-2474] Generator postprocessing refactoring Signed-off-by: marifunf <[email protected]> * [IMG-2474] Load postprocessing refactoring Signed-off-by: marifunf <[email protected]> * [IMG-2474] Losses postprocessing refactoring Signed-off-by: marifunf <[email protected]> * [IMG-2474] Curative results sum computation Signed-off-by: marifunf <[email protected]> * GeneratorPostProcessingPrefixContainer is now a record Signed-off-by: Nicolas Rol <[email protected]> * refacto imports Signed-off-by: Nicolas Rol <[email protected]> * convert BranchPostProcessingPrefixContainer to record Signed-off-by: Nicolas Rol <[email protected]> * remove duplicated code Signed-off-by: Nicolas Rol <[email protected]> * add spaces Signed-off-by: Nicolas Rol <[email protected]> * add spaces and fix imports Signed-off-by: Nicolas Rol <[email protected]> * remove exception not thrown Signed-off-by: Nicolas Rol <[email protected]> * [IMG-2474] abs corrections Signed-off-by: marifunf <[email protected]> * [IMG-2474] abs test corrections Signed-off-by: marifunf <[email protected]> * [IMG-2474] add some doc Signed-off-by: marifunf <[email protected]> * [IMG-2474] add test on losses Signed-off-by: marifunf <[email protected]> --------- Signed-off-by: marifunf <[email protected]> Signed-off-by: Nicolas Rol <[email protected]> Co-authored-by: Nicolas Rol <[email protected]>
1 parent 9e00ea2 commit 977754d

15 files changed

+1104
-276
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright (c) 2023, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
* SPDX-License-Identifier: MPL-2.0
7+
*/
8+
package com.powsybl.metrix.integration;
9+
10+
import java.util.List;
11+
12+
/**
13+
* @author Marianne Funfrock {@literal <marianne.funfrock at rte-france.com>}
14+
*/
15+
public record BranchPostProcessingPrefixContainer(String postProcessingType, String loadPrefix, String overloadPrefix,
16+
String overallOverloadPrefix, String maxThreatPrefix) {
17+
18+
public List<String> postProcessingPrefixList() {
19+
return List.of(loadPrefix, overloadPrefix, overallOverloadPrefix);
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright (c) 2023, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
* SPDX-License-Identifier: MPL-2.0
7+
*/
8+
package com.powsybl.metrix.integration;
9+
10+
/**
11+
* @author Marianne Funfrock {@literal <marianne.funfrock at rte-france.com>}
12+
*/
13+
public record GeneratorPostProcessingPrefixContainer(String postProcessingType, String redispatchingUpPrefix,
14+
String redispatchingUpCostPrefix, String redispatchingDownPrefix,
15+
String redispatchingDownCostPrefix, String redispatchingPrefix,
16+
String redispatchingCostPrefix) {
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* Copyright (c) 2023, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
* SPDX-License-Identifier: MPL-2.0
7+
*/
8+
package com.powsybl.metrix.integration;
9+
10+
import com.powsybl.metrix.integration.dataGenerator.MetrixOutputData;
11+
import com.powsybl.metrix.mapping.MappingKey;
12+
import com.powsybl.metrix.mapping.TimeSeriesMappingConfig;
13+
import com.powsybl.timeseries.ast.BinaryOperation;
14+
import com.powsybl.timeseries.ast.FloatNodeCalc;
15+
import com.powsybl.timeseries.ast.IntegerNodeCalc;
16+
import com.powsybl.timeseries.ast.NodeCalc;
17+
import com.powsybl.timeseries.ast.TimeSeriesNameNodeCalc;
18+
import com.powsybl.timeseries.ast.UnaryOperation;
19+
import org.slf4j.Logger;
20+
import org.slf4j.LoggerFactory;
21+
22+
import java.util.HashMap;
23+
import java.util.List;
24+
import java.util.Map;
25+
import java.util.Objects;
26+
import java.util.Set;
27+
28+
import static com.powsybl.metrix.integration.AbstractMetrix.MAX_THREAT_PREFIX;
29+
import static com.powsybl.metrix.integration.MetrixPostProcessingTimeSeries.findIdsToProcess;
30+
31+
/**
32+
* @author Marianne Funfrock {@literal <marianne.funfrock at rte-france.com>}
33+
*/
34+
public final class MetrixBranchPostProcessingTimeSeries {
35+
36+
private static final Logger LOGGER = LoggerFactory.getLogger(MetrixBranchPostProcessingTimeSeries.class);
37+
38+
public static final String BASECASE_LOAD_PREFIX = "basecaseLoad_";
39+
public static final String BASECASE_OVERLOAD_PREFIX = "basecaseOverload_";
40+
public static final BranchPostProcessingPrefixContainer OUTAGE_PREFIX_CONTAINER = new BranchPostProcessingPrefixContainer("Outage", "outageLoad_", "outageOverload_", "overallOverload_", MAX_THREAT_PREFIX);
41+
public static final BranchPostProcessingPrefixContainer ITAM_PREFIX_CONTAINER = new BranchPostProcessingPrefixContainer("ITAM", "itamLoad_", "itamOverload_", "overallItamOverload_", MetrixOutputData.MAX_TMP_THREAT_FLOW);
42+
43+
private final MetrixDslData metrixDslData;
44+
private final TimeSeriesMappingConfig mappingConfig;
45+
private final Set<String> allTimeSeriesNames;
46+
private final String nullableSchemaName;
47+
Map<String, NodeCalc> calculatedTimeSeries;
48+
49+
private final Map<String, NodeCalc> postProcessingTimeSeries = new HashMap<>();
50+
51+
public MetrixBranchPostProcessingTimeSeries(MetrixDslData metrixDslData,
52+
TimeSeriesMappingConfig mappingConfig,
53+
Set<String> allTimeSeriesNames,
54+
String nullableSchemaName) {
55+
this.metrixDslData = metrixDslData;
56+
this.mappingConfig = mappingConfig;
57+
this.allTimeSeriesNames = allTimeSeriesNames;
58+
this.nullableSchemaName = nullableSchemaName;
59+
this.calculatedTimeSeries = new HashMap<>(mappingConfig.getTimeSeriesNodes());
60+
}
61+
62+
public Map<String, NodeCalc> createPostProcessingTimeSeries() {
63+
createBaseCasePostProcessingTimeSeries();
64+
createOutagePostProcessingTimeSeries();
65+
createItamPostProcessingTimeSeries();
66+
return postProcessingTimeSeries;
67+
}
68+
69+
private static NodeCalc createLoadTimeSeries(NodeCalc flowTimeSeries, NodeCalc ratingTimeSeries) {
70+
return BinaryOperation.multiply(BinaryOperation.div(flowTimeSeries, ratingTimeSeries), new FloatNodeCalc(100));
71+
}
72+
73+
private static NodeCalc createLoadTimeSeries(NodeCalc flowTimeSeries, NodeCalc ratingTimeSeriesOrEx, NodeCalc ratingTimeSeriesExOr) {
74+
if (ratingTimeSeriesOrEx == ratingTimeSeriesExOr) {
75+
return createLoadTimeSeries(flowTimeSeries, ratingTimeSeriesOrEx);
76+
} else {
77+
NodeCalc zero = new IntegerNodeCalc(0);
78+
NodeCalc ratingTimeSeries = BinaryOperation.plus(BinaryOperation.multiply(BinaryOperation.greaterThan(flowTimeSeries, zero), ratingTimeSeriesOrEx),
79+
BinaryOperation.multiply(BinaryOperation.lessThan(flowTimeSeries, zero), ratingTimeSeriesExOr));
80+
return createLoadTimeSeries(flowTimeSeries, ratingTimeSeries);
81+
}
82+
}
83+
84+
private static NodeCalc createOverloadTimeSeries(NodeCalc flowTimeSeries, NodeCalc ratingTimeSeriesOrEx, NodeCalc ratingTimeSeriesExOr) {
85+
NodeCalc positiveOverloadTimeSeries = BinaryOperation.minus(flowTimeSeries, ratingTimeSeriesOrEx);
86+
NodeCalc negativeRatingTimeSeries = UnaryOperation.negative(ratingTimeSeriesExOr);
87+
NodeCalc negativeOverloadTimeSeries = BinaryOperation.minus(flowTimeSeries, negativeRatingTimeSeries);
88+
return BinaryOperation.plus(BinaryOperation.multiply(BinaryOperation.greaterThan(flowTimeSeries, ratingTimeSeriesOrEx), positiveOverloadTimeSeries),
89+
BinaryOperation.multiply(BinaryOperation.lessThan(flowTimeSeries, negativeRatingTimeSeries), negativeOverloadTimeSeries));
90+
}
91+
92+
private static NodeCalc createOverallOverloadTimeSeries(NodeCalc basecaseOverloadTimeSeries, NodeCalc otherOverloadTimeSeries) {
93+
return BinaryOperation.plus(UnaryOperation.abs(basecaseOverloadTimeSeries), UnaryOperation.abs(otherOverloadTimeSeries));
94+
}
95+
96+
private void createBaseCasePostProcessingTimeSeries() {
97+
List<String> branchIds = findIdsToProcess(metrixDslData.getBranchMonitoringNList(), allTimeSeriesNames, MetrixOutputData.FLOW_NAME);
98+
for (String branch : branchIds) {
99+
MetrixVariable threshold = metrixDslData.getBranchMonitoringStatisticsThresholdN(branch);
100+
if (mappingConfig.getTimeSeriesName(new MappingKey(threshold, branch)) != null) {
101+
MetrixVariable thresholdEndOr = threshold == MetrixVariable.THRESHOLD_N ? MetrixVariable.THRESHOLD_N_END_OR : MetrixVariable.ANALYSIS_THRESHOLD_N_END_OR;
102+
createBaseCasePostProcessingTimeSeries(branch, threshold, thresholdEndOr);
103+
}
104+
}
105+
}
106+
107+
private void createBaseCasePostProcessingTimeSeries(String branch,
108+
MetrixVariable thresholdN,
109+
MetrixVariable thresholdNEndOr) {
110+
LOGGER.debug("Creating basecase postprocessing time-series for {}", branch);
111+
NodeCalc flowTimeSeries = new TimeSeriesNameNodeCalc(MetrixDataName.getNameWithSchema(MetrixOutputData.FLOW_NAME + branch, nullableSchemaName));
112+
RatingTimeSeriesData ratingTimeSeriesData = new RatingTimeSeriesData(branch, thresholdN, thresholdNEndOr);
113+
114+
// Basecase load
115+
postProcessingTimeSeries.put(MetrixDataName.getNameWithSchema(BASECASE_LOAD_PREFIX + branch, nullableSchemaName), createLoadTimeSeries(flowTimeSeries, ratingTimeSeriesData.ratingTimeSeriesOrEx, ratingTimeSeriesData.ratingTimeSeriesExOr));
116+
// Basecase overload
117+
postProcessingTimeSeries.put(MetrixDataName.getNameWithSchema(BASECASE_OVERLOAD_PREFIX + branch, nullableSchemaName), createOverloadTimeSeries(flowTimeSeries, ratingTimeSeriesData.ratingTimeSeriesOrEx, ratingTimeSeriesData.ratingTimeSeriesExOr));
118+
}
119+
120+
private void createOutagePostProcessingTimeSeries() {
121+
List<String> branchIds = findIdsToProcess(metrixDslData.getBranchMonitoringNList(), allTimeSeriesNames, OUTAGE_PREFIX_CONTAINER.maxThreatPrefix());
122+
for (String branch : branchIds) {
123+
MetrixVariable threshold = metrixDslData.getBranchMonitoringStatisticsThresholdNk(branch);
124+
if (mappingConfig.getTimeSeriesName(new MappingKey(threshold, branch)) != null) {
125+
MetrixVariable thresholdEndOr = threshold == MetrixVariable.THRESHOLD_N1 ? MetrixVariable.THRESHOLD_N1_END_OR : MetrixVariable.ANALYSIS_THRESHOLD_NK_END_OR;
126+
createPostProcessingTimeSeries(branch, threshold, thresholdEndOr, OUTAGE_PREFIX_CONTAINER);
127+
}
128+
}
129+
}
130+
131+
private void createItamPostProcessingTimeSeries() {
132+
List<String> branchIds = findIdsToProcess(metrixDslData.getBranchMonitoringNList(), allTimeSeriesNames, ITAM_PREFIX_CONTAINER.maxThreatPrefix());
133+
for (String branch : branchIds) {
134+
MetrixVariable threshold = MetrixVariable.THRESHOLD_ITAM;
135+
if (mappingConfig.getTimeSeriesName(new MappingKey(threshold, branch)) != null) {
136+
MetrixVariable thresholdEndOr = MetrixVariable.THRESHOLD_ITAM_END_OR;
137+
createPostProcessingTimeSeries(branch, threshold, thresholdEndOr, ITAM_PREFIX_CONTAINER);
138+
}
139+
}
140+
}
141+
142+
private void createPostProcessingTimeSeries(String branch,
143+
MetrixVariable threshold,
144+
MetrixVariable thresholdEndOr,
145+
BranchPostProcessingPrefixContainer postProcessingPrefixContainer) {
146+
if (LOGGER.isDebugEnabled()) {
147+
LOGGER.debug("Creating {} postprocessing time-series for {}", postProcessingPrefixContainer.postProcessingType(), branch);
148+
}
149+
NodeCalc flowTimeSeries = new TimeSeriesNameNodeCalc(MetrixDataName.getNameWithSchema(postProcessingPrefixContainer.maxThreatPrefix() + branch, nullableSchemaName));
150+
RatingTimeSeriesData ratingTimeSeriesData = new RatingTimeSeriesData(branch, threshold, thresholdEndOr);
151+
152+
// load
153+
postProcessingTimeSeries.put(MetrixDataName.getNameWithSchema(postProcessingPrefixContainer.loadPrefix() + branch, nullableSchemaName), createLoadTimeSeries(flowTimeSeries, ratingTimeSeriesData.ratingTimeSeriesOrEx, ratingTimeSeriesData.ratingTimeSeriesExOr));
154+
// overload
155+
NodeCalc overloadTimeSeries = createOverloadTimeSeries(flowTimeSeries, ratingTimeSeriesData.ratingTimeSeriesOrEx, ratingTimeSeriesData.ratingTimeSeriesExOr);
156+
postProcessingTimeSeries.put(MetrixDataName.getNameWithSchema(postProcessingPrefixContainer.overloadPrefix() + branch, nullableSchemaName), overloadTimeSeries);
157+
NodeCalc basecaseOverLoadTimeSeries = postProcessingTimeSeries.get(BASECASE_OVERLOAD_PREFIX + branch);
158+
if (!Objects.isNull(basecaseOverLoadTimeSeries)) {
159+
postProcessingTimeSeries.put(MetrixDataName.getNameWithSchema(postProcessingPrefixContainer.overallOverloadPrefix() + branch, nullableSchemaName), createOverallOverloadTimeSeries(basecaseOverLoadTimeSeries, overloadTimeSeries));
160+
}
161+
}
162+
163+
private class RatingTimeSeriesData {
164+
protected String ratingTimeSeriesName;
165+
protected NodeCalc ratingTimeSeriesOrEx;
166+
protected NodeCalc ratingTimeSeriesExOr;
167+
168+
protected RatingTimeSeriesData(String branch,
169+
MetrixVariable threshold,
170+
MetrixVariable thresholdEndOr) {
171+
ratingTimeSeriesName = mappingConfig.getTimeSeriesName(new MappingKey(threshold, branch));
172+
ratingTimeSeriesOrEx = calculatedTimeSeries.computeIfAbsent(ratingTimeSeriesName, TimeSeriesNameNodeCalc::new);
173+
ratingTimeSeriesExOr = ratingTimeSeriesOrEx;
174+
if (thresholdEndOr != null) {
175+
ratingTimeSeriesName = mappingConfig.getTimeSeriesName(new MappingKey(thresholdEndOr, branch));
176+
if (ratingTimeSeriesName != null) {
177+
ratingTimeSeriesExOr = calculatedTimeSeries.computeIfAbsent(ratingTimeSeriesName, TimeSeriesNameNodeCalc::new);
178+
}
179+
}
180+
}
181+
}
182+
}

0 commit comments

Comments
 (0)