|
13 | 13 | import country_converter as coco |
14 | 14 | import numpy as np |
15 | 15 | import pandas as pd |
| 16 | +import geopandas as gpd |
16 | 17 | import powerplantmatching as pm |
17 | 18 | import pypsa |
18 | 19 | import xarray as xr |
@@ -716,6 +717,80 @@ def add_heating_capacities_installed_before_baseyear( |
716 | 717 | ) |
717 | 718 |
|
718 | 719 |
|
| 720 | +def prepare_plant_data(): |
| 721 | + |
| 722 | + # add existing industry |
| 723 | + regions = gpd.read_file(snakemake.input.regions_onshore).set_index("name") |
| 724 | + |
| 725 | + isi_data = pd.read_excel(snakemake.input.isi_database, sheet_name="Database", index_col=1) |
| 726 | + # assign bus region to each plant |
| 727 | + geometry = gpd.points_from_xy(isi_data["Longitude"], isi_data["Latitude"]) |
| 728 | + plant_data = gpd.GeoDataFrame(isi_data, geometry=geometry, crs="EPSG:4326") |
| 729 | + plant_data = gpd.sjoin(plant_data, regions, how="inner", predicate="within") |
| 730 | + plant_data.rename(columns={"name": "bus"}, inplace=True) |
| 731 | + # filter for countries in model scope |
| 732 | + plant_data = plant_data[plant_data.Country.isin(snakemake.params.countries)] |
| 733 | + # replace UK with GB in Country column |
| 734 | + plant_data["Country"] = plant_data["Country"].replace("UK", "GB") |
| 735 | + # assign industry grouping year |
| 736 | + grouping_years = snakemake.params.existing_capacities["grouping_years_industry"] |
| 737 | + plant_data.loc[:, 'Year of last modernisation'] = plant_data['Year of last modernisation'].replace("x", np.nan) |
| 738 | + plant_data['grouping_year'] = 0 |
| 739 | + valid_mask = plant_data['Year of last modernisation'].notna() |
| 740 | + valid_years = plant_data.loc[valid_mask, 'Year of last modernisation'] |
| 741 | + indices = np.searchsorted(grouping_years, valid_years, side='right') |
| 742 | + plant_data.loc[valid_years.index, 'grouping_year'] = np.array(grouping_years)[indices] |
| 743 | + |
| 744 | + return plant_data, regions |
| 745 | + |
| 746 | + |
| 747 | +def add_existing_ammonia_plants(n): |
| 748 | + |
| 749 | + logger.info("Adding existing ammonia plants.") |
| 750 | + |
| 751 | + plant_data, regions = prepare_plant_data() |
| 752 | + |
| 753 | + ammonia_plants = plant_data[plant_data.Product=="Ammonia"] |
| 754 | + |
| 755 | + ammonia_plants = ammonia_plants.groupby(['bus', 'Country', 'grouping_year', 'Product'], as_index=False)['Production in tons (calibrated)'].sum() |
| 756 | + |
| 757 | + ammonia_plants.index = ammonia_plants['bus'] + " Haber-Bosch-" + ammonia_plants['grouping_year'].astype(str) |
| 758 | + |
| 759 | + # add dataset |
| 760 | + df = pd.read_csv(snakemake.input.ammonia, index_col=0) |
| 761 | + |
| 762 | + geometry = gpd.points_from_xy(df.Longitude, df.Latitude) |
| 763 | + gdf = gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326") |
| 764 | + |
| 765 | + gdf = gpd.sjoin(gdf, regions, how="inner", predicate="within") |
| 766 | + |
| 767 | + gdf.rename(columns={"name": "bus"}, inplace=True) |
| 768 | + gdf["country"] = gdf.bus.str[:2] |
| 769 | + # filter for countries that are missing |
| 770 | + gdf[~gdf.country.isin(ammonia_plants.Country.unique())] |
| 771 | + |
| 772 | + n.add( |
| 773 | + "Link", |
| 774 | + ammonia_plants.index, |
| 775 | + bus0=ammonia_plants.bus, |
| 776 | + bus1=[bus + " NH3" for bus in ammonia_plants.bus] if snakemake.params.sector["ammonia"] else "EU NH3", |
| 777 | + bus2=[bus + " gas" for bus in ammonia_plants.bus] if snakemake.params.sector["gas_network"] else "EU gas", |
| 778 | + p_nom=ammonia_plants["Production in tons (calibrated)"].mul(snakemake.params.MWh_NH3_per_tNH3).div(costs.at["Haber-Bosch", "electricity-input"]).div(8760).values, |
| 779 | + p_nom_extendable=False, |
| 780 | + carrier="Haber-Bosch", |
| 781 | + efficiency=1 / costs.at["Haber-Bosch", "electricity-input"], |
| 782 | + efficiency2=-costs.at["Haber-Bosch", "hydrogen-input"] |
| 783 | + / costs.at["Haber-Bosch", "electricity-input"], |
| 784 | + capital_cost=costs.at["Haber-Bosch", "capital_cost"] |
| 785 | + / costs.at["Haber-Bosch", "electricity-input"], |
| 786 | + marginal_cost=costs.at["Haber-Bosch", "VOM"] |
| 787 | + / costs.at["Haber-Bosch", "electricity-input"], |
| 788 | + build_year=ammonia_plants["grouping_year"], |
| 789 | + lifetime=costs.at["Haber-Bosch", "lifetime"], |
| 790 | + ) |
| 791 | + |
| 792 | + |
| 793 | + |
719 | 794 | if __name__ == "__main__": |
720 | 795 | if "snakemake" not in globals(): |
721 | 796 | from scripts._helpers import mock_snakemake |
@@ -797,6 +872,10 @@ def add_heating_capacities_installed_before_baseyear( |
797 | 872 | if options.get("cluster_heat_buses", False): |
798 | 873 | cluster_heat_buses(n) |
799 | 874 |
|
| 875 | + # add existing industry plants |
| 876 | + if snakemake.sector.ammonia: |
| 877 | + add_existing_ammonia_plants(n) |
| 878 | + |
800 | 879 | n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) |
801 | 880 |
|
802 | 881 | sanitize_custom_columns(n) |
|
0 commit comments