Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DEA transport data #128

Merged
merged 6 commits into from
May 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Snakefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ rule compile_cost_assumptions:
fraunhofer_vehicles_costs = "inputs/Fraunhofer_ISE_vehicles_costs.csv",
EWG_costs = "inputs/EWG_costs.csv",
dea_transport = "inputs/energy_transport_data_sheet_dec_2017.xlsx",
dea_vehicles = "inputs/data_sheets_for_commercial_freight_and_passenger_transport_0.xlsx",
dea_renewable_fuels = "inputs/data_sheets_for_renewable_fuels.xlsx",
dea_storage = "inputs/technology_data_catalogue_for_energy_storage.xlsx",
dea_generation = "inputs/technology_data_for_el_and_dh.xlsx",
dea_heating = "inputs/technologydatafor_heating_installations_marts_2018.xlsx",
dea_industrial = "inputs/technology_data_for_industrial_process_heat.xlsx",
dea_ship = "inputs/data_sheets_for_maritime_commercial_freight_and_passenger_transport.xlsx",
dea_ccts = "inputs/technology_data_for_carbon_capture_transport_storage.xlsx",
pnnl_energy_storage = "inputs/pnnl-energy-storage-database.xlsx",
manual_input = "inputs/manual_input.csv"
Expand Down
1 change: 1 addition & 0 deletions docs/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Release Notes
.. Upcoming Release
.. ================

* add heavy duty and shipping technology assumptions from DEA

Technology-Data 0.8.1 (28 February 2024)
========================================
Expand Down
Binary file not shown.
Binary file not shown.
117 changes: 117 additions & 0 deletions outputs/costs_2020.csv

Large diffs are not rendered by default.

117 changes: 117 additions & 0 deletions outputs/costs_2025.csv

Large diffs are not rendered by default.

117 changes: 117 additions & 0 deletions outputs/costs_2030.csv

Large diffs are not rendered by default.

117 changes: 117 additions & 0 deletions outputs/costs_2035.csv

Large diffs are not rendered by default.

117 changes: 117 additions & 0 deletions outputs/costs_2040.csv

Large diffs are not rendered by default.

117 changes: 117 additions & 0 deletions outputs/costs_2045.csv

Large diffs are not rendered by default.

117 changes: 117 additions & 0 deletions outputs/costs_2050.csv

Large diffs are not rendered by default.

205 changes: 202 additions & 3 deletions scripts/compile_cost_assumptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@
]


# %% -------- FUNCTIONS ---------------------------------------------------
# -------- FUNCTIONS ---------------------------------------------------

def get_excel_sheets(excel_files):
""""
Expand Down Expand Up @@ -273,6 +273,197 @@ def get_sheet_location(tech, sheet_names, data_in):
return None

#

def get_dea_maritime_data(fn, data):
"""
Get technology data for shipping from DEA.
"""
sheet_names = ['Container feeder, diesel',
'Container feeder, methanol',
'Container feeder, ammonia',
'Container, diesel',
'Container, methanol',
'Container, ammonia',
'Tank&bulk, diesel',
'Tank&bulk, methanol',
'Tankbulk, ammonia',
]
excel = pd.read_excel(fn,
sheet_name=sheet_names,
index_col=[0,1],
usecols="A:F",
na_values="N/A")

wished_index = ["Typical ship lifetime (years)",
"Upfront ship cost (mill. €)",
"Fixed O&M (€/year)",
"Variable O&M (€/nm)",
]


for sheet in excel.keys():
df = excel[sheet]
df = df.iloc[1:,:].set_axis(df.iloc[0], axis=1)

assert "Typical operational speed" in df.index.get_level_values(1)[22]
# in unit GJ/nm
efficiency = df.iloc[22]

df = df[df.index.get_level_values(1).isin(wished_index)]
df = df.droplevel(level=0)
df.loc["efficiency (GJ/nm)"] = efficiency
df = df.reindex(columns=pd.Index(years).union(df.columns))
df = df.astype(float)
df = df.interpolate(axis=1, limit_direction="both")
df = df[years]

# dropna
df = df.dropna(how="all", axis=0)
# add column for units
df["unit"] = (df.rename(index=lambda x:
x[x.rfind("(")+1: x.rfind(")")]).index.values)
df["unit"] = df.unit.str.replace("€", "EUR")
# remove units from index
df.index = df.index.str.replace(r" \(.*\)","", regex=True)

# convert million Euro -> Euro
df_i = df[df.unit == 'mill. EUR'].index
df.loc[df_i, years] *= 1e6
df.loc[df_i, "unit"] = "EUR"

# convert FOM in % of investment/year
if 'Fixed O&M' in df.index:
df.loc['Fixed O&M', years] /= (df.loc['Upfront ship cost', years]
* 100)
df.loc['Fixed O&M', "unit"] = "%/year"

# convert nm in km
# 1 Nautical Mile (nm) = 1.852 Kilometers (km)
df_i = df[df.unit.str.contains('/nm')].index
df.loc[df_i, years] /= 1.852
df.loc[df_i, "unit"] = df.loc[df_i, "unit"].str.replace("/nm", "/km")

# 1 GJ = 1/3600 * 1e9 Wh = 1/3600 * 1e3 MWh
df_i = df[df.unit.str.contains('GJ')].index
df.loc[df_i, years] *= 1e3/3600
df.loc[df_i, "unit"] = df.loc[df_i, "unit"].str.replace("GJ", "MWh")

# add source + cost year
df["source"] = f"Danish Energy Agency, {fn}"
# cost year is 2023 p.10
df["currency_year"] = 2023
# add sheet name
df['further description'] = sheet

# FOM, VOM,efficiency, lifetime, investment
rename = {'Typical ship lifetime': "lifetime",
'Upfront ship cost': "investment",
'Fixed O&M': "FOM",
'Variable O&M': "VOM",
}

df = df.rename(index=rename)

df = pd.concat([df], keys=[sheet], names=["technology", "parameter"])

data = pd.concat([data, df])

return data



def get_dea_vehicle_data(fn, data):
"""
Get heavy-duty vehicle data from DEA.
"""
sheet_names = ['Diesel L1', 'Diesel L2', 'Diesel L3',
'Diesel B1', 'Diesel B2',
'BEV L1', 'BEV L2', 'BEV L3',
'BEV B1', 'BEV B2',
'FCV L1', 'FCV L2', 'FCV L3',
'FCV B1', 'FCV B2']
excel = pd.read_excel(fn,
sheet_name=sheet_names,
index_col=0,
usecols="A:F",
na_values="no data")

wished_index = ["Typical vehicle lifetime (years)",
"Upfront vehicle cost (€)",
"Fixed maintenance cost (€/year)",
"Variable maintenance cost (€/km)",
"Motor size (kW)",
]

# clarify DEA names
types = {"L1": "Truck Solo max 26 tons",
"L2": "Truck Trailer max 56 tons",
"L3": "Truck Semi-Trailer max 50 tons",
"B1": "Bus city",
"B2": "Coach"}

for sheet in excel.keys():
df = excel[sheet]
tech = sheet.split()[0] + " " + types.get(sheet.split()[1], "")
df = df.iloc[1:,:].set_axis(df.iloc[0], axis=1)
# "Fuel energy - typical load (MJ/km)"
# represents efficiency for average weight vehicle carries during normal
# operation, currently assuming mean between urban, regional and long haul
assert df.index[27] == 'Fuel energy - typical load (MJ/km)'
efficiency = df.iloc[28:31].mean()
df = df[df.index.isin(wished_index)]
df.loc["efficiency (MJ/km)"] = efficiency
df = df.reindex(columns=pd.Index(years).union(df.columns))
df = df.interpolate(axis=1, limit_direction="both")
df = df[years]

# add column for units
df["unit"] = (df.rename(index=lambda x:
x[x.rfind("(")+1: x.rfind(")")]).index.values)
df["unit"] = df.unit.str.replace("€", "EUR")
# remove units from index
df.index = df.index.str.replace(r" \(.*\)","", regex=True)

# convert MJ in kWh -> 1 kWh = 3.6 MJ
df_i = df.index[df.unit=="MJ/km"]
df.loc[df_i, years] /= 3.6
df.loc[df_i, "unit"] = "kWh/km"

# convert FOM in % of investment/year
df.loc["Fixed maintenance cost", years] /= (df.loc["Upfront vehicle cost", years]
* 100)
df.loc["Fixed maintenance cost", "unit"] = "%/year"

# clarify costs are per vehicle
df.loc["Upfront vehicle cost", "unit"] += "/vehicle"

# add source + cost year
df["source"] = f"Danish Energy Agency, {fn}"
# cost year is 2022 p.12
df["currency_year"] = 2022
# add sheet name
df['further description'] = sheet

# FOM, VOM,efficiency, lifetime, investment
rename = {'Typical vehicle lifetime': "lifetime",
'Upfront vehicle cost': "investment",
'Fixed maintenance cost': "FOM",
'Variable maintenance cost': "VOM",
}

df = df.rename(index=rename)

to_keep = ['Motor size', 'lifetime', "FOM", "VOM", "efficiency",
"investment"]
df = df[df.index.isin(to_keep)]

df = pd.concat([df], keys=[tech], names=["technology", "parameter"])

data = pd.concat([data, df])

return data


def get_data_DEA(tech, data_in, expectation=None):
"""
interpolate cost for a given technology from DEA database sheet
Expand Down Expand Up @@ -2171,7 +2362,7 @@ def prepare_inflation_rate(fn):
years = snakemake.config['years']
inflation_rate = prepare_inflation_rate(snakemake.input.inflation_rate)


# p.77 Figure 51 share of vehicle-km driven by truck

# (1) DEA data
# (a)-------- get data from DEA excel sheets ----------------------------------
Expand Down Expand Up @@ -2208,7 +2399,7 @@ def prepare_inflation_rate(fn):
data = add_gas_storage(data)
# add carbon capture
data = add_carbon_capture(data, tech_data)

# adjust for inflation
for x in data.index.get_level_values("technology"):
if x in cost_year_2020:
Expand All @@ -2217,6 +2408,12 @@ def prepare_inflation_rate(fn):
data.at[x, "currency_year"] = 2019
else:
data.at[x, "currency_year"] = 2015

# add heavy duty assumptions, cost year is 2022
data = get_dea_vehicle_data(snakemake.input.dea_vehicles, data)

# add shipping data
data = get_dea_maritime_data(snakemake.input.dea_ship, data)

# %% (2) -- get data from other sources which need formatting -----------------
# (a) ---------- get old pypsa costs ---------------------------------------
Expand Down Expand Up @@ -2261,6 +2458,8 @@ def prepare_inflation_rate(fn):
data = add_SMR_data(data)
# add solar rooftop costs by taking the mean of commercial and residential
data = add_mean_solar_rooftop(data)

data.index.names = ["technology", "parameter"]
# %% (3) ------ add additional sources and save cost as csv ------------------
# [RTD-target-multiindex-df]
for year in years:
Expand Down
Loading