Skip to content

Commit

Permalink
update h2 storage sizing parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
kbrunik committed Jun 5, 2024
1 parent d8ff547 commit 2fb25f7
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def hydrogen_storage_capacity(H2_Results, electrolyzer_size_mw, hydrogen_demand_
Returns:
hydrogen_storage_capacity_kg (float): Hydrogen storage capacity in kilograms.
hydrogen_storage_duration_hr (float): Hydrogen storage duration in hours using HHV/LHV?
hydrogen_storage_duration_hr (float): Hydrogen storage duration in hours using HHV/LHV.
hydrogen_storage_soc (list): Timeseries of the hydrogen storage state of charge.
"""

Expand All @@ -22,7 +22,7 @@ def hydrogen_storage_capacity(H2_Results, electrolyzer_size_mw, hydrogen_demand_
hydrogen_demand_kgphr, np.mean(hydrogen_production_kgphr)
) # TODO: potentially add buffer No buffer needed since we are already oversizing

# TODO: SOC is currently allowed to go negative. Ideally would calculate as shortfall in future.
# TODO: SOC is just an absolute value and is not a percentage. Ideally would calculate as shortfall in future.
hydrogen_storage_soc = []
for j in range(len(hydrogen_production_kgphr)):
if j == 0:
Expand All @@ -36,6 +36,12 @@ def hydrogen_storage_capacity(H2_Results, electrolyzer_size_mw, hydrogen_demand_
- hydrogen_demand_kgphr
)

minimum_soc = np.min(hydrogen_storage_soc)

#adjust soc so it's not negative.
if minimum_soc < 0:
hydrogen_storage_soc = [x + np.abs(minimum_soc) for x in hydrogen_storage_soc]

hydrogen_storage_capacity_kg = np.max(hydrogen_storage_soc) - np.min(
hydrogen_storage_soc
)
Expand All @@ -44,26 +50,26 @@ def hydrogen_storage_capacity(H2_Results, electrolyzer_size_mw, hydrogen_demand_
hydrogen_storage_capacity_MWh_LHV = hydrogen_storage_capacity_kg * h2_LHV / 3600
hydrogen_storage_capacity_MWh_HHV = hydrogen_storage_capacity_kg * h2_HHV / 3600

# Get max injection/withdrawal rate
hydrogen_injection_withdrawal_rate = []
for j in range(len(hydrogen_production_kgphr)):
hydrogen_injection_withdrawal_rate.append(
hydrogen_production_kgphr[j] - hydrogen_demand_kgphr
)
max_h2_injection_rate_kgphr = max(hydrogen_injection_withdrawal_rate)

# Get storage compressor capacity. TODO: sync compressor calculation here with GreenHEART compressor model
compressor_total_capacity_kW = (
max_h2_injection_rate_kgphr / 3600 / 2.0158 * 8641.678424
)
# # Get max injection/withdrawal rate
# hydrogen_injection_withdrawal_rate = []
# for j in range(len(hydrogen_production_kgphr)):
# hydrogen_injection_withdrawal_rate.append(
# hydrogen_production_kgphr[j] - hydrogen_demand_kgphr
# )
# max_h2_injection_rate_kgphr = max(hydrogen_injection_withdrawal_rate)

compressor_max_capacity_kw = 16000
n_comps = math.ceil(compressor_total_capacity_kW / compressor_max_capacity_kw)
# # Get storage compressor capacity. TODO: sync compressor calculation here with GreenHEART compressor model
# compressor_total_capacity_kW = (
# max_h2_injection_rate_kgphr / 3600 / 2.0158 * 8641.678424
# )

small_positive = 1e-6
compressor_avg_capacity_kw = compressor_total_capacity_kW / (
n_comps + small_positive
)
# compressor_max_capacity_kw = 16000
# n_comps = math.ceil(compressor_total_capacity_kW / compressor_max_capacity_kw)

# small_positive = 1e-6
# compressor_avg_capacity_kw = compressor_total_capacity_kW / (
# n_comps + small_positive
# )

# Get average electrolyzer efficiency
electrolyzer_average_efficiency_HHV = H2_Results['Sim: Average Efficiency [%-HHV]']
Expand Down
8 changes: 4 additions & 4 deletions greenheart/tools/eco/hydrogen_mgmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,10 @@ def run_h2_storage(
greenheart_config["h2_capacity"] = 0.0
h2_storage_results["h2_storage_kg"] = 0.0
else:
if greenheart_config['h2_storage']['demand_capacity']:
hydrogen_storage_demand = electrolyzer_physics_results["H2_Results"][
"Life: Annual H2 production [kg/year]"
] # TODO: update demand based on end-use needs
if greenheart_config['h2_storage']['size_capacity_from_demand']['flag']:
hydrogen_storage_demand = np.mean(electrolyzer_physics_results["H2_Results"][
"Hydrogen Hourly Production [kg/hr]"
]) # TODO: update demand based on end-use needs
hydrogen_storage_capacity_kg, hydrogen_storage_duration_hr, hydrogen_storage_soc = hydrogen_storage_capacity(electrolyzer_physics_results['H2_Results'], greenheart_config['electrolyzer']['rating'], hydrogen_storage_demand)
greenheart_config["h2_capacity"] = hydrogen_storage_capacity_kg
h2_storage_results["h2_storage_kg"] = hydrogen_storage_capacity_kg
Expand Down
6 changes: 3 additions & 3 deletions tests/greenheart/input_files/plant/greenheart_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ h2_storage_compressor:
h2_transport_pipe:
outlet_pressure: 10 # bar - from example in code from Jamie #TODO check this value
h2_storage:
# capacity_kg: 18750 # kg
demand_capacity: False # If True, then storage is sized to provide steady-state storage
size_capacity_from_demand:
flag: False # If True, then storage is sized to provide steady-state storage
capacity_from_max_on_turbine_storage: False # if True, then days of storage is ignored and storage capacity is based on how much h2 storage fits on the turbines in the plant using Kottenstete 2003.
type: "none" # can be one of ["none", "pipe", "turbine", "pressure_vessel", "salt_cavern", "lined_rock_cavern"]
days: 3 # [days] how many days worth of production we should be able to store (this is ignored if `capacity_from_max_on_turbine_storage` or `demand_capacity` is set to True)
days: 3 # [days] how many days worth of production we should be able to store (this is ignored if `capacity_from_max_on_turbine_storage` or `size_capacity_from_demand` is set to True)

platform:
opex_rate: 0.0111 # % of capex to determine opex (see table 5 in https://www.acm.nl/sites/default/files/documents/study-on-estimation-method-for-additional-efficient-offshore-grid-opex.pdf)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ h2_storage_compressor:
h2_transport_pipe:
outlet_pressure: 10 # bar - from example in code from Jamie #TODO check this value
h2_storage:
# capacity_kg: 18750 # kg
size_capacity_from_demand:
flag: False # If True, then storage is sized to provide steady-state storage
capacity_from_max_on_turbine_storage: False # if True, then days of storage is ignored and storage capacity is based on how much h2 storage fits on the turbines in the plant using Kottenstete 2003.
type: "none" # can be one of ["none", "pipe", "turbine", "pressure_vessel", "salt_cavern", "lined_rock_cavern"]
days: 3 # [days] how many days worth of production we should be able to store (this is ignored if `capacity_from_max_on_turbine_storage` is set to True)
Expand Down
2 changes: 1 addition & 1 deletion tests/greenheart/test_greenheart_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ def test_simulation_wind_onshore_steel_ammonia_ss_h2storage(subtests):
output_level=7,
)

config.greenheart_config['h2_storage']['demand_capacity'] = True
config.greenheart_config['h2_storage']['size_capacity_from_demand']['flag'] = True
config.greenheart_config['h2_storage']['type'] = 'pipe'

# based on 2023 ATB moderate case for onshore wind
Expand Down

0 comments on commit 2fb25f7

Please sign in to comment.