Separate ammonia from other "Basic chemicals"

This allows us to control the substitution of natural gas for hydrogen
in NH3 production.

Remaining basic chemicals are olefins, BTX and chlorine.

For 2015 NH3 production, we use the USGS data source.
This commit is contained in:
Tom Brown 2020-08-28 19:13:18 +02:00
parent b761281b3d
commit f45b9a37ae
7 changed files with 147 additions and 23 deletions

2
.gitignore vendored
View File

@ -43,3 +43,5 @@ gurobi.log
config.yaml
doc/_build
*.xls

View File

@ -146,8 +146,19 @@ rule build_biomass_potentials:
resources: mem_mb=1000
script: 'scripts/build_biomass_potentials.py'
rule build_ammonia_production:
input:
usgs="data/myb1-2017-nitro.xls"
output:
ammonia_production="resources/ammonia_production.csv"
threads: 1
resources: mem_mb=1000
script: 'scripts/build_ammonia_production.py'
rule build_industry_sector_ratios:
input:
ammonia_production="resources/ammonia_production.csv"
output:
industry_sector_ratios="resources/industry_sector_ratios.csv"
threads: 1
@ -156,6 +167,8 @@ rule build_industry_sector_ratios:
rule build_industrial_production_per_country:
input:
ammonia_production="resources/ammonia_production.csv"
output:
industrial_production_per_country="resources/industrial_production_per_country.csv"
threads: 1

View File

@ -161,7 +161,10 @@ industry:
'St_primary_fraction' : 0.3 # fraction of steel produced via primary route (DRI + EAF) versus secondary route (EAF); today fraction is 0.6
'H2_DRI' : 1.7 #H2 consumption in Direct Reduced Iron (DRI), MWh_H2,LHV/ton_Steel from Vogl et al (2018) doi:10.1016/j.jclepro.2018.08.279
'Al_primary_fraction' : 0.2 # fraction of aluminium produced via the primary route versus scrap; today fraction is 0.4
'H2_for_NH3' : 85000 # H2 in GWh/a for 17 MtNH3/a transformed from SMR to electrolyzed-H2, following Lechtenböhmer(2016)
'MWh_CH4_per_tNH3_SMR' : 10.8 # 2012's demand from https://ec.europa.eu/docsroom/documents/4165/attachments/1/translations/en/renditions/pdf
'MWh_elec_per_tNH3_SMR' : 0.7 # same source, assuming 94-6% split methane-elec of total energy demand 11.5 MWh/tNH3
'MWh_H2_per_tNH3_electrolysis' : 6.5 # from https://doi.org/10.1016/j.joule.2018.04.017, around 0.197 tH2/tHN3 (>3/17 since some H2 lost and used for energy)
'MWh_elec_per_tNH3_electrolysis' : 1.17 # from https://doi.org/10.1016/j.joule.2018.04.017 Table 13 (air separation and HB)
'NH3_process_emissions' : 24.5 # in MtCO2/a from SMR for H2 production for NH3 from UNFCCC for 2015 for EU28
'petrochemical_process_emissions' : 25.5 # in MtCO2/a for petrochemical and other from UNFCCC for 2015 for EU28

View File

@ -161,7 +161,10 @@ industry:
'St_primary_fraction' : 0.3 # fraction of steel produced via primary route (DRI + EAF) versus secondary route (EAF); today fraction is 0.6
'H2_DRI' : 1.7 #H2 consumption in Direct Reduced Iron (DRI), MWh_H2,LHV/ton_Steel from Vogl et al (2018) doi:10.1016/j.jclepro.2018.08.279
'Al_primary_fraction' : 0.2 # fraction of aluminium produced via the primary route versus scrap; today fraction is 0.4
'H2_for_NH3' : 85000 # H2 in GWh/a for 17 MtNH3/a transformed from SMR to electrolyzed-H2, following Lechtenböhmer(2016)
'MWh_CH4_per_tNH3_SMR' : 10.8 # 2012's demand from https://ec.europa.eu/docsroom/documents/4165/attachments/1/translations/en/renditions/pdf
'MWh_elec_per_tNH3_SMR' : 0.7 # same source, assuming 94-6% split methane-elec of total energy demand 11.5 MWh/tNH3
'MWh_H2_per_tNH3_electrolysis' : 6.5 # from https://doi.org/10.1016/j.joule.2018.04.017, around 0.197 tH2/tHN3 (>3/17 since some H2 lost and used for energy)
'MWh_elec_per_tNH3_electrolysis' : 1.17 # from https://doi.org/10.1016/j.joule.2018.04.017 Table 13 (air separation and HB)
'NH3_process_emissions' : 24.5 # in MtCO2/a from SMR for H2 production for NH3 from UNFCCC for 2015 for EU28
'petrochemical_process_emissions' : 25.5 # in MtCO2/a for petrochemical and other from UNFCCC for 2015 for EU28

View File

@ -0,0 +1,45 @@
import pandas as pd
ammonia = pd.read_excel(snakemake.input.usgs,
sheet_name="T12",
skiprows=5,
header=0,
index_col=0,
skipfooter=19)
rename = {"Austriae" : "AT",
"Bulgaria" : "BG",
"Belgiume" : "BE",
"Croatia" : "HR",
"Czechia" : "CZ",
"Estonia" : "EE",
"Finland" : "FI",
"France" : "FR",
"Germany" : "DE",
"Greece" : "GR",
"Hungarye" : "HU",
"Italye" : "IT",
"Lithuania" : "LT",
"Netherlands" : "NL",
"Norwaye" : "NO",
"Poland" : "PL",
"Romania" : "RO",
"Serbia" : "RS",
"Slovakia" : "SK",
"Spain" : "ES",
"Switzerland" : "CH",
"United Kingdom" : "GB",
}
ammonia = ammonia.rename(rename)
ammonia = ammonia.loc[rename.values(),[str(i) for i in range(2013,2018)]].astype(float)
#convert from ktonN to ktonNH3
ammonia = ammonia*17/14
ammonia.index.name = "ktonNH3/a"
ammonia.to_csv(snakemake.output.ammonia_production)

View File

@ -9,6 +9,10 @@ ktoe_to_twh = 0.01163
jrc_base_dir = "data/jrc-idees-2015"
eb_base_dir = "data/eurostat-energy_balances-may_2018_edition"
# year for which data is retrieved
raw_year = 2015
year = raw_year-2016
sub_sheet_name_dict = { 'Iron and steel':'ISI',
'Chemicals Industry':'CHI',
'Non-metallic mineral products': 'NMM',
@ -162,7 +166,7 @@ for country in countries:
#energy consumption in the sector and EU28
excel_sum_out = pd.read_excel('{}/JRC-IDEES-2015_Industry_EU28.xlsx'.format(jrc_base_dir),
sheet_name='Ind_Summary', index_col=0,header=0,squeeze=True) # the summary sheet
s_sum_out = excel_sum_out.iloc[49:76,-1]
s_sum_out = excel_sum_out.iloc[49:76,year]
e_EU28 = s_sum_out[dic_sec_summary[sector]]
ratio_country_EU28=e_country/e_EU28
@ -170,7 +174,7 @@ for country in countries:
excel_out = pd.read_excel('{}/JRC-IDEES-2015_Industry_EU28.xlsx'.format(jrc_base_dir),
sheet_name=sub_sheet_name_dict[sector],index_col=0,header=0,squeeze=True) # the summary sheet
s_out = excel_out.iloc[loc_dic[sector][0]:loc_dic[sector][1],-1]
s_out = excel_out.iloc[loc_dic[sector][0]:loc_dic[sector][1],year]
for subsector in sect2sub[sector]:
countries_demand.loc[country,subsector] = ratio_country_EU28*s_out[out_dic[subsector]]
@ -180,11 +184,34 @@ for country in countries:
# read the input sheets
excel_out = pd.read_excel('{}/JRC-IDEES-2015_Industry_{}.xlsx'.format(jrc_base_dir,jrc_names.get(country,country)), sheet_name=sub_sheet_name_dict[sector],index_col=0,header=0,squeeze=True) # the summary sheet
s_out = excel_out.iloc[loc_dic[sector][0]:loc_dic[sector][1],-1]
s_out = excel_out.iloc[loc_dic[sector][0]:loc_dic[sector][1],year]
for subsector in sect2sub[sector]:
countries_demand.loc[country,subsector] = s_out[out_dic[subsector]]
#include ammonia demand separately and remove ammonia from basic chemicals
ammonia = pd.read_csv(snakemake.input.ammonia_production,
index_col=0)
there = ammonia.index.intersection(countries_demand.index)
missing = countries_demand.index^there
print("Following countries have no ammonia demand:", missing)
countries_demand.insert(2,"Ammonia",0.)
countries_demand.loc[there,"Ammonia"] = ammonia.loc[there, str(raw_year)]
countries_demand["Basic chemicals"] -= countries_demand["Ammonia"]
#EE, HR and LT got negative demand through subtraction - poor data
countries_demand.loc[countries_demand["Basic chemicals"] < 0.,"Basic chemicals"] = 0.
countries_demand.rename(columns={"Basic chemicals" : "Basic chemicals (without ammonia)"},
inplace=True)
countries_demand.index.name = "kton/a"
countries_demand.to_csv(snakemake.output.industrial_production_per_country,

View File

@ -5,11 +5,11 @@ import numpy as np
base_dir = "data/jrc-idees-2015"
# year for wich data is retrieved
year = 2015
year = year-2016
# year for which data is retrieved
raw_year = 2015
year = raw_year-2016
conv_factor=11.630 #ktoe/kton -> MWh/ton
conv_factor=11.630 #GWh/ktoe OR MWh/toe
country = 'EU28'
@ -185,6 +185,8 @@ excel_emi = pd.read_excel('{}/JRC-IDEES-2015_Industry_{}.xlsx'.format(base_dir,c
### Basic chemicals
## Ammonia is separate afterwards
sector = 'Basic chemicals'
df[sector] = 0
@ -203,9 +205,8 @@ df.loc['heat',sector] += s_fec['Low enthalpy heat']
#### Chemicals: Feedstock (energy used as raw material)
#> There are Solids, Refinery gas, LPG, Diesel oil, Residual fuel oil, Other liquids, Naphtha, Natural gas for feedstock.
#
#> Naphta represents 47%, methane 17%. LPG (18%) solids, refinery gas, diesel oil, residual fuel oils and other liquids are asimilated to Napthta
#
#> Following Lechtenbohmer 2016, the 85 TWh/year of methane for the ammonia industry are substited by hydrogen.
#> Naphta represents 47%, methane 17%. LPG (18%) solids, refinery gas, diesel oil, residual fuel oils and other liquids are asimilated to Naphtha
subsector = 'Chemicals: Feedstock (energy used as raw material)'
@ -218,10 +219,7 @@ assert s_fec.index[0] == subsector
df.loc['naphtha',sector] += s_fec['Naphtha']
# natural gas
# 85 TWh/year of methane for the ammonia industry are substituted by hydrogen
df.loc['methane',sector] += s_fec['Natural gas'] - snakemake.config["industry"]["H2_for_NH3"]/conv_factor
df.loc['hydrogen',sector] += snakemake.config["industry"]["H2_for_NH3"]/conv_factor
# 1 ktoe = 11630 MWh
df.loc['methane',sector] += s_fec['Natural gas']
# LPG and other feedstock materials are assimilated to naphtha since they will be produced trough Fischer-Tropsh process
df.loc['naphtha',sector] += (s_fec['Solids'] + s_fec['Refinery gas'] + s_fec['LPG'] + s_fec['Diesel oil']
@ -244,8 +242,10 @@ assert s_fec.index[0] == subsector
# efficiency of biomass
eff_bio = s_ued['Biomass']/s_fec['Biomass']
# replace all fec by biomass
df.loc['biomass',sector] += s_ued[subsector]/eff_bio
# replace all non-methane fec by biomass
df.loc['biomass',sector] += (s_ued[subsector]-s_ued['Natural gas (incl. biogas)'])/eff_bio
df.loc['methane',sector] += s_fec['Natural gas (incl. biogas)']
#### Chemicals: Furnaces
#> assume fully electrified
@ -297,10 +297,25 @@ s_emi = excel_emi.iloc[3:57,year]
assert s_emi.index[0] == sector
## Correct everything by subtracting 2015's ammonia demand and putting in ammonia demand for H2 and electricity separately
s_out = excel_out.iloc[8:9,year]
assert sector in str(s_out.index)
ammonia = pd.read_csv(snakemake.input.ammonia_production,
index_col=0)
eu28 = ['FR', 'DE', 'GB', 'IT', 'ES', 'PL', 'SE', 'NL', 'BE', 'FI',
'DK', 'PT', 'RO', 'AT', 'BG', 'EE', 'GR', 'LV', 'CZ',
'HU', 'IE', 'SK', 'LT', 'HR', 'LU', 'SI', 'CY', 'MT']
#ktNH3/a
total_ammonia = ammonia.loc[ammonia.index.intersection(eu28),str(raw_year)].sum()
s_out -= total_ammonia
df.loc['process emission',sector] += (s_emi['Process emissions'] - snakemake.config["industry"]['petrochemical_process_emissions']*1e3 - snakemake.config["industry"]['NH3_process_emissions']*1e3)/s_out.values # unit tCO2/t material
#these are emissions originating from feedstock, i.e. could be non-fossil origin
@ -310,8 +325,24 @@ df.loc['process emission from feedstock',sector] += (snakemake.config["industry"
# final energy consumption per t
sources=['elec','biomass', 'methane', 'hydrogen', 'heat','naphtha']
df.loc[sources,sector] = df.loc[sources,sector]*conv_factor/s_out.values# unit MWh/t material
# 1 ktoe = 11630 MWh
#convert from ktoe/a to GWh/a
df.loc[sources,sector] *= conv_factor
df.loc['methane',sector] -= total_ammonia*snakemake.config['industry']['MWh_CH4_per_tNH3_SMR']
df.loc['elec',sector] -= total_ammonia*snakemake.config['industry']['MWh_elec_per_tNH3_SMR']
df.loc[sources,sector] = df.loc[sources,sector]/s_out.values # unit MWh/t material
df.rename(columns={sector : sector + " (without ammonia)"},
inplace=True)
sector = 'Ammonia'
df[sector] = 0.
df.loc['hydrogen',sector] = snakemake.config['industry']['MWh_H2_per_tNH3_electrolysis']
df.loc['elec',sector] = snakemake.config['industry']['MWh_elec_per_tNH3_electrolysis']
### Other chemicals
@ -404,7 +435,7 @@ df.loc['process emission',sector] += s_emi['Process emissions']/s_out.values # u
# final energy consumption per t
sources=['elec','biomass', 'methane', 'hydrogen', 'heat','naphtha']
df.loc[sources,sector] = df.loc[sources,sector]*11.630/s_out.values # unit MWh/t material
df.loc[sources,sector] = df.loc[sources,sector]*conv_factor/s_out.values # unit MWh/t material
# 1 ktoe = 11630 MWh
### Pharmaceutical products etc.
@ -494,7 +525,7 @@ df.loc['process emission',sector] += 0 # unit tCO2/t material
# final energy consumption per t
sources=['elec','biomass', 'methane', 'hydrogen', 'heat', 'naphtha']
df.loc[sources,sector] = df.loc[sources,sector]*11.630/s_out.values # unit MWh/t material
df.loc[sources,sector] = df.loc[sources,sector]*conv_factor/s_out.values # unit MWh/t material
# 1 ktoe = 11630 MWh
## Non-metallic mineral products
@ -634,7 +665,7 @@ df.loc['process emission',sector] += s_emi['Process emissions']/s_out.values # u
# final energy consumption per t
sources=['elec','biomass', 'methane', 'hydrogen', 'heat','naphtha']
df.loc[sources,sector] = df.loc[sources,sector]*11.630/s_out.values # unit MWh/t material
df.loc[sources,sector] = df.loc[sources,sector]*conv_factor/s_out.values # unit MWh/t material
# 1 ktoe = 11630 MWh
### Glass production