Open olperr1 opened 4 months ago
Can use of local dry run replace Rao canBeApplied? yes
Rao canBeApplied was only doing separate equivalent of local dry runs for each of its elementary actions, without taking into account interaction between multiple elementary actions (but most network action have only one elementary action). So local dry run (as describe above) can be used in Rao on each elementary actions to reproduce canBeApplied behavior* (even without using NetworkModificationList) and using NetworkModificationList local dry run or a full dry run will be more precise than actual Rao.
NB. The exception in Rao is the network action SwitchPair elementary action which canBeApplied is not linked to the fact that the modification are applicable and so it will keep is own implementation of canBeApplied in Rao.
*To be exact: canBeApplied was verifying less thinks that the local dry run will, but it was not on purpose so using less permissive local dry run will be better.
Can use of dry run (local or full) can replace Rao hasImpactOnNetwork? no
Local dry run as describe above do not answer this question but we could imagine a similar mechanism than the local dry run that will answer the question of hasImpactOnNetwork by checking if the elements of the network are already in the configuration expected post-modification. It will have the same limitation in case of multiple actions by not saying if one modification cancel a previous one for instance.
Full dry run will not give that information because it return only a boolean, but it computes that information, for instance, if we return the copy of the network on which we applied the modifications we could compare it to the original network to see if there is at least one difference, in that case hasImpactOnNetwork is true.
Update: the full dry run is kept and has to be transferred in a dedicated PR. A new PR should be open to transferred the work done around the local dry run, in changing terminology because the local dry run is more a check than a dry run. Indeed, the user should be aware that in the check method, the treatments couldn't be equivalent as what could be done in a full dry run.
The check must cover a need to know if a remedial action can be applied on a network. But, it seems pertinent to cover also the need to know if a remedial action, that can be applied on a network, has or not a real impact. Doing these two functionalities in a single method leads to performance gain.
See in powsybl-open-rao
, where the needs are located:
/**
* Remedial action interface specifying a direct action on the network.
* <p>
* The Network Action is completely defined by itself.
* It involves a Set of {@link Action}.
* When the apply method is called, a {@link com.powsybl.iidm.modification.NetworkModification}
* is triggered on each of these elementary remedial actions.
*
* @author Joris Mancini {@literal <joris.mancini at rte-france.com>}
* @author Baptiste Seguinot {@literal <baptiste.seguinot at rte-france.com>}
*/
public interface NetworkAction extends RemedialAction<NetworkAction> {
/**
* States if the remedial action would change the current state of the network. It has no impact on the network.
*
* @param network: Network that serves as reference for the impact.
* @return True if the remedial action would have an impact on the network.
*/
boolean hasImpactOnNetwork(final Network network);
we have to look at all implementations and put the equivalent method in powsybl-core
. And
@Override
public boolean canBeApplied(Network network) {
// TODO: To implement on powsybl-core Action
return elementaryActions.stream().allMatch(elementaryAction -> {
if (elementaryAction instanceof ShuntCompensatorPositionAction shuntCompensatorPositionAction) {
ShuntCompensator shuntCompensator = network.getShuntCompensator(shuntCompensatorPositionAction.getShuntCompensatorId());
return shuntCompensatorPositionAction.getSectionCount() <= shuntCompensator.getMaximumSectionCount();
} else if (elementaryAction instanceof GeneratorAction || elementaryAction instanceof LoadAction || elementaryAction instanceof DanglingLineAction) {
return true;
} else if (elementaryAction instanceof PhaseTapChangerTapPositionAction phaseTapChangerTapPositionAction) {
// hypothesis: transformer is a two windings transformer
PhaseTapChanger phaseTapChanger = network.getTwoWindingsTransformer(phaseTapChangerTapPositionAction.getTransformerId()).getPhaseTapChanger();
int tapPosition = phaseTapChangerTapPositionAction.getTapPosition();
return tapPosition >= phaseTapChanger.getLowTapPosition() && tapPosition <= phaseTapChanger.getHighTapPosition();
} else if (elementaryAction instanceof SwitchPair switchPair) {
// It is only applicable if, initially, one switch was closed and the other was open.
return network.getSwitch(switchPair.getSwitchToOpen().getId()).isOpen() != network.getSwitch(switchPair.getSwitchToClose().getId()).isOpen();
} else if (elementaryAction instanceof TerminalsConnectionAction || elementaryAction instanceof SwitchAction) {
return true;
} else {
throw new NotImplementedException();
}
});
}
Describe the current behavior
When applying network modifications to a network, there is no way to know if all of them can be successfully applied prior to applying them.
Describe the expected behavior
We want to add "dry run" capabilities to network modifications. They would allow to check that all the modifications could successfully be applied before their real application.
Describe the motivation
When applying several network modifications, if one of them fails, the network is left in an unknown state: the first modifications where applied but not the ones after the failing one. To return in a stable state, it is necessary to identify the applied modifications and to revert them, which could not be easily done.
Extra Information
Problem description
For simple network modifications, it is easy to check if they could be applied or not. For instance, an
OpeningSwitch
modification could be applied if the switch exists (regardless its previous state). Thus a list of network modifications containing onlyOpeningSwitch
operations could be applied if every single modification could be applied on the network.On the contrary, some modifications can have an impact on the next operations. For instance, if you have a modification removing a switch, it would be applicable if the switch exists… but if it is followed by another modification opening the switch, the application of the whole list of modifications will fail.
Principle
To cover both of these cases, it is proposed to create 2 "dry run" modes:
NetworkModification
;Local dry run
To implement the local dry run, the
NetworkModification.apply(Network, NamingStrategy, boolean, ComputationManager, ReportNode)
method will take an additional parameter:boolean dryRun
and will return aboolean
:dryRun
isfalse
, the method's behavior should be the same as before (the return value should be alwaystrue
if no exception is thrown);dryRun
istrue
:false
;true
;PowsyblException
informing that "This network modification's application cannot be checked with a local dry run".Full dry run
This type is the simplest to implement, but also the most costly. It consists of a single method in
NetworkModificationList
:boolean fullDryRun(Network, NamingStrategy, ComputationManager, ReportNode)
This method should clone the network and call the
NetworkModificationList
'sapply
method with it. If noPowsyblException
is catched, the dry run is a success and the method should returntrue
. Else, It should returnfalse
.Special case of
NetworkModificationList
'sapply
methodAs each
NetworkModification
'sapply
method, the one ofNetworkModificationList
should have the additionalboolean dryRun
parameter and should return a boolean:dryRun
isfalse
, the method's behavior should be the same as before (the return value should be alwaystrue
if no exception is thrown);dryRun
istrue
, the method should run a local dry run on all of its modifications if it is pertinent, or else run the full dry run. In both case, it should return the result of the performed dry run.How to know if a local dry run is pertinent? Each
NetworkModification
should implement 2 new methods (better names can be used):boolean hasImpactOnOtherModifications()
: this method should returntrue
if it may have impact on aNetworkModification
which could be applied after. Typically, it should returntrue
for topological network modifications.boolean isLocalDryRunPossible()
: this method should returntrue
if all the prerequisites of the modification can be checked in the local dry run. Thus:true
, the local dry run should no throw any exception;false
, the local dry run should throw aPowsyblException
.The local dry run could be performed by the
NetworkModificationList
'sapply
method if:isLocalDryRunPossible()
returnstrue
for every modification of the list;hasImpactOnOtherModifications()
returnsfalse
for all the n-1 first modifications of the list, with n being the size of the list (since no modification will be applied after the last one, it doesn't matter if it has a potential impact).