Skip to content

Aggregations

FINE aggregation modules provide additional functionalities for reducing the complexity of spatially highly-resolved models.

Spatial Aggregation

manager

Manager function that calls spatial grouping and aggregation algorithm.

Functions:

perform_spatial_aggregation

perform_spatial_aggregation(
    xr_datasets,
    shapefile,
    grouping_mode="parameter_based",
    n_groups=3,
    distance_threshold=None,
    aggregatedResultsPath=None,
    **kwargs,
)

Perform spatial grouping of regions (by calling the functions in grouping.py) and then representation of the data within each region group (by calling functions in representation.py).

:param xr_datasets: Either the path to .netCDF file or the read-in xarray datasets\n * Dimensions in the datasets: 'time', 'space', 'space_2' :type xr_datasets: str/Dict[str, xr.Dataset]

:param shapefile: Either the path to the shapefile or the read-in shapefile :type shapefile: str/GeoDataFrame

Default arguments:

:param grouping_mode: Defines how to spatially group the regions. Refer to grouping.py for more information. |br| * the default value is 'parameter_based' :type grouping_mode: str, one of {'parameter_based', 'string_based', 'distance_based'}

:param n_groups: The number of region groups to be formed from the original region set. This parameter is irrelevant if grouping_mode is 'string_based'. |br| * the default value is 3 :type n_groups: strictly positive int

:param distance_threshold: The distance threshold at or above which regions will not be aggregated into one. |br| * the default value is None. If not None, n_groups must be None :type distance_threshold: float

:param aggregatedResultsPath: Indicates path to which the aggregated results should be saved. If None, results are not saved. |br| * the default value is None :type aggregatedResultsPath: str

Additional keyword arguments that can be passed via kwargs:

:param geom_col_name: The geomtry column name in shapefile |br| * the default value is 'geometry' :type geom_col_name: str

:param geom_id_col_name: The colum in shapefile consisting geom IDs |br| * the default value is 'index' :type geom_id_col_name: str

:param geom_id_col_name: The colum in shapefile consisting geom IDs |br| * the default value is 'index' :type geom_id_col_name: str

:param separator: Relevant only if grouping_mode is 'string_based'. The character or string in the region IDs that defines where the ID should be split.\n E.g.: region IDs -> ['01_es', '02_es'] and separator='_', then IDs are split at _ and the last part ('es') is taken as the group ID

|br| * the default value is None

:type separator: str

:param position: Relevant only if grouping_mode is 'string_based'. Used to define the position(s) of the region IDs where the split should happen. An int i would mean the part from 0 to i is taken as the group ID. A tuple (i,j) would mean the part i to j is taken at the group ID.

.. note:: either `separator` or `position` must be passed in order to perform string_based_grouping

|br| * the default value is None

:type position: int/tuple

:param weights: Relevant only if grouping_mode is 'parameter_based'. Through the weights dictionary, one can assign weights to variable-component pairs. When calculating distance corresonding to each variable-component pair, these specified weights are considered, otherwise taken as 1.

It must be in one of the formats:

* If you want to specify weights for particular variables and particular corresponding components:\n
    { 'components' : Dict[<component_name>, <weight>}], 'variables' : List[<variable_name>] }

* If you want to specify weights for particular variables, but all corresponding components:\n
    { 'components' : {'all' : <weight>}, 'variables' : List[<variable_name>] }

* If you want to specify weights for all variables, but particular corresponding components:\n
    { 'components' : Dict[<component_name>, <weight>}], 'variables' : 'all' }

<weight> can be of type int/float
|br| * the default value is None

:type weights: Dict

:param aggregation_method: Relevant only if grouping_mode is 'parameter_based'. The clustering method that should be used to group the regions. Options:

    * 'kmedoids_contiguity':
        kmedoids clustering with added contiguity constraint.
        Refer to TSAM docs for more info: https://github.com/FZJ-IEK3-VSA/tsam/blob/master/tsam/utils/k_medoids_contiguity.py
    * 'hierarchical':
        sklearn's agglomerative clustering with complete linkage, with a connetivity matrix to ensure contiguity.
        Refer to Sklearn docs for more info: https://scikit-learn.org/stable/modules/generated/sklearn.cluster.AgglomerativeClustering.html

|br| * the default value is 'kmedoids_contiguity'

:type aggregation_method: str, one of {'kmedoids_contiguity', 'hierarchical'}

:param skip_regions: The region IDs to be skipped while aggregating regions

.. note:: currently only implemented for `grouping_mode` 'distance_based'

|br| * the default value is None

:type skip_regions: List[str]

:param enforced_groups: The groups that should be enforced when aggregating regions.

.. note:: currently only implemented for `grouping_mode` 'distance_based'

|br| * the default value is None

:type enforced_groups: Dict[str, List[str]]

:param solver: Relevant only if grouping_mode is 'parameter_based' and aggregation_method is 'kmedoids_contiguity'. The optimization solver to be chosen. |br| * the default value is 'gurobi' :type solver: str

:param solver: Relevant only if grouping_mode is 'parameter_based' and aggregation_method is 'kmedoids_contiguity'. The optimization solver to be chosen. |br| * the default value is 'gurobi' :type solver: str

:param aggregation_function_dict: - Contains information regarding the mode of aggregation for each individual variable.

* Possibilities: mean, weighted mean, sum, bool (boolean OR).
* Format of the dictionary:

    {<variable_name>: (<mode_of_aggregation>, <weights>),
    <variable_name>: (<mode_of_aggregation>, None)}

  <weights> is required only if <mode_of_aggregation> is
  'weighted mean'. The name of the variable that should act as weights should be provided. Can be None otherwise.

.. note::
    A default dictionary is considered with the following corresponding modes. If `aggregation_function_dict` is
    passed, this default dictionary is updated. The default dictionary:

    {\n
    "operationRateMax": ("weighted mean", "capacityMax"),\n
    "operationRateFix": ("sum", None),\n
    "locationalEligibility": ("bool", None),\n
    "capacityMax": ("sum", None),\n
    "investPerCapacity": ("mean", None),\n
    "investIfBuilt": ("bool", None),\n
    "opexPerOperation": ("mean", None),\n
    "opexPerCapacity": ("mean", None),\n
    "opexIfBuilt": ("bool", None),\n
    "interestRate": ("mean", None),\n
    "economicLifetime": ("mean", None),\n
    "capacityFix": ("sum", None),\n
    "losses": ("mean", None),\n
    "distances": ("mean", None),\n
    "commodityCost": ("mean", None),\n
    "commodityRevenue": ("mean", None),\n
    "opexPerChargeOperation": ("mean", None),\n
    "opexPerDischargeOperation": ("mean", None),\n
    "QPcostScale": ("sum", None),\n
    "technicalLifetime": ("mean", None),\n
    "balanceLimit": ("sum", None)\n
    "pathwayBalanceLimit": ("sum", None)\n
    }

|br| * the default value is None

:type aggregation_function_dict: Dict[str, Tuple(str, None/str)]

:param aggregated_shp_name: Name to be given to the saved shapefiles after aggregation |br| * the default value is 'aggregated_regions' :type aggregated_shp_name: str

:param crs: Coordinate reference system (crs) in which to save the shapefiles |br| * the default value is 3035 :type crs: int

:param aggregated_xr_filename: Name to be given to the saved netCDF file containing aggregated esM data |br| * the default value is 'aggregated_xr_dataset.nc' :type aggregated_xr_filename: str

:returns: aggregated_xr_dataset - The xarray datasets holding aggregated data :rtype: Dict[str, xr.Dataset]

Technology Aggregation

techAggregation

Aggregation of RE technologies in every region.

Functions:

aggregate_RE_technology

aggregate_RE_technology(
    gridded_RE_ds=None,
    CRS_attr=None,
    shp_file=None,
    non_gridded_RE_ds=None,
    n_timeSeries_perRegion=1,
    capacity_var_name="capacity",
    capfac_var_name="capacity factor",
    region_var_name="region",
    longitude_dim_name="x",
    latitude_dim_name="y",
    time_dim_name="time",
    location_dim_name="locations",
    shp_index_col="region_ids",
    shp_geometry_col="geometry",
    linkage="average",
)

Reduce the number of a particular RE technology (e.g. onshore wind turbine) to a desired number, within each region.

.. note:: The explanation below uses wind turbines as an example. It could, in reality, be any variable RE technology like PV, offshore wind turbine, etc.

The number of simulated wind turbines could be huge. This function reduces them to a few turbine types, in each of the defined region. Each wind turbine is characterised by its capacity and capacity factor time series.

The basic idea here is to group the turbines, within each region, such that the turbines with most similar capacity factor time series appear in the same group. Next, the turbines in each group are aggregated to obtain one turbine type, per group, thereby reducing the total number of turbines.

Please go through the parameters list below for more information.

Default arguments:

:param gridded_RE_ds: Either the path to the dataset or the read-in xr.Dataset

* Dimensions in this data - `latitude_dim_name`, `longitude_dim_name`, and `time_dim_name`
* Variables: `capacity_var_name` and `capfac_var_name`

:type gridded_RE_ds: str/xr.Dataset

:param CRS_attr: The attribute in gridded_RE_ds that holds its Coordinate Reference System (CRS) information :type CRS_attr: str

:param shp_file: Either the path to the shapefile or the read-in shapefile that should be overlapped with gridded_RE_ds, in order to obtain regions' information :type shp_file: str/GeoDataFrame

:param non_gridded_RE_ds: Either the path to the dataset or the read-in xr.Dataset

* Dimensions in this data - `location_dim_name` and `time_dim_name`
* Variables - `capacity_var_name`, `capfac_var_name`, and `region_var_name`

One can either pass `gridded_RE_ds` or `non_gridded_RE_ds` to work with. If both are passed,
`gridded_RE_ds` is considered

:type non_gridded_RE_ds: str/xr.Dataset

:param n_timeSeries_perRegion: The number of time series to which the original set should be aggregated, within each region.

* If set to 1, performs simple aggregation

    - Within every region, calculates the weighted mean of RE
      time series (capacities being weights), and sums the capacities.

* If set to a value greater than 1, time series clustering is employed

    - Clustering method: Sklearn's agglomerative hierarchical clustering
    - Distance measure: Euclidean distance
    - Aggregation within each resulting cluster is the same as simple
      aggregation

|br| * the default value is 1

:type n_timeSeries_perRegion: strictly positive int

:param capacity_var_name: The name of the data variable in the provided dataset that corresponds to capacity |br| * the default value is 'capacity' :type capacity_var_name: str

:param capfac_var_name: The name of the data variable in the provided dataset that corresponds to capacity factor time series |br| * the default value is 'capacity factor' :type capfac_var_name: str

:param region_var_name: The name of the data variable in non_gridded_RE_ds that contains region IDs |br| * the default value is 'region' :type region_var_name: str

:param longitude_dim_name: The dimension name in gridded_RE_ds that corresponds to longitude |br| * the default value is 'x' :type longitude_dim_name: str

:param latitude_dim_name: The dimension name in gridded_RE_ds that corresponds to latitude |br| * the default value is 'y' :type latitude_dim_name: str

:param time_dim_name: The dimension name in in the provided dataset that corresponds to time |br| * the default value is 'time' :type time_dim_name: str

:param location_dim_name: The dimension name in non_gridded_RE_ds that corresponds to locations |br| * the default value is 'locations' :type location_dim_name: str

:param shp_index_col: The column in shp_file that needs to be taken as location-index in gridded_RE_ds |br| * the default value is 'region_ids' :type shp_index_col: str

:param shp_geometry_col: The column in shp_file that holds geometries |br| * the default value is 'geometry' :type shp_geometry_col: str

:param linkage:

* Relevant only if `n_timeSeries_perRegion` is greater than 1.
* The linkage criterion to be used with agglomerative hierarchical clustering.
  Can be 'complete', 'single', etc. Refer to Sklearn's documentation for more info.

|br| * the default value is 'average'

:type linkage: str

:returns: regional_aggregated_RE_ds

* Dimensions in this data: `time_dim_name`, 'region_ids'
* The dimension 'region_ids' has its coordinates corresponding to `shp_index_col` if
    `gridded_RE_ds` is passed. Otherwise, it corresponds to `region_var_name` values

If `n_timeSeries_perRegion` is greater than 1, additional dimension - 'TS_ids' is present
* Within each region, different time series are indicated by this 'TS_ids'

* In addition, the dataset also contains attributes which indicate which time series were
    clustered. Calling represented_RE_ds.attrs would render a dictionary that contains
    <region_ids>.<TS_ids> as keys and a list of original locations as values. In case of
    `gridded_RE_ds`, these locations are a tuple - (x/longitude, y/latitude)

:rtype: xr.Dataset