Skip to content

Commit

Permalink
Flow decomposition observers (#132)
Browse files Browse the repository at this point in the history
Signed-off-by: Guillaume Verger <[email protected]>
Signed-off-by: Damien Jeandemange <[email protected]>
  • Loading branch information
gverger authored Jan 31, 2024
1 parent 4f4d8f0 commit 63e62d7
Show file tree
Hide file tree
Showing 6 changed files with 699 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2024, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/)
* 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/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.flow_decomposition;

import com.powsybl.iidm.network.Branch;
import com.powsybl.iidm.network.Identifiable;

import java.util.Collection;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author Guillaume Verger {@literal <guillaume.verger at artelys.com>}
*/
class AcReferenceFlowComputer {
private static ReferenceFlowComputer flowComputer = new ReferenceFlowComputer();

Map<String, Double> run(Collection<Branch> xnecList, LoadFlowRunningService.Result loadFlowServiceAcResult) {
if (loadFlowServiceAcResult.fallbackHasBeenActivated()) {
return xnecList.stream().collect(Collectors.toMap(Identifiable::getId, branch -> Double.NaN));
}

return flowComputer.run(xnecList);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.powsybl.flow_decomposition.glsk_provider.AutoGlskProvider;
import com.powsybl.iidm.network.Branch;
import com.powsybl.iidm.network.Country;
import com.powsybl.iidm.network.Identifiable;
import com.powsybl.iidm.network.Network;
import com.powsybl.loadflow.LoadFlow;
import com.powsybl.loadflow.LoadFlowParameters;
Expand All @@ -19,13 +18,13 @@
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @author Sebastien Murgey {@literal <sebastien.murgey at rte-france.com>}
* @author Hugo Schindler {@literal <hugo.schindler at rte-france.com>}
*/
public class FlowDecompositionComputer {

static final String DEFAULT_LOAD_FLOW_PROVIDER = null;
static final String DEFAULT_SENSITIVITY_ANALYSIS_PROVIDER = null;
private final LoadFlowParameters loadFlowParameters;
Expand All @@ -34,6 +33,8 @@ public class FlowDecompositionComputer {
private final SensitivityAnalysis.Runner sensitivityAnalysisRunner;
private final LossesCompensator lossesCompensator;

private final FlowDecompositionObserverList observers;

public FlowDecompositionComputer() {
this(new FlowDecompositionParameters());
}
Expand All @@ -46,6 +47,7 @@ public FlowDecompositionComputer(FlowDecompositionParameters flowDecompositionPa
this.loadFlowRunningService = new LoadFlowRunningService(LoadFlow.find(loadFlowProvider));
this.sensitivityAnalysisRunner = SensitivityAnalysis.find(sensitivityAnalysisProvider);
this.lossesCompensator = parameters.isLossesCompensationEnabled() ? new LossesCompensator(parameters) : null;
this.observers = new FlowDecompositionObserverList();
}

public FlowDecompositionComputer(FlowDecompositionParameters flowDecompositionParameters,
Expand All @@ -63,30 +65,38 @@ public FlowDecompositionResults run(XnecProvider xnecProvider, Network network)
}

public FlowDecompositionResults run(XnecProvider xnecProvider, GlskProvider glskProvider, Network network) {
NetworkStateManager networkStateManager = new NetworkStateManager(network, xnecProvider);

LoadFlowRunningService.Result loadFlowServiceAcResult = runAcLoadFlow(network);

Map<Country, Map<String, Double>> glsks = glskProvider.getGlsk(network);
Map<Country, Double> netPositions = getZonesNetPosition(network);

FlowDecompositionResults flowDecompositionResults = new FlowDecompositionResults(network);
decomposeFlowForNState(network,
flowDecompositionResults,
xnecProvider.getNetworkElements(network),
netPositions,
glsks,
loadFlowServiceAcResult);
xnecProvider.getNetworkElementsPerContingency(network)
.forEach((contingencyId, xnecList) -> decomposeFlowForContingencyState(network,
flowDecompositionResults,
networkStateManager,
contingencyId,
xnecList,
netPositions,
glsks));
networkStateManager.deleteAllContingencyVariants();
return flowDecompositionResults;
observers.runStart();
try {
NetworkStateManager networkStateManager = new NetworkStateManager(network, xnecProvider);

LoadFlowRunningService.Result loadFlowServiceAcResult = runAcLoadFlow(network);

Map<Country, Map<String, Double>> glsks = glskProvider.getGlsk(network);
observers.computedGlsk(glsks);

Map<Country, Double> netPositions = getZonesNetPosition(network);
observers.computedNetPositions(netPositions);

FlowDecompositionResults flowDecompositionResults = new FlowDecompositionResults(network);
decomposeFlowForNState(network,
flowDecompositionResults,
xnecProvider.getNetworkElements(network),
netPositions,
glsks,
loadFlowServiceAcResult);
xnecProvider.getNetworkElementsPerContingency(network)
.forEach((contingencyId, xnecList) -> decomposeFlowForContingencyState(network,
flowDecompositionResults,
networkStateManager,
contingencyId,
xnecList,
netPositions,
glsks));
networkStateManager.deleteAllContingencyVariants();
return flowDecompositionResults;
} finally {
observers.runDone();
}
}

private void decomposeFlowForNState(Network network,
Expand All @@ -96,6 +106,7 @@ private void decomposeFlowForNState(Network network,
Map<Country, Map<String, Double>> glsks,
LoadFlowRunningService.Result loadFlowServiceAcResult) {
if (!xnecList.isEmpty()) {
observers.computingBaseCase();
FlowDecompositionResults.PerStateBuilder flowDecompositionResultsBuilder = flowDecompositionResults.getBuilder(xnecList);
decomposeFlowForState(network, xnecList, flowDecompositionResultsBuilder, netPositions, glsks, loadFlowServiceAcResult);
}
Expand All @@ -109,6 +120,7 @@ private void decomposeFlowForContingencyState(Network network,
Map<Country, Double> netPositions,
Map<Country, Map<String, Double>> glsks) {
if (!xnecList.isEmpty()) {
observers.computingContingency(contingencyId);
networkStateManager.setNetworkVariant(contingencyId);
LoadFlowRunningService.Result loadFlowServiceAcResult = runAcLoadFlow(network);
FlowDecompositionResults.PerStateBuilder flowDecompositionResultsBuilder = flowDecompositionResults.getBuilder(contingencyId, xnecList);
Expand All @@ -124,20 +136,27 @@ private void decomposeFlowForState(Network network,
LoadFlowRunningService.Result loadFlowServiceAcResult) {
saveAcReferenceFlow(flowDecompositionResultsBuilder, xnecList, loadFlowServiceAcResult);
compensateLosses(network);
observers.computedAcFlows(network, loadFlowServiceAcResult);

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

runDcLoadFlow(network);
observers.computedDcFlows(network);
observers.computedDcNodalInjections(networkMatrixIndexes);

SparseMatrixWithIndexesTriplet nodalInjectionsMatrix = getNodalInjectionsMatrix(network,
netPositions, networkMatrixIndexes, glsks);
saveDcReferenceFlow(flowDecompositionResultsBuilder, xnecList);
observers.computedNodalInjectionsMatrix(nodalInjectionsMatrix);

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

// None
computeAllocatedAndLoopFlows(flowDecompositionResultsBuilder, nodalInjectionsMatrix, ptdfMatrix);
Expand All @@ -146,17 +165,20 @@ private void decomposeFlowForState(Network network,
flowDecompositionResultsBuilder.build(parameters.isRescaleEnabled());
}

public void addObserver(FlowDecompositionObserver observer) {
this.observers.addObserver(observer);
}

public void removeObserver(FlowDecompositionObserver observer) {
this.observers.removeObserver(observer);
}

private LoadFlowRunningService.Result runAcLoadFlow(Network network) {
return loadFlowRunningService.runAcLoadflow(network, loadFlowParameters, parameters.isDcFallbackEnabledAfterAcDivergence());
}

private void saveAcReferenceFlow(FlowDecompositionResults.PerStateBuilder flowDecompositionResultBuilder, Set<Branch> xnecList, LoadFlowRunningService.Result loadFlowServiceAcResult) {
Map<String, Double> acReferenceFlows;
if (loadFlowServiceAcResult.fallbackHasBeenActivated()) {
acReferenceFlows = xnecList.stream().collect(Collectors.toMap(Identifiable::getId, branch -> Double.NaN));
} else {
acReferenceFlows = getXnecReferenceFlows(xnecList);
}
Map<String, Double> acReferenceFlows = new AcReferenceFlowComputer().run(xnecList, loadFlowServiceAcResult);
flowDecompositionResultBuilder.saveAcReferenceFlow(acReferenceFlows);
}

Expand All @@ -165,9 +187,8 @@ private Map<Country, Double> getZonesNetPosition(Network network) {
return netPositionComputer.run(network);
}

private Map<String, Double> getXnecReferenceFlows(Set<Branch> xnecList) {
ReferenceFlowComputer referenceFlowComputer = new ReferenceFlowComputer();
return referenceFlowComputer.run(xnecList);
private Map<String, Double> getBranchReferenceFlows(Set<Branch> branches) {
return new ReferenceFlowComputer().run(branches);
}

private void compensateLosses(Network network) {
Expand All @@ -189,7 +210,7 @@ private SparseMatrixWithIndexesTriplet getNodalInjectionsMatrix(Network network,
}

private void saveDcReferenceFlow(FlowDecompositionResults.PerStateBuilder flowDecompositionResultBuilder, Set<Branch> xnecList) {
flowDecompositionResultBuilder.saveDcReferenceFlow(getXnecReferenceFlows(xnecList));
flowDecompositionResultBuilder.saveDcReferenceFlow(getBranchReferenceFlows(xnecList));
}

private SensitivityAnalyser getSensitivityAnalyser(Network network, NetworkMatrixIndexes networkMatrixIndexes) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright (c) 2024, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/)
* 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/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.flow_decomposition;

import com.powsybl.iidm.network.Country;

import java.util.Map;

/**
* @author Guillaume Verger {@literal <guillaume.verger at artelys.com>}
*/
public interface FlowDecompositionObserver {

/**
* Called when the computation starts
*/
void runStart();

/**
* Called when the computation is done
*/
void runDone();

/**
* Called when the base case starts to be computed
*/
void computingBaseCase();

/**
* Called when a contingency computation starts
*
* @param contingencyId The current contingency id
*/
void computingContingency(String contingencyId);

/**
* Called when Glsk are computed thanks to the GlskProvider (during base case computation)
*
* @param glsks the Glsks per country per generator
*/
void computedGlsk(Map<Country, Map<String, Double>> glsks);

/**
* Called when net positions are computed (for base case computation)
*
* @param netPositions the net positions per country
*/
void computedNetPositions(Map<Country, Double> netPositions);

/**
* Called when the nodal injection matrix is computed (for base case or contingency)
*
* @param nodalInjections the matrix of nodal injections indexed by(node, flow)
*/
void computedNodalInjectionsMatrix(Map<String, Map<String, Double>> nodalInjections);

/**
* Called when the PTDF matrix is computed (for base case or contingency)
*
* @param pdtfMatrix the matrix of ptdf indexed by (line, node)
*/
void computedPtdfMatrix(Map<String, Map<String, Double>> pdtfMatrix);

/**
* Called when the PSDF matrix is computed (for base case or contingency)
*
* @param psdfMatrix the matrix of psdf indexed by (line, node)
*/
void computedPsdfMatrix(Map<String, Map<String, Double>> psdfMatrix);

/**
* Called when the AC nodal injections matrix is computed (for base case or contingency)
*
* @param positions the positions after AC loadflow
* @param fallbackHasBeenActivated true if AC loadflow didn't converge
*/
void computedAcNodalInjections(Map<String, Double> positions, boolean fallbackHasBeenActivated);

/**
* Called when the DC nodal injections matrix is computed (for base case or contingency)
*
* @param positions the positions after DC loadflow
*/
void computedDcNodalInjections(Map<String, Double> positions);

/**
* Called when the AC loadflow is computed (for base case or contingency)
*
* @param flows the flows for all branches
*/
void computedAcFlows(Map<String, Double> flows);

/**
* Called when the DC loadflow is computed (for base case or contingency)
*
* @param flows the flows for all branches
*/
void computedDcFlows(Map<String, Double> flows);
}
Loading

0 comments on commit 63e62d7

Please sign in to comment.