Merge branch 'master' into distribution

This commit is contained in:
Tom Brown 2020-09-22 20:18:21 +02:00 committed by GitHub
commit a1904886ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 697 additions and 195 deletions

2
.gitignore vendored
View File

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

View File

@ -130,9 +130,9 @@ rule build_energy_totals:
input:
nuts3_shapes=pypsaeur('resources/nuts3_shapes.geojson')
output:
energy_name='data/energy_totals.csv',
co2_name='data/co2_totals.csv',
transport_name='data/transport_data.csv'
energy_name='resources/energy_totals.csv',
co2_name='resources/co2_totals.csv',
transport_name='resources/transport_data.csv'
threads: 1
resources: mem_mb=10000
script: 'scripts/build_energy_totals.py'
@ -141,13 +141,25 @@ rule build_biomass_potentials:
input:
jrc_potentials="data/biomass/JRC Biomass Potentials.xlsx"
output:
biomass_potentials='data/biomass_potentials.csv'
biomass_potentials_all='resources/biomass_potentials_all.csv',
biomass_potentials='resources/biomass_potentials.csv'
threads: 1
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
@ -155,20 +167,51 @@ rule build_industry_sector_ratios:
script: 'scripts/build_industry_sector_ratios.py'
rule build_industrial_demand_per_country:
rule build_industrial_production_per_country:
input:
industry_sector_ratios="resources/industry_sector_ratios.csv"
ammonia_production="resources/ammonia_production.csv"
output:
industrial_demand_per_country="resources/industrial_demand_per_country.csv"
industrial_production_per_country="resources/industrial_production_per_country.csv"
threads: 1
resources: mem_mb=1000
script: 'scripts/build_industrial_demand_per_country.py'
script: 'scripts/build_industrial_production_per_country.py'
rule build_industrial_production_per_country_tomorrow:
input:
industrial_production_per_country="resources/industrial_production_per_country.csv"
output:
industrial_production_per_country_tomorrow="resources/industrial_production_per_country_tomorrow.csv"
threads: 1
resources: mem_mb=1000
script: 'scripts/build_industrial_production_per_country_tomorrow.py'
rule build_industrial_energy_demand_per_country_today:
input:
ammonia_production="resources/ammonia_production.csv",
industrial_production_per_country="resources/industrial_production_per_country.csv"
output:
industrial_energy_demand_per_country_today="resources/industrial_energy_demand_per_country_today.csv"
threads: 1
resources: mem_mb=1000
script: 'scripts/build_industrial_energy_demand_per_country_today.py'
rule build_industrial_energy_demand_per_country:
input:
industry_sector_ratios="resources/industry_sector_ratios.csv",
industrial_production_per_country="resources/industrial_production_per_country_tomorrow.csv"
output:
industrial_energy_demand_per_country="resources/industrial_energy_demand_per_country.csv"
threads: 1
resources: mem_mb=1000
script: 'scripts/build_industrial_energy_demand_per_country.py'
rule build_industrial_demand:
input:
clustered_pop_layout="resources/pop_layout_{network}_s{simpl}_{clusters}.csv",
industrial_demand_per_country="resources/industrial_demand_per_country.csv"
industrial_demand_per_country="resources/industrial_energy_demand_per_country.csv"
output:
industrial_demand="resources/industrial_demand_{network}_s{simpl}_{clusters}.csv"
threads: 1
@ -179,10 +222,10 @@ rule build_industrial_demand:
rule prepare_sector_network:
input:
network=pypsaeur('networks/{network}_s{simpl}_{clusters}_ec_lv{lv}_{opts}.nc'),
energy_totals_name='data/energy_totals.csv',
co2_totals_name='data/co2_totals.csv',
transport_name='data/transport_data.csv',
biomass_potentials='data/biomass_potentials.csv',
energy_totals_name='resources/energy_totals.csv',
co2_totals_name='resources/co2_totals.csv',
transport_name='resources/transport_data.csv',
biomass_potentials='resources/biomass_potentials.csv',
timezone_mappings='data/timezone_mappings.csv',
heat_profile="data/heat_load_profile_BDEW.csv",
costs=config['costs_dir'] + "costs_{planning_horizons}.csv",

View File

@ -48,6 +48,10 @@ electricity:
biomass:
year: 2030
scenario: "Med"
classes:
solid biomass: ['Primary agricultural residues', 'Forestry energy residue', 'Secondary forestry residues', 'Secondary Forestry residues sawdust', 'Forestry residues from landscape care biomass', 'Municipal waste']
not included: ['Bioethanol sugar beet biomass', 'Rapeseeds for biodiesel', 'sunflower and soya for Biodiesel', 'Starchy crops biomass', 'Grassy crops biomass', 'Willow biomass', 'Poplar biomass potential', 'Roundwood fuelwood', 'Roundwood Chips & Pellets']
biogas: ['Manure biomass potential', 'Sludge biomass']
# only relevant for foresight = myopic or perfect
existing_capacities:
@ -160,10 +164,14 @@ solving:
mem: 30000 #memory in MB; 20 GB enough for 50+B+I+H2; 100 GB for 181+B+I+H2
industry:
'DRI_ratio' : 0.5 #ratio of today's blast-furnace steel (60% primary route, 40% secondary) to future assumption (30% primary, 70% secondary), transformed into DRI + electric arc
'H2_DRI' : 1.7 #H2 consumption in Direct Reduced Iron (DRI), MWh_H2/ton_Steel from Vogl et al (2018) doi:10.1016/j.jclepro.2018.08.279
'Al_to_scrap' : 0.5 # ratio of primary-route Aluminum transformed into scrap (today 40% to future 20% primary route)
'H2_for_NH3' : 85000 # H2 in GWh/a for 17 MtNH3/a transformed from SMR to electrolyzed-H2, following Lechtenböhmer(2016)
'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
'elec_DRI' : 0.322 #electricity consumption in Direct Reduced Iron (DRI) shaft, MWh/tSt HYBRIT brochure https://ssabwebsitecdn.azureedge.net/-/media/hybrit/files/hybrit_brochure.pdf
'Al_primary_fraction' : 0.2 # fraction of aluminium produced via the primary route versus scrap; today fraction is 0.4
'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

@ -48,6 +48,10 @@ electricity:
biomass:
year: 2030
scenario: "Med"
classes:
solid biomass: ['Primary agricultural residues', 'Forestry energy residue', 'Secondary forestry residues', 'Secondary Forestry residues sawdust', 'Forestry residues from landscape care biomass', 'Municipal waste']
not included: ['Bioethanol sugar beet biomass', 'Rapeseeds for biodiesel', 'sunflower and soya for Biodiesel', 'Starchy crops biomass', 'Grassy crops biomass', 'Willow biomass', 'Poplar biomass potential', 'Roundwood fuelwood', 'Roundwood Chips & Pellets']
biogas: ['Manure biomass potential', 'Sludge biomass']
# only relevant for foresight = myopic or perfect
existing_capacities:
@ -160,10 +164,14 @@ solving:
mem: 30000 #memory in MB; 20 GB enough for 50+B+I+H2; 100 GB for 181+B+I+H2
industry:
'DRI_ratio' : 0.5 #ratio of today's blast-furnace steel (60% primary route, 40% secondary) to future assumption (30% primary, 70% secondary), transformed into DRI + electric arc
'H2_DRI' : 1.7 #H2 consumption in Direct Reduced Iron (DRI), MWh_H2/ton_Steel from Vogl et al (2018) doi:10.1016/j.jclepro.2018.08.279
'Al_to_scrap' : 0.5 # ratio of primary-route Aluminum transformed into scrap (today 40% to future 20% primary route)
'H2_for_NH3' : 85000 # H2 in GWh/a for 17 MtNH3/a transformed from SMR to electrolyzed-H2, following Lechtenböhmer(2016)
'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
'elec_DRI' : 0.322 #electricity consumption in Direct Reduced Iron (DRI) shaft, MWh/tSt HYBRIT brochure https://ssabwebsitecdn.azureedge.net/-/media/hybrit/files/hybrit_brochure.pdf
'Al_primary_fraction' : 0.2 # fraction of aluminium produced via the primary route versus scrap; today fraction is 0.4
'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

@ -18,7 +18,11 @@ its dependencies. Clone the repository:
projects % git clone git@github.com:PyPSA/pypsa-eur.git
then download and unpack all the PyPSA-Eur data files.
then download and unpack all the PyPSA-Eur data files by running the following snakemake rule:
.. code:: bash
projects/pypsa-eur % snakemake -j 1 retrieve_databundle
Clone technology-data repository
@ -65,8 +69,8 @@ To download and extract it on the command line:
.. code:: bash
projects/pypsa-eur-sec/data % wget "https://nworbmot.org/pypsa-eur-sec-data-bundle-190719.tar.gz"
projects/pypsa-eur-sec/data % tar xvzf pypsa-eur-sec-data-bundle-190719.tar.gz
projects/pypsa-eur-sec/data % wget "https://nworbmot.org/pypsa-eur-sec-data-bundle-200921.tar.gz"
projects/pypsa-eur-sec/data % tar xvzf pypsa-eur-sec-data-bundle-200921.tar.gz
Set up the default configuration
================================

View File

@ -74,3 +74,9 @@ Release Process
* Make a `GitHub release <https://github.com/PyPSA/pypsa-eur-sec/releases>`_, which automatically triggers archiving by `zenodo <https://doi.org/10.5281/zenodo.3938042>`_.
* Send announcement on the `PyPSA mailing list <https://groups.google.com/forum/#!forum/pypsa>`_.
To make a new release of the data bundle, do:
.. code:: bash
data % tar pczf pypsa-eur-sec-data-bundle-date.tar.gz eea switzerland-sfoe biomass eurostat-energy_balances-* jrc-idees-2015 emobility urban_percent.csv timezone_mappings.csv heat_load_profile_DK_AdamJensen.csv WindWaveWEC_GLTB.xlsx myb1-2017-nitro.xls

View File

@ -98,8 +98,8 @@ if __name__ == "__main__":
output=['pypsa-eur-sec/results/test/prenetworks_brownfield/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{planning_horizons}.nc']
)
import yaml
with open('config.yaml') as f:
snakemake.config = yaml.load(f)
with open('config.yaml', encoding='utf8') as f:
snakemake.config = yaml.safe_load(f)
print(snakemake.input.network_p)
logging.basicConfig(level=snakemake.config['logging_level'])

View File

@ -423,8 +423,8 @@ if __name__ == "__main__":
output=['pypsa-eur-sec/results/test/prenetworks_brownfield/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{planning_horizons}.nc'],
)
import yaml
with open('config.yaml') as f:
snakemake.config = yaml.load(f)
with open('config.yaml', encoding='utf8') as f:
snakemake.config = yaml.safe_load(f)
logging.basicConfig(level=snakemake.config['logging_level'])

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

@ -19,29 +19,28 @@ def build_biomass_potentials():
for i in range(36):
df_dict[df.iloc[i*16,1]] = df.iloc[1+i*16:(i+1)*16].astype(float)
df_new = pd.concat(df_dict)
#convert from PJ to MWh
df_new = pd.concat(df_dict).rename({"UK" : "GB", "BH" : "BA"})/3.6*1e6
df_new.index.name = "MWh/a"
df_new.to_csv(snakemake.output.biomass_potentials_all)
# solid biomass includes: Primary agricultural residues (MINBIOAGRW1),
# Forestry energy residue (MINBIOFRSF1),
# Forestry energy residue (MINBIOFRSF1),
# Secondary forestry residues (MINBIOWOOW1),
# Secondary Forestry residues sawdust (MINBIOWOO1a)',
# Forestry residues from landscape care biomass (MINBIOFRSF1a),
# Forestry residues from landscape care biomass (MINBIOFRSF1a),
# Municipal waste (MINBIOMUN1)',
# biogas includes : Manure biomass potential (MINBIOGAS1),
# Sludge biomass (MINBIOSLU1)
us_type = pd.Series(index=df_new.columns)
us_type.iloc[0:7] = "not included"
us_type.iloc[7:8] = "biogas"
us_type.iloc[8:9] = "solid biomass"
us_type.iloc[9:11] = "not included"
us_type.iloc[11:16] = "solid biomass"
us_type.iloc[16:17] = "biogas"
us_type = pd.Series("", df_new.columns)
#convert from PJ to MWh
biomass_potentials = df_new.loc[idx[:,snakemake.config['biomass']['year'],snakemake.config['biomass']['scenario']],:].groupby(us_type,axis=1).sum().groupby(level=0).sum().rename({"UK" : "GB", "BH" : "BA"})/3.6*1e6
for k,v in snakemake.config['biomass']['classes'].items():
us_type.loc[v] = k
biomass_potentials = df_new.swaplevel(0,2).loc[snakemake.config['biomass']['scenario'],snakemake.config['biomass']['year']].groupby(us_type,axis=1).sum()
biomass_potentials.index.name = "MWh/a"
biomass_potentials.to_csv(snakemake.output.biomass_potentials)
@ -58,7 +57,7 @@ if __name__ == "__main__":
snakemake.input['jrc_potentials'] = "data/biomass/JRC Biomass Potentials.xlsx"
snakemake.output = Dict()
snakemake.output['biomass_potentials'] = 'data/biomass_potentials.csv'
with open('config.yaml') as f:
snakemake.config = yaml.load(f)
with open('config.yaml', encoding='utf8') as f:
snakemake.config = yaml.safe_load(f)
build_biomass_potentials()

