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

com.powsybl.flow_decomposition.FlowDecompositionResults 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.flow_decomposition;

import com.powsybl.flow_decomposition.rescaler.DecomposedFlowRescaler;
import com.powsybl.iidm.network.*;

import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.powsybl.flow_decomposition.DecomposedFlow.ALLOCATED_COLUMN_NAME;
import static com.powsybl.flow_decomposition.DecomposedFlow.NO_FLOW;
import static com.powsybl.flow_decomposition.DecomposedFlow.PST_COLUMN_NAME;
import static com.powsybl.flow_decomposition.DecomposedFlow.XNODE_COLUMN_NAME;
import static com.powsybl.flow_decomposition.NetworkUtil.LOOP_FLOWS_COLUMN_PREFIX;

/**
 * This class provides flow decomposition results from a network.
 * Those results are returned by a flowDecompositionComputer when run on a network.
 *
 * @author Sebastien Murgey {@literal }
 * @author Hugo Schindler {@literal }
 * @see FlowDecompositionComputer
 * @see DecomposedFlow
 */
public class FlowDecompositionResults {
    private static final String NO_CONTINGENCY_ID = "";
    private final String networkId;
    private final String id;
    private final Set zoneSet;
    private final Map decomposedFlowMap = new HashMap<>();

    class PerStateBuilder {
        private final Map xnecMap;
        private final String contingencyId;
        private SparseMatrixWithIndexesCSC allocatedAndLoopFlowsMatrix;
        private Map> pstFlowMap;
        private Map acTerminal1ReferenceFlow;
        private Map acTerminal2ReferenceFlow;
        private Map acCurrentTerminal1;
        private Map acCurrentTerminal2;
        private Map dcReferenceFlow;

        PerStateBuilder(String contingencyId, Set xnecList) {
            this.xnecMap = xnecList.stream().collect(Collectors.toMap(Identifiable::getId, Function.identity()));
            this.contingencyId = contingencyId;
        }

        void saveAllocatedAndLoopFlowsMatrix(SparseMatrixWithIndexesCSC allocatedAndLoopFlowsMatrix) {
            this.allocatedAndLoopFlowsMatrix = allocatedAndLoopFlowsMatrix;
        }

        void savePstFlowMatrix(SparseMatrixWithIndexesCSC pstFlowMatrix) {
            this.pstFlowMap = pstFlowMatrix.toMap();
        }

        void saveAcTerminal1ReferenceFlow(Map acTerminal1ReferenceFlow) {
            this.acTerminal1ReferenceFlow = acTerminal1ReferenceFlow;
        }

        void saveAcTerminal2ReferenceFlow(Map acTerminal2ReferenceFlow) {
            this.acTerminal2ReferenceFlow = acTerminal2ReferenceFlow;
        }

        void saveAcCurrentTerminal1(Map acTerminal1Current) {
            this.acCurrentTerminal1 = acTerminal1Current;
        }

        void saveAcCurrentTerminal2(Map acTerminal2Current) {
            this.acCurrentTerminal2 = acTerminal2Current;
        }

        void saveDcReferenceFlow(Map dcReferenceFlow) {
            this.dcReferenceFlow = dcReferenceFlow;
        }

        void build(DecomposedFlowRescaler decomposedFlowRescaler, Network network) {
            allocatedAndLoopFlowsMatrix.toMap()
                .forEach((branchId, decomposedFlow) -> {
                    String xnecId = DecomposedFlow.getXnecId(contingencyId, branchId);
                    decomposedFlowMap.put(xnecId, createDecomposedFlow(branchId, decomposedFlow, decomposedFlowRescaler, network));
                });
        }

        private DecomposedFlow createDecomposedFlow(String branchId, Map allocatedAndLoopFlowMap, DecomposedFlowRescaler decomposedFlowRescaler, Network network) {
            Map loopFlowsMap = allocatedAndLoopFlowMap.entrySet().stream()
                .filter(entry -> entry.getKey().startsWith(LOOP_FLOWS_COLUMN_PREFIX))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
            double allocatedFlow = allocatedAndLoopFlowMap.get(ALLOCATED_COLUMN_NAME);
            double pstFlow = pstFlowMap.getOrDefault(branchId, Collections.emptyMap()).getOrDefault(PST_COLUMN_NAME, NO_FLOW);
            double xNodeFlow = allocatedAndLoopFlowMap.getOrDefault(XNODE_COLUMN_NAME, NO_FLOW);
            Country country1 = NetworkUtil.getTerminalCountry(xnecMap.get(branchId).getTerminal1());
            Country country2 = NetworkUtil.getTerminalCountry(xnecMap.get(branchId).getTerminal2());
            double internalFlow = extractInternalFlow(loopFlowsMap, country1, country2);
            DecomposedFlow decomposedFlow = new DecomposedFlowBuilder()
                    .withBranchId(branchId)
                    .withContingencyId(contingencyId)
                    .withCountry1(country1)
                    .withCountry2(country2)
                    .withAcTerminal1ReferenceFlow(acTerminal1ReferenceFlow.get(branchId))
                    .withAcTerminal2ReferenceFlow(acTerminal2ReferenceFlow.get(branchId))
                    .withDcReferenceFlow(dcReferenceFlow.get(branchId))
                    .withAcCurrentTerminal1(acCurrentTerminal1.get(branchId))
                    .withAcCurrentTerminal2(acCurrentTerminal2.get(branchId))
                    .withAllocatedFlow(allocatedFlow)
                    .withXNodeFlow(xNodeFlow)
                    .withPstFlow(pstFlow)
                    .withInternalFlow(internalFlow)
                    .withLoopFlowsMap(loopFlowsMap)
                    .build();
            return decomposedFlowRescaler.rescale(decomposedFlow, network);
        }

        private double extractInternalFlow(Map loopFlowsMap, Country country1, Country country2) {
            if (Objects.equals(country1, country2)) {
                return Optional.ofNullable(loopFlowsMap.remove(NetworkUtil.getLoopFlowIdFromCountry(country1)))
                    .orElse(NO_FLOW);
            }
            return NO_FLOW;
        }
    }

    FlowDecompositionResults(Network network) {
        Date date = Date.from(Instant.now());
        String dateString = new SimpleDateFormat("yyyyMMdd-HHmmss").format(date);
        this.networkId = network.getNameOrId();
        this.id = "Flow_Decomposition_Results_of_" + dateString + "_on_network_" + networkId;
        this.zoneSet = network.getCountries();
    }

    /**
     * @return Network Id
     */
    public String getNetworkId() {
        return networkId;
    }

    /**
     * @return Id composed of a time format and the network id.
     */
    public String getId() {
        return id;
    }

    /**
     * @return the set of available zones in this result
     */
    public Set getZoneSet() {
        return zoneSet;
    }

    /**
     * @return A rescaled flow decomposition map. The keys are the XNEC and the values are {@code DecomposedFlow} objects.
     */
    public Map getDecomposedFlowMap() {
        return decomposedFlowMap;
    }

    PerStateBuilder getBuilder(String contingencyId, Set xnecList) {
        return new PerStateBuilder(contingencyId, xnecList);
    }

    public PerStateBuilder getBuilder(Set xnecList) {
        return new PerStateBuilder(NO_CONTINGENCY_ID, xnecList);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy