InterTemporalRaoResultImpl.java
/*
* Copyright (c) 2025, 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.searchtreerao.marmot.results;
import com.powsybl.iidm.network.TwoSides;
import com.powsybl.openrao.commons.OpenRaoException;
import com.powsybl.openrao.commons.PhysicalParameter;
import com.powsybl.openrao.commons.TemporalData;
import com.powsybl.openrao.commons.Unit;
import com.powsybl.openrao.data.crac.api.Instant;
import com.powsybl.openrao.data.crac.api.InstantKind;
import com.powsybl.openrao.data.crac.api.State;
import com.powsybl.openrao.data.crac.api.cnec.FlowCnec;
import com.powsybl.openrao.data.crac.api.networkaction.NetworkAction;
import com.powsybl.openrao.data.crac.api.rangeaction.PstRangeAction;
import com.powsybl.openrao.data.crac.api.rangeaction.RangeAction;
import com.powsybl.openrao.data.raoresult.api.ComputationStatus;
import com.powsybl.openrao.data.raoresult.api.InterTemporalRaoResult;
import com.powsybl.openrao.data.raoresult.api.RaoResult;
import com.powsybl.openrao.searchtreerao.marmot.MarmotUtils;
import com.powsybl.openrao.searchtreerao.result.api.ObjectiveFunctionResult;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Thomas Bouquet {@literal <thomas.bouquet at rte-france.com>}
*/
public class InterTemporalRaoResultImpl implements InterTemporalRaoResult {
private final ObjectiveFunctionResult initialGlobalObjectiveFunctionResult;
private final ObjectiveFunctionResult postPrasGlobalObjectiveFunctionResult;
private final TemporalData<RaoResult> raoResultPerTimestamp;
private static final String MISSING_RAO_RESULT_ERROR_MESSAGE = "No RAO Result data found for the provided timestamp.";
public InterTemporalRaoResultImpl(ObjectiveFunctionResult initialGlobalObjectiveFunctionResult, ObjectiveFunctionResult postPrasGlobalObjectiveFunctionResult, TemporalData<RaoResult> raoResultPerTimestamp) {
this.initialGlobalObjectiveFunctionResult = initialGlobalObjectiveFunctionResult;
this.postPrasGlobalObjectiveFunctionResult = postPrasGlobalObjectiveFunctionResult;
this.raoResultPerTimestamp = raoResultPerTimestamp;
}
@Override
public List<OffsetDateTime> getTimestamps() {
return raoResultPerTimestamp.getTimestamps();
}
@Override
public double getGlobalFunctionalCost(InstantKind instantKind) {
return getRelevantResult(instantKind).getFunctionalCost();
}
@Override
public double getGlobalVirtualCost(InstantKind instantKind) {
return getRelevantResult(instantKind).getVirtualCost();
}
@Override
public double getGlobalVirtualCost(InstantKind instantKind, String virtualCostName) {
return getRelevantResult(instantKind).getVirtualCost(virtualCostName);
}
@Override
public double getFunctionalCost(Instant optimizedInstant, OffsetDateTime timestamp) {
return raoResultPerTimestamp.getData(timestamp).orElseThrow(() -> new OpenRaoException(MISSING_RAO_RESULT_ERROR_MESSAGE)).getFunctionalCost(optimizedInstant);
}
@Override
public double getVirtualCost(Instant optimizedInstant, OffsetDateTime timestamp) {
return raoResultPerTimestamp.getData(timestamp).orElseThrow(() -> new OpenRaoException(MISSING_RAO_RESULT_ERROR_MESSAGE)).getVirtualCost(optimizedInstant);
}
@Override
public double getVirtualCost(Instant optimizedInstant, String virtualCostName, OffsetDateTime timestamp) {
return raoResultPerTimestamp.getData(timestamp).orElseThrow(() -> new OpenRaoException(MISSING_RAO_RESULT_ERROR_MESSAGE)).getVirtualCost(optimizedInstant, virtualCostName);
}
@Override
public boolean isSecure(Instant optimizedInstant, OffsetDateTime timestamp, PhysicalParameter... u) {
return raoResultPerTimestamp.getData(timestamp).orElseThrow(() -> new OpenRaoException(MISSING_RAO_RESULT_ERROR_MESSAGE)).isSecure(optimizedInstant, u);
}
@Override
public boolean isSecure(OffsetDateTime timestamp, PhysicalParameter... u) {
return raoResultPerTimestamp.getData(timestamp).orElseThrow(() -> new OpenRaoException(MISSING_RAO_RESULT_ERROR_MESSAGE)).isSecure(u);
}
@Override
public ComputationStatus getComputationStatus() {
return MarmotUtils.getGlobalComputationStatus(raoResultPerTimestamp, RaoResult::getComputationStatus);
}
@Override
public ComputationStatus getComputationStatus(State state) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, state).getComputationStatus(state);
}
@Override
public double getFlow(Instant optimizedInstant, FlowCnec flowCnec, TwoSides side, Unit unit) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, flowCnec.getState()).getFlow(optimizedInstant, flowCnec, side, unit);
}
@Override
public double getMargin(Instant optimizedInstant, FlowCnec flowCnec, Unit unit) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, flowCnec.getState()).getMargin(optimizedInstant, flowCnec, unit);
}
@Override
public double getRelativeMargin(Instant optimizedInstant, FlowCnec flowCnec, Unit unit) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, flowCnec.getState()).getRelativeMargin(optimizedInstant, flowCnec, unit);
}
@Override
public double getCommercialFlow(Instant optimizedInstant, FlowCnec flowCnec, TwoSides side, Unit unit) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, flowCnec.getState()).getCommercialFlow(optimizedInstant, flowCnec, side, unit);
}
@Override
public double getLoopFlow(Instant optimizedInstant, FlowCnec flowCnec, TwoSides side, Unit unit) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, flowCnec.getState()).getLoopFlow(optimizedInstant, flowCnec, side, unit);
}
@Override
public double getPtdfZonalSum(Instant optimizedInstant, FlowCnec flowCnec, TwoSides side) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, flowCnec.getState()).getPtdfZonalSum(optimizedInstant, flowCnec, side);
}
@Override
public double getFunctionalCost(Instant optimizedInstant) {
throw new OpenRaoException("Calling getFunctionalCost with an instant alone is ambiguous. For the global functional cost, use getGlobalFunctionalCost. Otherwise, please provide a timestamp.");
}
@Override
public double getVirtualCost(Instant optimizedInstant) {
throw new OpenRaoException("Calling getVirtualCost with an instant alone is ambiguous. For the global virtual cost, use getGlobalVirtualCost. Otherwise, please provide a timestamp.");
}
@Override
public Set<String> getVirtualCostNames() {
return postPrasGlobalObjectiveFunctionResult.getVirtualCostNames();
}
@Override
public double getVirtualCost(Instant optimizedInstant, String virtualCostName) {
throw new OpenRaoException("Calling getVirtualCost with an instant and a name alone is ambiguous. For the global virtual cost, use getGlobalVirtualCost. Otherwise, please provide a timestamp.");
}
@Override
public boolean wasActivatedBeforeState(State state, NetworkAction networkAction) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, state).wasActivatedBeforeState(state, networkAction);
}
@Override
public boolean isActivatedDuringState(State state, NetworkAction networkAction) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, state).isActivatedDuringState(state, networkAction);
}
@Override
public Set<NetworkAction> getActivatedNetworkActionsDuringState(State state) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, state).getActivatedNetworkActionsDuringState(state);
}
@Override
public boolean isActivatedDuringState(State state, RangeAction<?> rangeAction) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, state).isActivatedDuringState(state, rangeAction);
}
@Override
public int getPreOptimizationTapOnState(State state, PstRangeAction pstRangeAction) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, state).getPreOptimizationTapOnState(state, pstRangeAction);
}
@Override
public int getOptimizedTapOnState(State state, PstRangeAction pstRangeAction) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, state).getOptimizedTapOnState(state, pstRangeAction);
}
@Override
public double getPreOptimizationSetPointOnState(State state, RangeAction<?> rangeAction) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, state).getPreOptimizationSetPointOnState(state, rangeAction);
}
@Override
public double getOptimizedSetPointOnState(State state, RangeAction<?> rangeAction) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, state).getOptimizedSetPointOnState(state, rangeAction);
}
@Override
public Set<RangeAction<?>> getActivatedRangeActionsDuringState(State state) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, state).getActivatedRangeActionsDuringState(state);
}
@Override
public Map<PstRangeAction, Integer> getOptimizedTapsOnState(State state) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, state).getOptimizedTapsOnState(state);
}
@Override
public Map<RangeAction<?>, Double> getOptimizedSetPointsOnState(State state) {
return MarmotUtils.getDataFromState(raoResultPerTimestamp, state).getOptimizedSetPointsOnState(state);
}
@Override
public String getExecutionDetails() {
List<String> executionDetails = new ArrayList<>();
getTimestamps().forEach(timestamp -> executionDetails.add(timestamp.format(DateTimeFormatter.ISO_DATE_TIME) + ": " + raoResultPerTimestamp.getData(timestamp).orElseThrow().getExecutionDetails()));
return String.join(" - ", executionDetails);
}
@Override
public void setExecutionDetails(String executionDetails) {
// nothing to do
}
@Override
public boolean isSecure(Instant optimizedInstant, PhysicalParameter... u) {
throw new OpenRaoException("Calling isSecure with an instant and physical parameters alone is ambiguous. Please provide a timestamp.");
}
@Override
public boolean isSecure(PhysicalParameter... u) {
return raoResultPerTimestamp.map(raoResult -> raoResult.isSecure(u)).getDataPerTimestamp().values().stream().allMatch(bool -> bool);
}
private ObjectiveFunctionResult getRelevantResult(InstantKind instantKind) {
return instantKind == null ? initialGlobalObjectiveFunctionResult : postPrasGlobalObjectiveFunctionResult;
}
}