Skip to content

This file contains the methods used to generate postprocessed data tables that are available by default in the model results.

calliope.postprocess.postprocess.capacity_factor(results, model_data, systemwide=False)

Calculation of capacity factors.

Processes whether flow_cap is a parameter or a result, then calculates the capacity factor.

The weight of timesteps is considered when computing systemwide capacity factors, such that higher-weighted timesteps have a stronger influence on the resulting system-wide time-averaged capacity factor.

Source code in src/calliope/postprocess/postprocess.py
def capacity_factor(
    results: xr.Dataset, model_data: xr.Dataset, systemwide=False
) -> xr.DataArray:
    """Calculation of capacity factors.

    Processes whether `flow_cap` is a parameter or a result, then calculates the
    capacity factor.

    The weight of timesteps is considered when computing systemwide capacity factors,
    such that higher-weighted timesteps have a stronger influence on the resulting
    system-wide time-averaged capacity factor.
    """
    # In operate mode, flow_cap is an input parameter
    if "flow_cap" not in results.keys():
        flow_cap = model_data.flow_cap
    else:
        flow_cap = results.flow_cap

    if systemwide:
        prod_sum = (results["flow_out"] * model_data.timestep_weights).sum(
            dim=["timesteps", "nodes"], min_count=1
        )

        cap_sum = flow_cap.where(lambda x: x > 0)
        if "nodes" in cap_sum.dims:
            cap_sum = cap_sum.sum(dim="nodes", min_count=1)
        time_sum = (model_data.timestep_resolution * model_data.timestep_weights).sum()

        capacity_factors = (prod_sum / (cap_sum * time_sum)).fillna(0)
    else:
        capacity_factors = (
            results["flow_out"]
            / (flow_cap.where(lambda x: x > 0) * model_data.timestep_resolution)
        ).where(results["flow_out"].notnull())

    return capacity_factors

calliope.postprocess.postprocess.systemwide_levelised_cost(results, model_data, total=False)

Calculates systemwide levelised costs.

Returns a DataArray with systemwide levelised costs for the given results, indexed by techs, carriers and costs if total is False, or by carriers and costs if total is True.

The weight of timesteps is considered when computing levelised costs:

  • costs are already multiplied by weight in the constraints, and not further adjusted here.

  • production (flow_out + flow_export) is not multiplied by weight in the constraints, so scaled by weight here to be consistent with costs. CAUTION: this scaling is temporary during levelised cost computation - the actual costs in the results remain untouched.

Parameters:

Name Type Description Default
results Dataset

Model results.

required
model_data Dataset

Model input data.

required
total bool

If False (default) returns per-technology levelised cost, if True, returns overall system-wide levelised cost.

False

Returns:

Type Description
DataArray

xr.DataArray: Array of levelised costs.

Source code in src/calliope/postprocess/postprocess.py
def systemwide_levelised_cost(
    results: xr.Dataset, model_data: xr.Dataset, total: bool = False
) -> xr.DataArray:
    """Calculates systemwide levelised costs.

    Returns a DataArray with systemwide levelised costs for the given
    results, indexed by techs, carriers and costs if total is False,
    or by carriers and costs if total is True.

    The weight of timesteps is considered when computing levelised costs:

    * costs are already multiplied by weight in the constraints, and not further adjusted here.

    * production (`flow_out` + `flow_export`) is not multiplied by weight in the constraints,
      so scaled by weight here to be consistent with costs.
      CAUTION: this scaling is temporary during levelised cost computation -
      the actual costs in the results remain untouched.

    Args:
        results (xarray.Dataset): Model results.
        model_data (xarray.Dataset): Model input data.
        total (bool, optional):
            If False (default) returns per-technology levelised cost, if True,
            returns overall system-wide levelised cost.

    Returns:
        xr.DataArray: Array of levelised costs.
    """
    # Here we scale production by timestep weight
    cost = results["cost"].sum(dim="nodes", min_count=1)
    generation = (
        (results["flow_out"] + results.get("flow_export", xr.DataArray(0)).fillna(0))
        * model_data.timestep_weights
    ).sum(dim=["timesteps", "nodes"], min_count=1)

    if total:
        # `cost` is the total cost of the system
        # `generation`` is only the generation of supply and conversion technologies
        allowed_techs = ("supply", "conversion")
        valid_techs = model_data.base_tech.isin(allowed_techs)
        cost = cost.sum(dim="techs", min_count=1)
        generation = generation.sel(techs=valid_techs).sum(dim="techs", min_count=1)

    levelised_cost = cost / generation.where(lambda x: x > 0)

    return levelised_cost