Built-in example models

This section gives a listing of all the YAML configuration files included in the built-in example models. Refer to the tutorials section for a brief overview of how these parts together provide a working model.

The example models are accessible in the calliope.examples module. To create an instance of an example model, call its constructor function, e.g.:

urban_model = calliope.examples.urban_scale()

The available example models and their constructor functions are:

calliope.examples.national_scale(*args, **kwargs)[source]

Returns the built-in national-scale example model.

calliope.examples.time_clustering(*args, **kwargs)[source]

Returns the built-in national-scale example model with time clustering.

calliope.examples.time_resampling(*args, **kwargs)[source]

Returns the built-in national-scale example model with time resampling.

calliope.examples.urban_scale(*args, **kwargs)[source]

Returns the built-in urban-scale example model.

calliope.examples.milp(*args, **kwargs)[source]

Returns the built-in urban-scale example model with MILP constraints enabled.

calliope.examples.operate(*args, **kwargs)[source]

Returns the built-in urban-scale example model in operate mode.

calliope.examples.time_masking(*args, **kwargs)[source]

Returns the built-in urban-scale example model with time masking.

National-scale example

Available as calliope.examples.national_scale.

Model settings

The layout of the model directory is as follows (+ denotes directories, - files):

- model.yaml
- scenarios.yaml
+ timeseries_data
    - csp_resource.csv
    - demand-1.csv
    - demand-2.csv
+ model_config
    - locations.yaml
    - techs.yaml

model.yaml:

import:  # Import other files from paths relative to this file, or absolute paths
    - 'model_config/techs.yaml'  # This file specifies the model's technologies
    - 'model_config/locations.yaml'  # This file specifies the model's locations
    - 'scenarios.yaml'  # Scenario and override group definitions

# Model configuration: all settings that affect the built model
model:
    name: National-scale example model

    # What version of Calliope this model is intended for
    calliope_version: 0.6.4

    # Time series data path - can either be a path relative to this file, or an absolute path
    timeseries_data_path: 'timeseries_data'

    subset_time: ['2005-01-01', '2005-01-05']  # Subset of timesteps

# Run configuration: all settings that affect how the built model is run
run:
    solver: cbc

    ensure_feasibility: true  # Switches on the "unmet demand" constraint

    bigM: 1e6  # Sets the scale of unmet demand, which cannot be too high, otherwise the optimisation will not converge

    zero_threshold: 1e-10  # Any value coming out of the backend that is smaller than this (due to floating point errors, probably) will be set to zero

    mode: plan  # Choices: plan, operate

scenarios.yaml:

##
# Scenarios are optional, named combinations of overrides
##
scenarios:
    cold_fusion_with_production_share: ['cold_fusion', 'cold_fusion_prod_share']
    cold_fusion_with_capacity_share: ['cold_fusion', 'cold_fusion_cap_share']


##
# Overrides are the building blocks from which scenarios can be defined
##
overrides:
    profiling:
        model.name: 'National-scale example model (profiling run)'
        model.subset_time: ['2005-01-01', '2005-01-15']
        run.solver: cbc

    time_resampling:
        model.name: 'National-scale example model with time resampling'
        model.subset_time: '2005-01'
        # Resample time resolution to 6-hourly
        model.time: {function: resample, function_options: {'resolution': '6H'}}

    time_clustering:
        model.random_seed: 23
        model.name: 'National-scale example model with time clustering'
        model.subset_time: null  # No time subsetting
        # Cluster timesteps using k-means
        model.time: {function: apply_clustering, function_options: {clustering_func: 'kmeans', how: 'closest', k: 10}}

    operate:
        run.mode: operate
        run.operation:
            window: 12
            horizon: 24
        model.subset_time: ['2005-01-01', '2005-01-10']
        locations:
            region1.techs.ccgt.constraints.energy_cap_equals: 30000

            region2.techs.battery.constraints.energy_cap_equals: 1000
            region2.techs.battery.constraints.storage_cap_equals: 5240

            region1-1.techs.csp.constraints.energy_cap_equals: 10000
            region1-1.techs.csp.constraints.storage_cap_equals: 244301
            region1-1.techs.csp.constraints.resource_area_equals: 130385

            region1-2.techs.csp.constraints.energy_cap_equals: 0
            region1-2.techs.csp.constraints.storage_cap_equals: 0
            region1-2.techs.csp.constraints.resource_area_equals: 0

            region1-3.techs.csp.constraints.energy_cap_equals: 2534
            region1-3.techs.csp.constraints.storage_cap_equals: 25301
            region1-3.techs.csp.constraints.resource_area_equals: 8487

        links:
            region1,region2.techs.ac_transmission.constraints.energy_cap_equals: 3231
            region1,region1-1.techs.free_transmission.constraints.energy_cap_equals: 9000
            region1,region1-2.techs.free_transmission.constraints.energy_cap_equals: 0
            region1,region1-3.techs.free_transmission.constraints.energy_cap_equals: 2281

    check_feasibility:
        run:
            ensure_feasibility: False
            objective: 'check_feasibility'
        model:
            subset_time: '2005-01-04'

    reserve_margin:
        model:
            # Model-wide settings for the system-wide reserve margin
            # Even setting a reserve margin of zero activates the constraint,
            # forcing enough installed capacity to cover demand in
            # the maximum demand timestep
            reserve_margin:
                power: 0.10  # 10% reserve margin for power

    ##
    # Overrides to demonstrate the run generator ("calliope generate_runs")
    ##

    run1:
        model.subset_time: ['2005-01-01', '2005-01-31']
    run2:
        model.subset_time: ['2005-02-01', '2005-02-31']
    run3:
        model.subset_time: ['2005-01-01', '2005-01-31']
        locations.region1.techs.ccgt.constraints.energy_cap_max: 0  # Disallow CCGT
    run4:
        subset_time: ['2005-02-01', '2005-02-31']
        locations.region1.techs.ccgt.constraints.energy_cap_max: 0  # Disallow CCGT

    ##
    # Overrides to demonstrate group constraints
    ##

    cold_fusion:  # Defines a hypothetical cold fusion tech to use in group constraints
        techs:
            cold_fusion:
                essentials:
                    name: 'Cold fusion'
                    color: '#233B39'
                    parent: supply
                    carrier_out: power
                constraints:
                    energy_cap_max: 10000
                    lifetime: 50
                costs:
                    monetary:
                        interest_rate: 0.20
                        energy_cap: 100
        locations.region1.techs.cold_fusion: null
        locations.region2.techs.cold_fusion: null

    cold_fusion_prod_share:
        group_constraints:
            min_supply_share_group:
                techs: ['csp', 'cold_fusion']
                supply_share_min:
                    # At least 85% of power supply must come from CSP and cold fusion together
                    power: 0.85

    cold_fusion_cap_share:
        group_constraints:
            max_cap_share_group:
                techs: ['csp', 'cold_fusion']
                # At most 20% of total energy_cap can come from CSP and cold fusion together
                energy_cap_share_max: 0.20
        locations:
            region1:
                techs:
                    ccgt:
                        constraints:
                            energy_cap_max: 100000  # Increased to keep model feasible

    minimize_emissions_costs:
        run:
            objective_options:
                cost_class: {'emissions': 1, 'monetary': 0}
        techs:
            ccgt:
                costs:
                    emissions:
                        om_prod: 100 # kgCO2/kWh
            csp:
                costs:
                    emissions:
                        om_prod: 10 # kgCO2/kWh

    maximize_utility_costs:
        run:
            objective_options:
                cost_class: {'utility': 1 , 'monetary': 0}
                sense: maximize
        techs:
            ccgt:
                costs:
                    utility:
                        om_prod: 10 # arbitrary utility value
            csp:
                costs:
                    utility:
                        om_prod: 100 # arbitrary utility value

techs.yaml:

##
# TECHNOLOGY DEFINITIONS
##

# Note: '-start' and '-end' is used in tutorial documentation only

techs:

    ##
    # Supply
    ##

    # ccgt-start
    ccgt:
        essentials:
            name: 'Combined cycle gas turbine'
            color: '#E37A72'
            parent: supply
            carrier_out: power
        constraints:
            resource: inf
            energy_eff: 0.5
            energy_cap_max: 40000  # kW
            energy_cap_max_systemwide: 100000  # kW
            energy_ramping: 0.8
            lifetime: 25
        costs:
            monetary:
                interest_rate: 0.10
                energy_cap: 750  # USD per kW
                om_con: 0.02  # USD per kWh
    # ccgt-end

    # csp-start
    csp:
        essentials:
            name: 'Concentrating solar power'
            color: '#F9CF22'
            parent: supply_plus
            carrier_out: power
        constraints:
            storage_cap_max: 614033
            energy_cap_per_storage_cap_max: 1
            storage_loss: 0.002
            resource: file=csp_resource.csv
            resource_unit: energy_per_area
            energy_eff: 0.4
            parasitic_eff: 0.9
            resource_area_max: inf
            energy_cap_max: 10000
            lifetime: 25
        costs:
            monetary:
                interest_rate: 0.10
                storage_cap: 50
                resource_area: 200
                resource_cap: 200
                energy_cap: 1000
                om_prod: 0.002
    # csp-end

    ##
    # Storage
    ##
    # battery-start
    battery:
        essentials:
            name: 'Battery storage'
            color: '#3B61E3'
            parent: storage
            carrier: power
        constraints:
            energy_cap_max: 1000  # kW
            storage_cap_max: inf
            energy_cap_per_storage_cap_max: 4
            energy_eff: 0.95  # 0.95 * 0.95 = 0.9025 round trip efficiency
            storage_loss: 0  # No loss over time assumed
            lifetime: 25
        costs:
            monetary:
                interest_rate: 0.10
                storage_cap: 200  # USD per kWh storage capacity
    # battery-end

    ##
    # Demand
    ##
    # demand-start
    demand_power:
        essentials:
            name: 'Power demand'
            color: '#072486'
            parent: demand
            carrier: power
    # demand-end

    ##
    # Transmission
    ##

    # transmission-start
    ac_transmission:
        essentials:
            name: 'AC power transmission'
            color: '#8465A9'
            parent: transmission
            carrier: power
        constraints:
            energy_eff: 0.85
            lifetime: 25
        costs:
            monetary:
                interest_rate: 0.10
                energy_cap: 200
                om_prod: 0.002

    free_transmission:
        essentials:
            name: 'Local power transmission'
            color: '#6783E3'
            parent: transmission
            carrier: power
        constraints:
            energy_cap_max: inf
            energy_eff: 1.0
        costs:
            monetary:
                om_prod: 0
    # transmission-end

locations.yaml:

##
# LOCATIONS
##

locations:
    # region-1-start
    region1:
        coordinates: {lat: 40, lon: -2}
        techs:
            demand_power:
                constraints:
                    resource: file=demand-1.csv:demand
            ccgt:
                constraints:
                    energy_cap_max: 30000 # increased to ensure no unmet_demand in first timestep
    # region-1-end
    # other-locs-start
    region2:
        coordinates: {lat: 40, lon: -8}
        techs:
            demand_power:
                constraints:
                    resource: file=demand-2.csv:demand
            battery:

    region1-1.coordinates: {lat: 41, lon: -2}
    region1-2.coordinates: {lat: 39, lon: -1}
    region1-3.coordinates: {lat: 39, lon: -2}

    region1-1, region1-2, region1-3:
        techs:
            csp:
    # other-locs-end

##
# TRANSMISSION CAPACITIES
##

links:
    # links-start
    region1,region2:
        techs:
            ac_transmission:
                constraints:
                    energy_cap_max: 10000
    region1,region1-1:
        techs:
            free_transmission:
    region1,region1-2:
        techs:
            free_transmission:
    region1,region1-3:
        techs:
            free_transmission:
    # links-end

Urban-scale example

Available as calliope.examples.urban_scale.

Model settings

model.yaml:

import:  # Import other files from paths relative to this file, or absolute paths
    - 'model_config/techs.yaml'
    - 'model_config/locations.yaml'
    - 'scenarios.yaml'

model:
    name: Urban-scale example model

    # What version of Calliope this model is intended for
    calliope_version: 0.6.4

    # Time series data path - can either be a path relative to this file, or an absolute path
    timeseries_data_path: 'timeseries_data'

    subset_time: ['2005-07-01', '2005-07-02']  # Subset of timesteps

run:
    mode: plan  # Choices: plan, operate

    solver: cbc

    ensure_feasibility: true # Switching on unmet demand

    bigM: 1e6 # setting the scale of unmet demand, which cannot be too high, otherwise the optimisation will not converge

scenarios.yaml:

##
# Overrides for different example model configuratiions
##

overrides:
    milp:
        model.name: 'Urban-scale example model with MILP'
        run.solver_options.mipgap: 0.05
        techs:
            # chp-start
            chp:
                constraints:
                    units_max: 4
                    energy_cap_per_unit: 300
                    energy_cap_min_use: 0.2
                costs:
                    monetary:
                        energy_cap: 700
                        purchase: 40000
            # chp-end
            # boiler-start
            boiler:
                costs:
                    monetary:
                        energy_cap: 35
                        purchase: 2000
            # boiler-end
            # heat_pipes-start
            heat_pipes:
                constraints:
                    force_asynchronous_prod_con: true
            # heat_pipes-end

    mapbox_ready:
        locations:
            X1.coordinates: {lat: 51.4596158, lon: -0.1613446}
            X2.coordinates: {lat: 51.4652373, lon: -0.1141548}
            X3.coordinates: {lat: 51.4287016, lon: -0.1310635}
            N1.coordinates: {lat: 51.4450766, lon: -0.1247183}
        links:
            X1,X2.techs.power_lines.distance: 10
            X1,X3.techs.power_lines.istance: 5
            X1,N1.techs.heat_pipes.distance: 3
            N1,X2.techs.heat_pipes.distance: 3
            N1,X3.techs.heat_pipes.distance: 4

    operate:
        run.mode: operate
        run.operation:
            window: 24
            horizon: 48
        model.subset_time: ['2005-07-01', '2005-07-10']
        locations:
            X1:
                techs:
                    chp.constraints.energy_cap_max: 300
                    pv.constraints.energy_cap_max: 0
                    supply_grid_power.constraints.energy_cap_max: 40
                    supply_gas.constraints.energy_cap_max: 700

            X2:
                techs:
                    boiler.constraints.energy_cap_max: 200
                    pv.constraints.energy_cap_max: 70
                    supply_gas.constraints.energy_cap_max: 250

            X3:
                techs:
                    boiler.constraints.energy_cap_max: 0
                    pv.constraints.energy_cap_max: 50
                    supply_gas.constraints.energy_cap_max: 0

        links:
            X1,X2.techs.power_lines.constraints.energy_cap_max: 300
            X1,X3.techs.power_lines.constraints.energy_cap_max: 60
            X1,N1.techs.heat_pipes.constraints.energy_cap_max: 300
            N1,X2.techs.heat_pipes.constraints.energy_cap_max: 250
            N1,X3.techs.heat_pipes.constraints.energy_cap_max: 320

    time_masking:
        model.name: 'Urban-scale example model with time masking'
        model.subset_time: '2005-01'
        # Resample time resolution to 6-hourly
        model.time:
            masks:
                - {function: extreme_diff, options: {tech0: demand_heat, tech1: demand_electricity, how: max, n: 2}}
            function: resample
            function_options: {resolution: 6H}

techs.yaml:

##
# TECHNOLOGY DEFINITIONS
##

# Note: '-start' and '-end' is used in tutorial documentation only

# supply_power_plus-start
tech_groups:
    supply_power_plus:
        essentials:
            parent: supply_plus
            carrier: electricity
# supply_power_plus-end

techs:

##-GRID SUPPLY-##
    # supply-start
    supply_grid_power:
        essentials:
            name: 'National grid import'
            color: '#C5ABE3'
            parent: supply
            carrier: electricity
        constraints:
            resource: inf
            energy_cap_max: 2000
            lifetime: 25
        costs:
            monetary:
                interest_rate: 0.10
                energy_cap: 15
                om_con: 0.1 # 10p/kWh electricity price #ppt

    supply_gas:
        essentials:
            name: 'Natural gas import'
            color: '#C98AAD'
            parent: supply
            carrier: gas
        constraints:
            resource: inf
            energy_cap_max: 2000
            lifetime: 25
        costs:
            monetary:
                interest_rate: 0.10
                energy_cap: 1
                om_con: 0.025 # 2.5p/kWh gas price #ppt
    # supply-end

##-Renewables-##
    # pv-start
    pv:
        essentials:
            name: 'Solar photovoltaic power'
            color: '#F9D956'
            parent: supply_power_plus
        constraints:
            export_carrier: electricity
            resource: file=pv_resource.csv:per_area  # Already accounts for panel efficiency - kWh/m2. Source: Renewables.ninja Solar PV Power - Version: 1.1 - License: https://creativecommons.org/licenses/by-nc/4.0/ - Reference: https://doi.org/10.1016/j.energy.2016.08.060
            resource_unit: energy_per_area
            parasitic_eff: 0.85 # inverter losses
            energy_cap_max: 250
            resource_area_max: 1500
            force_resource: true
            resource_area_per_energy_cap: 7 # 7m2 of panels needed to fit 1kWp of panels
            lifetime: 25
        costs:
            monetary:
                interest_rate: 0.10
                energy_cap: 1350
    # pv-end

