Merge branch 'master' into multiyear
This commit is contained in:
commit
c3bb41c900
1
.gitignore
vendored
1
.gitignore
vendored
@ -46,6 +46,7 @@ data/costs_*.csv
|
||||
|
||||
dask-worker-space/
|
||||
publications.jrc.ec.europa.eu/
|
||||
d1gam3xoknrgr2.cloudfront.net/
|
||||
|
||||
*.org
|
||||
|
||||
|
@ -5,7 +5,7 @@ exclude: "^LICENSES"
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.4.0
|
||||
rev: v4.5.0
|
||||
hooks:
|
||||
- id: check-merge-conflict
|
||||
- id: end-of-file-fixer
|
||||
@ -17,7 +17,7 @@ repos:
|
||||
|
||||
# Sort package imports alphabetically
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.12.0
|
||||
rev: 5.13.2
|
||||
hooks:
|
||||
- id: isort
|
||||
args: ["--profile", "black", "--filter-files"]
|
||||
@ -45,13 +45,13 @@ repos:
|
||||
args: ["--in-place", "--make-summary-multi-line", "--pre-summary-newline"]
|
||||
|
||||
- repo: https://github.com/keewis/blackdoc
|
||||
rev: v0.3.8
|
||||
rev: v0.3.9
|
||||
hooks:
|
||||
- id: blackdoc
|
||||
|
||||
# Formatting with "black" coding style
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.9.1
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: 23.12.1
|
||||
hooks:
|
||||
# Format Python files
|
||||
- id: black
|
||||
@ -67,14 +67,14 @@ repos:
|
||||
|
||||
# Do YAML formatting (before the linter checks it for misses)
|
||||
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
|
||||
rev: v2.10.0
|
||||
rev: v2.12.0
|
||||
hooks:
|
||||
- id: pretty-format-yaml
|
||||
args: [--autofix, --indent, "2", --preserve-quotes]
|
||||
|
||||
# Format Snakemake rule / workflow files
|
||||
- repo: https://github.com/snakemake/snakefmt
|
||||
rev: v0.8.4
|
||||
rev: v0.8.5
|
||||
hooks:
|
||||
- id: snakefmt
|
||||
|
||||
|
@ -61,9 +61,9 @@ The dataset consists of:
|
||||
|
||||
- A grid model based on a modified [GridKit](https://github.com/bdw/GridKit)
|
||||
extraction of the [ENTSO-E Transmission System
|
||||
Map](https://www.entsoe.eu/data/map/). The grid model contains 6763 lines
|
||||
Map](https://www.entsoe.eu/data/map/). The grid model contains 7072 lines
|
||||
(alternating current lines at and above 220kV voltage level and all high
|
||||
voltage direct current lines) and 3642 substations.
|
||||
voltage direct current lines) and 3803 substations.
|
||||
- The open power plant database
|
||||
[powerplantmatching](https://github.com/FRESNA/powerplantmatching).
|
||||
- Electrical demand time series from the
|
||||
@ -103,6 +103,6 @@ We strongly welcome anyone interested in contributing to this project. If you ha
|
||||
# Licence
|
||||
|
||||
The code in PyPSA-Eur is released as free software under the
|
||||
[MIT License](https://opensource.org/licenses/MIT), see `LICENSE.txt`.
|
||||
[MIT License](https://opensource.org/licenses/MIT), see [`doc/licenses.rst`](doc/licenses.rst).
|
||||
However, different licenses and terms of use may apply to the various
|
||||
input data.
|
||||
|
@ -69,6 +69,7 @@ enable:
|
||||
retrieve_sector_databundle: true
|
||||
retrieve_cost_data: true
|
||||
build_cutout: false
|
||||
retrieve_irena: false
|
||||
retrieve_cutout: true
|
||||
retrieve_opsd_load_data: true
|
||||
retrieve_artificial_load_data: false
|
||||
@ -89,7 +90,7 @@ co2_budget:
|
||||
|
||||
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#electricity
|
||||
electricity:
|
||||
voltages: [220., 300., 380.]
|
||||
voltages: [220., 300., 380., 500., 750.]
|
||||
gaslimit: false
|
||||
co2limit: 7.75e+7
|
||||
co2base: 1.487e+9
|
||||
@ -138,14 +139,14 @@ atlite:
|
||||
# module: era5
|
||||
europe-2013-era5:
|
||||
module: era5 # in priority order
|
||||
x: [-12., 35.]
|
||||
x: [-12., 42.]
|
||||
y: [33., 72]
|
||||
dx: 0.3
|
||||
dy: 0.3
|
||||
time: ['2013', '2013']
|
||||
europe-2013-sarah:
|
||||
module: [sarah, era5] # in priority order
|
||||
x: [-12., 45.]
|
||||
x: [-12., 42.]
|
||||
y: [33., 65]
|
||||
dx: 0.2
|
||||
dy: 0.2
|
||||
@ -161,6 +162,7 @@ renewable:
|
||||
resource:
|
||||
method: wind
|
||||
turbine: Vestas_V112_3MW
|
||||
add_cutout_windspeed: true
|
||||
capacity_per_sqkm: 3
|
||||
# correction_factor: 0.93
|
||||
corine:
|
||||
@ -169,13 +171,13 @@ renewable:
|
||||
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
|
||||
offwind-ac:
|
||||
cutout: europe-2013-era5
|
||||
resource:
|
||||
method: wind
|
||||
turbine: NREL_ReferenceTurbine_5MW_offshore
|
||||
turbine: NREL_ReferenceTurbine_2020ATB_5.5MW
|
||||
add_cutout_windspeed: true
|
||||
capacity_per_sqkm: 2
|
||||
correction_factor: 0.8855
|
||||
corine: [44, 255]
|
||||
@ -184,13 +186,13 @@ renewable:
|
||||
max_depth: 50
|
||||
max_shore_distance: 30000
|
||||
excluder_resolution: 200
|
||||
potential: simple # or conservative
|
||||
clip_p_max_pu: 1.e-2
|
||||
offwind-dc:
|
||||
cutout: europe-2013-era5
|
||||
resource:
|
||||
method: wind
|
||||
turbine: NREL_ReferenceTurbine_5MW_offshore
|
||||
turbine: NREL_ReferenceTurbine_2020ATB_5.5MW
|
||||
add_cutout_windspeed: true
|
||||
capacity_per_sqkm: 2
|
||||
correction_factor: 0.8855
|
||||
corine: [44, 255]
|
||||
@ -199,7 +201,6 @@ renewable:
|
||||
max_depth: 50
|
||||
min_shore_distance: 30000
|
||||
excluder_resolution: 200
|
||||
potential: simple # or conservative
|
||||
clip_p_max_pu: 1.e-2
|
||||
solar:
|
||||
cutout: europe-2013-sarah
|
||||
@ -214,7 +215,6 @@ renewable:
|
||||
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
|
||||
hydro:
|
||||
cutout: europe-2013-era5
|
||||
@ -241,10 +241,13 @@ lines:
|
||||
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"
|
||||
500.: "Al/St 240/40 4-bundle 380.0"
|
||||
750.: "Al/St 560/50 4-bundle 750.0"
|
||||
s_max_pu: 0.7
|
||||
s_nom_max: .inf
|
||||
max_extension: .inf
|
||||
length_factor: 1.25
|
||||
reconnect_crimea: true
|
||||
under_construction: 'zero' # 'zero': set capacity to zero, 'remove': remove, 'keep': with full capacity
|
||||
dynamic_line_rating:
|
||||
activate: false
|
||||
@ -452,14 +455,15 @@ sector:
|
||||
solar_cf_correction: 0.788457 # = >>> 1/1.2683
|
||||
marginal_cost_storage: 0. #1e-4
|
||||
methanation: true
|
||||
helmeth: false
|
||||
coal_cc: false
|
||||
dac: true
|
||||
co2_vent: false
|
||||
central_heat_vent: false
|
||||
allam_cycle: false
|
||||
hydrogen_fuel_cell: true
|
||||
hydrogen_turbine: false
|
||||
SMR: true
|
||||
SMR_cc: true
|
||||
regional_co2_sequestration_potential:
|
||||
enable: false
|
||||
attribute: 'conservative estimate Mt'
|
||||
@ -479,11 +483,15 @@ sector:
|
||||
- nearshore # within 50 km of sea
|
||||
# - offshore
|
||||
ammonia: false
|
||||
min_part_load_fischer_tropsch: 0.9
|
||||
min_part_load_methanolisation: 0.5
|
||||
min_part_load_fischer_tropsch: 0.7
|
||||
min_part_load_methanolisation: 0.3
|
||||
min_part_load_methanation: 0.3
|
||||
use_fischer_tropsch_waste_heat: true
|
||||
use_haber_bosch_waste_heat: true
|
||||
use_methanolisation_waste_heat: true
|
||||
use_methanation_waste_heat: true
|
||||
use_fuel_cell_waste_heat: true
|
||||
use_electrolysis_waste_heat: false
|
||||
use_electrolysis_waste_heat: true
|
||||
electricity_distribution_grid: true
|
||||
electricity_distribution_grid_cost_factor: 1.0
|
||||
electricity_grid_connection: true
|
||||
@ -496,6 +504,7 @@ sector:
|
||||
gas_distribution_grid_cost_factor: 1.0
|
||||
biomass_spatial: false
|
||||
biomass_transport: false
|
||||
biogas_upgrading_cc: false
|
||||
conventional_generation:
|
||||
OCGT: gas
|
||||
biomass_to_liquid: false
|
||||
@ -546,8 +555,8 @@ industry:
|
||||
MWh_NH3_per_tNH3: 5.166
|
||||
MWh_CH4_per_tNH3_SMR: 10.8
|
||||
MWh_elec_per_tNH3_SMR: 0.7
|
||||
MWh_H2_per_tNH3_electrolysis: 6.5
|
||||
MWh_elec_per_tNH3_electrolysis: 1.17
|
||||
MWh_H2_per_tNH3_electrolysis: 5.93
|
||||
MWh_elec_per_tNH3_electrolysis: 0.2473
|
||||
MWh_NH3_per_MWh_H2_cracker: 1.46 # https://github.com/euronion/trace/blob/44a5ff8401762edbef80eff9cfe5a47c8d3c8be4/data/efficiencies.csv
|
||||
NH3_process_emissions: 24.5
|
||||
petrochemical_process_emissions: 25.5
|
||||
@ -600,6 +609,7 @@ costs:
|
||||
|
||||
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#clustering
|
||||
clustering:
|
||||
focus_weights: false
|
||||
simplify_network:
|
||||
to_substations: false
|
||||
algorithm: kmeans # choose from: [hac, kmeans]
|
||||
@ -741,6 +751,7 @@ plotting:
|
||||
H2: "Hydrogen Storage"
|
||||
lines: "Transmission Lines"
|
||||
ror: "Run of River"
|
||||
load: "Load Shedding"
|
||||
ac: "AC"
|
||||
dc: "DC"
|
||||
|
||||
@ -791,6 +802,7 @@ plotting:
|
||||
fossil gas: '#e05b09'
|
||||
natural gas: '#e05b09'
|
||||
biogas to gas: '#e36311'
|
||||
biogas to gas CC: '#e51245'
|
||||
CCGT: '#a85522'
|
||||
CCGT marginal: '#a85522'
|
||||
allam: '#B98F76'
|
||||
@ -821,6 +833,7 @@ plotting:
|
||||
Coal: '#545454'
|
||||
coal: '#545454'
|
||||
Coal marginal: '#545454'
|
||||
coal for industry: '#343434'
|
||||
solid: '#545454'
|
||||
Lignite: '#826837'
|
||||
lignite: '#826837'
|
||||
@ -891,12 +904,14 @@ plotting:
|
||||
# heat demand
|
||||
Heat load: '#cc1f1f'
|
||||
heat: '#cc1f1f'
|
||||
heat vent: '#aa3344'
|
||||
heat demand: '#cc1f1f'
|
||||
rural heat: '#ff5c5c'
|
||||
residential rural heat: '#ff7c7c'
|
||||
services rural heat: '#ff9c9c'
|
||||
central heat: '#cc1f1f'
|
||||
urban central heat: '#d15959'
|
||||
urban central heat vent: '#a74747'
|
||||
decentral heat: '#750606'
|
||||
residential urban decentral heat: '#a33c3c'
|
||||
services urban decentral heat: '#cc1f1f'
|
||||
@ -959,7 +974,6 @@ plotting:
|
||||
Sabatier: '#9850ad'
|
||||
methanation: '#c44ce6'
|
||||
methane: '#c44ce6'
|
||||
helmeth: '#e899ff'
|
||||
# synfuels
|
||||
Fischer-Tropsch: '#25c49a'
|
||||
liquid: '#25c49a'
|
||||
@ -1005,3 +1019,4 @@ plotting:
|
||||
DC: "#8a1caf"
|
||||
DC-DC: "#8a1caf"
|
||||
DC link: "#8a1caf"
|
||||
load: "#dd2e23"
|
||||
|
43
config/config.entsoe-all.yaml
Normal file
43
config/config.entsoe-all.yaml
Normal file
@ -0,0 +1,43 @@
|
||||
# SPDX-FileCopyrightText: 2017-2023 The PyPSA-Eur Authors
|
||||
#
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
run:
|
||||
name: "entsoe-all"
|
||||
disable_progressbar: true
|
||||
shared_resources: false
|
||||
shared_cutouts: true
|
||||
|
||||
scenario:
|
||||
simpl:
|
||||
- ''
|
||||
ll:
|
||||
- vopt
|
||||
clusters:
|
||||
- 39
|
||||
- 128
|
||||
- 256
|
||||
opts:
|
||||
- ''
|
||||
sector_opts:
|
||||
- ''
|
||||
planning_horizons:
|
||||
- ''
|
||||
|
||||
# TODO add Turkey (TR)
|
||||
countries: ['AL', 'AT', 'BA', 'BE', 'BG', 'CH', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'IE', 'IT', 'LT', 'LU', 'LV', 'ME', 'MD', 'MK', 'NL', 'NO', 'PL', 'PT', 'RO', 'RS', 'SE', 'SI', 'SK', 'UA']
|
||||
|
||||
electricity:
|
||||
custom_powerplants: true
|
||||
co2limit: 9.59e+7
|
||||
co2base: 1.918e+9
|
||||
|
||||
lines:
|
||||
reconnect_crimea: true
|
||||
|
||||
enable:
|
||||
retrieve: true
|
||||
retrieve_databundle: true
|
||||
retrieve_sector_databundle: false
|
||||
retrieve_cost_data: true
|
||||
retrieve_cutout: true
|
@ -32,6 +32,9 @@ snapshots:
|
||||
start: "2013-03-01"
|
||||
end: "2013-03-08"
|
||||
|
||||
sector:
|
||||
central_heat_vent: true
|
||||
|
||||
electricity:
|
||||
co2limit: 100.e+6
|
||||
|
||||
|
@ -44,6 +44,7 @@ electricity:
|
||||
sector:
|
||||
min_part_load_fischer_tropsch: 0
|
||||
min_part_load_methanolisation: 0
|
||||
|
||||
atlite:
|
||||
default_cutout: be-03-2013-era5
|
||||
cutouts:
|
||||
|
151
data/GDP_PPP_30arcsec_v3_mapped_default.csv
Normal file
151
data/GDP_PPP_30arcsec_v3_mapped_default.csv
Normal file
@ -0,0 +1,151 @@
|
||||
name,GDP_PPP,country
|
||||
3140,632728.0438507323,MD
|
||||
3139,806541.9318093687,MD
|
||||
3142,1392454.6690911907,MD
|
||||
3152,897871.2903553953,MD
|
||||
3246,645554.8588933202,MD
|
||||
7049,1150156.4449477682,MD
|
||||
1924,162285.16792916053,UA
|
||||
1970,751970.6071848695,UA
|
||||
2974,368873.75840156944,UA
|
||||
2977,294847.85539198935,UA
|
||||
2979,197988.13680768458,UA
|
||||
2980,301371.2491126519,UA
|
||||
3031,56925.21878805953,UA
|
||||
3032,139395.18279351242,UA
|
||||
3033,145377.8061037629,UA
|
||||
3035,52282.83655208812,UA
|
||||
3036,497950.25890516065,UA
|
||||
3037,1183293.1987702171,UA
|
||||
3038,255005.98207636533,UA
|
||||
3039,224711.50098325178,UA
|
||||
3040,342959.943226467,UA
|
||||
3044,69119.31486955672,UA
|
||||
3045,246273.65986119965,UA
|
||||
3047,146742.08407299497,UA
|
||||
3049,107265.7028733467,UA
|
||||
3050,1126147.985259493,UA
|
||||
3051,69833.56303043803,UA
|
||||
3052,67230.88206577855,UA
|
||||
3053,27019.224685201345,UA
|
||||
3054,260571.47337292184,UA
|
||||
3055,88760.94152915622,UA
|
||||
3056,101368.26196568517,UA
|
||||
3058,55752.92329667119,UA
|
||||
3059,89024.37880630122,UA
|
||||
3062,358411.291265149,UA
|
||||
3064,75081.64142862396,UA
|
||||
3065,158101.42949135564,UA
|
||||
3066,83763.89576442329,UA
|
||||
3068,173474.51218344545,UA
|
||||
3069,60327.01572375589,UA
|
||||
3070,18073.687271955278,UA
|
||||
3071,249069.43314695224,UA
|
||||
3072,220707.35700825177,UA
|
||||
3073,61342.30137462664,UA
|
||||
3074,254235.98867635374,UA
|
||||
3077,769558.9832370486,UA
|
||||
3078,132674.2315809836,UA
|
||||
3079,1388517.1478032232,UA
|
||||
3080,1861003.8718246964,UA
|
||||
3082,140123.73854745473,UA
|
||||
3083,834887.5595419679,UA
|
||||
3084,1910795.5590558557,UA
|
||||
3086,93828.36549170096,UA
|
||||
3088,347197.65113392205,UA
|
||||
3089,3754718.141734592,UA
|
||||
3090,521912.69768585655,UA
|
||||
3093,232818.05269714879,UA
|
||||
3095,435376.20361377904,UA
|
||||
3099,345596.5288937008,UA
|
||||
3100,175689.10947424968,UA
|
||||
3105,538438.9311459162,UA
|
||||
3107,88096.86032871014,UA
|
||||
3108,79847.68447063807,UA
|
||||
3109,348504.73449373,UA
|
||||
3144,71657.0165675802,UA
|
||||
3146,80342.05037424155,UA
|
||||
3158,74465.12922576343,UA
|
||||
3164,3102112.2672631275,UA
|
||||
3165,65215.04081671433,UA
|
||||
3166,413924.2225725632,UA
|
||||
3167,135060.0056434935,UA
|
||||
3168,54980.442979330146,UA
|
||||
3170,29584.879122227037,UA
|
||||
3171,142780.68163047134,UA
|
||||
3172,40436.63814695243,UA
|
||||
3173,1253342.1790126422,UA
|
||||
3174,173842.03139155387,UA
|
||||
3176,65699.76352408895,UA
|
||||
3177,143591.75419817626,UA
|
||||
3178,56434.04525832523,UA
|
||||
3179,389996.1670051216,UA
|
||||
3180,138452.84503524794,UA
|
||||
3181,67402.59500436619,UA
|
||||
3184,51204.293695376415,UA
|
||||
3185,46867.82356528432,UA
|
||||
3186,103892.35612417295,UA
|
||||
3187,193668.91476930346,UA
|
||||
3189,54584.176457692694,UA
|
||||
3190,219077.64942830536,UA
|
||||
3197,88516.52699983507,UA
|
||||
3198,298166.8272673622,UA
|
||||
3199,61334.952541812374,UA
|
||||
3229,175692.61136747137,UA
|
||||
3230,106722.62773321665,UA
|
||||
3236,61542.06264321315,UA
|
||||
3241,83752.90489164277,UA
|
||||
4301,48419.52825967164,UA
|
||||
4305,147759.74280349456,UA
|
||||
4306,53156.905740992224,UA
|
||||
4315,218025.78516351627,UA
|
||||
4317,155240.40554731718,UA
|
||||
4318,1342144.2459407183,UA
|
||||
4319,91669.1449633853,UA
|
||||
4321,85852.49282415409,UA
|
||||
4347,67938.7698430624,UA
|
||||
4357,20064.979012172935,UA
|
||||
4360,47840.51245168512,UA
|
||||
4361,55580.924388032574,UA
|
||||
4362,165753.82588729708,UA
|
||||
4363,46390.2448142152,UA
|
||||
4365,96265.47592938849,UA
|
||||
4366,272003.25510057947,UA
|
||||
4367,80878.50229245829,UA
|
||||
4370,330072.35444044066,UA
|
||||
4371,7707066.181975477,UA
|
||||
4373,2019766.7891575783,UA
|
||||
4374,985354.331818515,UA
|
||||
4377,230805.08833664874,UA
|
||||
4382,125670.67125287943,UA
|
||||
4383,46914.065511740075,UA
|
||||
4384,48020.804310510954,UA
|
||||
4385,55612.34707641123,UA
|
||||
4387,74558.3475791577,UA
|
||||
4388,245243.33449409154,UA
|
||||
4389,95696.56767732685,UA
|
||||
4391,251085.7523045193,UA
|
||||
4401,66375.82996856027,UA
|
||||
4403,111954.41038437477,UA
|
||||
4405,46911.68560148837,UA
|
||||
4408,150782.51691456966,UA
|
||||
4409,112776.7399582134,UA
|
||||
4410,153076.56860965435,UA
|
||||
4412,192629.31238456024,UA
|
||||
4413,181295.3120834606,UA
|
||||
4414,995694.9413199169,UA
|
||||
4416,157640.7868989174,UA
|
||||
4418,77580.20674809469,UA
|
||||
4420,122320.99275223716,UA
|
||||
4424,184891.10924920067,UA
|
||||
4425,84486.75974340564,UA
|
||||
4431,50485.84380961137,UA
|
||||
4435,231040.45446464577,UA
|
||||
4436,81222.18707585508,UA
|
||||
4438,114819.76472988473,UA
|
||||
4439,76839.1052178896,UA
|
||||
4440,135337.0313562152,UA
|
||||
4441,49159.485269198034,UA
|
||||
7031,42001.73757065917,UA
|
||||
7059,159790.48382874,UA
|
||||
7063,39599.10564971086,UA
|
|
@ -1 +1,37 @@
|
||||
Name,Fueltype,Technology,Set,Country,Capacity,Efficiency,Duration,Volume_Mm3,DamHeight_m,YearCommissioned,Retrofit,lat,lon,projectID,YearDecommissioning
|
||||
,Name,Fueltype,Technology,Set,Country,Capacity,Efficiency,Duration,Volume_Mm3,DamHeight_m,StorageCapacity_MWh,DateIn,DateRetrofit,DateMothball,DateOut,lat,lon,EIC,projectID
|
||||
1266,Khmelnitskiy,Nuclear,,PP,UA,1901.8916595755832,,0.0,0.0,0.0,0.0,1988.0,2005.0,,,50.3023,26.6466,[nan],"{'GEO': ['GEO3842'], 'GPD': ['WRI1005111'], 'CARMA': ['CARMA22000']}"
|
||||
1268,Kaniv,Hydro,Reservoir,PP,UA,452.1656050955414,,0.0,0.0,0.0,0.0,1972.0,2003.0,,,49.76653,31.47165,[nan],"{'GEO': ['GEO43017'], 'GPD': ['WRI1005122'], 'CARMA': ['CARMA21140']}"
|
||||
1269,Kahovska kakhovka,Hydro,Reservoir,PP,UA,352.45222929936307,,0.0,0.0,0.0,0.0,1955.0,1956.0,,,46.77858,33.36965,[nan],"{'GEO': ['GEO43018'], 'GPD': ['WRI1005118'], 'CARMA': ['CARMA20855']}"
|
||||
1347,Kharkiv,Natural Gas,Steam Turbine,CHP,UA,494.94274967602314,,0.0,0.0,0.0,0.0,1979.0,1980.0,,,49.9719,36107,[nan],"{'GEO': ['GEO43027'], 'GPD': ['WRI1005126'], 'CARMA': ['CARMA21972']}"
|
||||
1348,Kremenchuk,Hydro,Reservoir,PP,UA,617.0382165605096,,0.0,0.0,0.0,0.0,1959.0,1960.0,,,49.07759,33.2505,[nan],"{'GEO': ['GEO43019'], 'GPD': ['WRI1005121'], 'CARMA': ['CARMA23072']}"
|
||||
1377,Krivorozhskaya,Hard Coal,Steam Turbine,PP,UA,2600.0164509342876,,0.0,0.0,0.0,0.0,1965.0,1992.0,,,47.5432,33.6583,[nan],"{'GEO': ['GEO42989'], 'GPD': ['WRI1005100'], 'CARMA': ['CARMA23176']}"
|
||||
1407,Zmiyevskaya zmiivskaya,Hard Coal,Steam Turbine,PP,UA,2028.3816283884514,,0.0,0.0,0.0,0.0,1960.0,2005.0,,,49.5852,36.5231,[nan],"{'GEO': ['GEO42999'], 'GPD': ['WRI1005103'], 'CARMA': ['CARMA51042']}"
|
||||
1408,Pridneprovskaya,Hard Coal,Steam Turbine,CHP,UA,1627.3152609570984,,0.0,0.0,0.0,0.0,1959.0,1966.0,,,48.4051,35.1131,[nan],"{'GEO': ['GEO42990'], 'GPD': ['WRI1005102'], 'CARMA': ['CARMA35874']}"
|
||||
1409,Kurakhovskaya,Hard Coal,Steam Turbine,PP,UA,1371.0015824607397,,0.0,0.0,0.0,0.0,1972.0,2003.0,,,47.9944,37.24022,[nan],"{'GEO': ['GEO42994'], 'GPD': ['WRI1005104'], 'CARMA': ['CARMA23339']}"
|
||||
1410,Dobrotvorsky,Hard Coal,Steam Turbine,PP,UA,553.1949895604868,,0.0,0.0,0.0,0.0,1960.0,1964.0,,,50.2133,24375,[nan],"{'GEO': ['GEO42992'], 'GPD': ['WRI1005096'], 'CARMA': ['CARMA10971']}"
|
||||
1422,Zuyevskaya,Hard Coal,Steam Turbine,PP,UA,1147.87960333801,,0.0,0.0,0.0,0.0,1982.0,2007.0,,,48.0331,38.28615,[nan],"{'GEO': ['GEO42995'], 'GPD': ['WRI1005106'], 'CARMA': ['CARMA51083']}"
|
||||
1423,Zaporozhye,Nuclear,,PP,UA,5705.67497872675,,0.0,0.0,0.0,0.0,1985.0,1996.0,,,47.5119,34.5863,[nan],"{'GEO': ['GEO6207'], 'GPD': ['WRI1005114'], 'CARMA': ['CARMA50875']}"
|
||||
1424,Trypilska,Hard Coal,Steam Turbine,PP,UA,1659.5849686814602,,0.0,0.0,0.0,0.0,1969.0,1972.0,,,50.1344,30.7468,[nan],"{'GEO': ['GEO43000'], 'GPD': ['WRI1005099'], 'CARMA': ['CARMA46410']}"
|
||||
1425,Tashlyk,Hydro,Pumped Storage,Store,UA,285.55968954109585,,0.0,0.0,0.0,0.0,2006.0,2007.0,,,47.7968,31.1811,[nan],"{'GEO': ['GEO43025'], 'GPD': ['WRI1005117'], 'CARMA': ['CARMA44696']}"
|
||||
1426,Starobeshivska,Hard Coal,Steam Turbine,PP,UA,1636.5351774497733,,0.0,0.0,0.0,0.0,1961.0,1967.0,,,47.7997,38.00612,[nan],"{'GEO': ['GEO43003'], 'GPD': ['WRI1005105'], 'CARMA': ['CARMA43083']}"
|
||||
1427,South,Nuclear,,PP,UA,2852.837489363375,,0.0,0.0,0.0,0.0,1983.0,1989.0,,,47812,31.22,[nan],"{'GEO': ['GEO5475'], 'GPD': ['WRI1005113'], 'CARMA': ['CARMA42555']}"
|
||||
1428,Rovno rivne,Nuclear,,PP,UA,2695.931427448389,,0.0,0.0,0.0,0.0,1981.0,2006.0,,,51.3245,25.89744,[nan],"{'GEO': ['GEO5174'], 'GPD': ['WRI1005112'], 'CARMA': ['CARMA38114']}"
|
||||
1429,Ladyzhinska,Hard Coal,Steam Turbine,PP,UA,1659.5849686814602,,0.0,0.0,0.0,0.0,1970.0,1971.0,,,48706,29.2202,[nan],"{'GEO': ['GEO42993'], 'GPD': ['WRI1005098'], 'CARMA': ['CARMA24024']}"
|
||||
1430,Kiev,Hydro,Pumped Storage,PP,UA,635.8694635681177,,0.0,0.0,0.0,0.0,1964.0,1972.0,,,50.5998,30501,"[nan, nan]","{'GEO': ['GEO43024', 'GEO43023'], 'GPD': ['WRI1005123', 'WRI1005124'], 'CARMA': ['CARMA23516', 'CARMA23517']}"
|
||||
2450,Cet chisinau,Natural Gas,,PP,MD,306.0,,0.0,0.0,0.0,0.0,,,,,47.027550000000005,28.8801,"[nan, nan]","{'GPD': ['WRI1002985', 'WRI1002984'], 'CARMA': ['CARMA8450', 'CARMA8451']}"
|
||||
2460,Hydropower che costesti,Hydro,,PP,MD,16.0,,0.0,0.0,0.0,0.0,1978.0,,,,47.8381,27.2246,[nan],"{'GPD': ['WRI1002987'], 'CARMA': ['CARMA9496']}"
|
||||
2465,Moldavskaya gres,Hard Coal,,PP,MD,2520.0,,0.0,0.0,0.0,0.0,,,,,46.6292,29.9407,[nan],"{'GPD': ['WRI1002989'], 'CARMA': ['CARMA28979']}"
|
||||
2466,Hydropower dubasari,Hydro,,PP,MD,48.0,,0.0,0.0,0.0,0.0,,,,,47.2778,29123,[nan],"{'GPD': ['WRI1002988'], 'CARMA': ['CARMA11384']}"
|
||||
2676,Cet nord balti,Natural Gas,,PP,MD,24.0,,0.0,0.0,0.0,0.0,,,,,47.7492,27.8938,[nan],"{'GPD': ['WRI1002986'], 'CARMA': ['CARMA3071']}"
|
||||
2699,Dniprodzerzhynsk,Hydro,Reservoir,PP,UA,360.3503184713376,,0.0,0.0,0.0,0.0,1963.0,1964.0,,,48.5485,34.541015,[nan],"{'GEO': ['GEO43020'], 'GPD': ['WRI1005119']}"
|
||||
2707,Burshtynska tes,Hard Coal,Steam Turbine,PP,UA,2212.779958241947,,0.0,0.0,0.0,0.0,1965.0,1984.0,,,49.21038,24.66654,[nan],"{'GEO': ['GEO42991'], 'GPD': ['WRI1005097']}"
|
||||
2708,Danipro dnieper,Hydro,Reservoir,PP,UA,1484.8407643312103,,0.0,0.0,0.0,0.0,1932.0,1947.0,,,47.86944,35.08611,[nan],"{'GEO': ['GEO43016'], 'GPD': ['WRI1005120']}"
|
||||
2709,Dniester,Hydro,Pumped Storage,Store,UA,612.7241020616891,,0.0,0.0,0.0,0.0,2009.0,2011.0,,,48.51361,27.47333,[nan],"{'GEO': ['GEO43022'], 'GPD': ['WRI1005116', 'WRI1005115']}"
|
||||
2710,Kiev,Natural Gas,Steam Turbine,CHP,UA,458.2803237740955,,0.0,0.0,0.0,0.0,1982.0,1984.0,,,50532,30.6625,[nan],"{'GEO': ['GEO42998'], 'GPD': ['WRI1005125']}"
|
||||
2712,Luganskaya,Hard Coal,Steam Turbine,PP,UA,1060.2903966575996,,0.0,0.0,0.0,0.0,1962.0,1969.0,,,48.74781,39.2624,[nan],"{'GEO': ['GEO42996'], 'GPD': ['WRI1005110']}"
|
||||
2713,Slavyanskaya,Hard Coal,Steam Turbine,PP,UA,737.5933194139823,,0.0,0.0,0.0,0.0,1971.0,1971.0,,,48872,37.76567,[nan],"{'GEO': ['GEO43002'], 'GPD': ['WRI1005109']}"
|
||||
2714,Vuhlehirska uglegorskaya,Hard Coal,Steam Turbine,PP,UA,3319.1699373629203,,0.0,0.0,0.0,0.0,1972.0,1977.0,,,48.4633,38.20328,[nan],"{'GEO': ['GEO43001'], 'GPD': ['WRI1005107']}"
|
||||
2715,Zaporiska,Hard Coal,Steam Turbine,PP,UA,3319.1699373629203,,0.0,0.0,0.0,0.0,1972.0,1977.0,,,47.5089,34.6253,[nan],"{'GEO': ['GEO42988'], 'GPD': ['WRI1005101']}"
|
||||
3678,Mironovskaya,Hard Coal,,PP,UA,815.0,,0.0,0.0,0.0,0.0,,,,,48.3407,38.4049,[nan],"{'GPD': ['WRI1005108'], 'CARMA': ['CARMA28679']}"
|
||||
3679,Kramatorskaya,Hard Coal,,PP,UA,120.0,,0.0,0.0,0.0,0.0,1974.0,,,,48.7477,37.5723,[nan],"{'GPD': ['WRI1075856'], 'CARMA': ['CARMA54560']}"
|
||||
3680,Chernihiv,Hard Coal,,PP,UA,200.0,,0.0,0.0,0.0,0.0,1968.0,,,,51455,31.2602,[nan],"{'GPD': ['WRI1075853'], 'CARMA': ['CARMA8190']}"
|
||||
|
|
@ -1,50 +1,53 @@
|
||||
https://www.eia.gov/international/data/world/electricity/electricity-generation?pd=2&p=000000000000000000000000000000g&u=1&f=A&v=mapbubble&a=-&i=none&vo=value&t=R&g=000000000000002&l=73-1028i008017kg6368g80a4k000e0ag00gg0004g8g0ho00g000400008&s=315532800000&e=1577836800000&ev=false&
|
||||
Report generated on: 03-28-2022 11:20:48
|
||||
"API","","1980","1981","1982","1983","1984","1985","1986","1987","1988","1989","1990","1991","1992","1993","1994","1995","1996","1997","1998","1999","2000","2001","2002","2003","2004","2005","2006","2007","2008","2009","2010","2011","2012","2013","2014","2015","2016","2017","2018","2019","2020"
|
||||
"","hydroelectricity net generation (billion kWh)","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""
|
||||
"INTL.33-12-EURO-BKWH.A"," Europe","458.018","464.155","459.881","473.685","481.241","476.739","459.535","491.085","534.517","465.365","474.466","475.47","509.041","526.448","531.815","543.743","529.114164","543.845616","562.441501","569.308453","591.206662","587.371195","541.542535","506.19703","544.536443","545.176179","537.335934","540.934407","567.557921","564.244482","619.96477","543.05273","600.46622","631.86431","619.59229","615.53013","629.98906","562.59258","619.31106","610.62616","670.925"
|
||||
"INTL.33-12-ALB-BKWH.A"," Albania","2.919","3.018","3.093","3.167","3.241","3.315","3.365","3.979","3.713","3.846","2.82","3.483","3.187","3.281","3.733","4.162","5.669","4.978","4.872","5.231","4.548","3.519","3.477","5.117","5.411","5.319","4.951","2.76","3.759","5.201","7.49133","4.09068","4.67775","6.88941","4.67676","5.83605","7.70418","4.47975","8.46648","5.15394","5.281"
|
||||
"INTL.33-12-AUT-BKWH.A"," Austria","28.501","30.008","29.893","29.577","28.384","30.288","30.496","25.401","35.151","34.641","31.179","31.112","34.483","36.336","35.349","36.696","33.874","35.744","36.792","40.292","41.418","40.05","39.825","32.883","36.394","36.31","35.48","36.732","37.969","40.487","36.466","32.511","41.862","40.138","39.001","35.255","37.954","36.462","35.73","40.43655","45.344"
|
||||
"INTL.33-12-BEL-BKWH.A"," Belgium","0.274","0.377","0.325","0.331","0.348","0.282","0.339","0.425","0.354","0.3","0.263","0.226","0.338","0.252","0.342","0.335","0.237","0.30195","0.38511","0.338","0.455","0.437","0.356","0.245","0.314","0.285","0.355","0.385","0.406","0.325","0.298","0.193","0.353","0.376","0.289","0.314","0.367","0.268","0.311","0.108","1.29"
|
||||
"INTL.33-12-BIH-BKWH.A"," Bosnia and Herzegovina","--","--","--","--","--","--","--","--","--","--","--","--","3.374","2.343","3.424","3.607","5.104","4.608","4.511","5.477","5.043","5.129","5.215","4.456","5.919","5.938","5.798","3.961","4.818","6.177","7.946","4.343","4.173","7.164","5.876","5.495","5.585","3.7521","6.35382","6.02019","6.1"
|
||||
"INTL.33-12-BGR-BKWH.A"," Bulgaria","3.674","3.58","3.018","3.318","3.226","2.214","2.302","2.512","2.569","2.662","1.859","2.417","2.042","1.923","1.453","2.291","2.89","2.726","3.066","2.725","2.646","1.72","2.172","2.999","3.136","4.294","4.196","2.845","2.796","3.435","4.98168","2.84328","3.14622","3.99564","4.55598","5.59845","3.8412","2.79972","5.09553","3.34917","3.37"
|
||||
"INTL.33-12-HRV-BKWH.A"," Croatia","--","--","--","--","--","--","--","--","--","--","--","--","4.298","4.302","4.881","5.212","7.156","5.234","5.403","6.524","5.794","6.482","5.311","4.827","6.888","6.27","5.94","4.194","5.164","6.663","9.035","4.983","4.789","8.536","8.917","6.327","6.784","5.255","7.62399","5.87268","3.4"
|
||||
"INTL.33-12-CYP-BKWH.A"," Cyprus","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"
|
||||
"INTL.33-12-CZE-BKWH.A"," Czech Republic","--","--","--","--","--","--","--","--","--","--","--","--","--","1.355","1.445","1.982","1.949","1.68201","1.382","1.664","1.7404","2.033","2.467","1.369","1.999","2.356","2.525","2.068","2.004","2.405","2.775","1.95","2.107","2.704","1.909","1.779","1.983","1.852","1.615","1.98792","3.4"
|
||||
"INTL.33-12-DNK-BKWH.A"," Denmark","0.03","0.031","0.028","0.036","0.028","0.027","0.029","0.029","0.032","0.027","0.027","0.026","0.028","0.027","0.033","0.03","0.019","0.019","0.02673","0.031","0.03","0.028","0.032","0.021","0.027","0.023","0.023","0.028","0.026","0.019","0.021","0.017","0.017","0.013","0.015","0.018","0.019","0.018","0.015","0.01584","0.02"
|
||||
"INTL.33-12-EST-BKWH.A"," Estonia","--","--","--","--","--","--","--","--","--","--","--","--","0.001","0.001","0.003","0.002","0.002","0.003","0.004","0.004","0.005","0.007","0.006","0.013","0.022","0.022","0.014","0.021","0.028","0.032","0.027","0.03","0.042","0.026","0.027","0.027","0.035","0.026","0.015","0.01881","0.04"
|
||||
"INTL.33-12-FRO-BKWH.A"," Faroe Islands","0.049","0.049","0.049","0.049","0.049","0.049","0.049","0.049","0.062","0.071","0.074","0.074","0.083","0.073","0.075","0.075","0.069564","0.075066","0.076501","0.069453","0.075262","0.075195","0.095535","0.08483","0.093443","0.097986","0.099934","0.103407","0.094921","0.091482","0.06676","0.092","0.099","0.091","0.121","0.132","0.105","0.11","0.107","0.102","0.11"
|
||||
"INTL.33-12-FIN-BKWH.A"," Finland","10.115","13.518","12.958","13.445","13.115","12.211","12.266","13.658","13.229","12.9","10.75","13.065","14.956","13.341","11.669","12.796","11.742","12.11958","14.9","12.652","14.513","13.073","10.668","9.495","14.919","13.646","11.379","14.035","16.941","12.559","12.743","12.278","16.667","12.672","13.24","16.584","15.634","14.61","13.137","12.31461","15.56"
|
||||
"INTL.33-12-CSK-BKWH.A"," Former Czechoslovakia","4.8","4.2","3.7","3.9","3.2","4.3","4","4.853","4.355","4.229","3.919","3.119","3.602","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--"
|
||||
"INTL.33-12-SCG-BKWH.A"," Former Serbia and Montenegro","--","--","--","--","--","--","--","--","--","--","--","--","11.23","10.395","11.016","12.071","14.266","12.636","12.763","13.243","11.88","12.326","11.633","9.752","11.01","11.912","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--"
|
||||
"INTL.33-12-YUG-BKWH.A"," Former Yugoslavia","27.868","25.044","23.295","21.623","25.645","24.363","27.474","25.98","25.612","23.256","19.601","18.929","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--"
|
||||
"INTL.33-12-FRA-BKWH.A"," France","68.253","70.358","68.6","67.515","64.01","60.248","60.953","68.623","73.952","45.744","52.796","56.277","68.313","64.3","78.057","72.196","64.43","63.151","61.479","71.832","66.466","73.888","59.992","58.567","59.276","50.965","55.741","57.029","63.017","56.428","61.945","45.184","59.099","71.042","62.993","54.876","60.094","49.389","64.485","56.98242","64.84"
|
||||
"INTL.33-12-DEU-BKWH.A"," Germany","--","--","--","--","--","--","--","--","--","--","--","14.742","17.223","17.699","19.731","21.562","21.737","17.18343","17.044","19.451","21.515","22.506","22.893","19.071","20.866","19.442","19.808","20.957","20.239","18.841","20.678","17.323","21.331","22.66","19.31","18.664","20.214","19.985","17.815","19.86039","24.75"
|
||||
"INTL.33-12-DDR-BKWH.A"," Germany, East","1.658","1.718","1.748","1.683","1.748","1.758","1.767","1.726","1.719","1.551","1.389","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--"
|
||||
"INTL.33-12-DEUW-BKWH.A"," Germany, West","17.125","17.889","17.694","16.713","16.434","15.354","16.526","18.36","18.128","16.482","15.769","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--"
|
||||
"INTL.33-12-GIB-BKWH.A"," Gibraltar","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"
|
||||
"INTL.33-12-GRC-BKWH.A"," Greece","3.396","3.398","3.551","2.331","2.852","2.792","3.222","2.768","2.354","1.888","1.751","3.068","2.181","2.26","2.573","3.494","4.305","3.84318","3.68","4.546","3.656","2.076","2.772","4.718","4.625","4.967","5.806","2.565","3.279","5.32","7.431","3.998","4.387","6.337","4.464","5.782","5.543","3.962","5.035","3.9798","3.43"
|
||||
"INTL.33-12-HUN-BKWH.A"," Hungary","0.111","0.166","0.158","0.153","0.179","0.153","0.152","0.167","0.167","0.156","0.176","0.192","0.156","0.164","0.159","0.161","0.205","0.21384","0.15345","0.179","0.176","0.184","0.192","0.169","0.203","0.2","0.184","0.208","0.211","0.226","0.184","0.216","0.206","0.208","0.294","0.227","0.253","0.214","0.216","0.21681","0.24"
|
||||
"INTL.33-12-ISL-BKWH.A"," Iceland","3.053","3.085","3.407","3.588","3.738","3.667","3.846","3.918","4.169","4.217","4.162","4.162","4.267","4.421","4.47","4.635","4.724","5.15493","5.565","5.987","6.292","6.512","6.907","7.017","7.063","6.949","7.22","8.31","12.303","12.156","12.51","12.382","12.214","12.747","12.554","13.541","13.092","13.892","13.679","13.32441","12.46"
|
||||
"INTL.33-12-IRL-BKWH.A"," Ireland","0.833","0.855","0.792","0.776","0.68","0.824","0.91","0.673","0.862","0.684","0.69","0.738","0.809","0.757","0.911","0.706","0.715","0.67122","0.907","0.838","0.838","0.59","0.903","0.592","0.624","0.625","0.717","0.66","0.959","0.893","0.593","0.699","0.795","0.593","0.701","0.798","0.674","0.685","0.687","0.87813","1.21"
|
||||
"INTL.33-12-ITA-BKWH.A"," Italy","44.997","42.782","41.216","40.96","41.923","40.616","40.626","39.05","40.205","33.647","31.31","41.817","41.778","41.011","44.212","37.404","41.617","41.18697","40.808","44.911","43.763","46.343","39.125","33.303","41.915","35.706","36.624","32.488","41.207","48.647","50.506","45.36477","41.45625","52.24626","57.95955","45.08163","42.00768","35.83701","48.29913","45.31824","47.72"
|
||||
"INTL.33-12-XKS-BKWH.A"," Kosovo","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","0.075","0.119","0.154","0.104","0.095","0.142","0.149","0.139","0.243","0.177","0.27027","0.2079","0.26"
|
||||
"INTL.33-12-LVA-BKWH.A"," Latvia","--","--","--","--","--","--","--","--","--","--","--","--","2.498","2.846","3.272","2.908","1.841","2.922","2.99","2.729","2.791","2.805","2.438","2.243","3.078","3.293","2.671","2.706","3.078","3.422","3.488","2.857","3.677","2.838","1.953","1.841","2.523","4.356","2.417","2.08692","2.59"
|
||||
"INTL.33-12-LTU-BKWH.A"," Lithuania","--","--","--","--","--","--","--","--","--","--","--","--","0.308","0.389","0.447","0.369","0.323","0.291","0.413","0.409","0.336","0.322","0.35","0.323","0.417","0.446193","0.393","0.417","0.398","0.42","0.535","0.475","0.419","0.516","0.395","0.346","0.45","0.597","0.427","0.34254","1.06"
|
||||
"INTL.33-12-LUX-BKWH.A"," Luxembourg","0.086","0.095","0.084","0.083","0.088","0.071","0.084","0.101","0.097","0.072","0.07","0.083","0.069","0.066","0.117","0.087","0.059","0.082","0.114","0.084","0.119","0.117","0.098","0.078","0.103","0.093","0.11","0.116","0.131","0.105","0.104","0.061","0.095","0.114","0.104","0.095","0.111","0.082","0.089","0.10593","1.09"
|
||||
"INTL.33-12-MLT-BKWH.A"," Malta","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"
|
||||
"INTL.33-12-MNE-BKWH.A"," Montenegro","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","1.733","1.271","1.524","2.05","2.723","1.192","1.462","2.479","1.734","1.476","1.825","1.014","2.09187","1.78","1.8"
|
||||
"INTL.33-12-NLD-BKWH.A"," Netherlands","0","0","0","0","0","0.003","0.003","0.001","0.002","0.037","0.119","0.079","0.119","0.091","0.1","0.087","0.079","0.09108","0.111","0.089","0.141","0.116","0.109","0.071","0.094","0.087","0.105","0.106","0.101","0.097","0.105","0.057","0.104","0.114","0.112","0.093","0.1","0.061","0.072","0.07326","0.05"
|
||||
"INTL.33-12-MKD-BKWH.A"," North Macedonia","--","--","--","--","--","--","--","--","--","--","--","--","0.817","0.517","0.696","0.793","0.842","0.891","1.072","1.375","1.158","0.62","0.749","1.36","1.467","1.477","1.634","1","0.832","1.257","2.407","1.419","1.031","1.568","1.195","1.846","1.878","1.099","1.773","1.15236","1.24"
|
||||
"INTL.33-12-NOR-BKWH.A"," Norway","82.717","91.876","91.507","104.704","104.895","101.464","95.321","102.341","107.919","117.369","119.933","109.032","115.505","118.024","110.398","120.315","102.823","108.677","114.546","120.237","140.4","119.258","128.078","104.425","107.693","134.331","118.175","132.319","137.654","124.03","116.257","119.78","141.189","127.551","134.844","136.662","142.244","141.651","138.202","123.66288","141.69"
|
||||
"INTL.33-12-POL-BKWH.A"," Poland","2.326","2.116","1.528","1.658","1.394","1.833","1.534","1.644","1.775","1.593","1.403","1.411","1.492","1.473","1.716","1.868","1.912","1.941","2.286","2.133","2.085","2.302","2.256","1.654","2.06","2.179","2.022","2.328","2.13","2.351","2.9","2.313","2.02","2.421","2.165","1.814","2.117","2.552","1.949","1.93842","2.93"
|
||||
"INTL.33-12-PRT-BKWH.A"," Portugal","7.873","4.934","6.82","7.897","9.609","10.512","8.364","9.005","12.037","5.72","9.065","8.952","4.599","8.453","10.551","8.26","14.613","12.97395","12.853","7.213","11.21","13.894","7.722","15.566","9.77","4.684","10.892","9.991","6.73","8.201","15.954","11.423","5.589","13.652","15.471","8.615","15.608","5.79","12.316","8.6526","13.96"
|
||||
"INTL.33-12-ROU-BKWH.A"," Romania","12.506","12.605","11.731","9.934","11.208","11.772","10.688","11.084","13.479","12.497","10.87","14.107","11.583","12.64","12.916","16.526","15.597","17.334","18.69","18.107","14.63","14.774","15.886","13.126","16.348","20.005","18.172","15.806","17.023","15.379","19.684","14.581","11.945","14.807","18.618","16.467","17.848","14.349","17.48736","15.65289","15.53"
|
||||
"INTL.33-12-SRB-BKWH.A"," Serbia","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","10.855","9.937","9.468","10.436","11.772","8.58","9.193","10.101","10.893","9.979","10.684","9.061","10.53261","10.07028","9.66"
|
||||
"INTL.33-12-SVK-BKWH.A"," Slovakia","--","--","--","--","--","--","--","--","--","--","--","--","--","3.432","4.311","4.831","4.185","4.023","4.224","4.429","4.569","4.878","5.215","3.4452","4.059","4.592","4.355","4.406","4","4.324","5.184","3.211","3.687","4.329","3.762","3.701","4.302","4.321","3.506","4.27383","4.67"
|
||||
"INTL.33-12-SVN-BKWH.A"," Slovenia","--","--","--","--","--","--","--","--","--","--","--","--","3.379","2.974","3.348","3.187","3.616","3.046","3.4","3.684","3.771","3.741","3.265","2.916","4.033","3.426","3.555","3.233","3.978","4.666","4.452","3.506","3.841","4.562","6.011","3.75","4.443","3.814","4.643","4.43421","5.24"
|
||||
"INTL.33-12-ESP-BKWH.A"," Spain","29.16","21.64","25.99","26.696","31.088","30.895","26.105","27.016","34.76","19.046","25.16","27.01","18.731","24.133","27.898","22.881","39.404","34.43","33.665","22.634","29.274","40.617","22.691","40.643","31.359","18.209","25.699","27.036","23.13","26.147","41.576","30.07","20.192","36.45","38.815","27.656","35.77","18.007","33.743","24.23025","33.34"
|
||||
"INTL.33-12-SWE-BKWH.A"," Sweden","58.133","59.006","54.369","62.801","67.106","70.095","60.134","70.95","69.016","70.911","71.778","62.603","73.588","73.905","58.508","67.421","51.2226","68.365","74.25","70.974","77.798","78.269","65.696","53.005","59.522","72.075","61.106","65.497","68.378","65.193","66.279","66.047","78.333","60.81","63.227","74.734","61.645","64.651","61.79","64.46583","71.6"
|
||||
"INTL.33-12-CHE-BKWH.A"," Switzerland","32.481","35.13","35.974","35.069","29.871","31.731","32.576","34.328","35.437","29.477","29.497","31.756","32.373","35.416","38.678","34.817","28.458","33.70257","33.136","39.604","36.466","40.895","34.862","34.471","33.411","30.914","30.649","34.898","35.676","35.366","35.704","32.069","38.218","38.08","37.659","37.879","34.281","33.754","34.637","37.6596","40.62"
|
||||
"INTL.33-12-TUR-BKWH.A"," Turkey","11.159","12.308","13.81","11.13","13.19","11.822","11.637","18.314","28.447","17.61","22.917","22.456","26.302","33.611","30.28","35.186","40.07","39.41784","41.80671","34.33","30.57","23.77","33.346","34.977","45.623","39.165","43.802","35.492","32.937","35.598","51.423","51.155","56.669","58.225","39.75","65.856","66.686","57.824","59.49","87.99714","77.39"
|
||||
"INTL.33-12-GBR-BKWH.A"," United Kingdom","3.921","4.369","4.543","4.548","3.992","4.08","4.767","4.13","4.915","4.732","5.119","4.534","5.329","4.237","5.043","4.79","3.359","4.127","5.067","5.283","5.035","4.015","4.74","3.195","4.795","4.873","4.547","5.026","5.094","5.178","3.566","5.655","5.286","4.667","5.832","6.246","5.342","5.836","5.189","5.89941","7.64"
|
||||
https://www.eia.gov/international/data/world/electricity/electricity-generation?pd=2&p=000000000000000000000000000000g&u=1&f=A&v=mapbubble&a=-&i=none&vo=value&t=R&g=000000000000002&l=73-1028i008017kg6368g80a4k000e0ag00gg0004g8g0ho00g000400008&l=72-00000000000000000000000000080000000000000000000g&s=315532800000&e=1609459200000&ev=false&,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Report generated on: 01-06-2023 21:17:46,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
API,,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021
|
||||
,hydroelectricity net generation (billion kWh),,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
INTL.33-12-EURO-BKWH.A, Europe,"458,018","464,155","459,881","473,685","481,241","476,739","459,535","491,085","534,517","465,365","474,466","475,47","509,041","526,448","531,815","543,743","529,114164","543,845616","562,491501","566,861453","588,644662","584,806195","539,051405","503,7067","542,112443","542,974669","535,006084","538,449707","565,143111","561,761402","617,547148","540,926277","598,055253","629,44709","617,111295","613,079848","627,720566217","560,362524","616,5081462","606,5997419","644,1106599","628,1390143"
|
||||
INTL.33-12-ALB-BKWH.A, Albania,"2,919","3,018","3,093","3,167","3,241","3,315","3,365","3,979","3,713","3,846","2,82","3,483","3,187","3,281","3,733","4,162","5,669","4,978","4,872","5,231","4,548","3,519","3,477","5,117","5,411","5,319","4,951","2,76","3,759","5,201","7,49133","4,09068","4,67775","6,88941","4,67676","5,83605","7,70418","4,47975","8,46648","5,15394","5,281","8,891943"
|
||||
INTL.33-12-AUT-BKWH.A, Austria,"28,501","30,008","29,893","29,577","28,384","30,288","30,496","25,401","35,151","34,641","31,179","31,112","34,483","36,336","35,349","36,696","33,874","35,744","36,792","40,292","41,418","40,05","39,825","32,883","36,394","36,31","35,48","36,732","37,969","40,487","36,466","32,511","41,862","40,138","39,001","35,255","37,954","36,462","35,73","40,43655","41,9356096","38,75133"
|
||||
INTL.33-12-BEL-BKWH.A, Belgium,"0,274","0,377","0,325","0,331","0,348","0,282","0,339","0,425","0,354","0,3","0,263","0,226","0,338","0,252","0,342","0,335","0,237","0,30195","0,38511","0,338","0,455","0,437","0,356","0,245","0,314","0,285","0,355","0,385","0,406","0,325","0,298","0,193","0,353","0,376","0,289","0,314","0,367","0,268","0,3135","0,302","0,2669","0,3933"
|
||||
INTL.33-12-BIH-BKWH.A, Bosnia and Herzegovina,--,--,--,--,--,--,--,--,--,--,--,--,"3,374","2,343","3,424","3,607","5,104","4,608","4,511","5,477","5,043","5,129","5,215","4,456","5,919","5,938","5,798","3,961","4,818","6,177","7,946","4,343","4,173","7,164","5,876","5,495","5,585","3,7521","6,35382","6,02019","4,58","6,722"
|
||||
INTL.33-12-BGR-BKWH.A, Bulgaria,"3,674","3,58","3,018","3,318","3,226","2,214","2,302","2,512","2,569","2,662","1,859","2,417","2,042","1,923","1,453","2,291","2,89","2,726","3,066","2,725","2,646","1,72","2,172","2,999","3,136","4,294","4,196","2,845","2,796","3,435","4,98168","2,84328","3,14622","3,99564","4,55598","5,59845","3,8412","2,79972","5,09553","2,929499","2,820398","4,819205"
|
||||
INTL.33-12-HRV-BKWH.A, Croatia,--,--,--,--,--,--,--,--,--,--,--,--,"4,298","4,302","4,881","5,212","7,156","5,234","5,403","6,524","5,794","6,482","5,311","4,827","6,888","6,27","5,94","4,194","5,164","6,663","9,035","4,983","4,789","8,536","8,917","6,327","6,784","5,255","7,62399","5,87268","5,6624","7,1277"
|
||||
INTL.33-12-CYP-BKWH.A, Cyprus,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
INTL.33-12-CZE-BKWH.A, Czechia,--,--,--,--,--,--,--,--,--,--,--,--,--,"1,355","1,445","1,982","1,949","1,68201","1,382","1,664","1,7404","2,033","2,467","1,369","1,999","2,356","2,525","2,068","2,004","2,405","2,775","1,95","2,107","2,704","1,909","1,779","1,983","1,852","1,615","1,98792","2,143884","2,40852"
|
||||
INTL.33-12-DNK-BKWH.A, Denmark,"0,03","0,031","0,028","0,036","0,028","0,027","0,029","0,029","0,032","0,027","0,027","0,026","0,028","0,027","0,033","0,03","0,019","0,019","0,02673","0,031","0,03","0,028","0,032","0,021","0,027","0,023","0,023","0,028","0,026","0,019","0,021","0,017","0,017","0,013","0,015","0,01803","0,01927","0,017871","0,0148621","0,0172171","0,017064","0,016295"
|
||||
INTL.33-12-EST-BKWH.A, Estonia,--,--,--,--,--,--,--,--,--,--,--,--,"0,001","0,001","0,003","0,002","0,002","0,003","0,004","0,004","0,005","0,007","0,006","0,013","0,022","0,022","0,014","0,021","0,028","0,032","0,027","0,029999","0,042","0,026","0,027","0,027","0,035","0,025999","0,0150003","0,0189999","0,03","0,0248"
|
||||
INTL.33-12-FRO-BKWH.A, Faroe Islands,"0,049","0,049","0,049","0,049","0,049","0,049","0,049","0,049","0,062","0,071","0,074","0,074","0,083","0,073","0,075","0,075","0,069564","0,075066","0,076501","0,069453","0,075262","0,075195","0,095535","0,08483","0,093443","0,097986","0,099934","0,103407","0,094921","0,091482","0,06676","0,092","0,099","0,091","0,121","0,132","0,105","0,11","0,107","0,102","0,11","0,11"
|
||||
INTL.33-12-FIN-BKWH.A, Finland,"10,115","13,518","12,958","13,445","13,115","12,211","12,266","13,658","13,229","12,9","10,75","13,065","14,956","13,341","11,669","12,796","11,742","12,11958","14,9","12,652","14,513","13,073","10,668","9,495","14,919","13,646","11,379","14,035","16,941","12,559","12,743","12,278001","16,666998","12,672","13,240001","16,583999","15,634127","14,609473","13,1369998","12,2454823","15,883","15,766"
|
||||
INTL.33-12-CSK-BKWH.A, Former Czechoslovakia,"4,8","4,2","3,7","3,9","3,2","4,3",4,"4,853","4,355","4,229","3,919","3,119","3,602",--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--
|
||||
INTL.33-12-SCG-BKWH.A, Former Serbia and Montenegro,--,--,--,--,--,--,--,--,--,--,--,--,"11,23","10,395","11,016","12,071","14,266","12,636","12,763","13,243","11,88","12,326","11,633","9,752","11,01","11,912",--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--
|
||||
INTL.33-12-YUG-BKWH.A, Former Yugoslavia,"27,868","25,044","23,295","21,623","25,645","24,363","27,474","25,98","25,612","23,256","19,601","18,929",--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--
|
||||
INTL.33-12-FRA-BKWH.A, France,"68,253","70,358","68,6","67,515","64,01","60,248","60,953","68,623","73,952","45,744","52,796","56,277","68,313","64,3","78,057","72,196","64,43","63,151","61,479","71,832","66,466","73,888","59,992","58,567","59,276","50,965","55,741","57,029","63,017","56,428","61,945","45,184","59,099","71,042","62,993","54,876","60,094","49,389","64,485","56,913891","62,06191","58,856657"
|
||||
INTL.33-12-DEU-BKWH.A, Germany,--,--,--,--,--,--,--,--,--,--,--,"14,742","17,223","17,699","19,731","21,562","21,737","17,18343","17,044","19,451","21,515","22,506","22,893","19,071","20,866","19,442","19,808","20,957","20,239","18,841","20,678","17,323","21,331","22,66","19,31","18,664","20,214","19,985","17,694","19,731","18,322","19,252"
|
||||
INTL.33-12-DDR-BKWH.A," Germany, East","1,658","1,718","1,748","1,683","1,748","1,758","1,767","1,726","1,719","1,551","1,389",--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--
|
||||
INTL.33-12-DEUW-BKWH.A," Germany, West","17,125","17,889","17,694","16,713","16,434","15,354","16,526","18,36","18,128","16,482","15,769",--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--
|
||||
INTL.33-12-GIB-BKWH.A, Gibraltar,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
INTL.33-12-GRC-BKWH.A, Greece,"3,396","3,398","3,551","2,331","2,852","2,792","3,222","2,768","2,354","1,888","1,751","3,068","2,181","2,26","2,573","3,494","4,305","3,84318","3,68","4,546","3,656","2,076","2,772","4,718","4,625","4,967","5,806","2,565","3,279","5,32","7,431","3,998","4,387","6,337","4,464","5,782","5,543","3,962","5,035","3,9798","3,343687","5,909225"
|
||||
INTL.33-12-HUN-BKWH.A, Hungary,"0,111","0,166","0,158","0,153","0,179","0,153","0,152","0,167","0,167","0,156","0,176","0,192","0,156","0,164","0,159","0,161","0,205","0,21384","0,15345","0,179","0,176","0,184","0,192","0,169","0,203","0,2","0,184","0,208","0,211","0,226","0,184","0,215999","0,205999","0,207999","0,294001","0,226719","0,253308","0,213999","0,216","0,2129999","0,238","0,202379"
|
||||
INTL.33-12-ISL-BKWH.A, Iceland,"3,053","3,085","3,407","3,588","3,738","3,667","3,846","3,918","4,169","4,217","4,162","4,162","4,267","4,421","4,47","4,635","4,724","5,15493","5,565","5,987","6,292","6,512","6,907","7,017","7,063","6,949","7,22","8,31","12,303","12,156","12,509999","12,381999","12,213999","12,747001","12,554","13,541","13,091609","13,891929","13,679377","13,32911","12,9196201","13,5746171"
|
||||
INTL.33-12-IRL-BKWH.A, Ireland,"0,833","0,855","0,792","0,776","0,68","0,824","0,91","0,673","0,862","0,684","0,69","0,738","0,809","0,757","0,911","0,706","0,715","0,67122","0,907","0,838","0,838","0,59","0,903","0,592","0,624","0,625","0,717","0,66","0,959","0,893","0,593","0,699","0,795","0,593","0,701","0,798","0,674","0,685","0,687","0,87813","0,932656","0,750122"
|
||||
INTL.33-12-ITA-BKWH.A, Italy,"44,997","42,782","41,216","40,96","41,923","40,616","40,626","39,05","40,205","33,647","31,31","41,817","41,778","41,011","44,212","37,404","41,617","41,18697","40,808","44,911","43,763","46,343","39,125","33,303","41,915","35,706","36,624","32,488","41,207","48,647","50,506","45,36477","41,45625","52,24626","57,95955","45,08163","42,00768","35,83701","48,29913","45,31824","47,551784","44,739"
|
||||
INTL.33-12-XKS-BKWH.A, Kosovo,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,"0,075","0,119","0,154","0,104","0,095","0,142","0,149","0,139","0,243","0,177","0,27027","0,2079","0,262826","0,300635"
|
||||
INTL.33-12-LVA-BKWH.A, Latvia,--,--,--,--,--,--,--,--,--,--,--,--,"2,498","2,846","3,272","2,908","1,841","2,922","2,99","2,729","2,791","2,805","2,438","2,243","3,078","3,293","2,671","2,706","3,078","3,422","3,487998","2,8568","3,677","2,838","1,953","1,841","2,522819","4,355513","2,4170639","2,0958919","2,5840101","2,6889293"
|
||||
INTL.33-12-LTU-BKWH.A, Lithuania,--,--,--,--,--,--,--,--,--,--,--,--,"0,308","0,389","0,447","0,369","0,323","0,291","0,413","0,409","0,336","0,322","0,35","0,323","0,417","0,446193","0,393","0,417","0,398","0,42","0,535","0,475","0,419","0,516","0,395","0,346","0,45","0,597","0,427","0,34254","0,3006","0,3837"
|
||||
INTL.33-12-LUX-BKWH.A, Luxembourg,"0,086","0,095","0,084","0,083","0,088","0,071","0,084","0,101","0,097","0,072","0,07","0,083","0,069","0,066","0,117","0,087","0,059","0,082","0,114","0,084","0,119","0,117","0,098","0,078","0,103","0,093","0,11","0,116","0,131","0,105","0,104","0,061","0,095","0,114","0,104","0,095","0,111","0,082","0,089","0,10593","0,091602","0,1068"
|
||||
INTL.33-12-MLT-BKWH.A, Malta,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
INTL.33-12-MNE-BKWH.A, Montenegro,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,"1,733","1,271","1,524","2,05","2,723","1,192","1,462","2,479","1,734","1,476","1,825","1,014","1,693443","1,262781","0,867637","1,212652"
|
||||
INTL.33-12-NLD-BKWH.A, Netherlands,0,0,0,0,0,"0,003","0,003","0,001","0,002","0,037","0,119","0,079","0,119","0,091","0,1","0,087","0,079","0,09108","0,111","0,089","0,141","0,116","0,109","0,071","0,094","0,087","0,105","0,106","0,101","0,097","0,105","0,057","0,104389","0,11431","0,112202","0,0927","0,100078","0,060759","0,0723481","0,074182","0,0462851","0,0838927"
|
||||
INTL.33-12-MKD-BKWH.A, North Macedonia,--,--,--,--,--,--,--,--,--,--,--,--,"0,817","0,517","0,696","0,793","0,842","0,891","1,072","1,375","1,158","0,62","0,749","1,36","1,467","1,477","1,634",1,"0,832","1,257","2,407","1,419","1,031","1,568","1,195","1,846","1,878","1,099","1,773","1,15236","1,277144","1,451623"
|
||||
INTL.33-12-NOR-BKWH.A, Norway,"82,717","91,876","91,507","104,704","104,895","101,464","95,321","102,341","107,919","117,369","119,933","109,032","115,505","118,024","110,398","120,315","102,823","108,677","114,546","120,237","140,4","119,258","128,078","104,425","107,693","134,331","118,175","132,319","137,654","124,03","116,257","119,78","141,189","127,551","134,844","136,662","142,244","141,651","138,202","123,66288","141,69",144
|
||||
INTL.33-12-POL-BKWH.A, Poland,"2,326","2,116","1,528","1,658","1,394","1,833","1,534","1,644","1,775","1,593","1,403","1,411","1,492","1,473","1,716","1,868","1,912","1,941","2,286","2,133","2,085","2,302","2,256","1,654","2,06","2,179","2,022","2,328","2,13","2,351","2,9","2,313","2,02","2,421","2,165","1,814","2,117","2,552","1,949","1,93842","2,118337","2,339192"
|
||||
INTL.33-12-PRT-BKWH.A, Portugal,"7,873","4,934","6,82","7,897","9,609","10,512","8,364","9,005","12,037","5,72","9,065","8,952","4,599","8,453","10,551","8,26","14,613","12,97395","12,853","7,213","11,21","13,894","7,722","15,566","9,77","4,684","10,892","9,991","6,73","8,201","15,954","11,423","5,589","13,652","15,471","8,615","15,608","5,79","12,316","8,6526","12,082581","11,846464"
|
||||
INTL.33-12-ROU-BKWH.A, Romania,"12,506","12,605","11,731","9,934","11,208","11,772","10,688","11,084","13,479","12,497","10,87","14,107","11,583","12,64","12,916","16,526","15,597","17,334","18,69","18,107","14,63","14,774","15,886","13,126","16,348","20,005","18,172","15,806","17,023","15,379","19,684","14,581","11,945","14,807","18,618","16,467","17,848","14,349","17,48736","15,580622","15,381243","17,376933"
|
||||
INTL.33-12-SRB-BKWH.A, Serbia,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,"10,855","9,937","9,468","10,436","11,772","8,58","9,193","10,101","10,893","9,979","10,684","9,061","10,53261","9,457175","9,034496","11,284232"
|
||||
INTL.33-12-SVK-BKWH.A, Slovakia,--,--,--,--,--,--,--,--,--,--,--,--,--,"3,432","4,311","4,831","4,185","4,023","4,224","4,429","4,569","4,878","5,215","3,4452","4,059","4,592","4,355","4,406",4,"4,324","5,184","3,211","3,687","4,329","3,762","3,701","4,302","4,321","3,506","4,27383","4,517","4,17"
|
||||
INTL.33-12-SVN-BKWH.A, Slovenia,--,--,--,--,--,--,--,--,--,--,--,--,"3,379","2,974","3,348","3,187","3,616","3,046","3,4","3,684","3,771","3,741","3,265","2,916","4,033","3,426","3,555","3,233","3,978","4,666","4,452","3,506","3,841","4,562","6,011","3,75","4,443","3,814","4,643","4,43421","4,93406","4,711944"
|
||||
INTL.33-12-ESP-BKWH.A, Spain,"29,16","21,64","25,99","26,696","31,088","30,895","26,105","27,016","34,76","19,046","25,16","27,01","18,731","24,133","27,898","22,881","39,404","34,43","33,665","22,634","29,274","40,617","22,691","40,643","31,359","18,209","25,699","27,036","23,13","26,147","41,576","30,07","20,192","36,45","38,815","27,656","35,77","18,007","33,743","24,23025","30,507","29,626"
|
||||
INTL.33-12-SWE-BKWH.A, Sweden,"58,133","59,006","54,369","62,801","67,106","70,095","60,134","70,95","69,016","70,911","71,778","62,603","73,588","73,905","58,508","67,421","51,2226","68,365","74,25","70,974","77,798","78,269","65,696","53,005","59,522","72,075","61,106","65,497","68,378","65,193","66,279","66,047","78,333","60,81","63,227","74,734","61,645","64,651","61,79","64,46583","71,6","71,086"
|
||||
INTL.33-12-CHE-BKWH.A, Switzerland,"32,481","35,13","35,974","35,069","29,871","31,731","32,576","34,328","35,437","29,477","29,497","31,756","32,373","35,416","38,678","34,817","28,458","33,70257","33,136","37,104","33,854","38,29","32,323","31,948","30,938","28,664","28,273","32,362","33,214","32,833","33,261","29,906","35,783","35,628","35,122","35,378","31,984","31,47968","32,095881","35,156989","37,867647","36,964485"
|
||||
INTL.33-12-TUR-BKWH.A, Turkey,"11,159","12,308","13,81","11,13","13,19","11,822","11,637","18,314","28,447","17,61","22,917","22,456","26,302","33,611","30,28","35,186","40,07","39,41784","41,80671","34,33","30,57","23,77","33,346","34,977","45,623","39,165","43,802","35,492","32,937","35,598","51,423001","51,154999","56,668998","58,225","39,750001","65,856","66,685883","57,823851","59,490211","88,2094218","78,094369","55,1755392"
|
||||
INTL.33-12-GBR-BKWH.A, United Kingdom,"3,921","4,369","4,543","4,548","3,992","4,08","4,767","4,13","4,915","4,732","5,119","4,534","5,329","4,237","5,043","4,79","3,359","4,127","5,117","5,336","5,085","4,055","4,78787","3,22767","4,844","4,92149","4,59315","5,0773","5,14119","5,22792","3,59138","5,69175","5,30965","4,70147","5,8878","6,29727","5,370412217","5,88187","5,44327","5,84628","6,75391","5,0149"
|
||||
, Eurasia,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
INTL.33-12-MDA-BKWH.A, Moldova,--,--,--,--,--,--,--,--,--,--,--,--,"0,255","0,371","0,275","0,321","0,362","0,378","0,387","0,363","0,392","0,359","0,348","0,358","0,35","0,359","0,365","0,354","0,385","0,354","0,403","0,348","0,266","0,311","0,317","0,265","0,228","0,282","0,27324","0,29799","0,276","0,316"
|
||||
INTL.33-12-UKR-BKWH.A, Ukraine,--,--,--,--,--,--,--,--,--,--,--,--,"7,725","10,929","11,997","9,853","8,546","9,757","15,756","14,177","11,161","11,912","9,531","9,146","11,635","12,239","12,757","10,042","11,397","11,817","13,02","10,837","10,374","13,663","8,393","5,343","7,594","8,856","10,32372","6,5083","7,5638","10,3326"
|
||||
|
Can't render this file because it has a wrong number of fields in line 3.
|
@ -1,34 +1,34 @@
|
||||
Country/area,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018
|
||||
Albania,,,,,,,,,,,,,,,,,,,
|
||||
Austria,,,,,,,,,,,,,,,,,,,
|
||||
Belgium,,,,,,,,,,31.5,196.5,196.5,381,707.7,707.7,712,712.2,877.2,1185.9
|
||||
Bosnia Herzg,,,,,,,,,,,,,,,,,,,
|
||||
Bulgaria,,,,,,,,,,,,,,,,,,,
|
||||
Croatia,,,,,,,,,,,,,,,,,,,
|
||||
Czechia,,,,,,,,,,,,,,,,,,,
|
||||
Denmark,50,50,214,423.4,423.4,423.4,423.4,423.4,423.4,660.9,867.9,871.5,921.9,1271.1,1271.1,1271.1,1271.1,1263.8,1700.8
|
||||
Estonia,,,,,,,,,,,,,,,,,,,
|
||||
Finland,,,,,,,,,24,24,26.3,26.3,26.3,26.3,26.3,32,32,72.7,72.7
|
||||
France,,,,,,,,,,,,,,,,,,2,2
|
||||
Germany,,,,,,,,,,35,80,188,268,508,994,3283,4132,5406,6396
|
||||
Greece,,,,,,,,,,,,,,,,,,,
|
||||
Hungary,,,,,,,,,,,,,,,,,,,
|
||||
Ireland,,,,,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2
|
||||
Italy,,,,,,,,,,,,,,,,,,,
|
||||
Latvia,,,,,,,,,,,,,,,,,,,
|
||||
Lithuania,,,,,,,,,,,,,,,,,,,
|
||||
Luxembourg,,,,,,,,,,,,,,,,,,,
|
||||
Montenegro,,,,,,,,,,,,,,,,,,,
|
||||
Netherlands,,,,,,,108,108,228,228,228,228,228,228,228,357,957,957,957
|
||||
North Macedonia,,,,,,,,,,,,,,,,,,,
|
||||
Norway,,,,,,,,,,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3
|
||||
Poland,,,,,,,,,,,,,,,,,,,
|
||||
Portugal,,,,,,,,,,,,1.9,2,2,2,2,,,
|
||||
Romania,,,,,,,,,,,,,,,,,,,
|
||||
Serbia,,,,,,,,,,,,,,,,,,,
|
||||
Slovakia,,,,,,,,,,,,,,,,,,,
|
||||
Slovenia,,,,,,,,,,,,,,,,,,,
|
||||
Spain,,,,,,,,,,,,,,5,5,5,5,5,5
|
||||
Sweden,13,22,22,22,22,22,22,131,133,163,163,163,163,212,213,213,203,203,203
|
||||
Switzerland,,,,,,,,,,,,,,,,,,,
|
||||
UK,3.8,3.8,3.8,63.8,123.8,213.8,303.8,393.8,596.2,951.2,1341.5,1838.3,2995.5,3696,4501.3,5093.4,5293.4,6987.9,8216.5
|
||||
Country/area,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022
|
||||
Albania,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Austria,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Belgium,,,,,,,,,,31.5,196.5,196.5,381.0,707.7,707.7,712.0,712.2,877.2,1185.9,1555.5,2261.8,2261.8,2261.8
|
||||
Bosnia Herzg,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Bulgaria,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Croatia,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Czechia,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Denmark,49.95,49.95,213.95,423.35,423.35,423.35,423.35,423.35,423.35,660.85,867.85,871.45,921.85,1271.05,1271.05,1271.05,1271.05,1263.8,1700.8,1700.8,1700.8,2305.6,2305.6
|
||||
Estonia,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Finland,,,,,,,,,24.0,24.0,26.3,26.3,26.3,26.3,26.3,32.0,32.0,72.7,72.7,73.0,73.0,73.0,73.0
|
||||
France,,,,,,,,,,,,,,,,,,2.0,2.0,2.0,2.0,2.0,482.0
|
||||
Germany,,,,,,,,,,35.0,80.0,188.0,268.0,508.0,994.0,3283.0,4132.0,5406.0,6393.0,7555.0,7787.0,7787.0,8129.0
|
||||
Greece,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Hungary,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Ireland,,,,,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2
|
||||
Italy,,,,,,,,,,,,,,,,,,,,,,,30.0
|
||||
Latvia,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Lithuania,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Luxembourg,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Montenegro,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Netherlands,,,,,,,108.0,108.0,228.0,228.0,228.0,228.0,228.0,228.0,228.0,357.0,957.0,957.0,957.0,957.0,2459.5,2459.5,2571.0
|
||||
North Macedonia,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Norway,,,,,,,,,,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,6.3,66.3
|
||||
Poland,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Portugal,,,,,,,,,,,,1.86,2.0,2.0,2.0,2.0,,,,,25.0,25.0,25.0
|
||||
Romania,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Serbia,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Slovakia,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Slovenia,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Spain,,,,,,,,,,,,,,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0
|
||||
Sweden,13.0,22.0,22.0,22.0,22.0,22.0,22.0,131.0,133.0,163.0,163.0,163.0,163.0,212.0,213.0,213.0,203.0,203.0,203.0,203.0,203.0,193.0,193.0
|
||||
Switzerland,,,,,,,,,,,,,,,,,,,,,,,
|
||||
UK,4.0,4.0,4.0,64.0,124.0,214.0,304.0,394.0,596.2,951.0,1341.0,1838.0,2995.0,3696.0,4501.0,5093.0,5293.0,6988.0,8181.0,9888.0,10383.0,11255.0,13928.0
|
||||
|
|
@ -1,34 +1,34 @@
|
||||
Country/area,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018
|
||||
Albania,,,,,,,,,,,,,,,,,,,
|
||||
Austria,50,67,109,322,581,825.2,968.3,991.2,992,1001,1015.8,1106,1337.2,1674.5,2110.3,2488.7,2730,2886.7,3132.7
|
||||
Belgium,14,26,31,67,96,167,212,276,324,576.5,715.5,872.5,989,1072.3,1236.3,1464,1657.8,1919.3,2074.8
|
||||
Bosnia Herzg,,,,,,,,,,,,0.3,0.3,0.3,0.3,0.3,0.3,0.3,50.9
|
||||
Bulgaria,,,,,1,8,27,30,114,333,488,541,677,683,699,699,699,698.4,698.9
|
||||
Croatia,,,,,6,6,17,17,17,70,79,130,180,254,339,418,483,576.1,586.3
|
||||
Czechia,2,,6.4,10.6,16.5,22,43.5,113.8,150,193,213,213,258,262,278,281,282,308.2,316.2
|
||||
Denmark,2340.1,2447.2,2680.6,2696.6,2700.4,2704.5,2712.3,2700.9,2739.5,2821.2,2934,3080.5,3240.1,3547.9,3615.4,3805.9,3974.5,4225.8,4419.8
|
||||
Estonia,,,1,3,7,31,31,50,77,104,108,180,266,248,275,300,310,311.8,310
|
||||
Finland,38,39,43,52,82,82,86,110,119,123,170.7,172.7,230.7,420.7,600.7,973,1533,1971.3,1968.3
|
||||
France,38,66,138,218,358,690,1412,2223,3403,4582,5912,6758,7607.5,8156,9201.4,10298.2,11566.6,13497.4,14898.1
|
||||
Germany,6095,8754,12001,14381,16419,18248,20474,22116,22794,25697,26823,28524,30711,32969,37620,41297,45303,50174,52447
|
||||
Greece,226,270,287,371,470,491,749,846,1022,1171,1298,1640,1753,1809,1978,2091,2370,2624,2877.5
|
||||
Hungary,,1,1,3,3,17,33,61,134,203,293,331,325,329,329,329,329,329,329
|
||||
Ireland,116.5,122.9,134.8,210.3,311.2,468.1,651.3,715.3,917.1,1226.1,1365.2,1559.4,1679.2,1983,2258.1,2426,2760.8,3292.8,3650.9
|
||||
Italy,363,664,780,874,1127,1635,1902,2702,3525,4879,5794,6918,8102,8542,8683,9137,9384,9736.6,10230.2
|
||||
Latvia,2,2,22,26,26,26,26,26,28,29,30,36,59,65.9,68.9,68.2,69.9,77.1,78.2
|
||||
Lithuania,,,,,1,1,31,47,54,98,133,202,275,279,288,436,509,518,533
|
||||
Luxembourg,14,13.9,13.9,20.5,34.9,34.9,34.9,34.9,42.9,42.9,43.7,44.5,58.3,58.3,58.3,63.8,119.7,119.7,122.9
|
||||
Montenegro,,,,,,,,,,,,,,,,,,72,118
|
||||
Netherlands,447,486,672,905,1075,1224,1453,1641,1921,1994,2009,2088,2205,2485,2637,3034,3300,3245,3436
|
||||
North Macedonia,,,,,,,,,,,,,,,37,37,37,37,37
|
||||
Norway,13,13,97,97,152,265,284,348,395,420.7,422.7,509.7,702.7,815.7,856.7,864.7,880.7,1204.7,1708
|
||||
Poland,4,19,32,35,40,121,172,306,526,709,1108,1800,2564,3429,3836,4886,5747,5759.4,5766.1
|
||||
Portugal,83,125,190,268,553,1064,1681,2201,2857,3326,3796,4254.4,4409.6,4607.9,4854.6,4934.8,5124.1,5124.1,5172.4
|
||||
Romania,,,,,,1,1,3,5,15,389,988,1822,2773,3244,3130,3025,3029.8,3032.3
|
||||
Serbia,,,,,,,,,,,,,0.5,0.5,0.5,10.4,17,25,25
|
||||
Slovakia,,,,3,3,5,5,5,5,3,3,3,3,5,3,3,3,4,3
|
||||
Slovenia,,,,,,,,,,,,,,4,4,5,5,5,5.2
|
||||
Spain,2206,3397,4891,5945,8317,9918,11722,14820,16555,19176,20693,21529,22789,22953,22920,22938,22985,23119.5,23400.1
|
||||
Sweden,196,273,335,395,453,500,563,692,956,1312,1854,2601,3443,3982,4875,5606,6232,6408,7097
|
||||
Switzerland,3,5,5,5,9,12,12,12,14,18,42,46,49,60,60,60,75,75,75
|
||||
UK,408.2,489.2,530.2,678.2,809.2,1351.2,1651.2,2083.2,2849.8,3470.8,4079.8,4758,6035,7586.3,8572.7,9212.2,10832.3,12596.9,13553.9
|
||||
Country/area,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022
|
||||
Albania,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Austria,50.0,67.0,109.0,322.0,581.0,825.22,968.27,991.16,991.97,1000.99,1015.83,1105.97,1337.15,1674.54,2110.28,2488.73,2730.0,2886.7,3132.71,3224.12,3225.98,3407.81,3735.81
|
||||
Belgium,14.0,26.0,31.0,67.0,96.0,167.0,212.0,276.0,324.0,576.5,715.5,872.5,985.9,1061.3,1225.0,1469.3,1621.6,1902.2,2119.0,2308.0,2410.9,2686.6,2989.6
|
||||
Bosnia Herzg,,,,,,,,,,,,0.3,0.3,0.3,0.3,0.3,0.3,0.3,51.0,87.0,87.0,135.0,135.0
|
||||
Bulgaria,,,,,1.0,8.0,27.0,30.0,114.0,333.0,488.0,541.0,677.0,683.0,699.0,699.0,699.0,698.39,698.92,703.12,702.8,704.38,704.38
|
||||
Croatia,,,,,6.0,6.0,17.0,17.0,17.0,70.0,79.0,130.0,180.0,254.0,339.0,418.0,483.0,576.1,586.3,646.3,801.3,986.9,1042.9
|
||||
Czechia,2.0,,6.4,10.6,16.5,22.0,43.5,113.8,150.0,193.0,213.0,213.0,258.0,262.0,278.0,281.0,282.0,308.21,316.2,339.41,339.42,339.41,339.41
|
||||
Denmark,2340.07,2447.2,2680.58,2696.57,2700.36,2704.49,2712.35,2700.86,2739.52,2821.24,2933.98,3080.53,3240.09,3547.87,3615.35,3805.92,3974.09,4225.15,4421.86,4409.74,4566.23,4715.24,4782.24
|
||||
Estonia,,,1.0,3.0,7.0,31.0,31.0,50.0,77.0,104.0,108.0,180.0,266.0,248.0,275.0,300.0,310.0,311.8,310.0,316.0,317.0,315.0,315.0
|
||||
Finland,38.0,39.0,43.0,52.0,82.0,82.0,86.0,110.0,119.0,123.0,170.7,172.7,230.7,420.7,600.7,973.0,1533.0,1971.3,1968.3,2211.0,2513.0,3184.0,5541.0
|
||||
France,38.0,66.0,138.0,218.0,358.0,690.0,1412.0,2223.0,3403.0,4582.0,5912.0,6758.02,7607.5,8155.96,9201.42,10298.18,11566.56,13497.35,14898.14,16424.85,17512.0,18737.98,20637.98
|
||||
Germany,6095.0,8754.0,12001.0,14381.0,16419.0,18248.0,20474.0,22116.0,22794.0,25697.0,26823.0,28524.0,30711.0,32969.0,37620.0,41297.0,45303.0,50174.0,52328.0,53187.0,54414.0,56046.0,58165.0
|
||||
Greece,226.0,270.0,287.0,371.0,470.0,491.0,749.0,846.0,1022.0,1171.0,1298.0,1640.0,1753.0,1809.0,1978.0,2091.0,2370.0,2624.0,2877.5,3589.0,4119.25,4649.13,4879.13
|
||||
Hungary,,1.0,1.0,3.0,3.0,17.0,33.0,61.0,134.0,203.0,293.0,331.0,325.0,329.0,329.0,329.0,329.0,329.0,329.0,323.0,323.0,324.0,324.0
|
||||
Ireland,116.5,122.9,134.8,210.3,311.2,468.1,651.3,715.3,917.1,1226.1,1365.2,1559.4,1679.15,1898.1,2258.05,2425.95,2776.45,3293.95,3648.65,4101.25,4281.5,4313.84,4593.84
|
||||
Italy,363.0,664.0,780.0,874.0,1127.0,1635.0,1902.0,2702.0,3525.0,4879.0,5794.0,6918.0,8102.0,8542.0,8683.0,9137.0,9384.0,9736.58,10230.25,10679.46,10870.62,11253.73,11749.73
|
||||
Latvia,2.0,2.0,22.0,26.0,26.0,26.0,26.0,26.0,28.0,29.0,30.0,36.0,59.0,65.89,68.92,68.17,69.91,77.11,78.17,78.07,78.07,77.13,136.13
|
||||
Lithuania,,,,,1.0,1.0,31.0,47.0,54.0,98.0,133.0,202.0,275.0,279.0,288.0,436.0,509.0,518.0,533.0,534.0,540.0,671.0,814.0
|
||||
Luxembourg,14.0,13.9,13.9,20.5,34.9,34.9,34.9,34.9,42.92,42.93,43.73,44.53,58.33,58.33,58.34,63.79,119.69,119.69,122.89,135.79,152.74,136.44,165.44
|
||||
Montenegro,,,,,,,,,,,,,,,,,,72.0,72.0,118.0,118.0,118.0,118.0
|
||||
Netherlands,447.0,486.0,672.0,905.0,1075.0,1224.0,1453.0,1641.0,1921.0,1994.0,2009.0,2088.0,2205.0,2485.0,2637.0,3033.84,3300.12,3245.0,3436.11,3527.16,4188.38,5309.87,6176.0
|
||||
North Macedonia,,,,,,,,,,,,,,,37.0,37.0,37.0,37.0,37.0,37.0,37.0,37.0,37.0
|
||||
Norway,13.0,13.0,97.0,97.0,152.0,265.0,284.0,348.0,395.0,420.7,422.7,509.7,702.7,815.7,856.7,864.7,880.7,1204.7,1707.7,2911.7,4027.7,5042.7,5067.7
|
||||
Poland,4.0,19.0,32.0,35.0,40.0,121.0,172.0,306.0,526.0,709.0,1108.0,1800.0,2564.0,3429.0,3836.0,4886.0,5747.0,5759.36,5766.08,5837.76,6298.25,6967.34,7987.34
|
||||
Portugal,83.0,125.0,190.0,268.0,553.0,1064.0,1681.0,2201.0,2857.0,3326.0,3796.0,4254.35,4409.55,4607.95,4854.56,4934.84,5124.1,5124.1,5172.36,5222.75,5097.26,5402.33,5430.33
|
||||
Romania,,,,,,1.0,1.0,3.0,5.0,15.0,389.0,988.0,1822.0,2773.0,3244.0,3130.0,3025.0,3029.8,3032.26,3037.52,3012.53,3014.96,3014.96
|
||||
Serbia,,,,,,,,,,,,,0.5,0.5,0.5,10.4,17.0,25.0,227.0,398.0,398.0,398.0,398.0
|
||||
Slovakia,,,,3.0,3.0,5.0,5.0,5.0,5.0,3.0,3.0,3.0,3.0,5.0,3.0,3.0,3.0,4.0,3.0,4.0,4.0,4.0,4.0
|
||||
Slovenia,,,,,,,,,,,,,2.0,2.0,3.0,3.0,3.0,3.3,3.3,3.3,3.3,3.33,3.33
|
||||
Spain,2206.0,3397.0,4891.0,5945.0,8317.0,9918.0,11722.0,14820.0,16555.0,19176.0,20693.0,21529.0,22789.0,22953.0,22920.0,22938.0,22985.0,23119.48,23400.06,25585.08,26814.19,27902.65,29302.84
|
||||
Sweden,196.0,273.0,335.0,395.0,453.0,500.0,563.0,692.0,956.0,1312.0,1854.0,2601.0,3443.0,3982.0,4875.0,5606.0,6232.0,6408.0,7097.0,8478.0,9773.0,11923.0,14364.0
|
||||
Switzerland,3.0,5.0,5.0,5.0,9.0,12.0,12.0,12.0,14.0,18.0,42.0,46.0,49.0,60.0,60.0,60.0,75.0,75.0,75.0,75.0,87.0,87.0,87.0
|
||||
UK,431.0,490.0,531.0,678.0,809.0,1351.0,1651.0,2083.0,2849.8,3468.0,4080.0,4758.0,6035.0,7586.0,8573.0,9212.0,10833.0,12597.0,13425.0,13999.0,14075.0,14492.0,14832.0
|
||||
|
|
@ -1,34 +1,34 @@
|
||||
Country/area,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018
|
||||
Albania,,0.1,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.3,0.4,0.6,0.7,0.8,0.9,1.1,1,1,1
|
||||
Austria,5,7,9,23,27,21,22.4,24.2,30.1,48.9,88.8,174.1,337.5,626,785.2,937.1,1096,1269,1437.6
|
||||
Belgium,,,1,1,1,2,2,20,62,386,1007,1979,2647,2902,3015.2,3131.7,3327,3616.2,3986.5
|
||||
Bosnia Herzg,,,,0.1,0.2,0.3,0.3,0.3,0.3,0.3,0.3,0.3,0.3,1.3,7.2,8.2,14.1,16,18.2
|
||||
Bulgaria,,,,,,,,0,0.1,2,25,154,1013,1020,1026,1029,1028,1035.6,1032.7
|
||||
Croatia,,,,,,,,,,0.3,0.3,0.3,4,19,33,47.8,55.8,60,67.7
|
||||
Czechia,0.1,0.1,0.2,0.3,0.4,0.6,0.8,4,39.5,464.6,1727,1913,2022,2063.5,2067.4,2074.9,2067.9,2069.5,2075.1
|
||||
Denmark,1,1,2,2,2,3,3,3,3,5,7,17,402,571,607,782.1,851,906.4,998
|
||||
Estonia,,,,,,,,,,0.1,0.1,0.2,0.4,1.5,3.3,6.5,10,15,31.9
|
||||
Finland,2,3,3,3,4,4,5,5,6,6,7,7,8,9,11,17,39,82,140
|
||||
France,7,7,8,9,11,13,15,26,80,277,1044,3003.6,4358.8,5277.3,6034.4,7137.5,7702.1,8610.4,9617
|
||||
Germany,114,195,260,435,1105,2056,2899,4170,6120,10564,18004,25914,34075,36708,37898,39222,40677,42291,45179
|
||||
Greece,,1,1,1,1,1,5,9,12,46,202,612,1536,2579,2596,2604,2604,2605.5,2651.6
|
||||
Hungary,,,,,,,,0.4,1,1,2,4,12,35,89,172,235,344,726
|
||||
Ireland,,,,,,,,,,0.6,0.7,0.8,0.9,1,1.6,2.4,5.9,15.7,24.2
|
||||
Italy,19,20,22,26,31,34,45,110,483,1264,3592,13131,16785,18185,18594,18901,19283,19682.3,20107.6
|
||||
Latvia,,,,,,,,,,,,,0.2,0.2,0.2,0.2,0.7,0.7,2
|
||||
Lithuania,,,,,,,,,0.1,0.1,0.1,0.3,7,68,69,69,70,73.8,82
|
||||
Luxembourg,,0.2,1.6,14.2,23.6,23.6,23.7,23.9,24.6,26.4,29.5,40.7,74.7,95,109.9,116.3,121.9,128.1,130.6
|
||||
Montenegro,,,,,,,0,0.2,0.4,0.4,0.6,0.8,0.9,1.1,2.1,2.7,3.1,3.4,3.4
|
||||
Netherlands,13,21,26,46,50,51,53,54,59,69,90,149,369,746,1048,1515,2049,2903,4522
|
||||
North Macedonia,,,,,,,,,,,0,2,4,7,15,17,16.7,16.7,20.6
|
||||
Norway,6,6,6,7,7,7,8,8,8.3,8.7,9.1,9.5,10,11,13,15,26.7,44.9,68.4
|
||||
Poland,,,,,,,,,,,,1.1,1.3,2.4,27.2,107.8,187.2,287.1,562
|
||||
Portugal,1,1,1,2,2,2,3,24,59,115,134,172,238,296,415,447,512.8,579.2,667.4
|
||||
Romania,,,,,,,,,0.1,0.1,0.1,1,41,761,1293,1326,1372,1374.1,1385.8
|
||||
Serbia,,,,,,0.1,0.2,0.4,0.9,1.2,1.3,1.5,3.1,4.7,6,9,11,10,10
|
||||
Slovakia,,,,,,,,,,,19,496,513,533,533,533,533,528,472
|
||||
Slovenia,,,0,0,0,0,0.2,0.6,1,4,12,57,142,187,223,238,233,246.8,221.3
|
||||
Spain,10,13,17,22,33,52,130,494,3384,3423,3873,4283,4569,4690,4697,4704,4713,4723,4763.5
|
||||
Sweden,3,3,3,4,4,4,5,6,8,9,11,12,24,43,60,104,153,402,492
|
||||
Switzerland,16,18,20,22,24,28,30,37,49,79,125,223,437,756,1061,1394,1664,1906,2171
|
||||
UK,2,3,4,6,8,11,14,18,23,27,95,1000,1753,2937,5528,9601.2,11930.5,12781.8,13118.3
|
||||
Country/area,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022
|
||||
Albania,,0.1,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.3,0.4,0.56,0.68,0.76,0.87,1.05,1.0,1.0,1.0,14.0,21.0,23.0,28.6
|
||||
Austria,5.0,7.0,9.0,23.0,27.0,18.49,19.61,21.42,27.0,45.56,85.27,169.88,333.09,620.78,779.76,931.56,1089.53,1262.01,1447.94,1694.4,2034.74,2773.91,3538.91
|
||||
Belgium,,,1.0,1.0,1.0,2.0,2.0,20.0,62.0,386.0,1006.6,1978.6,2646.6,2901.6,3015.0,3131.6,3328.8,3620.6,4000.0,4636.6,5572.8,6012.4,6898.4
|
||||
Bosnia Herzg,,,,0.1,0.2,0.3,0.3,0.3,0.3,0.3,0.3,0.3,0.35,1.34,7.17,8.17,14.12,16.0,18.15,22.35,34.89,56.51,107.47
|
||||
Bulgaria,,,,,,,,0.03,0.1,2.0,25.0,154.0,921.99,1038.54,1028.92,1027.89,1029.89,1030.7,1033.06,1044.39,1100.21,1274.71,1948.36
|
||||
Croatia,,,,,,,,,,0.3,0.3,0.3,4.0,19.0,33.0,47.8,55.8,60.0,67.7,84.8,108.5,138.3,182.3
|
||||
Czechia,0.1,0.1,0.2,0.3,0.4,0.59,0.84,3.96,39.5,464.6,1727.0,1913.0,2022.0,2063.5,2067.4,2074.9,2067.9,2075.44,2081.05,2110.67,2171.96,2246.09,2627.09
|
||||
Denmark,1.0,1.0,2.0,2.0,2.0,3.0,3.0,3.0,3.0,5.0,7.0,17.0,402.0,571.0,607.0,782.11,850.95,906.35,998.0,1080.0,1304.29,1704.04,3122.04
|
||||
Estonia,,,,,,,,,,0.1,0.1,0.2,0.38,1.5,3.34,6.5,10.0,15.0,31.9,120.6,207.67,394.77,534.77
|
||||
Finland,2.0,3.0,3.0,3.0,4.0,4.0,5.0,5.0,6.0,6.0,7.0,7.0,8.0,9.0,11.0,17.0,39.0,82.0,140.0,222.0,318.0,425.0,590.6
|
||||
France,7.0,7.0,8.0,9.0,11.0,13.0,15.0,26.0,80.0,277.0,1044.0,3003.57,4358.75,5277.29,6034.42,7137.52,7702.08,8610.44,9638.88,10738.39,11812.2,14436.97,17036.97
|
||||
Germany,114.0,195.0,260.0,435.0,1105.0,2056.0,2899.0,4170.0,6120.0,10564.0,18004.0,25914.0,34075.0,36708.0,37898.0,39222.0,40677.0,42291.0,45156.0,48912.0,53669.0,59371.0,66662.0
|
||||
Greece,,1.0,1.0,1.0,1.0,1.0,5.0,9.0,12.0,46.0,202.0,612.0,1536.0,2579.0,2596.0,2604.0,2604.0,2605.53,2651.57,2833.79,3287.72,4277.42,5557.42
|
||||
Hungary,,,,,,,,0.4,1.0,1.0,2.0,4.0,12.0,35.0,89.0,172.0,235.0,344.0,728.0,1400.0,2131.0,2968.0,2988.0
|
||||
Ireland,,,,,,,,,,,,,,,,,,,,,,,
|
||||
Italy,19.0,20.0,22.0,26.0,31.0,34.0,45.0,110.0,483.0,1264.0,3592.0,13131.0,16785.0,18185.0,18594.0,18901.0,19283.0,19682.29,20107.59,20865.28,21650.04,22594.26,25076.56
|
||||
Latvia,,,,,,,,,,,,,,,,,0.69,0.69,1.96,3.3,5.1,7.16,56.16
|
||||
Lithuania,,,,,,,,,0.1,0.1,0.1,0.3,7.0,68.0,69.0,69.0,70.0,70.08,72.0,73.0,80.0,84.0,397.0
|
||||
Luxembourg,,0.16,1.59,14.17,23.56,23.58,23.7,23.93,24.56,26.36,29.45,40.67,74.65,95.02,109.93,116.27,121.9,128.1,130.62,159.74,186.64,277.16,319.16
|
||||
Montenegro,,,,,,,,,,,,,,,,,,,,,2.57,2.57,22.2
|
||||
Netherlands,13.0,21.0,26.0,46.0,50.0,51.0,53.0,54.0,59.0,69.0,90.0,149.0,287.0,650.0,1007.0,1526.26,2135.02,2910.89,4608.0,7226.0,11108.43,14910.69,18848.69
|
||||
North Macedonia,,,,,,,,,,,,2.0,4.0,7.0,15.0,17.0,16.7,16.7,16.7,16.71,84.93,84.93,84.93
|
||||
Norway,6.0,6.0,6.0,7.0,7.0,7.0,8.0,8.0,8.3,8.7,9.1,9.5,10.0,11.0,13.0,15.0,26.7,44.9,53.11,102.53,141.53,186.53,302.53
|
||||
Poland,,,,,,,,,,,,1.11,1.3,2.39,27.15,107.78,187.25,287.09,561.98,1539.26,3954.96,7415.52,11166.52
|
||||
Portugal,1.0,1.0,1.0,2.0,2.0,2.0,3.0,24.0,59.0,115.0,134.0,169.6,235.6,293.6,412.6,441.75,493.05,539.42,617.85,832.74,1010.07,1474.78,2364.78
|
||||
Romania,,,,,,,,,0.1,0.1,0.1,1.0,41.0,761.0,1293.0,1326.0,1372.0,1374.13,1385.82,1397.71,1382.54,1393.92,1413.92
|
||||
Serbia,,,,,,0.1,0.2,0.4,0.9,1.2,1.3,1.5,3.1,4.7,6.0,9.0,11.0,10.0,11.0,11.0,11.5,11.94,11.94
|
||||
Slovakia,,,,,,,,,,,19.0,496.0,513.0,533.0,533.0,533.0,533.0,528.0,472.0,590.0,535.0,537.0,537.0
|
||||
Slovenia,1.0,1.0,,,,0.05,0.19,0.59,1.0,4.0,12.0,57.0,142.0,187.0,223.0,238.0,233.0,246.8,246.8,277.88,369.78,461.16,632.16
|
||||
Spain,1.0,3.0,6.0,10.0,19.0,37.0,113.0,476.0,3365.0,3403.0,3851.0,4260.0,4545.0,4665.0,4672.0,4677.0,4687.0,4696.0,4730.7,8772.02,10100.42,13678.4,18176.73
|
||||
Sweden,3.0,3.0,3.0,4.0,4.0,4.0,5.0,6.0,8.0,9.0,11.0,12.0,24.0,43.0,60.0,104.0,153.0,231.0,411.0,698.0,1090.0,1587.0,2587.0
|
||||
Switzerland,16.0,18.0,20.0,22.0,24.0,28.0,30.0,37.0,49.0,79.0,125.0,223.0,437.0,756.0,1061.0,1394.0,1664.0,1906.0,2173.0,2498.0,2973.0,3655.0,4339.92
|
||||
UK,2.0,3.0,4.0,6.0,8.0,11.0,14.0,18.0,23.0,27.0,95.0,1000.0,1753.0,2937.0,5528.0,9601.0,11914.0,12760.0,13059.0,13345.0,13579.0,13965.0,14660.0
|
||||
|
|
@ -1,4 +1,5 @@
|
||||
,Unit,Values,Description
|
||||
focus_weights,,,Optionally specify the focus weights for the clustering of countries. For instance: `DE: 0.8` will distribute 80% of all nodes to Germany and 20% to the rest of the countries.
|
||||
simplify_network,,,
|
||||
-- to_substations,bool,"{'true','false'}","Aggregates all nodes without power injection (positive or negative, i.e. demand or generation) to electrically closest ones"
|
||||
-- algorithm,str,"One of {‘kmeans’, ‘hac’, ‘modularity‘}",
|
||||
|
|
@ -5,6 +5,7 @@ retrieve_databundle,bool,"{true, false}","Switch to retrieve databundle from zen
|
||||
retrieve_sector_databundle,bool,"{true, false}","Switch to retrieve sector databundle from zenodo via the rule :mod:`retrieve_sector_databundle` or whether to keep a custom databundle located in the corresponding folder."
|
||||
retrieve_cost_data,bool,"{true, false}","Switch to retrieve technology cost data from `technology-data repository <https://github.com/PyPSA/technology-data>`_."
|
||||
build_cutout,bool,"{true, false}","Switch to enable the building of cutouts via the rule :mod:`build_cutout`."
|
||||
retrieve_irena,bool,"{true, false}",Switch to enable the retrieval of ``existing_capacities`` from IRENASTAT with :mod:`retrieve_irena`.
|
||||
retrieve_cutout,bool,"{true, false}","Switch to enable the retrieval of cutouts from zenodo with :mod:`retrieve_cutout`."
|
||||
build_natura_raster,bool,"{true, false}","Switch to enable the creation of the raster ``natura.tiff`` via the rule :mod:`build_natura_raster`."
|
||||
retrieve_natura_raster,bool,"{true, false}","Switch to enable the retrieval of ``natura.tiff`` from zenodo with :mod:`retrieve_natura_raster`."
|
||||
|
|
@ -5,7 +5,7 @@
|
||||
"naturalearth/*",,,,,http://www.naturalearthdata.com/about/terms-of-use/
|
||||
"NUTS_2013 _60M_SH/*","x","x",,"x",https://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units
|
||||
"cantons.csv","x",,"x",,https://en.wikipedia.org/wiki/Data_codes_for_Switzerland
|
||||
"EIA_hydro_generation _2000_2014.csv","x",,,,https://www.eia.gov/about/copyrights_reuse.php
|
||||
"eia_hydro_annual_generation.csv","x",,,,https://www.eia.gov/about/copyrights_reuse.php
|
||||
"GEBCO_2014_2D.nc","x",,,,https://www.gebco.net/data_and_products/gridded_bathymetry_data/documents/gebco_2014_historic.pdf
|
||||
"hydro_capacities.csv","x",,,,
|
||||
"je-e-21.03.02.xls","x","x",,,https://www.bfs.admin.ch/bfs/en/home/fso/swiss-federal-statistical-office/terms-of-use.html
|
||||
|
|
@ -5,6 +5,7 @@ s_nom_max,MW,"float","Global upper limit for the maximum capacity of each extend
|
||||
max_extension,MW,"float","Upper limit for the extended 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."
|
||||
reconnect_crimea,--,"true or false","Whether to reconnect Crimea to the Ukrainian grid"
|
||||
dynamic_line_rating,,,
|
||||
-- activate,bool,"true or false","Whether to take dynamic line rating into account"
|
||||
-- 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 must be ERA5.","Specifies the directory where the relevant weather data ist stored."
|
||||
|
|
@ -12,5 +12,4 @@ ship_threshold,--,float,"Ship density threshold from which areas are excluded."
|
||||
max_depth,m,float,"Maximum sea water depth at which wind turbines can be build. Maritime areas with deeper waters are excluded in the process of calculating the AC-connected offshore wind potential."
|
||||
min_shore_distance,m,float,"Minimum distance to the shore below which wind turbines cannot be build. Such areas close to the shore are excluded in the process of calculating the AC-connected offshore wind potential."
|
||||
max_shore_distance,m,float,"Maximum distance to the shore above which wind turbines cannot be build. Such areas close to the shore are excluded in the process of calculating the AC-connected offshore wind potential."
|
||||
potential,--,"One of {'simple', 'conservative'}","Method to compute the maximal installable potential for a node; confer :ref:`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."
|
||||
|
|
@ -12,5 +12,4 @@ ship_threshold,--,float,"Ship density threshold from which areas are excluded."
|
||||
max_depth,m,float,"Maximum sea water depth at which wind turbines can be build. Maritime areas with deeper waters are excluded in the process of calculating the AC-connected offshore wind potential."
|
||||
min_shore_distance,m,float,"Minimum distance to the shore below which wind turbines cannot be build."
|
||||
max_shore_distance,m,float,"Maximum distance to the shore above which wind turbines cannot be build."
|
||||
potential,--,"One of {'simple', 'conservative'}","Method to compute the maximal installable potential for a node; confer :ref:`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."
|
||||
|
|
@ -9,7 +9,6 @@ corine,,,
|
||||
-- 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 <http://www.eea.europa.eu/data-and-maps/data/corine-land-cover-2006-raster-1/corine-land-cover-classes-and/clc_legend.csv/at_download/file>`_","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 <https://en.wikipedia.org/wiki/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 :ref:`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."
|
||||
correction_factor,--,float,"Correction factor for capacity factor time series."
|
||||
excluder_resolution,m,float,"Resolution on which to perform geographical elibility analysis."
|
||||
|
|
@ -71,7 +71,6 @@ solar_thermal,--,"{true, false}",Add option for using solar thermal to generate
|
||||
solar_cf_correction,--,float,The correction factor for the value provided by the solar thermal profile calculations
|
||||
marginal_cost_storage,currency/MWh ,float,The marginal cost of discharging batteries in distributed grids
|
||||
methanation,--,"{true, false}",Add option for transforming hydrogen and CO2 into methane using methanation.
|
||||
helmeth,--,"{true, false}",Add option for transforming power into gas using HELMETH (Integrated High-Temperature ELectrolysis and METHanation for Effective Power to Gas Conversion)
|
||||
coal_cc,--,"{true, false}",Add option for coal CHPs with carbon capture
|
||||
dac,--,"{true, false}",Add option for Direct Air Capture (DAC)
|
||||
co2_vent,--,"{true, false}",Add option for vent out CO2 from storages to the atmosphere.
|
||||
@ -79,6 +78,7 @@ allam_cycle,--,"{true, false}",Add option to include `Allam cycle gas power plan
|
||||
hydrogen_fuel_cell,--,"{true, false}",Add option to include hydrogen fuel cell for re-electrification. Assuming OCGT technology costs
|
||||
hydrogen_turbine,--,"{true, false}",Add option to include hydrogen turbine for re-electrification. Assuming OCGT technology costs
|
||||
SMR,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR)
|
||||
SMR CC,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR) and Carbon Capture (CC)
|
||||
regional_co2 _sequestration_potential,,,
|
||||
-- enable,--,"{true, false}",Add option for regionally-resolved geological carbon dioxide sequestration potentials based on `CO2StoP <https://setis.ec.europa.eu/european-co2-storage-database_en>`_.
|
||||
-- attribute,--,string,Name of the attribute for the sequestration potential
|
||||
@ -117,6 +117,7 @@ gas_distribution_grid _cost_factor,,,Multiplier for the investment cost of the g
|
||||
,,,
|
||||
biomass_spatial,--,"{true, false}",Add option for resolving biomass demand regionally
|
||||
biomass_transport,--,"{true, false}",Add option for transporting solid biomass between nodes
|
||||
biogas_upgrading_cc,--,"{true, false}",Add option to capture CO2 from biomass upgrading
|
||||
conventional_generation,,,Add a more detailed description of conventional carriers. Any power generation requires the consumption of fuel from nodes representing that fuel.
|
||||
biomass_to_liquid,--,"{true, false}",Add option for transforming solid biomass into liquid fuel with the same properties as oil
|
||||
biosng,--,"{true, false}",Add option for transforming solid biomass into synthesis gas with the same properties as natural gas
|
||||
|
|
@ -10,6 +10,5 @@ capacity_per_sqkm,:math:`MW/km^2`,float,"Allowable density of solar panel placem
|
||||
correction_factor,--,float,"A correction factor for the capacity factor (availability) time series."
|
||||
corine,--,"Any subset of the `CORINE Land Cover code list <http://www.eea.europa.eu/data-and-maps/data/corine-land-cover-2006-raster-1/corine-land-cover-classes-and/clc_legend.csv/at_download/file>`_","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 <https://en.wikipedia.org/wiki/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 :ref:`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."
|
||||
excluder_resolution,m,float,"Resolution on which to perform geographical elibility analysis."
|
||||
|
|
BIN
doc/img/base.png
BIN
doc/img/base.png
Binary file not shown.
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 1.8 MiB |
Binary file not shown.
Before Width: | Height: | Size: 789 KiB After Width: | Height: | Size: 1.2 MiB |
@ -116,7 +116,7 @@ of the individual parts.
|
||||
topics we are working on. Please feel free to help or make suggestions.
|
||||
|
||||
This project is currently maintained by the `Department of Digital
|
||||
Transformation in Energy Systems <https:/www.ensys.tu-berlin.de>`_ at the
|
||||
Transformation in Energy Systems <https://www.tu.berlin/en/ensys>`_ at the
|
||||
`Technische Universität Berlin <https://www.tu.berlin>`_. Previous versions were
|
||||
developed within the `IAI <http://www.iai.kit.edu>`_ at the `Karlsruhe Institute
|
||||
of Technology (KIT) <http://www.kit.edu/english/index.php>`_ which was funded by
|
||||
@ -185,7 +185,7 @@ For sector-coupling studies: ::
|
||||
pages = "1--25"
|
||||
year = "2023",
|
||||
eprint = "2207.05816",
|
||||
doi = "10.1016/j.joule.2022.04.016",
|
||||
doi = "10.1016/j.joule.2023.06.016",
|
||||
}
|
||||
|
||||
For sector-coupling studies with pathway optimisation: ::
|
||||
|
@ -10,6 +10,9 @@ Release Notes
|
||||
Upcoming Release
|
||||
================
|
||||
|
||||
* Pin ``snakemake`` version to below 8.0.0, as the new version is not yet
|
||||
supported by ``pypsa-eur``.
|
||||
|
||||
* Updated Global Energy Monitor LNG terminal data to March 2023 version.
|
||||
|
||||
* For industry distribution, use EPRTR as fallback if ETS data is not available.
|
||||
@ -29,10 +32,63 @@ Upcoming Release
|
||||
|
||||
* Rule ``purge`` now initiates a dialog to confirm if purge is desired.
|
||||
|
||||
* Rule ``retrieve_irena`` get updated values for renewables capacities.
|
||||
|
||||
* Rule ``retrieve_wdpa`` updated to not only check for current and previous, but also potentially next months dataset availability.
|
||||
|
||||
* Split configuration to enable SMR and SMR CC.
|
||||
|
||||
* Bugfix: The unit of the capital cost of Haber-Bosch plants was corrected.
|
||||
|
||||
* The configuration setting for country focus weights when clustering the
|
||||
network has been moved from ``focus_weights:`` to ``clustering:
|
||||
focus_weights:``. Backwards compatibility to old config files is maintained.
|
||||
|
||||
* Extend options for waste usage from Haber-Bosch, methanolisation and methanation.
|
||||
|
||||
* Use electrolysis waste heat by default.
|
||||
|
||||
* Add new ``sector_opts`` wildcard option "nowasteheat" to disable all waste heat usage.
|
||||
|
||||
* Set minimum part loads for PtX processes to 30% for methanolisation and methanation, and to 70% for Fischer-Tropsch synthesis.
|
||||
|
||||
* Add VOM as marginal cost to PtX processes.
|
||||
|
||||
* Add pelletizing costs for biomass boilers.
|
||||
|
||||
* The ``mock_snakemake`` function can now be used with a Snakefile from a different directory using the new ``root_dir`` argument.
|
||||
|
||||
* Switch to using hydrogen and electricity inputs for Haber-Bosch from https://github.com/PyPSA/technology-data.
|
||||
|
||||
* Add option to capture CO2 contained in biogas when upgrading (``sector: biogas_to_gas_cc``).
|
||||
|
||||
* Merged option to extend geographical scope to Ukraine and Moldova. These
|
||||
countries are excluded by default and is currently constrained to power-sector
|
||||
only parts of the workflow. A special config file
|
||||
`config/config.entsoe-all.yaml` was added as an example to run the workflow
|
||||
with all ENTSO-E member countries (including observer members like Ukraine and
|
||||
Moldova). Moldova can currently only be included in conjunction with Ukraine
|
||||
due to the absence of demand data. The Crimean power system is manually
|
||||
reconnected to the main Ukrainian grid with the configuration option
|
||||
`reconnect_crimea`.
|
||||
|
||||
* Validate downloads from Zenodo using MD5 checksums. This identifies corrupted
|
||||
or incomplete downloads.
|
||||
|
||||
* Add locations, capacities and costs of existing gas storage using Global
|
||||
Energy Monitor's `Europe Gas Tracker
|
||||
<https://globalenergymonitor.org/projects/europe-gas-tracker>`_.
|
||||
|
||||
* Remove HELMETH option.
|
||||
|
||||
* Print Irreducible Infeasible Subset (IIS) if model is infeasible. Only for
|
||||
solvers with IIS support.
|
||||
|
||||
**Bugs and Compatibility**
|
||||
|
||||
* A bug preventing custom powerplants specified in ``data/custom_powerplants.csv`` was fixed. (https://github.com/PyPSA/pypsa-eur/pull/732)
|
||||
* Fix nodal fraction in ``add_existing_year`` when using distributed generators
|
||||
* Fix typo in buses definition for oil boilers in ``add_industry`` in ``prepare_sector_network``
|
||||
|
||||
|
||||
PyPSA-Eur 0.8.1 (27th July 2023)
|
||||
@ -158,6 +214,8 @@ PyPSA-Eur 0.8.1 (27th July 2023)
|
||||
(https://github.com/PyPSA/pypsa-eur/pull/672)
|
||||
|
||||
|
||||
* Addressed deprecation warnings for ``pandas=2.0``. ``pandas=2.0`` is now minimum requirement.
|
||||
|
||||
PyPSA-Eur 0.8.0 (18th March 2023)
|
||||
=================================
|
||||
|
||||
|
@ -22,11 +22,11 @@ Rule ``retrieve_databundle``
|
||||
Rule ``retrieve_cutout``
|
||||
============================
|
||||
|
||||
.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.3517949.svg
|
||||
:target: https://doi.org/10.5281/zenodo.3517949
|
||||
.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.6382570.svg
|
||||
:target: https://doi.org/10.5281/zenodo.6382570
|
||||
|
||||
Cutouts are spatio-temporal subsets of the European weather data from the `ECMWF ERA5 <https://software.ecmwf.int/wiki/display/CKB/ERA5+data+documentation>`_ reanalysis dataset and the `CMSAF SARAH-2 <https://wui.cmsaf.eu/safira/action/viewDoiDetails?acronym=SARAH_V002>`_ solar surface radiation dataset for the year 2013.
|
||||
They have been prepared by and are for use with the `atlite <https://github.com/PyPSA/atlite>`_ tool. You can either generate them yourself using the ``build_cutouts`` rule or retrieve them directly from `zenodo <https://doi.org/10.5281/zenodo.3517949>`__ through the rule ``retrieve_cutout``.
|
||||
They have been prepared by and are for use with the `atlite <https://github.com/PyPSA/atlite>`_ tool. You can either generate them yourself using the ``build_cutouts`` rule or retrieve them directly from `zenodo <https://doi.org/10.5281/zenodo.6382570>`__ through the rule ``retrieve_cutout``.
|
||||
The :ref:`tutorial` uses a smaller cutout than required for the full model (30 MB), which is also automatically downloaded.
|
||||
|
||||
.. note::
|
||||
@ -91,7 +91,7 @@ None.
|
||||
|
||||
**Outputs**
|
||||
|
||||
- ``data/load_raw.csv``
|
||||
- ``resources/load_raw.csv``
|
||||
|
||||
|
||||
Rule ``retrieve_cost_data``
|
||||
@ -118,6 +118,11 @@ This rule downloads techno-economic assumptions from the `technology-data reposi
|
||||
|
||||
- ``resources/costs.csv``
|
||||
|
||||
Rule ``retrieve_irena``
|
||||
================================
|
||||
|
||||
.. automodule:: retrieve_irena
|
||||
|
||||
Rule ``retrieve_ship_raster``
|
||||
================================
|
||||
|
||||
|
@ -25,7 +25,7 @@ full model, which allows the user to explore most of its functionalities on a
|
||||
local machine. The tutorial will cover examples on how to configure and
|
||||
customise the PyPSA-Eur model and run the ``snakemake`` workflow step by step
|
||||
from network creation to the solved network. The configuration for the tutorial
|
||||
is located at ``test/config.electricity.yaml``. It includes parts deviating from
|
||||
is located at ``config/test/config.electricity.yaml``. It includes parts deviating from
|
||||
the default config file ``config/config.default.yaml``. To run the tutorial with this
|
||||
configuration, execute
|
||||
|
||||
@ -96,7 +96,7 @@ open-source solver GLPK.
|
||||
:start-at: solver:
|
||||
:end-before: plotting:
|
||||
|
||||
Note, that ``test/config.electricity.yaml`` only includes changes relative to
|
||||
Note, that ``config/test/config.electricity.yaml`` only includes changes relative to
|
||||
the default configuration. There are many more configuration options, which are
|
||||
documented at :ref:`config`.
|
||||
|
||||
|
@ -11,6 +11,8 @@ dependencies:
|
||||
- pip
|
||||
|
||||
- atlite>=0.2.9
|
||||
- pypsa>=0.26.1
|
||||
- linopy
|
||||
- dask
|
||||
|
||||
# Dependencies of the workflow itself
|
||||
@ -18,23 +20,24 @@ dependencies:
|
||||
- openpyxl!=3.1.1
|
||||
- pycountry
|
||||
- seaborn
|
||||
- snakemake-minimal>=7.7.0
|
||||
# snakemake 8 introduced a number of breaking changes which the workflow has yet to be made compatible with
|
||||
- snakemake-minimal>=7.7.0,<8.0.0
|
||||
- memory_profiler
|
||||
- yaml
|
||||
- pytables
|
||||
- lxml
|
||||
- powerplantmatching>=0.5.5
|
||||
- numpy
|
||||
- pandas>=1.4
|
||||
- pandas>=2.1
|
||||
- geopandas>=0.11.0
|
||||
- xarray
|
||||
- xarray>=2023.11.0
|
||||
- rioxarray
|
||||
- netcdf4
|
||||
- networkx
|
||||
- scipy
|
||||
- shapely>=2.0
|
||||
- pyomo
|
||||
- matplotlib<3.6
|
||||
- matplotlib
|
||||
- proj
|
||||
- fiona
|
||||
- country_converter
|
||||
@ -44,6 +47,7 @@ dependencies:
|
||||
- tabula-py
|
||||
- pyxlsb
|
||||
- graphviz
|
||||
- ipopt
|
||||
|
||||
# Keep in conda environment when calling ipython
|
||||
- ipython
|
||||
@ -55,5 +59,4 @@ dependencies:
|
||||
|
||||
|
||||
- pip:
|
||||
- git+https://github.com/fneum/tsam.git@performance
|
||||
- pypsa>=0.25.2
|
||||
- tsam>=2.3.1
|
||||
|
@ -26,7 +26,7 @@ if config["enable"].get("retrieve_opsd_load_data", True):
|
||||
countries=config["countries"],
|
||||
load=config["load"],
|
||||
input:
|
||||
ancient("data/load_raw.csv"),
|
||||
ancient(RESOURCES + "/load_raw.csv"),
|
||||
output:
|
||||
RESOURCES + "load.csv",
|
||||
log:
|
||||
@ -244,10 +244,61 @@ rule build_ship_raster:
|
||||
"../scripts/build_ship_raster.py"
|
||||
|
||||
|
||||
rule determine_availability_matrix_MD_UA:
|
||||
input:
|
||||
copernicus="data/Copernicus_LC100_global_v3.0.1_2019-nrt_Discrete-Classification-map_EPSG-4326.tif",
|
||||
wdpa="data/WDPA.gpkg",
|
||||
wdpa_marine="data/WDPA_WDOECM_marine.gpkg",
|
||||
gebco=lambda w: (
|
||||
"data/bundle/GEBCO_2014_2D.nc"
|
||||
if "max_depth" in config["renewable"][w.technology].keys()
|
||||
else []
|
||||
),
|
||||
ship_density=lambda w: (
|
||||
RESOURCES + "shipdensity_raster.tif"
|
||||
if "ship_threshold" in config["renewable"][w.technology].keys()
|
||||
else []
|
||||
),
|
||||
country_shapes=RESOURCES + "country_shapes.geojson",
|
||||
offshore_shapes=RESOURCES + "offshore_shapes.geojson",
|
||||
regions=lambda w: (
|
||||
RESOURCES + "regions_onshore.geojson"
|
||||
if w.technology in ("onwind", "solar")
|
||||
else RESOURCES + "regions_offshore.geojson"
|
||||
),
|
||||
cutout=lambda w: "cutouts/"
|
||||
+ CDIR
|
||||
+ config["renewable"][w.technology]["cutout"]
|
||||
+ ".nc",
|
||||
output:
|
||||
availability_matrix=RESOURCES + "availability_matrix_MD-UA_{technology}.nc",
|
||||
availability_map=RESOURCES + "availability_matrix_MD-UA_{technology}.png",
|
||||
log:
|
||||
LOGS + "determine_availability_matrix_MD_UA_{technology}.log",
|
||||
threads: ATLITE_NPROCESSES
|
||||
resources:
|
||||
mem_mb=ATLITE_NPROCESSES * 5000,
|
||||
conda:
|
||||
"../envs/environment.yaml"
|
||||
script:
|
||||
"../scripts/determine_availability_matrix_MD_UA.py"
|
||||
|
||||
|
||||
# Optional input when having Ukraine (UA) or Moldova (MD) in the countries list
|
||||
if {"UA", "MD"}.intersection(set(config["countries"])):
|
||||
opt = {
|
||||
"availability_matrix_MD_UA": RESOURCES
|
||||
+ "availability_matrix_MD-UA_{technology}.nc"
|
||||
}
|
||||
else:
|
||||
opt = {}
|
||||
|
||||
|
||||
rule build_renewable_profiles:
|
||||
params:
|
||||
renewable=config["renewable"],
|
||||
input:
|
||||
**opt,
|
||||
base_network=RESOURCES + "networks/base.nc",
|
||||
corine=ancient("data/bundle/corine/g250_clc06_V18_5.tif"),
|
||||
natura=lambda w: (
|
||||
@ -264,7 +315,7 @@ rule build_renewable_profiles:
|
||||
),
|
||||
ship_density=lambda w: (
|
||||
RESOURCES + "shipdensity_raster.tif"
|
||||
if "ship_threshold" in config["renewable"][w.technology].keys()
|
||||
if config["renewable"][w.technology].get("ship_threshold", False)
|
||||
else []
|
||||
),
|
||||
country_shapes=RESOURCES + "country_shapes.geojson",
|
||||
@ -396,6 +447,7 @@ rule add_electricity:
|
||||
else [],
|
||||
load=RESOURCES + "load{weather_year}.csv",
|
||||
nuts3_shapes=RESOURCES + "nuts3_shapes.geojson",
|
||||
ua_md_gdp="data/GDP_PPP_30arcsec_v3_mapped_default.csv",
|
||||
output:
|
||||
RESOURCES + "networks/elec{weather_year}.nc",
|
||||
log:
|
||||
@ -415,7 +467,9 @@ rule simplify_network:
|
||||
params:
|
||||
simplify_network=config["clustering"]["simplify_network"],
|
||||
aggregation_strategies=config["clustering"].get("aggregation_strategies", {}),
|
||||
focus_weights=config.get("focus_weights", None),
|
||||
focus_weights=config["clustering"].get(
|
||||
"focus_weights", config.get("focus_weights")
|
||||
),
|
||||
renewable_carriers=config["electricity"]["renewable_carriers"],
|
||||
max_hours=config["electricity"]["max_hours"],
|
||||
length_factor=config["lines"]["length_factor"],
|
||||
@ -452,7 +506,9 @@ rule cluster_network:
|
||||
cluster_network=config["clustering"]["cluster_network"],
|
||||
aggregation_strategies=config["clustering"].get("aggregation_strategies", {}),
|
||||
custom_busmap=config["enable"].get("custom_busmap", False),
|
||||
focus_weights=config.get("focus_weights", None),
|
||||
focus_weights=config["clustering"].get(
|
||||
"focus_weights", config.get("focus_weights")
|
||||
),
|
||||
renewable_carriers=config["electricity"]["renewable_carriers"],
|
||||
conventional_carriers=config["electricity"].get("conventional_carriers", []),
|
||||
max_hours=config["electricity"]["max_hours"],
|
||||
|
@ -91,12 +91,12 @@ if config["sector"]["gas_network"] or config["sector"]["H2_retrofit"]:
|
||||
|
||||
rule build_gas_input_locations:
|
||||
input:
|
||||
lng=HTTP.remote(
|
||||
gem=HTTP.remote(
|
||||
"https://globalenergymonitor.org/wp-content/uploads/2023/07/Europe-Gas-Tracker-2023-03-v3.xlsx",
|
||||
keep_local=True,
|
||||
),
|
||||
entry="data/gas_network/scigrid-gas/data/IGGIELGN_BorderPoints.geojson",
|
||||
production="data/gas_network/scigrid-gas/data/IGGIELGN_Productions.geojson",
|
||||
storage="data/gas_network/scigrid-gas/data/IGGIELGN_Storages.geojson",
|
||||
regions_onshore=RESOURCES
|
||||
+ "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson",
|
||||
regions_offshore=RESOURCES
|
||||
@ -322,7 +322,7 @@ rule build_biomass_potentials:
|
||||
biomass=config["biomass"],
|
||||
input:
|
||||
enspreso_biomass=HTTP.remote(
|
||||
"https://cidportal.jrc.ec.europa.eu/ftp/jrc-opendata/ENSPRESO/ENSPRESO_BIOMASS.xlsx",
|
||||
"https://zenodo.org/records/10356004/files/ENSPRESO_BIOMASS.xlsx",
|
||||
keep_local=True,
|
||||
),
|
||||
nuts2="data/bundle-sector/nuts/NUTS_RG_10M_2013_4326_LEVL_2.geojson", # https://gisco-services.ec.europa.eu/distribution/v2/nuts/download/#nuts21
|
||||
@ -683,9 +683,8 @@ if config["sector"]["retrofitting"]["retro_endogen"]:
|
||||
countries=config["countries"],
|
||||
input:
|
||||
building_stock="data/retro/data_building_stock.csv",
|
||||
data_tabula="data/retro/tabula-calculator-calcsetbuilding.csv",
|
||||
air_temperature=RESOURCES
|
||||
+ "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc",
|
||||
data_tabula="data/bundle-sector/retro/tabula-calculator-calcsetbuilding.csv",
|
||||
air_temperature=RESOURCES + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc",
|
||||
u_values_PL="data/retro/u_values_poland.csv",
|
||||
tax_w="data/retro/electricity_taxes_eu.csv",
|
||||
construction_index="data/retro/comparative_level_investment.csv",
|
||||
|
@ -2,6 +2,11 @@
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import os, sys
|
||||
|
||||
sys.path.insert(0, os.path.abspath("scripts"))
|
||||
from _helpers import validate_checksum
|
||||
|
||||
|
||||
def memory(w):
|
||||
factor = 3.0
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
localrules:
|
||||
copy_config,
|
||||
copy_conda_env,
|
||||
|
||||
|
||||
if config["foresight"] != "perfect":
|
||||
|
@ -2,6 +2,9 @@
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import requests
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
if config["enable"].get("retrieve", "auto") == "auto":
|
||||
config["enable"]["retrieve"] = has_internet_access()
|
||||
|
||||
@ -39,6 +42,24 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_databundle",
|
||||
"../scripts/retrieve_databundle.py"
|
||||
|
||||
|
||||
if config["enable"].get("retrieve_irena"):
|
||||
|
||||
rule retrieve_irena:
|
||||
output:
|
||||
offwind="data/existing_infrastructure/offwind_capacity_IRENA.csv",
|
||||
onwind="data/existing_infrastructure/onwind_capacity_IRENA.csv",
|
||||
solar="data/existing_infrastructure/solar_capacity_IRENA.csv",
|
||||
log:
|
||||
LOGS + "retrieve_irena.log",
|
||||
resources:
|
||||
mem_mb=1000,
|
||||
retries: 2
|
||||
conda:
|
||||
"../envs/environment.yaml"
|
||||
script:
|
||||
"../scripts/retrieve_irena.py"
|
||||
|
||||
|
||||
if config["enable"]["retrieve"] and config["enable"].get("retrieve_cutout", True):
|
||||
|
||||
rule retrieve_cutout:
|
||||
@ -56,6 +77,7 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_cutout", True
|
||||
retries: 2
|
||||
run:
|
||||
move(input[0], output[0])
|
||||
validate_checksum(output[0], input[0])
|
||||
|
||||
|
||||
if config["enable"]["retrieve"] and config["enable"].get("retrieve_cost_data", True):
|
||||
@ -92,7 +114,7 @@ if config["enable"]["retrieve"] and config["enable"].get(
|
||||
static=True,
|
||||
),
|
||||
output:
|
||||
protected(RESOURCES + "natura.tiff"),
|
||||
RESOURCES + "natura.tiff",
|
||||
log:
|
||||
LOGS + "retrieve_natura_raster.log",
|
||||
resources:
|
||||
@ -100,6 +122,7 @@ if config["enable"]["retrieve"] and config["enable"].get(
|
||||
retries: 2
|
||||
run:
|
||||
move(input[0], output[0])
|
||||
validate_checksum(output[0], input[0])
|
||||
|
||||
|
||||
if config["enable"]["retrieve"] and config["enable"].get(
|
||||
@ -150,6 +173,7 @@ if config["enable"]["retrieve"] and (
|
||||
"IGGIELGN_LNGs.geojson",
|
||||
"IGGIELGN_BorderPoints.geojson",
|
||||
"IGGIELGN_Productions.geojson",
|
||||
"IGGIELGN_Storages.geojson",
|
||||
"IGGIELGN_PipeSegments.geojson",
|
||||
]
|
||||
|
||||
@ -180,7 +204,7 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_opsd_load_dat
|
||||
static=True,
|
||||
),
|
||||
output:
|
||||
"data/load_raw.csv",
|
||||
RESOURCES + "load_raw.csv",
|
||||
log:
|
||||
LOGS + "retrieve_electricity_demand.log",
|
||||
resources:
|
||||
@ -219,6 +243,106 @@ if config["enable"]["retrieve"]:
|
||||
retries: 2
|
||||
run:
|
||||
move(input[0], output[0])
|
||||
validate_checksum(output[0], input[0])
|
||||
|
||||
|
||||
if config["enable"]["retrieve"]:
|
||||
|
||||
# Downloading Copernicus Global Land Cover for land cover and land use:
|
||||
# Website: https://land.copernicus.eu/global/products/lc
|
||||
rule download_copernicus_land_cover:
|
||||
input:
|
||||
HTTP.remote(
|
||||
"zenodo.org/record/3939050/files/PROBAV_LC100_global_v3.0.1_2019-nrt_Discrete-Classification-map_EPSG-4326.tif",
|
||||
static=True,
|
||||
),
|
||||
output:
|
||||
"data/Copernicus_LC100_global_v3.0.1_2019-nrt_Discrete-Classification-map_EPSG-4326.tif",
|
||||
run:
|
||||
move(input[0], output[0])
|
||||
validate_checksum(output[0], input[0])
|
||||
|
||||
|
||||
if config["enable"]["retrieve"]:
|
||||
# Some logic to find the correct file URL
|
||||
# Sometimes files are released delayed or ahead of schedule, check which file is currently available
|
||||
|
||||
def check_file_exists(url):
|
||||
response = requests.head(url)
|
||||
return response.status_code == 200
|
||||
|
||||
# Basic pattern where WDPA files can be found
|
||||
url_pattern = (
|
||||
"https://d1gam3xoknrgr2.cloudfront.net/current/WDPA_{bYYYY}_Public_shp.zip"
|
||||
)
|
||||
|
||||
# 3-letter month + 4 digit year for current/previous/next month to test
|
||||
current_monthyear = datetime.now().strftime("%b%Y")
|
||||
prev_monthyear = (datetime.now() - timedelta(30)).strftime("%b%Y")
|
||||
next_monthyear = (datetime.now() + timedelta(30)).strftime("%b%Y")
|
||||
|
||||
# Test prioritised: current month -> previous -> next
|
||||
for bYYYY in [current_monthyear, prev_monthyear, next_monthyear]:
|
||||
if check_file_exists(url := url_pattern.format(bYYYY=bYYYY)):
|
||||
break
|
||||
else:
|
||||
# If None of the three URLs are working
|
||||
url = False
|
||||
|
||||
assert (
|
||||
url
|
||||
), f"No WDPA files found at {url_pattern} for bY='{current_monthyear}, {prev_monthyear}, or {next_monthyear}'"
|
||||
|
||||
# Downloading protected area database from WDPA
|
||||
# extract the main zip and then merge the contained 3 zipped shapefiles
|
||||
# Website: https://www.protectedplanet.net/en/thematic-areas/wdpa
|
||||
rule download_wdpa:
|
||||
input:
|
||||
HTTP.remote(
|
||||
url,
|
||||
static=True,
|
||||
keep_local=True,
|
||||
),
|
||||
params:
|
||||
zip="data/WDPA_shp.zip",
|
||||
folder=directory("data/WDPA"),
|
||||
output:
|
||||
gpkg=protected("data/WDPA.gpkg"),
|
||||
run:
|
||||
shell("cp {input} {params.zip}")
|
||||
shell("unzip -o {params.zip} -d {params.folder}")
|
||||
for i in range(3):
|
||||
# vsizip is special driver for directly working with zipped shapefiles in ogr2ogr
|
||||
layer_path = (
|
||||
f"/vsizip/{params.folder}/WDPA_{bYYYY}_Public_shp_{i}.zip"
|
||||
)
|
||||
print(f"Adding layer {i+1} of 3 to combined output file.")
|
||||
shell("ogr2ogr -f gpkg -update -append {output.gpkg} {layer_path}")
|
||||
|
||||
rule download_wdpa_marine:
|
||||
# Downloading Marine protected area database from WDPA
|
||||
# extract the main zip and then merge the contained 3 zipped shapefiles
|
||||
# Website: https://www.protectedplanet.net/en/thematic-areas/marine-protected-areas
|
||||
input:
|
||||
HTTP.remote(
|
||||
f"d1gam3xoknrgr2.cloudfront.net/current/WDPA_WDOECM_{bYYYY}_Public_marine_shp.zip",
|
||||
static=True,
|
||||
keep_local=True,
|
||||
),
|
||||
params:
|
||||
zip="data/WDPA_WDOECM_marine.zip",
|
||||
folder=directory("data/WDPA_WDOECM_marine"),
|
||||
output:
|
||||
gpkg=protected("data/WDPA_WDOECM_marine.gpkg"),
|
||||
run:
|
||||
shell("cp {input} {params.zip}")
|
||||
shell("unzip -o {params.zip} -d {params.folder}")
|
||||
for i in range(3):
|
||||
# vsizip is special driver for directly working with zipped shapefiles in ogr2ogr
|
||||
layer_path = f"/vsizip/{params.folder}/WDPA_WDOECM_{bYYYY}_Public_marine_shp_{i}.zip"
|
||||
print(f"Adding layer {i+1} of 3 to combined output file.")
|
||||
shell("ogr2ogr -f gpkg -update -append {output.gpkg} {layer_path}")
|
||||
|
||||
|
||||
|
||||
if config["enable"]["retrieve"]:
|
||||
|
@ -4,6 +4,7 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import contextlib
|
||||
import hashlib
|
||||
import logging
|
||||
import os
|
||||
import urllib
|
||||
@ -11,6 +12,7 @@ from pathlib import Path
|
||||
|
||||
import pandas as pd
|
||||
import pytz
|
||||
import requests
|
||||
import yaml
|
||||
from pypsa.components import component_attrs, components
|
||||
from pypsa.descriptors import Dict
|
||||
@ -191,7 +193,7 @@ def progress_retrieve(url, file, disable=False):
|
||||
urllib.request.urlretrieve(url, file, reporthook=update_to)
|
||||
|
||||
|
||||
def mock_snakemake(rulename, configfiles=[], **wildcards):
|
||||
def mock_snakemake(rulename, root_dir=None, configfiles=[], **wildcards):
|
||||
"""
|
||||
This function is expected to be executed from the 'scripts'-directory of '
|
||||
the snakemake project. It returns a snakemake.script.Snakemake object,
|
||||
@ -203,6 +205,8 @@ def mock_snakemake(rulename, configfiles=[], **wildcards):
|
||||
----------
|
||||
rulename: str
|
||||
name of the rule for which the snakemake object should be generated
|
||||
root_dir: str/path-like
|
||||
path to the root directory of the snakemake project
|
||||
configfiles: list, str
|
||||
list of configfiles to be used to update the config
|
||||
**wildcards:
|
||||
@ -217,7 +221,10 @@ def mock_snakemake(rulename, configfiles=[], **wildcards):
|
||||
from snakemake.script import Snakemake
|
||||
|
||||
script_dir = Path(__file__).parent.resolve()
|
||||
root_dir = script_dir.parent
|
||||
if root_dir is None:
|
||||
root_dir = script_dir.parent
|
||||
else:
|
||||
root_dir = Path(root_dir).resolve()
|
||||
|
||||
user_in_script_dir = Path.cwd().resolve() == script_dir
|
||||
if user_in_script_dir:
|
||||
@ -303,10 +310,7 @@ def generate_periodic_profiles(dt_index, nodes, weekly_profile, localize=None):
|
||||
|
||||
|
||||
def parse(l):
|
||||
if len(l) == 1:
|
||||
return yaml.safe_load(l[0])
|
||||
else:
|
||||
return {l.pop(0): parse(l)}
|
||||
return yaml.safe_load(l[0]) if len(l) == 1 else {l.pop(0): parse(l)}
|
||||
|
||||
|
||||
def update_config_with_sector_opts(config, sector_opts):
|
||||
@ -316,3 +320,63 @@ def update_config_with_sector_opts(config, sector_opts):
|
||||
if o.startswith("CF+"):
|
||||
l = o.split("+")[1:]
|
||||
update_config(config, parse(l))
|
||||
|
||||
|
||||
def get_checksum_from_zenodo(file_url):
|
||||
parts = file_url.split("/")
|
||||
record_id = parts[parts.index("record") + 1]
|
||||
filename = parts[-1]
|
||||
|
||||
response = requests.get(f"https://zenodo.org/api/records/{record_id}", timeout=30)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
|
||||
for file in data["files"]:
|
||||
if file["key"] == filename:
|
||||
return file["checksum"]
|
||||
return None
|
||||
|
||||
|
||||
def validate_checksum(file_path, zenodo_url=None, checksum=None):
|
||||
"""
|
||||
Validate file checksum against provided or Zenodo-retrieved checksum.
|
||||
Calculates the hash of a file using 64KB chunks. Compares it against a
|
||||
given checksum or one from a Zenodo URL.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
file_path : str
|
||||
Path to the file for checksum validation.
|
||||
zenodo_url : str, optional
|
||||
URL of the file on Zenodo to fetch the checksum.
|
||||
checksum : str, optional
|
||||
Checksum (format 'hash_type:checksum_value') for validation.
|
||||
|
||||
Raises
|
||||
------
|
||||
AssertionError
|
||||
If the checksum does not match, or if neither `checksum` nor `zenodo_url` is provided.
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> validate_checksum("/path/to/file", checksum="md5:abc123...")
|
||||
>>> validate_checksum(
|
||||
... "/path/to/file",
|
||||
... zenodo_url="https://zenodo.org/record/12345/files/example.txt",
|
||||
... )
|
||||
|
||||
If the checksum is invalid, an AssertionError will be raised.
|
||||
"""
|
||||
assert checksum or zenodo_url, "Either checksum or zenodo_url must be provided"
|
||||
if zenodo_url:
|
||||
checksum = get_checksum_from_zenodo(zenodo_url)
|
||||
hash_type, checksum = checksum.split(":")
|
||||
hasher = hashlib.new(hash_type)
|
||||
with open(file_path, "rb") as f:
|
||||
for chunk in iter(lambda: f.read(65536), b""): # 64kb chunks
|
||||
hasher.update(chunk)
|
||||
calculated_checksum = hasher.hexdigest()
|
||||
assert (
|
||||
calculated_checksum == checksum
|
||||
), "Checksum is invalid. This may be due to an incomplete download. Delete the file and re-execute the rule."
|
||||
|
@ -41,12 +41,9 @@ def add_brownfield(n, n_p, year):
|
||||
# remove assets if their optimized nominal capacity is lower than a threshold
|
||||
# since CHP heat Link is proportional to CHP electric Link, make sure threshold is compatible
|
||||
chp_heat = c.df.index[
|
||||
(
|
||||
c.df[attr + "_nom_extendable"]
|
||||
& c.df.index.str.contains("urban central")
|
||||
& c.df.index.str.contains("CHP")
|
||||
& c.df.index.str.contains("heat")
|
||||
)
|
||||
(c.df[f"{attr}_nom_extendable"] & c.df.index.str.contains("urban central"))
|
||||
& c.df.index.str.contains("CHP")
|
||||
& c.df.index.str.contains("heat")
|
||||
]
|
||||
|
||||
threshold = snakemake.params.threshold_capacity
|
||||
@ -60,21 +57,20 @@ def add_brownfield(n, n_p, year):
|
||||
)
|
||||
n_p.mremove(
|
||||
c.name,
|
||||
chp_heat[c.df.loc[chp_heat, attr + "_nom_opt"] < threshold_chp_heat],
|
||||
chp_heat[c.df.loc[chp_heat, f"{attr}_nom_opt"] < threshold_chp_heat],
|
||||
)
|
||||
|
||||
n_p.mremove(
|
||||
c.name,
|
||||
c.df.index[
|
||||
c.df[attr + "_nom_extendable"]
|
||||
& ~c.df.index.isin(chp_heat)
|
||||
& (c.df[attr + "_nom_opt"] < threshold)
|
||||
(c.df[f"{attr}_nom_extendable"] & ~c.df.index.isin(chp_heat))
|
||||
& (c.df[f"{attr}_nom_opt"] < threshold)
|
||||
],
|
||||
)
|
||||
|
||||
# copy over assets but fix their capacity
|
||||
c.df[attr + "_nom"] = c.df[attr + "_nom_opt"]
|
||||
c.df[attr + "_nom_extendable"] = False
|
||||
c.df[f"{attr}_nom"] = c.df[f"{attr}_nom_opt"]
|
||||
c.df[f"{attr}_nom_extendable"] = False
|
||||
|
||||
n.import_components_from_dataframe(c.df, c.name)
|
||||
|
||||
@ -124,7 +120,33 @@ def add_brownfield(n, n_p, year):
|
||||
n.links.loc[new_pipes, "p_nom_min"] = 0.0
|
||||
|
||||
|
||||
# %%
|
||||
def disable_grid_expansion_if_LV_limit_hit(n):
|
||||
if not "lv_limit" in n.global_constraints.index:
|
||||
return
|
||||
|
||||
total_expansion = (
|
||||
n.lines.eval("s_nom_min * length").sum()
|
||||
+ n.links.query("carrier == 'DC'").eval("p_nom_min * length").sum()
|
||||
).sum()
|
||||
|
||||
lv_limit = n.global_constraints.at["lv_limit", "constant"]
|
||||
|
||||
# allow small numerical differences
|
||||
if lv_limit - total_expansion < 1:
|
||||
logger.info(
|
||||
f"LV is already reached (gap {diff} MWkm), disabling expansion and LV limit"
|
||||
)
|
||||
extendable_acs = n.lines.query("s_nom_extendable").index
|
||||
n.lines.loc[extendable_acs, "s_nom_extendable"] = False
|
||||
n.lines.loc[extendable_acs, "s_nom"] = n.lines.loc[extendable_acs, "s_nom_min"]
|
||||
|
||||
extendable_dcs = n.links.query("carrier == 'DC' and p_nom_extendable").index
|
||||
n.links.loc[extendable_dcs, "p_nom_extendable"] = False
|
||||
n.links.loc[extendable_dcs, "p_nom"] = n.links.loc[extendable_dcs, "p_nom_min"]
|
||||
|
||||
n.global_constraints.drop("lv_limit", inplace=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
@ -156,5 +178,7 @@ if __name__ == "__main__":
|
||||
|
||||
add_brownfield(n, n_p, year)
|
||||
|
||||
disable_grid_expansion_if_LV_limit_hit(n)
|
||||
|
||||
n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards)))
|
||||
n.export_to_netcdf(snakemake.output[0])
|
||||
|
@ -84,6 +84,7 @@ It further adds extendable ``generators`` with **zero** capacity for
|
||||
|
||||
import logging
|
||||
from itertools import product
|
||||
from typing import Dict, List
|
||||
|
||||
import geopandas as gpd
|
||||
import numpy as np
|
||||
@ -255,6 +256,7 @@ def load_powerplants(ppl_fn):
|
||||
"bioenergy": "biomass",
|
||||
"ccgt, thermal": "CCGT",
|
||||
"hard coal": "coal",
|
||||
"natural gas": "OCGT",
|
||||
}
|
||||
return (
|
||||
pd.read_csv(ppl_fn, index_col=0, dtype={"bus": "str"})
|
||||
@ -279,11 +281,13 @@ def shapes_to_shapes(orig, dest):
|
||||
return transfer
|
||||
|
||||
|
||||
def attach_load(n, regions, load, nuts3_shapes, countries, scaling=1.0):
|
||||
def attach_load(n, regions, load, nuts3_shapes, ua_md_gdp, countries, scaling=1.0):
|
||||
substation_lv_i = n.buses.index[n.buses["substation_lv"]]
|
||||
regions = gpd.read_file(regions).set_index("name").reindex(substation_lv_i)
|
||||
opsd_load = pd.read_csv(load, index_col=0, parse_dates=True).filter(items=countries)
|
||||
|
||||
ua_md_gdp = pd.read_csv(ua_md_gdp, dtype={"name": "str"}).set_index("name")
|
||||
|
||||
logger.info(f"Load data scaled with scalling factor {scaling}.")
|
||||
opsd_load *= scaling
|
||||
|
||||
@ -291,26 +295,29 @@ def attach_load(n, regions, load, nuts3_shapes, countries, scaling=1.0):
|
||||
|
||||
def upsample(cntry, group):
|
||||
l = opsd_load[cntry]
|
||||
|
||||
if len(group) == 1:
|
||||
return pd.DataFrame({group.index[0]: l})
|
||||
else:
|
||||
nuts3_cntry = nuts3.loc[nuts3.country == cntry]
|
||||
transfer = shapes_to_shapes(group, nuts3_cntry.geometry).T.tocsr()
|
||||
gdp_n = pd.Series(
|
||||
transfer.dot(nuts3_cntry["gdp"].fillna(1.0).values), index=group.index
|
||||
)
|
||||
pop_n = pd.Series(
|
||||
transfer.dot(nuts3_cntry["pop"].fillna(1.0).values), index=group.index
|
||||
)
|
||||
nuts3_cntry = nuts3.loc[nuts3.country == cntry]
|
||||
transfer = shapes_to_shapes(group, nuts3_cntry.geometry).T.tocsr()
|
||||
gdp_n = pd.Series(
|
||||
transfer.dot(nuts3_cntry["gdp"].fillna(1.0).values), index=group.index
|
||||
)
|
||||
pop_n = pd.Series(
|
||||
transfer.dot(nuts3_cntry["pop"].fillna(1.0).values), index=group.index
|
||||
)
|
||||
|
||||
# relative factors 0.6 and 0.4 have been determined from a linear
|
||||
# regression on the country to continent load data
|
||||
factors = normed(0.6 * normed(gdp_n) + 0.4 * normed(pop_n))
|
||||
return pd.DataFrame(
|
||||
factors.values * l.values[:, np.newaxis],
|
||||
index=l.index,
|
||||
columns=factors.index,
|
||||
)
|
||||
# relative factors 0.6 and 0.4 have been determined from a linear
|
||||
# regression on the country to continent load data
|
||||
factors = normed(0.6 * normed(gdp_n) + 0.4 * normed(pop_n))
|
||||
if cntry in ["UA", "MD"]:
|
||||
# overwrite factor because nuts3 provides no data for UA+MD
|
||||
factors = normed(ua_md_gdp.loc[group.index, "GDP_PPP"].squeeze())
|
||||
return pd.DataFrame(
|
||||
factors.values * l.values[:, np.newaxis],
|
||||
index=l.index,
|
||||
columns=factors.index,
|
||||
)
|
||||
|
||||
load = pd.concat(
|
||||
[
|
||||
@ -435,7 +442,7 @@ def attach_conventional_generators(
|
||||
ppl = (
|
||||
ppl.query("carrier in @carriers")
|
||||
.join(costs, on="carrier", rsuffix="_r")
|
||||
.rename(index=lambda s: "C" + str(s))
|
||||
.rename(index=lambda s: f"C{str(s)}")
|
||||
)
|
||||
ppl["efficiency"] = ppl.efficiency.fillna(ppl.efficiency_r)
|
||||
|
||||
@ -512,7 +519,7 @@ def attach_hydro(n, costs, ppl, profile_hydro, hydro_capacities, carriers, **par
|
||||
ppl = (
|
||||
ppl.query('carrier == "hydro"')
|
||||
.reset_index(drop=True)
|
||||
.rename(index=lambda s: str(s) + " hydro")
|
||||
.rename(index=lambda s: f"{str(s)} hydro")
|
||||
)
|
||||
ror = ppl.query('technology == "Run-Of-River"')
|
||||
phs = ppl.query('technology == "Pumped Storage"')
|
||||
@ -609,16 +616,13 @@ def attach_hydro(n, costs, ppl, profile_hydro, hydro_capacities, carriers, **par
|
||||
)
|
||||
if not missing_countries.empty:
|
||||
logger.warning(
|
||||
"Assuming max_hours=6 for hydro reservoirs in the countries: {}".format(
|
||||
", ".join(missing_countries)
|
||||
)
|
||||
f'Assuming max_hours=6 for hydro reservoirs in the countries: {", ".join(missing_countries)}'
|
||||
)
|
||||
hydro_max_hours = hydro.max_hours.where(
|
||||
hydro.max_hours > 0, hydro.country.map(max_hours_country)
|
||||
).fillna(6)
|
||||
|
||||
flatten_dispatch = params.get("flatten_dispatch", False)
|
||||
if flatten_dispatch:
|
||||
if flatten_dispatch := params.get("flatten_dispatch", False):
|
||||
buffer = params.get("flatten_dispatch_buffer", 0.2)
|
||||
average_capacity_factor = inflow_t[hydro.index].mean() / hydro["p_nom"]
|
||||
p_max_pu = (average_capacity_factor + buffer).clip(upper=1)
|
||||
@ -714,7 +718,17 @@ def attach_extendable_generators(n, costs, ppl, carriers):
|
||||
)
|
||||
|
||||
|
||||
def attach_OPSD_renewables(n, tech_map):
|
||||
def attach_OPSD_renewables(n: pypsa.Network, tech_map: Dict[str, List[str]]) -> None:
|
||||
"""
|
||||
Attach renewable capacities from the OPSD dataset to the network.
|
||||
|
||||
Args:
|
||||
- n: The PyPSA network to attach the capacities to.
|
||||
- tech_map: A dictionary mapping fuel types to carrier names.
|
||||
|
||||
Returns:
|
||||
- None
|
||||
"""
|
||||
tech_string = ", ".join(sum(tech_map.values(), []))
|
||||
logger.info(f"Using OPSD renewable capacities for carriers {tech_string}.")
|
||||
|
||||
@ -739,7 +753,26 @@ def attach_OPSD_renewables(n, tech_map):
|
||||
n.generators.p_nom_min.update(gens.bus.map(caps).dropna())
|
||||
|
||||
|
||||
def estimate_renewable_capacities(n, year, tech_map, expansion_limit, countries):
|
||||
def estimate_renewable_capacities(
|
||||
n: pypsa.Network, year: int, tech_map: dict, expansion_limit: bool, countries: list
|
||||
) -> None:
|
||||
"""
|
||||
Estimate a different between renewable capacities in the network and
|
||||
reported country totals from IRENASTAT dataset. Distribute the difference
|
||||
with a heuristic.
|
||||
|
||||
Heuristic: n.generators_t.p_max_pu.mean() * n.generators.p_nom_max
|
||||
|
||||
Args:
|
||||
- n: The PyPSA network.
|
||||
- year: The year of optimisation.
|
||||
- tech_map: A dictionary mapping fuel types to carrier names.
|
||||
- expansion_limit: Boolean value from config file
|
||||
- countries: A list of country codes to estimate capacities for.
|
||||
|
||||
Returns:
|
||||
- None
|
||||
"""
|
||||
if not len(countries) or not len(tech_map):
|
||||
return
|
||||
|
||||
@ -756,7 +789,10 @@ def estimate_renewable_capacities(n, year, tech_map, expansion_limit, countries)
|
||||
|
||||
for ppm_technology, techs in tech_map.items():
|
||||
tech_i = n.generators.query("carrier in @techs").index
|
||||
stats = capacities.loc[ppm_technology].reindex(countries, fill_value=0.0)
|
||||
if ppm_technology in capacities.index.get_level_values("Technology"):
|
||||
stats = capacities.loc[ppm_technology].reindex(countries, fill_value=0.0)
|
||||
else:
|
||||
stats = pd.Series(0.0, index=countries)
|
||||
country = n.generators.bus[tech_i].map(n.buses.country)
|
||||
existent = n.generators.p_nom[tech_i].groupby(country).sum()
|
||||
missing = stats - existent
|
||||
@ -848,6 +884,7 @@ if __name__ == "__main__":
|
||||
snakemake.input.regions,
|
||||
snakemake.input.load,
|
||||
snakemake.input.nuts3_shapes,
|
||||
snakemake.input.ua_md_gdp,
|
||||
params.countries,
|
||||
params.scaling_factor,
|
||||
)
|
||||
|
@ -45,7 +45,7 @@ def add_build_year_to_new_assets(n, baseyear):
|
||||
|
||||
# add -baseyear to name
|
||||
rename = pd.Series(c.df.index, c.df.index)
|
||||
rename[assets] += "-" + str(baseyear)
|
||||
rename[assets] += f"-{str(baseyear)}"
|
||||
c.df.rename(index=rename, inplace=True)
|
||||
|
||||
# rename time-dependent
|
||||
@ -88,7 +88,9 @@ def add_existing_renewables(df_agg):
|
||||
]
|
||||
cfs = n.generators_t.p_max_pu[gens].mean()
|
||||
cfs_key = cfs / cfs.sum()
|
||||
nodal_fraction.loc[n.generators.loc[gens, "bus"]] = cfs_key.values
|
||||
nodal_fraction.loc[n.generators.loc[gens, "bus"]] = cfs_key.groupby(
|
||||
n.generators.loc[gens, "bus"]
|
||||
).sum()
|
||||
|
||||
nodal_df = df.loc[n.buses.loc[elec_buses, "country"]]
|
||||
nodal_df.index = elec_buses
|
||||
@ -252,7 +254,7 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas
|
||||
if "m" in snakemake.wildcards.clusters:
|
||||
for ind in new_capacity.index:
|
||||
# existing capacities are split evenly among regions in every country
|
||||
inv_ind = [i for i in inv_busmap[ind]]
|
||||
inv_ind = list(inv_busmap[ind])
|
||||
|
||||
# for offshore the splitting only includes coastal regions
|
||||
inv_ind = [
|
||||
@ -545,13 +547,17 @@ def add_heating_capacities_installed_before_baseyear(
|
||||
bus0=nodes[name],
|
||||
bus1=nodes[name] + " " + name + " heat",
|
||||
carrier=name + " resistive heater",
|
||||
efficiency=costs.at[name_type + " resistive heater", "efficiency"],
|
||||
capital_cost=costs.at[name_type + " resistive heater", "efficiency"]
|
||||
* costs.at[name_type + " resistive heater", "fixed"],
|
||||
p_nom=0.5
|
||||
* nodal_df[f"{heat_type} resistive heater"][nodes[name]]
|
||||
* ratio
|
||||
/ costs.at[name_type + " resistive heater", "efficiency"],
|
||||
efficiency=costs.at[f"{name_type} resistive heater", "efficiency"],
|
||||
capital_cost=(
|
||||
costs.at[f"{name_type} resistive heater", "efficiency"]
|
||||
* costs.at[f"{name_type} resistive heater", "fixed"]
|
||||
),
|
||||
p_nom=(
|
||||
0.5
|
||||
* nodal_df[f"{heat_type} resistive heater"][nodes[name]]
|
||||
* ratio
|
||||
/ costs.at[f"{name_type} resistive heater", "efficiency"]
|
||||
),
|
||||
build_year=int(grouping_year),
|
||||
lifetime=costs.at[costs_name, "lifetime"],
|
||||
)
|
||||
@ -564,16 +570,20 @@ def add_heating_capacities_installed_before_baseyear(
|
||||
bus1=nodes[name] + " " + name + " heat",
|
||||
bus2="co2 atmosphere",
|
||||
carrier=name + " gas boiler",
|
||||
efficiency=costs.at[name_type + " gas boiler", "efficiency"],
|
||||
efficiency=costs.at[f"{name_type} gas boiler", "efficiency"],
|
||||
efficiency2=costs.at["gas", "CO2 intensity"],
|
||||
capital_cost=costs.at[name_type + " gas boiler", "efficiency"]
|
||||
* costs.at[name_type + " gas boiler", "fixed"],
|
||||
p_nom=0.5
|
||||
* nodal_df[f"{heat_type} gas boiler"][nodes[name]]
|
||||
* ratio
|
||||
/ costs.at[name_type + " gas boiler", "efficiency"],
|
||||
capital_cost=(
|
||||
costs.at[f"{name_type} gas boiler", "efficiency"]
|
||||
* costs.at[f"{name_type} gas boiler", "fixed"]
|
||||
),
|
||||
p_nom=(
|
||||
0.5
|
||||
* nodal_df[f"{heat_type} gas boiler"][nodes[name]]
|
||||
* ratio
|
||||
/ costs.at[f"{name_type} gas boiler", "efficiency"]
|
||||
),
|
||||
build_year=int(grouping_year),
|
||||
lifetime=costs.at[name_type + " gas boiler", "lifetime"],
|
||||
lifetime=costs.at[f"{name_type} gas boiler", "lifetime"],
|
||||
)
|
||||
|
||||
n.madd(
|
||||
@ -593,7 +603,7 @@ def add_heating_capacities_installed_before_baseyear(
|
||||
* ratio
|
||||
/ costs.at["decentral oil boiler", "efficiency"],
|
||||
build_year=int(grouping_year),
|
||||
lifetime=costs.at[name_type + " gas boiler", "lifetime"],
|
||||
lifetime=costs.at[f"{name_type} gas boiler", "lifetime"],
|
||||
)
|
||||
|
||||
# delete links with p_nom=nan corresponding to extra nodes in country
|
||||
@ -622,7 +632,6 @@ def add_heating_capacities_installed_before_baseyear(
|
||||
n.mremove("Link", links_i)
|
||||
|
||||
|
||||
# %%
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
|
@ -149,9 +149,7 @@ def _load_buses_from_eg(eg_buses, europe_shape, config_elec):
|
||||
buses.v_nom.isin(config_elec["voltages"]) | buses.v_nom.isnull()
|
||||
)
|
||||
logger.info(
|
||||
"Removing buses with voltages {}".format(
|
||||
pd.Index(buses.v_nom.unique()).dropna().difference(config_elec["voltages"])
|
||||
)
|
||||
f'Removing buses with voltages {pd.Index(buses.v_nom.unique()).dropna().difference(config_elec["voltages"])}'
|
||||
)
|
||||
|
||||
return pd.DataFrame(buses.loc[buses_in_europe_b & buses_with_v_nom_to_keep_b])
|
||||
@ -366,6 +364,25 @@ def _apply_parameter_corrections(n, parameter_corrections):
|
||||
df.loc[inds, attr] = r[inds].astype(df[attr].dtype)
|
||||
|
||||
|
||||
def _reconnect_crimea(lines):
|
||||
logger.info("Reconnecting Crimea to the Ukrainian grid.")
|
||||
lines_to_crimea = pd.DataFrame(
|
||||
{
|
||||
"bus0": ["3065", "3181", "3181"],
|
||||
"bus1": ["3057", "3055", "3057"],
|
||||
"v_nom": [300, 300, 300],
|
||||
"num_parallel": [1, 1, 1],
|
||||
"length": [140, 120, 140],
|
||||
"carrier": ["AC", "AC", "AC"],
|
||||
"underground": [False, False, False],
|
||||
"under_construction": [False, False, False],
|
||||
},
|
||||
index=["Melitopol", "Liubymivka left", "Luibymivka right"],
|
||||
)
|
||||
|
||||
return pd.concat([lines, lines_to_crimea])
|
||||
|
||||
|
||||
def _set_electrical_parameters_lines(lines, config):
|
||||
v_noms = config["electricity"]["voltages"]
|
||||
linetypes = config["lines"]["types"]
|
||||
@ -450,19 +467,15 @@ def _remove_dangling_branches(branches, buses):
|
||||
)
|
||||
|
||||
|
||||
def _remove_unconnected_components(network):
|
||||
def _remove_unconnected_components(network, threshold=6):
|
||||
_, labels = csgraph.connected_components(network.adjacency_matrix(), directed=False)
|
||||
component = pd.Series(labels, index=network.buses.index)
|
||||
|
||||
component_sizes = component.value_counts()
|
||||
components_to_remove = component_sizes.iloc[1:]
|
||||
components_to_remove = component_sizes.loc[component_sizes < threshold]
|
||||
|
||||
logger.info(
|
||||
"Removing {} unconnected network components with less than {} buses. In total {} buses.".format(
|
||||
len(components_to_remove),
|
||||
components_to_remove.max(),
|
||||
components_to_remove.sum(),
|
||||
)
|
||||
f"Removing {len(components_to_remove)} unconnected network components with less than {components_to_remove.max()} buses. In total {components_to_remove.sum()} buses."
|
||||
)
|
||||
|
||||
return network[component == component_sizes.index[0]]
|
||||
@ -545,7 +558,7 @@ def _set_countries_and_substations(n, config, country_shapes, offshore_shapes):
|
||||
~buses["under_construction"]
|
||||
)
|
||||
|
||||
c_nan_b = buses.country.isnull()
|
||||
c_nan_b = buses.country == "na"
|
||||
if c_nan_b.sum() > 0:
|
||||
c_tag = _get_country(buses.loc[c_nan_b])
|
||||
c_tag.loc[~c_tag.isin(countries)] = np.nan
|
||||
@ -703,6 +716,9 @@ def base_network(
|
||||
lines = _load_lines_from_eg(buses, eg_lines)
|
||||
transformers = _load_transformers_from_eg(buses, eg_transformers)
|
||||
|
||||
if config["lines"].get("reconnect_crimea", True) and "UA" in config["countries"]:
|
||||
lines = _reconnect_crimea(lines)
|
||||
|
||||
lines = _set_electrical_parameters_lines(lines, config)
|
||||
transformers = _set_electrical_parameters_transformers(transformers, config)
|
||||
links = _set_electrical_parameters_links(links, config, links_p_nom)
|
||||
|
@ -134,7 +134,7 @@ def disaggregate_nuts0(bio):
|
||||
# get population in nuts2
|
||||
pop_nuts2 = pop.loc[pop.index.str.len() == 4]
|
||||
by_country = pop_nuts2.total.groupby(pop_nuts2.ct).sum()
|
||||
pop_nuts2["fraction"] = pop_nuts2.total / pop_nuts2.ct.map(by_country)
|
||||
pop_nuts2.loc[:, "fraction"] = pop_nuts2.total / pop_nuts2.ct.map(by_country)
|
||||
|
||||
# distribute nuts0 data to nuts2 by population
|
||||
bio_nodal = bio.loc[pop_nuts2.ct]
|
||||
@ -264,7 +264,7 @@ if __name__ == "__main__":
|
||||
df.to_csv(snakemake.output.biomass_potentials_all)
|
||||
|
||||
grouper = {v: k for k, vv in params["classes"].items() for v in vv}
|
||||
df = df.groupby(grouper, axis=1).sum()
|
||||
df = df.T.groupby(grouper).sum().T
|
||||
|
||||
df *= 1e6 # TWh/a to MWh/a
|
||||
df.index.name = "MWh/a"
|
||||
|
@ -30,10 +30,7 @@ if __name__ == "__main__":
|
||||
cutout = atlite.Cutout(cutout_name)
|
||||
|
||||
clustered_regions = (
|
||||
gpd.read_file(snakemake.input.regions_onshore)
|
||||
.set_index("name")
|
||||
.buffer(0)
|
||||
.squeeze()
|
||||
gpd.read_file(snakemake.input.regions_onshore).set_index("name").buffer(0)
|
||||
)
|
||||
|
||||
I = cutout.indicatormatrix(clustered_regions)
|
||||
|
@ -31,7 +31,7 @@ Relevant Settings
|
||||
Inputs
|
||||
------
|
||||
|
||||
- ``data/load_raw.csv``:
|
||||
- ``resources/load_raw.csv``:
|
||||
|
||||
Outputs
|
||||
-------
|
||||
@ -81,7 +81,7 @@ def load_timeseries(fn, years, countries, powerstatistics=True):
|
||||
return s[: -len(pattern)]
|
||||
|
||||
return (
|
||||
pd.read_csv(fn, index_col=0, parse_dates=[0])
|
||||
pd.read_csv(fn, index_col=0, parse_dates=[0], date_format="%Y-%m-%dT%H:%M:%SZ")
|
||||
.tz_localize(None)
|
||||
.filter(like=pattern)
|
||||
.rename(columns=rename)
|
||||
@ -155,7 +155,7 @@ def copy_timeslice(load, cntry, start, stop, delta, fn_load=None):
|
||||
].values
|
||||
|
||||
|
||||
def manual_adjustment(load, fn_load, powerstatistics):
|
||||
def manual_adjustment(load, fn_load, powerstatistics, countries):
|
||||
"""
|
||||
Adjust gaps manual for load data from OPSD time-series package.
|
||||
|
||||
@ -278,6 +278,14 @@ def manual_adjustment(load, fn_load, powerstatistics):
|
||||
load, "LU", "2019-02-05 20:00", "2019-02-06 19:00", Delta(weeks=-1)
|
||||
)
|
||||
|
||||
if "UA" in countries:
|
||||
copy_timeslice(
|
||||
load, "UA", "2013-01-25 14:00", "2013-01-28 21:00", Delta(weeks=1)
|
||||
)
|
||||
copy_timeslice(
|
||||
load, "UA", "2013-10-28 03:00", "2013-10-28 20:00", Delta(weeks=1)
|
||||
)
|
||||
|
||||
return load
|
||||
|
||||
|
||||
@ -315,8 +323,22 @@ if __name__ == "__main__":
|
||||
|
||||
load = load_timeseries(snakemake.input[0], years, countries, powerstatistics)
|
||||
|
||||
if "UA" in countries:
|
||||
# attach load of UA (best data only for entsoe transparency)
|
||||
load_ua = load_timeseries(snakemake.input[0], "2018", ["UA"], False)
|
||||
snapshot_year = str(snapshots.year.unique().item())
|
||||
time_diff = pd.Timestamp("2018") - pd.Timestamp(snapshot_year)
|
||||
load_ua.index -= (
|
||||
time_diff # hack indices (currently, UA is manually set to 2018)
|
||||
)
|
||||
load["UA"] = load_ua
|
||||
# attach load of MD (no time-series available, use 2020-totals and distribute according to UA):
|
||||
# https://www.iea.org/data-and-statistics/data-browser/?country=MOLDOVA&fuel=Energy%20consumption&indicator=TotElecCons
|
||||
if "MD" in countries:
|
||||
load["MD"] = 6.2e6 * (load_ua / load_ua.sum())
|
||||
|
||||
if snakemake.params.load["manual_adjustments"]:
|
||||
load = manual_adjustment(load, snakemake.input[0], powerstatistics)
|
||||
load = manual_adjustment(load, snakemake.input[0], powerstatistics, countries)
|
||||
|
||||
if load.empty:
|
||||
logger.warning("Build electricity demand time series is empty.")
|
||||
|
@ -149,11 +149,9 @@ def build_swiss(year=None):
|
||||
return df
|
||||
|
||||
|
||||
def idees_per_country(country, base_dir):
|
||||
|
||||
def idees_per_country(ct, year, base_dir):
|
||||
ct_totals = {}
|
||||
|
||||
ct_idees = idees_rename.get(country, country)
|
||||
ct_idees = idees_rename.get(ct, ct)
|
||||
fn_residential = f"{base_dir}/JRC-IDEES-2015_Residential_{ct_idees}.xlsx"
|
||||
fn_tertiary = f"{base_dir}/JRC-IDEES-2015_Tertiary_{ct_idees}.xlsx"
|
||||
fn_transport = f"{base_dir}/JRC-IDEES-2015_Transport_{ct_idees}.xlsx"
|
||||
@ -188,7 +186,7 @@ def idees_per_country(country, base_dir):
|
||||
assert df.index[46] == "Derived heat"
|
||||
ct_totals["derived heat residential"] = df.iloc[46]
|
||||
|
||||
assert df.index[50] == 'Thermal uses'
|
||||
assert df.index[50] == "Thermal uses"
|
||||
ct_totals["thermal uses residential"] = df.iloc[50]
|
||||
|
||||
# services
|
||||
@ -221,7 +219,7 @@ def idees_per_country(country, base_dir):
|
||||
assert df.index[49] == "Derived heat"
|
||||
ct_totals["derived heat services"] = df.iloc[49]
|
||||
|
||||
assert df.index[53] == 'Thermal uses'
|
||||
assert df.index[53] == "Thermal uses"
|
||||
ct_totals["thermal uses services"] = df.iloc[53]
|
||||
|
||||
# agriculture, forestry and fishing
|
||||
@ -319,7 +317,7 @@ def idees_per_country(country, base_dir):
|
||||
|
||||
assert df.index[8] == "International - Intra-EU"
|
||||
assert df.index[9] == "International - Extra-EU"
|
||||
ct_totals["total international aviation passenger"] = df.iloc[[8,9]].sum()
|
||||
ct_totals["total international aviation passenger"] = df.iloc[[8, 9]].sum()
|
||||
|
||||
assert df.index[11] == "Domestic and International - Intra-EU"
|
||||
ct_totals["total domestic aviation freight"] = df.iloc[11]
|
||||
|
@ -23,11 +23,10 @@ def read_scigrid_gas(fn):
|
||||
return df
|
||||
|
||||
|
||||
def build_gem_lng_data(lng_fn):
|
||||
df = pd.read_excel(lng_fn[0], sheet_name="LNG terminals - data")
|
||||
def build_gem_lng_data(fn):
|
||||
df = pd.read_excel(fn[0], sheet_name="LNG terminals - data")
|
||||
df = df.set_index("ComboID")
|
||||
|
||||
remove_status = ["Cancelled"]
|
||||
remove_country = ["Cyprus", "Turkey"]
|
||||
remove_terminal = ["Puerto de la Luz LNG Terminal", "Gran Canaria LNG Terminal"]
|
||||
|
||||
@ -42,9 +41,50 @@ def build_gem_lng_data(lng_fn):
|
||||
return gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326")
|
||||
|
||||
|
||||
def build_gas_input_locations(lng_fn, entry_fn, prod_fn, countries):
|
||||
def build_gem_prod_data(fn):
|
||||
df = pd.read_excel(fn[0], sheet_name="Gas extraction - main")
|
||||
df = df.set_index("GEM Unit ID")
|
||||
|
||||
remove_country = ["Cyprus", "Türkiye"]
|
||||
remove_fuel_type = ["oil"]
|
||||
|
||||
df = df.query(
|
||||
"Status != 'shut in' \
|
||||
& 'Fuel type' != 'oil' \
|
||||
& Country != @remove_country \
|
||||
& ~Latitude.isna() \
|
||||
& ~Longitude.isna()"
|
||||
).copy()
|
||||
|
||||
p = pd.read_excel(fn[0], sheet_name="Gas extraction - production")
|
||||
p = p.set_index("GEM Unit ID")
|
||||
p = p[p["Fuel description"] == "gas"]
|
||||
|
||||
capacities = pd.DataFrame(index=df.index)
|
||||
for key in ["production", "production design capacity", "reserves"]:
|
||||
cap = (
|
||||
p.loc[p["Production/reserves"] == key, "Quantity (converted)"]
|
||||
.groupby("GEM Unit ID")
|
||||
.sum()
|
||||
.reindex(df.index)
|
||||
)
|
||||
# assume capacity such that 3% of reserves can be extracted per year (25% quantile)
|
||||
annualization_factor = 0.03 if key == "reserves" else 1.0
|
||||
capacities[key] = cap * annualization_factor
|
||||
|
||||
df["mcm_per_year"] = (
|
||||
capacities["production"]
|
||||
.combine_first(capacities["production design capacity"])
|
||||
.combine_first(capacities["reserves"])
|
||||
)
|
||||
|
||||
geometry = gpd.points_from_xy(df["Longitude"], df["Latitude"])
|
||||
return gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326")
|
||||
|
||||
|
||||
def build_gas_input_locations(gem_fn, entry_fn, sto_fn, countries):
|
||||
# LNG terminals
|
||||
lng = build_gem_lng_data(lng_fn)
|
||||
lng = build_gem_lng_data(gem_fn)
|
||||
|
||||
# Entry points from outside the model scope
|
||||
entry = read_scigrid_gas(entry_fn)
|
||||
@ -55,25 +95,30 @@ def build_gas_input_locations(lng_fn, entry_fn, prod_fn, countries):
|
||||
| (entry.from_country == "NO") # malformed datapoint # entries from NO to GB
|
||||
]
|
||||
|
||||
sto = read_scigrid_gas(sto_fn)
|
||||
remove_country = ["RU", "UA", "TR", "BY"]
|
||||
sto = sto.query("country_code != @remove_country")
|
||||
|
||||
# production sites inside the model scope
|
||||
prod = read_scigrid_gas(prod_fn)
|
||||
prod = prod.loc[
|
||||
(prod.geometry.y > 35) & (prod.geometry.x < 30) & (prod.country_code != "DE")
|
||||
]
|
||||
prod = build_gem_prod_data(gem_fn)
|
||||
|
||||
mcm_per_day_to_mw = 437.5 # MCM/day to MWh/h
|
||||
mcm_per_year_to_mw = 1.199 # MCM/year to MWh/h
|
||||
mtpa_to_mw = 1649.224 # mtpa to MWh/h
|
||||
lng["p_nom"] = lng["CapacityInMtpa"] * mtpa_to_mw
|
||||
entry["p_nom"] = entry["max_cap_from_to_M_m3_per_d"] * mcm_per_day_to_mw
|
||||
prod["p_nom"] = prod["max_supply_M_m3_per_d"] * mcm_per_day_to_mw
|
||||
mcm_to_gwh = 11.36 # MCM to GWh
|
||||
lng["capacity"] = lng["CapacityInMtpa"] * mtpa_to_mw
|
||||
entry["capacity"] = entry["max_cap_from_to_M_m3_per_d"] * mcm_per_day_to_mw
|
||||
prod["capacity"] = prod["mcm_per_year"] * mcm_per_year_to_mw
|
||||
sto["capacity"] = sto["max_cushionGas_M_m3"] * mcm_to_gwh
|
||||
|
||||
lng["type"] = "lng"
|
||||
entry["type"] = "pipeline"
|
||||
prod["type"] = "production"
|
||||
sto["type"] = "storage"
|
||||
|
||||
sel = ["geometry", "p_nom", "type"]
|
||||
sel = ["geometry", "capacity", "type"]
|
||||
|
||||
return pd.concat([prod[sel], entry[sel], lng[sel]], ignore_index=True)
|
||||
return pd.concat([prod[sel], entry[sel], lng[sel], sto[sel]], ignore_index=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@ -83,7 +128,7 @@ if __name__ == "__main__":
|
||||
snakemake = mock_snakemake(
|
||||
"build_gas_input_locations",
|
||||
simpl="",
|
||||
clusters="37",
|
||||
clusters="128",
|
||||
)
|
||||
|
||||
logging.basicConfig(level=snakemake.config["logging"]["level"])
|
||||
@ -104,9 +149,9 @@ if __name__ == "__main__":
|
||||
countries = regions.index.str[:2].unique().str.replace("GB", "UK")
|
||||
|
||||
gas_input_locations = build_gas_input_locations(
|
||||
snakemake.input.lng,
|
||||
snakemake.input.gem,
|
||||
snakemake.input.entry,
|
||||
snakemake.input.production,
|
||||
snakemake.input.storage,
|
||||
countries,
|
||||
)
|
||||
|
||||
@ -116,9 +161,13 @@ if __name__ == "__main__":
|
||||
|
||||
gas_input_nodes.to_file(snakemake.output.gas_input_nodes, driver="GeoJSON")
|
||||
|
||||
ensure_columns = ["lng", "pipeline", "production", "storage"]
|
||||
gas_input_nodes_s = (
|
||||
gas_input_nodes.groupby(["bus", "type"])["p_nom"].sum().unstack()
|
||||
gas_input_nodes.groupby(["bus", "type"])["capacity"]
|
||||
.sum()
|
||||
.unstack()
|
||||
.reindex(columns=ensure_columns)
|
||||
)
|
||||
gas_input_nodes_s.columns.name = "p_nom"
|
||||
gas_input_nodes_s.columns.name = "capacity"
|
||||
|
||||
gas_input_nodes_s.to_csv(snakemake.output.gas_input_nodes_simplified)
|
||||
|
@ -29,25 +29,25 @@ def diameter_to_capacity(pipe_diameter_mm):
|
||||
Based on p.15 of
|
||||
https://gasforclimate2050.eu/wp-content/uploads/2020/07/2020_European-Hydrogen-Backbone_Report.pdf
|
||||
"""
|
||||
# slopes definitions
|
||||
m0 = (1500 - 0) / (500 - 0)
|
||||
m1 = (5000 - 1500) / (600 - 500)
|
||||
m2 = (11250 - 5000) / (900 - 600)
|
||||
m3 = (21700 - 11250) / (1200 - 900)
|
||||
|
||||
# intercept
|
||||
a0 = 0
|
||||
a1 = -16000
|
||||
a2 = -7500
|
||||
a3 = -20100
|
||||
|
||||
if pipe_diameter_mm < 500:
|
||||
# slopes definitions
|
||||
m0 = (1500 - 0) / (500 - 0)
|
||||
# intercept
|
||||
a0 = 0
|
||||
return a0 + m0 * pipe_diameter_mm
|
||||
elif pipe_diameter_mm < 600:
|
||||
return a1 + m1 * pipe_diameter_mm
|
||||
elif pipe_diameter_mm < 900:
|
||||
return a2 + m2 * pipe_diameter_mm
|
||||
else:
|
||||
m3 = (21700 - 11250) / (1200 - 900)
|
||||
|
||||
a3 = -20100
|
||||
|
||||
return a3 + m3 * pipe_diameter_mm
|
||||
|
||||
|
||||
|
@ -47,10 +47,7 @@ if __name__ == "__main__":
|
||||
cutout = atlite.Cutout(cutout_name).sel(time=time)
|
||||
|
||||
clustered_regions = (
|
||||
gpd.read_file(snakemake.input.regions_onshore)
|
||||
.set_index("name")
|
||||
.buffer(0)
|
||||
.squeeze()
|
||||
gpd.read_file(snakemake.input.regions_onshore).set_index("name").buffer(0)
|
||||
)
|
||||
|
||||
I = cutout.indicatormatrix(clustered_regions)
|
||||
|
@ -26,7 +26,7 @@ Relevant Settings
|
||||
Inputs
|
||||
------
|
||||
|
||||
- ``data/bundle/EIA_hydro_generation_2000_2014.csv``: Hydroelectricity net generation per country and year (`EIA <https://www.eia.gov/beta/international/data/browser/#/?pa=000000000000000000000000000000g&c=1028i008006gg6168g80a4k000e0ag00gg0004g800ho00g8&ct=0&ug=8&tl_id=2-A&vs=INTL.33-12-ALB-BKWH.A&cy=2014&vo=0&v=H&start=2000&end=2016>`_)
|
||||
- ``data/bundle/eia_hydro_annual_generation.csv``: Hydroelectricity net generation per country and year (`EIA <https://www.eia.gov/beta/international/data/browser/#/?pa=000000000000000000000000000000g&c=1028i008006gg6168g80a4k000e0ag00gg0004g800ho00g8&ct=0&ug=8&tl_id=2-A&vs=INTL.33-12-ALB-BKWH.A&cy=2014&vo=0&v=H&start=2000&end=2016>`_)
|
||||
|
||||
.. image:: img/hydrogeneration.png
|
||||
:scale: 33 %
|
||||
@ -73,13 +73,14 @@ cc = coco.CountryConverter()
|
||||
|
||||
def get_eia_annual_hydro_generation(fn, countries, capacities=False):
|
||||
# in billion kWh/a = TWh/a
|
||||
# capacity: in billion kW = GW
|
||||
df = pd.read_csv(fn, skiprows=2, index_col=1, na_values=[" ", "--"]).iloc[1:, 1:]
|
||||
df = pd.read_csv(
|
||||
fn, skiprows=2, index_col=1, na_values=[" ", "--"], decimal=","
|
||||
).iloc[1:, 1:]
|
||||
df.index = df.index.str.strip()
|
||||
|
||||
former_countries = {
|
||||
"Former Czechoslovakia": dict(
|
||||
countries=["Czech Republic", "Slovakia"], start=1980, end=1992
|
||||
countries=["Czechia", "Slovakia"], start=1980, end=1992
|
||||
),
|
||||
"Former Serbia and Montenegro": dict(
|
||||
countries=["Serbia", "Montenegro"], start=1992, end=2005
|
||||
|
@ -96,23 +96,6 @@ def prepare_hotmaps_database(regions):
|
||||
gdf.rename(columns={"index_right": "bus"}, inplace=True)
|
||||
gdf["country"] = gdf.bus.str[:2]
|
||||
|
||||
# the .sjoin can lead to duplicates if a geom is in two regions
|
||||
if gdf.index.duplicated().any():
|
||||
import pycountry
|
||||
|
||||
# get all duplicated entries
|
||||
duplicated_i = gdf.index[gdf.index.duplicated()]
|
||||
# convert from raw data country name to iso-2-code
|
||||
s = df.loc[duplicated_i, "Country"].apply(
|
||||
lambda x: pycountry.countries.lookup(x).alpha_2
|
||||
)
|
||||
# Get a boolean mask where gdf's country column matches s's values for the same index
|
||||
mask = gdf["country"] == gdf.index.map(s)
|
||||
# Filter gdf using the mask
|
||||
gdf_filtered = gdf[mask]
|
||||
# concat not duplicated and filtered gdf
|
||||
gdf = pd.concat([gdf.drop(duplicated_i), gdf_filtered]).sort_index()
|
||||
|
||||
# the .sjoin can lead to duplicates if a geom is in two overlapping regions
|
||||
if gdf.index.duplicated().any():
|
||||
# get all duplicated entries
|
||||
@ -164,7 +147,6 @@ def build_nodal_distribution_key(hotmaps, regions, countries):
|
||||
return keys
|
||||
|
||||
|
||||
# %%
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
|
@ -167,9 +167,7 @@ def industrial_energy_demand(countries, year):
|
||||
with mp.Pool(processes=nprocesses) as pool:
|
||||
demand_l = list(tqdm(pool.imap(func, countries), **tqdm_kwargs))
|
||||
|
||||
demand = pd.concat(demand_l, keys=countries)
|
||||
|
||||
return demand
|
||||
return pd.concat(demand_l, keys=countries)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -83,8 +83,7 @@ def calculate_resistance(T, R_ref, T_ref=293, alpha=0.00403):
|
||||
-------
|
||||
Resistance of at given temperature.
|
||||
"""
|
||||
R = R_ref * (1 + alpha * (T - T_ref))
|
||||
return R
|
||||
return R_ref * (1 + alpha * (T - T_ref))
|
||||
|
||||
|
||||
def calculate_line_rating(n, cutout):
|
||||
@ -120,18 +119,17 @@ def calculate_line_rating(n, cutout):
|
||||
.apply(lambda x: int(re.findall(r"(\d+)-bundle", x)[0]))
|
||||
)
|
||||
# Set default number of bundles per line
|
||||
relevant_lines["n_bundle"].fillna(1, inplace=True)
|
||||
relevant_lines["n_bundle"] = relevant_lines["n_bundle"].fillna(1)
|
||||
R *= relevant_lines["n_bundle"]
|
||||
R = calculate_resistance(T=353, R_ref=R)
|
||||
Imax = cutout.line_rating(shapes, R, D=0.0218, Ts=353, epsilon=0.8, alpha=0.8)
|
||||
line_factor = relevant_lines.eval("v_nom * n_bundle * num_parallel") / 1e3 # in mW
|
||||
da = xr.DataArray(
|
||||
return xr.DataArray(
|
||||
data=np.sqrt(3) * Imax * line_factor.values.reshape(-1, 1),
|
||||
attrs=dict(
|
||||
description="Maximal possible power in MW for given line considering line rating"
|
||||
),
|
||||
)
|
||||
return da
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -146,8 +146,7 @@ if __name__ == "__main__":
|
||||
ppl, snakemake.input.custom_powerplants, custom_ppl_query
|
||||
)
|
||||
|
||||
countries_wo_ppl = set(countries) - set(ppl.Country.unique())
|
||||
if countries_wo_ppl:
|
||||
if countries_wo_ppl := set(countries) - set(ppl.Country.unique()):
|
||||
logging.warning(f"No powerplants known in: {', '.join(countries_wo_ppl)}")
|
||||
|
||||
substations = n.buses.query("substation_lv")
|
||||
|
@ -26,20 +26,9 @@ Relevant settings
|
||||
|
||||
renewable:
|
||||
{technology}:
|
||||
cutout:
|
||||
corine:
|
||||
grid_codes:
|
||||
distance:
|
||||
natura:
|
||||
max_depth:
|
||||
max_shore_distance:
|
||||
min_shore_distance:
|
||||
capacity_per_sqkm:
|
||||
correction_factor:
|
||||
potential:
|
||||
min_p_max_pu:
|
||||
clip_p_max_pu:
|
||||
resource:
|
||||
cutout: corine: grid_codes: distance: natura: max_depth:
|
||||
max_shore_distance: min_shore_distance: capacity_per_sqkm:
|
||||
correction_factor: min_p_max_pu: clip_p_max_pu: resource:
|
||||
|
||||
.. seealso::
|
||||
Documentation of the configuration file ``config/config.yaml`` at
|
||||
@ -48,21 +37,30 @@ Relevant settings
|
||||
Inputs
|
||||
------
|
||||
|
||||
- ``data/bundle/corine/g250_clc06_V18_5.tif``: `CORINE Land Cover (CLC) <https://land.copernicus.eu/pan-european/corine-land-cover>`_ inventory on `44 classes <https://wiki.openstreetmap.org/wiki/Corine_Land_Cover#Tagging>`_ of land use (e.g. forests, arable land, industrial, urban areas).
|
||||
- ``data/bundle/corine/g250_clc06_V18_5.tif``: `CORINE Land Cover (CLC)
|
||||
<https://land.copernicus.eu/pan-european/corine-land-cover>`_ inventory on `44
|
||||
classes <https://wiki.openstreetmap.org/wiki/Corine_Land_Cover#Tagging>`_ of
|
||||
land use (e.g. forests, arable land, industrial, urban areas).
|
||||
|
||||
.. image:: img/corine.png
|
||||
:scale: 33 %
|
||||
|
||||
- ``data/bundle/GEBCO_2014_2D.nc``: A `bathymetric <https://en.wikipedia.org/wiki/Bathymetry>`_ data set with a global terrain model for ocean and land at 15 arc-second intervals by the `General Bathymetric Chart of the Oceans (GEBCO) <https://www.gebco.net/data_and_products/gridded_bathymetry_data/>`_.
|
||||
- ``data/bundle/GEBCO_2014_2D.nc``: A `bathymetric
|
||||
<https://en.wikipedia.org/wiki/Bathymetry>`_ data set with a global terrain
|
||||
model for ocean and land at 15 arc-second intervals by the `General
|
||||
Bathymetric Chart of the Oceans (GEBCO)
|
||||
<https://www.gebco.net/data_and_products/gridded_bathymetry_data/>`_.
|
||||
|
||||
.. image:: img/gebco_2019_grid_image.jpg
|
||||
:scale: 50 %
|
||||
|
||||
**Source:** `GEBCO <https://www.gebco.net/data_and_products/images/gebco_2019_grid_image.jpg>`_
|
||||
**Source:** `GEBCO
|
||||
<https://www.gebco.net/data_and_products/images/gebco_2019_grid_image.jpg>`_
|
||||
|
||||
- ``resources/natura.tiff``: confer :ref:`natura`
|
||||
- ``resources/offshore_shapes.geojson``: confer :ref:`shapes`
|
||||
- ``resources/regions_onshore.geojson``: (if not offshore wind), confer :ref:`busregions`
|
||||
- ``resources/regions_onshore.geojson``: (if not offshore wind), confer
|
||||
:ref:`busregions`
|
||||
- ``resources/regions_offshore.geojson``: (if offshore wind), :ref:`busregions`
|
||||
- ``"cutouts/" + params["renewable"][{technology}]['cutout']``: :ref:`cutout`
|
||||
- ``networks/base.nc``: :ref:`base`
|
||||
@ -128,25 +126,25 @@ Description
|
||||
This script functions at two main spatial resolutions: the resolution of the
|
||||
network nodes and their `Voronoi cells
|
||||
<https://en.wikipedia.org/wiki/Voronoi_diagram>`_, and the resolution of the
|
||||
cutout grid cells for the weather data. Typically the weather data grid is
|
||||
finer than the network nodes, so we have to work out the distribution of
|
||||
generators across the grid cells within each Voronoi cell. This is done by
|
||||
taking account of a combination of the available land at each grid cell and the
|
||||
capacity factor there.
|
||||
cutout grid cells for the weather data. Typically the weather data grid is finer
|
||||
than the network nodes, so we have to work out the distribution of generators
|
||||
across the grid cells within each Voronoi cell. This is done by taking account
|
||||
of a combination of the available land at each grid cell and the capacity factor
|
||||
there.
|
||||
|
||||
First the script computes how much of the technology can be installed at each
|
||||
cutout grid cell and each node using the `GLAES
|
||||
<https://github.com/FZJ-IEK3-VSA/glaes>`_ library. This uses the CORINE land use data,
|
||||
Natura2000 nature reserves and GEBCO bathymetry data.
|
||||
<https://github.com/FZJ-IEK3-VSA/glaes>`_ library. This uses the CORINE land use
|
||||
data, Natura2000 nature reserves and GEBCO bathymetry data.
|
||||
|
||||
.. image:: img/eligibility.png
|
||||
:scale: 50 %
|
||||
:align: center
|
||||
|
||||
To compute the layout of generators in each node's Voronoi cell, the
|
||||
installable potential in each grid cell is multiplied with the capacity factor
|
||||
at each grid cell. This is done since we assume more generators are installed
|
||||
at cells with a higher capacity factor.
|
||||
To compute the layout of generators in each node's Voronoi cell, the installable
|
||||
potential in each grid cell is multiplied with the capacity factor at each grid
|
||||
cell. This is done since we assume more generators are installed at cells with a
|
||||
higher capacity factor.
|
||||
|
||||
.. image:: img/offwinddc-gridcell.png
|
||||
:scale: 50 %
|
||||
@ -164,20 +162,14 @@ at cells with a higher capacity factor.
|
||||
:scale: 50 %
|
||||
:align: center
|
||||
|
||||
This layout is then used to compute the generation availability time series
|
||||
from the weather data cutout from ``atlite``.
|
||||
This layout is then used to compute the generation availability time series from
|
||||
the weather data cutout from ``atlite``.
|
||||
|
||||
Two methods are available to compute the maximal installable potential for the
|
||||
node (`p_nom_max`): ``simple`` and ``conservative``:
|
||||
|
||||
- ``simple`` adds up the installable potentials of the individual grid cells.
|
||||
If the model comes close to this limit, then the time series may slightly
|
||||
overestimate production since it is assumed the geographical distribution is
|
||||
proportional to capacity factor.
|
||||
|
||||
- ``conservative`` assertains the nodal limit by increasing capacities
|
||||
proportional to the layout until the limit of an individual grid cell is
|
||||
reached.
|
||||
The maximal installable potential for the node (`p_nom_max`) is computed by
|
||||
adding up the installable potentials of the individual grid cells.
|
||||
If the model comes close to this limit, then the time series may slightly
|
||||
overestimate production since it is assumed the geographical distribution is
|
||||
proportional to capacity factor.
|
||||
"""
|
||||
import functools
|
||||
import logging
|
||||
@ -212,7 +204,6 @@ if __name__ == "__main__":
|
||||
resource = params["resource"] # pv panel params / wind turbine params
|
||||
correction_factor = params.get("correction_factor", 1.0)
|
||||
capacity_per_sqkm = params["capacity_per_sqkm"]
|
||||
p_nom_max_meth = params.get("potential", "conservative")
|
||||
|
||||
if isinstance(params.get("corine", {}), list):
|
||||
params["corine"] = {"grid_codes": params["corine"]}
|
||||
@ -253,7 +244,7 @@ if __name__ == "__main__":
|
||||
snakemake.input.corine, codes=codes, buffer=buffer, crs=3035
|
||||
)
|
||||
|
||||
if "ship_threshold" in params:
|
||||
if params.get("ship_threshold"):
|
||||
shipping_threshold = (
|
||||
params["ship_threshold"] * 8760 * 6
|
||||
) # approximation because 6 years of data which is hourly collected
|
||||
@ -279,15 +270,22 @@ if __name__ == "__main__":
|
||||
snakemake.input.country_shapes, buffer=buffer, invert=True
|
||||
)
|
||||
|
||||
logger.info("Calculate landuse availability...")
|
||||
start = time.time()
|
||||
|
||||
kwargs = dict(nprocesses=nprocesses, disable_progressbar=noprogress)
|
||||
if noprogress:
|
||||
logger.info("Calculate landuse availabilities...")
|
||||
start = time.time()
|
||||
availability = cutout.availabilitymatrix(regions, excluder, **kwargs)
|
||||
duration = time.time() - start
|
||||
logger.info(f"Completed availability calculation ({duration:2.2f}s)")
|
||||
else:
|
||||
availability = cutout.availabilitymatrix(regions, excluder, **kwargs)
|
||||
availability = cutout.availabilitymatrix(regions, excluder, **kwargs)
|
||||
|
||||
duration = time.time() - start
|
||||
logger.info(f"Completed landuse availability calculation ({duration:2.2f}s)")
|
||||
|
||||
# For Moldova and Ukraine: Overwrite parts not covered by Corine with
|
||||
# externally determined available areas
|
||||
if "availability_matrix_MD_UA" in snakemake.input.keys():
|
||||
availability_MDUA = xr.open_dataarray(
|
||||
snakemake.input["availability_matrix_MD_UA"]
|
||||
)
|
||||
availability.loc[availability_MDUA.coords] = availability_MDUA
|
||||
|
||||
area = cutout.grid.to_crs(3035).area / 1e6
|
||||
area = xr.DataArray(
|
||||
@ -298,8 +296,19 @@ if __name__ == "__main__":
|
||||
func = getattr(cutout, resource.pop("method"))
|
||||
if client is not None:
|
||||
resource["dask_kwargs"] = {"scheduler": client}
|
||||
|
||||
logger.info("Calculate average capacity factor...")
|
||||
start = time.time()
|
||||
|
||||
capacity_factor = correction_factor * func(capacity_factor=True, **resource)
|
||||
layout = capacity_factor * area * capacity_per_sqkm
|
||||
|
||||
duration = time.time() - start
|
||||
logger.info(f"Completed average capacity factor calculation ({duration:2.2f}s)")
|
||||
|
||||
logger.info("Calculate weighted capacity factor time series...")
|
||||
start = time.time()
|
||||
|
||||
profile, capacities = func(
|
||||
matrix=availability.stack(spatial=["y", "x"]),
|
||||
layout=layout,
|
||||
@ -309,17 +318,13 @@ if __name__ == "__main__":
|
||||
**resource,
|
||||
)
|
||||
|
||||
logger.info(f"Calculating maximal capacity per bus (method '{p_nom_max_meth}')")
|
||||
if p_nom_max_meth == "simple":
|
||||
p_nom_max = capacity_per_sqkm * availability @ area
|
||||
elif p_nom_max_meth == "conservative":
|
||||
max_cap_factor = capacity_factor.where(availability != 0).max(["x", "y"])
|
||||
p_nom_max = capacities / max_cap_factor
|
||||
else:
|
||||
raise AssertionError(
|
||||
'Config key `potential` should be one of "simple" '
|
||||
f'(default) or "conservative", not "{p_nom_max_meth}"'
|
||||
)
|
||||
duration = time.time() - start
|
||||
logger.info(
|
||||
f"Completed weighted capacity factor time series calculation ({duration:2.2f}s)"
|
||||
)
|
||||
|
||||
logger.info(f"Calculating maximal capacity per bus")
|
||||
p_nom_max = capacity_per_sqkm * availability @ area
|
||||
|
||||
logger.info("Calculate average distances.")
|
||||
layoutmatrix = (layout * availability).stack(spatial=["y", "x"])
|
||||
|
@ -102,7 +102,7 @@ solar_energy_transmittance = (
|
||||
)
|
||||
# solar global radiation [kWh/(m^2a)]
|
||||
solar_global_radiation = pd.Series(
|
||||
[246, 401, 246, 148],
|
||||
[271, 392, 271, 160],
|
||||
index=["east", "south", "west", "north"],
|
||||
name="solar_global_radiation [kWh/(m^2a)]",
|
||||
)
|
||||
@ -164,6 +164,12 @@ def prepare_building_stock_data():
|
||||
},
|
||||
inplace=True,
|
||||
)
|
||||
building_data["feature"].replace(
|
||||
{
|
||||
"Construction features (U-value)": "Construction features (U-values)",
|
||||
},
|
||||
inplace=True,
|
||||
)
|
||||
|
||||
building_data.country_code = building_data.country_code.str.upper()
|
||||
building_data["subsector"].replace(
|
||||
@ -198,12 +204,14 @@ def prepare_building_stock_data():
|
||||
}
|
||||
)
|
||||
|
||||
building_data["country_code"] = building_data["country"].map(country_iso_dic)
|
||||
|
||||
# heated floor area ----------------------------------------------------------
|
||||
area = building_data[
|
||||
(building_data.type == "Heated area [Mm²]")
|
||||
& (building_data.subsector != "Total")
|
||||
]
|
||||
area_tot = area.groupby(["country", "sector"]).sum()
|
||||
area_tot = area[["country", "sector", "value"]].groupby(["country", "sector"]).sum()
|
||||
area = pd.concat(
|
||||
[
|
||||
area,
|
||||
@ -223,7 +231,7 @@ def prepare_building_stock_data():
|
||||
usecols=[0, 1, 2, 3],
|
||||
encoding="ISO-8859-1",
|
||||
)
|
||||
area_tot = area_tot.append(area_missing.unstack(level=-1).dropna().stack())
|
||||
area_tot = pd.concat([area_tot, area_missing.unstack(level=-1).dropna().stack()])
|
||||
area_tot = area_tot.loc[~area_tot.index.duplicated(keep="last")]
|
||||
|
||||
# for still missing countries calculate floor area by population size
|
||||
@ -246,7 +254,7 @@ def prepare_building_stock_data():
|
||||
averaged_data.index = index
|
||||
averaged_data["estimated"] = 1
|
||||
if ct not in area_tot.index.levels[0]:
|
||||
area_tot = area_tot.append(averaged_data, sort=True)
|
||||
area_tot = pd.concat([area_tot, averaged_data], sort=True)
|
||||
else:
|
||||
area_tot.loc[averaged_data.index] = averaged_data
|
||||
|
||||
@ -272,7 +280,7 @@ def prepare_building_stock_data():
|
||||
][x["bage"]].iloc[0],
|
||||
axis=1,
|
||||
)
|
||||
data_PL_final = data_PL_final.append(data_PL)
|
||||
data_PL_final = pd.concat([data_PL_final, data_PL])
|
||||
|
||||
u_values = pd.concat([u_values, data_PL_final]).reset_index(drop=True)
|
||||
|
||||
@ -609,12 +617,11 @@ def calculate_costs(u_values, l, cost_retro, window_assumptions):
|
||||
/ x.A_C_Ref
|
||||
if x.name[3] != "Window"
|
||||
else (
|
||||
window_cost(x["new_U_{}".format(l)], cost_retro, window_assumptions)
|
||||
* x.A_element
|
||||
(window_cost(x[f"new_U_{l}"], cost_retro, window_assumptions) * x.A_element)
|
||||
/ x.A_C_Ref
|
||||
if x.value > window_limit(float(l), window_assumptions)
|
||||
else 0
|
||||
),
|
||||
)
|
||||
if x.value > window_limit(float(l), window_assumptions)
|
||||
else 0,
|
||||
axis=1,
|
||||
)
|
||||
|
||||
@ -739,12 +746,12 @@ def calculate_heat_losses(u_values, data_tabula, l_strength, temperature_factor)
|
||||
# (1) by transmission
|
||||
# calculate new U values of building elements due to additional insulation
|
||||
for l in l_strength:
|
||||
u_values["new_U_{}".format(l)] = calculate_new_u(
|
||||
u_values[f"new_U_{l}"] = calculate_new_u(
|
||||
u_values, l, l_weight, window_assumptions
|
||||
)
|
||||
# surface area of building components [m^2]
|
||||
area_element = (
|
||||
data_tabula[["A_{}".format(e) for e in u_values.index.levels[3]]]
|
||||
data_tabula[[f"A_{e}" for e in u_values.index.levels[3]]]
|
||||
.rename(columns=lambda x: x[2:])
|
||||
.stack()
|
||||
.unstack(-2)
|
||||
@ -756,7 +763,7 @@ def calculate_heat_losses(u_values, data_tabula, l_strength, temperature_factor)
|
||||
|
||||
# heat transfer H_tr_e [W/m^2K] through building element
|
||||
# U_e * A_e / A_C_Ref
|
||||
columns = ["value"] + ["new_U_{}".format(l) for l in l_strength]
|
||||
columns = ["value"] + [f"new_U_{l}" for l in l_strength]
|
||||
heat_transfer = pd.concat(
|
||||
[u_values[columns].mul(u_values.A_element, axis=0), u_values.A_element], axis=1
|
||||
)
|
||||
@ -829,9 +836,9 @@ def calculate_heat_losses(u_values, data_tabula, l_strength, temperature_factor)
|
||||
F_red_temp = map_to_lstrength(l_strength, F_red_temp)
|
||||
|
||||
Q_ht = (
|
||||
heat_transfer_perm2.groupby(level=1, axis=1)
|
||||
heat_transfer_perm2.T.groupby(level=1)
|
||||
.sum()
|
||||
.mul(F_red_temp.droplevel(0, axis=1))
|
||||
.T.mul(F_red_temp.droplevel(0, axis=1))
|
||||
.mul(temperature_factor.reindex(heat_transfer_perm2.index, level=0), axis=0)
|
||||
)
|
||||
|
||||
@ -871,14 +878,11 @@ def calculate_gain_utilisation_factor(heat_transfer_perm2, Q_ht, Q_gain):
|
||||
Calculates gain utilisation factor nu.
|
||||
"""
|
||||
# time constant of the building tau [h] = c_m [Wh/(m^2K)] * 1 /(H_tr_e+H_tb*H_ve) [m^2 K /W]
|
||||
tau = c_m / heat_transfer_perm2.groupby(level=1, axis=1).sum()
|
||||
tau = c_m / heat_transfer_perm2.T.groupby(axis=1).sum().T
|
||||
alpha = alpha_H_0 + (tau / tau_H_0)
|
||||
# heat balance ratio
|
||||
gamma = (1 / Q_ht).mul(Q_gain.sum(axis=1), axis=0)
|
||||
# gain utilisation factor
|
||||
nu = (1 - gamma**alpha) / (1 - gamma ** (alpha + 1))
|
||||
|
||||
return nu
|
||||
return (1 - gamma**alpha) / (1 - gamma ** (alpha + 1))
|
||||
|
||||
|
||||
def calculate_space_heat_savings(
|
||||
@ -947,7 +951,8 @@ def sample_dE_costs_area(
|
||||
.rename(index=rename_sectors, level=2)
|
||||
.reset_index()
|
||||
)
|
||||
.rename(columns={"country": "country_code"})
|
||||
# if uncommented, leads to the second `country_code` column
|
||||
# .rename(columns={"country": "country_code"})
|
||||
.set_index(["country_code", "subsector", "bage"])
|
||||
)
|
||||
|
||||
@ -960,13 +965,14 @@ def sample_dE_costs_area(
|
||||
)
|
||||
|
||||
# map missing countries
|
||||
for ct in countries.difference(cost_dE.index.levels[0]):
|
||||
for ct in set(countries).difference(cost_dE.index.levels[0]):
|
||||
averaged_data = (
|
||||
cost_dE.reindex(index=map_for_missings[ct], level=0)
|
||||
.mean(level=1)
|
||||
.groupby(level=1)
|
||||
.mean()
|
||||
.set_index(pd.MultiIndex.from_product([[ct], cost_dE.index.levels[1]]))
|
||||
)
|
||||
cost_dE = cost_dE.append(averaged_data)
|
||||
cost_dE = pd.concat([cost_dE, averaged_data])
|
||||
|
||||
# weights costs after construction index
|
||||
if construction_index:
|
||||
@ -983,24 +989,23 @@ def sample_dE_costs_area(
|
||||
# drop not considered countries
|
||||
cost_dE = cost_dE.reindex(countries, level=0)
|
||||
# get share of residential and service floor area
|
||||
sec_w = area_tot.value / area_tot.value.groupby(level=0).sum()
|
||||
sec_w = area_tot.div(area_tot.groupby(level=0).transform("sum"))
|
||||
# get the total cost-energy-savings weight by sector area
|
||||
tot = (
|
||||
cost_dE.mul(sec_w, axis=0)
|
||||
.groupby(level="country_code")
|
||||
# sec_w has columns "estimated" and "value"
|
||||
cost_dE.mul(sec_w.value, axis=0)
|
||||
# for some reasons names of the levels were lost somewhere
|
||||
# .groupby(level="country_code")
|
||||
.groupby(level=0)
|
||||
.sum()
|
||||
.set_index(
|
||||
pd.MultiIndex.from_product(
|
||||
[cost_dE.index.unique(level="country_code"), ["tot"]]
|
||||
)
|
||||
)
|
||||
.set_index(pd.MultiIndex.from_product([cost_dE.index.unique(level=0), ["tot"]]))
|
||||
)
|
||||
cost_dE = cost_dE.append(tot).unstack().stack()
|
||||
cost_dE = pd.concat([cost_dE, tot]).unstack().stack()
|
||||
|
||||
summed_area = pd.DataFrame(area_tot.groupby("country").sum()).set_index(
|
||||
pd.MultiIndex.from_product([area_tot.index.unique(level="country"), ["tot"]])
|
||||
summed_area = pd.DataFrame(area_tot.groupby(level=0).sum()).set_index(
|
||||
pd.MultiIndex.from_product([area_tot.index.unique(level=0), ["tot"]])
|
||||
)
|
||||
area_tot = area_tot.append(summed_area).unstack().stack()
|
||||
area_tot = pd.concat([area_tot, summed_area]).unstack().stack()
|
||||
|
||||
cost_per_saving = cost_dE["cost"] / (
|
||||
1 - cost_dE["dE"]
|
||||
|
@ -66,11 +66,7 @@ def salt_cavern_potential_by_region(caverns, regions):
|
||||
"capacity_per_area * share * area_caverns / 1000"
|
||||
) # TWh
|
||||
|
||||
caverns_regions = (
|
||||
overlay.groupby(["name", "storage_type"]).e_nom.sum().unstack("storage_type")
|
||||
)
|
||||
|
||||
return caverns_regions
|
||||
return overlay.groupby(["name", "storage_type"]).e_nom.sum().unstack("storage_type")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -119,7 +119,7 @@ def countries(naturalearth, country_list):
|
||||
fieldnames = (
|
||||
df[x].where(lambda s: s != "-99") for x in ("ISO_A2", "WB_A2", "ADM0_A3")
|
||||
)
|
||||
df["name"] = reduce(lambda x, y: x.fillna(y), fieldnames, next(fieldnames)).str[0:2]
|
||||
df["name"] = reduce(lambda x, y: x.fillna(y), fieldnames, next(fieldnames)).str[:2]
|
||||
|
||||
df = df.loc[
|
||||
df.name.isin(country_list) & ((df["scalerank"] == 0) | (df["scalerank"] == 5))
|
||||
@ -174,8 +174,8 @@ def nuts3(country_shapes, nuts3, nuts3pop, nuts3gdp, ch_cantons, ch_popgdp):
|
||||
pd.MultiIndex.from_tuples(pop.pop("unit,geo\\time").str.split(","))
|
||||
)
|
||||
.loc["THS"]
|
||||
.applymap(lambda x: pd.to_numeric(x, errors="coerce"))
|
||||
.fillna(method="bfill", axis=1)
|
||||
.map(lambda x: pd.to_numeric(x, errors="coerce"))
|
||||
.bfill(axis=1)
|
||||
)["2014"]
|
||||
|
||||
gdp = pd.read_table(nuts3gdp, na_values=[":"], delimiter=" ?\t", engine="python")
|
||||
@ -184,8 +184,8 @@ def nuts3(country_shapes, nuts3, nuts3pop, nuts3gdp, ch_cantons, ch_popgdp):
|
||||
pd.MultiIndex.from_tuples(gdp.pop("unit,geo\\time").str.split(","))
|
||||
)
|
||||
.loc["EUR_HAB"]
|
||||
.applymap(lambda x: pd.to_numeric(x, errors="coerce"))
|
||||
.fillna(method="bfill", axis=1)
|
||||
.map(lambda x: pd.to_numeric(x, errors="coerce"))
|
||||
.bfill(axis=1)
|
||||
)["2014"]
|
||||
|
||||
cantons = pd.read_csv(ch_cantons)
|
||||
|
@ -64,7 +64,7 @@ if __name__ == "__main__":
|
||||
with zipfile.ZipFile(snakemake.input.ship_density) as zip_f:
|
||||
zip_f.extract("shipdensity_global.tif")
|
||||
with rioxarray.open_rasterio("shipdensity_global.tif") as ship_density:
|
||||
ship_density = ship_density.drop(["band"]).sel(
|
||||
ship_density = ship_density.drop_vars(["band"]).sel(
|
||||
x=slice(min(xs), max(Xs)), y=slice(max(Ys), min(ys))
|
||||
)
|
||||
ship_density.rio.to_raster(snakemake.output[0])
|
||||
|
@ -46,10 +46,7 @@ if __name__ == "__main__":
|
||||
cutout = atlite.Cutout(cutout_name).sel(time=time)
|
||||
|
||||
clustered_regions = (
|
||||
gpd.read_file(snakemake.input.regions_onshore)
|
||||
.set_index("name")
|
||||
.buffer(0)
|
||||
.squeeze()
|
||||
gpd.read_file(snakemake.input.regions_onshore).set_index("name").buffer(0)
|
||||
)
|
||||
|
||||
I = cutout.indicatormatrix(clustered_regions)
|
||||
|
@ -43,10 +43,7 @@ if __name__ == "__main__":
|
||||
cutout = atlite.Cutout(cutout_name).sel(time=time)
|
||||
|
||||
clustered_regions = (
|
||||
gpd.read_file(snakemake.input.regions_onshore)
|
||||
.set_index("name")
|
||||
.buffer(0)
|
||||
.squeeze()
|
||||
gpd.read_file(snakemake.input.regions_onshore).set_index("name").buffer(0)
|
||||
)
|
||||
|
||||
I = cutout.indicatormatrix(clustered_regions)
|
||||
|
@ -81,14 +81,12 @@ def build_transport_demand(traffic_fn, airtemp_fn, nodes, nodal_transport_data):
|
||||
- pop_weighted_energy_totals["electricity rail"]
|
||||
)
|
||||
|
||||
transport = (
|
||||
return (
|
||||
(transport_shape.multiply(energy_totals_transport) * 1e6 * nyears)
|
||||
.divide(efficiency_gain * ice_correction)
|
||||
.multiply(1 + dd_EV)
|
||||
)
|
||||
|
||||
return transport
|
||||
|
||||
|
||||
def transport_degree_factor(
|
||||
temperature,
|
||||
@ -132,14 +130,12 @@ def bev_availability_profile(fn, snapshots, nodes, options):
|
||||
traffic.mean() - traffic.min()
|
||||
)
|
||||
|
||||
avail_profile = generate_periodic_profiles(
|
||||
return generate_periodic_profiles(
|
||||
dt_index=snapshots,
|
||||
nodes=nodes,
|
||||
weekly_profile=avail.values,
|
||||
)
|
||||
|
||||
return avail_profile
|
||||
|
||||
|
||||
def bev_dsm_profile(snapshots, nodes, options):
|
||||
dsm_week = np.zeros((24 * 7,))
|
||||
@ -148,14 +144,12 @@ def bev_dsm_profile(snapshots, nodes, options):
|
||||
"bev_dsm_restriction_value"
|
||||
]
|
||||
|
||||
dsm_profile = generate_periodic_profiles(
|
||||
return generate_periodic_profiles(
|
||||
dt_index=snapshots,
|
||||
nodes=nodes,
|
||||
weekly_profile=dsm_week,
|
||||
)
|
||||
|
||||
return dsm_profile
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
|
@ -16,8 +16,7 @@ Relevant Settings
|
||||
clustering:
|
||||
cluster_network:
|
||||
aggregation_strategies:
|
||||
|
||||
focus_weights:
|
||||
focus_weights:
|
||||
|
||||
solving:
|
||||
solver:
|
||||
@ -237,7 +236,7 @@ def distribute_clusters(n, n_clusters, focus_weights=None, solver_name="cbc"):
|
||||
n_clusters >= len(N) and n_clusters <= N.sum()
|
||||
), f"Number of clusters must be {len(N)} <= n_clusters <= {N.sum()} for this selection of countries."
|
||||
|
||||
if focus_weights is not None:
|
||||
if isinstance(focus_weights, dict):
|
||||
total_focus = sum(list(focus_weights.values()))
|
||||
|
||||
assert (
|
||||
@ -271,7 +270,7 @@ def distribute_clusters(n, n_clusters, focus_weights=None, solver_name="cbc"):
|
||||
)
|
||||
|
||||
opt = po.SolverFactory(solver_name)
|
||||
if not opt.has_capability("quadratic_objective"):
|
||||
if solver_name == "appsi_highs" or not opt.has_capability("quadratic_objective"):
|
||||
logger.warning(
|
||||
f"The configured solver `{solver_name}` does not support quadratic objectives. Falling back to `ipopt`."
|
||||
)
|
||||
@ -322,9 +321,9 @@ def busmap_for_n_clusters(
|
||||
neighbor_bus = n.lines.query(
|
||||
"bus0 == @disconnected_bus or bus1 == @disconnected_bus"
|
||||
).iloc[0][["bus0", "bus1"]]
|
||||
new_country = list(
|
||||
set(n.buses.loc[neighbor_bus].country) - set([country])
|
||||
)[0]
|
||||
new_country = list(set(n.buses.loc[neighbor_bus].country) - {country})[
|
||||
0
|
||||
]
|
||||
|
||||
logger.info(
|
||||
f"overwriting country `{country}` of bus `{disconnected_bus}` "
|
||||
@ -468,9 +467,13 @@ if __name__ == "__main__":
|
||||
|
||||
params = snakemake.params
|
||||
solver_name = snakemake.config["solving"]["solver"]["name"]
|
||||
solver_name = "appsi_highs" if solver_name == "highs" else solver_name
|
||||
|
||||
n = pypsa.Network(snakemake.input.network)
|
||||
|
||||
# remove integer outputs for compatibility with PyPSA v0.26.0
|
||||
n.generators.drop("n_mod", axis=1, inplace=True, errors="ignore")
|
||||
|
||||
exclude_carriers = params.cluster_network["exclude_carriers"]
|
||||
aggregate_carriers = set(n.generators.carrier) - set(exclude_carriers)
|
||||
conventional_carriers = set(params.conventional_carriers)
|
||||
|
156
scripts/determine_availability_matrix_MD_UA.py
Normal file
156
scripts/determine_availability_matrix_MD_UA.py
Normal file
@ -0,0 +1,156 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import functools
|
||||
import logging
|
||||
import time
|
||||
|
||||
import atlite
|
||||
import fiona
|
||||
import geopandas as gpd
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from _helpers import configure_logging
|
||||
from atlite.gis import shape_availability
|
||||
from rasterio.plot import show
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_wdpa_layer_name(wdpa_fn, layer_substring):
|
||||
"""
|
||||
Get layername from file "wdpa_fn" whose name contains "layer_substring".
|
||||
"""
|
||||
l = fiona.listlayers(wdpa_fn)
|
||||
return [_ for _ in l if layer_substring in _][0]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
|
||||
snakemake = mock_snakemake(
|
||||
"determine_availability_matrix_MD_UA", technology="solar"
|
||||
)
|
||||
configure_logging(snakemake)
|
||||
|
||||
nprocesses = None # snakemake.config["atlite"].get("nprocesses")
|
||||
noprogress = not snakemake.config["atlite"].get("show_progress", True)
|
||||
config = snakemake.config["renewable"][snakemake.wildcards.technology]
|
||||
|
||||
cutout = atlite.Cutout(snakemake.input.cutout)
|
||||
regions = (
|
||||
gpd.read_file(snakemake.input.regions).set_index("name").rename_axis("bus")
|
||||
)
|
||||
buses = regions.index
|
||||
|
||||
excluder = atlite.ExclusionContainer(crs=3035, res=100)
|
||||
|
||||
corine = config.get("corine", {})
|
||||
if "grid_codes" in corine:
|
||||
# Land cover codes to emulate CORINE results
|
||||
if snakemake.wildcards.technology == "solar":
|
||||
codes = [20, 30, 40, 50, 60, 90, 100]
|
||||
elif snakemake.wildcards.technology == "onwind":
|
||||
codes = [20, 30, 40, 60, 100]
|
||||
elif snakemake.wildcards.technology == "offwind-ac":
|
||||
codes = [80, 200]
|
||||
elif snakemake.wildcards.technology == "offwind-dc":
|
||||
codes = [80, 200]
|
||||
else:
|
||||
assert False, "technology not supported"
|
||||
|
||||
excluder.add_raster(
|
||||
snakemake.input.copernicus, codes=codes, invert=True, crs="EPSG:4326"
|
||||
)
|
||||
if "distance" in corine and corine.get("distance", 0.0) > 0.0:
|
||||
# Land cover codes to emulate CORINE results
|
||||
if snakemake.wildcards.technology == "onwind":
|
||||
codes = [50]
|
||||
else:
|
||||
assert False, "technology not supported"
|
||||
|
||||
buffer = corine["distance"]
|
||||
excluder.add_raster(
|
||||
snakemake.input.copernicus, codes=codes, buffer=buffer, crs="EPSG:4326"
|
||||
)
|
||||
|
||||
if config["natura"]:
|
||||
wdpa_fn = (
|
||||
snakemake.input.wdpa_marine
|
||||
if "offwind" in snakemake.wildcards.technology
|
||||
else snakemake.input.wdpa
|
||||
)
|
||||
layer = get_wdpa_layer_name(wdpa_fn, "polygons")
|
||||
wdpa = gpd.read_file(
|
||||
wdpa_fn,
|
||||
bbox=regions.geometry,
|
||||
layer=layer,
|
||||
).to_crs(3035)
|
||||
if not wdpa.empty:
|
||||
excluder.add_geometry(wdpa.geometry)
|
||||
|
||||
layer = get_wdpa_layer_name(wdpa_fn, "points")
|
||||
wdpa_pts = gpd.read_file(
|
||||
wdpa_fn,
|
||||
bbox=regions.geometry,
|
||||
layer=layer,
|
||||
).to_crs(3035)
|
||||
wdpa_pts = wdpa_pts[wdpa_pts["REP_AREA"] > 1]
|
||||
wdpa_pts["buffer_radius"] = np.sqrt(wdpa_pts["REP_AREA"] / np.pi) * 1000
|
||||
wdpa_pts = wdpa_pts.set_geometry(
|
||||
wdpa_pts["geometry"].buffer(wdpa_pts["buffer_radius"])
|
||||
)
|
||||
if not wdpa_pts.empty:
|
||||
excluder.add_geometry(wdpa_pts.geometry)
|
||||
|
||||
if "max_depth" in config:
|
||||
# lambda not supported for atlite + multiprocessing
|
||||
# use named function np.greater with partially frozen argument instead
|
||||
# and exclude areas where: -max_depth > grid cell depth
|
||||
func = functools.partial(np.greater, -config["max_depth"])
|
||||
excluder.add_raster(snakemake.input.gebco, codes=func, crs=4236, nodata=-1000)
|
||||
|
||||
if "min_shore_distance" in config:
|
||||
buffer = config["min_shore_distance"]
|
||||
excluder.add_geometry(snakemake.input.country_shapes, buffer=buffer)
|
||||
|
||||
if "max_shore_distance" in config:
|
||||
buffer = config["max_shore_distance"]
|
||||
excluder.add_geometry(
|
||||
snakemake.input.country_shapes, buffer=buffer, invert=True
|
||||
)
|
||||
|
||||
if "ship_threshold" in config:
|
||||
shipping_threshold = config["ship_threshold"] * 8760 * 6
|
||||
func = functools.partial(np.less, shipping_threshold)
|
||||
excluder.add_raster(
|
||||
snakemake.input.ship_density, codes=func, crs=4326, allow_no_overlap=True
|
||||
)
|
||||
|
||||
kwargs = dict(nprocesses=nprocesses, disable_progressbar=noprogress)
|
||||
if noprogress:
|
||||
logger.info("Calculate landuse availabilities...")
|
||||
start = time.time()
|
||||
availability = cutout.availabilitymatrix(regions, excluder, **kwargs)
|
||||
duration = time.time() - start
|
||||
logger.info(f"Completed availability calculation ({duration:2.2f}s)")
|
||||
else:
|
||||
availability = cutout.availabilitymatrix(regions, excluder, **kwargs)
|
||||
|
||||
regions_geometry = regions.to_crs(3035).geometry
|
||||
band, transform = shape_availability(regions_geometry, excluder)
|
||||
fig, ax = plt.subplots(figsize=(4, 8))
|
||||
gpd.GeoSeries(regions_geometry.unary_union).plot(ax=ax, color="none")
|
||||
show(band, transform=transform, cmap="Greens", ax=ax)
|
||||
plt.axis("off")
|
||||
plt.savefig(snakemake.output.availability_map, bbox_inches="tight", dpi=500)
|
||||
|
||||
# Limit results only to buses for UA and MD
|
||||
buses = regions.loc[regions["country"].isin(["UA", "MD"])].index.values
|
||||
availability = availability.sel(bus=buses)
|
||||
|
||||
# Save and plot for verification
|
||||
availability.to_netcdf(snakemake.output.availability_matrix)
|
@ -33,10 +33,7 @@ def assign_locations(n):
|
||||
ifind = pd.Series(c.df.index.str.find(" ", start=4), c.df.index)
|
||||
for i in ifind.unique():
|
||||
names = ifind.index[ifind == i]
|
||||
if i == -1:
|
||||
c.df.loc[names, "location"] = ""
|
||||
else:
|
||||
c.df.loc[names, "location"] = names.str[:i]
|
||||
c.df.loc[names, "location"] = "" if i == -1 else names.str[:i]
|
||||
|
||||
|
||||
def calculate_nodal_cfs(n, label, nodal_cfs):
|
||||
@ -397,7 +394,7 @@ def calculate_supply_energy(n, label, supply_energy):
|
||||
|
||||
for c in n.iterate_components(n.branch_components):
|
||||
for end in [col[3:] for col in c.df.columns if col[:3] == "bus"]:
|
||||
items = c.df.index[c.df["bus" + str(end)].map(bus_map).fillna(False)]
|
||||
items = c.df.index[c.df[f"bus{str(end)}"].map(bus_map).fillna(False)]
|
||||
|
||||
if len(items) == 0:
|
||||
continue
|
||||
@ -449,6 +446,10 @@ def calculate_metrics(n, label, metrics):
|
||||
if "CO2Limit" in n.global_constraints.index:
|
||||
metrics.at["co2_shadow", label] = n.global_constraints.at["CO2Limit", "mu"]
|
||||
|
||||
if "co2_sequestration_limit" in n.global_constraints.index:
|
||||
metrics.at["co2_storage_shadow", label] = n.global_constraints.at[
|
||||
"co2_sequestration_limit", "mu"
|
||||
]
|
||||
return metrics
|
||||
|
||||
|
||||
@ -493,7 +494,7 @@ def calculate_weighted_prices(n, label, weighted_prices):
|
||||
"H2": ["Sabatier", "H2 Fuel Cell"],
|
||||
}
|
||||
|
||||
for carrier in link_loads:
|
||||
for carrier, value in link_loads.items():
|
||||
if carrier == "electricity":
|
||||
suffix = ""
|
||||
elif carrier[:5] == "space":
|
||||
@ -515,15 +516,15 @@ def calculate_weighted_prices(n, label, weighted_prices):
|
||||
else:
|
||||
load = n.loads_t.p_set[buses]
|
||||
|
||||
for tech in link_loads[carrier]:
|
||||
for tech in value:
|
||||
names = n.links.index[n.links.index.to_series().str[-len(tech) :] == tech]
|
||||
|
||||
if names.empty:
|
||||
continue
|
||||
|
||||
load += (
|
||||
n.links_t.p0[names].groupby(n.links.loc[names, "bus0"], axis=1).sum()
|
||||
)
|
||||
if not names.empty:
|
||||
load += (
|
||||
n.links_t.p0[names]
|
||||
.groupby(n.links.loc[names, "bus0"], axis=1)
|
||||
.sum()
|
||||
)
|
||||
|
||||
# Add H2 Store when charging
|
||||
# if carrier == "H2":
|
||||
@ -651,11 +652,7 @@ def make_summaries(networks_dict):
|
||||
names=["weather_year", "cluster", "ll", "opt", "planning_horizon"],
|
||||
)
|
||||
|
||||
df = {}
|
||||
|
||||
for output in outputs:
|
||||
df[output] = pd.DataFrame(columns=columns, dtype=float)
|
||||
|
||||
df = {output: pd.DataFrame(columns=columns, dtype=float) for output in outputs}
|
||||
for label, filename in networks_dict.items():
|
||||
logger.info(f"Make summary for scenario {label}, using {filename}")
|
||||
|
||||
|
@ -28,6 +28,16 @@ idx = pd.IndexSlice
|
||||
opt_name = {"Store": "e", "Line": "s", "Transformer": "s"}
|
||||
|
||||
|
||||
def reindex_columns(df, cols):
|
||||
investments = cols.levels[3]
|
||||
if len(cols.names) != len(df.columns.levels):
|
||||
df = pd.concat([df] * len(investments), axis=1)
|
||||
df.columns = cols
|
||||
df = df.reindex(cols, axis=1)
|
||||
|
||||
return df
|
||||
|
||||
|
||||
def calculate_costs(n, label, costs):
|
||||
investments = n.investment_periods
|
||||
cols = pd.MultiIndex.from_product(
|
||||
@ -39,7 +49,8 @@ def calculate_costs(n, label, costs):
|
||||
],
|
||||
names=costs.columns.names[:3] + ["year"],
|
||||
)
|
||||
costs = costs.reindex(cols, axis=1)
|
||||
|
||||
costs = reindex_columns(costs, cols)
|
||||
|
||||
for c in n.iterate_components(
|
||||
n.branch_components | n.controllable_one_port_components ^ {"Load"}
|
||||
@ -176,7 +187,7 @@ def calculate_capacities(n, label, capacities):
|
||||
],
|
||||
names=capacities.columns.names[:3] + ["year"],
|
||||
)
|
||||
capacities = capacities.reindex(cols, axis=1)
|
||||
capacities = reindex_columns(capacities, cols)
|
||||
|
||||
for c in n.iterate_components(
|
||||
n.branch_components | n.controllable_one_port_components ^ {"Load"}
|
||||
@ -229,7 +240,7 @@ def calculate_energy(n, label, energy):
|
||||
],
|
||||
names=energy.columns.names[:3] + ["year"],
|
||||
)
|
||||
energy = energy.reindex(cols, axis=1)
|
||||
energy = reindex_columns(energy, cols)
|
||||
|
||||
for c in n.iterate_components(n.one_port_components | n.branch_components):
|
||||
if c.name in n.one_port_components:
|
||||
@ -336,7 +347,7 @@ def calculate_supply_energy(n, label, supply_energy):
|
||||
],
|
||||
names=supply_energy.columns.names[:3] + ["year"],
|
||||
)
|
||||
supply_energy = supply_energy.reindex(cols, axis=1)
|
||||
supply_energy = reindex_columns(supply_energy, cols)
|
||||
|
||||
bus_carriers = n.buses.carrier.unique()
|
||||
|
||||
@ -382,7 +393,7 @@ def calculate_supply_energy(n, label, supply_energy):
|
||||
|
||||
for c in n.iterate_components(n.branch_components):
|
||||
for end in [col[3:] for col in c.df.columns if col[:3] == "bus"]:
|
||||
items = c.df.index[c.df["bus" + str(end)].map(bus_map).fillna(False)]
|
||||
items = c.df.index[c.df[f"bus{str(end)}"].map(bus_map).fillna(False)]
|
||||
|
||||
if len(items) == 0:
|
||||
continue
|
||||
@ -483,7 +494,7 @@ def calculate_weighted_prices(n, label, weighted_prices):
|
||||
"H2": ["Sabatier", "H2 Fuel Cell"],
|
||||
}
|
||||
|
||||
for carrier in link_loads:
|
||||
for carrier, value in link_loads.items():
|
||||
if carrier == "electricity":
|
||||
suffix = ""
|
||||
elif carrier[:5] == "space":
|
||||
@ -496,12 +507,12 @@ def calculate_weighted_prices(n, label, weighted_prices):
|
||||
if buses.empty:
|
||||
continue
|
||||
|
||||
if carrier in ["H2", "gas"]:
|
||||
load = pd.DataFrame(index=n.snapshots, columns=buses, data=0.0)
|
||||
else:
|
||||
load = n.loads_t.p_set.reindex(buses, axis=1)
|
||||
|
||||
for tech in link_loads[carrier]:
|
||||
load = (
|
||||
pd.DataFrame(index=n.snapshots, columns=buses, data=0.0)
|
||||
if carrier in ["H2", "gas"]
|
||||
else n.loads_t.p_set.reindex(buses, axis=1)
|
||||
)
|
||||
for tech in value:
|
||||
names = n.links.index[n.links.index.to_series().str[-len(tech) :] == tech]
|
||||
|
||||
if names.empty:
|
||||
@ -604,7 +615,7 @@ def calculate_price_statistics(n, label, price_statistics):
|
||||
price_statistics.at["mean", label] = n.buses_t.marginal_price[buses].mean().mean()
|
||||
|
||||
price_statistics.at["standard_deviation", label] = (
|
||||
n.buses_t.marginal_price[buses].droplevel(0).unstack().std()
|
||||
n.buses_t.marginal_price[buses].std().std()
|
||||
)
|
||||
|
||||
return price_statistics
|
||||
@ -706,7 +717,6 @@ def to_csv(df):
|
||||
df[key].to_csv(snakemake.output[key])
|
||||
|
||||
|
||||
# %%
|
||||
if __name__ == "__main__":
|
||||
# Detect running outside of snakemake and mock snakemake for testing
|
||||
if "snakemake" not in globals():
|
||||
|
@ -31,7 +31,7 @@ def rename_techs_tyndp(tech):
|
||||
tech = rename_techs(tech)
|
||||
if "heat pump" in tech or "resistive heater" in tech:
|
||||
return "power-to-heat"
|
||||
elif tech in ["H2 Electrolysis", "methanation", "helmeth", "H2 liquefaction"]:
|
||||
elif tech in ["H2 Electrolysis", "methanation", "H2 liquefaction"]:
|
||||
return "power-to-gas"
|
||||
elif tech == "H2":
|
||||
return "H2 storage"
|
||||
@ -145,12 +145,12 @@ def plot_map(
|
||||
ac_color = "rosybrown"
|
||||
dc_color = "darkseagreen"
|
||||
|
||||
title = "added grid"
|
||||
|
||||
if snakemake.wildcards["ll"] == "v1.0":
|
||||
# should be zero
|
||||
line_widths = n.lines.s_nom_opt - n.lines.s_nom
|
||||
link_widths = n.links.p_nom_opt - n.links.p_nom
|
||||
title = "added grid"
|
||||
|
||||
if transmission:
|
||||
line_widths = n.lines.s_nom_opt
|
||||
link_widths = n.links.p_nom_opt
|
||||
@ -160,8 +160,6 @@ def plot_map(
|
||||
else:
|
||||
line_widths = n.lines.s_nom_opt - n.lines.s_nom_min
|
||||
link_widths = n.links.p_nom_opt - n.links.p_nom_min
|
||||
title = "added grid"
|
||||
|
||||
if transmission:
|
||||
line_widths = n.lines.s_nom_opt
|
||||
link_widths = n.links.p_nom_opt
|
||||
@ -262,12 +260,7 @@ def group_pipes(df, drop_direction=False):
|
||||
lambda x: f"H2 pipeline {x.bus0.replace(' H2', '')} -> {x.bus1.replace(' H2', '')}",
|
||||
axis=1,
|
||||
)
|
||||
# group pipe lines connecting the same buses and rename them for plotting
|
||||
pipe_capacity = df.groupby(level=0).agg(
|
||||
{"p_nom_opt": sum, "bus0": "first", "bus1": "first"}
|
||||
)
|
||||
|
||||
return pipe_capacity
|
||||
return df.groupby(level=0).agg({"p_nom_opt": sum, "bus0": "first", "bus1": "first"})
|
||||
|
||||
|
||||
def plot_h2_map(network, regions):
|
||||
@ -502,7 +495,7 @@ def plot_ch4_map(network):
|
||||
# make a fake MultiIndex so that area is correct for legend
|
||||
fossil_gas.index = pd.MultiIndex.from_product([fossil_gas.index, ["fossil gas"]])
|
||||
|
||||
methanation_i = n.links[n.links.carrier.isin(["helmeth", "Sabatier"])].index
|
||||
methanation_i = n.links.query("carrier == 'Sabatier'").index
|
||||
methanation = (
|
||||
abs(
|
||||
n.links_t.p1.loc[:, methanation_i].mul(
|
||||
@ -766,11 +759,13 @@ def plot_series(network, carrier="AC", name="test"):
|
||||
supply = pd.concat(
|
||||
(
|
||||
supply,
|
||||
(-1)
|
||||
* c.pnl["p" + str(i)]
|
||||
.loc[:, c.df.index[c.df["bus" + str(i)].isin(buses)]]
|
||||
.groupby(c.df.carrier, axis=1)
|
||||
.sum(),
|
||||
(
|
||||
-1
|
||||
* c.pnl[f"p{str(i)}"]
|
||||
.loc[:, c.df.index[c.df[f"bus{str(i)}"].isin(buses)]]
|
||||
.groupby(c.df.carrier, axis=1)
|
||||
.sum()
|
||||
),
|
||||
),
|
||||
axis=1,
|
||||
)
|
||||
@ -1065,7 +1060,6 @@ def plot_map_perfect(
|
||||
)
|
||||
|
||||
|
||||
# %%
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
|
@ -33,8 +33,6 @@ if __name__ == "__main__":
|
||||
lambda s: s != "", "lightgrey"
|
||||
)
|
||||
|
||||
# %%
|
||||
|
||||
def rename_index(ds):
|
||||
specific = ds.index.map(lambda x: f"{x[1]}\n({x[0]})")
|
||||
generic = ds.index.get_level_values("carrier")
|
||||
|
@ -121,7 +121,6 @@ preferred_order = pd.Index(
|
||||
"gas boiler",
|
||||
"gas",
|
||||
"natural gas",
|
||||
"helmeth",
|
||||
"methanation",
|
||||
"ammonia",
|
||||
"hydrogen storage",
|
||||
@ -297,11 +296,7 @@ def plot_balances():
|
||||
df.abs().max(axis=1) < snakemake.params.plotting["energy_threshold"] / 10
|
||||
]
|
||||
|
||||
if v[0] in co2_carriers:
|
||||
units = "MtCO2/a"
|
||||
else:
|
||||
units = "TWh/a"
|
||||
|
||||
units = "MtCO2/a" if v[0] in co2_carriers else "TWh/a"
|
||||
logger.debug(
|
||||
f"Dropping technology energy balance smaller than {snakemake.params['plotting']['energy_threshold']/10} {units}"
|
||||
)
|
||||
@ -456,7 +451,6 @@ def plot_carbon_budget_distribution(input_eurostat):
|
||||
|
||||
sns.set()
|
||||
sns.set_style("ticks")
|
||||
plt.style.use("seaborn-ticks")
|
||||
plt.rcParams["xtick.direction"] = "in"
|
||||
plt.rcParams["ytick.direction"] = "in"
|
||||
plt.rcParams["xtick.labelsize"] = 20
|
||||
@ -568,7 +562,6 @@ def plot_carbon_budget_distribution(input_eurostat):
|
||||
plt.savefig(path, bbox_inches="tight")
|
||||
|
||||
|
||||
# %%
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
@ -587,7 +580,5 @@ if __name__ == "__main__":
|
||||
|
||||
for sector_opts in snakemake.params.sector_opts:
|
||||
opts = sector_opts.split("-")
|
||||
if any(["cb" in o for o in opts]) or (
|
||||
snakemake.config["foresight"] == "perfect"
|
||||
):
|
||||
if any("cb" in o for o in opts) or snakemake.config["foresight"] == "perfect":
|
||||
plot_carbon_budget_distribution(snakemake.input.eurostat)
|
||||
|
@ -84,13 +84,9 @@ def cross_border_time_series(countries, data):
|
||||
df_neg.plot.area(
|
||||
ax=ax[axis], stacked=True, linewidth=0.0, color=color, ylim=[-1, 1]
|
||||
)
|
||||
if (axis % 2) == 0:
|
||||
title = "Historic"
|
||||
else:
|
||||
title = "Optimized"
|
||||
|
||||
title = "Historic" if (axis % 2) == 0 else "Optimized"
|
||||
ax[axis].set_title(
|
||||
title + " Import / Export for " + cc.convert(country, to="name_short")
|
||||
f"{title} Import / Export for " + cc.convert(country, to="name_short")
|
||||
)
|
||||
|
||||
# Custom legend elements
|
||||
@ -137,16 +133,12 @@ def cross_border_bar(countries, data):
|
||||
df_country = sort_one_country(country, df)
|
||||
df_neg, df_pos = df_country.clip(upper=0), df_country.clip(lower=0)
|
||||
|
||||
if (order % 2) == 0:
|
||||
title = "Historic"
|
||||
else:
|
||||
title = "Optimized"
|
||||
|
||||
title = "Historic" if (order % 2) == 0 else "Optimized"
|
||||
df_positive_new = pd.DataFrame(data=df_pos.sum()).T.rename(
|
||||
{0: title + " " + cc.convert(country, to="name_short")}
|
||||
{0: f"{title} " + cc.convert(country, to="name_short")}
|
||||
)
|
||||
df_negative_new = pd.DataFrame(data=df_neg.sum()).T.rename(
|
||||
{0: title + " " + cc.convert(country, to="name_short")}
|
||||
{0: f"{title} " + cc.convert(country, to="name_short")}
|
||||
)
|
||||
|
||||
df_positive = pd.concat([df_positive_new, df_positive])
|
||||
|
@ -274,7 +274,6 @@ def set_line_nom_max(
|
||||
n.links.p_nom_max.clip(upper=p_nom_max_set, inplace=True)
|
||||
|
||||
|
||||
# %%
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
|
@ -56,7 +56,7 @@ def get_investment_weighting(time_weighting, r=0.01):
|
||||
end = time_weighting.cumsum()
|
||||
start = time_weighting.cumsum().shift().fillna(0)
|
||||
return pd.concat([start, end], axis=1).apply(
|
||||
lambda x: sum([get_social_discount(t, r) for t in range(int(x[0]), int(x[1]))]),
|
||||
lambda x: sum(get_social_discount(t, r) for t in range(int(x[0]), int(x[1]))),
|
||||
axis=1,
|
||||
)
|
||||
|
||||
@ -306,7 +306,7 @@ def set_carbon_constraints(n, opts):
|
||||
if m is not None:
|
||||
budget = snakemake.config["co2_budget"][m.group(0)] * 1e9
|
||||
if budget != None:
|
||||
logger.info("add carbon budget of {}".format(budget))
|
||||
logger.info(f"add carbon budget of {budget}")
|
||||
n.add(
|
||||
"GlobalConstraint",
|
||||
"Budget",
|
||||
@ -340,9 +340,7 @@ def set_carbon_constraints(n, opts):
|
||||
first_year = n.snapshots.levels[0][0]
|
||||
time_weightings = n.investment_period_weightings.loc[first_year, "years"]
|
||||
co2min = emissions_2019 - ((first_year - 2019) * annual_reduction)
|
||||
logger.info(
|
||||
"add minimum emissions for {} of {} t CO2/a".format(first_year, co2min)
|
||||
)
|
||||
logger.info(f"add minimum emissions for {first_year} of {co2min} t CO2/a")
|
||||
n.add(
|
||||
"GlobalConstraint",
|
||||
f"Co2Min-{first_year}",
|
||||
@ -495,7 +493,6 @@ def set_temporal_aggregation_SEG(n, opts, solver_name):
|
||||
return n
|
||||
|
||||
|
||||
# %%
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
@ -519,9 +516,7 @@ if __name__ == "__main__":
|
||||
social_discountrate = float(o.replace("sdr", "")) / 100
|
||||
|
||||
logger.info(
|
||||
"Concat networks of investment period {} with social discount rate of {}%".format(
|
||||
years, social_discountrate * 100
|
||||
)
|
||||
f"Concat networks of investment period {years} with social discount rate of {social_discountrate * 100}%"
|
||||
)
|
||||
|
||||
# concat prenetworks of planning horizon to single network ------------
|
||||
|
@ -95,12 +95,14 @@ def define_spatial(nodes, options):
|
||||
spatial.gas.industry = nodes + " gas for industry"
|
||||
spatial.gas.industry_cc = nodes + " gas for industry CC"
|
||||
spatial.gas.biogas_to_gas = nodes + " biogas to gas"
|
||||
spatial.gas.biogas_to_gas_cc = nodes + "biogas to gas CC"
|
||||
else:
|
||||
spatial.gas.nodes = ["EU gas"]
|
||||
spatial.gas.locations = ["EU"]
|
||||
spatial.gas.biogas = ["EU biogas"]
|
||||
spatial.gas.industry = ["gas for industry"]
|
||||
spatial.gas.biogas_to_gas = ["EU biogas to gas"]
|
||||
spatial.gas.biogas_to_gas_cc = ["EU biogas to gas CC"]
|
||||
if options.get("co2_spatial", options["co2network"]):
|
||||
spatial.gas.industry_cc = nodes + " gas for industry CC"
|
||||
else:
|
||||
@ -184,10 +186,7 @@ def get(item, investment_year=None):
|
||||
"""
|
||||
Check whether item depends on investment year.
|
||||
"""
|
||||
if isinstance(item, dict):
|
||||
return item[investment_year]
|
||||
else:
|
||||
return item
|
||||
return item[investment_year] if isinstance(item, dict) else item
|
||||
|
||||
|
||||
def co2_emissions_year(
|
||||
@ -413,11 +412,9 @@ def update_wind_solar_costs(n, costs):
|
||||
# e.g. clusters == 37m means that VRE generators are left
|
||||
# at clustering of simplified network, but that they are
|
||||
# connected to 37-node network
|
||||
if snakemake.wildcards.clusters[-1:] == "m":
|
||||
genmap = busmap_s
|
||||
else:
|
||||
genmap = clustermaps
|
||||
|
||||
genmap = (
|
||||
busmap_s if snakemake.wildcards.clusters[-1:] == "m" else clustermaps
|
||||
)
|
||||
connection_cost = (connection_cost * weight).groupby(
|
||||
genmap
|
||||
).sum() / weight.groupby(genmap).sum()
|
||||
@ -457,10 +454,11 @@ def add_carrier_buses(n, carrier, nodes=None):
|
||||
n.add("Carrier", carrier)
|
||||
|
||||
unit = "MWh_LHV" if carrier == "gas" else "MWh_th"
|
||||
# preliminary value for non-gas carriers to avoid zeros
|
||||
capital_cost = costs.at["gas storage", "fixed"] if carrier == "gas" else 0.02
|
||||
|
||||
n.madd("Bus", nodes, location=location, carrier=carrier, unit=unit)
|
||||
|
||||
# capital cost could be corrected to e.g. 0.2 EUR/kWh * annuity and O&M
|
||||
n.madd(
|
||||
"Store",
|
||||
nodes + " Store",
|
||||
@ -468,8 +466,7 @@ def add_carrier_buses(n, carrier, nodes=None):
|
||||
e_nom_extendable=True,
|
||||
e_cyclic=True,
|
||||
carrier=carrier,
|
||||
capital_cost=0.2
|
||||
* costs.at[carrier, "discount rate"], # preliminary value to avoid zeros
|
||||
capital_cost=capital_cost,
|
||||
)
|
||||
|
||||
n.madd(
|
||||
@ -505,8 +502,7 @@ def remove_non_electric_buses(n):
|
||||
"""
|
||||
Remove buses from pypsa-eur with carriers which are not AC buses.
|
||||
"""
|
||||
to_drop = list(n.buses.query("carrier not in ['AC', 'DC']").carrier.unique())
|
||||
if to_drop:
|
||||
if to_drop := list(n.buses.query("carrier not in ['AC', 'DC']").carrier.unique()):
|
||||
logger.info(f"Drop buses from PyPSA-Eur with carrier: {to_drop}")
|
||||
n.buses = n.buses[n.buses.carrier.isin(["AC", "DC"])]
|
||||
|
||||
@ -815,14 +811,13 @@ def add_ammonia(n, costs):
|
||||
bus2=nodes + " H2",
|
||||
p_nom_extendable=True,
|
||||
carrier="Haber-Bosch",
|
||||
efficiency=1
|
||||
/ (
|
||||
cf_industry["MWh_elec_per_tNH3_electrolysis"]
|
||||
/ cf_industry["MWh_NH3_per_tNH3"]
|
||||
), # output: MW_NH3 per MW_elec
|
||||
efficiency2=-cf_industry["MWh_H2_per_tNH3_electrolysis"]
|
||||
/ cf_industry["MWh_elec_per_tNH3_electrolysis"], # input: MW_H2 per MW_elec
|
||||
capital_cost=costs.at["Haber-Bosch", "fixed"],
|
||||
efficiency=1 / costs.at["Haber-Bosch", "electricity-input"],
|
||||
efficiency2=-costs.at["Haber-Bosch", "hydrogen-input"]
|
||||
/ costs.at["Haber-Bosch", "electricity-input"],
|
||||
capital_cost=costs.at["Haber-Bosch", "fixed"]
|
||||
/ costs.at["Haber-Bosch", "electricity-input"],
|
||||
marginal_cost=costs.at["Haber-Bosch", "VOM"]
|
||||
/ costs.at["Haber-Bosch", "electricity-input"],
|
||||
lifetime=costs.at["Haber-Bosch", "lifetime"],
|
||||
)
|
||||
|
||||
@ -1033,7 +1028,7 @@ def insert_gas_distribution_costs(n, costs):
|
||||
f"Inserting gas distribution grid with investment cost factor of {f_costs}"
|
||||
)
|
||||
|
||||
capital_cost = costs.loc["electricity distribution grid"]["fixed"] * f_costs
|
||||
capital_cost = costs.at["electricity distribution grid", "fixed"] * f_costs
|
||||
|
||||
# gas boilers
|
||||
gas_b = n.links.index[
|
||||
@ -1110,6 +1105,7 @@ def add_storage_and_grids(n, costs):
|
||||
efficiency=costs.at["OCGT", "efficiency"],
|
||||
capital_cost=costs.at["OCGT", "fixed"]
|
||||
* costs.at["OCGT", "efficiency"], # NB: fixed cost is per MWel
|
||||
marginal_cost=costs.at["OCGT", "VOM"],
|
||||
lifetime=costs.at["OCGT", "lifetime"],
|
||||
)
|
||||
|
||||
@ -1170,7 +1166,7 @@ def add_storage_and_grids(n, costs):
|
||||
|
||||
if options["gas_network"]:
|
||||
logger.info(
|
||||
"Add natural gas infrastructure, incl. LNG terminals, production and entry-points."
|
||||
"Add natural gas infrastructure, incl. LNG terminals, production, storage and entry-points."
|
||||
)
|
||||
|
||||
if options["H2_retrofit"]:
|
||||
@ -1215,10 +1211,25 @@ def add_storage_and_grids(n, costs):
|
||||
remove_i = n.generators[gas_i & internal_i].index
|
||||
n.generators.drop(remove_i, inplace=True)
|
||||
|
||||
p_nom = gas_input_nodes.sum(axis=1).rename(lambda x: x + " gas")
|
||||
input_types = ["lng", "pipeline", "production"]
|
||||
p_nom = gas_input_nodes[input_types].sum(axis=1).rename(lambda x: x + " gas")
|
||||
n.generators.loc[gas_i, "p_nom_extendable"] = False
|
||||
n.generators.loc[gas_i, "p_nom"] = p_nom
|
||||
|
||||
# add existing gas storage capacity
|
||||
gas_i = n.stores.carrier == "gas"
|
||||
e_nom = (
|
||||
gas_input_nodes["storage"]
|
||||
.rename(lambda x: x + " gas Store")
|
||||
.reindex(n.stores.index)
|
||||
.fillna(0.0)
|
||||
* 1e3
|
||||
) # MWh_LHV
|
||||
e_nom.clip(
|
||||
upper=e_nom.quantile(0.98), inplace=True
|
||||
) # limit extremely large storage
|
||||
n.stores.loc[gas_i, "e_nom_min"] = e_nom
|
||||
|
||||
# add candidates for new gas pipelines to achieve full connectivity
|
||||
|
||||
G = nx.Graph()
|
||||
@ -1236,11 +1247,9 @@ def add_storage_and_grids(n, costs):
|
||||
|
||||
# apply k_edge_augmentation weighted by length of complement edges
|
||||
k_edge = options.get("gas_network_connectivity_upgrade", 3)
|
||||
augmentation = list(
|
||||
if augmentation := list(
|
||||
k_edge_augmentation(G, k_edge, avail=complement_edges.values)
|
||||
)
|
||||
|
||||
if augmentation:
|
||||
):
|
||||
new_gas_pipes = pd.DataFrame(augmentation, columns=["bus0", "bus1"])
|
||||
new_gas_pipes["length"] = new_gas_pipes.apply(haversine, axis=1)
|
||||
|
||||
@ -1355,6 +1364,7 @@ def add_storage_and_grids(n, costs):
|
||||
bus2=spatial.co2.nodes,
|
||||
p_nom_extendable=True,
|
||||
carrier="Sabatier",
|
||||
p_min_pu=options.get("min_part_load_methanation", 0),
|
||||
efficiency=costs.at["methanation", "efficiency"],
|
||||
efficiency2=-costs.at["methanation", "efficiency"]
|
||||
* costs.at["gas", "CO2 intensity"],
|
||||
@ -1363,23 +1373,6 @@ def add_storage_and_grids(n, costs):
|
||||
lifetime=costs.at["methanation", "lifetime"],
|
||||
)
|
||||
|
||||
if options["helmeth"]:
|
||||
n.madd(
|
||||
"Link",
|
||||
spatial.nodes,
|
||||
suffix=" helmeth",
|
||||
bus0=nodes,
|
||||
bus1=spatial.gas.nodes,
|
||||
bus2=spatial.co2.nodes,
|
||||
carrier="helmeth",
|
||||
p_nom_extendable=True,
|
||||
efficiency=costs.at["helmeth", "efficiency"],
|
||||
efficiency2=-costs.at["helmeth", "efficiency"]
|
||||
* costs.at["gas", "CO2 intensity"],
|
||||
capital_cost=costs.at["helmeth", "fixed"],
|
||||
lifetime=costs.at["helmeth", "lifetime"],
|
||||
)
|
||||
|
||||
if options.get("coal_cc"):
|
||||
n.madd(
|
||||
"Link",
|
||||
@ -1404,7 +1397,7 @@ def add_storage_and_grids(n, costs):
|
||||
lifetime=costs.at["coal", "lifetime"],
|
||||
)
|
||||
|
||||
if options["SMR"]:
|
||||
if options["SMR_cc"]:
|
||||
n.madd(
|
||||
"Link",
|
||||
spatial.nodes,
|
||||
@ -1422,6 +1415,7 @@ def add_storage_and_grids(n, costs):
|
||||
lifetime=costs.at["SMR CC", "lifetime"],
|
||||
)
|
||||
|
||||
if options["SMR"]:
|
||||
n.madd(
|
||||
"Link",
|
||||
nodes + " SMR",
|
||||
@ -1567,14 +1561,7 @@ def add_land_transport(n, costs):
|
||||
)
|
||||
|
||||
if ice_share > 0:
|
||||
if "oil" not in n.buses.carrier.unique():
|
||||
n.madd(
|
||||
"Bus",
|
||||
spatial.oil.nodes,
|
||||
location=spatial.oil.locations,
|
||||
carrier="oil",
|
||||
unit="MWh_LHV",
|
||||
)
|
||||
add_carrier_buses(n, "oil")
|
||||
|
||||
ice_efficiency = options["transport_internal_combustion_efficiency"]
|
||||
|
||||
@ -1648,7 +1635,7 @@ def build_heat_demand(n):
|
||||
electric_nodes = n.loads.index[n.loads.carrier == "electricity"]
|
||||
n.loads_t.p_set[electric_nodes] = (
|
||||
n.loads_t.p_set[electric_nodes]
|
||||
- electric_heat_supply.groupby(level=1, axis=1).sum()[electric_nodes]
|
||||
- electric_heat_supply.T.groupby(level=1).sum().T[electric_nodes]
|
||||
)
|
||||
|
||||
return heat_demand
|
||||
@ -1711,6 +1698,19 @@ def add_heat(n, costs):
|
||||
unit="MWh_th",
|
||||
)
|
||||
|
||||
if name == "urban central" and options.get("central_heat_vent"):
|
||||
n.madd(
|
||||
"Generator",
|
||||
nodes[name] + f" {name} heat vent",
|
||||
bus=nodes[name] + f" {name} heat",
|
||||
location=nodes[name],
|
||||
carrier=name + " heat vent",
|
||||
p_nom_extendable=True,
|
||||
p_max_pu=0,
|
||||
p_min_pu=-1,
|
||||
unit="MWh_th",
|
||||
)
|
||||
|
||||
## Add heat load
|
||||
|
||||
for sector in sectors:
|
||||
@ -1729,15 +1729,17 @@ def add_heat(n, costs):
|
||||
if sector in name:
|
||||
heat_load = (
|
||||
heat_demand[[sector + " water", sector + " space"]]
|
||||
.groupby(level=1, axis=1)
|
||||
.sum()[nodes[name]]
|
||||
.T.groupby(level=1)
|
||||
.sum()
|
||||
.T[nodes[name]]
|
||||
.multiply(factor)
|
||||
)
|
||||
|
||||
if name == "urban central":
|
||||
heat_load = (
|
||||
heat_demand.groupby(level=1, axis=1)
|
||||
.sum()[nodes[name]]
|
||||
heat_demand.T.groupby(level=1)
|
||||
.sum()
|
||||
.T[nodes[name]]
|
||||
.multiply(
|
||||
factor * (1 + options["district_heating"]["district_heating_loss"])
|
||||
)
|
||||
@ -1965,7 +1967,7 @@ def add_heat(n, costs):
|
||||
# demand 'dE' [per unit of original heat demand] for each country and
|
||||
# different retrofitting strengths [additional insulation thickness in m]
|
||||
retro_data = pd.read_csv(
|
||||
snakemake.input.retro_cost_energy,
|
||||
snakemake.input.retro_cost,
|
||||
index_col=[0, 1],
|
||||
skipinitialspace=True,
|
||||
header=[0, 1],
|
||||
@ -2009,7 +2011,11 @@ def add_heat(n, costs):
|
||||
space_heat_demand = demand * w_space[sec][node]
|
||||
# normed time profile of space heat demand 'space_pu' (values between 0-1),
|
||||
# p_max_pu/p_min_pu of retrofitting generators
|
||||
space_pu = (space_heat_demand / space_heat_demand.max()).to_frame(name=node)
|
||||
space_pu = (
|
||||
(space_heat_demand / space_heat_demand.max())
|
||||
.to_frame(name=node)
|
||||
.fillna(0)
|
||||
)
|
||||
|
||||
# minimum heat demand 'dE' after retrofitting in units of original heat demand (values between 0-1)
|
||||
dE = retro_data.loc[(ct, sec), ("dE")]
|
||||
@ -2021,6 +2027,9 @@ def add_heat(n, costs):
|
||||
* floor_area_node
|
||||
/ ((1 - dE) * space_heat_demand.max())
|
||||
)
|
||||
if space_heat_demand.max() == 0:
|
||||
capital_cost = capital_cost.apply(lambda b: 0 if b == np.inf else b)
|
||||
|
||||
# number of possible retrofitting measures 'strengths' (set in list at config.yaml 'l_strength')
|
||||
# given in additional insulation thickness [m]
|
||||
# for each measure, a retrofitting generator is added at the node
|
||||
@ -2164,12 +2173,42 @@ def add_biomass(n, costs):
|
||||
bus1=spatial.gas.nodes,
|
||||
bus2="co2 atmosphere",
|
||||
carrier="biogas to gas",
|
||||
capital_cost=costs.loc["biogas upgrading", "fixed"],
|
||||
marginal_cost=costs.loc["biogas upgrading", "VOM"],
|
||||
capital_cost=costs.at["biogas", "fixed"]
|
||||
+ costs.at["biogas upgrading", "fixed"],
|
||||
marginal_cost=costs.at["biogas upgrading", "VOM"],
|
||||
efficiency=costs.at["biogas", "efficiency"],
|
||||
efficiency2=-costs.at["gas", "CO2 intensity"],
|
||||
p_nom_extendable=True,
|
||||
)
|
||||
|
||||
if options.get("biogas_upgrading_cc"):
|
||||
# Assuming for costs that the CO2 from upgrading is pure, such as in amine scrubbing. I.e., with and without CC is
|
||||
# equivalent. Adding biomass CHP capture because biogas is often small-scale and decentral so further
|
||||
# from e.g. CO2 grid or buyers. This is a proxy for the added cost for e.g. a raw biogas pipeline to a central upgrading facility
|
||||
|
||||
n.madd(
|
||||
"Link",
|
||||
spatial.gas.biogas_to_gas_cc,
|
||||
bus0=spatial.gas.biogas,
|
||||
bus1=spatial.gas.nodes,
|
||||
bus2="co2 stored",
|
||||
bus3="co2 atmosphere",
|
||||
carrier="biogas to gas CC",
|
||||
capital_cost=costs.at["biogas CC", "fixed"]
|
||||
+ costs.at["biogas upgrading", "fixed"]
|
||||
+ costs.at["biomass CHP capture", "fixed"]
|
||||
* costs.at["biogas CC", "CO2 stored"],
|
||||
marginal_cost=costs.at["biogas CC", "VOM"]
|
||||
+ costs.at["biogas upgrading", "VOM"],
|
||||
efficiency=costs.at["biogas CC", "efficiency"],
|
||||
efficiency2=costs.at["biogas CC", "CO2 stored"]
|
||||
* costs.at["biogas CC", "capture rate"],
|
||||
efficiency3=-costs.at["gas", "CO2 intensity"]
|
||||
- costs.at["biogas CC", "CO2 stored"]
|
||||
* costs.at["biogas CC", "capture rate"],
|
||||
p_nom_extendable=True,
|
||||
)
|
||||
|
||||
if options["biomass_transport"]:
|
||||
# add biomass transport
|
||||
transport_costs = pd.read_csv(
|
||||
@ -2295,6 +2334,7 @@ def add_biomass(n, costs):
|
||||
efficiency=costs.at["biomass boiler", "efficiency"],
|
||||
capital_cost=costs.at["biomass boiler", "efficiency"]
|
||||
* costs.at["biomass boiler", "fixed"],
|
||||
marginal_cost=costs.at["biomass boiler", "pelletizing cost"],
|
||||
lifetime=costs.at["biomass boiler", "lifetime"],
|
||||
)
|
||||
|
||||
@ -2314,7 +2354,7 @@ def add_biomass(n, costs):
|
||||
+ costs.at["BtL", "CO2 stored"],
|
||||
p_nom_extendable=True,
|
||||
capital_cost=costs.at["BtL", "fixed"],
|
||||
marginal_cost=costs.at["BtL", "efficiency"] * costs.loc["BtL", "VOM"],
|
||||
marginal_cost=costs.at["BtL", "efficiency"] * costs.at["BtL", "VOM"],
|
||||
)
|
||||
|
||||
# TODO: Update with energy penalty
|
||||
@ -2335,7 +2375,7 @@ def add_biomass(n, costs):
|
||||
p_nom_extendable=True,
|
||||
capital_cost=costs.at["BtL", "fixed"]
|
||||
+ costs.at["biomass CHP capture", "fixed"] * costs.at["BtL", "CO2 stored"],
|
||||
marginal_cost=costs.at["BtL", "efficiency"] * costs.loc["BtL", "VOM"],
|
||||
marginal_cost=costs.at["BtL", "efficiency"] * costs.at["BtL", "VOM"],
|
||||
)
|
||||
|
||||
# BioSNG from solid biomass
|
||||
@ -2354,7 +2394,7 @@ def add_biomass(n, costs):
|
||||
+ costs.at["BioSNG", "CO2 stored"],
|
||||
p_nom_extendable=True,
|
||||
capital_cost=costs.at["BioSNG", "fixed"],
|
||||
marginal_cost=costs.at["BioSNG", "efficiency"] * costs.loc["BioSNG", "VOM"],
|
||||
marginal_cost=costs.at["BioSNG", "efficiency"] * costs.at["BioSNG", "VOM"],
|
||||
)
|
||||
|
||||
# TODO: Update with energy penalty for CC
|
||||
@ -2378,7 +2418,7 @@ def add_biomass(n, costs):
|
||||
capital_cost=costs.at["BioSNG", "fixed"]
|
||||
+ costs.at["biomass CHP capture", "fixed"]
|
||||
* costs.at["BioSNG", "CO2 stored"],
|
||||
marginal_cost=costs.at["BioSNG", "efficiency"] * costs.loc["BioSNG", "VOM"],
|
||||
marginal_cost=costs.at["BioSNG", "efficiency"] * costs.at["BioSNG", "VOM"],
|
||||
)
|
||||
|
||||
|
||||
@ -2611,6 +2651,8 @@ def add_industry(n, costs):
|
||||
p_min_pu=options.get("min_part_load_methanolisation", 0),
|
||||
capital_cost=costs.at["methanolisation", "fixed"]
|
||||
* options["MWh_MeOH_per_MWh_H2"], # EUR/MW_H2/a
|
||||
marginal_cost=options["MWh_MeOH_per_MWh_H2"]
|
||||
* costs.at["methanolisation", "VOM"],
|
||||
lifetime=costs.at["methanolisation", "lifetime"],
|
||||
efficiency=options["MWh_MeOH_per_MWh_H2"],
|
||||
efficiency2=-options["MWh_MeOH_per_MWh_H2"] / options["MWh_MeOH_per_MWh_e"],
|
||||
@ -2708,7 +2750,7 @@ def add_industry(n, costs):
|
||||
nodes_heat[name] + f" {name} oil boiler",
|
||||
p_nom_extendable=True,
|
||||
bus0=spatial.oil.nodes,
|
||||
bus1=nodes_heat[name] + f" {name} heat",
|
||||
bus1=nodes_heat[name] + f" {name} heat",
|
||||
bus2="co2 atmosphere",
|
||||
carrier=f"{name} oil boiler",
|
||||
efficiency=costs.at["decentral oil boiler", "efficiency"],
|
||||
@ -2728,6 +2770,8 @@ def add_industry(n, costs):
|
||||
efficiency=costs.at["Fischer-Tropsch", "efficiency"],
|
||||
capital_cost=costs.at["Fischer-Tropsch", "fixed"]
|
||||
* costs.at["Fischer-Tropsch", "efficiency"], # EUR/MW_H2/a
|
||||
marginal_cost=costs.at["Fischer-Tropsch", "efficiency"]
|
||||
* costs.at["Fischer-Tropsch", "VOM"],
|
||||
efficiency2=-costs.at["oil", "CO2 intensity"]
|
||||
* costs.at["Fischer-Tropsch", "efficiency"],
|
||||
p_nom_extendable=True,
|
||||
@ -2898,6 +2942,30 @@ def add_industry(n, costs):
|
||||
p_set=p_set,
|
||||
)
|
||||
|
||||
primary_steel = get(
|
||||
snakemake.config["industry"]["St_primary_fraction"], investment_year
|
||||
)
|
||||
dri_steel = get(snakemake.config["industry"]["DRI_fraction"], investment_year)
|
||||
bof_steel = primary_steel - dri_steel
|
||||
|
||||
if bof_steel > 0:
|
||||
add_carrier_buses(n, "coal")
|
||||
|
||||
mwh_coal_per_mwh_coke = 1.366 # from eurostat energy balance
|
||||
p_set = (
|
||||
industrial_demand["coal"].sum()
|
||||
+ mwh_coal_per_mwh_coke * industrial_demand["coke"].sum()
|
||||
) / nhours
|
||||
|
||||
n.madd(
|
||||
"Load",
|
||||
spatial.coal.nodes,
|
||||
suffix=" for industry",
|
||||
bus=spatial.coal.nodes,
|
||||
carrier="coal for industry",
|
||||
p_set=p_set,
|
||||
)
|
||||
|
||||
|
||||
def add_waste_heat(n):
|
||||
# TODO options?
|
||||
@ -2909,8 +2977,13 @@ def add_waste_heat(n):
|
||||
if not urban_central.empty:
|
||||
urban_central = urban_central.str[: -len(" urban central heat")]
|
||||
|
||||
link_carriers = n.links.carrier.unique()
|
||||
|
||||
# TODO what is the 0.95 and should it be a config option?
|
||||
if options["use_fischer_tropsch_waste_heat"]:
|
||||
if (
|
||||
options["use_fischer_tropsch_waste_heat"]
|
||||
and "Fischer-Tropsch" in link_carriers
|
||||
):
|
||||
n.links.loc[urban_central + " Fischer-Tropsch", "bus3"] = (
|
||||
urban_central + " urban central heat"
|
||||
)
|
||||
@ -2918,8 +2991,48 @@ def add_waste_heat(n):
|
||||
0.95 - n.links.loc[urban_central + " Fischer-Tropsch", "efficiency"]
|
||||
)
|
||||
|
||||
if options["use_methanation_waste_heat"] and "Sabatier" in link_carriers:
|
||||
n.links.loc[urban_central + " Sabatier", "bus3"] = (
|
||||
urban_central + " urban central heat"
|
||||
)
|
||||
n.links.loc[urban_central + " Sabatier", "efficiency3"] = (
|
||||
0.95 - n.links.loc[urban_central + " Sabatier", "efficiency"]
|
||||
)
|
||||
|
||||
# DEA quotes 15% of total input (11% of which are high-value heat)
|
||||
if options["use_haber_bosch_waste_heat"] and "Haber-Bosch" in link_carriers:
|
||||
n.links.loc[urban_central + " Haber-Bosch", "bus3"] = (
|
||||
urban_central + " urban central heat"
|
||||
)
|
||||
total_energy_input = (
|
||||
cf_industry["MWh_H2_per_tNH3_electrolysis"]
|
||||
+ cf_industry["MWh_elec_per_tNH3_electrolysis"]
|
||||
) / cf_industry["MWh_NH3_per_tNH3"]
|
||||
electricity_input = (
|
||||
cf_industry["MWh_elec_per_tNH3_electrolysis"]
|
||||
/ cf_industry["MWh_NH3_per_tNH3"]
|
||||
)
|
||||
n.links.loc[urban_central + " Haber-Bosch", "efficiency3"] = (
|
||||
0.15 * total_energy_input / electricity_input
|
||||
)
|
||||
|
||||
if (
|
||||
options["use_methanolisation_waste_heat"]
|
||||
and "methanolisation" in link_carriers
|
||||
):
|
||||
n.links.loc[urban_central + " methanolisation", "bus4"] = (
|
||||
urban_central + " urban central heat"
|
||||
)
|
||||
n.links.loc[urban_central + " methanolisation", "efficiency4"] = (
|
||||
costs.at["methanolisation", "heat-output"]
|
||||
/ costs.at["methanolisation", "hydrogen-input"]
|
||||
)
|
||||
|
||||
# TODO integrate usable waste heat efficiency into technology-data from DEA
|
||||
if options.get("use_electrolysis_waste_heat", False):
|
||||
if (
|
||||
options.get("use_electrolysis_waste_heat", False)
|
||||
and "H2 Electrolysis" in link_carriers
|
||||
):
|
||||
n.links.loc[urban_central + " H2 Electrolysis", "bus2"] = (
|
||||
urban_central + " urban central heat"
|
||||
)
|
||||
@ -2927,7 +3040,7 @@ def add_waste_heat(n):
|
||||
0.84 - n.links.loc[urban_central + " H2 Electrolysis", "efficiency"]
|
||||
)
|
||||
|
||||
if options["use_fuel_cell_waste_heat"]:
|
||||
if options["use_fuel_cell_waste_heat"] and "H2 Fuel Cell" in link_carriers:
|
||||
n.links.loc[urban_central + " H2 Fuel Cell", "bus2"] = (
|
||||
urban_central + " urban central heat"
|
||||
)
|
||||
@ -3367,6 +3480,15 @@ if __name__ == "__main__":
|
||||
if "nodistrict" in opts:
|
||||
options["district_heating"]["progress"] = 0.0
|
||||
|
||||
if "nowasteheat" in opts:
|
||||
logger.info("Disabling waste heat.")
|
||||
options["use_fischer_tropsch_waste_heat"] = False
|
||||
options["use_methanolisation_waste_heat"] = False
|
||||
options["use_haber_bosch_waste_heat"] = False
|
||||
options["use_methanation_waste_heat"] = False
|
||||
options["use_fuel_cell_waste_heat"] = False
|
||||
options["use_electrolysis_waste_heat"] = False
|
||||
|
||||
if "T" in opts:
|
||||
add_land_transport(n, costs)
|
||||
|
||||
|
@ -36,7 +36,7 @@ import logging
|
||||
import tarfile
|
||||
from pathlib import Path
|
||||
|
||||
from _helpers import configure_logging, progress_retrieve
|
||||
from _helpers import configure_logging, progress_retrieve, validate_checksum
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -65,6 +65,8 @@ if __name__ == "__main__":
|
||||
disable_progress = snakemake.config["run"].get("disable_progressbar", False)
|
||||
progress_retrieve(url, tarball_fn, disable=disable_progress)
|
||||
|
||||
validate_checksum(tarball_fn, url)
|
||||
|
||||
logger.info("Extracting databundle.")
|
||||
tarfile.open(tarball_fn).extractall(to_fn)
|
||||
|
||||
|
@ -11,7 +11,7 @@ import logging
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
from _helpers import progress_retrieve
|
||||
from _helpers import progress_retrieve, validate_checksum
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -35,6 +35,8 @@ if __name__ == "__main__":
|
||||
disable_progress = snakemake.config["run"].get("disable_progressbar", False)
|
||||
progress_retrieve(url, zip_fn, disable=disable_progress)
|
||||
|
||||
validate_checksum(zip_fn, url)
|
||||
|
||||
logger.info("Extracting databundle.")
|
||||
zipfile.ZipFile(zip_fn).extractall(to_fn)
|
||||
|
||||
|
107
scripts/retrieve_irena.py
Normal file
107
scripts/retrieve_irena.py
Normal file
@ -0,0 +1,107 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2023 Thomas Gilon (Climact)
|
||||
# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
This rule downloads the existing capacities from `IRENASTAT <https://www.irena.org/Data/Downloads/IRENASTAT>`_ and extracts it in the ``data/existing_capacities`` sub-directory.
|
||||
|
||||
**Relevant Settings**
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
enable:
|
||||
retrieve_irena:
|
||||
|
||||
.. seealso::
|
||||
Documentation of the configuration file ``config.yaml`` at
|
||||
:ref:`enable_cf`
|
||||
|
||||
**Outputs**
|
||||
|
||||
- ``data/existing_capacities``: existing capacities for offwind, onwind and solar
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
import pandas as pd
|
||||
from _helpers import configure_logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
REGIONS = [
|
||||
"Albania",
|
||||
"Austria",
|
||||
"Belgium",
|
||||
"Bosnia and Herzegovina",
|
||||
"Bulgaria",
|
||||
"Croatia",
|
||||
"Czechia",
|
||||
"Denmark",
|
||||
"Estonia",
|
||||
"Finland",
|
||||
"France",
|
||||
"Germany",
|
||||
"Greece",
|
||||
"Hungary",
|
||||
"Ireland",
|
||||
"Italy",
|
||||
"Latvia",
|
||||
"Lithuania",
|
||||
"Luxembourg",
|
||||
"Montenegro",
|
||||
# "Netherlands",
|
||||
"Netherlands (Kingdom of the)",
|
||||
"North Macedonia",
|
||||
"Norway",
|
||||
"Poland",
|
||||
"Portugal",
|
||||
"Romania",
|
||||
"Serbia",
|
||||
"Slovakia",
|
||||
"Slovenia",
|
||||
"Spain",
|
||||
"Sweden",
|
||||
"Switzerland",
|
||||
# "United Kingdom",
|
||||
"United Kingdom of Great Britain and Northern Ireland (the)",
|
||||
]
|
||||
|
||||
REGIONS_DICT = {
|
||||
"Bosnia and Herzegovina": "Bosnia Herzg",
|
||||
"Netherlands (Kingdom of the)": "Netherlands",
|
||||
"United Kingdom of Great Britain and Northern Ireland (the)": "UK",
|
||||
}
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
|
||||
snakemake = mock_snakemake("retrieve_irena")
|
||||
configure_logging(snakemake)
|
||||
|
||||
irena_raw = pd.read_csv(
|
||||
"https://pxweb.irena.org:443/sq/99e64b12-fe03-4a7b-92ea-a22cc3713b92",
|
||||
skiprows=2,
|
||||
index_col=[0, 1, 3],
|
||||
encoding="latin-1",
|
||||
)
|
||||
|
||||
var = "Installed electricity capacity (MW)"
|
||||
irena = irena_raw[var].unstack(level=2).reset_index(level=1).replace(0, "")
|
||||
|
||||
irena = irena[irena.index.isin(REGIONS)]
|
||||
irena.rename(index=REGIONS_DICT, inplace=True)
|
||||
|
||||
df_offwind = irena[irena.Technology.str.contains("Offshore")].drop(
|
||||
columns=["Technology"]
|
||||
)
|
||||
df_onwind = irena[irena.Technology.str.contains("Onshore")].drop(
|
||||
columns=["Technology"]
|
||||
)
|
||||
df_pv = irena[irena.Technology.str.contains("Solar")].drop(columns=["Technology"])
|
||||
|
||||
df_offwind.to_csv(snakemake.output["offwind"])
|
||||
df_onwind.to_csv(snakemake.output["onwind"])
|
||||
df_pv.to_csv(snakemake.output["solar"])
|
@ -13,7 +13,7 @@ logger = logging.getLogger(__name__)
|
||||
import tarfile
|
||||
from pathlib import Path
|
||||
|
||||
from _helpers import configure_logging, progress_retrieve
|
||||
from _helpers import configure_logging, progress_retrieve, validate_checksum
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
@ -34,6 +34,8 @@ if __name__ == "__main__":
|
||||
disable_progress = snakemake.config["run"].get("disable_progressbar", False)
|
||||
progress_retrieve(url, tarball_fn, disable=disable_progress)
|
||||
|
||||
validate_checksum(tarball_fn, url)
|
||||
|
||||
logger.info("Extracting databundle.")
|
||||
tarfile.open(tarball_fn).extractall(to_fn)
|
||||
|
||||
|
@ -152,22 +152,20 @@ def _prepare_connection_costs_per_link(n, costs, renewable_carriers, length_fact
|
||||
if n.links.empty:
|
||||
return {}
|
||||
|
||||
connection_costs_per_link = {}
|
||||
|
||||
for tech in renewable_carriers:
|
||||
if tech.startswith("offwind"):
|
||||
connection_costs_per_link[tech] = (
|
||||
n.links.length
|
||||
* length_factor
|
||||
* (
|
||||
n.links.underwater_fraction
|
||||
* costs.at[tech + "-connection-submarine", "capital_cost"]
|
||||
+ (1.0 - n.links.underwater_fraction)
|
||||
* costs.at[tech + "-connection-underground", "capital_cost"]
|
||||
)
|
||||
return {
|
||||
tech: (
|
||||
n.links.length
|
||||
* length_factor
|
||||
* (
|
||||
n.links.underwater_fraction
|
||||
* costs.at[tech + "-connection-submarine", "capital_cost"]
|
||||
+ (1.0 - n.links.underwater_fraction)
|
||||
* costs.at[tech + "-connection-underground", "capital_cost"]
|
||||
)
|
||||
|
||||
return connection_costs_per_link
|
||||
)
|
||||
for tech in renewable_carriers
|
||||
if tech.startswith("offwind")
|
||||
}
|
||||
|
||||
|
||||
def _compute_connection_costs_to_bus(
|
||||
@ -538,6 +536,9 @@ if __name__ == "__main__":
|
||||
n = pypsa.Network(snakemake.input.network)
|
||||
Nyears = n.snapshot_weightings.objective.sum() / 8760
|
||||
|
||||
# remove integer outputs for compatibility with PyPSA v0.26.0
|
||||
n.generators.drop("n_mod", axis=1, inplace=True, errors="ignore")
|
||||
|
||||
n, trafo_map = simplify_network_to_380(n)
|
||||
|
||||
technology_costs = load_costs(
|
||||
|
@ -153,12 +153,7 @@ def _add_land_use_constraint_m(n, planning_horizons, config):
|
||||
for carrier in ["solar", "onwind", "offwind-ac", "offwind-dc"]:
|
||||
existing = n.generators.loc[n.generators.carrier == carrier, "p_nom"]
|
||||
ind = list(
|
||||
set(
|
||||
[
|
||||
i.split(sep=" ")[0] + " " + i.split(sep=" ")[1]
|
||||
for i in existing.index
|
||||
]
|
||||
)
|
||||
{i.split(sep=" ")[0] + " " + i.split(sep=" ")[1] for i in existing.index}
|
||||
)
|
||||
|
||||
previous_years = [
|
||||
@ -217,7 +212,6 @@ def add_carbon_constraint(n, snapshots):
|
||||
if glcs.empty:
|
||||
return
|
||||
for name, glc in glcs.iterrows():
|
||||
rhs = glc.constant
|
||||
carattr = glc.carrier_attribute
|
||||
emissions = n.carriers.query(f"{carattr} != 0")[carattr]
|
||||
|
||||
@ -227,14 +221,15 @@ def add_carbon_constraint(n, snapshots):
|
||||
# stores
|
||||
n.stores["carrier"] = n.stores.bus.map(n.buses.carrier)
|
||||
stores = n.stores.query("carrier in @emissions.index and not e_cyclic")
|
||||
time_valid = int(glc.loc["investment_period"])
|
||||
if not stores.empty:
|
||||
last = n.snapshot_weightings.reset_index().groupby("period").last()
|
||||
last_i = last.set_index([last.index, last.timestep]).index
|
||||
final_e = n.model["Store-e"].loc[last_i, stores.index]
|
||||
time_valid = int(glc.loc["investment_period"])
|
||||
time_i = pd.IndexSlice[time_valid, :]
|
||||
lhs = final_e.loc[time_i, :] - final_e.shift(snapshot=1).loc[time_i, :]
|
||||
|
||||
rhs = glc.constant
|
||||
n.model.add_constraints(lhs <= rhs, name=f"GlobalConstraint-{name}")
|
||||
|
||||
|
||||
@ -243,7 +238,6 @@ def add_carbon_budget_constraint(n, snapshots):
|
||||
if glcs.empty:
|
||||
return
|
||||
for name, glc in glcs.iterrows():
|
||||
rhs = glc.constant
|
||||
carattr = glc.carrier_attribute
|
||||
emissions = n.carriers.query(f"{carattr} != 0")[carattr]
|
||||
|
||||
@ -253,15 +247,16 @@ def add_carbon_budget_constraint(n, snapshots):
|
||||
# stores
|
||||
n.stores["carrier"] = n.stores.bus.map(n.buses.carrier)
|
||||
stores = n.stores.query("carrier in @emissions.index and not e_cyclic")
|
||||
time_valid = int(glc.loc["investment_period"])
|
||||
weighting = n.investment_period_weightings.loc[time_valid, "years"]
|
||||
if not stores.empty:
|
||||
last = n.snapshot_weightings.reset_index().groupby("period").last()
|
||||
last_i = last.set_index([last.index, last.timestep]).index
|
||||
final_e = n.model["Store-e"].loc[last_i, stores.index]
|
||||
time_valid = int(glc.loc["investment_period"])
|
||||
time_i = pd.IndexSlice[time_valid, :]
|
||||
weighting = n.investment_period_weightings.loc[time_valid, "years"]
|
||||
lhs = final_e.loc[time_i, :] * weighting
|
||||
|
||||
rhs = glc.constant
|
||||
n.model.add_constraints(lhs <= rhs, name=f"GlobalConstraint-{name}")
|
||||
|
||||
|
||||
@ -350,13 +345,12 @@ def prepare_network(
|
||||
):
|
||||
df.where(df > solve_opts["clip_p_max_pu"], other=0.0, inplace=True)
|
||||
|
||||
load_shedding = solve_opts.get("load_shedding")
|
||||
if load_shedding:
|
||||
if load_shedding := solve_opts.get("load_shedding"):
|
||||
# intersect between macroeconomic and surveybased willingness to pay
|
||||
# http://journal.frontiersin.org/article/10.3389/fenrg.2015.00055/full
|
||||
# TODO: retrieve color and nice name from config
|
||||
n.add("Carrier", "load", color="#dd2e23", nice_name="Load shedding")
|
||||
buses_i = n.buses.query("carrier == 'AC'").index
|
||||
buses_i = n.buses.index
|
||||
if not np.isscalar(load_shedding):
|
||||
# TODO: do not scale via sign attribute (use Eur/MWh instead of Eur/kWh)
|
||||
load_shedding = 1e2 # Eur/kWh
|
||||
@ -803,9 +797,7 @@ def solve_network(n, config, solving, opts="", **kwargs):
|
||||
set_of_options = solving["solver"]["options"]
|
||||
cf_solving = solving["options"]
|
||||
|
||||
kwargs["multi_investment_periods"] = (
|
||||
True if config["foresight"] == "perfect" else False
|
||||
)
|
||||
kwargs["multi_investment_periods"] = config["foresight"] == "perfect"
|
||||
kwargs["solver_options"] = (
|
||||
solving["solver_options"][set_of_options] if set_of_options else {}
|
||||
)
|
||||
@ -847,12 +839,14 @@ def solve_network(n, config, solving, opts="", **kwargs):
|
||||
f"Solving status '{status}' with termination condition '{condition}'"
|
||||
)
|
||||
if "infeasible" in condition:
|
||||
labels = n.model.compute_infeasibilities()
|
||||
logger.info("Labels:\n" + labels)
|
||||
n.model.print_infeasibilities()
|
||||
raise RuntimeError("Solving status 'infeasible'")
|
||||
|
||||
return n
|
||||
|
||||
|
||||
# %%
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
@ -904,7 +898,7 @@ if __name__ == "__main__":
|
||||
log_fn=snakemake.log.solver,
|
||||
)
|
||||
|
||||
logger.info("Maximum memory usage: {}".format(mem.mem_usage))
|
||||
logger.info(f"Maximum memory usage: {mem.mem_usage}")
|
||||
|
||||
n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards)))
|
||||
n.export_to_netcdf(snakemake.output[0])
|
||||
|
@ -7,6 +7,7 @@ Solves linear optimal dispatch in hourly resolution using the capacities of
|
||||
previous capacity expansion in rule :mod:`solve_network`.
|
||||
"""
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
import numpy as np
|
||||
@ -36,7 +37,7 @@ if __name__ == "__main__":
|
||||
configure_logging(snakemake)
|
||||
update_config_with_sector_opts(snakemake.config, snakemake.wildcards.sector_opts)
|
||||
|
||||
opts = (snakemake.wildcards.opts + "-" + snakemake.wildcards.sector_opts).split("-")
|
||||
opts = f"{snakemake.wildcards.opts}-{snakemake.wildcards.sector_opts}".split("-")
|
||||
opts = [o for o in opts if o != ""]
|
||||
solve_opts = snakemake.params.options
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user