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

com.powsybl.openrao.searchtreerao.linearoptimisation.algorithms.fillers.MaxMinMarginFiller Maven / Gradle / Ivy

/*
 * Copyright (c) 2020, 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.linearoptimisation.algorithms.fillers;

import com.powsybl.openrao.commons.Unit;
import com.powsybl.openrao.data.cracapi.Identifiable;
import com.powsybl.openrao.data.cracapi.cnec.FlowCnec;
import com.powsybl.openrao.searchtreerao.commons.RaoUtil;
import com.powsybl.openrao.searchtreerao.linearoptimisation.algorithms.linearproblem.OpenRaoMPConstraint;
import com.powsybl.openrao.searchtreerao.linearoptimisation.algorithms.linearproblem.OpenRaoMPVariable;
import com.powsybl.openrao.searchtreerao.linearoptimisation.algorithms.linearproblem.LinearProblem;
import com.powsybl.openrao.searchtreerao.result.api.FlowResult;
import com.powsybl.openrao.searchtreerao.result.api.RangeActionActivationResult;
import com.powsybl.openrao.searchtreerao.result.api.SensitivityResult;

import java.util.Comparator;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;

import static com.powsybl.openrao.commons.Unit.MEGAWATT;

/**
 * @author Viktor Terrier {@literal }
 * @author Baptiste Seguinot {@literal }
 */
public class MaxMinMarginFiller implements ProblemFiller {
    protected final Set optimizedCnecs;
    private final Unit unit;

    public MaxMinMarginFiller(Set optimizedCnecs,
                              Unit unit) {
        this.optimizedCnecs = new TreeSet<>(Comparator.comparing(Identifiable::getId));
        this.optimizedCnecs.addAll(optimizedCnecs);
        this.unit = unit;
    }

    @Override
    public void fill(LinearProblem linearProblem, FlowResult flowResult, SensitivityResult sensitivityResult) {
        Set validFlowCnecs = FillersUtil.getFlowCnecsComputationStatusOk(optimizedCnecs, sensitivityResult);

        // build variables
        buildMinimumMarginVariable(linearProblem, validFlowCnecs);

        // build constraints
        buildMinimumMarginConstraints(linearProblem, validFlowCnecs);

        // complete objective
        fillObjectiveWithMinMargin(linearProblem);
    }

    @Override
    public void updateBetweenSensiIteration(LinearProblem linearProblem, FlowResult flowResult, SensitivityResult sensitivityResult, RangeActionActivationResult rangeActionActivationResult) {
        // Objective does not change, nothing to do
    }

    @Override
    public void updateBetweenMipIteration(LinearProblem linearProblem, RangeActionActivationResult rangeActionActivationResult) {
        // Objective does not change, nothing to do
    }

    /**
     * Build the minimum margin variable MM.
     * MM represents the smallest margin of all Cnecs.
     * It is given in MEGAWATT.
     */
    private void buildMinimumMarginVariable(LinearProblem linearProblem, Set validFlowCnecs) {
        if (!validFlowCnecs.isEmpty()) {
            linearProblem.addMinimumMarginVariable(-LinearProblem.infinity(), LinearProblem.infinity());
        } else {
            // if there is no Cnecs, the minMarginVariable is forced to zero.
            // otherwise it would be unbounded in the LP
            linearProblem.addMinimumMarginVariable(0.0, 0.0);
        }
    }

    /**
     * Build two minimum margin constraints for each Cnec c.
     * The minimum margin constraints ensure that the minimum margin variable is below
     * the margin of each Cnec. They consist in a linear equivalent of the definitilon
     * of the min margin : MM = min{c in CNEC} margin[c].
     * 

* For each Cnec c, the constraints are (if the max margin is defined in MEGAWATT) : *

* MM <= fmax[c] - F[c] (ABOVE_THRESHOLD) * MM <= F[c] - fmin[c] (BELOW_THRESHOLD) *

* For each Cnec c, the constraints are (if the max margin is defined in AMPERE) : *

* MM <= (fmax[c] - F[c]) * 1000 / (Unom * sqrt(3)) (ABOVE_THRESHOLD) * MM <= (F[c] - fmin[c]) * 1000 / (Unom * sqrt(3)) (BELOW_THRESHOLD) */ private void buildMinimumMarginConstraints(LinearProblem linearProblem, Set validFlowCnecs) { OpenRaoMPVariable minimumMarginVariable = linearProblem.getMinimumMarginVariable(); validFlowCnecs.forEach(cnec -> cnec.getMonitoredSides().forEach(side -> { OpenRaoMPVariable flowVariable = linearProblem.getFlowVariable(cnec, side); Optional minFlow; Optional maxFlow; minFlow = cnec.getLowerBound(side, MEGAWATT); maxFlow = cnec.getUpperBound(side, MEGAWATT); double unitConversionCoefficient = RaoUtil.getFlowUnitMultiplier(cnec, side, unit, MEGAWATT); if (minFlow.isPresent()) { OpenRaoMPConstraint minimumMarginNegative = linearProblem.addMinimumMarginConstraint(-LinearProblem.infinity(), -minFlow.get(), cnec, side, LinearProblem.MarginExtension.BELOW_THRESHOLD); minimumMarginNegative.setCoefficient(minimumMarginVariable, unitConversionCoefficient); minimumMarginNegative.setCoefficient(flowVariable, -1); } if (maxFlow.isPresent()) { OpenRaoMPConstraint minimumMarginPositive = linearProblem.addMinimumMarginConstraint(-LinearProblem.infinity(), maxFlow.get(), cnec, side, LinearProblem.MarginExtension.ABOVE_THRESHOLD); minimumMarginPositive.setCoefficient(minimumMarginVariable, unitConversionCoefficient); minimumMarginPositive.setCoefficient(flowVariable, 1); } })); } /** * Add in the objective function of the linear problem the min Margin. *

* min(-MM) */ private void fillObjectiveWithMinMargin(LinearProblem linearProblem) { OpenRaoMPVariable minimumMarginVariable = linearProblem.getMinimumMarginVariable(); linearProblem.getObjective().setCoefficient(minimumMarginVariable, -1); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy