Skip to content

Commit

Permalink
[Flow decomposition] Observer, NetworkUtil and Losses compensator imp…
Browse files Browse the repository at this point in the history
…rovements (#147)

improved Observer, NetworkUtil and Losses compensator

Signed-off-by: Caio Luke <caioluke97@gmail.com>
  • Loading branch information
caioluke authored Jun 6, 2024
1 parent 470388e commit 799f478
Show file tree
Hide file tree
Showing 18 changed files with 1,235 additions and 210 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,
> - have 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
saveAcReferenceFlows(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 saveAcReferenceFlows(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 @@ -107,24 +107,24 @@ public void computedDcFlows(Network network) {
}
}

public void computedAcNodalInjections(NetworkMatrixIndexes networkMatrixIndexes, boolean fallbackHasBeenActivated) {
public void computedAcNodalInjections(Network network, boolean fallbackHasBeenActivated) {
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.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
Loading

0 comments on commit 799f478

Please sign in to comment.