@@ -961,67 +961,59 @@ def unify_diw(costs):
961961
962962 return costs
963963
964- def biomethanation_dea (df ):
965- """This function deos:
966- - iport dea data for biomethanation from DEA (4H2 + CO2 -> CH4 + 2H2O)
967- - recalculated the cost and inputs per MW of H2 added (bus 0 is H2)"""
964+ def biomethanation_dea (df ):
965+ """This function does:
966+ - import DEA data for biomethanation (4H2 + CO2 -> CH4 + 2H2O)
967+ - recalculates cost and inputs per MW of H2 added (bus 0 is H2)
968+ """
968969
970+ CO2_density = 1.98 / 1000 # kg/Nm3
971+ CH4_vol = 0.58 # biogas vol%, from DEA source for biomethanation
972+ CO2_vol = 0.42 # biogas vol%, from DEA source for biomethanation
973+ CH4_lhv = 35.8 / 3600 # MWh/Nm3
974+ CO2_biogas = CO2_vol / CH4_vol / CH4_lhv * CO2_density # t_CO2/MWh_biogas
969975
970- CO2_density = 1.98 # kg/Nm3
971- CH4_vol = 0.58 # biogas vol%, from DEA source for biomethanation
972- CO2_vol = 0.42 # biogas vol%, from DEA source for biomethanation
973- CH4_lhv = 35.8 / 3600 # MWh/m3
976+ # Find index labels directly
977+ idx = df .index [df .index .str .contains ("Total Input" )]
978+ idx2 = df .index [df .index .str .contains ("Hydrogen Consumption" )]
979+ idx3 = df .index [df .index .str .contains ("CO2 Consumption" )]
980+ idx4 = df .index [df .index .str .contains ("Methane Output" )]
981+ idx5 = df .index [df .index .str .contains ("EUR" )]
974982
975- idx = df .index .str .contains ("Total Input" )
976- idx2 = df .index .str .contains ("Hydrogen Consumption" )
977- idx3 = df .index .str .contains ('CO2 Consumption' )
978- idx4 = df .index .str .contains ("Methane Output" )
983+ # H2/CH4 ratio (MW/MW)
984+ CH4_H2_ratio = df .loc [idx4 ].astype (float ) / df .loc [idx2 [0 ]].astype (float )
979985
980- # calculate H2/CH4 ratio (MW/MW)
981- CH4_H2_ratio = df .loc [idx4 ].astype (float ) / df .loc [idx2 ].values .astype (
982- float )
983-
984- # adjust cost basis from €/MWh CH4 (check pdf) to €/MW H2
985- # Note costs are give for the CH4 produced only (excluding the input CH4 in biogas)
986- idx5 = df .index .str .contains ("EUR" )
986+ # Adjust costs from €/MWh CH4 to €/MW_H2
987987 df .loc [idx5 ] = df .loc [idx5 ].astype (float ).mul (CH4_H2_ratio .values .flatten (), axis = 1 )
988988 df .index = [
989- idx .replace ("MW" , "MW_H2" ).replace ("MWh" , "MWh_H2" ) if i else idx
990- for idx , i in zip ( df .index , idx5 )
989+ i .replace ("MW" , "MW_H2" ).replace ("MWh" , "MWh_H2" ) if i in idx5 else i
990+ for i in df .index
991991 ]
992992
993- # normalize all inputs & outputs to MW of hydrogen
994- df .loc [idx ] = df .loc [idx ].astype (float ) / df .loc [idx2 ].values .astype (
995- float )
996- df .index = df .index .str .replace (" Total Input" , "_H2" )
993+ # Normalize all inputs & outputs to MW of hydrogen
994+ df .loc [idx ] = df .loc [idx ].astype (float ) / df .loc [idx2 [0 ]].astype (float )
995+
996+ # Convert CO2 input from Nm3 to tons
997+ df .loc [idx3 [0 ]] = df .loc [idx3 [0 ]].astype (float ) * CO2_density # tCO2 / h / MW_H2
997998
998- # Calculate biogas input in MWh/MWh_H2(consumption)
999- CH4_vol = 0.58
1000- CO2_vol = 0.42
1001- CH4_lhv = 35.8 / 3600 # ≈ 0.009944 MWh/Nm³
1002- print (df )
999+ # Biogas input in MWh/MWh_H2
10031000 df .loc ['Biogas Consumption, [MWh_th/MWh_H2]' ] = (
1004- df .loc [idx3 ].astype (float ).iloc [0 ] * CH4_vol / CO2_vol * CH4_lhv
1005- ) # in MW_biogas/ MW_H2
1006- print (df )
1001+ df .loc [idx3 [0 ]].astype (float ) / CO2_biogas
1002+ )
10071003
1008- # convert CO2 from Nm3 to tons
1009- idx3 = df .index .str .contains ('CO2 Consumption' )
1010- df .loc [idx3 ] = df .loc [idx3 ].astype (float ) * CO2_density / 1000 # tCO2 / h / MW_H2
1011- print (df )
1004+ # Add biogas back to methane output (correct total output)
1005+ df .loc [idx4 ] = df .loc [idx4 ].astype (float ) + df .loc ['Biogas Consumption, [MWh_th/MWh_H2]' ]
10121006
1013- # correct methane output to the total biomethane (biogas + production)
1014- idx4 = df .index .str .contains ("Methane Output" )
1015- df .loc [idx4 ] = df .loc [idx4 ] + df .loc ['Biogas Consumption, [MWh_th/MWh_H2]' ]
1016- print (df )
1007+ # change unit to H2 basis
1008+ df .index = df .index .str .replace (" Total Input" , "_H2" )
10171009
1018- # rename units
1010+ # Rename indices and update units
10191011 replacements = {
10201012 "Hydrogen Consumption" : "Hydrogen Input" ,
10211013 "CO2 Consumption" : "CO2 Input" ,
10221014 "Electricity Consumption" : "El-Input" ,
1023- "Methane Output" : "Methane Output" ,
1024- "Heat Output" : "H-Output" ,
1015+ "Methane Output" : "Methane Output" ,
1016+ "Heat Output" : "H-Output" ,
10251017 }
10261018
10271019 old_units = {
@@ -1054,34 +1046,45 @@ def biogas_plus_hydrogen_dea(df):
10541046 # convert efficiencies from MW/MWTotal input to bigas input basis
10551047 # adjust names of efficiencies paramaters for further processing
10561048
1057- idx = df .index .str .contains ("Total Input" )
1058- idx2 = df .index .str .contains ("Hydrogen Consumption" )
1059- idx4 = df .index .str .contains ("SNG Output" )
1060- idx5 = df .index .str .contains ("EUR" )
1049+ CO2_density = 1.98 / 1000 # kg/Nm3
1050+ CH4_vol = 0.65 # biogas vol%, from DEA source for SNG from Methanation of Biogas
1051+ CO2_vol = 0.35 # biogas vol%, from DEA source for SNG from Methanation of Biogas
1052+ CH4_lhv = 35.8 / 3600 # MWh/Nm3
1053+ CO2_biogas = CO2_vol / CH4_vol / CH4_lhv * CO2_density # t_CO2/MWh_biogas
1054+
1055+ # use actual index names instead of boolean masks
1056+ idx = df .index [df .index .str .contains ("Total Input" )]
1057+ idx2 = df .index [df .index .str .contains ("Hydrogen Consumption" )]
1058+ idx3 = df .index [df .index .str .contains ("Biogas Consumption" )]
1059+ idx4 = df .index [df .index .str .contains ("SNG Output" )]
1060+ idx5 = df .index [df .index .str .contains ("EUR" )]
10611061
1062- # calculate H2/CH4 ratio (MW/MW)
1063- SNG_H2_ratio = df .loc [idx4 ].astype (float ) / df .loc [idx2 ].values .astype (
1064- float )
1062+ # calculate H2/CH4 ratio (MW/MW) using the first match (assuming one match)
1063+ SNG_H2_ratio = df .loc [idx4 ].astype (float ) / df .loc [idx2 [0 ]].astype (float )
10651064
1066- # adjust cost basis from €/MWh CH4 (check pdf) to €/MW H2
1067- # note cost are given for the total SNG (biogas + production)
1065+ # adjust cost basis from €/MWh CH4 to €/MW H2
10681066 df .loc [idx5 ] = df .loc [idx5 ].astype (float ).mul (SNG_H2_ratio .values .flatten (), axis = 1 )
10691067 df .index = [
1070- idx .replace (" SNG" , "_H2" ) if i else idx
1071- for idx , i in zip ( df .index , idx5 )
1068+ i .replace (" SNG" , "_H2" ) if i in idx5 else i
1069+ for i in df .index
10721070 ]
10731071
10741072 # normalize all inputs & outputs to MW of hydrogen
1075- df .loc [idx ] = df .loc [idx ].astype (float ) / df .loc [idx2 ].values .astype (
1076- float )
1073+ df .loc [idx ] = df .loc [idx ].astype (float ) / df .loc [idx2 [0 ]].astype (float )
1074+
1075+ # Calculate CO2 input in t_CO2/MWh_H2
1076+ df .loc ['CO2 Input, [t_CO2/MWh_H2]' ] = df .loc [idx3 [0 ]].astype (float ) * CO2_biogas
1077+
1078+ # change unit to H2 basis
10771079 df .index = df .index .str .replace (" Total Input" , "_H2" )
10781080
1081+ # Renaming for standardization
10791082 replacements = {
10801083 "Hydrogen Consumption" : "Hydrogen Consumption" ,
10811084 "Biogas Consumption" : "Biogas Consumption" ,
10821085 "Electricity Consumption" : "El-Input" ,
1083- "SNG Output" : "Methane Output" ,
1084- "District Heating Output" : "H-Output" ,
1086+ "SNG Output" : "Methane Output" ,
1087+ "District Heating Output" : "H-Output" ,
10851088 }
10861089
10871090 old_units = {
@@ -1110,6 +1113,7 @@ def biogas_plus_hydrogen_dea(df):
11101113
11111114 return df
11121115
1116+
11131117def biochar_pyrolysis_dea (df ):
11141118 """This function does:
11151119 1) defined the properties of solid biomass in pypsa-eur: moisture, LHV dry and LHV moist
@@ -1775,12 +1779,12 @@ def order_data(tech_data):
17751779 clean_df [tech ] = pd .concat ([clean_df [tech ], electricity_input ])
17761780
17771781 elif tech == "biomethanation" :
1778- efficiency_biomethanation = efficiency [efficiency .index .str .contains ("Hydrogen Input" )].copy ()
1779- efficiency_biomethanation ["parameter" ] = "Hydrogen Input"
1780- clean_df [tech ] = pd .concat ([clean_df [tech ], efficiency_biomethanation ])
1781- efficiency_biomethanation = efficiency [efficiency .index .str .contains ("CO2 Input" )].copy ()
1782- efficiency_biomethanation ["parameter" ] = "CO2 Input"
1783- clean_df [tech ] = pd .concat ([clean_df [tech ], efficiency_biomethanation ])
1782+ h2_input = efficiency [efficiency .index .str .contains ("Hydrogen Input" )].copy ()
1783+ h2_input ["parameter" ] = "Hydrogen Input"
1784+ clean_df [tech ] = pd .concat ([clean_df [tech ], h2_input ])
1785+ co2_input = efficiency [efficiency .index .str .contains ("CO2 Input" )].copy ()
1786+ co2_input ["parameter" ] = "CO2 Input"
1787+ clean_df [tech ] = pd .concat ([clean_df [tech ], co2_input ])
17841788 efficiency_heat_out = efficiency [efficiency .index .str .contains ("H-Output" )].copy ()
17851789 efficiency_heat_out ["parameter" ] = "heat output"
17861790 clean_df [tech ] = pd .concat ([clean_df [tech ], efficiency_heat_out ])
@@ -1805,6 +1809,11 @@ def order_data(tech_data):
18051809 biogas_input ["parameter" ] = "Biogas Input"
18061810 clean_df [tech ] = pd .concat ([clean_df [tech ], biogas_input ])
18071811
1812+ co2_input = efficiency [efficiency .index .str .contains ("CO2 Input" )].copy ()
1813+ if not biogas_input .empty :
1814+ co2_input ["parameter" ] = "CO2 Input"
1815+ clean_df [tech ] = pd .concat ([clean_df [tech ], co2_input ])
1816+
18081817 sng_output = efficiency [efficiency .index .str .contains ("Methane Output" )].copy ()
18091818 if not sng_output .empty :
18101819 sng_output ["parameter" ] = "Methane Output"
@@ -3174,6 +3183,7 @@ def prepare_inflation_rate(fn):
31743183 to_add ["currency_year" ] = 2015
31753184 costs_tot = pd .concat ([costs_tot , to_add ], sort = False )
31763185
3186+
31773187 # unify the cost from DIW2010
31783188 costs_tot = unify_diw (costs_tot )
31793189 costs_tot .drop ("fixed" , level = 1 , inplace = True )
0 commit comments