# Conversion
    # boiler-start
    boiler:
        essentials:
            name: 'Natural gas boiler'
            color: '#8E2999'
            parent: conversion
            carrier_out: heat
            carrier_in: gas
        constraints:
            energy_cap_max: 600
            energy_eff: 0.85
            lifetime: 25
        costs:
            monetary:
                interest_rate: 0.10
                om_con: 0.004  # .4p/kWh
    # boiler-end

# Conversion_plus
    # chp-start
    chp:
        essentials:
            name: 'Combined heat and power'
            color: '#E4AB97'
            parent: conversion_plus
            primary_carrier_out: electricity
            carrier_in: gas
            carrier_out: electricity
            carrier_out_2: heat
        constraints:
            export_carrier: electricity
            energy_cap_max: 1500
            energy_eff: 0.405
            carrier_ratios.carrier_out_2.heat: 0.8
            lifetime: 25
        costs:
            monetary:
                interest_rate: 0.10
                energy_cap: 750
                om_prod: 0.004  # .4p/kWh for 4500 operating hours/year
                export: file=export_power.csv
    # chp-end

##-DEMAND-##
    # demand-start
    demand_electricity:
        essentials:
            name: 'Electrical demand'
            color: '#072486'
            parent: demand
            carrier: electricity

    demand_heat:
        essentials:
            name: 'Heat demand'
            color: '#660507'
            parent: demand
            carrier: heat
    # demand-end

##-DISTRIBUTION-##
    # transmission-start
    power_lines:
        essentials:
            name: 'Electrical power distribution'
            color: '#6783E3'
            parent: transmission
            carrier: electricity
        constraints:
            energy_cap_max: 2000
            energy_eff: 0.98
            lifetime: 25
        costs:
            monetary:
                interest_rate: 0.10
                energy_cap_per_distance: 0.01

    heat_pipes:
        essentials:
            name: 'District heat distribution'
            color: '#823739'
            parent: transmission
            carrier: heat
        constraints:
            energy_cap_max: 2000
            energy_eff_per_distance: 0.975
            lifetime: 25
        costs:
            monetary:
                interest_rate: 0.10
                energy_cap_per_distance: 0.3
    # transmission-end

locations.yaml:

locations:
    # X1-start
    X1:
        techs:
            chp:
            pv:
            supply_grid_power:
                costs.monetary.energy_cap: 100 # cost of transformers
            supply_gas:
            demand_electricity:
                constraints.resource: file=demand_power.csv
            demand_heat:
                constraints.resource: file=demand_heat.csv
        available_area: 500
        coordinates: {x: 2, y: 7}
    # X1-end
    # other-locs-start
    X2:
        techs:
            boiler:
                costs.monetary.energy_cap: 43.1 # different boiler costs
            pv:
                costs.monetary:
                        om_prod: -0.0203 # revenue for just producing electricity
                        export: -0.0491 # FIT return for PV export
            supply_gas:
            demand_electricity:
                constraints.resource: file=demand_power.csv
            demand_heat:
                constraints.resource: file=demand_heat.csv
        available_area: 1300
        coordinates: {x: 8, y: 7}

    X3:
        techs:
            boiler:
                costs.monetary.energy_cap: 78 # different boiler costs
            pv:
                constraints:
                    energy_cap_max: 50 # changing tariff structure below 50kW
                costs.monetary:
                        om_annual: -80.5 # reimbursement per kWp from FIT
            supply_gas:
            demand_electricity:
                constraints.resource: file=demand_power.csv
            demand_heat:
                constraints.resource: file=demand_heat.csv
        available_area: 900
        coordinates: {x: 5, y: 3}
    # other-locs-end
    # N1-start
    N1: # location for branching heat transmission network
        coordinates: {x: 5, y: 7}
    # N1-end

links:
    # links-start
    X1,X2:
        techs:
            power_lines:
                distance: 10
    X1,X3:
        techs:
            power_lines:
    X1,N1:
        techs:
            heat_pipes:
    N1,X2:
        techs:
            heat_pipes:
    N1,X3:
        techs:
            heat_pipes:
    # links-end

Previous: More info (reference) | Next: Configuration reference