Configuration

PyPSA-ZA has several configuration options which are documented in this section and are collected in a config.yaml file located in the root directory. Users should copy the provided default configuration (config.default.yaml) and amend their own modifications and assumptions in the user-specific configuration file (config.yaml); confer installation instructions at Set Up the Default Configuration.

Top-level configuration

PyPSA-ZA imports the configuration options originally developed in PyPSA-Eur and here reported and adapted.

The options here described are collected in a config.yaml file located in the root directory. Users should copy the provided default configuration (config.default.yaml) and amend their own modifications and assumptions in the user-specific configuration file (config.yaml); confer installation instructions at Set Up the Default Configuration.

Note

Credits to PyPSA-Eur and PyPSA-meets-Earth developers for the initial drafting of the configuration documentation here reported

Top-level configuration

version: 2.0

logging:
  level: INFO
  format: "%(levelname)s:%(name)s:%(message)s"
  model_file: ['IRP_2019','validation_4']
  opts: [Co2L-3H,LC-1H]

# General inputs
data:
  resarea:
    redz: REDZ_DEA_Unpublished_Draft_2015

scenario

It is common conduct to analysis of energy system optimisation models for multiple scenarios for a variety of reasons, e.g. assessing their sensitivity towards changing the temporal and/or geographical resolution or investigating how investment changes as more ambitious greenhouse-gas emission reduction targets are applied.

The scenario section is an extraordinary section of the config file that is strongly connected to the Wildcards and is designed to facilitate running multiple scenarios through a single command

snakemake -j 1 solve_all_networks

For each wildcard, a list of values is provided. The rule solve_all_networks will trigger the rules for creating results/networks/solved_{model_file}_{regions}_{resarea}_l{ll}_{opts}.nc for all combinations of the provided wildcard values as defined by Python’s itertools.product(…) function that snakemake’s expand(…) function uses.

An exemplary dependency graph (starting from the simplification rules) then looks like this:

img/scenarios.png
scenario:
  resarea: [redz]
  regions: [27-supply]
  ll: ['copt']
  clusters: ['']
  model_file: ['IRP_2019','validation_4']
  opts: [Co2L-3H,LC-1H]

# General inputs

Unit

Values

Description

resarea

cf. The {resarea} wildcard

List of {resarea} wildcards to run.

regions

cf. The {regions} wildcard

List of {regions} wildcards to run.

model_file

cf. The {model_file} wildcard

List of {model_file} wildcards to run.

ll

cf. The {ll} wildcard

List of {ll} wildcards to run.

opts

cf. The {opts} wildcard

List of {opts} wildcards to run.

snapshots- now specified in model_file.xlsx

Specifies the temporal range to build an energy system model for as arguments to pandas.date_range

electricity

electricity:
  co2limit: 2.e+9    # 470.9e+5  Cumulative CO2 emissions budget for all simulation years combined
  renewable_carriers: [solar, onwind, CSP, biomass, hydro] # defines renewable carriers
  generator_availability: # generator planned and unplanned outages are included based on Eskom data
    implement_availability: true
    reference_years: [2021] #if multiple years specified an average is used
    new_unit_ref: 
    # New generator availability is based on an existing Eskom generator
    # in the format [generator, ref year/s (avg), rescale e.g 10% higher]
      coal: ['Lethabo', [2017], 1]
      OCGT: ['Ankerlig', [2017], 1]
      CCGT: ['Ankerlig', [2017], 1]
      nuclear: ['Koeberg', [2017], 1.1]

  # Only for new generators, existing generators are specified in model_file
  min_stable_levels:
    coal: 0 
    OCGT: 0 
    CCGT: 0
    nuclear: 0

  min_capacity_factor: # Minimum annual capacity factor 
    # TODO make per week
    CCGT: 0.3 
    nuclear: 0.5

  extendable_carriers:
    Renewables: ['onwind', solar]
    Generator: [CCGT, OCGT, coal, nuclear]
    StorageUnit: [battery, PHS] 

  buses:
    9_10_11-supply: 
      OCGT: [GAUTENG, WESTERN CAPE, KZN, EASTERN CAPE] # Saldana Bay, Richards Bay, Coega
      CCGT: [GAUTENG, WESTERN CAPE, KZN, EASTERN CAPE]
      coal: [GAUTENG, LIMPOPO] # Johannesburg, Waterberg
      nuclear: [EASTERN CAPE, WESTERN CAPE] # Thyspunt, Koeberg
      imports: [LIMPOPO]         
    27-supply:
      OCGT: [JOHANNESBURG, WEST COAST, EMPANGENI, PORT ELIZABETH] # Saldana Bay, Richards Bay, Coega
      CCGT: [JOHANNESBURG, WEST COAST, EMPANGENI, PORT ELIZABETH]
      coal: [JOHANNESBURG, WATERBERG]
      nuclear: [PORT ELIZABETH, PENINSULA] # Thyspunt, Koeberg
      imports: [POLOKWANE]
  
  SAFE_reservemargin: 0.1

  reserves:
    reserve_margin: # like https://genxproject.github.io/GenX/dev/core/#Reserves
      activate: false
      epsilon_load: 0.02 # share of total load
      epsilon_vres: 0.02 # share of total renewable supply
      contingency: 0 # fixed capacity in MW
    operating_reserves:
      fast: ['battery','PHS']
      total: ['diesel','gas','OCGT','CCGT','battery','PHS'] 
  max_hours:
    battery: 3
    PHS: 20
    H2: 10

Unit

Values

Description

voltages

kV

Any subset of {220., 300., 380.}

Voltage levels to consider

gaslimit

MWhth

float or false

Global gas usage limit

co2limit

\(t_{CO_2-eq}/a\)

float

Cap on total annual system carbon dioxide emissions

co2base

\(t_{CO_2-eq}/a\)

float

Reference value of total annual system carbon dioxide emissions if relative emission reduction target is specified in {opts} wildcard.

agg_p_nom_limits

file

path

Reference to .csv file specifying per carrier generator nominal capacity constraints for individual countries if 'CCL' is in {opts} wildcard. Defaults to data/agg_p_nom_minmax.csv.

operational_reserve

Settings for reserve requirements following like GenX

– activate

bool

true or false

Whether to take operational reserve requirements into account during optimisation

– epsilon_load

float

share of total load

– epsilon_vres

float

share of total renewable supply

– contingency

MW

float

fixed reserve capacity

max_hours

– battery

h

float

Maximum state of charge capacity of the battery in terms of hours at full output capacity p_nom. Cf. PyPSA documentation.

– H2

h

float

Maximum state of charge capacity of the hydrogen storage in terms of hours at full output capacity p_nom. Cf. PyPSA documentation.

extendable_carriers

– Generator

Any extendable carrier

Defines existing or non-existing conventional and renewable power plants to be extendable during the optimization. Conventional generators can only be built/expanded where already existent today. If a listed conventional carrier is not included in the conventional_carriers list, the lower limit of the capacity expansion is set to 0.

– StorageUnit

Any subset of {‘battery’,’H2’}

Adds extendable storage units (battery and/or hydrogen) at every node/bus after clustering without capacity limits and with zero initial capacity.

– Store

Any subset of {‘battery’,’H2’}

Adds extendable storage units (battery and/or hydrogen) at every node/bus after clustering without capacity limits and with zero initial capacity.

– Link

Any subset of {‘H2 pipeline’}

Adds extendable links (H2 pipelines only) at every connection where there are lines or HVDC links without capacity limits and with zero initial capacity. Hydrogen pipelines require hydrogen storage to be modelled as Store.

powerplants_filter

use pandas.query strings here, e.g. Country not in [‘Germany’]

Filter query for the default powerplant database.

custom_powerplants

use pandas.query strings here, e.g. Country in [‘Germany’]

Filter query for the custom powerplant database.

conventional_carriers

Any subset of {nuclear, oil, OCGT, CCGT, coal, lignite, geothermal, biomass}

List of conventional power plants to include in the model from resources/powerplants.csv. If an included carrier is also listed in extendable_carriers, the capacity is taken as a lower bound.

renewable_carriers

Any subset of {solar, onwind, offwind-ac, offwind-dc, hydro}

List of renewable generators to include in the model.

estimate_renewable_capacities

– enable

bool

Activate routine to estimate renewable capacities

– from_opsd

bool

Add capacities from OPSD data

– year

bool

Renewable capacities are based on existing capacities reported by IRENA for the specified year

– expansion_limit

float or false

Artificially limit maximum capacities to factor * (IRENA capacities), i.e. 110% of <years>’s capacities => expansion_limit: 1.1 false: Use estimated renewable potentials determine by the workflow

– technology_mapping

Mapping between powerplantmatching and PyPSA-Eur technology names

Warning

Carriers in conventional_carriers must not also be in extendable_carriers.

atlite

Define and specify the atlite.Cutout used for calculating renewable potentials and time-series. All options except for features are directly used as cutout parameters.

atlite:
  cutout_snapshots:
    start: "2012-01-01"
    end: "2013-01-01"
    closed: 'left' # end is not inclusive
  nprocesses: 1
  cutouts:
    RSA-2012-era5:
      module: era5 # in priority order
      x: [16, 35]
      y: [-35., -21]
      dx: 0.3
      dy: 0.3
      time: ['2012', '2012']
    # RSA-2012-sarah:
    #  module: [sarah, era5] # in priority order
    #  x: [16, 35]
    #  y: [-35.,-21]
    #  dx: 0.2
    #  dy: 0.2
    #  time: ['2012', '2012']
    #  sarah_interpolate: false
    #  sarah_dir:
    #  features: [influx, temperature]
  apply_wind_correction: true

Unit

Values

Description

nprocesses

int

Number of parallel processes in cutout preparation

cutouts

– {name}

