Skip to content

Compressed Gas H2 Storage#680

Merged
johnjasa merged 23 commits intoNatLabRockies:developfrom
jmartin4u:comp_h2_storage
Apr 23, 2026
Merged

Compressed Gas H2 Storage#680
johnjasa merged 23 commits intoNatLabRockies:developfrom
jmartin4u:comp_h2_storage

Conversation

@jmartin4u
Copy link
Copy Markdown
Collaborator

@jmartin4u jmartin4u commented Apr 15, 2026

Compressed Gas H2 Storage

This adds in the Compressed Gas Terminal storage cost model from HDSAM, to complement the geologic and pipe storage models that were already (partially) based on HDSAM. HDSAM's "Compressed Gas H2 Terminal" tab contains highly detailed calculations for the cost of H2 stored in many compressed gas tanks, at either 350 bar or 700 bar, as well as the mechanisms needed to load H2 onto shipment trucks. This cost model makes a key simplifications to the HDSAM model to reduce computational complexity and make it match the cost of just storage, without the truck loading pieces that are considered in HDSAM. The principal additions are made in h2integrate/storage/hydrogen/hydrogen_storage_cost.py

The piping, plumbing, and land costs, which are minor cost components compared to the storage vessel and compressor costs, have had their computation simplified. Constant ratios of material to H2 charge/discharge capacity have been established for these costs, by varying the capacity as an input to HDSAM and recording the ratio of material needed to achieve this H2 charge/discharge capacity. Although these ratios varied slightly throughout the range of possible capacities, they have been simplified to a constant for the purposes of this model. These constants are as follows:

  • Piping: 300 kg/day per meter of pipe
  • Plumbing: 1600 kg/day per tank storage bay
  • Land: 4 kg/day per m^2 of land

The tank cost is only modeled in HDSAM at two specific pressures: 350 bar and 700 bar. To allow any storage pressure to be simulated, I have simply used a linear interpolation of the two discrete $/kg costs for these pressure levels.

The compressor model h2integrate/storage/hydrogen/h2_transport/h2_compression.py, also based on HDSAM, is modified to distinguish between pipeline and storage compressors. This was previous using only the pipeline compressor HDSAM model; a new input has been created to distinguish between pipeline and storage compressors.

Regression tests for this new model were added to match the previous existing tests in h2integrate/storage/hydrogen/test/test_hydrogen_storage.py. For this, a distinction was added between expected_capex (used in test_h2_storage_capex_opex) and a new expected_storage_capex (used in test_h2_storage_capex_per_kg) - this is because, while the Papadias polynomial fits were used to calculate storage costs as a single capex value, the new compressed gas model distinguishes between the tank cost per kg (used to calculate expected_storage_capex) and other, minor capex components. The test_h2_storage_capex_per_kg only calculates this first tank component of the capex, not the whole capex.

Feedback is requested on whether the simplifications to the HDSAM model are acceptable, and if this model will serve larger H2 storage modeling goals.

Section 1: Type of Contribution

  • Feature Enhancement
    • Framework
    • New Model
    • Updated Model
    • Tools/Utilities
    • Other (please describe):
  • Bug Fix
  • Documentation Update
  • CI Changes
  • Other (please describe):

Section 2: Draft PR Checklist

  • Open draft PR
  • Describe the feature that will be added
  • Fill out TODO list steps
  • Describe requested feedback from reviewers on draft PR
  • Complete Section 7: New Model Checklist (if applicable)

TODO:

  • Step 1
  • Step 2

Type of Reviewer Feedback Requested (on Draft PR)

Structural feedback:

Implementation feedback:

Other feedback:

Section 3: General PR Checklist

  • PR description thoroughly describes the new feature, bug fix, etc.
  • Added tests for new functionality or bug fixes
  • Tests pass (If not, and this is expected, please elaborate in the Section 6: Test Results)
  • Documentation
    • Docstrings are up-to-date
    • Related docs/ files are up-to-date, or added when necessary
    • Documentation has been rebuilt successfully
    • Examples have been updated (if applicable)
  • CHANGELOG.md
    • At least one complete sentence has been provided to describe the changes made in this PR
    • After the above, a hyperlink has been provided to the PR using the following format:
      "A complete thought. [PR XYZ]((https://github.com/NatLabRockies/H2Integrate/pull/XYZ)", where
      XYZ should be replaced with the actual number.

Section 3: Related Issues

#355 and #508

Section 4: Impacted Areas of the Software

Section 4.1: New Files

None

Section 4.2: Modified Files

  • h2integrate/storage/hydrogen/h2_storage_cost.py
    • CompressedGasStorageCostModel: Models compressed gas h2 storage
    • HydrogenStorageBaseCostModelConfig: Added inlet_pressure_bar and storage_pressure_bar as fields to allow compressor in/out pressures to vary.
  • h2integrate/storage/hydrogen/h2_compression.py
    • Compressor: Split into pipeline and storage compressors
  • .gitignore: Not ignoring images within docs
  • Moved images for docs\storage\hydrogen_storage.md into the right folder so broken images aren't shown

Section 5: Additional Supporting Information

Section 6: Test Results, if applicable

Section 7 (Optional): New Model Checklist

  • Model Structure:
    • Follows established naming conventions outlined in docs/developer_guide/coding_guidelines.md
    • Used attrs class to define the Config to load in attributes for the model
      • If applicable: inherit from BaseConfig or CostModelBaseConfig
    • Added: initialize() method, setup() method, compute() method
      • If applicable: inherit from CostModelBaseClass
  • Integration: Model has been properly integrated into H2Integrate
    • Added to supported_models.py
    • If a new commodity_type is added, update create_financial_model in h2integrate_model.py
  • Tests: Unit tests have been added for the new model
    • Pytest-style unit tests
    • Unit tests are in a "test" folder within the folder a new model was added to
    • If applicable add integration tests
  • Example: If applicable, a working example demonstrating the new model has been created
    • Input file comments
    • Run file comments
    • Example has been tested and runs successfully in test_all_examples.py
  • Documentation:
    • Write docstrings using the Google style
    • Model added to the main models list in docs/user_guide/model_overview.md
      • Model documentation page added to the appropriate docs/ section
      • <model_name>.md is added to the _toc.yml

self,
p_outlet,
flow_rate_kg_d,
compressor_type="pipeline",
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The compressor cost model works different for pipeline compressors and storage compressors - see HDSAM, "Cost Data" tab, "Compressor Costs" section (lines 120-131)

@jmartin4u jmartin4u marked this pull request as ready for review April 16, 2026 17:56
Copy link
Copy Markdown
Collaborator

@elenya-grant elenya-grant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR Jonathan! This is looking awesome! I wanted to give some high-level feedback sooner rather than later but would like to do a more detailed review of the h2_storage_cost.py file and the h2_compression.py file. The doc pages look awesome - and the added cost model looks good I think it's hard with converting spreadsheet models to decide what should be hard-coded vs what should be user-configurable - so feel free to push back on any comments I have related to that!

Again - its looking great and although I'd like to do a more thorough review of two files that were primarily changed, I don't want to hold-up the PR if I can't get to it soon! Great work!

Comment thread h2integrate/storage/hydrogen/test/test_hydrogen_storage.py
Comment thread h2integrate/storage/hydrogen/test/test_hydrogen_storage.py Outdated
Comment thread h2integrate/storage/hydrogen/test/test_hydrogen_storage.py
Comment thread h2integrate/storage/hydrogen/h2_storage_cost.py Outdated
Comment thread h2integrate/storage/hydrogen/h2_storage_cost.py Outdated
Comment thread h2integrate/storage/hydrogen/h2_storage_cost.py Outdated
Comment thread h2integrate/storage/hydrogen/h2_storage_cost.py
Comment thread h2integrate/storage/hydrogen/h2_storage_cost.py
Copy link
Copy Markdown
Collaborator

@johnjasa johnjasa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks for this Jonathan! Really smooth addition and I appreciate your fantastic docs and clarity of where your numbers came from in HDSAM. Just some small notes, nothing major for sure. I do want @elenya-grant to re-review before we bring this in to make sure it's meeting her expectations.

## Cost Correlations
## Cost Correlations - Options 1-3

For the first three options (underground pipe, lined rock caverns, and salt caverns), cost correlations from [Papadias and Ahluwalia](https://doi.org/10.1016/j.ijhydene.2021.08.028) are used for capital cost calculation.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this citation addition!

Comment thread docs/storage/hydrogen_storage.md Outdated

The model uses the calculation in the HDSAM "Compressed Gas H2 Terminal" sheet.
Although HDSAM as a whole calculates the "Terminal capacity (kg/day)", and "Design terminal storage capacity (kg)" values from other sheets, our simplified CGT model instead takes these as inputs.
- "Terminal capacity (kg/day)" from HDSAM is, in our model, set by the maximum value of the `hydrogen_in` input
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor but maybe worth clarifying in the docs here; is it the max across a 24-hour timespan? Since the capacity is kg/day. Or is it the kg/hr amount multiplied by 24? I bet I'll find out shortly, but worth saying here imo

Copy link
Copy Markdown
Collaborator Author

@jmartin4u jmartin4u Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the max across the whole timeseries - happening in lines 614-617 of h2_storage_cost.py. Updating the docs text

Comment on lines +15 to +33
Attributes:
- max_capacity (float): Maximum storage capacity (kg)
- max_charge_rate (float): Maximum charging rate (kg/h)
- sizing_mode (str): Mode for sizing storage (auto or set)
- commodity_name (str): Name of the commodity
- commodity_rate_units (str): Units of the commodity
- cost_year (int): Year for cost calculations
- labor_rate (float): Labor rate for cost calculations
- insurance (float): Insurance cost as a fraction of total cost
- property_taxes (float): Property taxes as a fraction of total cost
- licensing_permits (float): Licensing and permits cost as a fraction of total cost
- compressor_om (float): Compressor operation and maintenance cost as a fraction of total cost
- facility_om (float): Facility operation and maintenance cost as a fraction of total cost
- inlet_pressure_bar (float): Inlet pressure for compressed gas storage (bar)
- storage_pressure_bar (float): Storage pressure for compressed gas storage (bar) - max 700
- cg_capex_per_kg_350_bar (float): Capital cost per kg for compressed gas storage at 350 bar
Default is $1200 (2013 dollars) from HDSAM, converted to 2018 dollars using CEPCI.
- cg_capex_per_kg_700_bar (float): Capital cost per kg for compressed gas storage at 700 bar
Default is $1800 (2013 dollars) from HDSAM, converted to 2018 dollars using CEPCI.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for cleaning this up!


commodity_name: str = field(default="hydrogen")
commodity_units: str = field(default="kg/h", validator=contains(["kg/h", "g/h", "t/h"]))
commodity_rate_units: str = field(default="kg/h", validator=contains(["kg/h", "g/h", "t/h"]))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marking this for @elenya-grant to review; does this jive with your desired usage of commodity_rate_units for storage? i.e. those are the kg/h units? Was this h2_storage_cost.py just not up-to-date with other naming conventions in H2I?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes - this one was not up-to-date and thanks Jonathan for updating it!

installed_capex = depreciable_capex + land_capex + other_capex

# ============================================================================
# Calculate OPEX - NEEDS TO BE UPDATED
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this "NEEDS TO BE UPDATED" note still relevant? part of this PR or follow-on work?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope - I put that there in an intermediate commit where I had just copy-pasted code from the geologic storage. Now it is updated, I'll remove the note

Copy link
Copy Markdown
Collaborator

@elenya-grant elenya-grant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Thanks for putting this together Jonathan! I pushed up a small change (I removed commodity_name from the config since it wasn't being used)

Copy link
Copy Markdown
Collaborator

@johnjasa johnjasa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, thanks for addressing those comments! 🎉

@johnjasa johnjasa merged commit a23ae26 into NatLabRockies:develop Apr 23, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants