Skip to content

Commit

Permalink
Support of three windings transformers as variable or function in sen…
Browse files Browse the repository at this point in the history
…sitivity analysis (#654)

Signed-off-by: Bertrand Rix <bertrand.rix@artelys.com>
Signed-off-by: Anne Tilloy <anne.tilloy@rte-france.com>
Signed-off-by: Geoffroy Jamgotchian <geoffroy.jamgotchian@rte-france.com>
Signed-off-by: Florian Dupuy <florian.dupuy@rte-france.com>
  • Loading branch information
obrix authored Jan 18, 2023
1 parent 669de3c commit 49993dc
Show file tree
Hide file tree
Showing 4 changed files with 293 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@
import com.powsybl.openloadflow.network.LfBus;
import com.powsybl.openloadflow.network.LfElement;
import com.powsybl.openloadflow.network.LfNetwork;
import com.powsybl.openloadflow.network.impl.HvdcConverterStations;
import com.powsybl.openloadflow.network.impl.LfDanglingLineBus;
import com.powsybl.openloadflow.network.impl.Networks;
import com.powsybl.openloadflow.network.impl.PropagatedContingency;
import com.powsybl.openloadflow.network.impl.*;
import com.powsybl.openloadflow.network.util.ActivePowerDistribution;
import com.powsybl.openloadflow.network.util.ParticipatingElement;
import com.powsybl.openloadflow.util.PerUnit;
Expand Down Expand Up @@ -231,17 +228,22 @@ public ContingencyContext getContingencyContext() {

@Override
public EquationTerm<V, E> getFunctionEquationTerm() {
LfBranch branch;
switch (functionType) {
case BRANCH_ACTIVE_POWER:
case BRANCH_ACTIVE_POWER_1:
case BRANCH_ACTIVE_POWER_3:
return (EquationTerm<V, E>) ((LfBranch) functionElement).getP1();
case BRANCH_ACTIVE_POWER_2:
return (EquationTerm<V, E>) ((LfBranch) functionElement).getP2();
branch = (LfBranch) functionElement;
return branch instanceof LfLegBranch ? (EquationTerm<V, E>) ((LfBranch) functionElement).getP1() : (EquationTerm<V, E>) ((LfBranch) functionElement).getP2();
case BRANCH_CURRENT:
case BRANCH_CURRENT_1:
case BRANCH_CURRENT_3:
return (EquationTerm<V, E>) ((LfBranch) functionElement).getI1();
case BRANCH_CURRENT_2:
return (EquationTerm<V, E>) ((LfBranch) functionElement).getI2();
branch = (LfBranch) functionElement;
return branch instanceof LfLegBranch ? (EquationTerm<V, E>) ((LfBranch) functionElement).getI1() : (EquationTerm<V, E>) ((LfBranch) functionElement).getI2();
case BUS_VOLTAGE:
return (EquationTerm<V, E>) ((LfBus) functionElement).getCalculatedV();
default:
Expand Down Expand Up @@ -341,6 +343,9 @@ public LfElement getVariableElement() {
public Equation<V, E> getVariableEquation() {
switch (variableType) {
case TRANSFORMER_PHASE:
case TRANSFORMER_PHASE_1:
case TRANSFORMER_PHASE_2:
case TRANSFORMER_PHASE_3:
LfBranch lfBranch = (LfBranch) variableElement;
return ((EquationTerm<V, E>) lfBranch.getA1()).getEquation();
case BUS_TARGET_VOLTAGE:
Expand Down Expand Up @@ -372,7 +377,7 @@ public boolean isVariableInContingency(PropagatedContingency contingency) {
case BUS_TARGET_VOLTAGE:
// a generator or a two windings transformer.
// shunt contingency not supported yet.
// phase shifter in a three windings transformer not supported yet.
// ratio tap changer in a three windings transformer not supported yet.
return contingency.getGeneratorIdsToLose().contains(variableId) || contingency.getBranchIdsToOpen().contains(variableId);
case TRANSFORMER_PHASE:
// a phase shifter on a two windings transformer.
Expand Down Expand Up @@ -516,6 +521,9 @@ static class SingleVariableFactorGroup<V extends Enum<V> & Quantity, E extends E
public void fillRhs(Matrix rhs, Map<LfBus, Double> participationByBus) {
switch (variableType) {
case TRANSFORMER_PHASE:
case TRANSFORMER_PHASE_1:
case TRANSFORMER_PHASE_2:
case TRANSFORMER_PHASE_3:
if (variableEquation.isActive()) {
rhs.set(variableEquation.getColumn(), getIndex(), Math.toRadians(1d));
}
Expand Down Expand Up @@ -859,14 +867,20 @@ public void visitTerminal(Terminal terminal) {
throw new PowsyblException("Injection '" + injectionId + "' not found");
}

private static void checkBranch(Network network, String branchId) {
private static LfBranch checkAndGetBranchOrLeg(Network network, String branchId, SensitivityFunctionType fType, LfNetwork lfNetwork) {
Branch<?> branch = network.getBranch(branchId);
if (branch == null) {
DanglingLine danglingLine = network.getDanglingLine(branchId);
if (danglingLine == null) {
throw new PowsyblException("Branch '" + branchId + "' not found");
}
if (branch != null) {
return lfNetwork.getBranchById(branchId);
}
DanglingLine danglingLine = network.getDanglingLine(branchId);
if (danglingLine != null) {
return lfNetwork.getBranchById(branchId);
}
ThreeWindingsTransformer twt = network.getThreeWindingsTransformer(branchId);
if (twt != null) {
return lfNetwork.getBranchById(LfLegBranch.getId(branchId, getLegNumber(fType)));
}
throw new PowsyblException("Branch, dangling line or leg of '" + branchId + "' not found");
}

private static void checkBus(Network network, String busId, Map<String, Bus> busCache, boolean breakers) {
Expand All @@ -889,6 +903,30 @@ private static void checkPhaseShifter(Network network, String transformerId) {
}
}

private static void checkThreeWindingsTransformerPhaseShifter(Network network, String transformerId, SensitivityVariableType type) {
ThreeWindingsTransformer twt = network.getThreeWindingsTransformer(transformerId);
if (twt == null) {
throw new PowsyblException("Three windings transformer '" + transformerId + "' not found");
}
ThreeWindingsTransformer.Leg l;
switch (type) {
case TRANSFORMER_PHASE_1:
l = twt.getLeg1();
break;
case TRANSFORMER_PHASE_2:
l = twt.getLeg2();
break;
case TRANSFORMER_PHASE_3:
l = twt.getLeg3();
break;
default:
throw new PowsyblException("Three transformer variable type " + type + " cannot be converted to a leg");
}
if (l.getPhaseTapChanger() == null) {
throw new PowsyblException("Three windings transformer '" + transformerId + "' leg on side '" + type + "' has no phase tap changer");
}
}

private static void checkRegulatingTerminal(Network network, String equipmentId) {
Terminal terminal = getEquipmentRegulatingTerminal(network, equipmentId);
if (terminal == null) {
Expand Down Expand Up @@ -958,13 +996,10 @@ public SensitivityFactorHolder<V, E> readAndCheckFactors(Network network, Map<St
int[] factorIndex = new int[1];
factorReader.read((functionType, functionId, variableType, variableId, variableSet, contingencyContext) -> {
if (variableSet) {
if (functionType == SensitivityFunctionType.BRANCH_ACTIVE_POWER
|| functionType == SensitivityFunctionType.BRANCH_ACTIVE_POWER_1
|| functionType == SensitivityFunctionType.BRANCH_ACTIVE_POWER_2) {
checkBranch(network, functionId);
LfBranch branch = lfNetwork.getBranchById(functionId);
LfElement functionElement = branch != null && branch.getBus1() != null && branch.getBus2() != null ? branch : null;
if (isActivePowerFunctionType(functionType)) {
if (variableType == SensitivityVariableType.INJECTION_ACTIVE_POWER) {
LfBranch branch = checkAndGetBranchOrLeg(network, functionId, functionType, lfNetwork);
LfElement functionElement = branch != null && branch.getBus1() != null && branch.getBus2() != null ? branch : null;
Map<LfElement, Double> injectionLfBuses = injectionBusesByVariableId.get(variableId);
Set<String> originalVariableSetIds = originalVariableSetIdsByVariableId.get(variableId);
if (injectionLfBuses == null && originalVariableSetIds == null) {
Expand Down Expand Up @@ -1001,12 +1036,8 @@ public SensitivityFactorHolder<V, E> readAndCheckFactors(Network network, Map<St
throw createFunctionTypeNotSupportedException(functionType);
}
} else {
if ((functionType == SensitivityFunctionType.BRANCH_ACTIVE_POWER ||
functionType == SensitivityFunctionType.BRANCH_ACTIVE_POWER_1 ||
functionType == SensitivityFunctionType.BRANCH_ACTIVE_POWER_2)
&& variableType == SensitivityVariableType.HVDC_LINE_ACTIVE_POWER) {
checkBranch(network, functionId);
LfBranch branch = lfNetwork.getBranchById(functionId);
if (isActivePowerFunctionType(functionType) && variableType == SensitivityVariableType.HVDC_LINE_ACTIVE_POWER) {
LfBranch branch = checkAndGetBranchOrLeg(network, functionId, functionType, lfNetwork);
LfElement functionElement = branch != null && branch.getBus1() != null && branch.getBus2() != null ? branch : null;

HvdcLine hvdcLine = network.getHvdcLine(variableId);
Expand Down Expand Up @@ -1038,37 +1069,28 @@ public SensitivityFactorHolder<V, E> readAndCheckFactors(Network network, Map<St
} else {
LfElement functionElement;
LfElement variableElement;
if (functionType == SensitivityFunctionType.BRANCH_ACTIVE_POWER
|| functionType == SensitivityFunctionType.BRANCH_ACTIVE_POWER_1
|| functionType == SensitivityFunctionType.BRANCH_ACTIVE_POWER_2) {
checkBranch(network, functionId);
LfBranch branch = lfNetwork.getBranchById(functionId);
functionElement = branch != null && branch.getBus1() != null && branch.getBus2() != null ? branch : null;
if (variableType == SensitivityVariableType.INJECTION_ACTIVE_POWER) {
String injectionBusId = getInjectionBusId(network, variableId, breakers);
variableElement = injectionBusId != null ? lfNetwork.getBusById(injectionBusId) : null;
} else if (variableType == SensitivityVariableType.TRANSFORMER_PHASE) {
checkPhaseShifter(network, variableId);
LfBranch twt = lfNetwork.getBranchById(variableId);
variableElement = twt != null && twt.getBus1() != null && twt.getBus2() != null ? twt : null;
} else {
throw createVariableTypeNotSupportedWithFunctionTypeException(variableType, functionType);
}
} else if (functionType == SensitivityFunctionType.BRANCH_CURRENT
|| functionType == SensitivityFunctionType.BRANCH_CURRENT_1
|| functionType == SensitivityFunctionType.BRANCH_CURRENT_2) {
checkBranch(network, functionId);
LfBranch branch = lfNetwork.getBranchById(functionId);
if (isActivePowerFunctionType(functionType) || isCurrentFunctionType(functionType)) {
LfBranch branch = checkAndGetBranchOrLeg(network, functionId, functionType, lfNetwork);
functionElement = branch != null && branch.getBus1() != null && branch.getBus2() != null ? branch : null;
if (variableType == SensitivityVariableType.TRANSFORMER_PHASE) {
checkPhaseShifter(network, variableId);
LfBranch twt = lfNetwork.getBranchById(variableId);
variableElement = twt != null && twt.getBus1() != null && twt.getBus2() != null ? twt : null;
} else if (variableType == SensitivityVariableType.INJECTION_ACTIVE_POWER) {
String injectionBusId = getInjectionBusId(network, variableId, breakers);
variableElement = injectionBusId != null ? lfNetwork.getBusById(injectionBusId) : null;
} else {
throw createVariableTypeNotSupportedWithFunctionTypeException(variableType, functionType);
switch (variableType) {
case INJECTION_ACTIVE_POWER:
String injectionBusId = getInjectionBusId(network, variableId, breakers);
variableElement = injectionBusId != null ? lfNetwork.getBusById(injectionBusId) : null;
break;
case TRANSFORMER_PHASE:
checkPhaseShifter(network, variableId);
LfBranch twt = lfNetwork.getBranchById(variableId);
variableElement = twt != null && twt.getBus1() != null && twt.getBus2() != null ? twt : null;
break;
case TRANSFORMER_PHASE_1:
case TRANSFORMER_PHASE_2:
case TRANSFORMER_PHASE_3:
checkThreeWindingsTransformerPhaseShifter(network, variableId, variableType);
LfBranch leg = lfNetwork.getBranchById(LfLegBranch.getId(variableId, getLegNumber(variableType)));
variableElement = leg != null && leg.getBus1() != null && leg.getBus2() != null ? leg : null;
break;
default:
throw createVariableTypeNotSupportedWithFunctionTypeException(variableType, functionType);
}
} else if (functionType == SensitivityFunctionType.BUS_VOLTAGE) {
checkBus(network, functionId, busCache, breakers);
Expand All @@ -1094,6 +1116,20 @@ public SensitivityFactorHolder<V, E> readAndCheckFactors(Network network, Map<St
return factorHolder;
}

public static boolean isActivePowerFunctionType(SensitivityFunctionType functionType) {
return functionType == SensitivityFunctionType.BRANCH_ACTIVE_POWER
|| functionType == SensitivityFunctionType.BRANCH_ACTIVE_POWER_1
|| functionType == SensitivityFunctionType.BRANCH_ACTIVE_POWER_2
|| functionType == SensitivityFunctionType.BRANCH_ACTIVE_POWER_3;
}

public static boolean isCurrentFunctionType(SensitivityFunctionType functionType) {
return functionType == SensitivityFunctionType.BRANCH_CURRENT
|| functionType == SensitivityFunctionType.BRANCH_CURRENT_1
|| functionType == SensitivityFunctionType.BRANCH_CURRENT_2
|| functionType == SensitivityFunctionType.BRANCH_CURRENT_3;
}

public Pair<Boolean, Boolean> hasBusTargetVoltage(SensitivityFactorReader factorReader, Network network) {
// Left value if we find a BUS_TARGET_VOLTAGE factor and right value if it is linked to a transformer.
AtomicBoolean hasBusTargetVoltage = new AtomicBoolean(false);
Expand Down Expand Up @@ -1130,14 +1166,16 @@ private static <V extends Enum<V> & Quantity, E extends Enum<E> & Quantity> doub
case BRANCH_ACTIVE_POWER:
case BRANCH_ACTIVE_POWER_1:
case BRANCH_ACTIVE_POWER_2:
case BRANCH_ACTIVE_POWER_3:
return PerUnit.SB;
case BRANCH_CURRENT:
case BRANCH_CURRENT_1:
case BRANCH_CURRENT_3:
LfBranch branch = (LfBranch) factor.getFunctionElement();
return PerUnit.ib(branch.getBus1().getNominalV());
case BRANCH_CURRENT_2:
LfBranch branch2 = (LfBranch) factor.getFunctionElement();
return PerUnit.ib(branch2.getBus2().getNominalV());
return branch2 instanceof LfLegBranch ? PerUnit.ib(branch2.getBus1().getNominalV()) : PerUnit.ib(branch2.getBus2().getNominalV());
case BUS_VOLTAGE:
LfBus bus = (LfBus) factor.getFunctionElement();
return bus.getNominalV();
Expand All @@ -1155,12 +1193,15 @@ private static <V extends Enum<V> & Quantity, E extends Enum<E> & Quantity> doub
case INJECTION_ACTIVE_POWER:
return PerUnit.SB;
case TRANSFORMER_PHASE:
case TRANSFORMER_PHASE_1:
case TRANSFORMER_PHASE_2:
case TRANSFORMER_PHASE_3:
return 1; //TODO: radians ?
case BUS_TARGET_VOLTAGE:
LfBus bus = (LfBus) ((SingleVariableLfSensitivityFactor<V, E>) factor).getVariableElement();
return bus.getNominalV();
default:
throw new IllegalArgumentException("Unknown function type " + factor.getFunctionType());
throw new IllegalArgumentException("Unknown variable type " + factor.getVariableType());
}
}

Expand All @@ -1177,4 +1218,33 @@ protected static <V extends Enum<V> & Quantity, E extends Enum<E> & Quantity> do
protected static <V extends Enum<V> & Quantity, E extends Enum<E> & Quantity> double unscaleFunction(LfSensitivityFactor<V, E> factor, double value) {
return value * getFunctionBaseValue(factor);
}

protected static int getLegNumber(SensitivityFunctionType type) {
switch (type) {
case BRANCH_ACTIVE_POWER_1:
case BRANCH_CURRENT_1:
return 1;
case BRANCH_ACTIVE_POWER_2:
case BRANCH_CURRENT_2:
return 2;
case BRANCH_ACTIVE_POWER_3:
case BRANCH_CURRENT_3:
return 3;
default:
throw new PowsyblException("Cannot convert function type " + type + " to a leg number");
}
}

protected static int getLegNumber(SensitivityVariableType type) {
switch (type) {
case TRANSFORMER_PHASE_1:
return 1;
case TRANSFORMER_PHASE_2:
return 2;
case TRANSFORMER_PHASE_3:
return 3;
default:
throw new PowsyblException("Cannot convert variable type " + type + " to a leg number");
}
}
}
Loading

0 comments on commit 49993dc

Please sign in to comment.