View File

@ -7,7 +7,7 @@ def build_industrial_demand():
pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout,index_col=0)
pop_layout["ct"] = pop_layout.index.str[:2]
ct_total = pop_layout.total.groupby(pop_layout["ct"]).sum()
pop_layout["ct_total"] = pop_layout["ct"].map(ct_total.get)
pop_layout["ct_total"] = pop_layout["ct"].map(ct_total)
pop_layout["fraction"] = pop_layout["total"]/pop_layout["ct_total"]
industrial_demand_per_country = pd.read_csv(snakemake.input.industrial_demand_per_country,index_col=0)
@ -33,7 +33,7 @@ if __name__ == "__main__":
snakemake.input['industrial_demand_per_country']="resources/industrial_demand_per_country.csv"
snakemake.output = Dict()
snakemake.output['industrial_demand'] = "resources/industrial_demand_elec_s_128.csv"
with open('config.yaml') as f:
snakemake.config = yaml.load(f)
with open('config.yaml', encoding='utf8') as f:
snakemake.config = yaml.safe_load(f)
build_industrial_demand()

View File

@ -0,0 +1,83 @@
import pandas as pd
import numpy as np
tj_to_ktoe = 0.0238845
ktoe_to_twh = 0.01163
eb_base_dir = "data/eurostat-energy_balances-may_2018_edition"
jrc_base_dir = "data/jrc-idees-2015"
# import EU ratios df as csv
industry_sector_ratios=pd.read_csv(snakemake.input.industry_sector_ratios,
index_col=0)
#material demand per country and industry (kton/a)
countries_production = pd.read_csv(snakemake.input.industrial_production_per_country, index_col=0)
#Annual energy consumption in Switzerland by sector in 2015 (in TJ)
#From: Energieverbrauch in der Industrie und im Dienstleistungssektor, Der Bundesrat
#http://www.bfe.admin.ch/themen/00526/00541/00543/index.html?lang=de&dossier_id=00775
dic_Switzerland ={'Iron and steel': 7889.,
'Chemicals Industry': 26871.,
'Non-metallic mineral products': 15513.+3820.,
'Pulp, paper and printing': 12004.,
'Food, beverages and tobacco': 17728.,
'Non Ferrous Metals': 3037.,
'Transport Equipment': 14993.,
'Machinery Equipment': 4724.,
'Textiles and leather': 1742.,
'Wood and wood products': 0.,
'Other Industrial Sectors': 10825.,
'current electricity': 53760.}
eb_names={'NO':'Norway', 'AL':'Albania', 'BA':'Bosnia and Herzegovina',
'MK':'FYR of Macedonia', 'GE':'Georgia', 'IS':'Iceland',
'KO':'Kosovo', 'MD':'Moldova', 'ME':'Montenegro', 'RS':'Serbia',
'UA':'Ukraine', 'TR':'Turkey', }
jrc_names = {"GR" : "EL",
"GB" : "UK"}
#final energy consumption per country and industry (TWh/a)
countries_df = countries_production.dot(industry_sector_ratios.T)
countries_df*= 0.001 #GWh -> TWh (ktCO2 -> MtCO2)
non_EU = ['NO', 'CH', 'ME', 'MK', 'RS', 'BA', 'AL']
# save current electricity consumption
for country in countries_df.index:
if country in non_EU:
if country == 'CH':
countries_df.loc[country, 'current electricity']=dic_Switzerland['current electricity']*tj_to_ktoe*ktoe_to_twh
else:
excel_balances = pd.read_excel('{}/{}.XLSX'.format(eb_base_dir,eb_names[country]),
sheet_name='2016', index_col=1,header=0, skiprows=1 ,squeeze=True)
countries_df.loc[country, 'current electricity'] = excel_balances.loc['Industry', 'Electricity']*ktoe_to_twh
else:
excel_out = pd.read_excel('{}/JRC-IDEES-2015_Industry_{}.xlsx'.format(jrc_base_dir,jrc_names.get(country,country)),
sheet_name='Ind_Summary',index_col=0,header=0,squeeze=True) # the summary sheet
s_out = excel_out.iloc[27:48,-1]
countries_df.loc[country, 'current electricity'] = s_out['Electricity']*ktoe_to_twh
rename_sectors = {'elec':'electricity',
'biomass':'solid biomass',
'heat':'low-temperature heat'}
countries_df.rename(columns=rename_sectors,inplace=True)
countries_df.index.name = "TWh/a (MtCO2/a)"
countries_df.to_csv(snakemake.output.industrial_energy_demand_per_country,
float_format='%.2f')

View File

@ -0,0 +1,140 @@
import pandas as pd
# sub-sectors as used in PyPSA-Eur-Sec and listed in JRC-IDEES industry sheets
sub_sectors = {'Iron and steel' : ['Integrated steelworks','Electric arc'],
'Non-ferrous metals' : ['Alumina production','Aluminium - primary production','Aluminium - secondary production','Other non-ferrous metals'],
'Chemicals' : ['Basic chemicals', 'Other chemicals', 'Pharmaceutical products etc.', 'Basic chemicals feedstock'],
'Non-metalic mineral' : ['Cement','Ceramics & other NMM','Glass production'],
'Printing' : ['Pulp production','Paper production','Printing and media reproduction'],
'Food' : ['Food, beverages and tobacco'],
'Transport equipment' : ['Transport Equipment'],
'Machinery equipment' : ['Machinery Equipment'],
'Textiles and leather' : ['Textiles and leather'],
'Wood and wood products' : ['Wood and wood products'],
'Other Industrial Sectors' : ['Other Industrial Sectors'],
}
# name in JRC-IDEES Energy Balances
eb_sheet_name = {'Integrated steelworks' : 'cisb',
'Electric arc' : 'cise',
'Alumina production' : 'cnfa',
'Aluminium - primary production' : 'cnfp',
'Aluminium - secondary production' : 'cnfs',
'Other non-ferrous metals' : 'cnfo',
'Basic chemicals' : 'cbch',
'Other chemicals' : 'coch',
'Pharmaceutical products etc.' : 'cpha',
'Basic chemicals feedstock' : 'cpch',
'Cement' : 'ccem',
'Ceramics & other NMM' : 'ccer',
'Glass production' : 'cgla',
'Pulp production' : 'cpul',
'Paper production' : 'cpap',
'Printing and media reproduction' : 'cprp',
'Food, beverages and tobacco' : 'cfbt',
'Transport Equipment' : 'ctre',
'Machinery Equipment' : 'cmae',
'Textiles and leather' : 'ctel',
'Wood and wood products' : 'cwwp',
'Mining and quarrying' : 'cmiq',
'Construction' : 'ccon',
'Non-specified': 'cnsi',
}
fuels = {'all' : ['All Products'],
'solid' : ['Solid Fuels'],
'liquid' : ['Total petroleum products (without biofuels)'],
'gas' : ['Gases'],
'heat' : ['Nuclear heat','Derived heat'],
'biomass' : ['Biomass and Renewable wastes'],
'waste' : ['Wastes (non-renewable)'],
'electricity' : ['Electricity'],
}
ktoe_to_twh = 0.011630
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']
jrc_names = {"GR" : "EL",
"GB" : "UK"}
year = 2015
summaries = {}
#for some reason the Energy Balances list Other Industrial Sectors separately
ois_subs = ['Mining and quarrying','Construction','Non-specified']
#MtNH3/a
ammonia = pd.read_csv(snakemake.input.ammonia_production,
index_col=0)/1e3
for ct in eu28:
print(ct)
filename = 'data/jrc-idees-2015/JRC-IDEES-2015_EnergyBalance_{}.xlsx'.format(jrc_names.get(ct,ct))
summary = pd.DataFrame(index=list(fuels.keys()) + ['other'])
for sector in sub_sectors:
if sector == 'Other Industrial Sectors':
subs = ois_subs
else:
subs = sub_sectors[sector]
for sub in subs:
df = pd.read_excel(filename,
sheet_name=eb_sheet_name[sub],
index_col=0)
s = df[year].astype(float)
for fuel in fuels:
summary.at[fuel,sub] = s[fuels[fuel]].sum()
summary.at['other',sub] = summary.at['all',sub] - summary.loc[summary.index^['all','other'],sub].sum()
summary['Other Industrial Sectors'] = summary[ois_subs].sum(axis=1)
summary.drop(columns=ois_subs,inplace=True)
summary.drop(index=['all'],inplace=True)
summary *= ktoe_to_twh
summary['Basic chemicals'] += summary['Basic chemicals feedstock']
summary.drop(columns=['Basic chemicals feedstock'], inplace=True)
summary['Ammonia'] = 0.
summary.at['gas','Ammonia'] = snakemake.config['industry']['MWh_CH4_per_tNH3_SMR']*ammonia[str(year)].get(ct,0.)
summary.at['electricity','Ammonia'] = snakemake.config['industry']['MWh_elec_per_tNH3_SMR']*ammonia[str(year)].get(ct,0.)
summary['Basic chemicals (without ammonia)'] = summary['Basic chemicals'] - summary['Ammonia']
summary.loc[summary['Basic chemicals (without ammonia)'] < 0, 'Basic chemicals (without ammonia)'] = 0.
summary.drop(columns=['Basic chemicals'], inplace=True)
summaries[ct] = summary
final_summary = pd.concat(summaries,axis=1)
# add in the non-EU28 based on their output (which is derived from their energy too)
# output in MtMaterial/a
output = pd.read_csv(snakemake.input.industrial_production_per_country,
index_col=0)/1e3
eu28_averages = final_summary.groupby(level=1,axis=1).sum().divide(output.loc[eu28].sum(),axis=1)
non_eu28 = output.index^eu28
for ct in non_eu28:
print(ct)
final_summary = pd.concat((final_summary,pd.concat({ct : eu28_averages.multiply(output.loc[ct],axis=1)},axis=1)),axis=1)
final_summary.index.name = 'TWh/a'
final_summary.to_csv(snakemake.output.industrial_energy_demand_per_country_today)

View File

@ -1,26 +1,17 @@
#%matplotlib inline
import pandas as pd
import numpy as np
tj_to_ktoe = 0.0238845
ktoe_to_twh = 0.01163
jrc_base_dir = "data/jrc-idees-2015"
eb_base_dir = "data/eurostat-energy_balances-may_2018_edition"
tj_to_ktoe = 0.0238845
ktoe_to_twh = 0.01163
# import EU ratios df as csv
df=pd.read_csv('resources/industry_sector_ratios.csv', sep=';', index_col=0)
# year for which data is retrieved
raw_year = 2015
year = raw_year-2016
sub_sheet_name_dict = { 'Iron and steel':'ISI',
'Chemicals Industry':'CHI',
@ -36,20 +27,17 @@ sub_sheet_name_dict = { 'Iron and steel':'ISI',
index = ['elec','biomass','methane','hydrogen','heat','naphtha','process emission','process emission from feedstock']
countries_df = pd.DataFrame(columns=index) #data frame final energy consumption per country and source
non_EU = ['NO', 'CH', 'ME', 'MK', 'RS', 'BA', 'AL']
rename = {"GR" : "EL",
"GB" : "UK"}
jrc_names = {"GR" : "EL",
"GB" : "UK"}
eu28 = ['FR', 'DE', 'GB', 'IT', 'ES', 'PL', 'SE', 'NL', 'BE', 'FI', 'CZ',
'DK', 'PT', 'RO', 'AT', 'BG', 'EE', 'GR', 'LV',
'HU', 'IE', 'SK', 'LT', 'HR', 'LU', 'SI'] + ['CY','MT']
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']
countries = non_EU + [rename.get(eu,eu) for eu in eu28[:-2]]
countries = non_EU + eu28
sectors = ['Iron and steel','Chemicals Industry','Non-metallic mineral products',
@ -69,6 +57,14 @@ sect2sub = {'Iron and steel':['Electric arc','Integrated steelworks'],
'Wood and wood products' :['Wood and wood products'],
'Other Industrial Sectors':['Other Industrial Sectors']}
subsectors = [ss for s in sectors for ss in sect2sub[s]]
#material demand per country and industry (kton/a)
countries_demand = pd.DataFrame(index=countries,
columns=subsectors,
dtype=float)
out_dic ={'Electric arc': 'Electric arc',
'Integrated steelworks': 'Integrated steelworks',
'Basic chemicals': 'Basic chemicals (kt ethylene eq.)',
@ -117,10 +113,11 @@ dic_sec_summary = {'Iron and steel': 'Iron and steel',
'Other Industrial Sectors': ' Other Industrial Sectors'}
#countries=['CH']
dic_countries={'NO':'Norway', 'AL':'Albania', 'BA':'Bosnia and Herzegovina',
'MK':'FYR of Macedonia', 'GE':'Georgia', 'IS':'Iceland',
'KO':'Kosovo', 'MD':'Moldova', 'ME':'Montenegro', 'RS':'Serbia',
'UA':'Ukraine', 'TR':'Turkey', }
eb_names={'NO':'Norway', 'AL':'Albania', 'BA':'Bosnia and Herzegovina',
'MK':'FYR of Macedonia', 'GE':'Georgia', 'IS':'Iceland',
'KO':'Kosovo', 'MD':'Moldova', 'ME':'Montenegro', 'RS':'Serbia',
'UA':'Ukraine', 'TR':'Turkey', }
dic_sec ={'Iron and steel':'Iron & steel industry',
'Chemicals Industry': 'Chemical and Petrochemical industry',
'Non-metallic mineral products': 'Non-ferrous metal industry',
@ -153,8 +150,8 @@ dic_Switzerland ={'Iron and steel': 7889.,
dic_sec_position={}
for country in countries:
countries_df.loc[country] = 0
print (country)
countries_demand.loc[country] = 0.
print(country)
for sector in sectors:
if country in non_EU:
if country == 'CH':
@ -162,14 +159,14 @@ for country in countries:
else:
# estimate physical output
#energy consumption in the sector and country
excel_balances = pd.read_excel('{}/{}.XLSX'.format(eb_base_dir,dic_countries[country]),
excel_balances = pd.read_excel('{}/{}.XLSX'.format(eb_base_dir,eb_names[country]),
sheet_name='2016', index_col=2,header=0, skiprows=1 ,squeeze=True)
e_country = excel_balances.loc[dic_sec[sector], 'Total all products']
#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
@ -177,62 +174,45 @@ 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]:
output = ratio_country_EU28*s_out[out_dic[subsector]]
for ind in index:
countries_df.loc[country, ind] += float(output*df.loc[ind, subsector]) # kton * MWh = GWh (# kton * tCO2 = ktCO2)
countries_demand.loc[country,subsector] = ratio_country_EU28*s_out[out_dic[subsector]]
else:
# read the input sheets
excel_out = pd.read_excel('{}/JRC-IDEES-2015_Industry_{}.xlsx'.format(jrc_base_dir,country), sheet_name=sub_sheet_name_dict[sector],index_col=0,header=0,squeeze=True) # the summary sheet
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]:
output = s_out[out_dic[subsector]]
for ind in index:
countries_df.loc[country, ind] += output*df.loc[ind, subsector] #kton * MWh = GWh (# kton * tCO2 = ktCO2)
countries_df*= 0.001 #GWh -> TWh (ktCO2 -> MtCO2)
# save current electricity consumption
for country in countries:
if country in non_EU:
if country == 'CH':
countries_df.loc[country, 'current electricity']=dic_Switzerland['current electricity']*tj_to_ktoe*ktoe_to_twh
else:
excel_balances = pd.read_excel('{}/{}.XLSX'.format(eb_base_dir,dic_countries[country]),
sheet_name='2016', index_col=1,header=0, skiprows=1 ,squeeze=True)
countries_df.loc[country, 'current electricity'] = excel_balances.loc['Industry', 'Electricity']*ktoe_to_twh
else:
excel_out = pd.read_excel('{}/JRC-IDEES-2015_Industry_{}.xlsx'.format(jrc_base_dir,country),
sheet_name='Ind_Summary',index_col=0,header=0,squeeze=True) # the summary sheet
s_out = excel_out.iloc[27:48,-1]
countries_df.loc[country, 'current electricity'] = s_out['Electricity']*ktoe_to_twh
print(countries_df.loc[country, 'current electricity'])
countries_demand.loc[country,subsector] = s_out[out_dic[subsector]]
#include ammonia demand separately and remove ammonia from basic chemicals
# save df as csv
for ind in index:
countries_df[ind]=countries_df[ind].astype('float')
countries_df = countries_df.round(3)
ammonia = pd.read_csv(snakemake.input.ammonia_production,
index_col=0)
countries_df.rename(index={value : key for key,value in rename.items()},inplace=True)
there = ammonia.index.intersection(countries_demand.index)
missing = countries_demand.index^there
rename_sectors = {'elec':'electricity',
'biomass':'solid biomass',
'heat':'low-temperature heat'}
print("Following countries have no ammonia demand:", missing)
countries_df.rename(columns=rename_sectors,inplace=True)
countries_demand.insert(2,"Ammonia",0.)
countries_df.to_csv('resources/industrial_demand_per_country.csv',
float_format='%.2f')
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,
float_format='%.2f')

View File

@ -0,0 +1,27 @@
import pandas as pd
industrial_production = pd.read_csv(snakemake.input.industrial_production_per_country,
index_col=0)
total_steel = industrial_production[["Integrated steelworks","Electric arc"]].sum(axis=1)
fraction_primary_stays_primary = snakemake.config["industry"]["St_primary_fraction"]*total_steel.sum()/industrial_production["Integrated steelworks"].sum()
industrial_production.insert(2, "DRI + Electric arc",
fraction_primary_stays_primary*industrial_production["Integrated steelworks"])
industrial_production["Electric arc"] = total_steel - industrial_production["DRI + Electric arc"]
industrial_production["Integrated steelworks"] = 0.
total_aluminium = industrial_production[["Aluminium - primary production","Aluminium - secondary production"]].sum(axis=1)
fraction_primary_stays_primary = snakemake.config["industry"]["Al_primary_fraction"]*total_aluminium.sum()/industrial_production["Aluminium - primary production"].sum()
industrial_production["Aluminium - primary production"] = fraction_primary_stays_primary*industrial_production["Aluminium - primary production"]
industrial_production["Aluminium - secondary production"] = total_aluminium - industrial_production["Aluminium - primary production"]
industrial_production.to_csv(snakemake.output.industrial_production_per_country_tomorrow,
float_format='%.2f')

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'
@ -26,7 +26,7 @@ sub_sheet_name_dict = { 'Iron and steel':'ISI',
'Wood and wood products': 'WWP',
'Other Industrial Sectors': 'OIS'}
index = ['elec','biomass','methane','hydrogen','heat','naphtha','process emission','process emission from feedstock']
index = ['elec','coal','coke','biomass','methane','hydrogen','heat','naphtha','process emission','process emission from feedstock']
df = pd.DataFrame(index=index)
@ -58,7 +58,7 @@ excel_emi = pd.read_excel('{}/JRC-IDEES-2015_Industry_{}.xlsx'.format(base_dir,c
sector = 'Electric arc'
df[sector] = 0
df[sector] = 0.
# read the corresponding lines
s_fec = excel_fec.iloc[51:57,year]
@ -150,21 +150,122 @@ df.loc['process emission',sector] = s_emi['Process emissions']/s_out[sector] # u
# final energy consumption per t
df.loc[['elec','heat','methane'],sector] = df.loc[['elec','heat','methane'],sector]*conv_factor/s_out[sector] # unit MWh/t material
### For primary route: DRI with H2 + EAF
## Integrated steelworks is converted to Electric arc
#
#> Electric arc uses scrap metal and Direct Reduced Iron
#
#> We assume that when substituting Integrated Steelworks by Electric arc furnaces.
#> 50% of Integrated steelworks is substituted by scrap metal + electric furnaces
#> 50% of Integrated steelworks is substituted by Direct Reduce Iron (with Hydrogen) + electric furnaces
df['Integrated steelworks']=df['Electric arc']
df['DRI + Electric arc'] = df['Electric arc']
# adding the Hydrogen necessary for the Direct Reduction of Iron. consumption 1.7 MWh H2 /ton steel
#(0.5 because only half of the steel requires DRI, the rest is scrap metal)
df.loc['hydrogen', 'Integrated steelworks'] =snakemake.config["industry"]["H2_DRI"] * snakemake.config["industry"]["DRI_ratio"]
df.loc['hydrogen', 'DRI + Electric arc'] = snakemake.config["industry"]["H2_DRI"]
# add electricity consumption in DRI shaft (0.322 MWh/tSl)
df.loc['elec', 'DRI + Electric arc'] += snakemake.config["industry"]["elec_DRI"]
### Integrated steelworks (could be used in combination with CCS)
### Assume existing fuels are kept, except for furnaces, refining, rolling, finishing
### Ignore 'derived gases' since these are top gases from furnaces
sector = 'Integrated steelworks'
df['Integrated steelworks']= 0.
# read the corresponding lines
s_fec = excel_fec.iloc[3:9,year]
assert s_fec.index[0] == sector
# Lighting, Air compressors, Motor drives, Fans and pumps
df.loc['elec',sector] += s_fec[['Lighting','Air compressors','Motor drives','Fans and pumps']].sum()
# Low enthalpy heat
df.loc['heat',sector] += s_fec['Low enthalpy heat']
#### Steel: Sinter/Pellet making
subsector = 'Steel: Sinter/Pellet making'
# read the corresponding lines
s_fec = excel_fec.iloc[13:19,year]
s_ued = excel_ued.iloc[13:19,year]
assert s_fec.index[0] == subsector
df.loc['elec',sector] += s_fec['Electricity']
df.loc['methane',sector] += s_fec['Natural gas (incl. biogas)']
df.loc['methane',sector] += s_fec['Residual fuel oil']
df.loc['coal',sector] += s_fec['Solids']
#### Steel: Blast / Basic Oxygen Furnace
subsector = 'Steel: Blast /Basic oxygen furnace'
# read the corresponding lines
s_fec = excel_fec.iloc[19:25,year]
s_ued = excel_ued.iloc[19:25,year]
assert s_fec.index[0] == subsector
df.loc['methane',sector] += s_fec['Natural gas (incl. biogas)']
df.loc['methane',sector] += s_fec['Residual fuel oil']
df.loc['coal',sector] += s_fec['Solids']
df.loc['coke',sector] += s_fec['Coke']
#### Steel: Furnaces, Refining and Rolling
#> assume fully electrified
#
#> other processes are scaled by the used energy
subsector = 'Steel: Furnaces, Refining and Rolling'
# read the corresponding lines
s_fec = excel_fec.iloc[25:32,year]
s_ued = excel_ued.iloc[25:32,year]
assert s_fec.index[0] == subsector
# this process can be electrified
eff = s_ued['Steel: Furnaces, Refining and Rolling - Electric']/s_fec['Steel: Furnaces, Refining and Rolling - Electric']
df.loc['elec',sector] += s_ued[subsector]/eff
#### Steel: Products finishing
#> assume fully electrified
subsector = 'Steel: Products finishing'
# read the corresponding lines
s_fec = excel_fec.iloc[32:49,year]
s_ued = excel_ued.iloc[32:49,year]
assert s_fec.index[0] == subsector
# this process can be electrified
eff = s_ued['Steel: Products finishing - Electric']/s_fec['Steel: Products finishing - Electric']
df.loc['elec',sector] += s_ued[subsector]/eff
#### Process emissions (per physical output)
s_emi = excel_emi.iloc[3:50,year]
assert s_emi.index[0] == sector
s_out = excel_out.iloc[6:7,year]
assert sector in str(s_out.index)
df.loc['process emission',sector] = s_emi['Process emissions']/s_out[sector] # unit tCO2/t material
# final energy consumption per t
df.loc[['elec','heat','methane','coke','coal'],sector] = df.loc[['elec','heat','methane','coke','coal'],sector]*conv_factor/s_out[sector] # unit MWh/t material
## Chemicals Industry
@ -186,6 +287,8 @@ excel_emi = pd.read_excel('{}/JRC-IDEES-2015_Industry_{}.xlsx'.format(base_dir,c
### Basic chemicals
## Ammonia is separated afterwards
sector = 'Basic chemicals'
df[sector] = 0
@ -204,9 +307,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)'
@ -219,19 +321,16 @@ 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']
+ s_fec['Residual fuel oil'] + s_fec['Other liquids'])
#### Chemicals: Steam processing
#> All the final energy consumption in the Stem processing is converted to biomass.
#> All the final energy consumption in the Steam processing is converted to methane, since we need >1000 C temperatures here.
#
#> The current efficiency of biomass is assumed in the conversion.
#> The current efficiency of methane is assumed in the conversion.
subsector = 'Chemicals: Steam processing'
@ -242,11 +341,11 @@ s_ued = excel_ued.iloc[22:33,year]
assert s_fec.index[0] == subsector
# efficiency of biomass
eff_bio = s_ued['Biomass']/s_fec['Biomass']
# efficiency of natural gas
eff_ch4 = s_ued['Natural gas (incl. biogas)']/s_fec['Natural gas (incl. biogas)']
# replace all fec by biomass
df.loc['biomass',sector] += s_ued[subsector]/eff_bio
# replace all fec by methane
df.loc['methane',sector] += s_ued[subsector]/eff_ch4
#### Chemicals: Furnaces
#> assume fully electrified
@ -298,10 +397,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
@ -311,8 +425,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
@ -405,7 +535,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.
@ -495,7 +625,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
@ -527,7 +657,7 @@ excel_emi = pd.read_excel('{}/JRC-IDEES-2015_Industry_{}.xlsx'.format(base_dir,c
#
#> Temperatures above 1400C are required for procesing limestone and sand into clinker.
#
#> Everything (except current electricity and heat consumption) is transformed into biomass
#> Everything (except current electricity and heat consumption and existing biomass) is transformed into methane for high T.
sector = 'Cement'
@ -546,10 +676,11 @@ df.loc['elec',sector] += s_fec[['Lighting','Air compressors','Motor drives','Fan
# Low enthalpy heat
df.loc['heat',sector] += s_fec['Low enthalpy heat']
# Efficiency changes due to biomass
eff_bio=s_ued['Biomass']/s_fec['Biomass']
# pre-processing: keep existing elec and biomass, rest to methane
df.loc['elec', sector] += s_fec['Cement: Grinding, milling of raw material']
df.loc['biomass', sector] += s_fec['Biomass']
df.loc['methane', sector] += s_fec['Cement: Pre-heating and pre-calcination'] - s_fec['Biomass']
df.loc['biomass', sector] += s_ued[['Cement: Grinding, milling of raw material', 'Cement: Pre-heating and pre-calcination']].sum()/eff_bio
#### Cement: Clinker production (kilns)
@ -562,10 +693,10 @@ s_ued = excel_ued.iloc[34:43,year]
assert s_fec.index[0] == subsector
# Efficiency changes due to biomass
eff_bio=s_ued['Biomass']/s_fec['Biomass']
df.loc['biomass', sector] += s_fec['Biomass']
df.loc['methane', sector] += s_fec['Cement: Clinker production (kilns)'] - s_fec['Biomass']
df.loc['elec', sector] += s_fec['Cement: Grinding, packaging']
df.loc['biomass', sector] += s_ued[['Cement: Clinker production (kilns)', 'Cement: Grinding, packaging']].sum()/eff_bio
#### Process-emission came from the calcination of limestone to chemically reactive calcium oxide (lime).
#> Calcium carbonate -> lime + CO2
@ -635,7 +766,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
@ -707,7 +838,7 @@ excel_out = pd.read_excel('{}/JRC-IDEES-2015_Industry_{}.xlsx'.format(base_dir,c
#
#> Includes three subcategories: (a) Wood preparation, grinding; (b) Pulping; (c) Cleaning.
#
#> (b) Pulping is electrified. The efficiency is calculated from the pulping process that is already electric.
#> (b) Pulping is either biomass or electric; left like this (dominated by biomass).
#
#> (a) Wood preparation, grinding and (c) Cleaning represent only 10% their current energy consumption is assumed to be electrified without any change in efficiency
@ -729,14 +860,11 @@ df.loc['elec', sector] += s_fec[['Lighting','Air compressors','Motor drives','Fa
df.loc['heat', sector] += s_fec['Low enthalpy heat']
# Industry-specific
df.loc['elec', sector] += s_fec[['Pulp: Wood preparation, grinding', 'Pulp: Cleaning']].sum()
df.loc['elec', sector] += s_fec[['Pulp: Wood preparation, grinding', 'Pulp: Cleaning', 'Pulp: Pulping electric']].sum()
# Efficiency changes due to electrification
eff_elec=s_ued['Pulp: Pulping electric']/s_fec['Pulp: Pulping electric']
df.loc['elec', sector] += s_ued['Pulp: Pulping thermal']/eff_elec
# add electricity from process that is already electrified
df.loc['elec', sector] += s_fec['Pulp: Pulping electric']
# Efficiency changes due to biomass
eff_bio=s_ued['Biomass']/s_fec['Biomass']
df.loc['biomass', sector] += s_ued['Pulp: Pulping thermal']/eff_bio
s_out = excel_out.iloc[8:9,year]
@ -751,7 +879,7 @@ df.loc[sources,sector] = df.loc[sources,sector]*conv_factor/s_out['Pulp producti
#
#> Includes three subcategories: (a) Stock preparation; (b) Paper machine; (c) Product finishing.
#
#> (b) Paper machine and (c) Product finishing are electrified. The efficiency is calculated from the pulping process that is already electric.
#> (b) Paper machine and (c) Product finishing are left electric and thermal is moved to biomass. The efficiency is calculated from the pulping process that is already biomass.
#
#> (a) Stock preparation represents only 7% and its current energy consumption is assumed to be electrified without any change in efficiency.
@ -775,16 +903,35 @@ df.loc['heat', sector] += s_fec['Low enthalpy heat']
# Industry-specific
df.loc['elec', sector] += s_fec['Paper: Stock preparation']
# Efficiency changes due to electrification
eff_elec=s_ued['Paper: Paper machine - Electricity']/s_fec['Paper: Paper machine - Electricity']
df.loc['elec', sector] += s_ued['Paper: Paper machine - Steam use']/eff_elec
eff_elec=s_ued['Paper: Product finishing - Electricity']/s_fec['Paper: Product finishing - Electricity']
df.loc['elec', sector] += s_ued['Paper: Product finishing - Steam use']/eff_elec
# add electricity from process that is already electrified
df.loc['elec', sector] += s_fec['Paper: Paper machine - Electricity']
# add electricity from process that is already electrified
df.loc['elec', sector] += s_fec['Paper: Product finishing - Electricity']
s_fec = excel_fec.iloc[53:64,year]
s_ued = excel_ued.iloc[53:64,year]
assert s_fec.index[0] == 'Paper: Paper machine - Steam use'
# Efficiency changes due to biomass
eff_bio=s_ued['Biomass']/s_fec['Biomass']
df.loc['biomass', sector] += s_ued['Paper: Paper machine - Steam use']/eff_bio
s_fec = excel_fec.iloc[66:77,year]
s_ued = excel_ued.iloc[66:77,year]
assert s_fec.index[0] == 'Paper: Product finishing - Steam use'
# Efficiency changes due to biomass
eff_bio=s_ued['Biomass']/s_fec['Biomass']
df.loc['biomass', sector] += s_ued['Paper: Product finishing - Steam use']/eff_bio
# read the corresponding lines
s_out = excel_out.iloc[9:10,year]
@ -878,8 +1025,8 @@ df.loc['elec', sector] += s_ued['Food: Drying']/eff_elec
eff_elec=s_ued['Food: Electric cooling']/s_fec['Food: Electric cooling']
df.loc['elec', sector] += s_ued['Food: Process cooling and refrigeration']/eff_elec
# Steam processing is electrified without change in efficiency
df.loc['elec', sector] += s_fec['Food: Steam processing']
# Steam processing goes all to biomass without change in efficiency
df.loc['biomass', sector] += s_fec['Food: Steam processing']
# add electricity from process that is already electrified
df.loc['elec', sector] += s_fec['Food: Electric machinery']
@ -1052,9 +1199,6 @@ sources=['elec','biomass', 'methane', 'hydrogen', 'heat','naphtha']
df.loc[sources,sector] = df.loc[sources,sector]*conv_factor/s_out['Aluminium - secondary production'] # unit MWh/t material
# 1 ktoe = 11630 MWh
# primary route is divided into 50% remains as today and 50% is transformed into secondary route
df.loc[sources,'Aluminium - primary production'] = (1-snakemake.config["industry"]["Al_to_scrap"])*df.loc[sources,'Aluminium - primary production'] + snakemake.config["industry"]["Al_to_scrap"]*df.loc[sources,'Aluminium - secondary production']
df.loc['process emission','Aluminium - primary production'] = (1-snakemake.config["industry"]["Al_to_scrap"])*df.loc['process emission','Aluminium - primary production']
### Other non-ferrous metals
@ -1372,4 +1516,5 @@ sources=['elec','biomass', 'methane', 'hydrogen', 'heat','naphtha']
df.loc[sources,sector] = df.loc[sources,sector]*conv_factor/s_out['Physical output (index)'] # unit MWh/t material
df.to_csv('resources/industry_sector_ratios.csv', sep=';')
df.index.name = "MWh/tMaterial"
df.to_csv('resources/industry_sector_ratios.csv')

View File

@ -565,8 +565,8 @@ if __name__ == "__main__":
from vresutils import Dict
import yaml
snakemake = Dict()
with open('config.yaml') as f:
snakemake.config = yaml.load(f)
with open('config.yaml', encoding='utf8') as f:
snakemake.config = yaml.safe_load(f)
#overwrite some options
snakemake.config["run"] = "test"

View File

@ -245,8 +245,8 @@ if __name__ == "__main__":
from vresutils import Dict
import yaml
snakemake = Dict()
with open('config.yaml') as f:
snakemake.config = yaml.load(f)
with open('config.yaml', encoding='utf8') as f:
snakemake.config = yaml.safe_load(f)
snakemake.input = Dict()
snakemake.output = Dict()

View File

@ -73,6 +73,7 @@ def update_wind_solar_costs(n,costs):
#map simplified network -> clustered network
busmap = pd.read_hdf(snakemake.input.clustermaps,
key="/busmap")
#map initial network -> clustered network
clustermaps = busmap_s.map(busmap)
#code adapted from pypsa-eur/scripts/add_electricity.py
@ -90,7 +91,16 @@ def update_wind_solar_costs(n,costs):
#convert to aggregated clusters with weighting
weight = ds['weight'].to_pandas()
connection_cost = (connection_cost*weight).groupby(clustermaps).sum()/weight.groupby(clustermaps).sum()
#e.g. clusters == 37m means that VRE generators are left
#at clustering of simplified network, but that they are
#connected to 37-node network
if snakemake.wildcards.clusters[-1:] == "m":
genmap = busmap_s
else:
genmap = clustermaps
connection_cost = (connection_cost*weight).groupby(genmap).sum()/weight.groupby(genmap).sum()
capital_cost = (costs.at['offwind', 'fixed'] +
costs.at[tech + '-station', 'fixed'] +
@ -655,6 +665,8 @@ def insert_electricity_distribution_grid(network):
lifetime=costs.at['electricity distribution grid','lifetime'],
capital_cost=costs.at['electricity distribution grid','fixed']*snakemake.config["sector"]['electricity_distribution_grid_cost_factor'])
#this catches regular electricity load and "industry new electricity"
loads = network.loads.index[network.loads.carrier.str.contains("electricity")]
network.loads.loc[loads,"bus"] += " low voltage"
@ -1722,8 +1734,8 @@ if __name__ == "__main__":
output=['pypsa-eur-sec/results/test/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_{planning_horizons}.nc']
)
import yaml
with open('config.yaml') as f:
snakemake.config = yaml.load(f)
with open('config.yaml', encoding='utf8') as f:
snakemake.config = yaml.safe_load(f)
logging.basicConfig(level=snakemake.config['logging_level'])

View File

@ -378,8 +378,8 @@ if __name__ == "__main__":
python="logs/{network}_s{simpl}_{clusters}_lv{lv}_{sector_opts}_{co2_budget_name}_{planning_horizons}_python-test.log")
)
import yaml
with open('config.yaml') as f:
snakemake.config = yaml.load(f)
with open('config.yaml', encoding='utf8') as f:
snakemake.config = yaml.safe_load(f)
tmpdir = snakemake.config['solving'].get('tmpdir')
if tmpdir is not None:
patch_pyomo_tmpdir(tmpdir)