Skip to content

Commit

Permalink
fixed h2 storage sizing bug
Browse files Browse the repository at this point in the history
  • Loading branch information
kbrunik committed Jun 6, 2024
1 parent 093de7d commit 2f42947
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ h2_transport_pipe:
outlet_pressure: 10 # bar - from example in code from Jamie #TODO check this value
h2_storage:
size_capacity_from_demand:
flag: False # If True, then storage is sized to provide steady-state storage
flag: True # 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: "lined_rock_cavern" # can be one of ["none", "pipe", "turbine", "pressure_vessel", "salt_cavern", "lined_rock_cavern"]
days: 8.57267 # from `hydrogen_storage_duration_hr` = 205.74419987482239 [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)
days: -1 #8.57267 # from `hydrogen_storage_duration_hr` = 205.74419987482239 [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)

policy_parameters: # these should be adjusted for inflation prior to application - order of operations: rate in 1992 $,
#then prevailing wage multiplier if applicable, then inflation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ h2_transport_pipe:
outlet_pressure: 10 # bar - from example in code from Jamie #TODO check this value
h2_storage:
size_capacity_from_demand:
flag: False # If True, then storage is sized to provide steady-state storage
flag: True # 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: 19.783 # from `hydrogen_storage_duration_hr` = 474.7948370015298 [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)
type: "salt_cavern" # can be one of ["none", "pipe", "turbine", "pressure_vessel", "salt_cavern", "lined_rock_cavern"]
days: -1 #19.783 # from `hydrogen_storage_duration_hr` = 474.7948370015298 [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)

policy_parameters: # these should be adjusted for inflation prior to application - order of operations: rate in 1992 $,
#then prevailing wage multiplier if applicable, then inflation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ h2_transport_pipe:
outlet_pressure: 10 # bar - from example in code from Jamie #TODO check this value
h2_storage:
size_capacity_from_demand:
flag: False # If True, then storage is sized to provide steady-state storage
flag: True # 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)
type: "salt_cavern" # can be one of ["none", "pipe", "turbine", "pressure_vessel", "salt_cavern", "lined_rock_cavern"]
days: -1 # [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)
# 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)
# installation_days: 14 # days
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ h2_transport_pipe:
outlet_pressure: 10 # bar - from example in code from Jamie #TODO check this value
h2_storage:
size_capacity_from_demand:
flag: False # If True, then storage is sized to provide steady-state storage
flag: True # 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)
type: "lined_rock_cavern" # can be one of ["none", "pipe", "turbine", "pressure_vessel", "salt_cavern", "lined_rock_cavern"]
days: 0 # [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)
# 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)
# installation_days: 14 # days
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ h2_transport_pipe:
outlet_pressure: 10 # bar - from example in code from Jamie #TODO check this value
h2_storage:
size_capacity_from_demand:
flag: False # If True, then storage is sized to provide steady-state storage
flag: True # 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)
type: "lined_rock_cavern" # can be one of ["none", "pipe", "turbine", "pressure_vessel", "salt_cavern", "lined_rock_cavern"]
days: 0 # [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)
# 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)
# installation_days: 14 # days
Expand Down
24 changes: 13 additions & 11 deletions greenheart/tools/eco/hydrogen_mgmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ def run_h2_storage(
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

else:
greenheart_config["h2_capacity"] = h2_capacity
h2_storage_results["h2_storage_kg"] = h2_capacity
Expand Down Expand Up @@ -355,7 +356,7 @@ def run_h2_storage(
area_site,
mass_tank_empty_site,
_,
) = h2_storage.distributed_storage_vessels(h2_capacity, 1)
) = h2_storage.distributed_storage_vessels(greenheart_config["h2_capacity"], 1)
# ) = h2_storage.distributed_storage_vessels(h2_capacity, nturbines)
# capex, opex, energy = h2_storage.calculate_from_fit(h2_capacity)

Expand All @@ -368,15 +369,15 @@ def run_h2_storage(
]
) # total in kWh
h2_storage_results["tank_mass_full_kg"] = (
h2_storage.get_tank_mass(h2_capacity)[1] + h2_capacity
h2_storage.get_tank_mass(greenheart_config["h2_capacity"])[1] + greenheart_config["h2_capacity"]
)
h2_storage_results["tank_footprint_m2"] = h2_storage.get_tank_footprint(
h2_capacity, upright=True
greenheart_config["h2_capacity"], upright=True
)[1]
h2_storage_results[
"tank volume (m^3)"
] = h2_storage.compressed_gas_function.Vtank
h2_storage_results["Number of tanks"] = h2_storage.get_tanks(h2_capacity)
h2_storage_results["Number of tanks"] = h2_storage.get_tanks(greenheart_config["h2_capacity"])
if verbose:
print("ENERGY FOR STORAGE: ", energy * 1e-3 / (365 * 24), " MW")
print("Tank volume (M^3): ", h2_storage_results["tank volume (m^3)"])
Expand All @@ -397,7 +398,7 @@ def run_h2_storage(
storage_input = dict()

# pull parameters from plat_config file
storage_input["h2_storage_kg"] = h2_capacity
storage_input["h2_storage_kg"] = greenheart_config["h2_capacity"]
storage_input["compressor_output_pressure"] = greenheart_config[
"h2_storage_compressor"
]["output_pressure"]
Expand Down Expand Up @@ -426,7 +427,7 @@ def run_h2_storage(
h2_storage = PressureVessel(Energy_cost=energy_cost)
h2_storage.run()

capex, opex, energy = h2_storage.calculate_from_fit(h2_capacity)
capex, opex, energy = h2_storage.calculate_from_fit(greenheart_config["h2_capacity"])

h2_storage_results["storage_capex"] = capex
h2_storage_results["storage_opex"] = opex
Expand All @@ -437,10 +438,10 @@ def run_h2_storage(
]
) # total in kWh
h2_storage_results["tank_mass_full_kg"] = (
h2_storage.get_tank_mass(h2_capacity)[1] + h2_capacity
h2_storage.get_tank_mass(greenheart_config["h2_capacity"])[1] + greenheart_config["h2_capacity"]
)
h2_storage_results["tank_footprint_m2"] = h2_storage.get_tank_footprint(
h2_capacity, upright=True
greenheart_config["h2_capacity"], upright=True
)[1]
h2_storage_results[
"tank volume (m^3)"
Expand All @@ -461,8 +462,8 @@ def run_h2_storage(
# initialize dictionary for salt cavern storage parameters
storage_input = dict()

# pull parameters from plat_config file
storage_input["h2_storage_kg"] = h2_capacity
# pull parameters from plant_config file
storage_input["h2_storage_kg"] = greenheart_config["h2_capacity"]
storage_input["system_flow_rate"] = storage_max_fill_rate
storage_input["model"] = "papadias"

Expand Down Expand Up @@ -495,7 +496,7 @@ def run_h2_storage(
storage_input = dict()

# pull parameters from plat_config file
storage_input["h2_storage_kg"] = h2_capacity
storage_input["h2_storage_kg"] = greenheart_config["h2_capacity"]
storage_input["system_flow_rate"] = storage_max_fill_rate
storage_input["model"] = "papadias"

Expand All @@ -521,6 +522,7 @@ def run_h2_storage(

if verbose:
print("\nH2 Storage Results:")
print("H2 Storage capacity (kg): ",greenheart_config["h2_capacity"])
print("H2 storage capex: ${0:,.0f}".format(h2_storage_results["storage_capex"]))
print(
"H2 storage annual opex: ${0:,.0f}/yr".format(
Expand Down
6 changes: 3 additions & 3 deletions tests/greenheart/test_greenheart_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def test_simulation_wind_wave_solar(subtests):
# prior to 20240207 value was approx(10.823798551850347)
# TODO base this test value on something. Currently just based on output at writing.
with subtests.test("lcoh"):
assert lcoh == approx(12.71510378132601, rel=rtol)
assert lcoh == approx(12.715103781326011, rel=rtol)

# prior to 20240207 value was approx(0.11035426429749774)
# TODO base this test value on something. Currently just based on output at writing.
Expand Down Expand Up @@ -397,15 +397,15 @@ def test_simulation_wind_onshore_steel_ammonia_ss_h2storage(subtests):

# TODO base this test value on something
with subtests.test("lcoh"):
assert lcoh == approx(4.023687007795485, rel=rtol)
assert lcoh == approx(10.0064010897151, rel=rtol)

# TODO base this test value on something
with subtests.test("lcoe"):
assert lcoe == approx(0.03486192934806013, rel=rtol)

# TODO base this test value on something
with subtests.test("steel_finance"):
lcos_expected = 1414.0330270955506
lcos_expected = 1812.985744428756

assert steel_finance.sol.get("price") == approx(lcos_expected, rel=rtol)

Expand Down

0 comments on commit 2f42947

Please sign in to comment.