Merge remote-tracking branch 'upstream/master' into add_methanol_techs
This commit is contained in:
commit
6a76aa4c6c
@ -33,7 +33,7 @@ repos:
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: codespell
|
||||
args: ['--ignore-regex="(\b[A-Z]+\b)"', '--ignore-words-list=fom,appartment,bage,ore,setis,tabacco,berfore,vor'] # Ignore capital case words, e.g. country codes
|
||||
args: ['--ignore-regex="(\b[A-Z]+\b)"', '--ignore-words-list=fom,appartment,bage,ore,setis,tabacco,berfore,vor,pris'] # Ignore capital case words, e.g. country codes
|
||||
types_or: [python, rst, markdown]
|
||||
files: ^(scripts|doc)/
|
||||
|
||||
|
@ -42,7 +42,7 @@ scenario:
|
||||
ll:
|
||||
- vopt
|
||||
clusters:
|
||||
- 38
|
||||
- 39
|
||||
- 128
|
||||
- 256
|
||||
opts:
|
||||
@ -56,7 +56,7 @@ scenario:
|
||||
- 2050
|
||||
|
||||
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#countries
|
||||
countries: ['AL', 'AT', 'BA', 'BE', 'BG', 'CH', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'IE', 'IT', 'LT', 'LU', 'LV', 'ME', 'MK', 'NL', 'NO', 'PL', 'PT', 'RO', 'RS', 'SE', 'SI', 'SK']
|
||||
countries: ['AL', 'AT', 'BA', 'BE', 'BG', 'CH', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'IE', 'IT', 'LT', 'LU', 'LV', 'ME', 'MK', 'NL', 'NO', 'PL', 'PT', 'RO', 'RS', 'SE', 'SI', 'SK', 'XK']
|
||||
|
||||
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#snapshots
|
||||
snapshots:
|
||||
@ -87,7 +87,7 @@ co2_budget:
|
||||
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#electricity
|
||||
electricity:
|
||||
voltages: [200., 220., 300., 380., 500., 750.]
|
||||
base_network: entsoegridkit
|
||||
base_network: osm-prebuilt
|
||||
gaslimit_enable: false
|
||||
gaslimit: false
|
||||
co2limit_enable: false
|
||||
@ -449,19 +449,26 @@ sector:
|
||||
2045: 0.8
|
||||
2050: 1.0
|
||||
district_heating_loss: 0.15
|
||||
# check these numbers!
|
||||
forward_temperature:
|
||||
default: 90
|
||||
DK: 70
|
||||
SE: 70
|
||||
NO: 70
|
||||
FI: 70
|
||||
return_temperature:
|
||||
default: 50
|
||||
DK: 40
|
||||
SE: 40
|
||||
NO: 40
|
||||
FI: 40
|
||||
supply_temperature_approximation:
|
||||
max_forward_temperature:
|
||||
default: 90
|
||||
DK: 70
|
||||
SE: 70
|
||||
NO: 70
|
||||
min_forward_temperature:
|
||||
default: 68
|
||||
DK: 54
|
||||
SE: 54
|
||||
NO: 54
|
||||
return_temperature:
|
||||
default: 50
|
||||
DK: 40
|
||||
SE: 40
|
||||
NO: 40
|
||||
FI: 40
|
||||
lower_threshold_ambient_temperature: 0
|
||||
upper_threshold_ambient_temperature: 10
|
||||
rolling_window_ambient_temperature: 72
|
||||
heat_source_cooling: 6 #K
|
||||
heat_pump_cop_approximation:
|
||||
refrigerant: ammonia
|
||||
|
@ -15,7 +15,7 @@ scenario:
|
||||
ll:
|
||||
- vopt
|
||||
clusters:
|
||||
- 39
|
||||
- 41
|
||||
- 128
|
||||
- 256
|
||||
opts:
|
||||
@ -26,7 +26,7 @@ scenario:
|
||||
- ''
|
||||
|
||||
# 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']
|
||||
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', 'XK']
|
||||
|
||||
electricity:
|
||||
custom_powerplants: true
|
||||
|
37
data/ammonia_plants.csv
Normal file
37
data/ammonia_plants.csv
Normal file
@ -0,0 +1,37 @@
|
||||
"Plant","Ammonia [kt/a]","Urea [kt/a]","AN [kt/a]","UAN [kt/a]","CAN [kt/a]","Nitrogen fertilisers [kt/a]","MAP [kt/a]","Country","Latitude","Longitude","Date","Source","Comment"
|
||||
"Yara Sluiskil","1700","1300",,,,,,"Netherlands","51.27186","3.84896","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"OCI Geleen","550",,,,,,,"Netherlands","50.99738","5.78497","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"CF Fertilisers Billingham","590",,,,,,,"United Kingdom","53.28149","-2.79744","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/; https://www.cfindustries.com/what-we-do/ammonia-productiont",
|
||||
"Yara Tertre","420",,,,,,,"Belgium","50.47842","3.80285","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"BASF Antwerp","650",,,,,,,"Belgium","51.35583","4.27811","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"Yara Gonfreville","400",,,,,,,"France","49.47982","0.19587","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"Borealis Rouen",,,,,,,,"France","49.41916","1.02584","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"BASF Ludwigshafen","880",,,,,,,"Germany","49.51171","8.42009","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"SKW","1300",,,,,,,"Germany","51.87746","12.5858","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"Yara Brunsbuettel","750",,,,,,,"Germany","53.91152","9.20982","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"Yara Porsgrunn","500",,,,,,,"Norway","59.12444","9.61922","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"Fertiberia Puertollano","400","250",,"200",,,,"Spain","38.67276","-4.0608","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/; https://www.icis.com/explore/resources/news/2021/10/25/10698264/spain-s-fertiberia-urea-ammonia-plants-in-palos-to-remain-shut-on-gas-prices/",
|
||||
"Fertiberia Huelva","200","130",,,,,,"Spain","37.22572","-6.94742","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/; https://www.icis.com/explore/resources/news/2021/10/25/10698264/spain-s-fertiberia-urea-ammonia-plants-in-palos-to-remain-shut-on-gas-prices/",
|
||||
"Yara Ferrara","600","600",,,,,,"Italy","44.86206","11.57922","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"Petrokemija",,"500",,,,,,"Croatia","45.46977","16.78944","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"Neochim","450",,"710",,,,,"Bulgaria","42.20514","25.61547","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"Agopolychim",,,"400","800",,,"300","Bulgaria","43.20652","27.65983","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/; https://ammoniaenergy.org/articles/agropolychim-investing-in-ammonia-distribution-from-bulgaria/","no own ammonia plant"
|
||||
"Azomures","1600",,,,,,,"Romania","46.76187","24.42361","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/","Total for ammonia, AN, NPK, UAN, Urea"
|
||||
"Nitrogenmuvek","497",,,,"1300",,,"Hungary","47.16691","18.12844","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"DUSLO","530",,,,,,,"Slovakia","48.18705","17.9301","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"Grupa Azoty","524","375",,,,,,"Poland","51.45179","21.98174","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"Anwil",,,,,,"965",,"Poland","52.70438","18.96606","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"Achema","1100","785","651","1300","540",,,"Lithuania","55.081","24.32377","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"Lifosa",,,,,,"3241",,"Lithuania","55.27567","24.01652","13-01-2023","https://www.icis.com/explore/resources/news/2023/01/18/10846094/insight-poor-demand-high-costs-stifle-europe-industry-despite-falling-gas-prices/",
|
||||
"Unknown (Linz)",,,,,,,,"Austria","48.28749","14.32369","15-08-2024",,"most likely location"
|
||||
"Unknown (Kothla-Järve)",,,,,,,,"Estonia","59.39984","27.25401","15-08-2024",,"most likely location"
|
||||
"Unknown (Oulu)",,,,,,,,"Finland","65.0033","25.43731","15-08-2024",,"most likely location"
|
||||
"Unknown (Ptolemaida)",,,,,,,,"Greece","40.50701","21.71414","15-08-2024",,"most likely location"
|
||||
"Unknown (Sabac)",,,,,,,,"Serbia","44.76298","19.68426","15-08-2024",,"most likely location"
|
||||
"Unknown (Lugano)",,,,,,,,"Switzerland","46.02709","8.9641","15-08-2024",,"most likely location"
|
||||
"Rivneazot","420",,"540","300","470 ",,,"Ukraine","50.70502","26.1630","28-08-2024","https://interfax.com/newsroom/top-stories/100959/; https://interfax.com/newsroom/top-stories/103386/; https://gmk.center/en/news/ostchem-plants-produced-520-6-thousand-tons-of-fertilizers-in-q1/; http://www.ostchem.com/en/o-kompanii/proizvodstvo/rovno",
|
||||
"Stirol (Horlivka)","1470","940 ","693",,,,,"Ukraine","48.29697","38.10412","28-08-2024","http://ostchem.com/en/o-kompanii/proizvodstvo/stirol",
|
||||
"Severodonetsk Azot","1020","390","550",,,,,"Ukraine","48.94185","38.47399","28-08-2024",,
|
||||
"Odessa Port Plant ","1160","942",,,,,,"Ukraine","46.49460","30.73222","28-08-2024","https://www.spfu.gov.ua/userfiles/files/OPP_Teaser_Eng.pdf",
|
||||
"Cherkazy Azot","963",,"970","500",,,,"Ukraine","49.38241","32.05719","28-08-2024","https://gmk.center/en/news/ostchem-plants-produced-520-6-thousand-tons-of-fertilizers-in-q1/https://gmk.center/en/news/ostchem-plants-produced-520-6-thousand-tons-of-fertilizers-in-q1/; http://ostchem.com/en/o-kompanii/proizvodstvo/azot",
|
||||
"DneproAZOT","660",,,,,,,"Ukraine","48.49004","34.66667","28-08-2024","https://www.alfalaval.com/media/stories/fertilizers/increased-plant-capacity-and-reduced-maintenance-at-fertilizer-plant/",
|
|
26
data/cement-plants-noneu.csv
Normal file
26
data/cement-plants-noneu.csv
Normal file
@ -0,0 +1,26 @@
|
||||
"Company","Site","Cement [kt/a]","Country","Latitude","Longitude","Date","Source","Comment"
|
||||
"Titan Cementarnica USJE AD","Skopje",910,"MK",41.96816,21.45604,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information",
|
||||
"Colacem Albania Sh.p.k","Balldre plant, Lezhe",500,"AL",41.83689,19.63339,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information",
|
||||
"Fushe Kruje Cement Factory, Sh.p.k.","Elbasan cement plant",300,"AL",41.12184,20.04347,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information",
|
||||
"Fushe Kruje Cement Factory, Sh.p.k.","Fushe Kruje plant",1330,"AL",40.46403,19.49948,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information",
|
||||
"Antea Cement Sh.A","Boka e Kuqe, Burizane",1500,"AL",41.54838,19.72574,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information",
|
||||
"Beocinska Fabrika Cementa","Beocin",2000,"RS",45.20952,19.71043,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information",
|
||||
"Holcim (Srbija) a.d.","Novi Popovac",1400,"RS",43.90633,21.50378,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information",
|
||||
"Titan Cementara Kosjerić Ltd.","Kosjeric",750,"RS",44.0125,19.88831,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information",
|
||||
"Sharrcem Sh.p.k.","Hani i Elezit,",850,"XK",42.14704,21.29863,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information",
|
||||
"Fabrika Cementa Lukavac d.d.","Lukavac",800,"BA",44.52596,18.52811,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information",
|
||||
"Tvornica Cementa Kakanj d.d. ","Kakanj",400,"BA",44.11922,18.10897,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information",
|
||||
"Lafarge Ciment Moldova SA","Rezina",1400,"MD",47.79094,28.9553,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information",
|
||||
"ZAO Rybnitsa Cement Comple","Rybnitsa",1100,"MD",47.78115,29.02078,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information",
|
||||
"ChAO Nikolayevtsemen","Mykolayiv",900,"UA",46.94555,32.06641,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information; https://cemark.ua/en/zavodi/prat-mikolajivcement ",
|
||||
"OAO KyivCement ","Kyiv",175,"UA",50.38525,30.55205,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information https://www.dyckerhoff.com.ua/en/dyckerhoff-cement-ukraine ",
|
||||
"OAO YuGCement ","Mykolayiv",1250,"UA",46.98512,31.9317,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information, https://www.dyckerhoff.com.ua/en/yug-cemen",
|
||||
"OOO Cement","Odessa",550,"UA",46.50818,30.67422,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information https://se.ua/en/projects/llc-cement-odessa-cement-plant/ ",
|
||||
"Overin Ltd","Amvrosievka",800,"UA",47.83453,38.46961,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information","assumed equal split"
|
||||
"Overin Ltd","Kamenskoye",800,"UA",48.51783,34.63382,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information","assumed equal split"
|
||||
"Overin Ltd","Kriviy Rih",800,"UA",47.87454,33.43586,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information","assumed equal split"
|
||||
"PAO Eurocement Ukraine","Balakleya, Kharkivs'ka",1000,"UA",49.49314,36.74926,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information https://www.globalcement.com/news/item/13733-update-on-ukraine-february-2022 ",
|
||||
"PAO Ivano-Frankovsktsement","Ivano-Frankivsk ",3600,"UA",48.97709,24.71227,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information",
|
||||
"PAO Kramatorkiy Tsementnyi Zavod PUSHKA ","Kramatorsk, Donets'ka",138,"UA",48.72802,37.54362,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information https://www.cemnet.com/News/story/144668/pushka-ups-cement-production-56-6p-per-cent-to138-400t-in-q1.html ",
|
||||
"PAO Podolsk Cement","Khmel'nyts'ka Oblast' ",2050,"UA",48.7461,26.64664,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information https://cemark.ua/en/zavodi/at-podilskiy-cement ",
|
||||
"PAO Volyn'Cement","Volyn'ska Oblast'",2000,"UA",50.54731,26.25774,"28-08-2024","https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information https://www.dyckerhoff.com.ua/volyn-cement ",
|
|
@ -25,7 +25,7 @@ SE,50.4,
|
||||
GB,2,
|
||||
BY,70,
|
||||
EE,52,5406
|
||||
KO,3,207
|
||||
XK,3,207
|
||||
RO,23,9962
|
||||
SK,54,15000
|
||||
NL,4,9800
|
||||
|
|
@ -29,6 +29,7 @@ PL,1615,1584,1275,1356,1364,1378,1517,1290,1230,1296,1249,1438,1294,1478,1446,15
|
||||
PT,114,114,102,113,86,110,95,79,94,96,107,103,99,109,80,131,106,93,93,97,78,106,104,115,103,98,103,97,112,110,115,116,106,109,109,109,99,139,107,102,89,90,95,104,99,108,85,89,75,87,104,96,104,85,66,88,62,82,96,90,90,78,87,97,103,90,91,91,84,96,80,101,100,81,79,87,79,96,81,72,78,98,75
|
||||
RO,931,939,801,813,874,851,839,815,799,780,736,811,883,948,822,968,810,789,826,731,744,826,890,867,873,706,791,776,858,792,787,798,838,782,752,855,772,836,780,880,801,811,763,807,917,815,882,827,710,700,846,801,848,701,806,869,842,805,740,710,760,721,844,754,799,780,684,695,695,757,793,781,709,662,681,721,720,690,624,648,740,973,611
|
||||
RS,292,305,246,274,285,276,265,263,261,239,222,252,273,300,249,313,248,249,254,231,226,270,283,271,274,233,253,243,267,254,251,246,272,242,243,265,233,265,241,273,251,255,244,253,275,256,268,254,231,220,275,243,263,223,250,270,259,250,237,217,234,217,262,238,265,247,217,214,222,229,251,244,214,192,222,223,232,211,197,212,234,306,192
|
||||
XK,292,305,246,274,285,276,265,263,261,239,222,252,273,300,249,313,248,249,254,231,226,270,283,271,274,233,253,243,267,254,251,246,272,242,243,265,233,265,241,273,251,255,244,253,275,256,268,254,231,220,275,243,263,223,250,270,259,250,237,217,234,217,262,238,265,247,217,214,222,229,251,244,214,192,222,223,232,211,197,212,234,306,192
|
||||
SK,221,219,199,207,209,201,212,202,189,189,178,210,195,217,208,228,192,193,185,185,178,208,213,211,219,179,187,192,203,200,192,188,195,178,178,197,188,204,193,215,191,190,180,193,212,198,207,187,172,173,202,186,191,171,186,204,193,184,177,162,184,174,190,184,191,182,163,161,170,188,175,179,174,142,161,170,176,157,152,158,180,231,150
|
||||
SI,81,77,66,74,72,71,72,69,61,65,61,72,67,73,69,78,65,66,62,61,59,75,75,73,73,62,65,67,71,69,67,68,71,62,61,69,62,71,68,74,67,65,65,69,73,71,71,63,59,58,70,61,63,55,61,71,63,62,62,54,59,55,65,63,67,61,54,57,57,65,58,59,59,46,55,57,58,53,52,53,61,77,51
|
||||
SE,4509,4537,3713,3939,4134,4059,4374,3918,3633,4015,3891,4219,3560,3919,4426,4488,3950,4223,3662,3988,3814,4451,4260,4021,4358,4613,3929,4280,4255,4254,4043,3806,3975,3634,3625,4238,4132,4314,4246,4287,4301,3913,3840,3819,4588,4139,4376,3931,3476,3446,3785,3695,3893,3991,3916,4073,3757,3950,3781,3446,3898,3778,3755,3769,3632,3561,3606,3590,3806,4397,3474,3935,3675,3452,3421,3635,3693,3705,3689,3247,3807,5084,3769
|
||||
|
|
@ -29,6 +29,7 @@ PL,19040.141287526196,13600.003649707409,4232.940272903036,6263.550300160282,117
|
||||
PT,17389.910347609384,7956.13238827081,8339.728858321132,2075.556471824434,3081.9400195534536,5428.965709165979,13519.093138173732,8266.183051247071,2305.611210847845,4751.414112923152,8372.129135066036,5969.31083523099,2397.6586063764958,3916.9962424030286,9654.699566273128,9603.363148222781,4163.162870337118,9179.465624121007,12131.854156488425,23406.646477036124,10635.077955993413,11029.404714084018,16475.917880350513,12087.55769685171,9804.492049893286,26178.184180984652,5669.820254013018,7559.528320921835,15405.930172416956,11163.387795923936,7088.025310785357,10191.330496756716,7128.069257230898,9335.631563569985,5236.13128329125,4572.251664471752,32605.577182903042,149323.86523586328,34294.81803755196,6061.11721308257,5836.654497517657,4843.7020037722705,7814.782411245904,9395.759000250582,14057.157961109715,8192.288977642056,7655.760207241933,9203.645337709624,7637.7450966202805,7971.812432879156,7421.37678917759,2935.2871895485287,6329.939163930326,8820.796560748415,8944.109217212255,14719.27363438586,11050.779819799696,8379.75073967695,5590.525909815882,10485.131539563748,20476.028147427794,7715.162648805314,11939.81827695821,5116.2596877306005,3047.0903835389504,9273.489011971804,5135.313604526994,3331.418010762715,6338.048693933388,12105.616460835923,7097.468638389797,3348.213951094401,11773.920694867731,13465.586888738457,4379.602415677836,11394.463621230614,3104.8789319036796,7216.150544702967,6653.765864361187,5720.580737490315,6685.493238874142,8486.079863634486,8329.192253601708
|
||||
RO,46545.50823036229,35517.718755954746,12007.97895282227,19448.903832688356,20440.973051620913,15132.394486734484,21523.767710605425,32075.68337603852,20312.088233477134,14653.654680967496,19346.344374357534,19295.50358149612,27702.617554877004,24644.67023787785,52797.882559506776,42262.7162454671,34689.01143849651,42583.74114324521,28973.147767939397,36882.64868179707,29063.471368254675,39575.626278602576,31898.858414072816,36283.98261870408,42207.50410750205,41714.957670180156,43270.313090823794,40474.54716426176,53565.91349208634,74865.02611452111,48190.11154819992,57257.26135564704,46523.80416861758,44300.83791323246,54901.1701096736,47361.27151969814,49156.09266449866,56461.30009557872,56062.45724028393,58506.511677323855,48499.732173446595,45901.64074770707,33171.12855766741,38310.49272614435,39377.41586450999,28638.803870927226,29424.553978129992,39429.14347226504,39300.73151290347,27525.04968129815,47095.77682827757,30948.90232192865,32939.14262154816,30155.99148400138,35067.04977301419,35592.25066656211,45790.67404045973,42596.77718301701,39223.35618808953,25767.93476452563,30963.38609617001,30034.908201595936,23323.05819720473,28517.276888551194,41560.85308154171,43999.15897330077,21427.19650317167,25084.131072037453,18450.764512377853,38182.39266803458,20422.517191285966,14090.243196787245,21998.55223596247,30809.187151501046,22071.90474198888,31906.454754357772,20763.073093214778,25620.747974742615,19248.368008063957,23289.011422937554,26669.846131314298,27207.74766143675,29386.08741874402
|
||||
RS,12898.821957973714,11760.375115749226,5762.823681912337,10868.645457667955,6851.647476795101,6489.091511565737,8016.427124526303,11096.059611708006,8784.092785314235,6844.044739629848,5968.673897869134,7450.873145908507,8457.218084424714,10466.134979346216,18700.932768467817,18783.264457747777,9647.157790116991,14650.396388121844,12360.14810912279,11640.673528541236,8882.446980807292,14762.619600006037,18399.930168952076,13646.806400326906,14489.119148714197,14104.804002759012,15462.34970923992,10894.228431882033,15095.088711819322,17853.281396922546,12916.46431873845,14207.379133135786,14418.834370720482,12752.5957180177,15544.588217112372,15820.904121022999,13534.055257847373,15215.146639151637,12996.626380040323,13029.919161637963,10196.668003968522,10284.440766030819,7022.693160251435,8401.249663323453,8435.803252725058,10265.915943082338,8623.546341166757,7782.429841191159,9309.259412625106,4849.32865233776,9480.40891035497,8237.330612702019,6688.9341497267815,7113.796951355988,8945.392918392941,11391.406447517316,8770.78174795334,7797.074404297926,11205.567652241964,7490.638744688466,6890.626375097134,8721.152535625733,6986.899718851523,10014.515393386338,11863.685949406314,12576.12226693591,6930.903954576986,6933.68818306879,8436.351253425808,11680.836931112251,5673.257881932308,4512.930178739657,6094.8735580904795,11616.485592765608,8423.704814584986,9582.260510301834,6280.960312130538,10196.683253538626,5869.428152205924,6637.126459584064,8223.324863109141,9163.49600405833,11744.973584261521
|
||||
XK,12898.821957973714,11760.375115749226,5762.823681912337,10868.645457667955,6851.647476795101,6489.091511565737,8016.427124526303,11096.059611708006,8784.092785314235,6844.044739629848,5968.673897869134,7450.873145908507,8457.218084424714,10466.134979346216,18700.932768467817,18783.264457747777,9647.157790116991,14650.396388121844,12360.14810912279,11640.673528541236,8882.446980807292,14762.619600006037,18399.930168952076,13646.806400326906,14489.119148714197,14104.804002759012,15462.34970923992,10894.228431882033,15095.088711819322,17853.281396922546,12916.46431873845,14207.379133135786,14418.834370720482,12752.5957180177,15544.588217112372,15820.904121022999,13534.055257847373,15215.146639151637,12996.626380040323,13029.919161637963,10196.668003968522,10284.440766030819,7022.693160251435,8401.249663323453,8435.803252725058,10265.915943082338,8623.546341166757,7782.429841191159,9309.259412625106,4849.32865233776,9480.40891035497,8237.330612702019,6688.9341497267815,7113.796951355988,8945.392918392941,11391.406447517316,8770.78174795334,7797.074404297926,11205.567652241964,7490.638744688466,6890.626375097134,8721.152535625733,6986.899718851523,10014.515393386338,11863.685949406314,12576.12226693591,6930.903954576986,6933.68818306879,8436.351253425808,11680.836931112251,5673.257881932308,4512.930178739657,6094.8735580904795,11616.485592765608,8423.704814584986,9582.260510301834,6280.960312130538,10196.683253538626,5869.428152205924,6637.126459584064,8223.324863109141,9163.49600405833,11744.973584261521
|
||||
SK,10526.703178382486,6581.841291454129,2779.6437301689157,6043.293021386589,8068.711762338472,4716.572547513843,4263.788112757618,7436.446538154413,5733.7942336519345,5091.94458281141,6885.47211985414,6956.591212284293,7116.928783228905,4573.269245439668,8169.130903254093,6799.092645889461,7190.199390340817,8819.311158887818,6679.080394471699,8681.76846617681,6714.688996801623,8780.135433744465,9674.052829336924,7510.89080672348,12315.672504913706,11551.288938768861,10658.095118642217,7760.467099195778,7334.701885838525,11743.053621084162,9101.455526104724,11252.254293590808,7089.2297957961755,11692.575497480175,11870.620362608648,8320.411050776946,12664.612697391287,10840.053026355938,9544.145158945727,8285.851845920657,6554.955003499832,6014.385824757616,5119.229272436076,5566.197178944401,8283.751441606055,4576.739002618681,5529.727054286627,4884.285979430572,7030.767074231632,6380.185010419688,6092.06334940043,4789.6919845964085,3988.728835990378,6100.445127127096,6174.336930810738,5839.492530664778,6739.897695678873,6073.547495791424,6239.663814901599,5985.626769812626,5946.910319392802,5350.4706690989715,2897.742723724252,3812.447551889599,5110.734824948982,5466.7571969447445,3822.1224333717755,4189.745228198809,3608.9397299109723,8925.718578619328,5520.297117401385,2338.023634704523,3634.014208205775,5079.021357670912,3789.3939110245783,3599.858750509022,4222.707040620564,3096.1701009538024,2158.8092391216674,4542.203594136759,4220.210061470592,2961.7796555712353,3705.0055429796116
|
||||
SI,8932.252857660058,6769.672897729603,3971.443731895907,6727.0196008878875,5996.060296331706,4552.96378417224,7787.375795346372,9548.071392837826,4890.204133819321,7094.028640574649,11752.798116380785,9378.602450871665,7169.30972105447,8221.267552376507,10568.142173580174,7705.119699907013,8559.440940655051,9496.2682906945,10641.418485889739,13644.09405840664,8756.865265119286,10877.994032024846,13095.473005855994,10408.222250010325,17110.767148034232,13257.44359305617,10163.420442559087,10743.809603872312,11213.570708968457,12419.028940460184,8518.188189494229,14975.496301661744,10217.449212514946,10521.007791805137,10759.209828867228,9699.803414833696,14530.647692616923,14530.715084460895,12439.143395173185,11990.046930204517,9001.647305603035,10111.423546501868,6824.172499114327,10267.968760960974,10233.709492652128,9562.175707725224,11231.941186997657,8178.692540046128,8568.526412713521,8103.883097000008,9639.895318751553,9157.43571368136,6814.50158997294,8089.913064615838,8170.645053083449,10765.044719853075,6713.170108103339,8936.8362631332,9542.147586182518,8964.110093884974,8653.114721452737,8353.75428643612,4558.589088593759,9432.405903987477,6927.92152111369,7408.760392367348,5834.871486466167,9336.912851251047,8839.494837985663,10766.693939731143,5073.937522450624,6475.598951785893,9482.419717110955,13414.771212079502,5906.5584945059145,9942.151265372298,7696.092255607837,9521.835825354157,8476.124990692872,6361.010018809483,7504.908031281684,6349.444363482254,12494.86342976942
|
||||
SE,97729.33612275522,104893.13349064675,152164.30605691054,147567.81837152236,172633.569885874,142454.06079467706,109264.12507808255,145966.80578917114,158733.59492028368,161670.6171803483,134822.12256461562,136958.6213484757,175679.6273876132,133962.36617697845,126787.36233921513,130861.49290945902,151133.2982760823,140247.52694114187,130508.52271890236,137421.63579450184,164132.0529341604,142467.57286064525,135886.87305352974,163762.3962091317,161128.38161511483,148196.28633931337,167892.87677861055,132017.696130452,105953.99289036485,119407.22923207263,147139.6039546916,151309.55114963037,164893.61323375857,137608.18237925606,149284.78771947857,108749.15747050248,131859.531763871,117290.48017785426,131751.97960784068,111117.27409251402,110551.615114603,81550.1135393761,114677.940027603,102356.46697333359,128977.80283219383,94483.98267503879,114937.96457142044,93256.91327642264,96751.29026217168,91074.34139788701,87931.96567208324,96560.83822983531,116746.94389793588,64626.25905820224,75156.91767736348,51489.37512699482,74729.26978432719,134673.01513808029,110440.65771030058,149033.9827088587,143576.83069821307,93040.02354987273,64075.160200006496,102493.08906248632,106664.82884715112,90351.43771324471,94801.81222609026,92445.93458012305,88919.20770998915,108111.72872590217,127440.80298482065,124444.06618883039,98961.91573013023,87913.90602563386,115956.48217115598,95526.84265190935,103459.08985036932,86058.90377748368,99040.9103276256,110493.22773914765,94182.7249029169,169752.66741900297,99896.09236620825
|
||||
|
|
@ -28,4 +28,5 @@ United Kingdom,160.49,1.26,7.39,13.81,0.81,0.21
|
||||
Norway,,,,,2.91,0.334
|
||||
Switzerland,,,,,1,0.849
|
||||
Serbia,,,,,,
|
||||
Kosovo,,,,,,
|
||||
Bosnia Herzegovina,,,,,,
|
||||
|
|
@ -1,32 +0,0 @@
|
||||
# Table 25 from F. Geth et al., An overview of large-scale stationary electricity storage plants in Europe (2015) 1212–1227
|
||||
country,n,p_nom_discharge,p_nom_charge,e_stor
|
||||
AT,19,4.051,3.246,132.41
|
||||
BE,3,1.301,1.196,5.71
|
||||
BG,3,1.399,0.93,11.13
|
||||
HR,3,0.281,0.246,2.34
|
||||
CY,0,-,-,-
|
||||
CZ,3,1.119,1.145,5.72
|
||||
DK,0,-,-,-
|
||||
EE,0,-,-,-
|
||||
FI ,0,-,-,-
|
||||
FR,10,5.512,4.317,83.37
|
||||
DE,34,6.805,6.417,39.12
|
||||
GR,2,0.735,-,4.97
|
||||
HU,0,-,-,-
|
||||
IE,1,0.292,-,1.8
|
||||
IT,25,7.833,7.64,68.27
|
||||
LV,0,-,-,-
|
||||
LT,1,0.9,0.88,10.8
|
||||
LU,1,1.296,1.05,4.92
|
||||
MT,0,-,-,-
|
||||
NL,0,-,-,-
|
||||
PL,6,1.757,1.647,7.96
|
||||
PT,7,1.279,-,40.77
|
||||
RO,5,0.285,0.2,10.2
|
||||
SK,4,1.016,0.79,3.63
|
||||
SI,1,0.185,0.18,0.5
|
||||
ES,26,6.358,5.859,70
|
||||
SE,2,0.091,-,72.12
|
||||
GB,4,2.788,2.65,26.7
|
||||
NO,8,1.273,0.892,399.39
|
||||
CH,20,2.291,1.512,311.48
|
|
@ -1,16 +1,17 @@
|
||||
country,factor
|
||||
BE,0.796
|
||||
BG,0.894
|
||||
CZ,0.827
|
||||
FI,0.936
|
||||
FR,0.71
|
||||
DE,0.871
|
||||
HU,0.913
|
||||
NL,0.868
|
||||
RO,0.909
|
||||
SK,0.9
|
||||
SI,0.913
|
||||
ES,0.897
|
||||
SE,0.851
|
||||
CH,0.87
|
||||
GB,0.656
|
||||
BE,0.883
|
||||
BG,0.876
|
||||
CZ,0.839
|
||||
FI,0.924
|
||||
FR,0.616
|
||||
DE,0.926
|
||||
HU,0.891
|
||||
NL,0.901
|
||||
RO,0.906
|
||||
SK,0.908
|
||||
SI,0.884
|
||||
ES,0.883
|
||||
SE,0.817
|
||||
CH,0.834
|
||||
GB,0.684
|
||||
UA,0.701
|
||||
|
|
15
data/refineries-noneu.csv
Normal file
15
data/refineries-noneu.csv
Normal file
@ -0,0 +1,15 @@
|
||||
"Site","Capacity [bbl/day]","Country","Latitude","Longitude","Date","Source","Comment"
|
||||
"Modrica",1,"BA",44.95978,18.31294,"29-08-2024","https://modricaoil.com/Content/Read/onama?lang=en-US","the only one"
|
||||
"OKTA, Skopje",1,"MK",42.0022,21.65532,"29-08-2024","https://en.wikipedia.org/wiki/OKTA","the only one"
|
||||
"Ballsh",20000,"AL",40.60468,19.75231,"29-08-2024","https://www.trade.gov/country-commercial-guides/albania-oil-and-gas",
|
||||
"Fier",10000,"AL",40.70095,19.54698,"29-08-2024","https://www.trade.gov/country-commercial-guides/albania-oil-and-gas",
|
||||
"Elbasan",5000,"AL",41.08621,20.00762,"29-08-2024","https://www.trade.gov/country-commercial-guides/albania-oil-and-gas",
|
||||
"Pančevo",96000,"RS",44.83051,20.68127,"29-08-2024","https://en.wikipedia.org/wiki/Naftna_Industrija_Srbije",
|
||||
"Novi Sad",52000,"RS",45.27559,19.86733,"29-08-2024","https://en.wikipedia.org/wiki/Naftna_Industrija_Srbije",
|
||||
"Halychyna Refinery (Pryvat), Drohobych",40000,"UA",49.34,23.4851,"29-08-2024","https://en.wikipedia.org/wiki/List_of_oil_refineries",
|
||||
"Kherson Refinery (Alliance)",36000,"UA",46.65946,32.57479,"29-08-2024","https://en.wikipedia.org/wiki/List_of_oil_refineries",
|
||||
"Kremenchuk Refinery (Ukrtatnafta)",368500,"UA",49.15299,33.4327,"29-08-2024","https://en.wikipedia.org/wiki/List_of_oil_refineries",
|
||||
"LINOS Refinery, Lysychansk Oil Refinery (TNK-BP)",320000,"UA",48.84876,38.29979,"29-08-2024","https://en.wikipedia.org/wiki/List_of_oil_refineries",
|
||||
"Lviv Oil Research & Refinery",18000,"UA",49.80662,24.04376,"29-08-2024","https://en.wikipedia.org/wiki/List_of_oil_refineries","capacity estimated based on number of employees"
|
||||
"Naftokhimik Prykarpattya (Pryvat) Nadvirna",39000,"UA",48.62873,24.59924,"29-08-2024","https://en.wikipedia.org/wiki/List_of_oil_refineries",
|
||||
"Odesa Refinery (LUKOIL)",70000,"UA",46.51189,30.68805,"29-08-2024","https://en.wikipedia.org/wiki/List_of_oil_refineries",
|
|
@ -1,30 +0,0 @@
|
||||
AT,66
|
||||
BA,40
|
||||
BE,98
|
||||
BG,74
|
||||
CH,74
|
||||
CZ,73
|
||||
DE,75
|
||||
DK,88
|
||||
EE,68
|
||||
ES,80
|
||||
FI,84
|
||||
FR,80
|
||||
GB,83
|
||||
GR,78
|
||||
HR,59
|
||||
HU,71
|
||||
IE,63
|
||||
IT,69
|
||||
LT,67
|
||||
LU,90
|
||||
LV,67
|
||||
NL,90
|
||||
NO,80
|
||||
PL,61
|
||||
PT,63
|
||||
RO,55
|
||||
RS,56
|
||||
SE,86
|
||||
SI,50
|
||||
SK,54
|
|
@ -1,2 +1,2 @@
|
||||
,Unit,Values,Description
|
||||
countries,--,"Subset of {'AL', 'AT', 'BA', 'BE', 'BG', 'CH', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'IE', 'IT', 'LT', 'LU', 'LV', 'ME', 'MK', 'NL', 'NO', 'PL', 'PT', 'RO', 'RS', 'SE', 'SI', 'SK'}","European countries defined by their `Two-letter country codes (ISO 3166-1) <https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2>`_ which should be included in the energy system model."
|
||||
countries,--,"Subset of {'AL', 'AT', 'BA', 'BE', 'BG', 'CH', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'IE', 'IT', 'LT', 'LU', 'LV', 'ME', 'MK', 'NL', 'NO', 'PL', 'PT', 'RO', 'RS', 'SE', 'SI', 'SK', 'XK'}","European countries defined by their `Two-letter country codes (ISO 3166-1) <https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2>`_ which should be included in the energy system model."
|
||||
|
|
@ -1,6 +1,5 @@
|
||||
description,file/folder,licence,source
|
||||
JRC IDEES database,jrc-idees-2015/,CC BY 4.0,https://ec.europa.eu/jrc/en/potencia/jrc-idees
|
||||
urban/rural fraction,urban_percent.csv,unknown,unknown
|
||||
JRC ENSPRESO biomass potentials,remote,CC BY 4.0,https://data.jrc.ec.europa.eu/dataset/74ed5a04-7d74-4807-9eab-b94774309d9f
|
||||
EEA emission statistics,eea/UNFCCC_v23.csv,EEA standard re-use policy,https://www.eea.europa.eu/data-and-maps/data/national-emissions-reported-to-the-unfccc-and-to-the-eu-greenhouse-gas-monitoring-mechanism-16
|
||||
Eurostat Energy Balances,eurostat-energy_balances-*/,Eurostat,https://ec.europa.eu/eurostat/web/energy/data/energy-balances
|
||||
|
|
@ -9,8 +9,13 @@ district_heating,--,,`prepare_sector_network.py <https://github.com/PyPSA/pypsa-
|
||||
-- potential,--,float,maximum fraction of urban demand which can be supplied by district heating
|
||||
-- progress,--,Dictionary with planning horizons as keys., Increase of today's district heating demand to potential maximum district heating share. Progress = 0 means today's district heating share. Progress = 1 means maximum fraction of urban demand is supplied by district heating
|
||||
-- district_heating_loss,--,float,Share increase in district heat demand in urban central due to heat losses
|
||||
-- forward_temperature,°C,Dictionary with country codes as keys. One key must be 'default'.,Forward temperature in district heating
|
||||
-- return_temperature,°C,Dictionary with country codes as keys. One key must be 'default'.,Return temperature in district heating. Must be lower than forward temperature
|
||||
-- supply_temperature_approximation,,,
|
||||
-- -- max_forward_temperature,°C,Dictionary with country codes as keys. One key must be 'default'., Max. forward temperature in district heating (if ambient temperature lower-or-equal `lower_threshold_ambient_temperature`)
|
||||
-- -- min_forward_temperature,°C,Dictionary with country codes as keys. One key must be 'default'., Min. forward temperature in district heating (if ambient temperature higher-or-equal `upper_threshold_ambient_temperature`)
|
||||
-- -- return_temperature,°C,Dictionary with country codes as keys. One key must be 'default'.,Return temperature in district heating. Must be lower than forward temperature
|
||||
-- -- lower_threshold_ambient_temperature,°C,float, Assume `max_forward_temperature` if ambient temperature is below this threshold
|
||||
-- -- upper_threshold_ambient_temperature,°C,float, Assume `min_forward_temperature` if ambient temperature is above this threshold
|
||||
-- -- rolling_window_ambient_temperature, h, int, Rolling window size for averaging ambient temperature when approximating supply temperature
|
||||
-- heat_source_cooling,K,float,Cooling of heat source for heat pumps
|
||||
-- heat_pump_cop_approximation,,,
|
||||
-- -- refrigerant,--,"{ammonia, isobutane}",Heat pump refrigerant assumed for COP approximation
|
||||
|
|
@ -1,3 +1,4 @@
|
||||
|
||||
..
|
||||
SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors
|
||||
|
||||
@ -11,6 +12,46 @@ Upcoming Release
|
||||
================
|
||||
* Add technology options for methanol, like electricity production from methanol, biomass to methanol, methanol to kerosene, ...
|
||||
|
||||
* Bugfix for passing function arguments in rule :mod:`solve_operations_network`.
|
||||
|
||||
* Represent Kosovo (XK) as separate country.
|
||||
|
||||
* Added data on the locations and capacities of ammonia plants in Europe.
|
||||
This data is used as a spatial distribution key for the ammonia demand.
|
||||
The data manually collected with sources noted in ``data/ammonia_plants.csv``.
|
||||
|
||||
* Added data on the locations and capacities of cement plants in Europe that are
|
||||
not included in the Hotmaps industrial database. The data sourced from the
|
||||
`USGS 2019 Minerals Yearbooks
|
||||
<https://www.usgs.gov/centers/national-minerals-information-center/international-minerals-statistics-and-information>`__
|
||||
of specific countries is used as a spatial distribution key for the cement
|
||||
demand. The data is stored in ``data/cement-plants-noneu.csv``.
|
||||
|
||||
* Added data on the locations and capacities of refineries in Europe that are
|
||||
not included in the Hotmaps industrial database. The data is mostly sourced
|
||||
from the `Wikipedia list of oil refineries
|
||||
<https://en.wikipedia.org/wiki/List_of_oil_refineries>`__. The data is stored
|
||||
in ``data/refineries-noneu.csv``.
|
||||
|
||||
* Included data from the `Global Steel Plant Tracker
|
||||
<https://globalenergymonitor.org/projects/global-steel-plant-tracker/>`__
|
||||
provided by Global Energy Monitor. The data includes among other attributes
|
||||
the locations, ages, operating status, relining dates, manufacturing process
|
||||
and capacities of steel plants in Europe. This data is used as a spatial
|
||||
distribution key for the steel production, which is now separated by process
|
||||
type (EAF, DRI + EAF, integrated).
|
||||
|
||||
* Retrieve share of urban population from `World Bank API
|
||||
<https://data.worldbank.org/indicator/SP.URB.TOTL.IN.ZS>`__. The data
|
||||
originates from the United Nations Population Division. Previously, a file
|
||||
``data/urban_percent.csv`` with an undocumented source was used.
|
||||
|
||||
* Updated country-specific Energy Availability Factors (EAFs) for nuclear power
|
||||
plants based on `IAEA 2021-2023 reported country averages
|
||||
<https://pris.iaea.org/PRIS/WorldStatistics/ThreeYrsEnergyAvailabilityFactor.aspx>`__.
|
||||
|
||||
* Update GEM Europe Gas Tracker to May 2024 version.
|
||||
|
||||
* Add investment period dependent CO2 sequestration potentials
|
||||
|
||||
* Add option to produce hydrogen from solid biomass (flag ``solid biomass to hydrogen``), combined with carbon capture
|
||||
@ -23,6 +64,8 @@ Upcoming Release
|
||||
|
||||
* Update JRC-IDEES-2015 to `JRC-IDEES-2021 <https://publications.jrc.ec.europa.eu/repository/handle/JRC137809>`__. The reference year is changed from 2015 to 2019.
|
||||
|
||||
* Made central heating supply temperatures dynamic based on an adaptation of a reference curve from Pieper et al. (2019) (https://www.sciencedirect.com/science/article/pii/S0360544219305857?via%3Dihub).
|
||||
|
||||
* Added option to use country-specific district heating forward and return temperatures. Defaults to lower temperatures in Scandinavia.
|
||||
|
||||
* Added unsustainable biomass potentials for solid, gaseous, and liquid biomass. The potentials can be phased-out and/or
|
||||
@ -76,7 +119,7 @@ Upcoming Release
|
||||
|
||||
* Enable parallelism in :mod:`determine_availability_matrix_MD_UA.py` and remove plots. This requires the use of temporary files.
|
||||
|
||||
* Added new major feature to create the base_network from OpenStreetMap (OSM) data (PR https://github.com/PyPSA/pypsa-eur/pull/1079). Note that a heuristics based cleaning process is used for lines and links where electrical parameters are incomplete, missing, or ambiguous. Through ``electricity["base_network"]``, the base network can be set to "entsoegridkit" (original default setting, deprecated soon), "osm-prebuilt" (which downloads the latest prebuilt snapshot based on OSM data from Zenodo), or "osm-raw" which retrieves (once) and cleans the raw OSM data and subsequently builds the network. Note that this process may take a few minutes.
|
||||
* Added new major feature to create the base_network from OpenStreetMap (OSM) data (PR https://github.com/PyPSA/pypsa-eur/pull/1079). Note that a heuristics based cleaning process is used for lines and links where electrical parameters are incomplete, missing, or ambiguous. Through ``electricity["base_network"]``, the base network can be set to "entsoegridkit" (now deprecated), "osm-prebuilt" (default, downloads the latest prebuilt snapshot based on OSM data from Zenodo), or "osm-raw" which retrieves (once) and cleans the raw OSM data and subsequently builds the network. Note that this process may take a few minutes.
|
||||
|
||||
* Updated pre-built `weather data cutouts
|
||||
<https://zenodo.org/records/12791128>`__. These are now merged cutouts with
|
||||
|
@ -373,7 +373,7 @@ rule build_transmission_projects:
|
||||
benchmark:
|
||||
benchmarks("build_transmission_projects")
|
||||
resources:
|
||||
mem_mb=2000,
|
||||
mem_mb=4000,
|
||||
threads: 1
|
||||
conda:
|
||||
"../envs/environment.yaml"
|
||||
@ -469,7 +469,6 @@ rule add_electricity:
|
||||
regions=resources("regions_onshore.geojson"),
|
||||
powerplants=resources("powerplants.csv"),
|
||||
hydro_capacities=ancient("data/hydro_capacities.csv"),
|
||||
geth_hydro_capacities="data/geth2015_hydro_capacities.csv",
|
||||
unit_commitment="data/unit_commitment.csv",
|
||||
fuel_price=lambda w: (
|
||||
resources("monthly_fuel_price.csv")
|
||||
|
@ -6,7 +6,7 @@
|
||||
rule build_population_layouts:
|
||||
input:
|
||||
nuts3_shapes=resources("nuts3_shapes.geojson"),
|
||||
urban_percent="data/urban_percent.csv",
|
||||
urban_percent="data/worldbank/API_SP.URB.TOTL.IN.ZS_DS2_en_csv_v2_3403768.csv",
|
||||
cutout=lambda w: "cutouts/"
|
||||
+ CDIR
|
||||
+ config_provider("atlite", "default_cutout")(w)
|
||||
@ -93,10 +93,7 @@ rule build_gas_network:
|
||||
|
||||
rule build_gas_input_locations:
|
||||
input:
|
||||
gem=storage(
|
||||
"https://globalenergymonitor.org/wp-content/uploads/2023/07/Europe-Gas-Tracker-2023-03-v3.xlsx",
|
||||
keep_local=True,
|
||||
),
|
||||
gem="data/gem/Europe-Gas-Tracker-2024-05.xlsx",
|
||||
entry="data/gas_network/scigrid-gas/data/IGGIELGN_BorderPoints.geojson",
|
||||
storage="data/gas_network/scigrid-gas/data/IGGIELGN_Storages.geojson",
|
||||
regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"),
|
||||
@ -215,17 +212,72 @@ rule build_temperature_profiles:
|
||||
"../scripts/build_temperature_profiles.py"
|
||||
|
||||
|
||||
rule build_central_heating_temperature_profiles:
|
||||
params:
|
||||
max_forward_temperature_central_heating=config_provider(
|
||||
"sector",
|
||||
"district_heating",
|
||||
"supply_temperature_approximation",
|
||||
"max_forward_temperature",
|
||||
),
|
||||
min_forward_temperature_central_heating=config_provider(
|
||||
"sector",
|
||||
"district_heating",
|
||||
"supply_temperature_approximation",
|
||||
"min_forward_temperature",
|
||||
),
|
||||
return_temperature_central_heating=config_provider(
|
||||
"sector",
|
||||
"district_heating",
|
||||
"supply_temperature_approximation",
|
||||
"return_temperature",
|
||||
),
|
||||
snapshots=config_provider("snapshots"),
|
||||
lower_threshold_ambient_temperature=config_provider(
|
||||
"sector",
|
||||
"district_heating",
|
||||
"supply_temperature_approximation",
|
||||
"lower_threshold_ambient_temperature",
|
||||
),
|
||||
upper_threshold_ambient_temperature=config_provider(
|
||||
"sector",
|
||||
"district_heating",
|
||||
"supply_temperature_approximation",
|
||||
"upper_threshold_ambient_temperature",
|
||||
),
|
||||
rolling_window_ambient_temperature=config_provider(
|
||||
"sector",
|
||||
"district_heating",
|
||||
"supply_temperature_approximation",
|
||||
"rolling_window_ambient_temperature",
|
||||
),
|
||||
input:
|
||||
temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"),
|
||||
regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"),
|
||||
output:
|
||||
central_heating_forward_temperature_profiles=resources(
|
||||
"central_heating_forward_temperature_profiles_elec_s{simpl}_{clusters}.nc"
|
||||
),
|
||||
central_heating_return_temperature_profiles=resources(
|
||||
"central_heating_return_temperature_profiles_elec_s{simpl}_{clusters}.nc"
|
||||
),
|
||||
resources:
|
||||
mem_mb=20000,
|
||||
log:
|
||||
logs("build_central_heating_temperature_profiles_s{simpl}_{clusters}.log"),
|
||||
benchmark:
|
||||
benchmarks("build_central_heating_temperature_profiles/s{simpl}_{clusters}")
|
||||
conda:
|
||||
"../envs/environment.yaml"
|
||||
script:
|
||||
"../scripts/build_central_heating_temperature_profiles/run.py"
|
||||
|
||||
|
||||
rule build_cop_profiles:
|
||||
params:
|
||||
heat_pump_sink_T_decentral_heating=config_provider(
|
||||
"sector", "heat_pump_sink_T_individual_heating"
|
||||
),
|
||||
forward_temperature_central_heating=config_provider(
|
||||
"sector", "district_heating", "forward_temperature"
|
||||
),
|
||||
return_temperature_central_heating=config_provider(
|
||||
"sector", "district_heating", "return_temperature"
|
||||
),
|
||||
heat_source_cooling_central_heating=config_provider(
|
||||
"sector", "district_heating", "heat_source_cooling"
|
||||
),
|
||||
@ -235,6 +287,12 @@ rule build_cop_profiles:
|
||||
heat_pump_sources=config_provider("sector", "heat_pump_sources"),
|
||||
snapshots=config_provider("snapshots"),
|
||||
input:
|
||||
central_heating_forward_temperature_profiles=resources(
|
||||
"central_heating_forward_temperature_profiles_elec_s{simpl}_{clusters}.nc"
|
||||
),
|
||||
central_heating_return_temperature_profiles=resources(
|
||||
"central_heating_return_temperature_profiles_elec_s{simpl}_{clusters}.nc"
|
||||
),
|
||||
temp_soil_total=resources("temp_soil_total_elec_s{simpl}_{clusters}.nc"),
|
||||
temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"),
|
||||
regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"),
|
||||
@ -578,10 +636,14 @@ rule build_industrial_distribution_key:
|
||||
input:
|
||||
regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"),
|
||||
clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"),
|
||||
hotmaps_industrial_database=storage(
|
||||
hotmaps=storage(
|
||||
"https://gitlab.com/hotmaps/industrial_sites/industrial_sites_Industrial_Database/-/raw/master/data/Industrial_Database.csv",
|
||||
keep_local=True,
|
||||
),
|
||||
gem_gspt="data/gem/Global-Steel-Plant-Tracker-April-2024-Standard-Copy-V1.xlsx",
|
||||
ammonia="data/ammonia_plants.csv",
|
||||
cement_supplement="data/cement-plants-noneu.csv",
|
||||
refineries_supplement="data/refineries-noneu.csv",
|
||||
output:
|
||||
industrial_distribution_key=resources(
|
||||
"industrial_distribution_key_elec_s{simpl}_{clusters}.csv"
|
||||
|
@ -259,6 +259,30 @@ if config["enable"]["retrieve"]:
|
||||
|
||||
|
||||
|
||||
if config["enable"]["retrieve"]:
|
||||
|
||||
rule retrieve_worldbank_urban_population:
|
||||
params:
|
||||
zip="data/worldbank/API_SP.URB.TOTL.IN.ZS_DS2_en_csv_v2_3403768.zip",
|
||||
output:
|
||||
gpkg="data/worldbank/API_SP.URB.TOTL.IN.ZS_DS2_en_csv_v2_3403768.csv",
|
||||
run:
|
||||
import os
|
||||
import requests
|
||||
|
||||
response = requests.get(
|
||||
"https://api.worldbank.org/v2/en/indicator/SP.URB.TOTL.IN.ZS?downloadformat=csv",
|
||||
params={"name": "API_SP.URB.TOTL.IN.ZS_DS2_en_csv_v2_3403768.zip"},
|
||||
)
|
||||
|
||||
with open(params["zip"], "wb") as f:
|
||||
f.write(response.content)
|
||||
output_folder = Path(params["zip"]).parent
|
||||
unpack_archive(params["zip"], output_folder)
|
||||
os.remove(params["zip"])
|
||||
|
||||
|
||||
|
||||
if config["enable"]["retrieve"]:
|
||||
|
||||
# Download directly from naciscdn.org which is a redirect from naturalearth.com
|
||||
@ -280,6 +304,40 @@ if config["enable"]["retrieve"]:
|
||||
os.remove(params["zip"])
|
||||
|
||||
|
||||
if config["enable"]["retrieve"]:
|
||||
|
||||
rule retrieve_gem_europe_gas_tracker:
|
||||
output:
|
||||
"data/gem/Europe-Gas-Tracker-2024-05.xlsx",
|
||||
run:
|
||||
import requests
|
||||
|
||||
response = requests.get(
|
||||
"https://globalenergymonitor.org/wp-content/uploads/2024/05/Europe-Gas-Tracker-2024-05.xlsx",
|
||||
headers={"User-Agent": "Mozilla/5.0"},
|
||||
)
|
||||
with open(output[0], "wb") as f:
|
||||
f.write(response.content)
|
||||
|
||||
|
||||
|
||||
if config["enable"]["retrieve"]:
|
||||
|
||||
rule retrieve_gem_steel_plant_tracker:
|
||||
output:
|
||||
"data/gem/Global-Steel-Plant-Tracker-April-2024-Standard-Copy-V1.xlsx",
|
||||
run:
|
||||
import requests
|
||||
|
||||
response = requests.get(
|
||||
"https://globalenergymonitor.org/wp-content/uploads/2024/04/Global-Steel-Plant-Tracker-April-2024-Standard-Copy-V1.xlsx",
|
||||
headers={"User-Agent": "Mozilla/5.0"},
|
||||
)
|
||||
with open(output[0], "wb") as f:
|
||||
f.write(response.content)
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
@ -41,6 +41,13 @@ rule solve_network:
|
||||
rule solve_operations_network:
|
||||
params:
|
||||
options=config_provider("solving", "options"),
|
||||
solving=config_provider("solving"),
|
||||
foresight=config_provider("foresight"),
|
||||
planning_horizons=config_provider("scenario", "planning_horizons"),
|
||||
co2_sequestration_potential=config_provider(
|
||||
"sector", "co2_sequestration_potential", default=200
|
||||
),
|
||||
custom_extra_functionality=input_custom_extra_functionality,
|
||||
input:
|
||||
network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc",
|
||||
output:
|
||||
|
@ -507,7 +507,8 @@ def generate_periodic_profiles(dt_index, nodes, weekly_profile, localize=None):
|
||||
week_df = pd.DataFrame(index=dt_index, columns=nodes)
|
||||
|
||||
for node in nodes:
|
||||
timezone = pytz.timezone(pytz.country_timezones[node[:2]][0])
|
||||
ct = node[:2] if node[:2] != "XK" else "RS"
|
||||
timezone = pytz.timezone(pytz.country_timezones[ct][0])
|
||||
tz_dt_index = dt_index.tz_convert(timezone)
|
||||
week_df[node] = [24 * dt.weekday() + dt.hour for dt in tz_dt_index]
|
||||
week_df[node] = week_df[node].map(weekly_profile)
|
||||
|
@ -51,7 +51,6 @@ Inputs
|
||||
.. image:: img/hydrocapacities.png
|
||||
:scale: 34 %
|
||||
|
||||
- ``data/geth2015_hydro_capacities.csv``: alternative to capacities above; not currently used!
|
||||
- ``resources/electricity_demand.csv`` Hourly per-country electricity demand profiles.
|
||||
- ``resources/regions_onshore.geojson``: confer :ref:`busregions`
|
||||
- ``resources/nuts3_shapes.geojson``: confer :ref:`shapes`
|
||||
|
@ -1008,12 +1008,12 @@ if __name__ == "__main__":
|
||||
)
|
||||
|
||||
shapes.to_file(snakemake.output.regions_onshore)
|
||||
append_bus_shapes(n, shapes, "onshore")
|
||||
# append_bus_shapes(n, shapes, "onshore")
|
||||
|
||||
if offshore_regions:
|
||||
shapes = pd.concat(offshore_regions, ignore_index=True)
|
||||
shapes.to_file(snakemake.output.regions_offshore)
|
||||
append_bus_shapes(n, shapes, "offshore")
|
||||
# append_bus_shapes(n, shapes, "offshore")
|
||||
else:
|
||||
offshore_shapes.to_frame().to_file(snakemake.output.regions_offshore)
|
||||
|
||||
|
@ -88,9 +88,11 @@ def build_nuts_population_data(year=2013):
|
||||
pop = pd.concat([pop, pd.concat(swiss)]).to_frame("total")
|
||||
|
||||
# add missing manually
|
||||
pop["AL"] = 2893
|
||||
pop["BA"] = 3871
|
||||
pop["RS"] = 7210
|
||||
pop["AL"] = 2778
|
||||
pop["BA"] = 3234
|
||||
pop["RS"] = 6664
|
||||
pop["ME"] = 617
|
||||
pop["XK"] = 1587
|
||||
|
||||
pop["ct"] = pop.index.str[:2]
|
||||
|
||||
@ -149,10 +151,6 @@ def enspreso_biomass_potentials(year=2020, scenario="ENS_Low"):
|
||||
|
||||
bio = dff.groupby(["NUTS2", "commodity"]).potential.sum().unstack()
|
||||
|
||||
# currently Serbia and Kosovo not split, so aggregate
|
||||
bio.loc["RS"] += bio.loc["XK"]
|
||||
bio.drop("XK", inplace=True)
|
||||
|
||||
return bio
|
||||
|
||||
|
||||
@ -199,7 +197,7 @@ def build_nuts2_shapes():
|
||||
)
|
||||
|
||||
countries = gpd.read_file(snakemake.input.country_shapes).set_index("name")
|
||||
missing_iso2 = countries.index.intersection(["AL", "RS", "BA"])
|
||||
missing_iso2 = countries.index.intersection(["AL", "RS", "XK", "BA"])
|
||||
missing = countries.loc[missing_iso2]
|
||||
|
||||
nuts2.rename(index={"ME00": "ME", "MK00": "MK"}, inplace=True)
|
||||
|
@ -0,0 +1,218 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import pandas as pd
|
||||
import xarray as xr
|
||||
|
||||
|
||||
class CentralHeatingTemperatureApproximator:
|
||||
"""
|
||||
A class to approximate central heating temperatures based on ambient
|
||||
temperature.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
ambient_temperature : xr.DataArray
|
||||
The ambient temperature data.
|
||||
max_forward_temperature : xr.DataArray
|
||||
The maximum forward temperature.
|
||||
min_forward_temperature : xr.DataArray
|
||||
The minimum forward temperature.
|
||||
fixed_return_temperature : xr.DataArray
|
||||
The fixed return temperature.
|
||||
lower_threshold_ambient_temperature : float
|
||||
Forward temperature is `max_forward_temperature` for ambient temperatures lower-or-equal this threshold.
|
||||
upper_threshold_ambient_temperature : float
|
||||
Forward temperature is `min_forward_temperature` for ambient temperatures higher-or-equal this threshold.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
ambient_temperature: xr.DataArray,
|
||||
max_forward_temperature: float,
|
||||
min_forward_temperature: float,
|
||||
fixed_return_temperature: float,
|
||||
lower_threshold_ambient_temperature: float,
|
||||
upper_threshold_ambient_temperature: float,
|
||||
rolling_window_ambient_temperature: int,
|
||||
) -> None:
|
||||
"""
|
||||
Initialize the CentralHeatingTemperatureApproximator.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ambient_temperature : xr.DataArray
|
||||
The ambient temperature data.
|
||||
max_forward_temperature : xr.DataArray
|
||||
The maximum forward temperature.
|
||||
min_forward_temperature : xr.DataArray
|
||||
The minimum forward temperature.
|
||||
fixed_return_temperature : xr.DataArray
|
||||
The fixed return temperature.
|
||||
lower_threshold_ambient_temperature : float
|
||||
Forward temperature is `max_forward_temperature` for ambient temperatures lower-or-equal this threshold.
|
||||
upper_threshold_ambient_temperature : float
|
||||
Forward temperature is `min_forward_temperature` for ambient temperatures higher-or-equal this threshold.
|
||||
rolling_window_ambient_temperature : int
|
||||
Rolling window size for averaging ambient temperature.
|
||||
"""
|
||||
self._ambient_temperature = ambient_temperature
|
||||
self.max_forward_temperature = max_forward_temperature
|
||||
self.min_forward_temperature = min_forward_temperature
|
||||
self.fixed_return_temperature = fixed_return_temperature
|
||||
self.lower_threshold_ambient_temperature = lower_threshold_ambient_temperature
|
||||
self.upper_threshold_ambient_temperature = upper_threshold_ambient_temperature
|
||||
self.rolling_window_ambient_temperature = rolling_window_ambient_temperature
|
||||
|
||||
def ambient_temperature_rolling_mean(self) -> xr.DataArray:
|
||||
"""
|
||||
Property to get ambient temperature.
|
||||
|
||||
Returns
|
||||
-------
|
||||
xr.DataArray
|
||||
Rolling mean of ambient temperature input.
|
||||
"""
|
||||
# bfill to avoid NAs in the beginning
|
||||
return (
|
||||
self._ambient_temperature.rolling(
|
||||
time=self.rolling_window_ambient_temperature
|
||||
)
|
||||
.mean(skip_na=True)
|
||||
.bfill(dim="time")
|
||||
)
|
||||
|
||||
@property
|
||||
def forward_temperature(self) -> xr.DataArray:
|
||||
"""
|
||||
Property to get dynamic forward temperature.
|
||||
|
||||
Returns
|
||||
-------
|
||||
xr.DataArray
|
||||
Dynamic forward temperatures
|
||||
"""
|
||||
return self._approximate_forward_temperature()
|
||||
|
||||
@property
|
||||
def return_temperature(self) -> float:
|
||||
"""
|
||||
Property to get return temperature.
|
||||
|
||||
Returns
|
||||
-------
|
||||
float
|
||||
Return temperature.
|
||||
"""
|
||||
return self._approximate_return_temperature()
|
||||
|
||||
def _approximate_forward_temperature(self) -> xr.DataArray:
|
||||
"""
|
||||
Approximate dynamic forward temperature based on reference curve. Adapted from [Pieper et al. (2019)](https://doi.org/10.1016/j.energy.2019.03.165).
|
||||
|
||||
Returns
|
||||
-------
|
||||
xr.DataArray
|
||||
Dynamic forward temperatures.
|
||||
"""
|
||||
|
||||
forward_temperature = xr.where(
|
||||
self.ambient_temperature_rolling_mean()
|
||||
<= self.lower_threshold_ambient_temperature,
|
||||
self.max_forward_temperature,
|
||||
xr.where(
|
||||
self.ambient_temperature_rolling_mean()
|
||||
>= self.upper_threshold_ambient_temperature,
|
||||
self.min_forward_temperature,
|
||||
self.min_forward_temperature
|
||||
+ (self.max_forward_temperature - self.min_forward_temperature)
|
||||
* (
|
||||
self.upper_threshold_ambient_temperature
|
||||
- self.ambient_temperature_rolling_mean()
|
||||
)
|
||||
/ (
|
||||
self.upper_threshold_ambient_temperature
|
||||
- self.lower_threshold_ambient_temperature
|
||||
),
|
||||
),
|
||||
)
|
||||
return forward_temperature
|
||||
|
||||
def _approximate_return_temperature(self) -> float:
|
||||
"""
|
||||
Approximate return temperature.
|
||||
|
||||
Returns
|
||||
-------
|
||||
float
|
||||
Return temperature.
|
||||
"""
|
||||
return self.fixed_return_temperature
|
||||
|
||||
@property
|
||||
def forward_temperature(self) -> xr.DataArray:
|
||||
"""
|
||||
Property to get dynamic forward temperature.
|
||||
|
||||
Returns
|
||||
-------
|
||||
xr.DataArray
|
||||
Dynamic forward temperatures.
|
||||
"""
|
||||
return self._approximate_forward_temperature()
|
||||
|
||||
@property
|
||||
def return_temperature(self) -> float:
|
||||
"""
|
||||
Property to get return temperature.
|
||||
|
||||
Returns
|
||||
-------
|
||||
float
|
||||
Return temperature.
|
||||
"""
|
||||
return self._approximate_return_temperature()
|
||||
|
||||
def _approximate_forward_temperature(self) -> xr.DataArray:
|
||||
"""
|
||||
Approximate dynamic forward temperature.
|
||||
|
||||
Returns
|
||||
-------
|
||||
xr.DataArray
|
||||
Dynamic forward temperatures.
|
||||
"""
|
||||
forward_temperature = xr.where(
|
||||
self.ambient_temperature_rolling_mean()
|
||||
<= self.lower_threshold_ambient_temperature,
|
||||
self.max_forward_temperature,
|
||||
xr.where(
|
||||
self.ambient_temperature_rolling_mean()
|
||||
>= self.upper_threshold_ambient_temperature,
|
||||
self.min_forward_temperature,
|
||||
self.min_forward_temperature
|
||||
+ (self.max_forward_temperature - self.min_forward_temperature)
|
||||
* (
|
||||
self.upper_threshold_ambient_temperature
|
||||
- self.ambient_temperature_rolling_mean()
|
||||
)
|
||||
/ (
|
||||
self.upper_threshold_ambient_temperature
|
||||
- self.lower_threshold_ambient_temperature
|
||||
),
|
||||
),
|
||||
)
|
||||
return forward_temperature
|
||||
|
||||
def _approximate_return_temperature(self) -> float:
|
||||
"""
|
||||
Approximate return temperature.
|
||||
|
||||
Returns
|
||||
-------
|
||||
float
|
||||
Return temperature.
|
||||
"""
|
||||
return self.fixed_return_temperature
|
147
scripts/build_central_heating_temperature_profiles/run.py
Normal file
147
scripts/build_central_heating_temperature_profiles/run.py
Normal file
@ -0,0 +1,147 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
Approximate district heating forward and return temperature profiles based on
|
||||
ambient temperature. The method is based on a reference curve from Pieper et
|
||||
al. 2019, where for ambient temperatures below 0C, the highest possible forward
|
||||
temperature is assumed and vice versa for temperatures above 10C. Between these
|
||||
threshold levels, forward temperatures are linearly interpolated.
|
||||
|
||||
By default, temperature levels are increased for non-Scandinavian countries.
|
||||
The default ratios between min. and max. forward temperatures is based on AGFW-Hauptbericht 2022.
|
||||
|
||||
Relevant Settings
|
||||
-----------------
|
||||
|
||||
.. code:: yaml
|
||||
sector:
|
||||
district_heating:
|
||||
max_forward_temperature:
|
||||
min_forward_temperature:
|
||||
return_temperature:
|
||||
Inputs
|
||||
------
|
||||
- `resources/<run_name>/temp_air_total`: Air temperature
|
||||
|
||||
Outputs
|
||||
-------
|
||||
- `resources/<run_name>/central_heating_temperature_profiles.nc`:
|
||||
|
||||
References
|
||||
----------
|
||||
- Pieper, et al. (2019): "Assessment of a combination of three heat sources for heat pumps to supply district heating" (https://doi.org/10.1016/j.energy.2019.03.165).
|
||||
- AGFW (2022): "Hauptbericht 2022" (https://www.agfw.de/zahlen-und-statistiken/agfw-hauptbericht)
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
import geopandas as gpd
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import xarray as xr
|
||||
from _helpers import set_scenario_config
|
||||
from central_heating_temperature_approximator import (
|
||||
CentralHeatingTemperatureApproximator,
|
||||
)
|
||||
|
||||
|
||||
def get_country_from_node_name(node_name: str) -> str:
|
||||
return node_name[:2]
|
||||
|
||||
|
||||
def map_temperature_dict_to_onshore_regions(
|
||||
supply_temperature_by_country: dict,
|
||||
regions_onshore: pd.Index,
|
||||
snapshots: pd.DatetimeIndex,
|
||||
) -> xr.DataArray:
|
||||
"""
|
||||
Map dictionary of temperatures to onshore regions.
|
||||
|
||||
Parameters:
|
||||
----------
|
||||
supply_temperature_by_country : dictionary
|
||||
Dictionary with temperatures as values and country keys as keys. One key must be named "default"
|
||||
regions_onshore : pd.Index
|
||||
Names of onshore regions
|
||||
snapshots : pd.DatetimeIndex
|
||||
Time stamps
|
||||
|
||||
Returns:
|
||||
-------
|
||||
xr.DataArray
|
||||
The dictionary values mapped to onshore regions with onshore regions as coordinates.
|
||||
"""
|
||||
return xr.DataArray(
|
||||
[
|
||||
[
|
||||
(
|
||||
supply_temperature_by_country[get_country_from_node_name(node_name)]
|
||||
if get_country_from_node_name(node_name)
|
||||
in supply_temperature_by_country.keys()
|
||||
else supply_temperature_by_country["default"]
|
||||
)
|
||||
for node_name in regions_onshore.values
|
||||
]
|
||||
# pass both nodes and snapshots as dimensions to preserve correct data structure
|
||||
for _ in snapshots
|
||||
],
|
||||
dims=["time", "name"],
|
||||
coords={"time": snapshots, "name": regions_onshore},
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
|
||||
snakemake = mock_snakemake(
|
||||
"build_cop_profiles",
|
||||
simpl="",
|
||||
clusters=48,
|
||||
)
|
||||
|
||||
set_scenario_config(snakemake)
|
||||
|
||||
# map forward and return temperatures specified on country-level to onshore regions
|
||||
regions_onshore = gpd.read_file(snakemake.input.regions_onshore)["name"]
|
||||
snapshots = pd.date_range(freq="h", **snakemake.params.snapshots)
|
||||
max_forward_temperature_central_heating_by_node_and_time: xr.DataArray = (
|
||||
map_temperature_dict_to_onshore_regions(
|
||||
supply_temperature_by_country=snakemake.params.max_forward_temperature_central_heating,
|
||||
regions_onshore=regions_onshore,
|
||||
snapshots=snapshots,
|
||||
)
|
||||
)
|
||||
min_forward_temperature_central_heating_by_node_and_time: xr.DataArray = (
|
||||
map_temperature_dict_to_onshore_regions(
|
||||
supply_temperature_by_country=snakemake.params.min_forward_temperature_central_heating,
|
||||
regions_onshore=regions_onshore,
|
||||
snapshots=snapshots,
|
||||
)
|
||||
)
|
||||
return_temperature_central_heating_by_node_and_time: xr.DataArray = (
|
||||
map_temperature_dict_to_onshore_regions(
|
||||
supply_temperature_by_country=snakemake.params.return_temperature_central_heating,
|
||||
regions_onshore=regions_onshore,
|
||||
snapshots=snapshots,
|
||||
)
|
||||
)
|
||||
|
||||
central_heating_temperature_approximator = CentralHeatingTemperatureApproximator(
|
||||
ambient_temperature=xr.open_dataarray(snakemake.input.temp_air_total),
|
||||
max_forward_temperature=max_forward_temperature_central_heating_by_node_and_time,
|
||||
min_forward_temperature=min_forward_temperature_central_heating_by_node_and_time,
|
||||
fixed_return_temperature=return_temperature_central_heating_by_node_and_time,
|
||||
lower_threshold_ambient_temperature=snakemake.params.lower_threshold_ambient_temperature,
|
||||
upper_threshold_ambient_temperature=snakemake.params.upper_threshold_ambient_temperature,
|
||||
rolling_window_ambient_temperature=snakemake.params.rolling_window_ambient_temperature,
|
||||
)
|
||||
|
||||
central_heating_temperature_approximator.forward_temperature.to_netcdf(
|
||||
snakemake.output.central_heating_forward_temperature_profiles
|
||||
)
|
||||
central_heating_temperature_approximator.return_temperature.to_netcdf(
|
||||
snakemake.output.central_heating_return_temperature_profiles
|
||||
)
|
@ -53,47 +53,6 @@ from DecentralHeatingCopApproximator import DecentralHeatingCopApproximator
|
||||
from scripts.definitions.heat_system_type import HeatSystemType
|
||||
|
||||
|
||||
def map_temperature_dict_to_onshore_regions(
|
||||
supply_temperature_by_country: dict,
|
||||
regions_onshore: pd.Index,
|
||||
snapshots: pd.DatetimeIndex,
|
||||
) -> xr.DataArray:
|
||||
"""
|
||||
Map dictionary of temperatures to onshore regions.
|
||||
|
||||
Parameters:
|
||||
----------
|
||||
supply_temperature_by_country : dictionary
|
||||
Dictionary with temperatures as values and country keys as keys. One key must be named "default"
|
||||
regions_onshore : pd.Index
|
||||
Names of onshore regions
|
||||
snapshots : pd.DatetimeIndex
|
||||
Time stamps
|
||||
|
||||
Returns:
|
||||
-------
|
||||
xr.DataArray
|
||||
The dictionary values mapped to onshore regions with onshore regions as coordinates.
|
||||
"""
|
||||
return xr.DataArray(
|
||||
[
|
||||
[
|
||||
(
|
||||
supply_temperature_by_country[get_country_from_node_name(node_name)]
|
||||
if get_country_from_node_name(node_name)
|
||||
in supply_temperature_by_country.keys()
|
||||
else supply_temperature_by_country["default"]
|
||||
)
|
||||
for node_name in regions_onshore.values
|
||||
]
|
||||
# pass both nodes and snapshots as dimensions to preserve correct data structure
|
||||
for _ in snapshots
|
||||
],
|
||||
dims=["time", "name"],
|
||||
coords={"time": snapshots, "name": regions_onshore},
|
||||
)
|
||||
|
||||
|
||||
def get_cop(
|
||||
heat_system_type: str,
|
||||
heat_source: str,
|
||||
@ -154,20 +113,13 @@ if __name__ == "__main__":
|
||||
# map forward and return temperatures specified on country-level to onshore regions
|
||||
regions_onshore = gpd.read_file(snakemake.input.regions_onshore)["name"]
|
||||
snapshots = pd.date_range(freq="h", **snakemake.params.snapshots)
|
||||
forward_temperature_central_heating_by_node_and_time: xr.DataArray = (
|
||||
map_temperature_dict_to_onshore_regions(
|
||||
supply_temperature_by_country=snakemake.params.forward_temperature_central_heating,
|
||||
regions_onshore=regions_onshore,
|
||||
snapshots=snapshots,
|
||||
)
|
||||
central_heating_forward_temperature: xr.DataArray = xr.open_dataarray(
|
||||
snakemake.input.central_heating_forward_temperature_profiles
|
||||
)
|
||||
return_temperature_central_heating_by_node_and_time: xr.DataArray = (
|
||||
map_temperature_dict_to_onshore_regions(
|
||||
supply_temperature_by_country=snakemake.params.return_temperature_central_heating,
|
||||
regions_onshore=regions_onshore,
|
||||
snapshots=snapshots,
|
||||
)
|
||||
central_heating_return_temperature: xr.DataArray = xr.open_dataarray(
|
||||
snakemake.input.central_heating_return_temperature_profiles
|
||||
)
|
||||
|
||||
cop_all_system_types = []
|
||||
for heat_system_type, heat_sources in snakemake.params.heat_pump_sources.items():
|
||||
cop_this_system_type = []
|
||||
@ -179,8 +131,8 @@ if __name__ == "__main__":
|
||||
heat_system_type=heat_system_type,
|
||||
heat_source=heat_source,
|
||||
source_inlet_temperature_celsius=source_inlet_temperature_celsius,
|
||||
forward_temperature_by_node_and_time=forward_temperature_central_heating_by_node_and_time,
|
||||
return_temperature_by_node_and_time=return_temperature_central_heating_by_node_and_time,
|
||||
forward_temperature_by_node_and_time=central_heating_forward_temperature,
|
||||
return_temperature_by_node_and_time=central_heating_return_temperature,
|
||||
)
|
||||
cop_this_system_type.append(cop_da)
|
||||
cop_all_system_types.append(
|
||||
|
@ -192,9 +192,9 @@ def manual_adjustment(load, fn_load, countries):
|
||||
if "ME" in load:
|
||||
load["BA"] = load.HR * (11.0 / 16.2)
|
||||
|
||||
if ("KV" not in load or load.KV.isnull().values.all()) and "KV" in countries:
|
||||
if "XK" not in load and "XK" in countries:
|
||||
if "RS" in load:
|
||||
load["KV"] = load["RS"] * (4.8 / 27.0)
|
||||
load["XK"] = load["RS"] * (4.8 / 27.0)
|
||||
|
||||
copy_timeslice(load, "GR", "2015-08-11 21:00", "2015-08-15 20:00", Delta(weeks=1))
|
||||
copy_timeslice(load, "AT", "2018-12-31 22:00", "2019-01-01 22:00", Delta(days=2))
|
||||
@ -311,8 +311,8 @@ if __name__ == "__main__":
|
||||
logger.info("Supplement missing data with synthetic data.")
|
||||
fn = snakemake.input.synthetic
|
||||
synthetic_load = pd.read_csv(fn, index_col=0, parse_dates=True)
|
||||
# "UA" does not appear in synthetic load data
|
||||
countries = list(set(countries) - set(["UA", "MD"]))
|
||||
# UA, MD, XK do not appear in synthetic load data
|
||||
countries = list(set(countries) - set(["UA", "MD", "XK"]))
|
||||
synthetic_load = synthetic_load.loc[snapshots, countries]
|
||||
load = load.combine_first(synthetic_load)
|
||||
|
||||
|
@ -1065,9 +1065,11 @@ def build_eurostat_co2(eurostat: pd.DataFrame, year: int = 1990) -> pd.Series:
|
||||
specific_emissions = pd.Series(index=eurostat.columns, dtype=float)
|
||||
|
||||
# emissions in tCO2_equiv per MWh_th
|
||||
specific_emissions["Solid fuels"] = 0.36 # Approximates coal
|
||||
specific_emissions["Oil (total)"] = 0.285 # Average of distillate and residue
|
||||
specific_emissions["Gas"] = 0.2 # For natural gas
|
||||
specific_emissions["Solid fossil fuels"] = 0.36 # Approximates coal
|
||||
specific_emissions["Oil and petroleum products"] = (
|
||||
0.285 # Average of distillate and residue
|
||||
)
|
||||
specific_emissions["Natural gas"] = 0.2 # For natural gas
|
||||
|
||||
return eurostat_year.multiply(specific_emissions).sum(axis=1)
|
||||
|
||||
@ -1099,7 +1101,9 @@ def build_co2_totals(
|
||||
|
||||
co2 = eea_co2.reindex(countries)
|
||||
|
||||
for ct in pd.Index(countries).intersection(["BA", "RS", "AL", "ME", "MK"]):
|
||||
for ct in pd.Index(countries).intersection(
|
||||
["BA", "RS", "XK", "AL", "ME", "MK", "UA", "MD"]
|
||||
):
|
||||
mappings = {
|
||||
"electricity": (ct, "+", "Electricity & heat generation", np.nan),
|
||||
"residential non-elec": (ct, "+", "+", "Residential"),
|
||||
@ -1451,10 +1455,10 @@ def update_residential_from_eurostat(energy: pd.DataFrame) -> pd.DataFrame:
|
||||
for nrg_name, (code, siec) in nrg_type.items():
|
||||
|
||||
# Select energy balance type, rename columns and countries to match IDEES data,
|
||||
# convert TJ to TWh, and drop XK data already since included in RS data
|
||||
# convert TJ to TWh
|
||||
col_to_rename = {"geo": "country", "TIME_PERIOD": "year", "OBS_VALUE": nrg_name}
|
||||
idx_to_rename = {v: k for k, v in idees_rename.items()}
|
||||
drop_geo = ["EU27_2020", "EA20", "XK"]
|
||||
drop_geo = ["EU27_2020", "EA20"]
|
||||
nrg_data = eurostat_households.query(
|
||||
"nrg_bal == @code and siec == @siec and geo not in @drop_geo and OBS_VALUE > 0"
|
||||
).copy()
|
||||
|
@ -36,15 +36,20 @@ def build_gem_lng_data(fn):
|
||||
"Gran Canaria LNG Terminal",
|
||||
]
|
||||
|
||||
status_list = ["Operating", "Construction"] # noqa: F841
|
||||
|
||||
df = df.query(
|
||||
"Status != 'Cancelled' \
|
||||
"Status in @status_list \
|
||||
& FacilityType == 'Import' \
|
||||
& Country != @remove_country \
|
||||
& TerminalName != @remove_terminal \
|
||||
& CapacityInMtpa != '--'"
|
||||
& CapacityInMtpa != '--' \
|
||||
& CapacityInMtpa != 0"
|
||||
)
|
||||
|
||||
geometry = gpd.points_from_xy(df["Longitude"], df["Latitude"])
|
||||
return gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326")
|
||||
gdf = gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326")
|
||||
return gdf
|
||||
|
||||
|
||||
def build_gem_prod_data(fn):
|
||||
@ -54,8 +59,10 @@ def build_gem_prod_data(fn):
|
||||
remove_country = ["Cyprus", "Türkiye"] # noqa: F841
|
||||
remove_fuel_type = ["oil"] # noqa: F841
|
||||
|
||||
status_list = ["operating", "in development"] # noqa: F841
|
||||
|
||||
df = df.query(
|
||||
"Status != 'shut in' \
|
||||
"Status in @status_list \
|
||||
& 'Fuel type' != 'oil' \
|
||||
& Country != @remove_country \
|
||||
& ~Latitude.isna() \
|
||||
@ -64,7 +71,7 @@ def build_gem_prod_data(fn):
|
||||
|
||||
p = pd.read_excel(fn, sheet_name="Gas extraction - production")
|
||||
p = p.set_index("GEM Unit ID")
|
||||
p = p[p["Fuel description"] == "gas"]
|
||||
p = p[p["Fuel description"].str.contains("gas")]
|
||||
|
||||
capacities = pd.DataFrame(index=df.index)
|
||||
for key in ["production", "production design capacity", "reserves"]:
|
||||
@ -85,7 +92,8 @@ def build_gem_prod_data(fn):
|
||||
)
|
||||
|
||||
geometry = gpd.points_from_xy(df["Longitude"], df["Latitude"])
|
||||
return gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326")
|
||||
gdf = gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326")
|
||||
return gdf
|
||||
|
||||
|
||||
def build_gas_input_locations(gem_fn, entry_fn, sto_fn, countries):
|
||||
@ -134,8 +142,7 @@ if __name__ == "__main__":
|
||||
snakemake = mock_snakemake(
|
||||
"build_gas_input_locations",
|
||||
simpl="",
|
||||
clusters="5",
|
||||
configfiles="config/test/config.overnight.yaml",
|
||||
clusters="128",
|
||||
)
|
||||
|
||||
configure_logging(snakemake)
|
||||
|
@ -82,7 +82,7 @@ def get_eia_annual_hydro_generation(fn, countries, capacities=False):
|
||||
countries=["Czechia", "Slovakia"], start=1980, end=1992
|
||||
),
|
||||
"Former Serbia and Montenegro": dict(
|
||||
countries=["Serbia", "Montenegro"], start=1992, end=2005
|
||||
countries=["Serbia", "Montenegro", "Kosovo"], start=1992, end=2005
|
||||
),
|
||||
"Former Yugoslavia": dict(
|
||||
countries=[
|
||||
@ -90,6 +90,7 @@ def get_eia_annual_hydro_generation(fn, countries, capacities=False):
|
||||
"Croatia",
|
||||
"Bosnia and Herzegovina",
|
||||
"Serbia",
|
||||
"Kosovo",
|
||||
"Montenegro",
|
||||
"North Macedonia",
|
||||
],
|
||||
@ -111,9 +112,8 @@ def get_eia_annual_hydro_generation(fn, countries, capacities=False):
|
||||
)
|
||||
|
||||
df.loc["Germany"] = df.filter(like="Germany", axis=0).sum()
|
||||
df.loc["Serbia"] += df.loc["Kosovo"].fillna(0.0)
|
||||
df = df.loc[~df.index.str.contains("Former")]
|
||||
df.drop(["Europe", "Germany, West", "Germany, East", "Kosovo"], inplace=True)
|
||||
df.drop(["Europe", "Germany, West", "Germany, East"], inplace=True)
|
||||
|
||||
df.index = cc.convert(df.index, to="iso2")
|
||||
df.index.name = "countries"
|
||||
@ -122,6 +122,8 @@ def get_eia_annual_hydro_generation(fn, countries, capacities=False):
|
||||
factor = 1e3 if capacities else 1e6
|
||||
df = df.T[countries] * factor
|
||||
|
||||
df.ffill(axis=0, inplace=True)
|
||||
|
||||
return df
|
||||
|
||||
|
||||
@ -129,7 +131,7 @@ def correct_eia_stats_by_capacity(eia_stats, fn, countries, baseyear=2019):
|
||||
cap = get_eia_annual_hydro_generation(fn, countries, capacities=True)
|
||||
ratio = cap / cap.loc[baseyear]
|
||||
eia_stats_corrected = eia_stats / ratio
|
||||
to_keep = ["AL", "AT", "CH", "DE", "GB", "NL", "RS", "RO", "SK"]
|
||||
to_keep = ["AL", "AT", "CH", "DE", "GB", "NL", "RS", "XK", "RO", "SK"]
|
||||
to_correct = eia_stats_corrected.columns.difference(to_keep)
|
||||
eia_stats.loc[:, to_correct] = eia_stats_corrected.loc[:, to_correct]
|
||||
|
||||
|
@ -100,7 +100,7 @@ def prepare_hotmaps_database(regions):
|
||||
"""
|
||||
Load hotmaps database of industrial sites and map onto bus regions.
|
||||
"""
|
||||
df = pd.read_csv(snakemake.input.hotmaps_industrial_database, sep=";", index_col=0)
|
||||
df = pd.read_csv(snakemake.input.hotmaps, sep=";", index_col=0)
|
||||
|
||||
df[["srid", "coordinates"]] = df.geom.str.split(";", expand=True)
|
||||
|
||||
@ -133,7 +133,97 @@ def prepare_hotmaps_database(regions):
|
||||
return gdf
|
||||
|
||||
|
||||
def build_nodal_distribution_key(hotmaps, regions, countries):
|
||||
def prepare_gem_database(regions):
|
||||
"""
|
||||
Load GEM database of steel plants and map onto bus regions.
|
||||
"""
|
||||
|
||||
df = pd.read_excel(
|
||||
snakemake.input.gem_gspt,
|
||||
sheet_name="Steel Plants",
|
||||
na_values=["N/A", "unknown", ">0"],
|
||||
).query("Region == 'Europe'")
|
||||
|
||||
df["Retired Date"] = pd.to_numeric(
|
||||
df["Retired Date"].combine_first(df["Idled Date"]), errors="coerce"
|
||||
)
|
||||
df["Start date"] = pd.to_numeric(
|
||||
df["Start date"].str.split("-").str[0], errors="coerce"
|
||||
)
|
||||
|
||||
latlon = (
|
||||
df["Coordinates"]
|
||||
.str.split(", ", expand=True)
|
||||
.rename(columns={0: "lat", 1: "lon"})
|
||||
)
|
||||
geometry = gpd.points_from_xy(latlon["lon"], latlon["lat"])
|
||||
gdf = gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326")
|
||||
|
||||
gdf = gpd.sjoin(gdf, regions, how="inner", predicate="within")
|
||||
|
||||
gdf.rename(columns={"name": "bus"}, inplace=True)
|
||||
gdf["country"] = gdf.bus.str[:2]
|
||||
|
||||
return gdf
|
||||
|
||||
|
||||
def prepare_ammonia_database(regions):
|
||||
"""
|
||||
Load ammonia database of plants and map onto bus regions.
|
||||
"""
|
||||
df = pd.read_csv(snakemake.input.ammonia, index_col=0)
|
||||
|
||||
geometry = gpd.points_from_xy(df.Longitude, df.Latitude)
|
||||
gdf = gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326")
|
||||
|
||||
gdf = gpd.sjoin(gdf, regions, how="inner", predicate="within")
|
||||
|
||||
gdf.rename(columns={"name": "bus"}, inplace=True)
|
||||
gdf["country"] = gdf.bus.str[:2]
|
||||
|
||||
return gdf
|
||||
|
||||
|
||||
def prepare_cement_supplement(regions):
|
||||
"""
|
||||
Load supplementary cement plants from non-EU-(NO-CH) and map onto bus
|
||||
regions.
|
||||
"""
|
||||
|
||||
df = pd.read_csv(snakemake.input.cement_supplement, index_col=0)
|
||||
|
||||
geometry = gpd.points_from_xy(df.Longitude, df.Latitude)
|
||||
gdf = gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326")
|
||||
|
||||
gdf = gpd.sjoin(gdf, regions, how="inner", predicate="within")
|
||||
|
||||
gdf.rename(columns={"name": "bus"}, inplace=True)
|
||||
gdf["country"] = gdf.bus.str[:2]
|
||||
|
||||
return gdf
|
||||
|
||||
|
||||
def prepare_refineries_supplement(regions):
|
||||
"""
|
||||
Load supplementary refineries from non-EU-(NO-CH) and map onto bus regions.
|
||||
"""
|
||||
|
||||
df = pd.read_csv(snakemake.input.refineries_supplement, index_col=0)
|
||||
|
||||
geometry = gpd.points_from_xy(df.Longitude, df.Latitude)
|
||||
gdf = gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326")
|
||||
|
||||
gdf = gpd.sjoin(gdf, regions, how="inner", predicate="within")
|
||||
|
||||
gdf.rename(columns={"name": "bus"}, inplace=True)
|
||||
gdf["country"] = gdf.bus.str[:2]
|
||||
|
||||
return gdf
|
||||
|
||||
|
||||
def build_nodal_distribution_key(
|
||||
hotmaps, gem, ammonia, cement, refineries, regions, countries
|
||||
):
|
||||
"""
|
||||
Build nodal distribution keys for each sector.
|
||||
"""
|
||||
@ -158,15 +248,137 @@ def build_nodal_distribution_key(hotmaps, regions, countries):
|
||||
if emissions.sum() == 0:
|
||||
key = pd.Series(1 / len(facilities), facilities.index)
|
||||
else:
|
||||
# BEWARE: this is a strong assumption
|
||||
emissions = emissions.fillna(emissions.mean())
|
||||
# assume 20% quantile for missing values
|
||||
emissions = emissions.fillna(emissions.quantile(0.2))
|
||||
key = emissions / emissions.sum()
|
||||
key = key.groupby(facilities.bus).sum().reindex(regions_ct, fill_value=0.0)
|
||||
elif sector == "Cement" and country in cement.country.unique():
|
||||
facilities = cement.query("country == @country")
|
||||
production = facilities["Cement [kt/a]"]
|
||||
if production.sum() == 0:
|
||||
key = pd.Series(1 / len(facilities), facilities.index)
|
||||
else:
|
||||
key = production / production.sum()
|
||||
key = key.groupby(facilities.bus).sum().reindex(regions_ct, fill_value=0.0)
|
||||
elif sector == "Refineries" and country in refineries.country.unique():
|
||||
facilities = refineries.query("country == @country")
|
||||
production = facilities["Capacity [bbl/day]"]
|
||||
if production.sum() == 0:
|
||||
key = pd.Series(1 / len(facilities), facilities.index)
|
||||
else:
|
||||
key = production / production.sum()
|
||||
key = key.groupby(facilities.bus).sum().reindex(regions_ct, fill_value=0.0)
|
||||
else:
|
||||
key = keys.loc[regions_ct, "population"]
|
||||
|
||||
keys.loc[regions_ct, sector] = key
|
||||
|
||||
# add specific steel subsectors
|
||||
steel_processes = ["EAF", "DRI + EAF", "Integrated steelworks"]
|
||||
for process, country in product(steel_processes, countries):
|
||||
regions_ct = regions.index[regions.index.str.contains(country)]
|
||||
|
||||
facilities = gem.query("country == @country")
|
||||
|
||||
if process == "EAF":
|
||||
status_list = [
|
||||
"construction",
|
||||
"operating",
|
||||
"operating pre-retirement",
|
||||
"retired",
|
||||
]
|
||||
capacities = facilities.loc[
|
||||
facilities["Capacity operating status"].isin(status_list)
|
||||
& (
|
||||
facilities["Retired Date"].isna()
|
||||
| facilities["Retired Date"].gt(2025)
|
||||
),
|
||||
"Nominal EAF steel capacity (ttpa)",
|
||||
].dropna()
|
||||
elif process == "DRI + EAF":
|
||||
status_list = [
|
||||
"construction",
|
||||
"operating",
|
||||
"operating pre-retirement",
|
||||
"retired",
|
||||
"announced",
|
||||
]
|
||||
sel = [
|
||||
"Nominal BOF steel capacity (ttpa)",
|
||||
"Nominal OHF steel capacity (ttpa)",
|
||||
"Nominal iron capacity (ttpa)",
|
||||
]
|
||||
status_filter = facilities["Capacity operating status"].isin(status_list)
|
||||
retirement_filter = facilities["Retired Date"].isna() | facilities[
|
||||
"Retired Date"
|
||||
].gt(2030)
|
||||
start_filter = (
|
||||
facilities["Start date"].isna()
|
||||
& ~facilities["Capacity operating status"].eq("announced")
|
||||
) | facilities["Start date"].le(2030)
|
||||
capacities = (
|
||||
facilities.loc[status_filter & retirement_filter & start_filter, sel]
|
||||
.sum(axis=1)
|
||||
.dropna()
|
||||
)
|
||||
elif process == "Integrated steelworks":
|
||||
status_list = [
|
||||
"construction",
|
||||
"operating",
|
||||
"operating pre-retirement",
|
||||
"retired",
|
||||
]
|
||||
sel = [
|
||||
"Nominal BOF steel capacity (ttpa)",
|
||||
"Nominal OHF steel capacity (ttpa)",
|
||||
]
|
||||
capacities = (
|
||||
facilities.loc[
|
||||
facilities["Capacity operating status"].isin(status_list)
|
||||
& (
|
||||
facilities["Retired Date"].isna()
|
||||
| facilities["Retired Date"].gt(2025)
|
||||
),
|
||||
sel,
|
||||
]
|
||||
.sum(axis=1)
|
||||
.dropna()
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Unknown process {process}")
|
||||
|
||||
if not capacities.empty:
|
||||
if capacities.sum() == 0:
|
||||
key = pd.Series(1 / len(capacities), capacities.index)
|
||||
else:
|
||||
key = capacities / capacities.sum()
|
||||
buses = facilities.loc[capacities.index, "bus"]
|
||||
key = key.groupby(buses).sum().reindex(regions_ct, fill_value=0.0)
|
||||
else:
|
||||
key = keys.loc[regions_ct, "population"]
|
||||
|
||||
keys.loc[regions_ct, process] = key
|
||||
|
||||
# add ammonia
|
||||
for country in countries:
|
||||
regions_ct = regions.index[regions.index.str.contains(country)]
|
||||
|
||||
facilities = ammonia.query("country == @country")
|
||||
|
||||
if not facilities.empty:
|
||||
production = facilities["Ammonia [kt/a]"]
|
||||
if production.sum() == 0:
|
||||
key = pd.Series(1 / len(facilities), facilities.index)
|
||||
else:
|
||||
# assume 50% of the minimum production for missing values
|
||||
production = production.fillna(0.5 * facilities["Ammonia [kt/a]"].min())
|
||||
key = production / production.sum()
|
||||
key = key.groupby(facilities.bus).sum().reindex(regions_ct, fill_value=0.0)
|
||||
else:
|
||||
key = 0.0
|
||||
|
||||
keys.loc[regions_ct, "Ammonia"] = key
|
||||
|
||||
return keys
|
||||
|
||||
|
||||
@ -188,6 +400,16 @@ if __name__ == "__main__":
|
||||
|
||||
hotmaps = prepare_hotmaps_database(regions)
|
||||
|
||||
keys = build_nodal_distribution_key(hotmaps, regions, countries)
|
||||
gem = prepare_gem_database(regions)
|
||||
|
||||
ammonia = prepare_ammonia_database(regions)
|
||||
|
||||
cement = prepare_cement_supplement(regions)
|
||||
|
||||
refineries = prepare_refineries_supplement(regions)
|
||||
|
||||
keys = build_nodal_distribution_key(
|
||||
hotmaps, gem, ammonia, cement, refineries, regions, countries
|
||||
)
|
||||
|
||||
keys.to_csv(snakemake.output.industrial_distribution_key)
|
||||
|
@ -33,10 +33,10 @@ from _helpers import set_scenario_config
|
||||
|
||||
# map JRC/our sectors to hotmaps sector, where mapping exist
|
||||
sector_mapping = {
|
||||
"Electric arc": "Iron and steel",
|
||||
"Integrated steelworks": "Iron and steel",
|
||||
"DRI + Electric arc": "Iron and steel",
|
||||
"Ammonia": "Chemical industry",
|
||||
"Electric arc": "EAF",
|
||||
"Integrated steelworks": "Integrated steelworks",
|
||||
"DRI + Electric arc": "DRI + EAF",
|
||||
"Ammonia": "Ammonia",
|
||||
"Basic chemicals (without ammonia)": "Chemical industry",
|
||||
"Other chemicals": "Chemical industry",
|
||||
"Pharmaceutical products etc.": "Chemical industry",
|
||||
|
@ -345,5 +345,7 @@ if __name__ == "__main__":
|
||||
|
||||
separate_basic_chemicals(demand, year)
|
||||
|
||||
demand.fillna(0.0, inplace=True)
|
||||
|
||||
fn = snakemake.output.industrial_production_per_country
|
||||
demand.to_csv(fn, float_format="%.2f")
|
||||
|
@ -32,10 +32,10 @@ from _helpers import set_scenario_config
|
||||
|
||||
# map JRC/our sectors to hotmaps sector, where mapping exist
|
||||
sector_mapping = {
|
||||
"Electric arc": "Iron and steel",
|
||||
"Integrated steelworks": "Iron and steel",
|
||||
"DRI + Electric arc": "Iron and steel",
|
||||
"Ammonia": "Chemical industry",
|
||||
"Electric arc": "EAF",
|
||||
"Integrated steelworks": "Integrated steelworks",
|
||||
"DRI + Electric arc": "DRI + EAF",
|
||||
"Ammonia": "Ammonia",
|
||||
"HVC": "Chemical industry",
|
||||
"HVC (mechanical recycling)": "Chemical industry",
|
||||
"HVC (chemical recycling)": "Chemical industry",
|
||||
|
@ -9,6 +9,7 @@ Build mapping between cutout grid cells and population (total, urban, rural).
|
||||
import logging
|
||||
|
||||
import atlite
|
||||
import country_converter as coco
|
||||
import geopandas as gpd
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
@ -17,6 +18,8 @@ from _helpers import configure_logging, set_scenario_config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
cc = coco.CountryConverter()
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
@ -27,6 +30,7 @@ if __name__ == "__main__":
|
||||
|
||||
configure_logging(snakemake)
|
||||
set_scenario_config(snakemake)
|
||||
coco.logging.getLogger().setLevel(coco.logging.CRITICAL)
|
||||
|
||||
cutout = atlite.Cutout(snakemake.input.cutout)
|
||||
|
||||
@ -45,19 +49,14 @@ if __name__ == "__main__":
|
||||
|
||||
countries = np.sort(nuts3.country.unique())
|
||||
|
||||
urban_fraction = pd.read_csv(snakemake.input.urban_percent, skiprows=4)
|
||||
iso3 = urban_fraction["Country Code"]
|
||||
urban_fraction["iso2"] = cc.convert(names=iso3, src="ISO3", to="ISO2")
|
||||
urban_fraction = (
|
||||
pd.read_csv(
|
||||
snakemake.input.urban_percent, header=None, index_col=0, names=["fraction"]
|
||||
).squeeze()
|
||||
/ 100.0
|
||||
urban_fraction.query("iso2 in @countries").set_index("iso2")["2019"].div(100)
|
||||
)
|
||||
|
||||
# fill missing Balkans values
|
||||
missing = ["AL", "ME", "MK"]
|
||||
reference = ["RS", "BA"]
|
||||
average = urban_fraction[reference].mean()
|
||||
fill_values = pd.Series({ct: average for ct in missing})
|
||||
urban_fraction = pd.concat([urban_fraction, fill_values])
|
||||
if "XK" in countries:
|
||||
urban_fraction["XK"] = urban_fraction["RS"]
|
||||
|
||||
# population in each grid cell
|
||||
pop_cells = pd.Series(I.dot(nuts3["pop"]))
|
||||
|
@ -206,12 +206,11 @@ if __name__ == "__main__":
|
||||
|
||||
# Add "everywhere powerplants" to all bus locations
|
||||
ppl = add_everywhere_powerplants(
|
||||
ppl, n.buses.query("substation_lv"), snakemake.params.everywhere_powerplants
|
||||
ppl, n.buses, snakemake.params.everywhere_powerplants
|
||||
)
|
||||
|
||||
substations = n.buses.query("substation_lv")
|
||||
ppl = ppl.dropna(subset=["lat", "lon"])
|
||||
ppl = map_country_bus(ppl, substations)
|
||||
ppl = map_country_bus(ppl, n.buses)
|
||||
|
||||
bus_null_b = ppl["bus"].isnull()
|
||||
if bus_null_b.any():
|
||||
|
@ -198,6 +198,7 @@ def prepare_building_stock_data():
|
||||
"Iceland": "IS",
|
||||
"Montenegro": "ME",
|
||||
"Serbia": "RS",
|
||||
"Kosovo": "XK",
|
||||
"Albania": "AL",
|
||||
"United Kingdom": "GB",
|
||||
"Bosnia and Herzegovina": "BA",
|
||||
@ -1073,6 +1074,7 @@ if __name__ == "__main__":
|
||||
"AL": ["BG", "RO", "GR"],
|
||||
"BA": ["HR"],
|
||||
"RS": ["BG", "RO", "HR", "HU"],
|
||||
"KV": ["RS"],
|
||||
"MK": ["BG", "GR"],
|
||||
"ME": ["BA", "AL", "RS", "HR"],
|
||||
"CH": ["SE", "DE"],
|
||||
|
@ -106,8 +106,6 @@ def _simplify_polys(polys, minarea=0.1, tolerance=None, filterremote=True):
|
||||
|
||||
|
||||
def countries(naturalearth, country_list):
|
||||
if "RS" in country_list:
|
||||
country_list.append("KV")
|
||||
|
||||
df = gpd.read_file(naturalearth)
|
||||
|
||||
@ -116,15 +114,12 @@ def countries(naturalearth, country_list):
|
||||
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[:2]
|
||||
df.replace({"name": {"KV": "XK"}}, inplace=True)
|
||||
|
||||
df = df.loc[
|
||||
df.name.isin(country_list) & ((df["scalerank"] == 0) | (df["scalerank"] == 5))
|
||||
]
|
||||
s = df.set_index("name")["geometry"].map(_simplify_polys).set_crs(df.crs)
|
||||
if "RS" in country_list:
|
||||
s["RS"] = s["RS"].union(s.pop("KV"))
|
||||
# cleanup shape union
|
||||
s["RS"] = Polygon(s["RS"].exterior.coords)
|
||||
|
||||
return s
|
||||
|
||||
@ -195,7 +190,9 @@ def nuts3(country_shapes, nuts3, nuts3pop, nuts3gdp, ch_cantons, ch_popgdp):
|
||||
|
||||
df = df.join(pd.DataFrame(dict(pop=pop, gdp=gdp)))
|
||||
|
||||
df["country"] = df.index.to_series().str[:2].replace(dict(UK="GB", EL="GR"))
|
||||
df["country"] = (
|
||||
df.index.to_series().str[:2].replace(dict(UK="GB", EL="GR", KV="XK"))
|
||||
)
|
||||
|
||||
excludenuts = pd.Index(
|
||||
(
|
||||
@ -217,13 +214,18 @@ def nuts3(country_shapes, nuts3, nuts3pop, nuts3gdp, ch_cantons, ch_popgdp):
|
||||
"FR9",
|
||||
)
|
||||
)
|
||||
excludecountry = pd.Index(("MT", "TR", "LI", "IS", "CY", "KV"))
|
||||
excludecountry = pd.Index(("MT", "TR", "LI", "IS", "CY"))
|
||||
|
||||
df = df.loc[df.index.difference(excludenuts)]
|
||||
df = df.loc[~df.country.isin(excludecountry)]
|
||||
|
||||
manual = gpd.GeoDataFrame(
|
||||
[["BA1", "BA", 3871.0], ["RS1", "RS", 7210.0], ["AL1", "AL", 2893.0]],
|
||||
[
|
||||
["BA1", "BA", 3234.0],
|
||||
["RS1", "RS", 6664.0],
|
||||
["AL1", "AL", 2778.0],
|
||||
["XK1", "XK", 1587.0],
|
||||
],
|
||||
columns=["NUTS_ID", "country", "pop"],
|
||||
geometry=gpd.GeoSeries(),
|
||||
crs=df.crs,
|
||||
@ -234,7 +236,7 @@ def nuts3(country_shapes, nuts3, nuts3pop, nuts3gdp, ch_cantons, ch_popgdp):
|
||||
|
||||
df = pd.concat([df, manual], sort=False)
|
||||
|
||||
df.loc["ME000", "pop"] = 650.0
|
||||
df.loc["ME000", "pop"] = 617.0
|
||||
|
||||
return df
|
||||
|
||||
|
@ -557,12 +557,12 @@ if __name__ == "__main__":
|
||||
): # also available: linemap_positive, linemap_negative
|
||||
getattr(clustering, attr).to_csv(snakemake.output[attr])
|
||||
|
||||
nc.shapes = n.shapes.copy()
|
||||
# nc.shapes = n.shapes.copy()
|
||||
for which in ["regions_onshore", "regions_offshore"]:
|
||||
regions = gpd.read_file(snakemake.input[which])
|
||||
clustered_regions = cluster_regions((clustering.busmap,), regions)
|
||||
clustered_regions.to_file(snakemake.output[which])
|
||||
append_bus_shapes(nc, clustered_regions, type=which.split("_")[1])
|
||||
# append_bus_shapes(nc, clustered_regions, type=which.split("_")[1])
|
||||
|
||||
nc.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards)))
|
||||
nc.export_to_netcdf(snakemake.output.network)
|
||||
|
@ -281,7 +281,7 @@ def co2_emissions_year(
|
||||
|
||||
eurostat = build_eurostat(input_eurostat, countries)
|
||||
|
||||
# this only affects the estimation of CO2 emissions for BA, RS, AL, ME, MK
|
||||
# this only affects the estimation of CO2 emissions for BA, RS, AL, ME, MK, XK
|
||||
eurostat_co2 = build_eurostat_co2(eurostat, year)
|
||||
|
||||
co2_totals = build_co2_totals(countries, eea_co2, eurostat_co2)
|
||||
@ -539,7 +539,24 @@ def add_carrier_buses(n, carrier, nodes=None):
|
||||
|
||||
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
|
||||
if carrier == "gas":
|
||||
capital_cost = costs.at["gas storage", "fixed"]
|
||||
elif carrier == "oil":
|
||||
# based on https://www.engineeringtoolbox.com/fuels-higher-calorific-values-d_169.html
|
||||
mwh_per_m3 = 44.9 * 724 * 0.278 * 1e-3 # MJ/kg * kg/m3 * kWh/MJ * MWh/kWh
|
||||
capital_cost = (
|
||||
costs.at["General liquid hydrocarbon storage (product)", "fixed"]
|
||||
/ mwh_per_m3
|
||||
)
|
||||
elif carrier == "methanol":
|
||||
# based on https://www.engineeringtoolbox.com/fossil-fuels-energy-content-d_1298.html
|
||||
mwh_per_m3 = 5.54 * 791 * 1e-3 # kWh/kg * kg/m3 * MWh/kWh
|
||||
capital_cost = (
|
||||
costs.at["General liquid hydrocarbon storage (product)", "fixed"]
|
||||
/ mwh_per_m3
|
||||
)
|
||||
else:
|
||||
capital_cost = 0.1
|
||||
|
||||
n.madd("Bus", nodes, location=location, carrier=carrier, unit=unit)
|
||||
|
||||
@ -2639,8 +2656,7 @@ def add_biomass(n, costs):
|
||||
if (
|
||||
options["municipal_solid_waste"]
|
||||
and not options["industry"]
|
||||
and cf_industry["waste_to_energy"]
|
||||
or cf_industry["waste_to_energy_cc"]
|
||||
and (cf_industry["waste_to_energy"] or cf_industry["waste_to_energy_cc"])
|
||||
):
|
||||
logger.warning(
|
||||
"Flag municipal_solid_waste can be only used with industry "
|
||||
@ -2660,7 +2676,12 @@ def add_biomass(n, costs):
|
||||
carrier="municipal solid waste",
|
||||
)
|
||||
|
||||
e_max_pu = pd.Series([1] * (len(n.snapshots) - 1) + [0], index=n.snapshots)
|
||||
e_max_pu = np.array(
|
||||
len(spatial.msw.nodes) * [[1] * (len(n.snapshots) - 1) + [0]]
|
||||
).T
|
||||
e_max_pu = pd.DataFrame(
|
||||
e_max_pu, index=n.snapshots, columns=spatial.msw.nodes
|
||||
).astype(float)
|
||||
n.madd(
|
||||
"Store",
|
||||
spatial.msw.nodes,
|
||||
@ -2757,7 +2778,7 @@ def add_biomass(n, costs):
|
||||
)
|
||||
|
||||
if biomass_potentials.filter(like="unsustainable").sum().sum() > 0:
|
||||
|
||||
add_carrier_buses(n, "oil")
|
||||
# Create timeseries to force usage of unsustainable potentials
|
||||
e_max_pu = pd.DataFrame(1, index=n.snapshots, columns=spatial.gas.biogas)
|
||||
e_max_pu.iloc[-1] = 0
|
||||
@ -2905,13 +2926,15 @@ def add_biomass(n, costs):
|
||||
if options["municipal_solid_waste"]:
|
||||
n.madd(
|
||||
"Link",
|
||||
biomass_transport.index,
|
||||
bus0=biomass_transport.bus0 + " municipal solid waste",
|
||||
bus1=biomass_transport.bus1 + " municipal solid waste",
|
||||
biomass_transport.index + " municipal solid waste",
|
||||
bus0=biomass_transport.bus0.values + " municipal solid waste",
|
||||
bus1=biomass_transport.bus1.values + " municipal solid waste",
|
||||
p_nom_extendable=False,
|
||||
p_nom=5e4,
|
||||
length=biomass_transport.length.values,
|
||||
marginal_cost=biomass_transport.costs * biomass_transport.length.values,
|
||||
marginal_cost=(
|
||||
biomass_transport.costs * biomass_transport.length
|
||||
).values,
|
||||
carrier="municipal solid waste transport",
|
||||
)
|
||||
|
||||
@ -3041,6 +3064,7 @@ def add_biomass(n, costs):
|
||||
|
||||
# Solid biomass to liquid fuel
|
||||
if options["biomass_to_liquid"]:
|
||||
add_carrier_buses(n, "oil")
|
||||
n.madd(
|
||||
"Link",
|
||||
spatial.biomass.nodes,
|
||||
@ -3084,7 +3108,7 @@ def add_biomass(n, costs):
|
||||
# Combination of efuels and biomass to liquid, both based on Fischer-Tropsch.
|
||||
# Experimental version - use with caution
|
||||
if options["electrobiofuels"]:
|
||||
|
||||
add_carrier_buses(n, "oil")
|
||||
efuel_scale_factor = costs.at["BtL", "C stored"]
|
||||
name = (
|
||||
pd.Index(spatial.biomass.nodes)
|
||||
@ -3196,6 +3220,10 @@ def add_biomass(n, costs):
|
||||
|
||||
def add_industry(n, costs):
|
||||
logger.info("Add industrial demand")
|
||||
# add oil buses for shipping, aviation and naptha for industry
|
||||
add_carrier_buses(n, "oil")
|
||||
# add methanol buses for industry
|
||||
add_carrier_buses(n, "methanol")
|
||||
|
||||
nodes = pop_layout.index
|
||||
nhours = n.snapshot_weightings.generators.sum()
|
||||
@ -3520,38 +3548,8 @@ def add_industry(n, costs):
|
||||
], # CO2 intensity methanol based on stoichiometric calculation with 22.7 GJ/t methanol (32 g/mol), CO2 (44 g/mol), 277.78 MWh/TJ = 0.218 t/MWh
|
||||
)
|
||||
|
||||
if "oil" not in n.buses.carrier.unique():
|
||||
n.madd(
|
||||
"Bus",
|
||||
spatial.oil.nodes,
|
||||
location=spatial.oil.locations,
|
||||
carrier="oil",
|
||||
unit="MWh_LHV",
|
||||
)
|
||||
|
||||
if "oil" not in n.stores.carrier.unique():
|
||||
# could correct to e.g. 0.001 EUR/kWh * annuity and O&M
|
||||
n.madd(
|
||||
"Store",
|
||||
spatial.oil.nodes,
|
||||
suffix=" Store",
|
||||
bus=spatial.oil.nodes,
|
||||
e_nom_extendable=True,
|
||||
e_cyclic=True,
|
||||
carrier="oil",
|
||||
)
|
||||
|
||||
if options.get("fossil_fuels", True) and "oil" not in n.generators.carrier.unique():
|
||||
n.madd(
|
||||
"Generator",
|
||||
spatial.oil.nodes,
|
||||
bus=spatial.oil.nodes,
|
||||
p_nom_extendable=True,
|
||||
carrier="oil",
|
||||
marginal_cost=costs.at["oil", "fuel"],
|
||||
)
|
||||
|
||||
if shipping_oil_share:
|
||||
|
||||
p_set_oil = shipping_oil_share * p_set.rename(lambda x: x + " shipping oil")
|
||||
|
||||
if not options["regional_oil_demand"]:
|
||||
|
@ -124,7 +124,6 @@ def simplify_network_to_380(n, linetype_380):
|
||||
|
||||
n.buses["v_nom"] = 380.0
|
||||
|
||||
linetype_380 = n.lines["type"].mode()[0]
|
||||
n.lines["type"] = linetype_380
|
||||
n.lines["v_nom"] = 380
|
||||
n.lines["i_nom"] = n.line_types.i_nom[linetype_380]
|
||||
@ -670,7 +669,7 @@ if __name__ == "__main__":
|
||||
n.lines.drop(remove, axis=1, errors="ignore", inplace=True)
|
||||
|
||||
if snakemake.wildcards.simpl:
|
||||
shapes = n.shapes
|
||||
# shapes = n.shapes
|
||||
n, cluster_map = cluster(
|
||||
n,
|
||||
int(snakemake.wildcards.simpl),
|
||||
@ -680,7 +679,7 @@ if __name__ == "__main__":
|
||||
params.simplify_network["feature"],
|
||||
params.aggregation_strategies,
|
||||
)
|
||||
n.shapes = shapes
|
||||
# n.shapes = shapes
|
||||
busmaps.append(cluster_map)
|
||||
|
||||
update_p_nom_max(n)
|
||||
@ -692,7 +691,7 @@ if __name__ == "__main__":
|
||||
regions = gpd.read_file(snakemake.input[which])
|
||||
clustered_regions = cluster_regions(busmaps, regions)
|
||||
clustered_regions.to_file(snakemake.output[which])
|
||||
append_bus_shapes(n, clustered_regions, type=which.split("_")[1])
|
||||
# append_bus_shapes(n, clustered_regions, type=which.split("_")[1])
|
||||
|
||||
n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards)))
|
||||
n.export_to_netcdf(snakemake.output.network)
|
||||
|
@ -1055,8 +1055,8 @@ def extra_functionality(n, snapshots):
|
||||
if config["sector"]["enhanced_geothermal"]["enable"]:
|
||||
add_flexible_egs_constraint(n)
|
||||
|
||||
if snakemake.params.custom_extra_functionality:
|
||||
source_path = snakemake.params.custom_extra_functionality
|
||||
if n.params.custom_extra_functionality:
|
||||
source_path = n.params.custom_extra_functionality
|
||||
assert os.path.exists(source_path), f"{source_path} does not exist"
|
||||
sys.path.append(os.path.dirname(source_path))
|
||||
module_name = os.path.splitext(os.path.basename(source_path))[0]
|
||||
@ -1065,7 +1065,7 @@ def extra_functionality(n, snapshots):
|
||||
custom_extra_functionality(n, snapshots, snakemake)
|
||||
|
||||
|
||||
def solve_network(n, config, solving, **kwargs):
|
||||
def solve_network(n, config, params, solving, **kwargs):
|
||||
set_of_options = solving["solver"]["options"]
|
||||
cf_solving = solving["options"]
|
||||
|
||||
@ -1093,6 +1093,7 @@ def solve_network(n, config, solving, **kwargs):
|
||||
|
||||
# add to network for extra_functionality
|
||||
n.config = config
|
||||
n.params = params
|
||||
|
||||
if rolling_horizon and snakemake.rule == "solve_operations_network":
|
||||
kwargs["horizon"] = cf_solving.get("horizon", 365)
|
||||
@ -1165,6 +1166,7 @@ if __name__ == "__main__":
|
||||
n = solve_network(
|
||||
n,
|
||||
config=snakemake.config,
|
||||
params=snakemake.params,
|
||||
solving=snakemake.params.solving,
|
||||
log_fn=snakemake.log.solver,
|
||||
)
|
||||
|
@ -49,7 +49,13 @@ if __name__ == "__main__":
|
||||
|
||||
n.optimize.fix_optimal_capacities()
|
||||
n = prepare_network(n, solve_opts, config=snakemake.config)
|
||||
n = solve_network(n, config=snakemake.config, log_fn=snakemake.log.solver)
|
||||
n = solve_network(
|
||||
n,
|
||||
config=snakemake.config,
|
||||
params=snakemake.params,
|
||||
solving=snakemake.params.solving,
|
||||
log_fn=snakemake.log.solver,
|
||||
)
|
||||
|
||||
n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards)))
|
||||
n.export_to_netcdf(snakemake.output[0])
|
||||
|
Loading…
Reference in New Issue
Block a user