Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -7,7 +7,12 @@

package com.powsybl.openrao.data.crac.api.rangeaction;

import com.powsybl.action.Action;
import com.powsybl.iidm.network.Country;
import com.powsybl.iidm.network.Network;
import com.powsybl.openrao.commons.OpenRaoException;

import java.util.Set;

/**
* @author Gabriel Plante {@literal <gabriel.plante_externe at rte-france.com>}
Expand All @@ -23,4 +28,9 @@ public interface CounterTradeRangeAction extends StandardRangeAction<CounterTrad
* Get the importing country
*/
Country getImportingCountry();

@Override
default Set<Action> toActions(double setPoint, Network network) {
throw new OpenRaoException("toActions is not implemented for CounterTradeRangeActions.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@

package com.powsybl.openrao.data.crac.api.rangeaction;

import com.powsybl.action.Action;
import com.powsybl.action.HvdcAction;
import com.powsybl.action.HvdcActionBuilder;
import com.powsybl.openrao.data.crac.api.NetworkElement;
import com.powsybl.iidm.network.Network;

import java.util.Set;

/**
* A range action interface specifying an action on a HVDC
*
Expand All @@ -26,4 +31,18 @@ public interface HvdcRangeAction extends StandardRangeAction<HvdcRangeAction> {
boolean isAngleDroopActivePowerControlEnabled(Network network);

void setInitialSetpoint(double initialSetpoint);

@Override
default Set<Action> toActions(double setPoint, Network network) {
return Set.of(toAction(setPoint));
}

default HvdcAction toAction(double setPoint) {
return new HvdcActionBuilder()
.withId("%s@%s".formatted(getId(), setPoint))
.withRelativeValue(false)
.withHvdcId(getNetworkElement().getId())
.withActivePowerSetpoint(setPoint)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,19 @@

package com.powsybl.openrao.data.crac.api.rangeaction;

import com.powsybl.action.Action;
import com.powsybl.action.GeneratorActionBuilder;
import com.powsybl.action.LoadActionBuilder;
import com.powsybl.iidm.network.Generator;
import com.powsybl.iidm.network.Identifiable;
import com.powsybl.iidm.network.Load;
import com.powsybl.iidm.network.Network;
import com.powsybl.openrao.commons.OpenRaoException;
import com.powsybl.openrao.data.crac.api.NetworkElement;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
* A range action interface specifying an action on one or several Injections
Expand Down Expand Up @@ -40,4 +50,36 @@ public interface InjectionRangeAction extends StandardRangeAction<InjectionRange
* is impacted by a change of setpoint of the RangeAction
*/
Map<NetworkElement, Double> getInjectionDistributionKeys();

@Override
default Set<Action> toActions(double setPoint, Network network) {
Set<Action> actions = new HashSet<>();
getInjectionDistributionKeys().forEach((networkElement, distributionKey) -> {
Identifiable<?> identifiable = network.getIdentifiable(networkElement.getId());
if (identifiable instanceof Generator generator) {
double injectionSetPoint = setPoint * getInjectionDistributionKeys().get(networkElement);
actions.add(
new GeneratorActionBuilder()
.withId("%s::%s@%s".formatted(getId(), identifiable.getId(), injectionSetPoint))
.withActivePowerValue(injectionSetPoint)
.withGeneratorId(generator.getId())
.withActivePowerRelativeValue(false)
.build()
);
} else if (identifiable instanceof Load load) {
double injectionSetPoint = Math.abs(setPoint * getInjectionDistributionKeys().get(networkElement));
actions.add(
new LoadActionBuilder()
.withId("%s::%s@%s".formatted(getId(), identifiable.getId(), injectionSetPoint))
.withActivePowerValue(injectionSetPoint)
.withLoadId(load.getId())
.withRelativeValue(false)
.build()
);
} else {
throw new OpenRaoException("Network element '%s' is neither a generator nor a load.".formatted(networkElement.getId()));
}
});
return actions;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@

package com.powsybl.openrao.data.crac.api.rangeaction;

import com.powsybl.action.Action;
import com.powsybl.action.PhaseTapChangerTapPositionAction;
import com.powsybl.openrao.data.crac.api.NetworkElement;
import com.powsybl.openrao.data.crac.api.range.TapRange;
import com.powsybl.iidm.network.Network;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* A range action interface specifying an action on a PST
Expand Down Expand Up @@ -72,4 +75,13 @@ public interface PstRangeAction extends RangeAction<PstRangeAction> {
* Integrity check for angle
*/
void checkAngle(double angle);

@Override
default Set<Action> toActions(double setPoint, Network network) {
return Set.of(toAction(convertAngleToTap(setPoint)));
}

default PhaseTapChangerTapPositionAction toAction(int tapPosition) {
return new PhaseTapChangerTapPositionAction("%s@%s".formatted(getId(), tapPosition), getNetworkElement().getId(), false, tapPosition);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@

package com.powsybl.openrao.data.crac.api.rangeaction;

import com.powsybl.action.Action;
import com.powsybl.openrao.data.crac.api.RemedialAction;
import com.powsybl.openrao.data.crac.api.networkaction.NetworkAction;
import com.powsybl.iidm.network.Network;

import java.util.Optional;
import java.util.Set;

/**
* Remedial action interface specifying an action of type range.
Expand Down Expand Up @@ -70,4 +72,6 @@ default double getTotalCostForVariation(Double variation) {
double variationCost = getVariationCost(variation > 0 ? VariationDirection.UP : VariationDirection.DOWN).orElse(0.) * Math.abs(variation);
return activationCost + variationCost;
}

Set<Action> toActions(double setPoint, Network network);
}
29 changes: 29 additions & 0 deletions data/rao-result/rao-result-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
<artifactId>open-rao-crac-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-security-analysis-api</artifactId>
<version>${powsybl.core.version}</version>
</dependency>

<!-- Test dependencies -->
<dependency>
Expand All @@ -38,6 +43,30 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-iidm-impl</artifactId>
<version>${powsybl.core.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-iidm-serde</artifactId>
<version>${powsybl.core.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>open-rao-crac-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>open-rao-crac-io-json</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2026, 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.openrao.data.raoresult.api;

import com.powsybl.action.Action;
import com.powsybl.action.ActionList;
import com.powsybl.contingency.Contingency;
import com.powsybl.contingency.ContingencyContext;
import com.powsybl.iidm.network.Network;
import com.powsybl.openrao.data.crac.api.Crac;
import com.powsybl.openrao.data.crac.api.Instant;
import com.powsybl.openrao.data.crac.api.State;
import com.powsybl.security.condition.Condition;
import com.powsybl.security.condition.TrueCondition;
import com.powsybl.security.strategy.ConditionalActions;
import com.powsybl.security.strategy.OperatorStrategy;
import com.powsybl.security.strategy.OperatorStrategyList;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @author Thomas Bouquet {@literal <thomas.bouquet at rte-france.com>}
*/
final class OperatorStrategyConverter {
private static final Condition TRUE = new TrueCondition();

private OperatorStrategyConverter() {
}

static StrategiesAndActions getOperatorStrategies(RaoResult raoResult, Crac crac, Network network) {
List<OperatorStrategy> operatorStrategies = new ArrayList<>();
Set<Action> actions = new HashSet<>();

// preventive strategy
ConditionalActions preventiveConditionalActions = getConditionalActionsForStateAndAddActionsToPool(crac.getPreventiveState(), raoResult, network, actions);
operatorStrategies.add(new OperatorStrategy(crac.getPreventiveState().getInstant().getId(), ContingencyContext.none(), List.of(preventiveConditionalActions)));

// post-contingency strategies
List<Instant> postOutageInstants = crac.getSortedInstants().stream().filter(instant -> instant.isAuto() || instant.isCurative()).toList();
for (Contingency contingency : crac.getContingencies()) {
List<ConditionalActions> conditionalActions = new ArrayList<>();
postOutageInstants.forEach(postOutageInstant -> conditionalActions.add(getConditionalActionsForStateAndAddActionsToPool(crac.getState(contingency.getId(), postOutageInstant), raoResult, network, actions)));
operatorStrategies.add(new OperatorStrategy(contingency.getId(), ContingencyContext.specificContingency(contingency.getId()), conditionalActions));
}

return new StrategiesAndActions(new OperatorStrategyList(operatorStrategies), new ActionList(actions.stream().toList()));
}

private static ConditionalActions getConditionalActionsForStateAndAddActionsToPool(State state, RaoResult raoResult, Network network, Set<Action> actionsPool) {
Set<Action> stateActions = getActivatedActionsForState(raoResult, state, network);
actionsPool.addAll(stateActions);
return new ConditionalActions(state.getId(), TRUE, getActionsIds(stateActions));
}

private static Set<Action> getActivatedActionsForState(RaoResult raoResult, State state, Network network) {
Set<Action> actions = new HashSet<>();
raoResult.getActivatedNetworkActionsDuringState(state).forEach(networkAction -> actions.addAll(networkAction.getElementaryActions()));
raoResult.getActivatedRangeActionsDuringState(state).forEach(rangeAction -> actions.addAll(rangeAction.toActions(raoResult.getOptimizedSetPointOnState(state, rangeAction), network)));
return actions;
}

private static List<String> getActionsIds(Set<Action> actions) {
return actions.stream().map(Action::getId).collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import com.powsybl.commons.extensions.Extendable;
import com.powsybl.commons.util.ServiceLoaderCache;
import com.powsybl.iidm.network.Network;
import com.powsybl.openrao.commons.OpenRaoException;
import com.powsybl.openrao.commons.PhysicalParameter;
import com.powsybl.openrao.commons.Unit;
Expand Down Expand Up @@ -555,4 +556,8 @@ private void write(List<Exporter> exporters, String format, Crac crac, Propertie
default void write(String format, Crac crac, Properties properties, OutputStream outputStream) {
write(new ServiceLoaderCache<>(Exporter.class).getServices(), format, crac, properties, outputStream);
}

default StrategiesAndActions getOperatorStrategies(Crac crac, Network network) {
return OperatorStrategyConverter.getOperatorStrategies(this, crac, network);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

maybe let's accept once and for all that a RaoResult depends on a Crac (thus we can add a RaoResult.getCrac() method) and that a Crac depends on a Network (Crac.getNetwork())
@phiedw @Godelaine thoughts ?

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright (c) 2026, 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.openrao.data.raoresult.api;

import com.powsybl.action.ActionList;
import com.powsybl.security.strategy.OperatorStrategyList;

/**
* @author Thomas Bouquet {@literal <thomas.bouquet at rte-france.com>}
*/
public record StrategiesAndActions(OperatorStrategyList operatorStrategyList, ActionList actionList) {
}
Loading