Skip to content

Commit

Permalink
Create rescale mode for flow decomposition (#146)
Browse files Browse the repository at this point in the history
* Replaced rescaleEnabled with rescaleMode
* Created interface and implementations for DecomposedFlowRescaler
* Create builder for DecomposedFlow

Signed-off-by: Caio Luke <[email protected]>
  • Loading branch information
caioluke authored May 31, 2024
1 parent 6ee7f9b commit 470388e
Show file tree
Hide file tree
Showing 28 changed files with 594 additions and 199 deletions.
12 changes: 11 additions & 1 deletion docs/flow_decomposition/algorithm-description.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,15 @@ calculated by the DC power flow.
However, the flow reference is the one calculated using AC power flow which is different. The final step of the algorithm
is though to rescale the different flow parts in order to ensure that the sum of the parts is equal to the initially calculated AC flow.

By default, no rescaling to the AC flow is done on the flow decomposition results.

Available rescaling modes are defined here below.

#### ACER methodology-based rescaling
The difference between reference AC flow and the sum of the parts of the decomposition is redispatched on the different
parts proportionally to their rectified linear unit ($\mathrm{ReLU}(x) = \mathrm{max}(x, 0)$).
parts proportionally to their rectified linear unit ($\mathrm{ReLU}(x) = \mathrm{max}(x, 0)$).

#### Proportional rescaling
Each flow is rescaled with a proportional coefficient. The coefficient is defined by $$\alpha_{\text{rescale}} = \frac{max(|AC p1|, |AC p2|)}{|DC p1|}$$.
In this way, the DC flow will have the same magnitude as the AC flow.
Since we divide by the DC flow to calculate the coefficient, lines with a too small DC flow are not rescaled.
17 changes: 9 additions & 8 deletions docs/flow_decomposition/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

## Dedicated parameters

| Name | Type | Default value | Description |
|-----------------------------------------|---------|---------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| enable-losses-compensation | boolean | false | When set to true, adds losses compensation step of the algorithm. Otherwise, all losses will be compensated using chosen power flow compensation strategy. |
| losses-compensation-epsilon | double | 1e-5 | Threshold used in losses compensation step of the algorihm. If actual losses are below the given threshold on a branch, no injection is created in the network to compensate these losses. Used to avoid creating too many injections in the network. May have an impact in overall algorithm performance and memory usage. |
| sensitivity-epsilon | double | 1e-5 | Threshold used when filling PTDF and PSDF matrices. If a sensitivity is below the given threshold, it is set to zero. Used to keep sparse matrices in the algorithm. May have an impact in overall algorithm performance and memory usage. |
| rescale-enabled | boolean | false | When set to true, rescaling step is done to ensure that the sum of all flow parts is equal to the AC reference flow. |
| dc-fallback-enabled-after-ac-divergence | boolean | true | Defines the fallback behavior after an AC divergence Use True to run DC loadflow if an AC loadflow diverges (default). Use False to throw an exception if an AC loadflow diverges. |
| sensitivity-variable-batch-size | int | 15000 | When set to a lower value, this parameter will reduce memory usage, but it might increase computation time |
| Name | Type | Default value | Description |
|-------------------------------------------|---------|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| enable-losses-compensation | boolean | false | When set to true, adds losses compensation step of the algorithm. Otherwise, all losses will be compensated using chosen power flow compensation strategy. |
| losses-compensation-epsilon | double | 1e-5 | Threshold used in losses compensation step of the algorihm. If actual losses are below the given threshold on a branch, no injection is created in the network to compensate these losses. Used to avoid creating too many injections in the network. May have an impact in overall algorithm performance and memory usage. |
| sensitivity-epsilon | double | 1e-5 | Threshold used when filling PTDF and PSDF matrices. If a sensitivity is below the given threshold, it is set to zero. Used to keep sparse matrices in the algorithm. May have an impact in overall algorithm performance and memory usage. |
| rescale-mode | enum | NONE | Use NONE if you don't want to rescale flow decomposition results. Use ACER_METHODOLOGY for the ACER methodology rescaling strategy. Use PROPORTIONAL for a proportional rescaling. See [Flow parts rescaling](../flow_decomposition/algorithm-description.md#flow-parts-rescaling) for more details. |
| proportional-rescaler-min-flow-tolerance | double | 1e-6 | Option only used if rescale-mode is PROPORTIONAL. Defines the minimum DC flow required in MW for the rescaling to happen. |
| dc-fallback-enabled-after-ac-divergence | boolean | true | Defines the fallback behavior after an AC divergence Use True to run DC loadflow if an AC loadflow diverges (default). Use False to throw an exception if an AC loadflow diverges. |
| sensitivity-variable-batch-size | int | 15000 | When set to a lower value, this parameter will reduce memory usage, but it might increase computation time |

## Impact of existing parameters

Expand Down
4 changes: 3 additions & 1 deletion docs/flow_decomposition/flow-decomposition-outputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

For each network element of interest, flow decomposition outputs contain the following elements:
- Reference flow : active power flow that is considered as the reference for the decomposition. It is actually equal
to the sum of all the flow parts calculated by the algorithm.
to the sum of all the flow parts calculated by the algorithm. to the sum of all the flow parts calculated by the algorithm.
Reference AC flows are available on terminal 1 and 2.
- Allocated flow : allocated flow part of the network element's flow.
- Internal flow : internal flow part of the network element's flow. It is calculated as the loop flow from the country
which network element is part of (interconnections are considered as part of no specific country, so will always have an internal flow to 0).
Expand All @@ -16,6 +17,7 @@ For each network element of interest, flow decomposition outputs contain the fol

On one hand, the reference flows are oriented from side 1 to side 2 of the associated IIDM branch. A positive reference flow implies
a flow from side 1 to side 2, while a negative one means a flow from side 2 to side 1.
For coherence and simplicity purposes, the entire algorithm (except [proportional rescaling](../flow_decomposition/algorithm-description.md#proportional-rescaling)) is based on the side 1.

On the other hand, all flow parts (allocated flow, internal flow, loop flows and PST flow) are oriented in the branch
flow convention. A positive flow part tends to increase the absolute flow on the branch (i.e. a burdening flow), while a
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ private void printHeaderRow(Set<String> loopFlowKeys, CSVPrinter printer) {
failSilentlyPrint(printer, DecomposedFlow.INTERNAL_COLUMN_NAME);
failSilentlyPrint(printer, DecomposedFlow.PST_COLUMN_NAME);
loopFlowKeys.stream().sorted().forEach(loopFlowKey -> failSilentlyPrint(printer, loopFlowKey));
failSilentlyPrint(printer, DecomposedFlow.AC_REFERENCE_FLOW_COLUMN_NAME);
failSilentlyPrint(printer, DecomposedFlow.AC_REFERENCE_FLOW_1_COLUMN_NAME);
failSilentlyPrint(printer, DecomposedFlow.AC_REFERENCE_FLOW_2_COLUMN_NAME);
failSilentlyPrint(printer, DecomposedFlow.DC_REFERENCE_FLOW_COLUMN_NAME);
failSilentlyPrintLn(printer);
}
Expand All @@ -100,7 +101,8 @@ private void printContentRow(String xnecId, DecomposedFlow decomposedFlow, Set<S
failSilentlyPrint(printer, decomposedFlow.getInternalFlow());
failSilentlyPrint(printer, decomposedFlow.getPstFlow());
allLoopFlowKeys.stream().sorted().forEach(loopFlowKey -> failSilentlyPrint(printer, decomposedFlow.getLoopFlows().getOrDefault(loopFlowKey, NO_FLOW)));
failSilentlyPrint(printer, decomposedFlow.getAcReferenceFlow());
failSilentlyPrint(printer, decomposedFlow.getAcTerminal1ReferenceFlow());
failSilentlyPrint(printer, decomposedFlow.getAcTerminal2ReferenceFlow());
failSilentlyPrint(printer, decomposedFlow.getDcReferenceFlow());
failSilentlyPrintLn(printer);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,36 @@ public class DecomposedFlow {
private final String contingencyId;
private final Country country1;
private final Country country2;
private final double acReferenceFlow;
private final double acTerminal1ReferenceFlow;
private final double acTerminal2ReferenceFlow;
private final double dcReferenceFlow;
private final double allocatedFlow;
private final double xNodeFlow;
private final double pstFlow;
private final double internalFlow;
private final Map<String, Double> loopFlowsMap = new TreeMap<>();
static final double NO_FLOW = 0.;
static final String AC_REFERENCE_FLOW_COLUMN_NAME = "Reference AC Flow";
static final String AC_REFERENCE_FLOW_1_COLUMN_NAME = "Reference AC Flow 1";
static final String AC_REFERENCE_FLOW_2_COLUMN_NAME = "Reference AC Flow 2";
static final String DC_REFERENCE_FLOW_COLUMN_NAME = "Reference DC Flow";
static final String ALLOCATED_COLUMN_NAME = "Allocated Flow";
static final String XNODE_COLUMN_NAME = "Xnode Flow";
static final String PST_COLUMN_NAME = "PST Flow";
static final String INTERNAL_COLUMN_NAME = "Internal Flow";

protected DecomposedFlow(String branchId, String contingencyId, Country country1, Country country2, double acReferenceFlow, double dcReferenceFlow, double allocatedFlow, double xNodeFlow, double pstFlow, double internalFlow, Map<String, Double> loopFlowsMap) {
this.branchId = branchId;
this.contingencyId = contingencyId;
this.country1 = country1;
this.country2 = country2;
this.acReferenceFlow = acReferenceFlow;
this.dcReferenceFlow = dcReferenceFlow;
this.allocatedFlow = allocatedFlow;
this.xNodeFlow = xNodeFlow;
this.pstFlow = pstFlow;
this.internalFlow = internalFlow;
this.loopFlowsMap.putAll(loopFlowsMap);
protected DecomposedFlow(DecomposedFlowBuilder builder) {
this.branchId = Objects.requireNonNull(builder.branchId);
this.contingencyId = Objects.requireNonNull(builder.contingencyId);
this.country1 = Objects.requireNonNull(builder.country1);
this.country2 = Objects.requireNonNull(builder.country2);
this.acTerminal1ReferenceFlow = builder.acTerminal1ReferenceFlow;
this.acTerminal2ReferenceFlow = builder.acTerminal2ReferenceFlow;
this.dcReferenceFlow = builder.dcReferenceFlow;
this.allocatedFlow = builder.allocatedFlow;
this.xNodeFlow = builder.xNodeFlow;
this.pstFlow = builder.pstFlow;
this.internalFlow = builder.internalFlow;
this.loopFlowsMap.putAll(Objects.requireNonNull(builder.loopFlowsMap));
}

public String getBranchId() {
Expand All @@ -68,8 +71,12 @@ public Country getCountry2() {
return country2;
}

public double getAcReferenceFlow() {
return acReferenceFlow;
public double getAcTerminal1ReferenceFlow() {
return acTerminal1ReferenceFlow;
}

public double getAcTerminal2ReferenceFlow() {
return acTerminal2ReferenceFlow;
}

public double getDcReferenceFlow() {
Expand Down Expand Up @@ -112,14 +119,19 @@ public double getTotalFlow() {
return getAllocatedFlow() + getXNodeFlow() + getPstFlow() + getInternalFlow() + getTotalLoopFlow();
}

public double getMaxAbsAcFlow() {
return Math.max(Math.abs(acTerminal1ReferenceFlow), Math.abs(acTerminal2ReferenceFlow));
}

@Override
public String toString() {
return String.format("branchId: %s, contingencyId: %s, decomposition: %s", branchId, contingencyId, getAllKeyMap());
}

private TreeMap<String, Double> getAllKeyMap() {
TreeMap<String, Double> localDecomposedFlowMap = new TreeMap<>();
localDecomposedFlowMap.put(AC_REFERENCE_FLOW_COLUMN_NAME, getAcReferenceFlow());
localDecomposedFlowMap.put(AC_REFERENCE_FLOW_1_COLUMN_NAME, getAcTerminal1ReferenceFlow());
localDecomposedFlowMap.put(AC_REFERENCE_FLOW_2_COLUMN_NAME, getAcTerminal2ReferenceFlow());
localDecomposedFlowMap.put(DC_REFERENCE_FLOW_COLUMN_NAME, getDcReferenceFlow());
localDecomposedFlowMap.put(ALLOCATED_COLUMN_NAME, getAllocatedFlow());
localDecomposedFlowMap.put(XNODE_COLUMN_NAME, getXNodeFlow());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* 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.flow_decomposition;

import com.powsybl.iidm.network.Country;

import java.util.Map;

/**
* @author Caio Luke {@literal <caio.luke at artelys.com>}
* @author Sebastien Murgey {@literal <sebastien.murgey at rte-france.com>}
* @author Hugo Schindler {@literal <hugo.schindler at rte-france.com>}
*/
public class DecomposedFlowBuilder {
protected String branchId;
protected String contingencyId;
protected Country country1;
protected Country country2;
protected double acTerminal1ReferenceFlow;
protected double acTerminal2ReferenceFlow;
protected double dcReferenceFlow;
protected double allocatedFlow;
protected double xNodeFlow;
protected double pstFlow;
protected double internalFlow;
protected Map<String, Double> loopFlowsMap;

public DecomposedFlowBuilder() {
// empty constructor
}

public DecomposedFlowBuilder withBranchId(String branchId) {
this.branchId = branchId;
return this;
}

public DecomposedFlowBuilder withContingencyId(String contingencyId) {
this.contingencyId = contingencyId;
return this;
}

public DecomposedFlowBuilder withCountry1(Country country1) {
this.country1 = country1;
return this;
}

public DecomposedFlowBuilder withCountry2(Country country2) {
this.country2 = country2;
return this;
}

public DecomposedFlowBuilder withAcTerminal1ReferenceFlow(double acTerminal1ReferenceFlow) {
this.acTerminal1ReferenceFlow = acTerminal1ReferenceFlow;
return this;
}

public DecomposedFlowBuilder withAcTerminal2ReferenceFlow(double acTerminal2ReferenceFlow) {
this.acTerminal2ReferenceFlow = acTerminal2ReferenceFlow;
return this;
}

public DecomposedFlowBuilder withDcReferenceFlow(double dcReferenceFlow) {
this.dcReferenceFlow = dcReferenceFlow;
return this;
}

public DecomposedFlowBuilder withAllocatedFlow(double allocatedFlow) {
this.allocatedFlow = allocatedFlow;
return this;
}

public DecomposedFlowBuilder withXNodeFlow(double xNodeFlow) {
this.xNodeFlow = xNodeFlow;
return this;
}

public DecomposedFlowBuilder withPstFlow(double pstFlow) {
this.pstFlow = pstFlow;
return this;
}

public DecomposedFlowBuilder withInternalFlow(double internalFlow) {
this.internalFlow = internalFlow;
return this;
}

public DecomposedFlowBuilder withLoopFlowsMap(Map<String, Double> loopFlowsMap) {
this.loopFlowsMap = loopFlowsMap;
return this;
}

public DecomposedFlow build() {
return new DecomposedFlow(this);
}
}
Loading

0 comments on commit 470388e

Please sign in to comment.