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

com.farao_community.farao.search_tree_rao.commons.AbsolutePtdfSumsComputation 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.farao_community.farao.search_tree_rao.commons;

import com.farao_community.farao.commons.EICode;
import com.farao_community.farao.data.crac_api.cnec.Side;
import com.powsybl.glsk.commons.ZonalData;
import com.farao_community.farao.data.crac_api.Contingency;
import com.farao_community.farao.data.crac_api.cnec.FlowCnec;
import com.farao_community.farao.loopflow_computation.XnodeGlskHandler;
import com.farao_community.farao.rao_api.ZoneToZonePtdfDefinition;
import com.farao_community.farao.sensitivity_analysis.SystematicSensitivityResult;
import com.powsybl.iidm.network.Network;
import com.powsybl.sensitivity.SensitivityVariableSet;

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

/**
 *  This class computes the absolute PTDF sums on a given set of CNECs
 *  It requires that the sensitivity values be already computed
 *
 *  @author Peter Mitri {@literal }
 *  @author Baptiste Seguinot {@literal }
 */
public class AbsolutePtdfSumsComputation {
    private final ZonalData glskProvider;
    private final List zTozPtdfs;
    private final Network network;

    public AbsolutePtdfSumsComputation(ZonalData glskProvider, List zTozPtdfs, Network network) {
        this.glskProvider = glskProvider;
        this.zTozPtdfs = zTozPtdfs;
        this.network = network;
    }

    public Map> computeAbsolutePtdfSums(Set flowCnecs, SystematicSensitivityResult sensitivityResult) {

        Set contingencies = flowCnecs.stream()
                .filter(cnec -> cnec.getState().getContingency().isPresent())
                .map(cnec -> cnec.getState().getContingency().get())
                .collect(Collectors.toSet());
        XnodeGlskHandler xnodeGlskHandler = new XnodeGlskHandler(glskProvider, contingencies, network);

        Map> ptdfSums = new HashMap<>();
        List eiCodesInPtdfs = zTozPtdfs.stream().flatMap(zToz -> zToz.getEiCodes().stream()).collect(Collectors.toList());

        for (FlowCnec flowCnec : flowCnecs) {
            flowCnec.getMonitoredSides().forEach(side -> {
                Map ptdfMap = buildZoneToSlackPtdfMap(flowCnec, side, glskProvider, eiCodesInPtdfs, sensitivityResult, xnodeGlskHandler);
                double sumOfZToZPtdf = zTozPtdfs.stream().mapToDouble(zToz -> Math.abs(computeZToZPtdf(zToz, ptdfMap))).sum();
                ptdfSums.computeIfAbsent(flowCnec, k -> new EnumMap<>(Side.class)).put(side, sumOfZToZPtdf);
            });
        }
        return ptdfSums;
    }

    private Map buildZoneToSlackPtdfMap(FlowCnec flowCnec, Side side, ZonalData glsks, List eiCodesInBoundaries, SystematicSensitivityResult sensitivityResult, XnodeGlskHandler xnodeGlskHandler) {
        Map ptdfs = new HashMap<>();
        for (EICode eiCode : eiCodesInBoundaries) {
            SensitivityVariableSet linearGlsk = glsks.getData(eiCode.getAreaCode());
            if (linearGlsk != null) {
                double ptdfValue;
                if (xnodeGlskHandler.isLinearGlskValidForCnec(flowCnec, linearGlsk)) {
                    ptdfValue = sensitivityResult.getSensitivityOnFlow(linearGlsk, flowCnec, side);
                } else {
                    ptdfValue = 0;
                }
                ptdfs.put(eiCode, ptdfValue);
            }
        }
        return ptdfs;
    }

    private double computeZToZPtdf(ZoneToZonePtdfDefinition zToz, Map zToSlackPtdfMap) {

        List zoneToSlackPtdf =  zToz.getZoneToSlackPtdfs().stream()
            .filter(zToS -> zToSlackPtdfMap.containsKey(zToS.getEiCode()))
            .map(zToS -> zToS.getWeight() * zToSlackPtdfMap.get(zToS.getEiCode()))
            .collect(Collectors.toList());

        if (zoneToSlackPtdf.size() < 2) {
            // the boundary should at least contains two zoneToSlack PTDFs
            return 0.0;
        } else {
            return zoneToSlackPtdf.stream().mapToDouble(v -> v).sum();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy