Skip to content

Commit

Permalink
do not throw error when trying to compute a sensitivity outside conne…
Browse files Browse the repository at this point in the history
…cted component

Signed-off-by: Gael Macherel <[email protected]>
  • Loading branch information
Djazouli committed Mar 2, 2021
1 parent 3256305 commit 393137d
Show file tree
Hide file tree
Showing 7 changed files with 319 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@
import com.powsybl.commons.PowsyblException;
import com.powsybl.contingency.ContingencyElement;
import com.powsybl.contingency.ContingencyElementType;
import com.powsybl.iidm.network.Bus;
import com.powsybl.iidm.network.Injection;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.TwoWindingsTransformer;
import com.powsybl.iidm.network.*;
import com.powsybl.loadflow.LoadFlowParameters;
import com.powsybl.math.matrix.DenseMatrix;
import com.powsybl.math.matrix.Matrix;
Expand All @@ -28,10 +25,16 @@
import com.powsybl.openloadflow.network.util.ParticipatingElement;
import com.powsybl.openloadflow.util.PropagatedContingency;
import com.powsybl.sensitivity.SensitivityFactor;
import com.powsybl.sensitivity.SensitivityFunction;
import com.powsybl.sensitivity.SensitivityValue;
import com.powsybl.sensitivity.SensitivityVariable;
import com.powsybl.sensitivity.factors.BranchFlowPerInjectionIncrease;
import com.powsybl.sensitivity.factors.BranchFlowPerLinearGlsk;
import com.powsybl.sensitivity.factors.BranchFlowPerPSTAngle;
import com.powsybl.sensitivity.factors.functions.BranchFlow;
import com.powsybl.sensitivity.factors.variables.InjectionIncrease;
import com.powsybl.sensitivity.factors.variables.LinearGlsk;
import com.powsybl.sensitivity.factors.variables.PhaseTapChangerAngle;
import org.apache.commons.lang3.NotImplementedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -82,7 +85,10 @@ protected static LfBus getInjectionLfBus(Network network, LfNetwork lfNetwork, B
}

protected static LfBus getInjectionLfBus(Network network, LfNetwork lfNetwork, String injectionId) {
Injection<?> injection = getInjection(network, injectionId);
Injection<?> injection = getInjection(network, injectionId, false);
if (injection == null) {
return null;
}
Bus bus = injection.getTerminal().getBusView().getBus();
return lfNetwork.getBusById(bus.getId());
}
Expand All @@ -98,6 +104,12 @@ protected JacobianMatrix createJacobianMatrix(EquationSystem equationSystem, Vol
}

static class LfSensitivityFactor<T extends EquationTerm> {

enum Status {
VALID,
SKIP,
NULL
}
// Wrap factors in specific class to have instant access to their branch, and their equation term
private final SensitivityFactor factor;

Expand All @@ -109,10 +121,12 @@ static class LfSensitivityFactor<T extends EquationTerm> {

private Double predefinedResult = null;

private Double functionReference;
private Double functionReference = 0d;

private Double baseCaseSensitivityValue = Double.NaN; // the sensitivity value without any +1-1 (needs to be recomputed if the stack distribution changes)

private Status status = Status.VALID;

public LfSensitivityFactor(SensitivityFactor factor, LfNetwork lfNetwork, EquationSystem equationSystem, Class<T> clazz) {
this.factor = factor;
if (factor instanceof BranchFlowPerInjectionIncrease) {
Expand All @@ -124,9 +138,14 @@ public LfSensitivityFactor(SensitivityFactor factor, LfNetwork lfNetwork, Equati
} else {
throw new UnsupportedOperationException("Only factors of type BranchFlow are supported");
}
functionLfBranchId = functionLfBranch.getId();
equationTerm = equationSystem.getEquationTerm(SubjectType.BRANCH, functionLfBranch.getNum(), clazz);
functionReference = 0d;
if (functionLfBranch == null) {
status = Status.NULL;
functionLfBranchId = null;
equationTerm = null;
} else {
functionLfBranchId = functionLfBranch.getId();
equationTerm = equationSystem.getEquationTerm(SubjectType.BRANCH, functionLfBranch.getNum(), clazz);
}
}

public static <T extends EquationTerm> LfSensitivityFactor<T> create(SensitivityFactor factor, Network network, LfNetwork lfNetwork, EquationSystem equationSystem, Class<T> clazz) {
Expand Down Expand Up @@ -181,6 +200,14 @@ public void setBaseCaseSensitivityValue(Double baseCaseSensitivityValue) {
this.baseCaseSensitivityValue = baseCaseSensitivityValue;
}

public Status getStatus() {
return status;
}

public void setStatus(Status status) {
this.status = status;
}

public boolean areVariableAndFunctionDisconnected(GraphDecrementalConnectivity<LfBus> connectivity) {
throw new NotImplementedException("areVariableAndFunctionDisconnected should have an override");
}
Expand All @@ -197,6 +224,10 @@ static class LfBranchFlowPerInjectionIncrease<T extends EquationTerm> extends Lf
LfBranchFlowPerInjectionIncrease(SensitivityFactor factor, Network network, LfNetwork lfNetwork, EquationSystem equationSystem, Class<T> clazz) {
super(factor, lfNetwork, equationSystem, clazz);
injectionLfBus = AbstractSensitivityAnalysis.getInjectionLfBus(network, lfNetwork, (BranchFlowPerInjectionIncrease) factor);
if (injectionLfBus == null) {
warnFactor(factor, "Injection '" + factor.getVariable().getId() + "' not found");
setStatus(Status.SKIP);
}
}

@Override
Expand All @@ -222,6 +253,10 @@ static class LfBranchFlowPerPSTAngle<T extends EquationTerm> extends LfSensitivi
LfBranchFlowPerPSTAngle(SensitivityFactor factor, LfNetwork lfNetwork, EquationSystem equationSystem, Class<T> clazz) {
super(factor, lfNetwork, equationSystem, clazz);
phaseTapChangerLfBranch = getPhaseTapChangerLfBranch(lfNetwork, (BranchFlowPerPSTAngle) factor);
if (phaseTapChangerLfBranch == null) {
warnFactor(factor, "Phase shifter '" + factor.getVariable().getId() + "' not found in the network");
setStatus(Status.SKIP);
}
}

@Override
Expand All @@ -243,14 +278,24 @@ static class LfBranchFlowPerLinearGlsk<T extends EquationTerm> extends LfSensiti

LfBranchFlowPerLinearGlsk(SensitivityFactor factor, Network network, LfNetwork lfNetwork, EquationSystem equationSystem, Class<T> clazz) {
super(factor, lfNetwork, equationSystem, clazz);
injectionBuses = ((LinearGlsk) factor.getVariable()).getGLSKs()
.entrySet()
.stream()
.collect(Collectors.toMap(
entry -> AbstractSensitivityAnalysis.getInjectionLfBus(network, lfNetwork, entry.getKey()),
entry -> entry.getValue().doubleValue(),
Double::sum
));
injectionBuses = new HashMap<>();
Map<String, Float> glsk = ((LinearGlsk) factor.getVariable()).getGLSKs();
Collection<String> skippedInjection = new ArrayList<>(glsk.size());
for (String injectionId : glsk.keySet()) {
LfBus lfBus = AbstractSensitivityAnalysis.getInjectionLfBus(network, lfNetwork, injectionId);
if (lfBus == null) {
skippedInjection.add(injectionId);
continue;
}
injectionBuses.put(lfBus, injectionBuses.getOrDefault(lfBus, 0d) + glsk.get(injectionId));
}

if (injectionBuses.isEmpty()) {
warnFactor(factor, "No generator of glsk '" + factor.getVariable().getId() + "' can be found in the network");
setStatus(Status.SKIP);
} else if (!skippedInjection.isEmpty()) {
LOGGER.warn("Injections {} cannot be found for glsk {} and will be ignored", String.join(", ", skippedInjection), factor.getVariable().getId());
}
}

@Override
Expand Down Expand Up @@ -485,6 +530,10 @@ protected <T extends EquationTerm> void setPredefinedResults(Collection<LfSensit
}
}

protected static SensitivityValue createNullValue(LfSensitivityFactor lfFactor) {
return new SensitivityValue(lfFactor.getFactor(), 0, Double.NaN, Double.NaN);
}

protected void rescaleGlsk(List<SensitivityFactorGroup> factorGroups, GraphDecrementalConnectivity<LfBus> connectivity, Integer mainComponentNumber) {
// compute the corresponding injection (with participation) for each factor
for (SensitivityFactorGroup factorGroup : factorGroups) {
Expand All @@ -499,45 +548,56 @@ protected void rescaleGlsk(List<SensitivityFactorGroup> factorGroups, GraphDecre
}
}

public void checkSensitivities(Network network, LfNetwork lfNetwork, List<SensitivityFactor> factors) {
protected static void warnFactor(SensitivityFactor factor, String error) {
LOGGER.warn("Sensitivity factor <{}, {}> will not be computed. Reason: {}", factor.getFunction().getId(), factor.getVariable().getId(), error);
}

private void checkInjectionIncrease(InjectionIncrease injection, Network network) {
getInjection(network, injection.getInjectionId()); // will crash if injection is not found
}

private void checkLinearGlsk(LinearGlsk glsk, Network network) {
glsk.getGLSKs().keySet().forEach(injection -> getInjection(network, injection));
}

private void checkPhaseTapChangerAngle(PhaseTapChangerAngle angle, Network network) {
TwoWindingsTransformer twt = network.getTwoWindingsTransformer(angle.getPhaseTapChangerHolderId());
if (twt == null) {
throw new PowsyblException("Two windings transformer '" + angle.getPhaseTapChangerHolderId() + "' not found");
}
}

private void checkVariable(SensitivityVariable variable, Network network) {
if (variable instanceof InjectionIncrease) {
checkInjectionIncrease((InjectionIncrease) variable, network);
} else if (variable instanceof LinearGlsk) {
checkLinearGlsk((LinearGlsk) variable, network);
} else if (variable instanceof PhaseTapChangerAngle) {
checkPhaseTapChangerAngle((PhaseTapChangerAngle) variable, network);
} else {
throw new PowsyblException("Variable of type " + variable.getClass().getSimpleName() + " is not recognized.");
}
}

private void checkBranchFlow(BranchFlow branchFlow, Network network) {
Branch branch = network.getBranch(branchFlow.getBranchId());
if (branch == null) {
throw new PowsyblException("Branch '" + branchFlow.getBranchId() + "' not found");
}
}

private void checkFunction(SensitivityFunction function, Network network) {
if (function instanceof BranchFlow) {
checkBranchFlow((BranchFlow) function, network);
} else {
throw new PowsyblException("Function of type " + function.getClass().getSimpleName() + " is not recognized.");
}
}

public void checkSensitivities(Network network, List<SensitivityFactor> factors) {
for (SensitivityFactor<?, ?> factor : factors) {
LfBranch monitoredBranch;
if (factor instanceof BranchFlowPerInjectionIncrease) {
BranchFlowPerInjectionIncrease injectionFactor = (BranchFlowPerInjectionIncrease) factor;
getInjection(network, injectionFactor.getVariable().getInjectionId()); // will crash if injection is not found
if (lfNetwork.getBranchById(factor.getFunction().getId()) == null) {
throw new PowsyblException("Branch '" + factor.getFunction().getId() + "' not found");
}
monitoredBranch = lfNetwork.getBranchById(injectionFactor.getFunction().getBranchId());
} else if (factor instanceof BranchFlowPerPSTAngle) {
BranchFlowPerPSTAngle pstAngleFactor = (BranchFlowPerPSTAngle) factor;
String phaseTapChangerHolderId = pstAngleFactor.getVariable().getPhaseTapChangerHolderId();
TwoWindingsTransformer twt = network.getTwoWindingsTransformer(phaseTapChangerHolderId);
if (twt == null) {
throw new PowsyblException("Phase shifter '" + phaseTapChangerHolderId + "' not found in the network");
}
if (lfNetwork.getBranchById(factor.getFunction().getId()) == null) {
throw new PowsyblException("Branch '" + factor.getFunction().getId() + "' not found");
}
monitoredBranch = lfNetwork.getBranchById(pstAngleFactor.getFunction().getBranchId());
} else if (factor instanceof BranchFlowPerLinearGlsk) {
BranchFlowPerLinearGlsk glskFactor = (BranchFlowPerLinearGlsk) factor;
if (glskFactor.getVariable().getGLSKs().isEmpty()) {
throw new PowsyblException("The glsk '" + factor.getVariable().getId() + "' cannot be empty");
}
for (Map.Entry<String, Float> injectionEntry : glskFactor.getVariable().getGLSKs().entrySet()) {
getInjection(network, injectionEntry.getKey()); // will crash if the injection is not found
}
if (lfNetwork.getBranchById(factor.getFunction().getId()) == null) {
throw new PowsyblException("Branch '" + factor.getFunction().getId() + "' not found");
}
monitoredBranch = lfNetwork.getBranchById(glskFactor.getFunction().getBranchId());
} else {
throw new PowsyblException("Only sensitivity factors of type BranchFlowPerInjectionIncrease and BranchFlowPerPSTAngle are yet supported");
}
if (monitoredBranch == null) {
throw new PowsyblException("Monitored branch " + factor.getFunction().getId() + " not found in the network");
}
checkVariable(factor.getVariable(), network);
checkFunction(factor.getFunction(), network);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public Pair<List<SensitivityValue>, Map<String, List<SensitivityValue>>> analyse
List<LfNetwork> lfNetworks = LfNetwork.load(network, new LfNetworkParameters(lfParametersExt.getSlackBusSelector(), false, true, lfParameters.isTwtSplitShuntAdmittance(), false, lfParametersExt.getPlausibleActivePowerLimit(), false));
LfNetwork lfNetwork = lfNetworks.get(0);
checkContingencies(lfNetwork, contingencies);
checkSensitivities(network, lfNetwork, factors);
checkSensitivities(network, factors);
checkLoadFlowParameters(lfParameters);
Map<Contingency, Collection<String>> propagatedContingencyMap = contingencies.stream().collect(
Collectors.toMap(PropagatedContingency::getContingency, contingency -> new HashSet<>(contingency.getBranchIdsToOpen()))
Expand All @@ -145,12 +145,13 @@ public Pair<List<SensitivityValue>, Map<String, List<SensitivityValue>>> analyse
engine.run();

List<LfSensitivityFactor<ClosedBranchSide1ActiveFlowEquationTerm>> lfFactors = factors.stream().map(factor -> LfSensitivityFactor.create(factor, network, lfNetwork, engine.getEquationSystem(), ClosedBranchSide1ActiveFlowEquationTerm.class)).collect(Collectors.toList());
List<LfSensitivityFactor<ClosedBranchSide1ActiveFlowEquationTerm>> nullFactors = lfFactors.stream().filter(factor -> factor.getStatus().equals(LfSensitivityFactor.Status.NULL)).collect(Collectors.toList());
lfFactors = lfFactors.stream().filter(factor -> factor.getStatus().equals(LfSensitivityFactor.Status.VALID)).collect(Collectors.toList());
List<SensitivityValue> baseValues = new ArrayList<>(nullFactors.size() + lfFactors.size());
baseValues.addAll(nullFactors.stream().map(AbstractSensitivityAnalysis::createNullValue).collect(Collectors.toList()));

// index factors by variable group to compute a minimal number of states
List<SensitivityFactorGroup> factorGroups = createFactorGroups(network, lfFactors);
if (factorGroups.isEmpty()) {
return Pair.of(Collections.emptyList(), Collections.emptyMap());
}

// compute the participation for each injection factor (+1 on the injection and then -participation factor on all
// buses that contain elements participating to slack distribution
Expand All @@ -168,8 +169,6 @@ public Pair<List<SensitivityValue>, Map<String, List<SensitivityValue>>> analyse
}
computeInjectionFactors(slackParticipationByBus, factorGroups);

List<SensitivityValue> baseValues;

// we make the assumption that we ran a loadflow before, and thus this jacobian is the right one
try (JacobianMatrix j = createJacobianMatrix(engine.getEquationSystem(), new PreviousValueVoltageInitializer())) {
// otherwise, defining the rhs matrix will result in integer overflow
Expand All @@ -182,7 +181,7 @@ public Pair<List<SensitivityValue>, Map<String, List<SensitivityValue>>> analyse

// calculate sensitivity values
setReferenceActivePowerFlows(lfFactors);
baseValues = calculateSensitivityValues(factorGroups, factorsStates);
baseValues.addAll(calculateSensitivityValues(factorGroups, factorsStates));
}

GraphDecrementalConnectivity<LfBus> connectivity = lfNetwork.createDecrementalConnectivity();
Expand All @@ -199,8 +198,10 @@ public Pair<List<SensitivityValue>, Map<String, List<SensitivityValue>>> analyse
lfFactors.stream()
.filter(lfFactor -> lfContingency.getBranches().contains(lfFactor.getFunctionLfBranch()))
.forEach(lfFactor -> lfFactor.setPredefinedResult(0d));
contingenciesValues.put(lfContingency.getContingency().getId(),
getPostContingencySensitivityValues(lfFactors, lfContingency, lfNetwork, engine, factorGroups, lfParameters, lfParametersExt));
List<SensitivityValue> contingencyValues = new ArrayList<>(nullFactors.size() + lfFactors.size());
contingencyValues.addAll(nullFactors.stream().map(AbstractSensitivityAnalysis::createNullValue).collect(Collectors.toList()));
contingencyValues.addAll(getPostContingencySensitivityValues(lfFactors, lfContingency, lfNetwork, engine, factorGroups, lfParameters, lfParametersExt));
contingenciesValues.put(lfContingency.getContingency().getId(), contingencyValues);
BusState.restoreBusStates(busStates);
}

Expand Down Expand Up @@ -231,8 +232,10 @@ public Pair<List<SensitivityValue>, Map<String, List<SensitivityValue>>> analyse

computeInjectionFactors(slackParticipationByBusForThisConnectivity, factorGroups);

contingenciesValues.put(lfContingency.getContingency().getId(),
getPostContingencySensitivityValues(lfFactors, lfContingency, lfNetwork, engine, factorGroups, lfParameters, lfParametersExt));
List<SensitivityValue> contingencyValues = new ArrayList<>(nullFactors.size() + lfFactors.size());
contingencyValues.addAll(nullFactors.stream().map(AbstractSensitivityAnalysis::createNullValue).collect(Collectors.toList()));
contingencyValues.addAll(getPostContingencySensitivityValues(lfFactors, lfContingency, lfNetwork, engine, factorGroups, lfParameters, lfParametersExt));
contingenciesValues.put(lfContingency.getContingency().getId(), contingencyValues);
BusState.restoreBusStates(busStates);

connectivity.reset();
Expand Down
Loading

0 comments on commit 393137d

Please sign in to comment.