Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AC Security Analysis with operator strategies #590

Merged
merged 61 commits into from
Oct 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
ea07d2d
Support multiple add and remove of the same edge in connectivity
geofjamg Aug 24, 2022
3dcf4b6
Fix unit test
geofjamg Aug 24, 2022
bb753a2
Fix comment
geofjamg Aug 24, 2022
eb55d67
new API
flo-dup Jul 27, 2022
9c61ead
Adapt MinimumSpanningTreeConnectivity to new API
flo-dup Jul 27, 2022
9f10f61
Fix implementation and connectivity calls
flo-dup Jul 29, 2022
79949cf
Always check before calling reset that some modifications were made
flo-dup Aug 3, 2022
14a066f
Fix reset
flo-dup Aug 4, 2022
38ddfa7
Replace save/reset mechanism by startTmpChanges/undoTmpChanges mechanism
flo-dup Aug 4, 2022
c4e727d
Save work.
annetill Aug 17, 2022
5c7c2cf
Fix some code smells.
annetill Aug 17, 2022
f94e2e1
Support a list of actions for an operator strategy.
annetill Aug 17, 2022
469648a
Fix bug.
annetill Aug 17, 2022
973ab64
Add unit test.
annetill Aug 17, 2022
12c68da
Add unit test.
annetill Aug 17, 2022
8cacc54
Add unit test.
annetill Aug 17, 2022
d308bd3
Fix merge
geofjamg Aug 17, 2022
33da158
Increase coverage.
annetill Aug 18, 2022
bddb21a
Fix code smells.
annetill Aug 18, 2022
1b36f58
Cleanup
geofjamg Aug 18, 2022
fb97b1d
Cleanup
geofjamg Aug 18, 2022
5940385
Apply review comments.
annetill Aug 19, 2022
5e04f88
Fixes after review.
annetill Aug 19, 2022
f37978f
Clean
geofjamg Aug 26, 2022
185ae3e
Remove workaround
geofjamg Aug 26, 2022
bf89e63
Refactoring
geofjamg Aug 26, 2022
4781777
Merge branch 'main' into try-as-with-actions-2
annetill Sep 2, 2022
2f4b49c
Fixes after review.
annetill Sep 2, 2022
10d28f5
Increase coverage and fixes.
annetill Sep 2, 2022
6065c26
Merge.
annetill Sep 15, 2022
01ef28b
Merge branch 'main' into try-as-with-actions-2
annetill Sep 16, 2022
5e75f63
Merge branch 'main' into try-as-with-actions-2
geofjamg Sep 30, 2022
ae7241a
Merge branch 'main' into try-as-with-actions-2
annetill Oct 3, 2022
c902c32
Fix checkstyle.
annetill Oct 4, 2022
f0f3b99
Merge branch 'main' into try-as-with-actions-2
annetill Oct 4, 2022
beeaef0
Clean action connectivity.
annetill Oct 4, 2022
bde6467
Clean
geofjamg Oct 4, 2022
914a1a5
Merge branch 'main' into try-as-with-actions-2
annetill Oct 7, 2022
69db0bf
Support of several operator strategies by contingency.
annetill Oct 13, 2022
0c6507c
Add Metrix tutorial.
annetill Oct 13, 2022
2b87a24
Continue Metrix tutorial.
annetill Oct 13, 2022
7b941a1
Clean.
annetill Oct 13, 2022
7db0284
Save.
annetill Oct 14, 2022
f1bc076
Fix code smells.
annetill Oct 14, 2022
e104e73
Clean.
annetill Oct 14, 2022
a4f72f4
Fix code smell.
annetill Oct 14, 2022
0d17aff
Merge branch 'main' into try-as-with-actions-2
geofjamg Oct 14, 2022
a5106c4
Refactoring
geofjamg Oct 14, 2022
e2885fa
Refactoring
geofjamg Oct 14, 2022
d1f79db
Fix initial topo restoration
geofjamg Oct 14, 2022
1d5aafe
Clean
geofjamg Oct 14, 2022
496635b
Clean
geofjamg Oct 14, 2022
3b281fa
Clean
geofjamg Oct 14, 2022
d0d15d5
Improve unit test.
annetill Oct 17, 2022
f73596a
Merge branch 'try-as-with-actions-2' of https://github.com/powsybl/po…
annetill Oct 17, 2022
322ff56
Fix indentation.
annetill Oct 17, 2022
f687551
Clean.
annetill Oct 17, 2022
4ce609d
Merge.
annetill Oct 18, 2022
fb670ca
Try to fix open lines.
annetill Oct 18, 2022
0247979
Force naive algo in case of operator stategies
geofjamg Oct 18, 2022
6acd8ff
Fix PreviousValueVoltageInitializer
geofjamg Oct 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@
import com.powsybl.openloadflow.network.LfHvdc;

import java.util.List;
import java.util.Objects;

/**
* @author Anne Tilloy <anne.tilloy at rte-france.com>
*/
public abstract class AbstractHvdcAcEmulationFlowEquationTerm extends AbstractNamedEquationTerm<AcVariableType, AcEquationType> {

protected final LfHvdc hvdc;

protected final Variable<AcVariableType> ph1Var;

protected final Variable<AcVariableType> ph2Var;
Expand All @@ -30,17 +33,16 @@ public abstract class AbstractHvdcAcEmulationFlowEquationTerm extends AbstractNa

protected final double p0;

protected final LfHvdc hvdc;

protected final double lossFactor1;

protected final double lossFactor2;

protected AbstractHvdcAcEmulationFlowEquationTerm(LfHvdc hvdc, LfBus bus1, LfBus bus2, VariableSet<AcVariableType> variableSet) {
super(!Objects.requireNonNull(hvdc).isDisabled());
this.hvdc = hvdc;
ph1Var = variableSet.getVariable(bus1.getNum(), AcVariableType.BUS_PHI);
ph2Var = variableSet.getVariable(bus2.getNum(), AcVariableType.BUS_PHI);
variables = List.of(ph1Var, ph2Var);
this.hvdc = hvdc;
k = hvdc.getDroop() * 180 / Math.PI;
p0 = hvdc.getP0();
lossFactor1 = hvdc.getConverterStation1().getLossFactor() / 100;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public abstract class AbstractShuntCompensatorEquationTerm extends AbstractNamed
protected final Variable<AcVariableType> vVar;

protected AbstractShuntCompensatorEquationTerm(LfShunt shunt, LfBus bus, VariableSet<AcVariableType> variableSet) {
this.shunt = Objects.requireNonNull(shunt);
super(!Objects.requireNonNull(shunt).isDisabled());
this.shunt = shunt;
Objects.requireNonNull(bus);
Objects.requireNonNull(variableSet);
vVar = variableSet.getVariable(bus.getNum(), AcVariableType.BUS_V);
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public abstract class AbstractBranchEquationTerm<V extends Enum<V> & Quantity, E
protected final LfBranch branch;

protected AbstractBranchEquationTerm(LfBranch branch) {
this.branch = Objects.requireNonNull(branch);
super(!Objects.requireNonNull(branch).isDisabled());
this.branch = branch;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public abstract class AbstractBusEquationTerm<V extends Enum<V> & Quantity, E ex
protected final LfBus bus;

protected AbstractBusEquationTerm(LfBus bus) {
this.bus = Objects.requireNonNull(bus);
super(!Objects.requireNonNull(bus).isDisabled());
this.bus = bus;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,20 @@ public abstract class AbstractEquationTerm<V extends Enum<V> & Quantity, E exten

private Equation<V, E> equation;

private boolean active = true;
private boolean active;

protected StateVector sv;

protected EquationTerm<V, E> self = this;

protected AbstractEquationTerm() {
this(true);
}

protected AbstractEquationTerm(boolean active) {
this.active = active;
}

@Override
public void setStateVector(StateVector sv) {
this.sv = Objects.requireNonNull(sv);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
*/
public abstract class AbstractNamedEquationTerm<V extends Enum<V> & Quantity, E extends Enum<E> & Quantity> extends AbstractEquationTerm<V, E> {

protected AbstractNamedEquationTerm(boolean active) {
super(active);
}

protected abstract String getName();

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ public boolean isActive() {
return active;
}

public void setActive(boolean active) {
public Equation<V, E> setActive(boolean active) {
if (active != this.active) {
this.active = active;
equationSystem.notifyEquationChange(this, active ? EquationEventType.EQUATION_ACTIVATED : EquationEventType.EQUATION_DEACTIVATED);
}
return this;
}

public Equation<V, E> addTerm(EquationTerm<V, E> term) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import com.powsybl.commons.PowsyblException;
import com.powsybl.openloadflow.network.ElementType;
import com.powsybl.openloadflow.network.LfElement;
import com.powsybl.openloadflow.network.LfNetwork;
import org.apache.commons.lang3.tuple.Pair;

Expand Down Expand Up @@ -101,6 +102,21 @@ public <T extends EquationTerm<V, E>> T getEquationTerm(ElementType elementType,
.orElseThrow(() -> new PowsyblException("Equation term not found"));
}

public Equation<V, E> createEquation(LfElement element, E type) {
Objects.requireNonNull(element);
Objects.requireNonNull(type);
if (element.getType() != type.getElementType()) {
throw new PowsyblException("Incorrect equation type: " + type);
}
Pair<Integer, E> p = Pair.of(element.getNum(), type);
Equation<V, E> equation = equations.get(p);
if (equation == null) {
equation = addEquation(p)
.setActive(!element.isDisabled());
}
return equation;
}

public Equation<V, E> createEquation(int num, E type) {
Pair<Integer, E> p = Pair.of(num, type);
Equation<V, E> equation = equations.get(p);
Expand Down
24 changes: 18 additions & 6 deletions src/main/java/com/powsybl/openloadflow/network/BranchState.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,21 @@
*/
public class BranchState extends ElementState<LfBranch> {

private final double a1;
private final double r1;
private double a1 = Double.NaN;
private double r1 = Double.NaN;
private final boolean phaseControlEnabled;
private final boolean voltageControlEnabled;
private Integer tapPosition;

public BranchState(LfBranch branch) {
super(branch);
PiModel piModel = branch.getPiModel();
a1 = piModel.getA1();
r1 = piModel.getR1();
if (piModel instanceof PiModelArray) {
tapPosition = piModel.getTapPosition();
} else {
a1 = piModel.getA1();
r1 = piModel.getR1();
}
phaseControlEnabled = branch.isPhaseControlEnabled();
voltageControlEnabled = branch.isVoltageControlEnabled();
}
Expand All @@ -29,8 +34,15 @@ public BranchState(LfBranch branch) {
public void restore() {
super.restore();
PiModel piModel = element.getPiModel();
piModel.setA1(a1);
piModel.setR1(r1);
if (tapPosition != null) {
piModel.setTapPosition(tapPosition);
}
if (!Double.isNaN(a1)) {
piModel.setA1(a1);
}
if (!Double.isNaN(r1)) {
piModel.setR1(r1);
}
element.setPhaseControlEnabled(phaseControlEnabled);
element.setVoltageControlEnabled(voltageControlEnabled);
}
Expand Down
190 changes: 190 additions & 0 deletions src/main/java/com/powsybl/openloadflow/network/LfAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/**
* Copyright (c) 2022, RTE (http://www.rte-france.com)
* 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/.
*/
package com.powsybl.openloadflow.network;

import com.powsybl.commons.PowsyblException;
import com.powsybl.openloadflow.graph.GraphConnectivity;
import com.powsybl.security.action.Action;
import com.powsybl.security.action.LineConnectionAction;
import com.powsybl.security.action.PhaseTapChangerTapPositionAction;
import com.powsybl.security.action.SwitchAction;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
* @author Anne Tilloy <anne.tilloy at rte-france.com>
*/
public class LfAction {

private static final class TapPositionChange {

private final LfBranch branch;

private final int value;

private final boolean relative;

private TapPositionChange(LfBranch branch, int value, boolean relative) {
this.branch = Objects.requireNonNull(branch);
this.value = value;
this.relative = relative;
}

public LfBranch getBranch() {
return branch;
}

public int getValue() {
return value;
}

public boolean isRelative() {
return relative;
}
}

private final String id;

private LfBranch disabledBranch; // switch to open

private LfBranch enabledBranch; // switch to close

private TapPositionChange tapPositionChange;

public LfAction(Action action, LfNetwork network) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the plan here is to support a list of action and that LfAction will be the sum/result of PowSyBl Core actions for the current strategy?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No: we keep a list of LfAction for an operator strategy. I am not able to do better...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When all design issues will be solved it should be easy to support

this.id = Objects.requireNonNull(action.getId());
Objects.requireNonNull(network);
LfBranch branch;
switch (action.getType()) {
case SwitchAction.NAME:
SwitchAction switchAction = (SwitchAction) action;
branch = network.getBranchById(switchAction.getSwitchId());
checkBranch(branch, switchAction.getSwitchId());
if (switchAction.isOpen()) {
disabledBranch = branch;
} else {
enabledBranch = branch;
}
break;
case LineConnectionAction.NAME:
LineConnectionAction lineConnectionAction = (LineConnectionAction) action;
branch = network.getBranchById(lineConnectionAction.getLineId());
checkBranch(branch, lineConnectionAction.getLineId());
if (lineConnectionAction.isOpenSide1() && lineConnectionAction.isOpenSide2()) {
disabledBranch = branch;
} else {
throw new UnsupportedOperationException("Line connection action: only open line at both sides is supported yet.");
}
break;
case PhaseTapChangerTapPositionAction.NAME:
PhaseTapChangerTapPositionAction phaseTapChangerTapPositionAction = (PhaseTapChangerTapPositionAction) action;
branch = network.getBranchById(phaseTapChangerTapPositionAction.getTransformerId()); // only two windings transformer for the moment.
checkBranch(branch, phaseTapChangerTapPositionAction.getTransformerId()); // how to check that it is really a phase tap changer?
if (branch.getPiModel() instanceof SimplePiModel) {
throw new UnsupportedOperationException("Phase tap changer tap connection action: only one tap in the branch {" + phaseTapChangerTapPositionAction.getTransformerId() + "}");
} else {
tapPositionChange = new TapPositionChange(branch, phaseTapChangerTapPositionAction.getValue(), phaseTapChangerTapPositionAction.isRelativeValue());
}
break;
default:
throw new UnsupportedOperationException("Unsupported action type: " + action.getType());
}
}

public String getId() {
return id;
}

public LfBranch getDisabledBranch() {
return disabledBranch;
}

public LfBranch getEnabledBranch() {
return enabledBranch;
}

public static void apply(List<LfAction> actions, LfNetwork network, LfContingency contingency) {
Objects.requireNonNull(actions);
Objects.requireNonNull(network);

// first process connectivity part of actions
updateConnectivity(actions, network, contingency);

// then process remaining changes of actions
for (LfAction action : actions) {
action.apply();
}
}

private static void updateConnectivity(List<LfAction> actions, LfNetwork network, LfContingency contingency) {
GraphConnectivity<LfBus, LfBranch> connectivity = network.getConnectivity();

// re-update connectivity according to post contingency state (revert after LfContingency apply)
connectivity.startTemporaryChanges();
contingency.getDisabledBranches().forEach(connectivity::removeEdge);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we support a bus contingency (bus/bar section or bus from a bus/breaker topology)? If one day yes, we also have to remove the disabled buses.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, we should add it now to not forget it later


// update connectivity according to post action state
connectivity.startTemporaryChanges();
for (LfAction action : actions) {
action.updateConnectivity(connectivity);
}

// add to action description buses and branches that won't be part of the main connected
// component in post action state.
Set<LfBus> removedBuses = connectivity.getVerticesRemovedFromMainComponent();
removedBuses.forEach(bus -> bus.setDisabled(true));
Set<LfBranch> removedBranches = new HashSet<>(connectivity.getEdgesRemovedFromMainComponent());
// we should manage branches open at one side.
for (LfBus bus : removedBuses) {
bus.getBranches().stream().filter(b -> !b.isConnectedAtBothSides()).forEach(removedBranches::add);
}
removedBranches.forEach(branch -> branch.setDisabled(true));

// add to action description buses and branches that will be part of the main connected
// component in post action state.
Set<LfBus> addedBuses = connectivity.getVerticesAddedToMainComponent();
addedBuses.forEach(bus -> bus.setDisabled(false));
Set<LfBranch> addedBranches = new HashSet<>(connectivity.getEdgesAddedToMainComponent());
// we should manage branches open at one side.
for (LfBus bus : addedBuses) {
bus.getBranches().stream().filter(b -> !b.isConnectedAtBothSides()).forEach(addedBranches::add);
}
addedBranches.forEach(branch -> branch.setDisabled(false));

// reset connectivity to discard post contingency connectivity and post action connectivity
connectivity.undoTemporaryChanges();
connectivity.undoTemporaryChanges();
}

public void updateConnectivity(GraphConnectivity<LfBus, LfBranch> connectivity) {
if (disabledBranch != null && disabledBranch.getBus1() != null && disabledBranch.getBus2() != null) {
connectivity.removeEdge(disabledBranch);
}
if (enabledBranch != null) {
connectivity.addEdge(enabledBranch.getBus1(), enabledBranch.getBus2(), enabledBranch);
}
}

public void apply() {
if (tapPositionChange != null) {
LfBranch branch = tapPositionChange.getBranch();
int tapPosition = branch.getPiModel().getTapPosition();
int value = tapPositionChange.getValue();
int newTapPosition = tapPositionChange.isRelative() ? tapPosition + value : value;
branch.getPiModel().setTapPosition(newTapPosition);
}
}

private static void checkBranch(LfBranch branch, String branchId) {
if (branch == null) {
throw new PowsyblException("Branch " + branchId + " not found in the network");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ public GraphConnectivity<LfBus, LfBranch> getConnectivity() {
getBranches().stream()
.filter(b -> b.getBus1() != null && b.getBus2() != null)
.forEach(b -> connectivity.addEdge(b.getBus1(), b.getBus2(), b));
connectivity.setMainComponentVertex(getSlackBus());
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@flo-dup can you please just take a look at this change and tell us if it is okay for you. Thanks!

}
return connectivity;
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/powsybl/openloadflow/network/PiModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,8 @@ enum AllowedDirection {
boolean setMinZ(double minZ, boolean dc);

void setBranch(LfBranch branch);

int getTapPosition();

PiModel setTapPosition(int tapPosition);
}
Loading