Calliope

Following sections give detailed instructions on how to create ready-to-use energy systems using calliope.core.model.Model objects.

Concept

Calliope aims to be a free and open source framework for energy system modelling and optimization. It is being developed on GitHub.

Calliope consists of a pyomo interface for modelling energy supply system components using linear and mixed integer linear problem formulation. By providing a very general approach (calliope components) Calliope tries to satisfy the most common use cases.

Unlike FINE, Oemof and PyPSA a Calliope model data is going to be stored in .yaml and .csv files. Alternatively these data can be read from python dictionaries and pandas dataframes, but in Tessif yaml and csv files are going to be used, since calliope refers to the easier human readability of the yaml files, A comparatively small py_hard does exist though.

Purpose

Within the context of Tessif, Calliope serves another pyomo solver interface with the goal to optimize the system for the minimum costs. Calliope could do an emission minimization as well, but in Tessif emissions are only constraint by a maximum allowed, while minimum costs are the target.

Using Calliope through Tessif is somewhat of a challenge since the parameterization on some components differ quite a lot and others might not even be included in Calliope. Nevertheless there are still enough components with a similar to same parameterization to transform a Tessif's Energy System into a calliope.core.model.Model.

USP

Calliope provides one feature that is not included in Tessif but has to be mentioned here as a unique selling point. This is the so called Spores mode which allows to calculate alternative results that are more expensive than the optimal result (the allowed cost range is user defined relatively to optimum) but differ in usage of technologies and therefore might present an interesting result fitting with socially or politically issues that are not represented inside the model parameters.

Examples

Minimum Working Example

  1. Create the model.yaml which is going to be called to build the energy system model

import:
  - mwe_config/locations.yaml
  - mwe_config/techs.yaml

model:
  name: Minimum_Working_Example
  calliope_version: 0.6.6-post1
  timeseries_data_path: mwe_data
  subset_time:
  - '1990-07-13 00:00:00'
  - '1990-07-13 03:00:00'

run:
  solver: cbc
  cyclic_storage: false
  objective_options.cost_class:
    monetary: 1
  1. Create the model_config/techs.yaml file holding the technology information.

techs:

  # build a demand
  # NOTE: Can't be named demand due to the name being blocked by its parent.
  # Thus it is going to be renamed using the carrier.
  electricity_Demand:
    essentials:
      name: Demand
      parent: demand
      carrier: electricity
    constraints:
      energy_con: true
      resource_unit: energy
      resource: file=electricity_Demand.csv:electricity_Demand
      force_resource: true

  Gas Station:
    essentials:
      name: Gas Station
      parent: supply
      carrier_out: fuel
    constraints:
      resource: .inf
      energy_ramping: true

  Generator:
    essentials:
      name: Generator
      parent: conversion
      carrier_in: fuel
      carrier_out: electricity
    constraints:
      energy_eff: 0.42
      energy_ramping: true
    costs:
      monetary:
        om_prod: 2

  Battery:
    essentials:
      name: Battery
      parent: storage
      carrier: electricity
    constraints:
      storage_cap_max: 20
      energy_cap_min: 20
      energy_cap_max: 20
      energy_ramping: true
      storage_cap_min: 20
      storage_initial: 0.5
    costs:
      monetary:
        om_prod: 0.1

  fuel transmission:
    essentials:
      name: fuel transmission
      parent: transmission
      carrier: fuel
    constraints:
      one_way: true

  electricity transmission:
    essentials:
      name: electricity transmission
      parent: transmission
      carrier: electricity
    constraints:
      one_way: true
  1. Create the model_config/locations.yaml file holding the locations information. Each technology is going to be called in a separated location. This way calliope can be used with tessif energy systems and post processing.

locations:

  Pipeline:
    coordinates: {lat: 0.0, lon: 0.0}

  Powerline:
    coordinates: {lat: 0.0, lon: 0.0}

  electricity_Demand location:
    coordinates: {lat: 0.0, lon: 0.0}
    techs:
      electricity_Demand:

  Gas Station location:
    coordinates: {lat: 0.0, lon: 0.0}
    techs:
      Gas Station:

  Generator location:
    coordinates: {lat: 0.0, lon: 0.0}
    techs:
      Generator:

  Battery location:
    coordinates: {lat: 0.0, lon: 0.0}
    techs:
      Battery:

# links do connect the different locations using a transmission technology
links:

  Gas Station location,Pipeline:
    techs:
      fuel transmission:
        constraints:
          one_way: true

  Pipeline,Generator location:
    techs:
      fuel transmission:
        constraints:
          one_way: true

  Battery location,Powerline:
    techs:
      electricity transmission:
        constraints:
          one_way: false

  Generator location,Powerline:
    techs:
      electricity transmission:
        constraints:
          one_way: true

  Powerline,electricity_Demand location:
    techs:
      electricity transmission:
        constraints:
          one_way: true

Note

The presented example yaml files are identical to those in tessifexamplesdatacalliopemwe.

  1. Save the timeseries data in a .csv file. From this point on python is going to be used.

import pandas as pd
import numpy as np
from tessif.frused.paths import example_dir

simulation_time = pd.date_range(
'7/13/1990', periods=4, freq='H')

demand_timeseries = np.array(4*[-10])

demand_timeseries = pd.DataFrame({'': simulation_time, 'electricity_Demand': demand_timeseries})

# commented out for better doctesting
# timeseries.to_csv(
#     os.path.join(
#         example_dir, 'data', 'calliope', 'timeseries_data', f'mwe_electricity_Demand.csv'), index=False)

Note

Each Calliope model needs at least one timeseries.

  1. Build and optimize the model.

    >>> from tessif.frused.paths import example_dir
    >>> import calliope
    
    >>> es = calliope.Model(f'{example_dir}/data/calliope/mwe/model.yaml')
    >>> es.run()
    
  2. Confirm the expected output.

    >>> for loc in sorted(es.inputs.locs.data):
    ...     print(loc)
    Battery location
    Gas Station location
    Generator location
    Pipeline
    Powerline
    electricity_Demand location
    
    >>> for tech in sorted(es.inputs.techs.data):
    ...     print(tech)
    Battery
    Gas Station
    Generator
    electricity transmission
    electricity_Demand
    fuel transmission
    

7. For examples on how to extract result information out ouf the optimized energy system using tessif, see tessif.transform.es2mapping.cllp