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

com.powsybl.metrix.mapping.TimeSeriesMappingConfigLoader Maven / Gradle / Ivy

There is a newer version: 2.6.0
Show newest version
/*
 * 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/.
 * SPDX-License-Identifier: MPL-2.0
 */
package com.powsybl.metrix.mapping;

import com.powsybl.iidm.network.Generator;
import com.powsybl.iidm.network.Injection;
import com.powsybl.iidm.network.Load;
import com.powsybl.iidm.network.VoltageLevel;
import com.powsybl.timeseries.ReadOnlyTimeSeriesStore;
import com.powsybl.timeseries.ast.FloatNodeCalc;
import com.powsybl.timeseries.ast.NodeCalc;
import com.powsybl.timeseries.ast.TimeSeriesNameNodeCalc;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Stream;

import static com.powsybl.metrix.mapping.TimeSeriesMappingConfigEquipmentCsvWriter.getSubstation;

/**
 * @author Marianne Funfrock {@literal }
 */
public class TimeSeriesMappingConfigLoader implements DefaultGenericMetadata {

    private final TimeSeriesMappingConfig config;
    private final Set existingTimeSeriesNames;

    public TimeSeriesMappingConfigLoader(TimeSeriesMappingConfig config, Set existingTimeSeriesNames) {
        this.config = config;
        this.existingTimeSeriesNames = existingTimeSeriesNames;
    }

    private static List getMultimapValue(Map> multimap, MappingKey key) {
        return multimap.computeIfAbsent(key, k -> new LinkedList<>());
    }

    private static  Stream keys(Map map, V value) {
        return map.entrySet().stream()
                .filter(entry -> value == entry.getValue())
                .map(Map.Entry::getKey);
    }

    protected String computeGroupName(Injection injection, EquipmentGroupType equipmentGroupType) {
        VoltageLevel voltageLevel = injection.getTerminal().getVoltageLevel();
        String name = StringUtils.EMPTY;
        if (!(equipmentGroupType instanceof SimpleEquipmentGroupType type)) {
            return name;
        }
        return switch (type) {
            case SUBSTATION -> getSubstation(voltageLevel);
            case VOLTAGE_LEVEL -> voltageLevel.getId();
        };
    }

    protected String computePowerTypeName(Generator generator) {
        return StringUtils.EMPTY;
    }

    protected Map tsMetadata(NodeCalc nodeCalc, ReadOnlyTimeSeriesStore store) {
        Map tsMetadata = new HashMap<>();
        if (config.getTimeSeriesNodes().containsValue(nodeCalc)) {
            String tsName = keys(config.getTimeSeriesNodes(), nodeCalc).findFirst().orElseThrow();
            tsMetadata.putAll(TsMetadata.tsMetadata(tsName, config.getTimeSeriesNodeTags()));
        }
        if (nodeCalc instanceof TimeSeriesNameNodeCalc) {
            tsMetadata.putAll(TsMetadata.tsMetadata(nodeCalc, store));
        }
        return tsMetadata;
    }

    protected void tag(NodeCalc nodeCalc, String tag, String parameter) {
        String tsName = keys(config.getTimeSeriesNodes(), nodeCalc).findFirst().orElseThrow();
        config.addTag(tsName, tag, parameter);
    }

    private static String nameWithDelimiter(String name) {
        return !name.isEmpty() ? "_" + name : StringUtils.EMPTY;
    }

    private static String computeSpecificName(String name) {
        if (name == null) {
            return StringUtils.EMPTY;
        }
        return name;
    }

    private static boolean isWithPowerType(Boolean withPowerType) {
        return withPowerType != null && withPowerType;
    }

    private String computeGeneratorTsName(Generator generator, EquipmentGroupType equipmentGroupType, Boolean withPowerType, String name) {
        String groupName = computeGroupName(generator, equipmentGroupType);
        String specificName = computeSpecificName(name);
        if (!isWithPowerType(withPowerType)) {
            return groupName + nameWithDelimiter(specificName);
        }
        String powerTypeName = computePowerTypeName(generator);
        return groupName + nameWithDelimiter(powerTypeName) + nameWithDelimiter(specificName);
    }

    private String computeLoadTsName(Load load, EquipmentGroupType equipmentGroupType, String name) {
        String groupName = computeGroupName(load, equipmentGroupType);
        String specificName = computeSpecificName(name);
        return groupName + nameWithDelimiter(specificName);
    }

