Skip to content

Commit

Permalink
[Flow decomposition][Reformat] Observer and NetworkUtil (#149)
Browse files Browse the repository at this point in the history
Signed-off-by: Hugo SCHINDLER <hugo.schindler@rte-france.com>
  • Loading branch information
OpenSuze committed Jun 4, 2024
1 parent 9ada372 commit 8b638fa
Show file tree
Hide file tree
Showing 14 changed files with 1,114 additions and 168 deletions.
21 changes: 20 additions & 1 deletion docs/flow_decomposition/algorithm-description.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ compensated at both sides proportionally to the resistance of each half line.

## Nodal Injections partitioning

> **_NOTE:_** In PowSyBl terminology, nodal injections are injection connectables that
> - are not paired dangling lines,
> - are connected to the network,
> - are in the main synchronous component (for sensitivity computation reasons),
> - are not a bus bar section (because of a lack of reference injection),
> - are not shunt compensator or static var compensator (for sensitivity computation reasons).
> **_NOTE:_** In PowSyBl terminology, xnodes are unpaired dangling lines connected to the network and in the main synchronous component.
In order to distinguish internal/loop flows and allocated flows, the nodal injections in each zone must de decomposed in two parts:
- Nodal injections for allocated flows
- Nodal injections for loop flows and internal flows
Expand Down Expand Up @@ -63,6 +72,16 @@ where:

## Sensitivity analysis

> **_NOTE:_** In PowSyBl terminology, only two windings transformers are considered. PSTs must:
> - be connected to the network,
> - have a phase tap changer,
> - having a neutral step on the phase tap changer,
> - have a bus at each terminal,
> - be connected to the main synchronous component.
> Therefore, three windings transformers are not supported.
> **_NOTE:_** Each element of the sensitivity computation must be connected to the main synchronous component (variables (injections) and functions (branches)).
In order to assess the linear impact (implied by the DC approximation) of each nodal injection and phase shift transformer
on the network elements' flow, a sensitivity analysis is run.

Expand All @@ -89,7 +108,7 @@ where:
- $\mathrm{F}_\mathrm{PST}$ is the vector of the network element PST (phase shift transformer) flow,
- $\mathrm{F}_\mathrm{X}$ is the vector of the network element xnode flow,
- $\mathrm{AM}$ is the allocation matrix, which associates each injection to its zone. $\mathrm{AM}_{ij}$ = 1 if node i is in zone j, 0 otherwise,
- $\mathrm{\Delta}_\mathrm{PST}$ is the phase shift transformers angle vector,
- $\mathrm{\Delta}_\mathrm{PST}$ is the phase shift transformers angle vector. The neutral tap position of each PST is used to compute this difference.

## Flow parts rescaling

Expand Down
63 changes: 35 additions & 28 deletions flow-decomposition/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,95 +14,102 @@
<description>Implementation of ACER methodology for flow decomposition</description>

<dependencies>
<!-- Compile dependencies -->
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-commons</artifactId>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-iidm-api</artifactId>
<artifactId>powsybl-glsk-document-api</artifactId>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-loadflow-api</artifactId>
<artifactId>powsybl-iidm-api</artifactId>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-glsk-document-api</artifactId>
<artifactId>powsybl-loadflow-api</artifactId>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-sensitivity-analysis-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>${commonscsv.version}</version>
</dependency>
<dependency>
<groupId>org.ejml</groupId>
<artifactId>ejml-all</artifactId>
<version>${ejml.version}</version>
</dependency>
<!-- Runtime dependencies -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>${commonscsv.version}</version>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-iidm-impl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-glsk-document-io-api</artifactId>
<scope>test</scope>
<artifactId>powsybl-iidm-serde</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-glsk-document-ucte</artifactId>
<scope>test</scope>
<artifactId>powsybl-open-loadflow</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-iidm-impl</artifactId>
<artifactId>powsybl-ucte-converter</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-iidm-serde</artifactId>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-cgmes-conversion</artifactId>
<groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-cgmes-conformity</artifactId>
<artifactId>powsybl-config-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-triple-store-impl-rdf4j</artifactId>
<artifactId>powsybl-cgmes-conformity</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-open-loadflow</artifactId>
<version>${powsyblopenloadflow.version}</version>
<scope>runtime</scope>
<artifactId>powsybl-cgmes-conversion</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-ucte-converter</artifactId>
<scope>runtime</scope>
<artifactId>powsybl-glsk-document-io-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-glsk-document-ucte</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-iidm-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-config-test</artifactId>
<artifactId>powsybl-triple-store-impl-rdf4j</artifactId>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public String getContingencyId() {
}

public String getId() {
return NetworkUtil.getXnecId(contingencyId, branchId);
return getXnecId(contingencyId, branchId);
}

public Country getCountry1() {
Expand Down Expand Up @@ -140,4 +140,8 @@ private TreeMap<String, Double> getAllKeyMap() {
localDecomposedFlowMap.putAll(loopFlowsMap);
return localDecomposedFlowMap;
}

public static String getXnecId(String contingencyId, String branchId) {
return contingencyId.isEmpty() ? branchId : String.format("%s_%s", branchId, contingencyId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,31 +141,27 @@ private void decomposeFlowForState(Network network,
Map<Country, Double> netPositions,
Map<Country, Map<String, Double>> glsks,
LoadFlowRunningService.Result loadFlowServiceAcResult) {
saveAcReferenceFlows(flowDecompositionResultsBuilder, xnecList, loadFlowServiceAcResult);
compensateLosses(network);
observers.computedAcFlows(network, loadFlowServiceAcResult);
// AC load flow
saveAcReferenceFlow(flowDecompositionResultsBuilder, network, xnecList, loadFlowServiceAcResult);

// None
NetworkMatrixIndexes networkMatrixIndexes = new NetworkMatrixIndexes(network, new ArrayList<>(xnecList));
observers.computedAcNodalInjections(networkMatrixIndexes, loadFlowServiceAcResult.fallbackHasBeenActivated());
// Losses compensation
compensateLosses(network);

// DC load flow
runDcLoadFlow(network);
observers.computedDcFlows(network);
observers.computedDcNodalInjections(networkMatrixIndexes);
saveDcReferenceFlow(flowDecompositionResultsBuilder, network, xnecList);

SparseMatrixWithIndexesTriplet nodalInjectionsMatrix = getNodalInjectionsMatrix(network,
netPositions, networkMatrixIndexes, glsks);
saveDcReferenceFlow(flowDecompositionResultsBuilder, xnecList);
observers.computedNodalInjectionsMatrix(nodalInjectionsMatrix);
// Nodal injections
NetworkMatrixIndexes networkMatrixIndexes = new NetworkMatrixIndexes(network, new ArrayList<>(xnecList));
SparseMatrixWithIndexesTriplet nodalInjectionsMatrix = getNodalInjectionsMatrix(network, netPositions,
networkMatrixIndexes, glsks);

// DC Sensi
// Sensitivity
SensitivityAnalyser sensitivityAnalyser = getSensitivityAnalyser(network, networkMatrixIndexes);
SparseMatrixWithIndexesTriplet ptdfMatrix = getPtdfMatrix(networkMatrixIndexes, sensitivityAnalyser);
observers.computedPtdfMatrix(ptdfMatrix);
SparseMatrixWithIndexesTriplet psdfMatrix = getPsdfMatrix(networkMatrixIndexes, sensitivityAnalyser);
observers.computedPsdfMatrix(psdfMatrix);

// None
// Flows
computeAllocatedAndLoopFlows(flowDecompositionResultsBuilder, nodalInjectionsMatrix, ptdfMatrix);
computePstFlows(network, flowDecompositionResultsBuilder, networkMatrixIndexes, psdfMatrix);

Expand All @@ -184,11 +180,13 @@ private LoadFlowRunningService.Result runAcLoadFlow(Network network) {
return loadFlowRunningService.runAcLoadflow(network, loadFlowParameters, parameters.isDcFallbackEnabledAfterAcDivergence());
}

private void saveAcReferenceFlows(FlowDecompositionResults.PerStateBuilder flowDecompositionResultBuilder, Set<Branch> xnecList, LoadFlowRunningService.Result loadFlowServiceAcResult) {
private void saveAcReferenceFlow(FlowDecompositionResults.PerStateBuilder flowDecompositionResultBuilder, Network network, Set<Branch> xnecList, LoadFlowRunningService.Result loadFlowServiceAcResult) {
Map<String, Double> acTerminal1ReferenceFlows = FlowComputerUtils.calculateAcTerminalReferenceFlows(xnecList, loadFlowServiceAcResult, TwoSides.ONE);
Map<String, Double> acTerminal2ReferenceFlows = FlowComputerUtils.calculateAcTerminalReferenceFlows(xnecList, loadFlowServiceAcResult, TwoSides.TWO);
flowDecompositionResultBuilder.saveAcTerminal1ReferenceFlow(acTerminal1ReferenceFlows);
flowDecompositionResultBuilder.saveAcTerminal2ReferenceFlow(acTerminal2ReferenceFlows);
observers.computedAcFlows(network, loadFlowServiceAcResult);
observers.computedAcNodalInjections(network, loadFlowServiceAcResult.fallbackHasBeenActivated());
}

private Map<Country, Double> getZonesNetPosition(Network network) {
Expand Down Expand Up @@ -220,11 +218,15 @@ private SparseMatrixWithIndexesTriplet getNodalInjectionsMatrix(Network network,
NetworkMatrixIndexes networkMatrixIndexes,
Map<Country, Map<String, Double>> glsks) {
NodalInjectionComputer nodalInjectionComputer = new NodalInjectionComputer(networkMatrixIndexes);
return nodalInjectionComputer.run(network, glsks, netPositions);
SparseMatrixWithIndexesTriplet nodalInjectionsMatrix = nodalInjectionComputer.run(network, glsks, netPositions);
observers.computedNodalInjectionsMatrix(nodalInjectionsMatrix);
return nodalInjectionsMatrix;
}

private void saveDcReferenceFlow(FlowDecompositionResults.PerStateBuilder flowDecompositionResultBuilder, Set<Branch> xnecList) {
private void saveDcReferenceFlow(FlowDecompositionResults.PerStateBuilder flowDecompositionResultBuilder, Network network, Set<Branch> xnecList) {
flowDecompositionResultBuilder.saveDcReferenceFlow(FlowComputerUtils.getTerminalReferenceFlow(xnecList, TwoSides.ONE));
observers.computedDcFlows(network);
observers.computedDcNodalInjections(network);
}

private SensitivityAnalyser getSensitivityAnalyser(Network network, NetworkMatrixIndexes networkMatrixIndexes) {
Expand All @@ -233,9 +235,11 @@ private SensitivityAnalyser getSensitivityAnalyser(Network network, NetworkMatri

private SparseMatrixWithIndexesTriplet getPtdfMatrix(NetworkMatrixIndexes networkMatrixIndexes,
SensitivityAnalyser sensitivityAnalyser) {
return sensitivityAnalyser.run(networkMatrixIndexes.getNodeIdList(),
SparseMatrixWithIndexesTriplet ptdfMatrix = sensitivityAnalyser.run(networkMatrixIndexes.getNodeIdList(),
networkMatrixIndexes.getNodeIndex(),
SensitivityVariableType.INJECTION_ACTIVE_POWER);
observers.computedPtdfMatrix(ptdfMatrix);
return ptdfMatrix;
}

private void computeAllocatedAndLoopFlows(FlowDecompositionResults.PerStateBuilder flowDecompositionResultBuilder,
Expand All @@ -248,8 +252,10 @@ private void computeAllocatedAndLoopFlows(FlowDecompositionResults.PerStateBuild

private SparseMatrixWithIndexesTriplet getPsdfMatrix(NetworkMatrixIndexes networkMatrixIndexes,
SensitivityAnalyser sensitivityAnalyser) {
return sensitivityAnalyser.run(networkMatrixIndexes.getPstList(),
SparseMatrixWithIndexesTriplet psdfMatrix = sensitivityAnalyser.run(networkMatrixIndexes.getPstList(),
networkMatrixIndexes.getPstIndex(), SensitivityVariableType.TRANSFORMER_PHASE);
observers.computedPsdfMatrix(psdfMatrix);
return psdfMatrix;
}

private void computePstFlows(Network network,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

import com.powsybl.flow_decomposition.LoadFlowRunningService.Result;
import com.powsybl.iidm.network.Country;
import com.powsybl.iidm.network.Injection;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.TwoSides;

Expand Down Expand Up @@ -108,26 +107,25 @@ public void computedDcFlows(Network network) {
}
}

public void computedAcNodalInjections(NetworkMatrixIndexes networkMatrixIndexes, boolean fallbackHasBeenActivated) {
public void computedAcNodalInjections(Network network, boolean fallbackHasBeenActivated) {
if (observers.isEmpty()) {
return;
}
// in case losses are compensated, losses terminal are not yet defined at this point, therefore we filter them
List<Injection<?>> nodeListWithoutCompensatedLosses = networkMatrixIndexes.getNodeList()
.stream()
.filter(injection -> !injection.getId().startsWith(LossesCompensator.getLossesId("")))
.toList();
Map<String, Double> results = new ReferenceNodalInjectionComputer().run(nodeListWithoutCompensatedLosses);

Map<String, Double> results = new ReferenceNodalInjectionComputer().run(NetworkUtil.getNodeList(network));

for (FlowDecompositionObserver o : observers) {
o.computedAcNodalInjections(results, fallbackHasBeenActivated);
}
}

public void computedDcNodalInjections(NetworkMatrixIndexes networkMatrixIndexes) {
public void computedDcNodalInjections(Network network) {
if (observers.isEmpty()) {
return;
}
Map<String, Double> results = new ReferenceNodalInjectionComputer().run(networkMatrixIndexes.getNodeList());

Map<String, Double> results = new ReferenceNodalInjectionComputer().run(NetworkUtil.getNodeList(network));

for (FlowDecompositionObserver o : observers) {
o.computedDcNodalInjections(results);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ void saveDcReferenceFlow(Map<String, Double> dcReferenceFlow) {
void build(DecomposedFlowRescaler decomposedFlowRescaler) {
allocatedAndLoopFlowsMatrix.toMap()
.forEach((branchId, decomposedFlow) -> {
String xnecId = NetworkUtil.getXnecId(contingencyId, branchId);
String xnecId = DecomposedFlow.getXnecId(contingencyId, branchId);
decomposedFlowMap.put(xnecId, createDecomposedFlow(branchId, decomposedFlow, decomposedFlowRescaler));
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

/**
* @author Sebastien Murgey {@literal <sebastien.murgey at rte-france.com>}
* @author Hugo Schindler{@literal <hugo.schindler@rte-france.com>}
* @author Hugo Schindler{@literal <hugo.schindler at rte-france.com>}
*/
class NetPositionComputer {
Map<Country, Double> run(Network network) {
Expand Down
Loading

0 comments on commit 8b638fa

Please sign in to comment.