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

Small updates to get things working with Green Steel #210

Merged
merged 3 commits into from
Aug 31, 2023
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
141 changes: 79 additions & 62 deletions hopp/to_organize/H2_Analysis/LCA_single_scenario_ProFAST.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
# grid_price_scenario = 'retail-flat'
# electrolyzer_energy_kWh_per_kg = 55

def hydrogen_LCA_singlescenario_ProFAST(grid_connection_scenario,atb_year,site_name,policy_option,hydrogen_production_while_running,H2_Results,electrolyzer_energy_kWh_per_kg,solar_size_mw,storage_size_mw,hopp_dict):
def hydrogen_LCA_singlescenario_ProFAST(grid_connection_scenario,atb_year,site_name,policy_option,hydrogen_production_while_running,H2_Results,electrolyzer_energy_kWh_per_kg,solar_size_mw,storage_size_mw,hopp_dict,H2_PTC_duration):

dircambium = os.path.join(hopp_dict.main_dict["Configuration"]["parent_path"], "H2_Analysis", "Cambium_data", "StdScen21_MidCase95by2035_hourly_")
dircambium = os.path.join(hopp_dict.main_dict["Configuration"]["parent_path"], "H2_Analysis", "Cambium_data", "Cambium22_MidCase100by2035_hourly_")

#==============================================================================
# DATA
Expand All @@ -33,7 +33,7 @@ def hydrogen_LCA_singlescenario_ProFAST(grid_connection_scenario,atb_year,site_n
#------------------------------------------------------------------------------
# Renewable infrastructure embedded emission intensities
#------------------------------------------------------------------------------
system_life = 30
#system_life = plant_life
ely_stack_capex_EI = 0.019 # PEM electrolyzer CAPEX emissions (kg CO2e/kg H2)
wind_capex_EI = 10 # Electricity generation capacity from wind, nominal value taken (g CO2e/kWh)
if solar_size_mw != 0:
Expand Down Expand Up @@ -62,67 +62,84 @@ def hydrogen_LCA_singlescenario_ProFAST(grid_connection_scenario,atb_year,site_n
cambium_year =2035
elif atb_year == 2035:
cambium_year = 2040


energy_from_grid_df = pd.DataFrame(hopp_dict.main_dict["Models"]["grid"]["ouput_dict"]['energy_from_the_grid'],columns=['Energy from the grid (kWh)'])
energy_from_renewables_df = pd.DataFrame(hopp_dict.main_dict["Models"]["grid"]["ouput_dict"]['energy_from_renewables'],columns=['Energy from renewables (kWh)'])
# Read in Cambium data
cambiumdata_filepath = dircambium + site_name + '_'+str(cambium_year) + '.csv'
cambium_data = pd.read_csv(cambiumdata_filepath,index_col = None,header = 4,usecols = ['lrmer_co2_c','lrmer_ch4_c','lrmer_n2o_c','lrmer_co2_p','lrmer_ch4_p','lrmer_n2o_p','lrmer_co2e_c','lrmer_co2e_p','lrmer_co2e'])

cambium_data = cambium_data.reset_index().rename(columns = {'index':'Interval','lrmer_co2_c':'LRMER CO2 combustion (kg-CO2/MWh)','lrmer_ch4_c':'LRMER CH4 combustion (g-CH4/MWh)','lrmer_n2o_c':'LRMER N2O combustion (g-N2O/MWh)',\
'lrmer_co2_p':'LRMER CO2 production (kg-CO2/MWh)','lrmer_ch4_p':'LRMER CH4 production (g-CH4/MWh)','lrmer_n2o_p':'LRMER N2O production (g-N2O/MWh)','lrmer_co2e_c':'LRMER CO2 equiv. combustion (kg-CO2e/MWh)',\
'lrmer_co2e_p':'LRMER CO2 equiv. production (kg-CO2e/MWh)','lrmer_co2e':'LRMER CO2 equiv. total (kg-CO2e/MWh)'})

cambium_data['Interval']=cambium_data['Interval']+1
cambium_data = cambium_data.set_index('Interval')

# Read in rodeo data
# rodeo_data = hydrogen_hourly_results_RODeO[['Interval','Input Power (MW)','Non-Ren Import (MW)','Renewable Input (MW)','Curtailment (MW)','Product Sold (units of product)']]
# rodeo_data = rodeo_data.rename(columns = {'Input Power (MW)':'Electrolyzer Power (MW)','Non-Ren Import (MW)':'Grid Import (MW)','Renewable Input (MW)':'Renewable Input (MW)', 'Curtailment (MW)':'Curtailment (MW)','Product Sold (units of product)':'Hydrogen production (kg-H2)'})
# Combine RODeO and Cambium data into one dataframe
# combined_data = rodeo_data.merge(cambium_data, on = 'Interval',how = 'outer')

# Calculate hourly grid emissions factors of interest. If we want to use different GWPs, we can do that here. The Grid Import is an hourly data i.e., in MWh
cambium_data['Total grid emissions (kg-CO2e)'] = energy_from_grid_df['Energy from the grid (kWh)'] * cambium_data['LRMER CO2 equiv. total (kg-CO2e/MWh)'] / 1000
cambium_data['Scope 2 (combustion) grid emissions (kg-CO2e)'] = energy_from_grid_df['Energy from the grid (kWh)'] * cambium_data['LRMER CO2 equiv. combustion (kg-CO2e/MWh)'] / 1000
cambium_data['Scope 3 (production) grid emissions (kg-CO2e)'] = energy_from_grid_df['Energy from the grid (kWh)'] * cambium_data['LRMER CO2 equiv. production (kg-CO2e/MWh)'] / 1000

# Sum total emissions
scope2_grid_emissions_sum = cambium_data['Scope 2 (combustion) grid emissions (kg-CO2e)'].sum()*system_life*kg_to_MT_conv
scope3_grid_emissions_sum = cambium_data['Scope 3 (production) grid emissions (kg-CO2e)'].sum()*system_life*kg_to_MT_conv
#scope3_ren_sum = energy_from_renewables_df['Energy from renewables (kWh)'].sum()/1000 # MWh
scope3_ren_sum = energy_from_renewables_df['Energy from renewables (kWh)'].sum()*system_life/1000 # MWh
#h2prod_sum = np.sum(hydrogen_production_while_running)*system_life*kg_to_MT_conv
# h2prod_grid_frac = cambium_data['Grid Import (MW)'].sum() / cambium_data['Electrolyzer Power (MW)'].sum()
h2prod_sum=H2_Results['hydrogen_annual_output']*system_life*kg_to_MT_conv


if grid_connection_scenario == 'hybrid-grid' :
# Calculate grid-connected electrolysis emissions/ future cases should reflect targeted electrolyzer electricity usage
electrolysis_Scope3_EI = scope3_grid_emissions_sum/h2prod_sum # + (wind_capex_EI + solar_pv_capex_EI + battery_EI) * (scope3_ren_sum/h2prod_sum) * g_to_kg_conv + ely_stack_capex_EI # kg CO2e/kg H2
electrolysis_Scope2_EI = scope2_grid_emissions_sum/h2prod_sum
electrolysis_Scope1_EI = 0
electrolysis_total_EI = electrolysis_Scope1_EI + electrolysis_Scope2_EI + electrolysis_Scope3_EI
electrolysis_total_EI_policy_grid = electrolysis_total_EI # - (wind_capex_EI + solar_pv_capex_EI + battery_EI) * (scope3_ren_sum/h2prod_sum) * g_to_kg_conv
electrolysis_total_EI_policy_offgrid = 0 #(wind_capex_EI + solar_pv_capex_EI + battery_EI) * (scope3_ren_sum/h2prod_sum) * g_to_kg_conv + ely_stack_capex_EI
elif grid_connection_scenario == 'grid-only':
# Calculate grid-connected electrolysis emissions
electrolysis_Scope3_EI = scope3_grid_emissions_sum/h2prod_sum # + ely_stack_capex_EI # kg CO2e/kg H2
electrolysis_Scope2_EI = scope2_grid_emissions_sum/h2prod_sum
electrolysis_Scope1_EI = 0
electrolysis_total_EI = electrolysis_Scope1_EI + electrolysis_Scope2_EI + electrolysis_Scope3_EI
electrolysis_total_EI_policy_grid = electrolysis_total_EI
electrolysis_total_EI_policy_offgrid = 0
elif grid_connection_scenario == 'off-grid':
# Calculate renewable only electrolysis emissions
electrolysis_Scope3_EI = 0#(wind_capex_EI + solar_pv_capex_EI + battery_EI) * (scope3_ren_sum/h2prod_sum) * g_to_kg_conv + ely_stack_capex_EI # kg CO2e/kg H2
electrolysis_Scope2_EI = 0
electrolysis_Scope1_EI = 0
electrolysis_total_EI = electrolysis_Scope1_EI + electrolysis_Scope2_EI + electrolysis_Scope3_EI
electrolysis_total_EI_policy_offgrid = electrolysis_total_EI
electrolysis_total_EI_policy_grid = 0

return(electrolysis_total_EI_policy_grid,electrolysis_total_EI_policy_offgrid)

emission_intensity_grid = []
emission_intensity_offgrid = []
years = list(range(cambium_year,2055,5))
for year in years:
cambiumdata_filepath = dircambium + site_name + '_'+str(year) + '.csv'
cambium_data = pd.read_csv(cambiumdata_filepath,index_col = None,header = 5,usecols = ['lrmer_co2_c','lrmer_ch4_c','lrmer_n2o_c','lrmer_co2_p','lrmer_ch4_p','lrmer_n2o_p','lrmer_co2e_c','lrmer_co2e_p','lrmer_co2e'])

cambium_data = cambium_data.reset_index().rename(columns = {'index':'Interval','lrmer_co2_c':'LRMER CO2 combustion (kg-CO2/MWh)','lrmer_ch4_c':'LRMER CH4 combustion (g-CH4/MWh)','lrmer_n2o_c':'LRMER N2O combustion (g-N2O/MWh)',\
'lrmer_co2_p':'LRMER CO2 production (kg-CO2/MWh)','lrmer_ch4_p':'LRMER CH4 production (g-CH4/MWh)','lrmer_n2o_p':'LRMER N2O production (g-N2O/MWh)','lrmer_co2e_c':'LRMER CO2 equiv. combustion (kg-CO2e/MWh)',\
'lrmer_co2e_p':'LRMER CO2 equiv. production (kg-CO2e/MWh)','lrmer_co2e':'LRMER CO2 equiv. total (kg-CO2e/MWh)'})

cambium_data['Interval']=cambium_data['Interval']+1
cambium_data = cambium_data.set_index('Interval')

# Calculate hourly grid emissions factors of interest. If we want to use different GWPs, we can do that here. The Grid Import is an hourly data i.e., in MWh
cambium_data['Total grid emissions (kg-CO2e)'] = energy_from_grid_df['Energy from the grid (kWh)'] * cambium_data['LRMER CO2 equiv. total (kg-CO2e/MWh)'] / 1000
cambium_data['Scope 2 (combustion) grid emissions (kg-CO2e)'] = energy_from_grid_df['Energy from the grid (kWh)'] * cambium_data['LRMER CO2 equiv. combustion (kg-CO2e/MWh)'] / 1000
cambium_data['Scope 3 (production) grid emissions (kg-CO2e)'] = energy_from_grid_df['Energy from the grid (kWh)'] * cambium_data['LRMER CO2 equiv. production (kg-CO2e/MWh)'] / 1000

# Sum total emissions
scope2_grid_emissions_sum = cambium_data['Scope 2 (combustion) grid emissions (kg-CO2e)'].sum()*kg_to_MT_conv
scope3_grid_emissions_sum = cambium_data['Scope 3 (production) grid emissions (kg-CO2e)'].sum()*kg_to_MT_conv
#scope3_ren_sum = energy_from_renewables_df['Energy from renewables (kWh)'].sum()/1000 # MWh
scope3_ren_sum = energy_from_renewables_df['Energy from renewables (kWh)'].sum()/1000 # MWh
#h2prod_sum = np.sum(hydrogen_production_while_running)*system_life*kg_to_MT_conv
# h2prod_grid_frac = cambium_data['Grid Import (MW)'].sum() / cambium_data['Electrolyzer Power (MW)'].sum()
h2prod_sum=H2_Results['hydrogen_annual_output']*kg_to_MT_conv


if grid_connection_scenario == 'hybrid-grid' :
# Calculate grid-connected electrolysis emissions/ future cases should reflect targeted electrolyzer electricity usage
electrolysis_Scope3_EI = scope3_grid_emissions_sum/h2prod_sum # + (wind_capex_EI + solar_pv_capex_EI + battery_EI) * (scope3_ren_sum/h2prod_sum) * g_to_kg_conv + ely_stack_capex_EI # kg CO2e/kg H2
electrolysis_Scope2_EI = scope2_grid_emissions_sum/h2prod_sum
electrolysis_Scope1_EI = 0
electrolysis_total_EI = electrolysis_Scope1_EI + electrolysis_Scope2_EI + electrolysis_Scope3_EI
electrolysis_total_EI_policy_grid = electrolysis_total_EI # - (wind_capex_EI + solar_pv_capex_EI + battery_EI) * (scope3_ren_sum/h2prod_sum) * g_to_kg_conv
electrolysis_total_EI_policy_offgrid = 0 #(wind_capex_EI + solar_pv_capex_EI + battery_EI) * (scope3_ren_sum/h2prod_sum) * g_to_kg_conv + ely_stack_capex_EI
elif grid_connection_scenario == 'grid-only':
# Calculate grid-connected electrolysis emissions
electrolysis_Scope3_EI = scope3_grid_emissions_sum/h2prod_sum # + ely_stack_capex_EI # kg CO2e/kg H2
electrolysis_Scope2_EI = scope2_grid_emissions_sum/h2prod_sum
electrolysis_Scope1_EI = 0
electrolysis_total_EI = electrolysis_Scope1_EI + electrolysis_Scope2_EI + electrolysis_Scope3_EI
electrolysis_total_EI_policy_grid = electrolysis_total_EI
electrolysis_total_EI_policy_offgrid = 0
elif grid_connection_scenario == 'off-grid':
# Calculate renewable only electrolysis emissions
electrolysis_Scope3_EI = 0#(wind_capex_EI + solar_pv_capex_EI + battery_EI) * (scope3_ren_sum/h2prod_sum) * g_to_kg_conv + ely_stack_capex_EI # kg CO2e/kg H2
electrolysis_Scope2_EI = 0
electrolysis_Scope1_EI = 0
electrolysis_total_EI = electrolysis_Scope1_EI + electrolysis_Scope2_EI + electrolysis_Scope3_EI
electrolysis_total_EI_policy_offgrid = electrolysis_total_EI
electrolysis_total_EI_policy_grid = 0

emission_intensity_grid.append(electrolysis_total_EI_policy_grid)
emission_intensity_offgrid.append(electrolysis_total_EI_policy_offgrid)

emission_intensities_df = pd.DataFrame({'Year':years,'Grid EI (kg CO2e/kg H2)':emission_intensity_grid,'Off-grid EI (kg CO2e/kg H2)':emission_intensity_offgrid})

# Interpolate results
endofincentives_year = cambium_year + H2_PTC_duration

grid_EI_interpolated = {}
offgrid_EI_interpolated = {}
for year in range(cambium_year,endofincentives_year):
if year <= max(emission_intensities_df['Year']):
grid_EI_interpolated[year]=np.interp(year,emission_intensities_df['Year'],emission_intensities_df['Grid EI (kg CO2e/kg H2)'])
offgrid_EI_interpolated[year]=np.interp(year,emission_intensities_df['Year'],emission_intensities_df['Off-grid EI (kg CO2e/kg H2)'])
else:
grid_EI_interpolated[year]=emission_intensities_df['Grid EI (kg CO2e/kg H2)'].values[-1:][0]
offgrid_EI_interpolated[year]=emission_intensities_df['Off-grid EI (kg CO2e/kg H2)'].values[-1:][0]

return(grid_EI_interpolated,offgrid_EI_interpolated)


9 changes: 8 additions & 1 deletion hopp/to_organize/H2_Analysis/hopp_for_h2.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,14 @@ def hopp_for_h2(site, scenario, technologies, wind_size_mw, solar_size_mw, stora
#wind_plant_size_check = hybrid_plant.wind.system_capacity_kw
# Save the outputs
annual_energies = hybrid_plant.annual_energies
wind_plus_solar_npv = hybrid_plant.net_present_values.wind + hybrid_plant.net_present_values.pv
if 'wind' in technologies and 'solar' in technologies:
wind_plus_solar_npv = hybrid_plant.net_present_values.wind + hybrid_plant.net_present_values.pv
elif 'wind' not in technologies and 'solar' in technologies:
wind_plus_solar_npv = hybrid_plant.net_present_values.pv
elif 'solar' not in technologies and 'wind' in technologies:
wind_plus_solar_npv = hybrid_plant.net_present_values.wind
else:
wind_plus_solar_npv = 0
npvs = hybrid_plant.net_present_values
lcoe = hybrid_plant.lcoe_real.hybrid
lcoe_nom = hybrid_plant.lcoe_nom.hybrid
Expand Down
2 changes: 1 addition & 1 deletion hopp/to_organize/distributed_pipe_cost_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def hydrogen_steel_pipeline_cost_analysis(parent_path,turbine_model,hydrogen_max
pipe_row_cost_USD.append(cpi_ratio*72634*(pipe_diam_in**1.07566)/(pipeline_length_miles**0.05284)*pipe_diam_in*pipeline_length_miles)


elif site_name == 'IA' or site_name == 'WY':
elif site_name == 'IA' or site_name == 'WY' or site_name == 'MN':
pipe_material_cost_USD.append(cpi_ratio*5813*(pipe_diam_in**0.31599)/(pipeline_length_miles**0.00376)*pipe_diam_in*pipeline_length_miles)

pipe_labor_cost_USD.append(cpi_ratio*10406*(pipe_diam_in**0.20953)/(pipeline_length_miles**0.08419)*pipe_diam_in*pipeline_length_miles)
Expand Down
Loading