All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.powsybl.openrao.searchtreerao.commons.optimizationperimeters.AbstractOptimizationPerimeter Maven / Gradle / Ivy

The newest version!
/*
 * 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.openrao.searchtreerao.commons.optimizationperimeters;

import com.powsybl.openrao.data.crac.api.Identifiable;
import com.powsybl.openrao.data.crac.api.State;
import com.powsybl.openrao.data.crac.api.cnec.Cnec;
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.RangeAction;
import com.powsybl.openrao.data.crac.loopflowextension.LoopFlowThreshold;
import com.powsybl.openrao.raoapi.parameters.RaoParameters;
import com.powsybl.openrao.raoapi.parameters.extensions.LoopFlowParametersExtension;
import com.powsybl.openrao.searchtreerao.result.api.RangeActionSetpointResult;
import com.powsybl.iidm.network.Network;

import java.util.*;
import java.util.stream.Collectors;

import static com.powsybl.openrao.commons.logs.OpenRaoLoggerProvider.BUSINESS_WARNS;

/**
 * @author Baptiste Seguinot {@literal }
 */
public abstract class AbstractOptimizationPerimeter implements OptimizationPerimeter {

    private final State mainOptimizationState;
    private final Set monitoredStates;
    private final Set flowCnecs;
    private final Set optimizedFlowCnecs;
    private final Set monitoredFlowCnecs;
    private final Set loopFlowCnecs;
    private final Set availableNetworkActions;
    private final Map>> availableRangeActions;

    protected AbstractOptimizationPerimeter(State mainOptimizationState,
                                         Set flowCnecs,
                                         Set loopFlowCnecs,
                                         Set availableNetworkActions,
                                         Map>> availableRangeActions) {
        this.mainOptimizationState = mainOptimizationState;

        this.monitoredStates = flowCnecs.stream().map(FlowCnec::getState).collect(Collectors.toSet());

        this.flowCnecs = new TreeSet<>(Comparator.comparing(Identifiable::getId));
        this.flowCnecs.addAll(flowCnecs);

        this.optimizedFlowCnecs = new TreeSet<>(Comparator.comparing(Identifiable::getId));
        this.optimizedFlowCnecs.addAll(flowCnecs.stream().filter(Cnec::isOptimized).collect(Collectors.toSet()));

        this.monitoredFlowCnecs = new TreeSet<>(Comparator.comparing(Identifiable::getId));
        this.monitoredFlowCnecs.addAll(flowCnecs.stream().filter(Cnec::isMonitored).collect(Collectors.toSet()));

        this.loopFlowCnecs = new TreeSet<>(Comparator.comparing(Identifiable::getId));
        this.loopFlowCnecs.addAll(loopFlowCnecs);

        this.availableNetworkActions = new TreeSet<>(Comparator.comparing(Identifiable::getId));
        this.availableNetworkActions.addAll(availableNetworkActions);

        this.availableRangeActions = new TreeMap<>(Comparator.comparing(State::getId));
        availableRangeActions.forEach((state, rangeActions) -> {
            Set> rangeActionSet = new TreeSet<>(Comparator.comparing(Identifiable::getId));
            rangeActionSet.addAll(availableRangeActions.get(state));
            this.availableRangeActions.put(state, rangeActionSet);
        });
    }

    @Override
    public State getMainOptimizationState() {
        return mainOptimizationState;
    }

    @Override
    public Set getRangeActionOptimizationStates() {
        return availableRangeActions.keySet();
    }

    @Override
    public Set getMonitoredStates() {
        return monitoredStates;
    }

    @Override
    public Set getFlowCnecs() {
        return flowCnecs;
    }

    @Override
    public Set getOptimizedFlowCnecs() {
        return optimizedFlowCnecs;
    }

    @Override
    public Set getMonitoredFlowCnecs() {
        return monitoredFlowCnecs;
    }

    @Override
    public Set getLoopFlowCnecs() {
        return loopFlowCnecs;
    }

    @Override
    public Set getNetworkActions() {
        return availableNetworkActions;
    }

    @Override
    public Map>> getRangeActionsPerState() {
        return availableRangeActions;
    }

    @Override
    public Set> getRangeActions() {
        return availableRangeActions.values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
    }

    public static Set getLoopFlowCnecs(Set flowCnecs, RaoParameters raoParameters, Network network) {
        if (raoParameters.hasExtension(LoopFlowParametersExtension.class)
                && !raoParameters.getExtension(LoopFlowParametersExtension.class).getCountries().isEmpty()) {
            // loopFlow limited, and set of country for which loop-flow are monitored is defined
            return flowCnecs.stream()
                .filter(cnec -> !Objects.isNull(cnec.getExtension(LoopFlowThreshold.class)) &&
                    cnec.getLocation(network).stream().anyMatch(country -> country.isPresent() && raoParameters.getExtension(LoopFlowParametersExtension.class).getCountries().contains(country.get())))
                .collect(Collectors.toSet());
        } else if (raoParameters.hasExtension(LoopFlowParametersExtension.class)) {

            // loopFlow limited, but no set of country defined
            return flowCnecs.stream()
                .filter(cnec -> !Objects.isNull(cnec.getExtension(LoopFlowThreshold.class)))
                .collect(Collectors.toSet());
        } else {

            //no loopFLow limitation
            return Collections.emptySet();
        }
    }

    static boolean doesPrePerimeterSetpointRespectRange(RangeAction rangeAction, RangeActionSetpointResult prePerimeterSetpoints) {
        double preperimeterSetPoint = prePerimeterSetpoints.getSetpoint(rangeAction);
        double minSetPoint = rangeAction.getMinAdmissibleSetpoint(preperimeterSetPoint);
        double maxSetPoint = rangeAction.getMaxAdmissibleSetpoint(preperimeterSetPoint);

        if (preperimeterSetPoint < minSetPoint || preperimeterSetPoint > maxSetPoint) {
            BUSINESS_WARNS.warn("Range action {} has an initial setpoint of {} that does not respect its allowed range [{} {}]. It will be filtered out of the linear problem.",
                rangeAction.getId(), preperimeterSetPoint, minSetPoint, maxSetPoint);
            return false;
        } else {
            return true;
        }
    }

    /**
     * If aligned range actions' initial setpoint are different, this function filters them out
     */
    static void removeAlignedRangeActionsWithDifferentInitialSetpoints(Set> rangeActions, RangeActionSetpointResult prePerimeterSetPoints) {
        Set groups = rangeActions.stream().map(RangeAction::getGroupId)
            .filter(Optional::isPresent).map(Optional::get).collect(Collectors.toSet());
        for (String group : groups) {
            Set> groupRangeActions = rangeActions.stream().filter(rangeAction -> rangeAction.getGroupId().isPresent() && rangeAction.getGroupId().get().equals(group)).collect(Collectors.toSet());
            double preperimeterSetPoint = prePerimeterSetPoints.getSetpoint(groupRangeActions.iterator().next());
            if (groupRangeActions.stream().anyMatch(rangeAction -> Math.abs(prePerimeterSetPoints.getSetpoint(rangeAction) - preperimeterSetPoint) > 1e-6)) {
                BUSINESS_WARNS.warn("Range actions of group {} do not have the same prePerimeter setpoint. They will be filtered out of the linear problem.", group);
                rangeActions.removeAll(groupRangeActions);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy