Skip to content

Thermodynamic NGCT model - #805

Open
cfrontin wants to merge 31 commits into
NatLabRockies:developfrom
cfrontin:feature/thermodynamic_NGCT_model
Open

Thermodynamic NGCT model#805
cfrontin wants to merge 31 commits into
NatLabRockies:developfrom
cfrontin:feature/thermodynamic_NGCT_model

Conversation

@cfrontin

@cfrontin cfrontin commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Thermodynamic models for NGCT (w/ support for future combustion_machines)

The performance of combustion machines, including both combustion turbines, combined cycle turbines, and reciprocating internal combustion engines, has significant dependence on ambient conditions (real time and design-specified).

These models use standard thermodynamic cycles to increase the fidelity of ICE combustion systems in H2I. These are critical for understanding complementarity of renewables and fuel combustion systems in hybrid energy generation, where ambient conditions determine the performance of nominally firm power sources as well as renewables, often in mutually complimentary ways.

Demonstration of code addendum showing diurnal and seasonal performance cycles as a function of ambient pressure and temperature.

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:

  • remove debug runner script
  • add upgraded cost model w/ fuel-consumption driven costs
  • develop example case(s)

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 4: Related Issues

Section 5: Impacted Areas of the Software

Section 5.1: New Files

  • h2integrate/converters/combustion_machines/__init__.py
    • allow import
  • h2integrate/converters/combustion_machines/NGCT_thermo_model.py
    • isolate thermodynamic modeling for independent testing w.r.t. H2I wrapper
  • h2integrate/converters/combustion_machines/test_NGCT_thermo_model.py
    • isolated testing for purely single-system thermodynamic modeling
  • h2integrate/converters/combustion_machines/turbine_simple_cycle.py
    • the H2I wrapper for the NGCT model

Section 5.2: Modified Files

  • h2integrate/core/supported_models.py
    • added new converter performance & cost model

Section 6: Additional Supporting Information

Section 7: Test Results, if applicable

Section 8 (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
    • Run generate_class_hierarchy.py to update the class hierarchy diagram in docs/developer_guide/class_structure.md

@cfrontin cfrontin changed the title Feature/thermodynamic ngct model Thermodynamic NGCT model Jul 20, 2026
@jaredthomas68
jaredthomas68 self-requested a review July 20, 2026 20:43
Comment thread pyproject.toml
Comment thread pyproject.toml Outdated

@kbrunik kbrunik left a comment

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.

@cfrontin this is super exciting stuff, I like the linking of resource data to other models that have been rather simplistically modeled up to this point. I left a few comments and thoughts, but overall, it's really great

Comment thread h2integrate/converters/combustion_machines/thermo_tools.py Outdated
Comment thread h2integrate/converters/combustion_machines/thermo_tools.py


@define(kw_only=True)
class SimpleCycleTurbinePerformanceConfig(BaseConfig):

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.

It seems useful to add design_conditions as an input to the config to be able to use all of the functionality of the NGCT model

return float(np.min(mass_flowrate_candidates))


class GE_7FA05_NGCT(NGCT):

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.

I'd be inclined to see the GE_7FA05_NGCT and GE_7EA_NGCT_2014 classes be converted to yaml files for easy inclusion when running the SimpleCycleTurbinePerformanceModel. It seems right now their functionality is limited to this particular file and not as something that would be able to be used within the larger H2I system.

Comment thread h2integrate/converters/combustion_machines/turbine_simple_cycle.py Outdated
Comment thread h2integrate/converters/combustion_machines/turbine_simple_cycle.py Outdated
Q_fluid_max=1.0, # (explicitly) unit-mass analysis
)

# try to run NGCT cycle here expensively, and all compute variations

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 there that big of a computational advantage precomputing this in the setup method versus using the given temperature and pressure data based on the solar resource in the actual compute method? It seems slightly redundant but maybe I'm missing something?

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.

yes! I was surprised to see that there was a significant speedup but there are a lot of chemical property lookups that are a function of the ambient conditions (typically unique per timestep). once those are done, they don't change as a function of the throttled mass flow, although this is a simplified model of throttled flow and it's likely better to include a plenum pressure drop to be slightly more accurate (which would necessitate moving away from precomputation but introduces a lot more complexity in how the compute stage would have to operate). anyway this is way too much info but I think this is the best way to do it for now.

Comment thread h2integrate/converters/combustion_machines/turbine_simple_cycle.py Outdated
Comment thread h2integrate/converters/combustion_machines/turbine_simple_cycle.py Outdated

@elenya-grant elenya-grant left a comment

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.

This is just a partial review that I wanted to submit before reviewing the whole thing! Mostly had minor questions and suggestions! I can do a more full review later!

Comment thread h2integrate/converters/combustion_machines/turbine_simple_cycle.py Outdated
Comment thread h2integrate/converters/combustion_machines/turbine_simple_cycle.py Outdated
Comment on lines +143 to +149
self.ngct = NGCT.NGCT(
ratio_P=self.config.pressure_ratio,
Trel_firing=self.config.firing_temp_C,
isentropic_efficiency_compressor=self.config.isentropic_efficiency_compressor,
isentropic_efficiency_turbine=self.config.isentropic_efficiency_turbine,
Q_fluid_max=1.0, # (explicitly) unit-mass analysis
)

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.

would any of the inputs to NGCT be optimization variables or swept in a parameter sweep for any foreseeable use-case? If so - then I think these should be inputs and then this could be moved to the compute() method.

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.

I didn't see these as being really in-scope as design variables for optimization ever and it's hard to see where they'd be used for a parameter sweep? they're kind of firing temp is limited by metallurgical considerations and the pressure ratio is a fairly fixed thing, it lives in a really tight window and is limited by specific design details of the engine

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 one piece we might want to understand is the questions of like "if we could improve the fundamental science of a combustion turbine by x what is the fleet-scale benefit?" but idk that our modeling is detailed enough to really dig in that far


# extract from the solar resource data
temperature_degC = discrete_inputs["solar_resource_data"]["temperature"]
pressure_Pa = (

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.

I think the pressure data output by the solar resource data defaults to mbar - not hPa?

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.

1 mbar == 1 hPa, iirc

Comment thread h2integrate/converters/combustion_machines/turbine_simple_cycle.py Outdated
Comment thread h2integrate/converters/combustion_machines/turbine_simple_cycle.py Outdated
Comment on lines +151 to +165
# try to run NGCT cycle here expensively, and all compute variations
# should be derivable w/o major new computation after that
P_ambient = 101325.0 # Pa
T_ambient = 15.0 # °C
self.working_fluid = NGCT.pyfluids.Fluid(NGCT.pyfluids.FluidsList.Air)
wx_data = [(T_ambient, P_ambient)]
self.wx_checksums = [hash(wxd) for wxd in wx_data]
self.ambient_fluid_list = [
self.working_fluid.with_state(
NGCT.pyfluids.Input.pressure(P),
NGCT.pyfluids.Input.temperature(T),
)
for T, P in wx_data
]
self.fundamental_cycle = self.ngct.run_turbine_model(self.ambient_fluid_list)

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.

I'm confused by this comment and the code itself. If the first run is always with the ambient temperature and pressure - then the self.wx_checksums and wx_checksums will always be different the first time compute() is called. Why not just initialize the self.wx_checksums to a list of empty strings or Nones and not run the NGCT model in the setup() method?

Comment thread h2integrate/converters/combustion_machines/turbine_simple_cycle.py Outdated
@cfrontin
cfrontin marked this pull request as ready for review August 13, 2026 17:18
@johnjasa
johnjasa marked this pull request as draft August 13, 2026 17:48
@johnjasa
johnjasa marked this pull request as ready for review August 13, 2026 17:48
@cfrontin
cfrontin marked this pull request as draft August 13, 2026 17:50
@cfrontin
cfrontin marked this pull request as ready for review August 13, 2026 21:21
@cfrontin
cfrontin marked this pull request as draft August 13, 2026 22:21
@cfrontin
cfrontin marked this pull request as ready for review August 13, 2026 22:21
@cfrontin
cfrontin marked this pull request as draft August 14, 2026 18:39
@cfrontin
cfrontin marked this pull request as ready for review August 14, 2026 18:39
@cfrontin
cfrontin marked this pull request as draft August 14, 2026 18:40
@cfrontin
cfrontin marked this pull request as ready for review August 14, 2026 18:41
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.

4 participants