Skip to content

Commit

Permalink
Fix secondary synchronous components in main CC not computed in SA (#…
Browse files Browse the repository at this point in the history
…1129)

Signed-off-by: Bertrand Rix <bertrand.rix@artelys.com>
  • Loading branch information
obrix authored Dec 2, 2024
1 parent 613d726 commit c1e8dd0
Show file tree
Hide file tree
Showing 3 changed files with 246 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -251,49 +251,64 @@ SecurityAnalysisReport runSync(SecurityAnalysisParameters securityAnalysisParame
SecurityAnalysisResult runSimulationsOnAllComponents(LfNetworkList networks, List<PropagatedContingency> propagatedContingencies, P parameters,
SecurityAnalysisParameters securityAnalysisParameters, List<OperatorStrategy> operatorStrategies,
List<Action> actions, List<LimitReduction> limitReductions, LoadFlowParameters lfParameters) {
// run simulation on main connected component network first
SecurityAnalysisResult result = networks.getList().stream().filter(n -> n.getValidity().equals(LfNetwork.Validity.VALID) && n.getNumCC() == ComponentConstants.MAIN_NUM)
.findFirst()
.map(n -> runSimulations(n, propagatedContingencies, parameters, securityAnalysisParameters, operatorStrategies, actions, limitReductions))
.orElse(createNoResult());

List<LfNetwork> networkToSimulate = new ArrayList<>(getNetworksToSimulate(networks, lfParameters.getConnectedComponentMode()));

if (networkToSimulate.isEmpty()) {
return createNoResult();
}

// run simulation on first lfNetwork to initialize results structures
LfNetwork firstNetwork = networkToSimulate.remove(0);
SecurityAnalysisResult result = runSimulations(firstNetwork, propagatedContingencies, parameters, securityAnalysisParameters, operatorStrategies, actions, limitReductions);

List<PostContingencyResult> postContingencyResults = result.getPostContingencyResults();
List<OperatorStrategyResult> operatorStrategyResults = result.getOperatorStrategyResults();
NetworkResult mergedPreContingencyNetworkResult = result.getPreContingencyResult().getNetworkResult();
List<LimitViolation> preContingenctViolations = result.getPreContingencyResult().getLimitViolationsResult().getLimitViolations();
List<LimitViolation> preContingencyViolations = result.getPreContingencyResult().getLimitViolationsResult().getLimitViolations();

if (lfParameters.getConnectedComponentMode() == LoadFlowParameters.ConnectedComponentMode.ALL) {
Map<String, PostContingencyResult> postContingencyResultMap = new LinkedHashMap<>();
Map<String, OperatorStrategyResult> operatorStrategyResultMap = new LinkedHashMap<>();
postContingencyResults.forEach(r -> postContingencyResultMap.put(r.getContingency().getId(), r));
operatorStrategyResults.forEach(r -> operatorStrategyResultMap.put(r.getOperatorStrategy().getId(), r));
Map<String, PostContingencyResult> postContingencyResultMap = new LinkedHashMap<>();
Map<String, OperatorStrategyResult> operatorStrategyResultMap = new LinkedHashMap<>();
postContingencyResults.forEach(r -> postContingencyResultMap.put(r.getContingency().getId(), r));
operatorStrategyResults.forEach(r -> operatorStrategyResultMap.put(r.getOperatorStrategy().getId(), r));

// Ensure the lists are writable and can be extended
preContingenctViolations = new ArrayList<>(preContingenctViolations);
// Ensure the lists are writable and can be extended
preContingencyViolations = new ArrayList<>(preContingencyViolations);

List<LfNetwork> networkToSimulate = networks.getList().stream()
.filter(n -> n.getNumCC() != ComponentConstants.MAIN_NUM && n.getValidity().equals(LfNetwork.Validity.VALID)).toList();
for (LfNetwork n : networkToSimulate) {
SecurityAnalysisResult resultOtherComponent = runSimulations(n, propagatedContingencies, parameters, securityAnalysisParameters, operatorStrategies, actions, limitReductions);
for (LfNetwork n : networkToSimulate) {
SecurityAnalysisResult resultOtherComponent = runSimulations(n, propagatedContingencies, parameters, securityAnalysisParameters, operatorStrategies, actions, limitReductions);

// Merge into first result
// PreContingency results first
preContingenctViolations.addAll(resultOtherComponent.getPreContingencyResult().getLimitViolationsResult().getLimitViolations());
mergedPreContingencyNetworkResult = mergeNetworkResult(mergedPreContingencyNetworkResult, resultOtherComponent.getPreContingencyResult().getNetworkResult());
// Merge into first result
// PreContingency results first
preContingencyViolations.addAll(resultOtherComponent.getPreContingencyResult().getLimitViolationsResult().getLimitViolations());
mergedPreContingencyNetworkResult = mergeNetworkResult(mergedPreContingencyNetworkResult, resultOtherComponent.getPreContingencyResult().getNetworkResult());

// PostContingency and OperatorStrategies results
mergeSecurityAnalysisResult(resultOtherComponent, postContingencyResultMap, operatorStrategyResultMap, n.getNumCC());
}
postContingencyResults = postContingencyResultMap.values().stream().toList();
operatorStrategyResults = operatorStrategyResultMap.values().stream().toList();
// PostContingency and OperatorStrategies results
mergeSecurityAnalysisResult(resultOtherComponent, postContingencyResultMap, operatorStrategyResultMap, n.getNumCC());
}
postContingencyResults = postContingencyResultMap.values().stream().toList();
operatorStrategyResults = operatorStrategyResultMap.values().stream().toList();

PreContingencyResult mergedPrecontingencyResult =
new PreContingencyResult(result.getPreContingencyResult().getStatus(),
new LimitViolationsResult(preContingenctViolations),
mergedPreContingencyNetworkResult);
new PreContingencyResult(result.getPreContingencyResult().getStatus(),
new LimitViolationsResult(preContingencyViolations),
mergedPreContingencyNetworkResult);
return new SecurityAnalysisResult(mergedPrecontingencyResult, postContingencyResults, operatorStrategyResults);
}

static List<LfNetwork> getNetworksToSimulate(LfNetworkList networks, LoadFlowParameters.ConnectedComponentMode mode) {

if (LoadFlowParameters.ConnectedComponentMode.MAIN.equals(mode)) {
return networks.getList().stream()
.filter(n -> n.getNumCC() == ComponentConstants.MAIN_NUM && n.getValidity().equals(LfNetwork.Validity.VALID)).toList();
} else if (LoadFlowParameters.ConnectedComponentMode.ALL.equals(mode)) {
return networks.getList().stream()
.filter(n -> n.getValidity().equals(LfNetwork.Validity.VALID)).toList();
} else {
throw new PowsyblException("Unsupported ConnectedComponentMode " + mode);
}
}

void mergeSecurityAnalysisResult(SecurityAnalysisResult resultToMerge, Map<String, PostContingencyResult> postContingencyResults,
Map<String, OperatorStrategyResult> operatorStrategyResults, int connectedComponentNum) {
resultToMerge.getPostContingencyResults().forEach(postContingencyResult -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
package com.powsybl.openloadflow.network;

import com.powsybl.iidm.network.Bus;
import com.powsybl.iidm.network.HvdcLine;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.TwoWindingsTransformer;

Expand Down Expand Up @@ -755,4 +756,119 @@ public static Network createTwoCcLinkedBySwitches() {
createLoad(b2, "d2", 1);
return network;
}

public static Network createNoCc0Sc0() {
// b01 -- b02 -- b03 -- b04 connected by DC lines
// b11 -- b12 connected by AC line
Network network = Network.create("test", "code");
Bus b01 = createBus(network, "b01");
Bus b02 = createBus(network, "b02");
Bus b03 = createBus(network, "b03");
Bus b04 = createBus(network, "b04");
Bus b11 = createBus(network, "b11");
Bus b12 = createBus(network, "b12");

b01.getVoltageLevel()
.newVscConverterStation()
.setId("cs1-12")
.setConnectableBus(b01.getId())
.setBus(b01.getId())
.setVoltageRegulatorOn(true)
.setVoltageSetpoint(1.0)
.setReactivePowerSetpoint(0.0)
.setLossFactor(0.0f)
.add();
b02.getVoltageLevel()
.newVscConverterStation()
.setId("cs2-12")
.setConnectableBus(b02.getId())
.setBus(b02.getId())
.setVoltageRegulatorOn(true)
.setVoltageSetpoint(1.0)
.setReactivePowerSetpoint(0.0)
.setLossFactor(0.0f)
.add();
network.newHvdcLine()
.setId("hvdc12")
.setConverterStationId1("cs1-12")
.setConverterStationId2("cs2-12")
.setNominalV(1.)
.setR(0.0)
.setActivePowerSetpoint(1.)
.setConvertersMode(HvdcLine.ConvertersMode.SIDE_1_RECTIFIER_SIDE_2_INVERTER)
.setMaxP(5)
.add();

b02.getVoltageLevel()
.newVscConverterStation()
.setId("cs1-23")
.setConnectableBus(b02.getId())
.setBus(b02.getId())
.setVoltageRegulatorOn(true)
.setVoltageSetpoint(1.0)
.setReactivePowerSetpoint(0.0)
.setLossFactor(0.0f)
.add();
b03.getVoltageLevel()
.newVscConverterStation()
.setId("cs2-23")
.setConnectableBus(b03.getId())
.setBus(b03.getId())
.setVoltageRegulatorOn(true)
.setVoltageSetpoint(1.0)
.setReactivePowerSetpoint(0.0)
.setLossFactor(0.0f)
.add();
network.newHvdcLine()
.setId("hvdc23")
.setConverterStationId1("cs1-23")
.setConverterStationId2("cs2-23")
.setNominalV(1.)
.setR(0.0)
.setActivePowerSetpoint(2.)
.setConvertersMode(HvdcLine.ConvertersMode.SIDE_1_RECTIFIER_SIDE_2_INVERTER)
.setMaxP(5)
.add();

b03.getVoltageLevel()
.newVscConverterStation()
.setId("cs1-34")
.setConnectableBus(b03.getId())
.setBus(b03.getId())
.setVoltageRegulatorOn(true)
.setVoltageSetpoint(1.0)
.setReactivePowerSetpoint(0.0)
.setLossFactor(0.0f)
.add();
b04.getVoltageLevel()
.newVscConverterStation()
.setId("cs2-34")
.setConnectableBus(b04.getId())
.setBus(b04.getId())
.setVoltageRegulatorOn(true)
.setVoltageSetpoint(1.0)
.setReactivePowerSetpoint(0.0)
.setLossFactor(0.0f)
.add();
network.newHvdcLine()
.setId("hvdc34")
.setConverterStationId1("cs1-34")
.setConverterStationId2("cs2-34")
.setNominalV(1.)
.setR(0.0)
.setActivePowerSetpoint(3.)
.setConvertersMode(HvdcLine.ConvertersMode.SIDE_1_RECTIFIER_SIDE_2_INVERTER)
.setMaxP(5)
.add();

createGenerator(b01, "g01", 1);
createGenerator(b02, "g02", 1);
createGenerator(b03, "g03", 1);
createGenerator(b04, "g04", 1);
createLoad(b04, "l04", 4);
createGenerator(b11, "g11", 2);
createLoad(b12, "l11", 2);
createLine(network, b11, b12, "l11-12", 0.1f);
return network;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
import com.powsybl.openloadflow.lf.outerloop.OuterLoopResult;
import com.powsybl.openloadflow.lf.outerloop.OuterLoopStatus;
import com.powsybl.openloadflow.network.*;
import com.powsybl.openloadflow.network.impl.LfNetworkList;
import com.powsybl.openloadflow.network.impl.Networks;
import com.powsybl.openloadflow.network.impl.OlfBranchResult;
import com.powsybl.openloadflow.network.impl.OlfThreeWindingsTransformerResult;
import com.powsybl.openloadflow.util.LoadFlowAssert;
Expand All @@ -60,6 +62,7 @@
import static com.powsybl.openloadflow.util.LoadFlowAssert.*;
import static java.util.Collections.emptySet;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;

/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
Expand Down Expand Up @@ -3911,4 +3914,87 @@ void testNoMoreVoltageControlledBusTwoBusNetwork() {
assertReactivePowerEquals(0.0, network.getGenerator("G2").getTerminal());
assertVoltageEquals(400.01, network.getBusBreakerView().getBus("B2"));
}

@Test
void testComponentSelectionOneCCtwoSC() {
// Network has one CC with two SC
Network network = HvdcNetworkFactory.createVsc();
LfNetworkList networks = new LfNetworkList(Networks.load(network, new LfNetworkParameters().setComputeMainConnectedComponentOnly(false)));
assertEquals(2, networks.getList().size());

assertEquals(0, networks.getList().get(0).getNumCC());
assertEquals(0, networks.getList().get(0).getNumSC());
assertEquals(0, networks.getList().get(1).getNumCC());
assertEquals(1, networks.getList().get(1).getNumSC());

// Main connected component mode and all connected component mode should yield same result
List<LfNetwork> componentMain = AbstractSecurityAnalysis.getNetworksToSimulate(networks, LoadFlowParameters.ConnectedComponentMode.MAIN);
assertEquals(2, componentMain.size());
assertEquals(0, componentMain.get(0).getNumCC());
assertEquals(0, componentMain.get(0).getNumSC());
assertEquals(0, componentMain.get(1).getNumCC());
assertEquals(1, componentMain.get(1).getNumSC());

List<LfNetwork> componentAll = AbstractSecurityAnalysis.getNetworksToSimulate(networks, LoadFlowParameters.ConnectedComponentMode.ALL);
assertEquals(2, componentAll.size());
assertEquals(0, componentAll.get(0).getNumCC());
assertEquals(0, componentAll.get(0).getNumSC());
assertEquals(0, componentAll.get(1).getNumCC());
assertEquals(1, componentAll.get(1).getNumSC());
}

@Test
void testComponentSelectionTwoCC() {
Network network = FourBusNetworkFactory.createWithTwoScs();
LfNetworkList networks = new LfNetworkList(Networks.load(network, new LfNetworkParameters().setComputeMainConnectedComponentOnly(false)));
assertEquals(2, networks.getList().size());

assertEquals(0, networks.getList().get(0).getNumCC());
assertEquals(0, networks.getList().get(0).getNumSC());
assertEquals(1, networks.getList().get(1).getNumCC());
assertEquals(1, networks.getList().get(1).getNumSC());

// Main connected component mode should only select component associated to main CC
List<LfNetwork> componentMain = AbstractSecurityAnalysis.getNetworksToSimulate(networks, LoadFlowParameters.ConnectedComponentMode.MAIN);
assertEquals(1, componentMain.size());
assertEquals(0, componentMain.get(0).getNumCC());
assertEquals(0, componentMain.get(0).getNumSC());

// All connected component mode should select all component
List<LfNetwork> componentAll = AbstractSecurityAnalysis.getNetworksToSimulate(networks, LoadFlowParameters.ConnectedComponentMode.ALL);
assertEquals(2, componentAll.size());
assertEquals(0, componentAll.get(0).getNumCC());
assertEquals(0, componentAll.get(0).getNumSC());
assertEquals(1, componentAll.get(1).getNumCC());
assertEquals(1, componentAll.get(1).getNumSC());
}

@Test
void testNoCc0Sc0() {
Network network = ConnectedComponentNetworkFactory.createNoCc0Sc0();
var compByBus = network.getBusBreakerView().getBusStream().collect(Collectors.toMap(Identifiable::getId, b -> String.format("CC%d SC%d", b.getConnectedComponent().getNum(), b.getSynchronousComponent().getNum())));
assertEquals(6, compByBus.size());
assertEquals("CC0 SC1", compByBus.get("b01"));
assertEquals("CC0 SC2", compByBus.get("b02"));
assertEquals("CC0 SC3", compByBus.get("b03"));
assertEquals("CC0 SC4", compByBus.get("b04"));
assertEquals("CC1 SC0", compByBus.get("b11"));
assertEquals("CC1 SC0", compByBus.get("b12"));
LoadFlowParameters lfParametersAll = new LoadFlowParameters().setConnectedComponentMode(LoadFlowParameters.ConnectedComponentMode.ALL);
LoadFlowParameters lfParametersMain = new LoadFlowParameters().setConnectedComponentMode(LoadFlowParameters.ConnectedComponentMode.MAIN);
var lfResultAll = LoadFlow.run(network, lfParametersAll);
assertTrue(lfResultAll.isFullyConverged());
var lfResultMain = LoadFlow.run(network, lfParametersMain);
assertTrue(lfResultAll.isFullyConverged());
assertEquals(5, lfResultAll.getComponentResults().size()); // 5 SCs
assertTrue(lfResultMain.isFullyConverged());
assertEquals(4, lfResultMain.getComponentResults().size()); // 4 SCs

var saResultMain = runSecurityAnalysis(network, Collections.emptyList(), createNetworkMonitors(network), lfParametersMain);
assertEquals(LoadFlowResult.ComponentResult.Status.CONVERGED, saResultMain.getPreContingencyResult().getStatus());
assertEquals(4, saResultMain.getPreContingencyResult().getNetworkResult().getBusResults().size()); // 4 buses in CC0
var saResultAll = runSecurityAnalysis(network, Collections.emptyList(), createNetworkMonitors(network), lfParametersAll);
assertEquals(LoadFlowResult.ComponentResult.Status.CONVERGED, saResultAll.getPreContingencyResult().getStatus());
assertEquals(6, saResultAll.getPreContingencyResult().getNetworkResult().getBusResults().size()); // 6 buses in total
}
}

0 comments on commit c1e8dd0

Please sign in to comment.