Convention is to name cutouts like <region>-<year>-<source> (e.g. europe-2013-era5).

Name of the cutout netcdf file. The user may specify multiple cutouts under configuration atlite: cutouts:. Reference is used in configuration renewable: {technology}: cutout:. The cutout base may be used to automatically calculate temporal and spatial bounds of the network.

– – module

Subset of {‘era5’,’sarah’}

Source of the reanalysis weather dataset (e.g. ERA5 or SARAH-2)

– – x

°

Float interval within [-180, 180]

Range of longitudes to download weather data for. If not defined, it defaults to the spatial bounds of all bus shapes.

– – y

°

Float interval within [-90, 90]

Range of latitudes to download weather data for. If not defined, it defaults to the spatial bounds of all bus shapes.

– – time

Time interval within [‘1979’, ‘2018’] (with valid pandas date time strings)

Time span to download weather data for. If not defined, it defaults to the time interval spanned by the snapshots.

– – features

String or list of strings with valid cutout features (‘inlfux’, ‘wind’).

When freshly building a cutout, retrieve data only for those features. If not defined, it defaults to all available features.

renewable

onwind

renewable:
  onwind:
    cutout: RSA-2012-era5
    resource:
      method: wind
      turbine: NREL_ReferenceTurbine_2020ATB_4MW
    capacity_per_sqkm: 3 # ScholzPhd Tab 4.3.1: 10MW/km^2 and assuming 30% fraction of the already restricted
    # area is available for installation of wind generators due to competing land use and likely public
    # acceptance issues.
    # correction_factor: 0.93
    salandcover:
      grid_codes: [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32]
      distance: 1000
      distance_grid_codes: [1, 2, 3, 4, 5, 6]

    #corine:
      # Scholz, Y. (2012). Renewable energy based electricity supply at low costs:
      #  development of the REMix model and application for Europe. ( p.42 / p.28)
    #  grid_codes: [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32]
    #  distance: 1000
    #  distance_grid_codes: [1, 2, 3, 4, 5, 6]
    natura: true
    excluder_resolution: 100
    potential: simple # or conservative
    clip_p_max_pu: 1.e-2

Unit

Values

Description

cutout

Should be a folder listed in the configuration atlite: cutouts: (e.g. ‘RSA-2013-era5’) or reference an existing folder in the directory cutouts. Source module must be ERA5.

Specifies the directory where the relevant weather data ist stored.

resource

– method

Must be ‘wind’

A superordinate technology type.

– turbine

One of turbine types included in atlite

Specifies the turbine type and its characteristic power curve.

capacity_per_sqkm

\(MW/km^2\)

float

Allowable density of wind turbine placement.

corine

– grid_codes

Any subset of the CORINE Land Cover code list

Specifies areas according to CORINE Land Cover codes which are generally eligible for wind turbine placement.

– distance

m

float

Distance to keep from areas specified in distance_grid_codes

– distance_grid_codes

Any subset of the CORINE Land Cover code list

Specifies areas according to CORINE Land Cover codes to which wind turbines must maintain a distance specified in the setting distance.

natura

bool

{true, false}

Switch to exclude Natura 2000 natural protection areas. Area is excluded if true.

potential

One of {‘simple’, ‘conservative’}

Method to compute the maximal installable potential for a node; confer renewableprofiles

clip_p_max_pu

p.u.

float

To avoid too small values in the renewables` per-unit availability time series values below this threshold are set to zero.

solar

  use_eskom_wind_solar: false # Model defaults to Eskom hourly pu profiles for all wind and solar generators
  use_excel_wind_solar: [true,"data/wind_solar_profiles.xlsx"] # Model defaults to excel input hourly pu profiles for all wind and solar generators  
  build_renewable_profiles: true #false # Enable calculation of renewable profiles

scenario:
  resarea: [redz]
  regions: [27-supply]
  ll: ['copt']
  clusters: ['']
  model_file: ['IRP_2019','validation_4']
  opts: [Co2L-3H,LC-1H]

# General inputs
data:
  resarea:
    redz: REDZ_DEA_Unpublished_Draft_2015
    corridors: Power_corridors

# definition of the Coordinate Reference Systems
crs:
  geo_crs: EPSG:4326  # general geographic projection, not used for metric measures. "EPSG:4326" is the standard used by OSM and google maps
  distance_crs: EPSG:3857  # projection for distance measurements only. Possible recommended values are "EPSG:3857" (used by OSM and Google Maps)
  area_crs: ESRI:54009  # projection for area measurements only. Possible recommended values are Global Mollweide "ESRI:54009"




# Specification of relevent years for the model
years: 
  reference_demand_year: 2017  # should be a single year at present, could be extended in the future
  reference_weather_years: 
    # reference years used for solar PV and wind profiles - can be single or multiple years
    # if multiple years are specified these are applied sequencially to the simulation years
    solar: [2012]
    onwind: [2012]
    # reference years from actual Eskom data published at https://www.eskom.co.za/dataportal/ 
    # can be single or multiple years if multiple years are specified these are applied 
    # sequencially to the simulation years
    CSP: [2021] 
    hydro: [2021]
    biomass: [2021]
    imports: [2021]

electricity:
  co2limit: 2.e+9    # 470.9e+5  Cumulative CO2 emissions budget for all simulation years combined
  renewable_carriers: [solar, onwind, CSP, biomass, hydro] # defines renewable carriers
  generator_availability: # generator planned and unplanned outages are included based on Eskom data
    implement_availability: true
    reference_years: [2021] #if multiple years specified an average is used
    new_unit_ref: 
    # New generator availability is based on an existing Eskom generator
    # in the format [generator, ref year/s (avg), rescale e.g 10% higher]
      coal: ['Lethabo', [2017], 1]
      OCGT: ['Ankerlig', [2017], 1]
      CCGT: ['Ankerlig', [2017], 1]
      nuclear: ['Koeberg', [2017], 1.1]

  # Only for new generators, existing generators are specified in model_file
  min_stable_levels:
    coal: 0 
    OCGT: 0 
    CCGT: 0
    nuclear: 0

  min_capacity_factor: # Minimum annual capacity factor 
    # TODO make per week
    CCGT: 0.3 
    nuclear: 0.5

  extendable_carriers:
    Renewables: ['onwind', solar]
    Generator: [CCGT, OCGT, coal, nuclear]
    StorageUnit: [battery, PHS] 

  buses:
    9_10_11-supply: 
      OCGT: [GAUTENG, WESTERN CAPE, KZN, EASTERN CAPE] # Saldana Bay, Richards Bay, Coega
      CCGT: [GAUTENG, WESTERN CAPE, KZN, EASTERN CAPE]
      coal: [GAUTENG, LIMPOPO] # Johannesburg, Waterberg
      nuclear: [EASTERN CAPE, WESTERN CAPE] # Thyspunt, Koeberg
      imports: [LIMPOPO]         
    27-supply:
      OCGT: [JOHANNESBURG, WEST COAST, EMPANGENI, PORT ELIZABETH] # Saldana Bay, Richards Bay, Coega
      CCGT: [JOHANNESBURG, WEST COAST, EMPANGENI, PORT ELIZABETH]
      coal: [JOHANNESBURG, WATERBERG]
      nuclear: [PORT ELIZABETH, PENINSULA] # Thyspunt, Koeberg
      imports: [POLOKWANE]
  
  SAFE_reservemargin: 0.1

  reserves:
    reserve_margin: # like https://genxproject.github.io/GenX/dev/core/#Reserves
      activate: false
      epsilon_load: 0.02 # share of total load
      epsilon_vres: 0.02 # share of total renewable supply
      contingency: 0 # fixed capacity in MW
    operating_reserves:
      fast: ['battery','PHS']
      total: ['diesel','gas','OCGT','CCGT','battery','PHS'] 
  max_hours:
    battery: 3
    PHS: 20
    H2: 10

respotentials:
  # Gives us ball-park the available areas the IWES study reports
  landusetype_percent:
  # grid codes
    wind:
      - [[7, 8, 9, 41], 80]
      # - [[5, 6], 50]
      # - [[11, 12, 14, 15], 10]
    solar:
      - [[7, 8, 9, 41], 80]
      # - [[11, 12, 14, 15], 50]
      # - [[46, 47, 51, 56, 64, 68, 72], 10]

  capacity_per_sqm:
    onwind: 5   # half of 10 (IWES)
    solar: 16.5 # half of 33 (IWES)

atlite:
  cutout_snapshots:
    start: "2012-01-01"
    end: "2013-01-01"
    closed: 'left' # end is not inclusive
  nprocesses: 1
  cutouts:
    RSA-2012-era5:
      module: era5 # in priority order
      x: [16, 35]
      y: [-35., -21]
      dx: 0.3
      dy: 0.3
      time: ['2012', '2012']
    # RSA-2012-sarah:
    #  module: [sarah, era5] # in priority order
    #  x: [16, 35]
    #  y: [-35.,-21]
    #  dx: 0.2
    #  dy: 0.2
    #  time: ['2012', '2012']
    #  sarah_interpolate: false
    #  sarah_dir:
    #  features: [influx, temperature]
  apply_wind_correction: true

renewable:
  onwind:
    cutout: RSA-2012-era5
    resource:
      method: wind
      turbine: NREL_ReferenceTurbine_2020ATB_4MW
    capacity_per_sqkm: 3 # ScholzPhd Tab 4.3.1: 10MW/km^2 and assuming 30% fraction of the already restricted
    # area is available for installation of wind generators due to competing land use and likely public
    # acceptance issues.
    # correction_factor: 0.93
    salandcover:
      grid_codes: [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32]
      distance: 1000
      distance_grid_codes: [1, 2, 3, 4, 5, 6]

    #corine:
      # Scholz, Y. (2012). Renewable energy based electricity supply at low costs:
      #  development of the REMix model and application for Europe. ( p.42 / p.28)
    #  grid_codes: [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32]
    #  distance: 1000
    #  distance_grid_codes: [1, 2, 3, 4, 5, 6]
    natura: true
    excluder_resolution: 100
    potential: simple # or conservative
    clip_p_max_pu: 1.e-2

  solar:
    cutout: RSA-2012-era5
    resource:
      method: pv
      panel: CSi
      orientation: latitude_optimal
        #slope: 35.
        #azimuth: 0.
    capacity_per_sqkm: 1.7 # ScholzPhd Tab 4.3.1: 170 MW/km^2 and assuming 1% of the area can be used for solar PV panels
    # Correction factor determined by comparing uncorrected area-weighted full-load hours to those
    # published in Supplementary Data to
    # Pietzcker, Robert Carl, et al. "Using the sun to decarbonize the power
    # sector: The economic potential of photovoltaics and concentrating solar
    # power." Applied Energy 135 (2014): 704-720.
    # This correction factor of 0.854337 may be in order if using reanalysis data.
    # for discussion refer to https://github.com/PyPSA/pypsa-eur/pull/304
    # correction_factor: 0.854337
  #  corine: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 26, 31, 32]
    natura: true
    excluder_resolution: 100
    potential: simple # or conservative
    clip_p_max_pu: 1.e-2
    salandcover:
      grid_codes: [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32]
      distance: 1000
      distance_grid_codes: [1, 2, 3, 4, 5, 6]
  # hydro:
  #   cutout: RSA-2013-era5
  #   carriers: [ror, PHS, hydro]
  #   PHS_max_hours: 6
  #   hydro_max_hours: "energy_capacity_totals_by_country" # one of energy_capacity_totals_by_country, estimate_by_large_installations or a float
  #   clip_min_inflow: 1.0

Unit

Values

Description

cutout

Should be a folder listed in the configuration atlite: cutouts: (e.g. ‘europe-2013-era5’) or reference an existing folder in the directory cutouts. Source module can be ERA5 or SARAH-2.

Specifies the directory where the relevant weather data ist stored that is specified at atlite/cutouts configuration. Both sarah and era5 work.

resource

– method

Must be ‘pv’

A superordinate technology type.

– panel

One of {‘Csi’, ‘CdTe’, ‘KANENA’} as defined in atlite

Specifies the solar panel technology and its characteristic attributes.

– orientation

– – slope

°

Realistically any angle in [0., 90.]

Specifies the tilt angle (or slope) of the solar panel. A slope of zero corresponds to the face of the panel aiming directly overhead. A positive tilt angle steers the panel towards the equator.

– – azimuth

°

Any angle in [0., 360.]

Specifies the azimuth orientation of the solar panel. South corresponds to 180.°.

capacity_per_sqkm

\(MW/km^2\)

float

Allowable density of solar panel placement.

correction_factor

float

A correction factor for the capacity factor (availability) time series.

corine

Any subset of the CORINE Land Cover code list

Specifies areas according to CORINE Land Cover codes which are generally eligible for solar panel placement.

natura

bool

{true, false}

Switch to exclude Natura 2000 natural protection areas. Area is excluded if true.

potential

One of {‘simple’, ‘conservative’}

Method to compute the maximal installable potential for a node; confer renewableprofiles

clip_p_max_pu

p.u.

float

To avoid too small values in the renewables` per-unit availability time series values below this threshold are set to zero.

hydro

hydro_inflow:
  disable: false #true
  source: eskom #or calculate runoff using atlite
  countries: [ZA, MZ] # only applicable to atlite
  cutout: za-mz-2012 # only applicable to atlite

Unit

Values

Description

cutout

Must be ‘RSA-2013-era5’

Specifies the directory where the relevant weather data ist stored.

carriers

Any subset of {‘ror’, ‘PHS’, ‘hydro’}

Specifies the types of hydro power plants to build per-unit availability time series for. ‘ror’ stands for run-of-river plants, ‘PHS’ represents pumped-hydro storage, and ‘hydro’ stands for hydroelectric dams.

PHS_max_hours

h

float

Maximum state of charge capacity of the pumped-hydro storage (PHS) in terms of hours at full output capacity p_nom. Cf. PyPSA documentation.

hydro_max_hours

h

Any of {float, ‘energy_capacity_totals_by_country’, ‘estimate_by_large_installations’}

Maximum state of charge capacity of the pumped-hydro storage (PHS) in terms of hours at full output capacity p_nom or heuristically determined. Cf. PyPSA documentation.

clip_min_inflow

MW

float

To avoid too small values in the inflow time series, values below this threshold are set to zero.

lines

lines:
  v_nom: 400. #changed from 380kV from PyPSA-EUR to 400kV for South Africa
  #type: 'Al/St 240/40 4-bundle 400.0' 
#lines:
  types:
    220.: "Al/St 240/40 2-bundle 220.0"
    300.: "Al/St 240/40 3-bundle 300.0"
    380.: "Al/St 240/40 4-bundle 380.0"
    400.: "Al/St 240/40 4-bundle 400.0" # network voltage set to 400kV
  dc_type: "DC_custom_linetype"
  s_max_pu: 0.7
  s_nom_factor: 0.7
  s_nom_max: .inf
  length_factor: 1.25
  under_construction: "zero" # 'zero': set capacity to zero, 'remove': remove, 'keep': with full capacity

Unit

Values

Description

types

Values should specify a line type in PyPSA. Keys should specify the corresponding voltage level (e.g. 220., 300. and 380. kV)

Specifies line types to assume for the different voltage levels of the ENTSO-E grid extraction. Should normally handle voltage levels 220, 300, and 380 kV

s_max_pu

Value in [0.,1.]

Correction factor for line capacities (s_nom) to approximate \(N-1\) security and reserve capacity for reactive power flows

s_nom_max

MW

float

Global upper limit for the maximum capacity of each extendable line.

length_factor

float

Correction factor to account for the fact that buses are not connected by lines through air-line distance.

under_construction

One of {‘zero’: set capacity to zero, ‘remove’: remove completely, ‘keep’: keep with full capacity}

Specifies how to handle lines which are currently under construction.

costs

      # Scholz, Y. (2012). Renewable energy based electricity supply at low costs:
      #  development of the REMix model and application for Europe. ( p.42 / p.28)
    #  grid_codes: [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32]
    #  distance: 1000
    #  distance_grid_codes: [1, 2, 3, 4, 5, 6]
    natura: true
    excluder_resolution: 100
    potential: simple # or conservative
    clip_p_max_pu: 1.e-2

  solar:
    cutout: RSA-2012-era5
    resource:
      method: pv
      panel: CSi
      orientation: latitude_optimal
        #slope: 35.
        #azimuth: 0.
    capacity_per_sqkm: 1.7 # ScholzPhd Tab 4.3.1: 170 MW/km^2 and assuming 1% of the area can be used for solar PV panels
    # Correction factor determined by comparing uncorrected area-weighted full-load hours to those
    # published in Supplementary Data to
    # Pietzcker, Robert Carl, et al. "Using the sun to decarbonize the power
    # sector: The economic potential of photovoltaics and concentrating solar
    # power." Applied Energy 135 (2014): 704-720.
    # This correction factor of 0.854337 may be in order if using reanalysis data.
    # for discussion refer to https://github.com/PyPSA/pypsa-eur/pull/304
    # correction_factor: 0.854337
  #  corine: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 26, 31, 32]
    natura: true
    excluder_resolution: 100
    potential: simple # or conservative
    clip_p_max_pu: 1.e-2
    salandcover:
      grid_codes: [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32]
      distance: 1000
      distance_grid_codes: [1, 2, 3, 4, 5, 6]
  # hydro:
  #   cutout: RSA-2013-era5
  #   carriers: [ror, PHS, hydro]
  #   PHS_max_hours: 6
  #   hydro_max_hours: "energy_capacity_totals_by_country" # one of energy_capacity_totals_by_country, estimate_by_large_installations or a float
  #   clip_min_inflow: 1.0

hydro_inflow:
  disable: false #true
  source: eskom #or calculate runoff using atlite
  countries: [ZA, MZ] # only applicable to atlite
  cutout: za-mz-2012 # only applicable to atlite

lines:
  v_nom: 400. #changed from 380kV from PyPSA-EUR to 400kV for South Africa
  #type: 'Al/St 240/40 4-bundle 400.0' 
#lines:
  types:
    220.: "Al/St 240/40 2-bundle 220.0"
    300.: "Al/St 240/40 3-bundle 300.0"
    380.: "Al/St 240/40 4-bundle 380.0"
    400.: "Al/St 240/40 4-bundle 400.0" # network voltage set to 400kV
  dc_type: "DC_custom_linetype"
  s_max_pu: 0.7
  s_nom_factor: 0.7
  s_nom_max: .inf
  length_factor: 1.25
  under_construction: "zero" # 'zero': set capacity to zero, 'remove': remove, 'keep': with full capacity

links:
  p_max_pu: 1.0
  p_nom_max: .inf
  include_tyndp: true
  under_construction: "zero" # 'zero': set capacity to zero, 'remove': remove, 'keep': with full capacity
  # costs
  s_nom_factor: 0.7
  length_factor: 1.25

augmented_line_connection:
  add_to_snakefile: true  # If True, includes this rule to the workflow
  connectivity_upgrade: 2  # Min. lines connection per node, https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.connectivity.edge_augmentation.k_edge_augmentation.html#networkx.algorithms.connectivity.edge_augmentation.k_edge_augmentation
  new_line_type: ["HVAC", "HVDC"]  # Expanded lines can be either ["HVAC"] or ["HVDC"] or both ["HVAC", "HVDC"]
  min_expansion: 1  # [MW] New created line expands by float/int input
  min_DC_length: 600  # [km] Minimum line length of DC line


costs:
  # costs come from data/technology_costs.xlsx
  discountrate: 0.082
  year: 2030
  # Marginal and capital costs can be overwritten
  # capital_cost:
  #   Wind: Bla
  marginal_cost: #
    solar: 0.01
    onwind: 0.015
    #offwind: 0.015 
    #PV: 0.01
    #Wind: 0.015
  USD_to_ZAR: 18.24
  EUR_to_ZAR: 17.83

  load_shedding: 100000 #R100/kWh
  fill_values:
    FOM: 0
    VOM: 0
    efficiency: 1
    fuel: 0
    investment: 0
    lifetime: 25
    "CO2 intensity": 0
    "discount rate": 0.07

  emission_prices: # only used with the option Ep (emission prices)
    # Externality costs from Integrated Energy Plan by the ZA DOE
    co2: 0.27e+3
    sox: 7.6e+3
    nox: 4.5e+3
    hg: 41484.e-6 # is also part of the excel sheet
    particulate: 11.3e+3

Unit

Values

Description

year

YYYY; e.g. ‘2030’

Year for which to retrieve cost assumptions of resources/costs.csv.

version

vX.X.X; e.g. ‘v0.1.0’

Version of technology-data repository to use.

rooftop_share

float

Share of rooftop PV when calculating capital cost of solar (joint rooftop and utility-scale PV).

fill_values

float

Default values if not specified for a technology in resources/costs.csv.

capital_cost

EUR/MW

Keys should be in the ‘technology’ column of resources/costs.csv. Values can be any float.

For the given technologies, assumptions about their capital investment costs are set to the corresponding value. Optional; overwrites cost assumptions from resources/costs.csv.

marginal_cost

EUR/MWh

Keys should be in the ‘technology’ column of resources/costs.csv. Values can be any float.

For the given technologies, assumptions about their marginal operating costs are set to the corresponding value. Optional; overwrites cost assumptions from resources/costs.csv.

emission_prices

Specify exogenous prices for emission types listed in network.carriers to marginal costs.

– co2

EUR/t

float

Exogenous price of carbon-dioxide added to the marginal costs of fossil-fuelled generators according to their carbon intensity. Added through the keyword Ep in the {opts} wildcard only in the rule prepare_network`.

Note

To change cost assumptions in more detail (i.e. other than marginal_cost and capital_cost), consider modifying cost assumptions directly in data/costs.csv as this is not yet supported through the config file. You can also build multiple different cost databases. Make a renamed copy of data/costs.csv (e.g. data/costs-optimistic.csv) and set the variable COSTS=data/costs-optimistic.csv in the Snakefile.

solving

options

solving:
  tmpdir: /tmp
  options:
    clip_p_max_pu: 1.e-2
    load_shedding: true
    noisy_costs: true
    skip_iterations: false
    min_iterations: 1
    max_iterations: 10
    formulation: kirchhoff
    # max_iterations: 1
    # nhours: 10

Unit

Values

Description

formulation

Any of {‘angles’, ‘kirchhoff’, ‘cycles’, ‘ptdf’}

Specifies which variant of linearized power flow formulations to use in the optimisation problem. Recommended is ‘kirchhoff’. Explained in this article.

load_shedding

bool

{‘true’,’false’}

Add generators with a prohibitively high marginal cost to simulate load shedding and avoid problem infeasibilities.

noisy_costs

bool

{‘true’,’false’}

Add random noise to marginal cost of generators by \(\mathcal{U}(0.009,0,011)\) and capital cost of lines and links by \(\mathcal{U}(0.09,0,11)\).

min_iterations

int

Minimum number of solving iterations in between which resistance and reactence (x/r) are updated for branches according to s_nom_opt of the previous run.

max_iterations

int

Maximum number of solving iterations in between which resistance and reactence (x/r) are updated for branches according to s_nom_opt of the previous run.

nhours

int

Specifies the \(n\) first snapshots to take into account. Must be less than the total number of snapshots. Rather recommended only for debugging.

clip_p_max_pu

p.u.

float

To avoid too small values in the renewables` per-unit availability time series values below this threshold are set to zero.

skip_iterations

bool

{‘true’,’false’}

Skip iterating, do not update impedances of branches.

track_iterations

bool

{‘true’,’false’}

Flag whether to store the intermediate branch capacities and objective function values are recorded for each iteration in network.lines['s_nom_opt_X'] (where X labels the iteration)

solver

  solver: 'xpress'

solving:
  tmpdir: /tmp
  options:
    clip_p_max_pu: 1.e-2
    load_shedding: true
    noisy_costs: true
    skip_iterations: false
    min_iterations: 1
    max_iterations: 10
    formulation: kirchhoff
    # max_iterations: 1
    # nhours: 10
  solver:
    name: xpress
    lpflags: 4
    crossover: 0
    bargapstop: 1.e-5
    # FeasibilityTol: 1.e-6
    # LogToConsole: 0
    # OutputFlag: 1

Unit

Values

Description

name

One of {‘gurobi’, ‘cplex’, ‘cbc’, ‘glpk’, ‘ipopt’}; potentially more possible

Solver to use for optimisation problems in the workflow; e.g. clustering and linear optimal power flow.

opts

Parameter list for Gurobi and CPLEX

Solver specific parameter settings.

plotting

plotting:
  map:
    figsize: [8, 8]
    boundaries: [14, 34, -35, -22] #[x1,x2,y1,y2]
    p_nom:
      bus_size_factor: 5.e+4
      linewidth_factor: 2.e+3 #1.e+3 # 1.e+3  #3.e+3

  costs_max: 1000

  vre_techs: ["onwind","solar", "ror"]
  conv_techs: ["OCGT", "CCGT", "nuclear", "coal"]
  storage_techs: ["hydro", "CAES", "battery", "PHS", "hydro+PHS"]
  store_techs: ["Li ion", "water tanks"]
  load_carriers: ["AC load", "heat load", "Li ion load"]
  AC_carriers: ["AC line", "AC transformer"]
  link_carriers: ["DC line", "Converter AC-DC"] 
  heat_links: ["heat pump", "resistive heater", "CHP heat", "CHP electric",
               "gas boiler", "central heat pump", "central resistive heater", "central CHP heat",
               "central CHP electric", "central gas boiler"]
  heat_generators: ["gas boiler", "central gas boiler", "solar thermal collector", "central solar thermal collector"]
  tech_colors:
    "onwind": "#77D1E4"
    "onshore wind": "#77D1E4"
    "offwind": "#77D1E4"
    "offwind-ac": "#77D1E4"
    "offshore wind": "#77D1E4"
    "offshore wind ac": "#77D1E4"
    "offwind-dc": "#77D1E4"
    "offshore wind dc": "#77D1E4"
    "hydro": "#004F95"
    "hydro+PHS": "#004F95"
    "PHS": "#004F95"
    "hydro reservoir": "#004F95"
    "hydroelectricity": "#004F95"
    "ror": "#4adbc8"
    "run of river": "#4adbc8"
    "solar": "#FFBB4E"
    "solar PV": "#FFBB4E"
    "CSP": "#FEED82"
    "biomass": "#0c6013"
    "solid biomass": "#06540d"
    "biogas": "#23932d"
    "waste": "#68896b"
    "geothermal": "#ba91b1"
    "OCGT": "#8D7867"
    "gas": "#d35050"
    "natural gas": "#d35050"
    "CCGT": "#CCC8C8"
    "nuclear": "#C84936"
    "coal": "#3C3C3C"
    "lignite": "#9e5a01"
    "diesel": "#262626"
    "H2": "#ea048a"
    "hydrogen storage": "#ea048a"
    "battery": "#AA68AA"
    "Electric load": "#f9d002"
    "electricity": "#f9d002"
    "lines": "#70af1d"
    "transmission lines": "#70af1d"
    "AC-AC": "#70af1d"
    "AC line": "#3C3C3C"
    "links": "#8a1caf"
    "HVDC links": "#8a1caf"
    "DC-DC": "#8a1caf"
    "DC link": "#8a1caf"
    "load_shedding": "#FF0000"
    "Load": "#FF0000"
  nice_names:
    OCGT: "OCGT" #"Open-Cycle Gas"
    CCGT: "CCGT" #"Combined-Cycle Gas"
    offwind-ac: "Offshore Wind (AC)"
    offwind-dc: "Offshore Wind (DC)"
    onwind: "Wind"
    solar: "PV"
    PHS: "Pumped Hydro Storage"
    hydro: "Hydro"
    hydro+PHS: "Hydro+PS"
    battery: "Battery"
    H2: "Hydrogen Storage"
    lines: "Transmission Lines"
    ror: "Run of River"
    coal: "Coal"
    nuclear: "Nuclear"
    biomass: "Biomass"

Unit

Values

Description

map

– figsize

[width, height]; e.g. [7,7]

Figure size in inches.

– boundaries

°

[x1,x2,y1,y2]

Boundaries of the map plots in degrees latitude (y) and longitude (x)

– p_nom

– – bus_size_factor

float

Factor by which values determining bus sizes are scaled to fit well in the plot.

– – linewidth_factor

float

Factor by which values determining bus sizes are scaled to fit well in the plot.

costs_max

bn Euro

float

Upper y-axis limit in cost bar plots.

costs_threshold

bn Euro

float

Threshold below which technologies will not be shown in cost bar plots.

energy_max

TWh

float

Upper y-axis limit in energy bar plots.

energy_min

TWh

float

Lower y-axis limit in energy bar plots.

energy_threshold

TWh

float

Threshold below which technologies will not be shown in energy bar plots.

tech_colors

carrier -> HEX colour code

Mapping from network carrier to a colour (HEX colour code).

nice_names

str -> str

Mapping from network carrier to a more readable name.