diff --git a/data/ammonia_plants.csv b/data/ammonia_plants.csv new file mode 100644 index 00000000..1317ceb9 --- /dev/null +++ b/data/ammonia_plants.csv @@ -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/", diff --git a/data/cement-plants-noneu.csv b/data/cement-plants-noneu.csv new file mode 100644 index 00000000..27c046c0 --- /dev/null +++ b/data/cement-plants-noneu.csv @@ -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 ", diff --git a/data/refineries-noneu.csv b/data/refineries-noneu.csv new file mode 100644 index 00000000..e6012797 --- /dev/null +++ b/data/refineries-noneu.csv @@ -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", diff --git a/doc/release_notes.rst b/doc/release_notes.rst index d5fbe781..d7a6e344 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -11,6 +11,31 @@ Release Notes Upcoming Release ================ +* 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 + `__ + 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 + `__. The data is stored + in ``data/refineries-noneu.csv``. + +* Included data from the `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 `__. The data originates from the United Nations Population Division. Previously, a file diff --git a/rules/build_sector.smk b/rules/build_sector.smk index f95731b7..23555dbc 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -575,10 +575,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" diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 5c4af68e..c0cd5b6c 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -321,6 +321,23 @@ if config["enable"]["retrieve"]: +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 diff --git a/scripts/build_industrial_distribution_key.py b/scripts/build_industrial_distribution_key.py index e6654728..76a0e6d6 100644 --- a/scripts/build_industrial_distribution_key.py +++ b/scripts/build_industrial_distribution_key.py @@ -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) diff --git a/scripts/build_industrial_energy_demand_per_node_today.py b/scripts/build_industrial_energy_demand_per_node_today.py index aa9e9dff..fd7c281c 100644 --- a/scripts/build_industrial_energy_demand_per_node_today.py +++ b/scripts/build_industrial_energy_demand_per_node_today.py @@ -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", diff --git a/scripts/build_industrial_production_per_node.py b/scripts/build_industrial_production_per_node.py index d3edfa45..862345e5 100644 --- a/scripts/build_industrial_production_per_node.py +++ b/scripts/build_industrial_production_per_node.py @@ -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",