    private void addMapping(String timeSeriesName, String equipmentId, DistributionKey distributionKey, MappingVariable variable,
                            Map> timeSerieToEquipmentsMapping,
                            Map> equipmentToTimeSeriesMapping) {

        MappingKey timeSerieToEquipmentsKey = new MappingKey(variable, timeSeriesName);
        if (equipmentId != null) {
            MappingKey equipmentToTimeSeriesKey = new MappingKey(variable, equipmentId);
            List timeSeriesAlreadyMappedToThisEquipment = getMultimapValue(equipmentToTimeSeriesMapping, equipmentToTimeSeriesKey);
            if (!timeSeriesAlreadyMappedToThisEquipment.isEmpty()) {
                // remove old mapping
                String oldTimeSeriesName = timeSeriesAlreadyMappedToThisEquipment.get(0);
                MappingKey oldTimeSeriesKey = new MappingKey(variable, oldTimeSeriesName);
                List equipmentsMappedToOldTimeSeries = getMultimapValue(timeSerieToEquipmentsMapping, oldTimeSeriesKey);
                equipmentsMappedToOldTimeSeries.remove(equipmentId);
                if (equipmentsMappedToOldTimeSeries.isEmpty()) {
                    timeSerieToEquipmentsMapping.remove(oldTimeSeriesKey);
                }
            }
            timeSeriesAlreadyMappedToThisEquipment.add(0, timeSeriesName);

            // add new mapping
            getMultimapValue(timeSerieToEquipmentsMapping, timeSerieToEquipmentsKey).add(equipmentId);

            config.distributionKeys.put(equipmentToTimeSeriesKey, distributionKey);
        } else {
            getMultimapValue(timeSerieToEquipmentsMapping, timeSerieToEquipmentsKey);
        }
        config.mappedTimeSeriesNames.add(timeSeriesName);
    }

    private void addHvdcLineMapping(String timeSeriesName, String equipmentId, DistributionKey distributionKey, EquipmentVariable variable) {
        addMapping(timeSeriesName, equipmentId, distributionKey, variable,
                config.timeSeriesToHvdcLinesMapping, config.hvdcLineToTimeSeriesMapping);
        switch (variable) {
            case ACTIVE_POWER_SETPOINT -> config.unmappedHvdcLines.remove(equipmentId);
            case MIN_P -> config.unmappedMinPHvdcLines.remove(equipmentId);
            case MAX_P -> config.unmappedMaxPHvdcLines.remove(equipmentId);
            default -> {
                // Do nothing
            }
        }
    }

    private void addLoadMapping(String timeSeriesName, String equipmentId, DistributionKey distributionKey, EquipmentVariable variable) {
        addMapping(timeSeriesName, equipmentId, distributionKey, variable,
                config.timeSeriesToLoadsMapping, config.loadToTimeSeriesMapping);
        switch (variable) {
            case P0 -> {
                config.unmappedLoads.remove(equipmentId);
                config.unmappedFixedActivePowerLoads.remove(equipmentId);
                config.unmappedVariableActivePowerLoads.remove(equipmentId);
            }
            case FIXED_ACTIVE_POWER -> {
                config.unmappedLoads.remove(equipmentId);
                config.unmappedFixedActivePowerLoads.remove(equipmentId);
            }
            case VARIABLE_ACTIVE_POWER -> {
                config.unmappedLoads.remove(equipmentId);
                config.unmappedVariableActivePowerLoads.remove(equipmentId);
            }
            default -> {
                // Do nothing
            }
        }
    }

    private void addGeneratorMapping(String timeSeriesName, String equipmentId, DistributionKey distributionKey, EquipmentVariable variable) {
        addMapping(timeSeriesName, equipmentId, distributionKey, variable,
                config.timeSeriesToGeneratorsMapping, config.generatorToTimeSeriesMapping);
        switch (variable) {
            case TARGET_P -> config.unmappedGenerators.remove(equipmentId);
            case MIN_P -> config.unmappedMinPGenerators.remove(equipmentId);
            case MAX_P -> config.unmappedMaxPGenerators.remove(equipmentId);
            default -> {
                // Do nothing
            }
        }
    }

    private void addNumberTimeSeries(String timeSeriesName, float value) {
        if (!config.getTimeSeriesNodesKeys().contains(timeSeriesName)) {
            config.timeSeriesNodes.put(timeSeriesName, new FloatNodeCalc(value));
        }
    }

    protected void timeSeriesExists(String timeSeriesName) {
        if (timeSeriesName == null) {
            throw new TimeSeriesMappingException("'timeSeriesName' is not set");
        }
        if (!existingTimeSeriesNames.contains(timeSeriesName) && !config.getTimeSeriesNodesKeys().contains(timeSeriesName)) {
            throw new TimeSeriesMappingException("Time Series '" + timeSeriesName + "' not found");
        }
    }

    protected void addEquipmentMapping(MappableEquipmentType equipmentType, String timeSeriesName, String equipmentId, DistributionKey distributionKey,
                                    EquipmentVariable variable) {
        switch (equipmentType) {
            case GENERATOR -> addGeneratorMapping(timeSeriesName, equipmentId, distributionKey, variable);
            case LOAD -> addLoadMapping(timeSeriesName, equipmentId, distributionKey, variable);
            case BOUNDARY_LINE -> {
                addMapping(timeSeriesName, equipmentId, distributionKey, variable,
                    config.timeSeriesToDanglingLinesMapping, config.danglingLineToTimeSeriesMapping);
                if (variable == EquipmentVariable.P0) {
                    config.unmappedDanglingLines.remove(equipmentId);
                }
            }
            case HVDC_LINE -> addHvdcLineMapping(timeSeriesName, equipmentId, distributionKey, variable);
            case SWITCH -> addMapping(timeSeriesName, equipmentId, distributionKey, variable,
                config.timeSeriesToBreakersMapping, config.breakerToTimeSeriesMapping);
            case PHASE_TAP_CHANGER -> {
                addMapping(timeSeriesName, equipmentId, distributionKey, variable,
                    config.timeSeriesToPhaseTapChangersMapping, config.phaseTapChangerToTimeSeriesMapping);
                if (variable == EquipmentVariable.PHASE_TAP_POSITION) {
                    config.unmappedPhaseTapChangers.remove(equipmentId);
                }
            }
            case TRANSFORMER -> addMapping(timeSeriesName, equipmentId, distributionKey, variable,
                        config.timeSeriesToTransformersMapping, config.transformerToTimeSeriesMapping);
            case LINE -> addMapping(timeSeriesName, equipmentId, distributionKey, variable,
                        config.timeSeriesToLinesMapping, config.lineToTimeSeriesMapping);
            case RATIO_TAP_CHANGER -> addMapping(timeSeriesName, equipmentId, distributionKey, variable,
                        config.timeSeriesToRatioTapChangersMapping, config.ratioTapChangerToTimeSeriesMapping);
            case LCC_CONVERTER_STATION -> addMapping(timeSeriesName, equipmentId, distributionKey, variable,
                        config.timeSeriesToLccConverterStationsMapping, config.lccConverterStationToTimeSeriesMapping);
            case VSC_CONVERTER_STATION -> addMapping(timeSeriesName, equipmentId, distributionKey, variable,
                        config.timeSeriesToVscConverterStationsMapping, config.vscConverterStationToTimeSeriesMapping);
            default -> throw new AssertionError();
        }
    }

    protected void addUnmappedEquipment(MappableEquipmentType equipmentType, String equipmentId) {
        switch (equipmentType) {
            case GENERATOR -> config.ignoredUnmappedGenerators.add(equipmentId);
            case LOAD -> config.ignoredUnmappedLoads.add(equipmentId);
            case BOUNDARY_LINE -> config.ignoredUnmappedDanglingLines.add(equipmentId);
            case HVDC_LINE -> config.ignoredUnmappedHvdcLines.add(equipmentId);
            case PHASE_TAP_CHANGER -> config.ignoredUnmappedPhaseTapChangers.add(equipmentId);
            default -> throw new AssertionError();
        }
    }

    protected void addEquipmentTimeSeries(MappableEquipmentType equipmentType, String equipmentId, Set equipmentVariables) {
        for (EquipmentVariable equipmentVariable : equipmentVariables) {
            MappingKey mappingKey = new MappingKey(equipmentVariable, equipmentId);
            switch (equipmentType) {
                case GENERATOR -> config.generatorTimeSeries.add(mappingKey);
                case LOAD -> config.loadTimeSeries.add(mappingKey);
                case BOUNDARY_LINE -> config.danglingLineTimeSeries.add(mappingKey);
                case HVDC_LINE -> config.hvdcLineTimeSeries.add(mappingKey);
                case SWITCH -> config.breakerTimeSeries.add(mappingKey);
                case TRANSFORMER -> config.transformerTimeSeries.add(mappingKey);
                case LINE -> config.lineTimeSeries.add(mappingKey);
                case PHASE_TAP_CHANGER -> config.phaseTapChangerTimeSeries.add(mappingKey);
                case RATIO_TAP_CHANGER -> config.ratioTapChangerTimeSeries.add(mappingKey);
                case LCC_CONVERTER_STATION -> config.lccConverterStationTimeSeries.add(mappingKey);
                case VSC_CONVERTER_STATION -> config.vscConverterStationTimeSeries.add(mappingKey);
                default -> throw new AssertionError();
            }
        }
    }

    protected void addGroupGeneratorTimeSeries(Generator generator, EquipmentGroupType equipmentGroupType, Boolean withPowerType, String name) {
        String timeSeriesName = computeGeneratorTsName(generator, equipmentGroupType, withPowerType, name);
        config.generatorGroupToTimeSeriesMapping.computeIfAbsent(generator.getId(), k -> new HashSet<>()).add(timeSeriesName);
    }

    protected void addGroupLoadTimeSeries(Load load, EquipmentGroupType equipmentGroupType, String name) {
        String timeSeriesName = computeLoadTsName(load, equipmentGroupType, name);
        config.loadGroupToTimeSeriesMapping.computeIfAbsent(load.getId(), k -> new HashSet<>()).add(timeSeriesName);
    }

    protected void addIgnoreLimits(String timeSeriesName) {
        config.ignoreLimitsTimeSeriesNames.add(timeSeriesName);
    }

    protected void addPlannedOutages(String timeSeriesName, Set disconnectedIds) {
        config.timeSeriesToPlannedOutagesMapping.put(timeSeriesName, disconnectedIds);
    }

    public void addEquipmentTimeSeries(Object timeSeriesName, MappingVariable variable, String equipmentId) {
        if (timeSeriesName instanceof Number number) {
            addNumberTimeSeries(timeSeriesName.toString(), number.floatValue());
        } else {
            timeSeriesExists(timeSeriesName.toString());
        }
        config.addEquipmentTimeSeries(timeSeriesName.toString(), variable, equipmentId);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy