From 611ba48f3870c409dbd5d21fe201eb624cb60c50 Mon Sep 17 00:00:00 2001 From: kbrunik Date: Thu, 6 Jun 2024 07:53:33 -0700 Subject: [PATCH 1/5] update key value for ss storage --- .../input/plant/greenheart_config_onshore_mn_2030.yaml | 2 ++ .../input/plant/greenheart_config_onshore_tx_2025.yaml | 2 ++ .../input/plant/greenheart_config_onshore_tx_2030.yaml | 2 ++ .../input/plant/greenheart_config_onshore_tx_2035.yaml | 2 ++ 4 files changed, 8 insertions(+) diff --git a/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_mn_2030.yaml b/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_mn_2030.yaml index 478f5128f..9d6ed4793 100644 --- a/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_mn_2030.yaml +++ b/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_mn_2030.yaml @@ -82,6 +82,8 @@ h2_storage_compressor: 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 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) diff --git a/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_tx_2025.yaml b/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_tx_2025.yaml index de7dd8b80..416b23034 100644 --- a/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_tx_2025.yaml +++ b/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_tx_2025.yaml @@ -82,6 +82,8 @@ h2_storage_compressor: 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 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: "salt_cavern" # 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) diff --git a/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_tx_2030.yaml b/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_tx_2030.yaml index d42dec406..d8836195a 100644 --- a/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_tx_2030.yaml +++ b/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_tx_2030.yaml @@ -82,6 +82,8 @@ h2_storage_compressor: 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 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: "salt_cavern" # 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) diff --git a/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_tx_2035.yaml b/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_tx_2035.yaml index b2447427e..4a9927930 100644 --- a/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_tx_2035.yaml +++ b/tests/greenheart/test_greensteel/input/plant/greenheart_config_onshore_tx_2035.yaml @@ -82,6 +82,8 @@ h2_storage_compressor: 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 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: "salt_cavern" # 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) From 093de7d5ec6d399bb9cdbd24ec13f290c1ba9b83 Mon Sep 17 00:00:00 2001 From: kbrunik Date: Thu, 6 Jun 2024 08:13:47 -0700 Subject: [PATCH 2/5] update examples with key changes --- .../input/plant/greenheart_config_onshore_mn.yaml | 9 +++++++++ .../input/plant/greenheart_config_onshore_tx.yaml | 9 +++++++++ .../input/plant/greenheart_config_offshore_gom.yaml | 10 +++++++++- .../input/plant/greenheart_config_offshore_ny.yaml | 10 +++++++++- .../input/plant/greenheart_config_offshore_ca.yaml | 10 +++++++++- .../05-offshore-hydrogen-ca/offshore-hydrogen-ca.py | 4 ++-- 6 files changed, 47 insertions(+), 5 deletions(-) diff --git a/examples/reference_plants/01-onshore-steel-mn/input/plant/greenheart_config_onshore_mn.yaml b/examples/reference_plants/01-onshore-steel-mn/input/plant/greenheart_config_onshore_mn.yaml index 1058640dc..596e98a02 100644 --- a/examples/reference_plants/01-onshore-steel-mn/input/plant/greenheart_config_onshore_mn.yaml +++ b/examples/reference_plants/01-onshore-steel-mn/input/plant/greenheart_config_onshore_mn.yaml @@ -81,6 +81,8 @@ h2_storage_compressor: 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 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) @@ -92,30 +94,36 @@ policy_parameters: # these should be adjusted for inflation prior to application electricity_itc: 0 electricity_ptc: 0 h2_ptc: 0 + h2_storage_itc: 0 option2: # base credit levels with H2 electricity_itc: 0 electricity_ptc: 0.003 # $0.003/kW (this is base, see inflation adjustment in option 3) h2_ptc: 0.6 # $0.60/kg h2 produced - assumes net zero but not meeting prevailing wage requirements - does this need to be # adjusted for inflation from 2022 dollars to claim date, probably constant after claim date? + h2_storage_itc: 0.06 option3: # same as option 5, but assuming prevailing wages are met --> 5x multiplier on both PTCs electricity_itc: 0 electricity_ptc: 0.015 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg 2022 dollars - do not adjust for inflation + h2_storage_itc: 0.3 # bonus options, option 5 and 6 but ITC equivalents option4: # prevailing wages not met electricity_itc: 0.06 # %/100 capex electricity_ptc: 0.00 # $/kW 1992 dollars h2_ptc: 0.6 # $0.60/kg produced 2022 dollars - assumes net zero but not meeting prevailing wage requirements - does this need to be # do not adjust for inflation, probably constant after claim date? + h2_storage_itc: 0.06 option5: # prevailing wages met electricity_itc: 0.30 # %/100 capex electricity_ptc: 0.0 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year + h2_storage_itc: 0.3 option6: # assumes prevailing wages are met, and includes 10% bonus credit of domestic content (100% of steel and iron # and mfg. components from the US) electricity_itc: 0.40 # %/100 capex electricity_ptc: 0.0 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year + h2_storage_itc: 0.4 option7: # assumes prevailing wages are met, and includes 10% bonus credit of domestic content (100% of steel and iron # and mfg. components from the US) electricity_itc: 0.0 # %/100 capex @@ -123,6 +131,7 @@ policy_parameters: # these should be adjusted for inflation prior to application h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year # you can elect itc_for_h2 in leu of the h2_ptc - this choice is independent of the other tech credit selections # 6% or %50 for itc_for_h2 + h2_storage_itc: 0.5 plant_design: scenario0: diff --git a/examples/reference_plants/02-onshore-ammonia-tx/input/plant/greenheart_config_onshore_tx.yaml b/examples/reference_plants/02-onshore-ammonia-tx/input/plant/greenheart_config_onshore_tx.yaml index d688c0753..d23442c05 100644 --- a/examples/reference_plants/02-onshore-ammonia-tx/input/plant/greenheart_config_onshore_tx.yaml +++ b/examples/reference_plants/02-onshore-ammonia-tx/input/plant/greenheart_config_onshore_tx.yaml @@ -81,6 +81,8 @@ h2_storage_compressor: 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 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) @@ -92,30 +94,36 @@ policy_parameters: # these should be adjusted for inflation prior to application electricity_itc: 0 electricity_ptc: 0 h2_ptc: 0 + h2_storage_itc: 0 option2: # base credit levels with H2 electricity_itc: 0 electricity_ptc: 0.003 # $0.003/kW (this is base, see inflation adjustment in option 3) h2_ptc: 0.6 # $0.60/kg h2 produced - assumes net zero but not meeting prevailing wage requirements - does this need to be # adjusted for inflation from 2022 dollars to claim date, probably constant after claim date? + h2_storage_itc: 0.06 option3: # same as option 5, but assuming prevailing wages are met --> 5x multiplier on both PTCs electricity_itc: 0 electricity_ptc: 0.015 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg 2022 dollars - do not adjust for inflation + h2_storage_itc: 0.3 # bonus options, option 5 and 6 but ITC equivalents option4: # prevailing wages not met electricity_itc: 0.06 # %/100 capex electricity_ptc: 0.00 # $/kW 1992 dollars h2_ptc: 0.6 # $0.60/kg produced 2022 dollars - assumes net zero but not meeting prevailing wage requirements - does this need to be # do not adjust for inflation, probably constant after claim date? + h2_storage_itc: 0.06 option5: # prevailing wages met electricity_itc: 0.30 # %/100 capex electricity_ptc: 0.0 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year + h2_storage_itc: 0.3 option6: # assumes prevailing wages are met, and includes 10% bonus credit of domestic content (100% of steel and iron # and mfg. components from the US) electricity_itc: 0.40 # %/100 capex electricity_ptc: 0.0 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year + h2_storage_itc: 0.4 option7: # assumes prevailing wages are met, and includes 10% bonus credit of domestic content (100% of steel and iron # and mfg. components from the US) electricity_itc: 0.0 # %/100 capex @@ -123,6 +131,7 @@ policy_parameters: # these should be adjusted for inflation prior to application h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year # you can elect itc_for_h2 in leu of the h2_ptc - this choice is independent of the other tech credit selections # 6% or %50 for itc_for_h2 + h2_storage_itc: 0.5 plant_design: scenario0: diff --git a/examples/reference_plants/03-offshore-hydrogen-gom/input/plant/greenheart_config_offshore_gom.yaml b/examples/reference_plants/03-offshore-hydrogen-gom/input/plant/greenheart_config_offshore_gom.yaml index e42726849..ef443d0e1 100644 --- a/examples/reference_plants/03-offshore-hydrogen-gom/input/plant/greenheart_config_offshore_gom.yaml +++ b/examples/reference_plants/03-offshore-hydrogen-gom/input/plant/greenheart_config_offshore_gom.yaml @@ -80,7 +80,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) @@ -118,30 +119,36 @@ policy_parameters: # these should be adjusted for inflation prior to application electricity_itc: 0 electricity_ptc: 0 h2_ptc: 0 + h2_storage_itc: 0 option2: # base credit levels with H2 electricity_itc: 0 electricity_ptc: 0.003 # $0.003/kW (this is base, see inflation adjustment in option 3) h2_ptc: 0.6 # $0.60/kg h2 produced - assumes net zero but not meeting prevailing wage requirements - does this need to be # adjusted for inflation from 2022 dollars to claim date, probably constant after claim date? + h2_storage_itc: 0.06 option3: # same as option 5, but assuming prevailing wages are met --> 5x multiplier on both PTCs electricity_itc: 0 electricity_ptc: 0.015 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg 2022 dollars - do not adjust for inflation + h2_storage_itc: 0.3 # bonus options, option 5 and 6 but ITC equivalents option4: # prevailing wages not met electricity_itc: 0.06 # %/100 capex electricity_ptc: 0.00 # $/kW 1992 dollars h2_ptc: 0.6 # $0.60/kg produced 2022 dollars - assumes net zero but not meeting prevailing wage requirements - does this need to be # do not adjust for inflation, probably constant after claim date? + h2_storage_itc: 0.06 option5: # prevailing wages met electricity_itc: 0.30 # %/100 capex electricity_ptc: 0.0 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year + h2_storage_itc: 0.3 option6: # assumes prevailing wages are met, and includes 10% bonus credit of domestic content (100% of steel and iron # and mfg. components from the US) electricity_itc: 0.40 # %/100 capex electricity_ptc: 0.0 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year + h2_storage_itc: 0.4 option7: # assumes prevailing wages are met, and includes 10% bonus credit of domestic content (100% of steel and iron # and mfg. components from the US) electricity_itc: 0.0 # %/100 capex @@ -149,6 +156,7 @@ policy_parameters: # these should be adjusted for inflation prior to application h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year # you can elect itc_for_h2 in leu of the h2_ptc - this choice is independent of the other tech credit selections # 6% or %50 for itc_for_h2 + h2_storage_itc: 0.5 plant_design: scenario0: diff --git a/examples/reference_plants/04-offshore-hydrogen-ny/input/plant/greenheart_config_offshore_ny.yaml b/examples/reference_plants/04-offshore-hydrogen-ny/input/plant/greenheart_config_offshore_ny.yaml index 9681aae2f..8d747decc 100644 --- a/examples/reference_plants/04-offshore-hydrogen-ny/input/plant/greenheart_config_offshore_ny.yaml +++ b/examples/reference_plants/04-offshore-hydrogen-ny/input/plant/greenheart_config_offshore_ny.yaml @@ -80,7 +80,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) @@ -118,30 +119,36 @@ policy_parameters: # these should be adjusted for inflation prior to application electricity_itc: 0 electricity_ptc: 0 h2_ptc: 0 + h2_storage_itc: 0 option2: # base credit levels with H2 electricity_itc: 0 electricity_ptc: 0.003 # $0.003/kW (this is base, see inflation adjustment in option 3) h2_ptc: 0.6 # $0.60/kg h2 produced - assumes net zero but not meeting prevailing wage requirements - does this need to be # adjusted for inflation from 2022 dollars to claim date, probably constant after claim date? + h2_storage_itc: 0.06 option3: # same as option 5, but assuming prevailing wages are met --> 5x multiplier on both PTCs electricity_itc: 0 electricity_ptc: 0.015 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg 2022 dollars - do not adjust for inflation + h2_storage_itc: 0.3 # bonus options, option 5 and 6 but ITC equivalents option4: # prevailing wages not met electricity_itc: 0.06 # %/100 capex electricity_ptc: 0.00 # $/kW 1992 dollars h2_ptc: 0.6 # $0.60/kg produced 2022 dollars - assumes net zero but not meeting prevailing wage requirements - does this need to be # do not adjust for inflation, probably constant after claim date? + h2_storage_itc: 0.06 option5: # prevailing wages met electricity_itc: 0.30 # %/100 capex electricity_ptc: 0.0 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year + h2_storage_itc: 0.3 option6: # assumes prevailing wages are met, and includes 10% bonus credit of domestic content (100% of steel and iron # and mfg. components from the US) electricity_itc: 0.40 # %/100 capex electricity_ptc: 0.0 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year + h2_storage_itc: 0.4 option7: # assumes prevailing wages are met, and includes 10% bonus credit of domestic content (100% of steel and iron # and mfg. components from the US) electricity_itc: 0.0 # %/100 capex @@ -149,6 +156,7 @@ policy_parameters: # these should be adjusted for inflation prior to application h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year # you can elect itc_for_h2 in leu of the h2_ptc - this choice is independent of the other tech credit selections # 6% or %50 for itc_for_h2 + h2_storage_itc: 0.5 plant_design: scenario0: diff --git a/examples/reference_plants/05-offshore-hydrogen-ca/input/plant/greenheart_config_offshore_ca.yaml b/examples/reference_plants/05-offshore-hydrogen-ca/input/plant/greenheart_config_offshore_ca.yaml index 2a1f6849d..136eab3f0 100644 --- a/examples/reference_plants/05-offshore-hydrogen-ca/input/plant/greenheart_config_offshore_ca.yaml +++ b/examples/reference_plants/05-offshore-hydrogen-ca/input/plant/greenheart_config_offshore_ca.yaml @@ -80,7 +80,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) @@ -118,30 +119,36 @@ policy_parameters: # these should be adjusted for inflation prior to application electricity_itc: 0 electricity_ptc: 0 h2_ptc: 0 + h2_storage_itc: 0 option2: # base credit levels with H2 electricity_itc: 0 electricity_ptc: 0.003 # $0.003/kW (this is base, see inflation adjustment in option 3) h2_ptc: 0.6 # $0.60/kg h2 produced - assumes net zero but not meeting prevailing wage requirements - does this need to be # adjusted for inflation from 2022 dollars to claim date, probably constant after claim date? + h2_storage_itc: 0.06 option3: # same as option 5, but assuming prevailing wages are met --> 5x multiplier on both PTCs electricity_itc: 0 electricity_ptc: 0.015 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg 2022 dollars - do not adjust for inflation + h2_storage_itc: 0.3 # bonus options, option 5 and 6 but ITC equivalents option4: # prevailing wages not met electricity_itc: 0.06 # %/100 capex electricity_ptc: 0.00 # $/kW 1992 dollars h2_ptc: 0.6 # $0.60/kg produced 2022 dollars - assumes net zero but not meeting prevailing wage requirements - does this need to be # do not adjust for inflation, probably constant after claim date? + h2_storage_itc: 0.06 option5: # prevailing wages met electricity_itc: 0.30 # %/100 capex electricity_ptc: 0.0 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year + h2_storage_itc: 0.3 option6: # assumes prevailing wages are met, and includes 10% bonus credit of domestic content (100% of steel and iron # and mfg. components from the US) electricity_itc: 0.40 # %/100 capex electricity_ptc: 0.0 # $/kWh 1992 dollars h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year + h2_storage_itc: 0.4 option7: # assumes prevailing wages are met, and includes 10% bonus credit of domestic content (100% of steel and iron # and mfg. components from the US) electricity_itc: 0.0 # %/100 capex @@ -149,6 +156,7 @@ policy_parameters: # these should be adjusted for inflation prior to application h2_ptc: 3.00 # $/kg of h2 produced 2022 dollars - do adjust for inflation every year applied and until application year # you can elect itc_for_h2 in leu of the h2_ptc - this choice is independent of the other tech credit selections # 6% or %50 for itc_for_h2 + h2_storage_itc: 0.5 plant_design: scenario0: diff --git a/examples/reference_plants/05-offshore-hydrogen-ca/offshore-hydrogen-ca.py b/examples/reference_plants/05-offshore-hydrogen-ca/offshore-hydrogen-ca.py index 8d4d788e0..9e2a08679 100644 --- a/examples/reference_plants/05-offshore-hydrogen-ca/offshore-hydrogen-ca.py +++ b/examples/reference_plants/05-offshore-hydrogen-ca/offshore-hydrogen-ca.py @@ -53,10 +53,10 @@ ) # for analysis - # prob, config = run_greenheart(config, run_only=True) + prob, config = run_greenheart(config, run_only=True) # for optimization - prob, config = run_greenheart(config, run_only=False) + # prob, config = run_greenheart(config, run_only=False) lcoe = prob.get_val("lcoe", units="USD/(MW*h)") lcoh = prob.get_val("lcoh", units="USD/kg") From 2f429472be4fc768ab5fc0fec8eaa3733dd0c578 Mon Sep 17 00:00:00 2001 From: kbrunik Date: Thu, 6 Jun 2024 08:52:44 -0700 Subject: [PATCH 3/5] fixed h2 storage sizing bug --- .../plant/greenheart_config_onshore_mn.yaml | 4 ++-- .../plant/greenheart_config_onshore_tx.yaml | 6 ++--- .../plant/greenheart_config_offshore_gom.yaml | 6 ++--- .../plant/greenheart_config_offshore_ny.yaml | 6 ++--- .../plant/greenheart_config_offshore_ca.yaml | 6 ++--- greenheart/tools/eco/hydrogen_mgmt.py | 24 ++++++++++--------- tests/greenheart/test_greenheart_system.py | 6 ++--- 7 files changed, 30 insertions(+), 28 deletions(-) diff --git a/examples/reference_plants/01-onshore-steel-mn/input/plant/greenheart_config_onshore_mn.yaml b/examples/reference_plants/01-onshore-steel-mn/input/plant/greenheart_config_onshore_mn.yaml index 596e98a02..7b98f4f20 100644 --- a/examples/reference_plants/01-onshore-steel-mn/input/plant/greenheart_config_onshore_mn.yaml +++ b/examples/reference_plants/01-onshore-steel-mn/input/plant/greenheart_config_onshore_mn.yaml @@ -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 diff --git a/examples/reference_plants/02-onshore-ammonia-tx/input/plant/greenheart_config_onshore_tx.yaml b/examples/reference_plants/02-onshore-ammonia-tx/input/plant/greenheart_config_onshore_tx.yaml index d23442c05..8ea5ecf52 100644 --- a/examples/reference_plants/02-onshore-ammonia-tx/input/plant/greenheart_config_onshore_tx.yaml +++ b/examples/reference_plants/02-onshore-ammonia-tx/input/plant/greenheart_config_onshore_tx.yaml @@ -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 diff --git a/examples/reference_plants/03-offshore-hydrogen-gom/input/plant/greenheart_config_offshore_gom.yaml b/examples/reference_plants/03-offshore-hydrogen-gom/input/plant/greenheart_config_offshore_gom.yaml index ef443d0e1..9daf5d2d0 100644 --- a/examples/reference_plants/03-offshore-hydrogen-gom/input/plant/greenheart_config_offshore_gom.yaml +++ b/examples/reference_plants/03-offshore-hydrogen-gom/input/plant/greenheart_config_offshore_gom.yaml @@ -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 diff --git a/examples/reference_plants/04-offshore-hydrogen-ny/input/plant/greenheart_config_offshore_ny.yaml b/examples/reference_plants/04-offshore-hydrogen-ny/input/plant/greenheart_config_offshore_ny.yaml index 8d747decc..980947a4f 100644 --- a/examples/reference_plants/04-offshore-hydrogen-ny/input/plant/greenheart_config_offshore_ny.yaml +++ b/examples/reference_plants/04-offshore-hydrogen-ny/input/plant/greenheart_config_offshore_ny.yaml @@ -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 diff --git a/examples/reference_plants/05-offshore-hydrogen-ca/input/plant/greenheart_config_offshore_ca.yaml b/examples/reference_plants/05-offshore-hydrogen-ca/input/plant/greenheart_config_offshore_ca.yaml index 136eab3f0..17255059e 100644 --- a/examples/reference_plants/05-offshore-hydrogen-ca/input/plant/greenheart_config_offshore_ca.yaml +++ b/examples/reference_plants/05-offshore-hydrogen-ca/input/plant/greenheart_config_offshore_ca.yaml @@ -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 diff --git a/greenheart/tools/eco/hydrogen_mgmt.py b/greenheart/tools/eco/hydrogen_mgmt.py index 46201c447..44a82e678 100644 --- a/greenheart/tools/eco/hydrogen_mgmt.py +++ b/greenheart/tools/eco/hydrogen_mgmt.py @@ -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 @@ -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) @@ -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)"]) @@ -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"] @@ -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 @@ -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)" @@ -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" @@ -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" @@ -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( diff --git a/tests/greenheart/test_greenheart_system.py b/tests/greenheart/test_greenheart_system.py index 912889931..2291cffcc 100644 --- a/tests/greenheart/test_greenheart_system.py +++ b/tests/greenheart/test_greenheart_system.py @@ -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. @@ -397,7 +397,7 @@ 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"): @@ -405,7 +405,7 @@ def test_simulation_wind_onshore_steel_ammonia_ss_h2storage(subtests): # 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) From 81e55f86fcd1e24b06a5fe27120eae6091aac2f3 Mon Sep 17 00:00:00 2001 From: kbrunik Date: Fri, 7 Jun 2024 05:45:38 -0700 Subject: [PATCH 4/5] clean up hydrogen mgmt logic --- .../plant/greenheart_config_onshore_mn.yaml | 2 +- .../plant/greenheart_config_onshore_tx.yaml | 2 +- .../plant/greenheart_config_offshore_gom.yaml | 2 +- greenheart/tools/eco/hydrogen_mgmt.py | 272 ++++++++++-------- 4 files changed, 152 insertions(+), 126 deletions(-) diff --git a/examples/reference_plants/01-onshore-steel-mn/input/plant/greenheart_config_onshore_mn.yaml b/examples/reference_plants/01-onshore-steel-mn/input/plant/greenheart_config_onshore_mn.yaml index 7b98f4f20..53f72b68a 100644 --- a/examples/reference_plants/01-onshore-steel-mn/input/plant/greenheart_config_onshore_mn.yaml +++ b/examples/reference_plants/01-onshore-steel-mn/input/plant/greenheart_config_onshore_mn.yaml @@ -85,7 +85,7 @@ h2_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: -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) + days: 0 #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 diff --git a/examples/reference_plants/02-onshore-ammonia-tx/input/plant/greenheart_config_onshore_tx.yaml b/examples/reference_plants/02-onshore-ammonia-tx/input/plant/greenheart_config_onshore_tx.yaml index 8ea5ecf52..f8801dcfc 100644 --- a/examples/reference_plants/02-onshore-ammonia-tx/input/plant/greenheart_config_onshore_tx.yaml +++ b/examples/reference_plants/02-onshore-ammonia-tx/input/plant/greenheart_config_onshore_tx.yaml @@ -85,7 +85,7 @@ h2_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: "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) + days: 0 #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 diff --git a/examples/reference_plants/03-offshore-hydrogen-gom/input/plant/greenheart_config_offshore_gom.yaml b/examples/reference_plants/03-offshore-hydrogen-gom/input/plant/greenheart_config_offshore_gom.yaml index 9daf5d2d0..8281fb7d4 100644 --- a/examples/reference_plants/03-offshore-hydrogen-gom/input/plant/greenheart_config_offshore_gom.yaml +++ b/examples/reference_plants/03-offshore-hydrogen-gom/input/plant/greenheart_config_offshore_gom.yaml @@ -84,7 +84,7 @@ h2_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: "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) + 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 diff --git a/greenheart/tools/eco/hydrogen_mgmt.py b/greenheart/tools/eco/hydrogen_mgmt.py index 44a82e678..9fac3d621 100644 --- a/greenheart/tools/eco/hydrogen_mgmt.py +++ b/greenheart/tools/eco/hydrogen_mgmt.py @@ -44,7 +44,9 @@ ) from greenheart.simulation.technologies.offshore.all_platforms import calc_platform_opex -from greenheart.simulation.technologies.hydrogen.h2_storage.storage_sizing import hydrogen_storage_capacity +from greenheart.simulation.technologies.hydrogen.h2_storage.storage_sizing import ( + hydrogen_storage_capacity, +) def run_h2_pipe_array( @@ -248,7 +250,6 @@ def run_h2_storage( design_scenario, verbose=False, ): - nturbines = hopp_config["technologies"]["wind"]["num_turbines"] if design_scenario["h2_storage_location"] == "platform": if ( @@ -259,16 +260,31 @@ def run_h2_storage( "Only pressure vessel storage can be used on the off shore platform" ) - # initialize output dictionary + if design_scenario["h2_storage_location"] == "turbine": + if ( + greenheart_config["h2_storage"]["type"] != "turbine" + and greenheart_config["h2_storage"]["type"] != "pressure_vessel" + and greenheart_config["h2_storage"]["type"] != "none" + ): + raise ValueError( + "Only turbine or pressure vessel storage can be used for turbine hydrogen storage location" + ) + ########### initialize output dictionary ########### h2_storage_results = dict() - storage_hours = greenheart_config["h2_storage"]["days"] * 24 storage_max_fill_rate = np.max( electrolyzer_physics_results["H2_Results"]["Hydrogen Hourly Production [kg/hr]"] ) + ########### get hydrogen storage size in kilograms ########### + ##################### no hydrogen storage + if greenheart_config["h2_storage"]["type"] == "none": + h2_storage_capacity_kg = 0.0 + storage_max_fill_rate = 0.0 + ##################### get storage capacity from turbine storage model - if greenheart_config["h2_storage"]["capacity_from_max_on_turbine_storage"]: + elif greenheart_config["h2_storage"]["capacity_from_max_on_turbine_storage"]: + nturbines = hopp_config["technologies"]["wind"]["num_turbines"] turbine = { "tower_length": turbine_config["tower"]["length"], "section_diameters": turbine_config["tower"]["section_diameters"], @@ -282,28 +298,39 @@ def run_h2_storage( h2_storage_capacity_single_turbine = h2_storage.get_capacity_H2() # kg - h2_capacity = nturbines * h2_storage_capacity_single_turbine # in kg - ################################### - else: - h2_capacity = round(storage_hours * storage_max_fill_rate) + h2_storage_capacity_kg = nturbines * h2_storage_capacity_single_turbine # in kg - if greenheart_config["h2_storage"]["type"] == "none": - greenheart_config["h2_capacity"] = 0.0 - h2_storage_results["h2_storage_kg"] = 0.0 + ##################### get storage capacity from hydrogen storage demand + elif 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, + ) + h2_storage_capacity_kg = hydrogen_storage_capacity_kg + h2_storage_results["hydrogen_storage_duration_hr"] = ( + hydrogen_storage_duration_hr + ) + h2_storage_results["hydrogen_storage_soc"] = hydrogen_storage_soc + + ##################### get storage capacity based on storage days in config else: - 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 + storage_hours = greenheart_config["h2_storage"]["days"] * 24 + h2_storage_capacity_kg = round(storage_hours * storage_max_fill_rate) - else: - greenheart_config["h2_capacity"] = h2_capacity - h2_storage_results["h2_storage_kg"] = h2_capacity + h2_storage_results["h2_storage_capacity_kg"] = h2_storage_capacity_kg + h2_storage_results["h2_storage_max_fill_rate_kg_hr"] = storage_max_fill_rate - # if storage_hours == 0: + ########### run specific hydrogen storage models for costs and energy use ########### if ( greenheart_config["h2_storage"]["type"] == "none" or design_scenario["h2_storage_location"] == "none" @@ -314,8 +341,8 @@ def run_h2_storage( h2_storage = None - elif design_scenario["h2_storage_location"] == "turbine": - if greenheart_config["h2_storage"]["type"] == "turbine": + elif greenheart_config["h2_storage"]["type"] == "turbine": + if design_scenario["h2_storage_location"] == "turbine": turbine = { "tower_length": turbine_config["tower"]["length"], "section_diameters": turbine_config["tower"]["section_diameters"], @@ -338,12 +365,41 @@ def run_h2_storage( ) print("storage pressure: ", h2_storage.get_pressure_H2()) - h2_storage_results[ - "storage_energy" - ] = 0.0 # low pressure, so no additional compression needed beyond electolyzer + h2_storage_results["storage_energy"] = ( + 0.0 # low pressure, so no additional compression needed beyond electolyzer + ) + else: + raise ValueError( + "`h2_storage_location` must be set to 'turbine' to use 'turbine' for h2 storage type." + ) - elif greenheart_config["h2_storage"]["type"] == "pressure_vessel": + elif greenheart_config["h2_storage"]["type"] == "pipe": + # for more information, see https://www.nrel.gov/docs/fy14osti/58564.pdf + # initialize dictionary for pipe storage parameters + storage_input = dict() + # pull parameters from plat_config file + storage_input["h2_storage_kg"] = h2_storage_capacity_kg + storage_input["compressor_output_pressure"] = greenheart_config[ + "h2_storage_compressor" + ]["output_pressure"] + storage_input["system_flow_rate"] = storage_max_fill_rate + storage_input["model"] = "papadias" + + # run pipe storage model + h2_storage = UndergroundPipeStorage(storage_input) + + h2_storage.pipe_storage_capex() + h2_storage.pipe_storage_opex() + + h2_storage_results["storage_capex"] = h2_storage.output_dict[ + "pipe_storage_capex" + ] + h2_storage_results["storage_opex"] = h2_storage.output_dict["pipe_storage_opex"] + h2_storage_results["storage_energy"] = 0.0 + + elif greenheart_config["h2_storage"]["type"] == "pressure_vessel": + if design_scenario["h2_storage_location"] == "turbine": energy_cost = 0.0 h2_storage = PressureVessel(Energy_cost=energy_cost) @@ -356,7 +412,7 @@ def run_h2_storage( area_site, mass_tank_empty_site, _, - ) = h2_storage.distributed_storage_vessels(greenheart_config["h2_capacity"], 1) + ) = h2_storage.distributed_storage_vessels(h2_storage_capacity_kg, 1) # ) = h2_storage.distributed_storage_vessels(h2_capacity, nturbines) # capex, opex, energy = h2_storage.calculate_from_fit(h2_capacity) @@ -369,15 +425,18 @@ def run_h2_storage( ] ) # total in kWh h2_storage_results["tank_mass_full_kg"] = ( - h2_storage.get_tank_mass(greenheart_config["h2_capacity"])[1] + greenheart_config["h2_capacity"] + h2_storage.get_tank_mass(h2_storage_capacity_kg)[1] + + h2_storage_capacity_kg ) h2_storage_results["tank_footprint_m2"] = h2_storage.get_tank_footprint( - greenheart_config["h2_capacity"], upright=True + h2_storage_capacity_kg, 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(greenheart_config["h2_capacity"]) + h2_storage_results["tank volume (m^3)"] = ( + h2_storage.compressed_gas_function.Vtank + ) + h2_storage_results["Number of tanks"] = h2_storage.get_tanks( + h2_storage_capacity_kg + ) if verbose: print("ENERGY FOR STORAGE: ", energy * 1e-3 / (365 * 24), " MW") print("Tank volume (M^3): ", h2_storage_results["tank volume (m^3)"]) @@ -388,82 +447,53 @@ def run_h2_storage( print("N Tanks: ", h2_storage_results["Number of tanks"]) else: - ValueError( - "with storage location set to tower, only 'pressure_vessel' and 'tower' types are implemented." - ) - - elif greenheart_config["h2_storage"]["type"] == "pipe": - # for more information, see https://www.nrel.gov/docs/fy14osti/58564.pdf - # initialize dictionary for pipe storage parameters - storage_input = dict() - - # pull parameters from plat_config file - storage_input["h2_storage_kg"] = greenheart_config["h2_capacity"] - storage_input["compressor_output_pressure"] = greenheart_config[ - "h2_storage_compressor" - ]["output_pressure"] - storage_input["system_flow_rate"] = storage_max_fill_rate - storage_input["model"] = "papadias" + # if plant_config["project_parameters"]["grid_connection"]: + # energy_cost = plant_config["project_parameters"]["ppa_price"] + # else: + # energy_cost = 0.0 + energy_cost = 0.0 # energy cost is now handled outside the storage model - # run pipe storage model - h2_storage = UndergroundPipeStorage(storage_input) - - h2_storage.pipe_storage_capex() - h2_storage.pipe_storage_opex() - - h2_storage_results["storage_capex"] = h2_storage.output_dict[ - "pipe_storage_capex" - ] - h2_storage_results["storage_opex"] = h2_storage.output_dict["pipe_storage_opex"] - h2_storage_results["storage_energy"] = 0.0 - - elif greenheart_config["h2_storage"]["type"] == "pressure_vessel": - # if plant_config["project_parameters"]["grid_connection"]: - # energy_cost = plant_config["project_parameters"]["ppa_price"] - # else: - # energy_cost = 0.0 - energy_cost = 0.0 # energy cost is now handled outside the storage model - - h2_storage = PressureVessel(Energy_cost=energy_cost) - h2_storage.run() + h2_storage = PressureVessel(Energy_cost=energy_cost) + h2_storage.run() - capex, opex, energy = h2_storage.calculate_from_fit(greenheart_config["h2_capacity"]) + capex, opex, energy = h2_storage.calculate_from_fit(h2_storage_capacity_kg) - h2_storage_results["storage_capex"] = capex - h2_storage_results["storage_opex"] = opex - h2_storage_results["storage_energy"] = ( - energy - * electrolyzer_physics_results["H2_Results"][ - "Life: Annual H2 production [kg/year]" - ] - ) # total in kWh - h2_storage_results["tank_mass_full_kg"] = ( - 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( - 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.compressed_gas_function.number_of_tanks - if verbose: - print("ENERGY FOR STORAGE: ", energy * 1e-3 / (365 * 24), " MW") - print("Tank volume (M^3): ", h2_storage_results["tank volume (m^3)"]) - print( - "Single Tank capacity (kg): ", - h2_storage.compressed_gas_function.single_tank_h2_capacity_kg, + h2_storage_results["storage_capex"] = capex + h2_storage_results["storage_opex"] = opex + h2_storage_results["storage_energy"] = ( + energy + * electrolyzer_physics_results["H2_Results"][ + "Life: Annual H2 production [kg/year]" + ] + ) # total in kWh + h2_storage_results["tank_mass_full_kg"] = ( + h2_storage.get_tank_mass(h2_storage_capacity_kg)[1] + + h2_storage_capacity_kg + ) + h2_storage_results["tank_footprint_m2"] = h2_storage.get_tank_footprint( + h2_storage_capacity_kg, upright=True + )[1] + h2_storage_results["tank volume (m^3)"] = ( + h2_storage.compressed_gas_function.Vtank + ) + h2_storage_results["Number of tanks"] = ( + h2_storage.compressed_gas_function.number_of_tanks ) - print("N Tanks: ", h2_storage_results["Number of tanks"]) + if verbose: + print("ENERGY FOR STORAGE: ", energy * 1e-3 / (365 * 24), " MW") + print("Tank volume (M^3): ", h2_storage_results["tank volume (m^3)"]) + print( + "Single Tank capacity (kg): ", + h2_storage.compressed_gas_function.single_tank_h2_capacity_kg, + ) + print("N Tanks: ", h2_storage_results["Number of tanks"]) elif greenheart_config["h2_storage"]["type"] == "salt_cavern": # initialize dictionary for salt cavern storage parameters storage_input = dict() # pull parameters from plant_config file - storage_input["h2_storage_kg"] = greenheart_config["h2_capacity"] + storage_input["h2_storage_kg"] = h2_storage_capacity_kg storage_input["system_flow_rate"] = storage_max_fill_rate storage_input["model"] = "papadias" @@ -480,23 +510,13 @@ def run_h2_storage( "salt_cavern_storage_opex" ] h2_storage_results["storage_energy"] = 0.0 - # TODO replace this rough estimate with real numbers - # h2_storage = None - # capex = 36.0 * h2_capacity # based on Papadias 2021 table 7 - # opex = ( - # 0.021 * capex - # ) # based on https://www.pnnl.gov/sites/default/files/media/file/Hydrogen_Methodology.pdf - - # h2_storage_results["storage_capex"] = capex - # h2_storage_results["storage_opex"] = opex - # h2_storage_results["storage_energy"] = 0.0 elif greenheart_config["h2_storage"]["type"] == "lined_rock_cavern": # initialize dictionary for salt cavern storage parameters storage_input = dict() # pull parameters from plat_config file - storage_input["h2_storage_kg"] = greenheart_config["h2_capacity"] + storage_input["h2_storage_kg"] = h2_storage_capacity_kg storage_input["system_flow_rate"] = storage_max_fill_rate storage_input["model"] = "papadias" @@ -516,13 +536,12 @@ def run_h2_storage( else: raise ( ValueError( - "H2 storage type %s was given, but must be one of ['none', 'pipe', 'pressure_vessel', 'salt_cavern', 'lined_rock_cavern']" + "H2 storage type %s was given, but must be one of ['none', 'turbine', 'pipe', 'pressure_vessel', 'salt_cavern', 'lined_rock_cavern']" ) ) 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( @@ -530,13 +549,14 @@ def run_h2_storage( ) ) print( - "H2 storage capacity (tonnes): ", h2_storage_results["h2_storage_kg"] / 1000 + "H2 storage capacity (tonnes): ", + h2_storage_results["h2_storage_capacity_kg"] / 1000, ) - if h2_storage_results["h2_storage_kg"] > 0: + if h2_storage_results["h2_storage_capacity_kg"] > 0: print( "H2 storage cost $/kg of H2: ", h2_storage_results["storage_capex"] - / h2_storage_results["h2_storage_kg"], + / h2_storage_results["h2_storage_capacity_kg"], ) return h2_storage, h2_storage_results @@ -592,12 +612,18 @@ def run_equipment_platform( topmass += battery_mass toparea += battery_area - if hopp_config["site"]["solar"] and design_scenario["pv_location"] == "platform": - pv_area = hopp_results['hybrid_plant'].pv.footprint_area - solar_mass = hopp_results['hybrid_plant'].pv.system_mass - + if ( + hopp_config["site"]["solar"] + and design_scenario["pv_location"] == "platform" + ): + pv_area = hopp_results["hybrid_plant"].pv.footprint_area + solar_mass = hopp_results["hybrid_plant"].pv.system_mass + if pv_area > toparea: - warnings.warn(f"Solar area ({pv_area} m^2) must be smaller than platform area ({toparea} m^2)", UserWarning) + warnings.warn( + f"Solar area ({pv_area} m^2) must be smaller than platform area ({toparea} m^2)", + UserWarning, + ) topmass += solar_mass #### initialize From 137b6aed1ea2aea98fa2ba2b38cb7c554534647f Mon Sep 17 00:00:00 2001 From: kbrunik Date: Fri, 7 Jun 2024 15:11:00 -0700 Subject: [PATCH 5/5] fix typo --- greenheart/tools/eco/electrolysis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/greenheart/tools/eco/electrolysis.py b/greenheart/tools/eco/electrolysis.py index e8e27e496..a9cc31bd0 100644 --- a/greenheart/tools/eco/electrolysis.py +++ b/greenheart/tools/eco/electrolysis.py @@ -89,7 +89,7 @@ def run_electrolyzer_physics( } if "time_between_replacement" in greenheart_config['electrolyzer']: - warnings.warn("`time_between_replacement` as an input is depricated. It is now calculated internally and is output in electrolyzer_physics_results['H2_Results']['Time Until Replacement [hrs]'].") + warnings.warn("`time_between_replacement` as an input is deprecated. It is now calculated internally and is output in electrolyzer_physics_results['H2_Results']['Time Until Replacement [hrs]'].") H2_Results, h2_ts, h2_tot, power_to_electrolyzer_kw = run_h2_PEM( electrical_generation_timeseries=energy_to_electrolyzer_kw,