242
242
]
243
243
244
244
245
- # %% -------- FUNCTIONS ---------------------------------------------------
245
+ # -------- FUNCTIONS ---------------------------------------------------
246
246
247
247
def get_excel_sheets (excel_files ):
248
248
""""
@@ -273,6 +273,197 @@ def get_sheet_location(tech, sheet_names, data_in):
273
273
return None
274
274
275
275
#
276
+
277
+ def get_dea_maritime_data (fn , data ):
278
+ """
279
+ Get technology data for shipping from DEA.
280
+ """
281
+ sheet_names = ['Container feeder, diesel' ,
282
+ 'Container feeder, methanol' ,
283
+ 'Container feeder, ammonia' ,
284
+ 'Container, diesel' ,
285
+ 'Container, methanol' ,
286
+ 'Container, ammonia' ,
287
+ 'Tank&bulk, diesel' ,
288
+ 'Tank&bulk, methanol' ,
289
+ 'Tankbulk, ammonia' ,
290
+ ]
291
+ excel = pd .read_excel (fn ,
292
+ sheet_name = sheet_names ,
293
+ index_col = [0 ,1 ],
294
+ usecols = "A:F" ,
295
+ na_values = "N/A" )
296
+
297
+ wished_index = ["Typical ship lifetime (years)" ,
298
+ "Upfront ship cost (mill. €)" ,
299
+ "Fixed O&M (€/year)" ,
300
+ "Variable O&M (€/nm)" ,
301
+ ]
302
+
303
+
304
+ for sheet in excel .keys ():
305
+ df = excel [sheet ]
306
+ df = df .iloc [1 :,:].set_axis (df .iloc [0 ], axis = 1 )
307
+
308
+ assert "Typical operational speed" in df .index .get_level_values (1 )[22 ]
309
+ # in unit GJ/nm
310
+ efficiency = df .iloc [22 ]
311
+
312
+ df = df [df .index .get_level_values (1 ).isin (wished_index )]
313
+ df = df .droplevel (level = 0 )
314
+ df .loc ["efficiency (GJ/nm)" ] = efficiency
315
+ df = df .reindex (columns = pd .Index (years ).union (df .columns ))
316
+ df = df .astype (float )
317
+ df = df .interpolate (axis = 1 , limit_direction = "both" )
318
+ df = df [years ]
319
+
320
+ # dropna
321
+ df = df .dropna (how = "all" , axis = 0 )
322
+ # add column for units
323
+ df ["unit" ] = (df .rename (index = lambda x :
324
+ x [x .rfind ("(" )+ 1 : x .rfind (")" )]).index .values )
325
+ df ["unit" ] = df .unit .str .replace ("€" , "EUR" )
326
+ # remove units from index
327
+ df .index = df .index .str .replace (r" \(.*\)" ,"" , regex = True )
328
+
329
+ # convert million Euro -> Euro
330
+ df_i = df [df .unit == 'mill. EUR' ].index
331
+ df .loc [df_i , years ] *= 1e6
332
+ df .loc [df_i , "unit" ] = "EUR"
333
+
334
+ # convert FOM in % of investment/year
335
+ if 'Fixed O&M' in df .index :
336
+ df .loc ['Fixed O&M' , years ] /= (df .loc ['Upfront ship cost' , years ]
337
+ * 100 )
338
+ df .loc ['Fixed O&M' , "unit" ] = "%/year"
339
+
340
+ # convert nm in km
341
+ # 1 Nautical Mile (nm) = 1.852 Kilometers (km)
342
+ df_i = df [df .unit .str .contains ('/nm' )].index
343
+ df .loc [df_i , years ] /= 1.852
344
+ df .loc [df_i , "unit" ] = df .loc [df_i , "unit" ].str .replace ("/nm" , "/km" )
345
+
346
+ # 1 GJ = 1/3600 * 1e9 Wh = 1/3600 * 1e3 MWh
347
+ df_i = df [df .unit .str .contains ('GJ' )].index
348
+ df .loc [df_i , years ] *= 1e3 / 3600
349
+ df .loc [df_i , "unit" ] = df .loc [df_i , "unit" ].str .replace ("GJ" , "MWh" )
350
+
351
+ # add source + cost year
352
+ df ["source" ] = f"Danish Energy Agency, { fn } "
353
+ # cost year is 2023 p.10
354
+ df ["currency_year" ] = 2023
355
+ # add sheet name
356
+ df ['further description' ] = sheet
357
+
358
+ # FOM, VOM,efficiency, lifetime, investment
359
+ rename = {'Typical ship lifetime' : "lifetime" ,
360
+ 'Upfront ship cost' : "investment" ,
361
+ 'Fixed O&M' : "FOM" ,
362
+ 'Variable O&M' : "VOM" ,
363
+ }
364
+
365
+ df = df .rename (index = rename )
366
+
367
+ df = pd .concat ([df ], keys = [sheet ], names = ["technology" , "parameter" ])
368
+
369
+ data = pd .concat ([data , df ])
370
+
371
+ return data
372
+
373
+
374
+
375
+ def get_dea_vehicle_data (fn , data ):
376
+ """
377
+ Get heavy-duty vehicle data from DEA.
378
+ """
379
+ sheet_names = ['Diesel L1' , 'Diesel L2' , 'Diesel L3' ,
380
+ 'Diesel B1' , 'Diesel B2' ,
381
+ 'BEV L1' , 'BEV L2' , 'BEV L3' ,
382
+ 'BEV B1' , 'BEV B2' ,
383
+ 'FCV L1' , 'FCV L2' , 'FCV L3' ,
384
+ 'FCV B1' , 'FCV B2' ]
385
+ excel = pd .read_excel (fn ,
386
+ sheet_name = sheet_names ,
387
+ index_col = 0 ,
388
+ usecols = "A:F" ,
389
+ na_values = "no data" )
390
+
391
+ wished_index = ["Typical vehicle lifetime (years)" ,
392
+ "Upfront vehicle cost (€)" ,
393
+ "Fixed maintenance cost (€/year)" ,
394
+ "Variable maintenance cost (€/km)" ,
395
+ "Motor size (kW)" ,
396
+ ]
397
+
398
+ # clarify DEA names
399
+ types = {"L1" : "Truck Solo max 26 tons" ,
400
+ "L2" : "Truck Trailer max 56 tons" ,
401
+ "L3" : "Truck Semi-Trailer max 50 tons" ,
402
+ "B1" : "Bus city" ,
403
+ "B2" : "Coach" }
404
+
405
+ for sheet in excel .keys ():
406
+ df = excel [sheet ]
407
+ tech = sheet .split ()[0 ] + " " + types .get (sheet .split ()[1 ], "" )
408
+ df = df .iloc [1 :,:].set_axis (df .iloc [0 ], axis = 1 )
409
+ # "Fuel energy - typical load (MJ/km)"
410
+ # represents efficiency for average weight vehicle carries during normal
411
+ # operation, currently assuming mean between urban, regional and long haul
412
+ assert df .index [27 ] == 'Fuel energy - typical load (MJ/km)'
413
+ efficiency = df .iloc [28 :31 ].mean ()
414
+ df = df [df .index .isin (wished_index )]
415
+ df .loc ["efficiency (MJ/km)" ] = efficiency
416
+ df = df .reindex (columns = pd .Index (years ).union (df .columns ))
417
+ df = df .interpolate (axis = 1 , limit_direction = "both" )
418
+ df = df [years ]
419
+
420
+ # add column for units
421
+ df ["unit" ] = (df .rename (index = lambda x :
422
+ x [x .rfind ("(" )+ 1 : x .rfind (")" )]).index .values )
423
+ df ["unit" ] = df .unit .str .replace ("€" , "EUR" )
424
+ # remove units from index
425
+ df .index = df .index .str .replace (r" \(.*\)" ,"" , regex = True )
426
+
427
+ # convert MJ in kWh -> 1 kWh = 3.6 MJ
428
+ df_i = df .index [df .unit == "MJ/km" ]
429
+ df .loc [df_i , years ] /= 3.6
430
+ df .loc [df_i , "unit" ] = "kWh/km"
431
+
432
+ # convert FOM in % of investment/year
433
+ df .loc ["Fixed maintenance cost" , years ] /= (df .loc ["Upfront vehicle cost" , years ]
434
+ * 100 )
435
+ df .loc ["Fixed maintenance cost" , "unit" ] = "%/year"
436
+
437
+ # clarify costs are per vehicle
438
+ df .loc ["Upfront vehicle cost" , "unit" ] += "/vehicle"
439
+
440
+ # add source + cost year
441
+ df ["source" ] = f"Danish Energy Agency, { fn } "
442
+ # cost year is 2022 p.12
443
+ df ["currency_year" ] = 2022
444
+ # add sheet name
445
+ df ['further description' ] = sheet
446
+
447
+ # FOM, VOM,efficiency, lifetime, investment
448
+ rename = {'Typical vehicle lifetime' : "lifetime" ,
449
+ 'Upfront vehicle cost' : "investment" ,
450
+ 'Fixed maintenance cost' : "FOM" ,
451
+ 'Variable maintenance cost' : "VOM" ,
452
+ }
453
+
454
+ df = df .rename (index = rename )
455
+
456
+ to_keep = ['Motor size' , 'lifetime' , "FOM" , "VOM" , "efficiency" ,
457
+ "investment" ]
458
+ df = df [df .index .isin (to_keep )]
459
+
460
+ df = pd .concat ([df ], keys = [tech ], names = ["technology" , "parameter" ])
461
+
462
+ data = pd .concat ([data , df ])
463
+
464
+ return data
465
+
466
+
276
467
def get_data_DEA (tech , data_in , expectation = None ):
277
468
"""
278
469
interpolate cost for a given technology from DEA database sheet
@@ -2177,7 +2368,7 @@ def prepare_inflation_rate(fn):
2177
2368
years = snakemake .config ['years' ]
2178
2369
inflation_rate = prepare_inflation_rate (snakemake .input .inflation_rate )
2179
2370
2180
-
2371
+ # p.77 Figure 51 share of vehicle-km driven by truck
2181
2372
2182
2373
# (1) DEA data
2183
2374
# (a)-------- get data from DEA excel sheets ----------------------------------
@@ -2214,7 +2405,7 @@ def prepare_inflation_rate(fn):
2214
2405
data = add_gas_storage (data )
2215
2406
# add carbon capture
2216
2407
data = add_carbon_capture (data , tech_data )
2217
-
2408
+
2218
2409
# adjust for inflation
2219
2410
for x in data .index .get_level_values ("technology" ):
2220
2411
if x in cost_year_2020 :
@@ -2223,6 +2414,12 @@ def prepare_inflation_rate(fn):
2223
2414
data .at [x , "currency_year" ] = 2019
2224
2415
else :
2225
2416
data .at [x , "currency_year" ] = 2015
2417
+
2418
+ # add heavy duty assumptions, cost year is 2022
2419
+ data = get_dea_vehicle_data (snakemake .input .dea_vehicles , data )
2420
+
2421
+ # add shipping data
2422
+ data = get_dea_maritime_data (snakemake .input .dea_ship , data )
2226
2423
2227
2424
# %% (2) -- get data from other sources which need formatting -----------------
2228
2425
# (a) ---------- get old pypsa costs ---------------------------------------
@@ -2267,6 +2464,8 @@ def prepare_inflation_rate(fn):
2267
2464
data = add_SMR_data (data )
2268
2465
# add solar rooftop costs by taking the mean of commercial and residential
2269
2466
data = add_mean_solar_rooftop (data )
2467
+
2468
+ data .index .names = ["technology" , "parameter" ]
2270
2469
# %% (3) ------ add additional sources and save cost as csv ------------------
2271
2470
# [RTD-target-multiindex-df]
2272
2471
for year in years :
0 commit comments