Skip to content

Add multi-unit combined cycle gas turbine component#232

Open
jfrederik-nrel wants to merge 59 commits into
NatLabRockies:developfrom
jfrederik-nrel:feature/mu_ccgt
Open

Add multi-unit combined cycle gas turbine component#232
jfrederik-nrel wants to merge 59 commits into
NatLabRockies:developfrom
jfrederik-nrel:feature/mu_ccgt

Conversation

@jfrederik-nrel
Copy link
Copy Markdown
Collaborator

@jfrederik-nrel jfrederik-nrel commented Mar 7, 2026

Work in progress. Still to do:

  • Merge latest version of feature/mm-thermal back in
  • Execute sanity check of the control logic
  • Clean up code, ruff
  • Complete the example, possibly merge with existing example
  • Write documentation
  • Add tests

No reviews necessary yet at this time.

dzalkind and others added 29 commits March 4, 2026 14:37
This reverts commit 71f3c90, reversing
changes made to bb51e82.
@misi9170 misi9170 mentioned this pull request Mar 9, 2026
Comment thread docs/_toc.yml
Comment thread examples/07_open_cycle_gas_turbine/hercules_runscript.py Outdated
Comment thread examples/07_thermal_plants/hercules_runscript.py
"For the combined cycle plant, one of the units must be an open cycle gas turbine."
)

if len(generic_units) != 2:
Copy link
Copy Markdown
Collaborator

@dzalkind dzalkind Mar 19, 2026

Choose a reason for hiding this comment

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

We may want to relax this constraint in some cases in the future, where multiple gas generators could be combined to feed a steam unit. We can probably work around this for now.

Will the code break in this case? I'm not sure we should change it now, but it might be good to know in the future.

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 thinking about that too. What I think I will try to do on the short term (though perhaps not in this PR) is allow at least 2 (or perhaps more? From what I can find, 2 is currently the max) gas units powering a single steam unit. I don't think that would break anything, but definitely not excluding the possibility that it causes complications that I'm currently not overseeing.


# Update h_dict with outputs
h_dict[self.component_name]["power"] = self.power_output
# h_dict[self.component_name]["state"] = self.state.value
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.

Do you want the state or is it not needed because each unit has its own state?

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.

Each unit has it's own state. We would need to define a new state machine for the combined unit as it has complicated combined states like "gas turbine on, steam turbine off". I refrained from doing that and just left it at each unit having its own state

return h_dict

def control(self, power_setpoint):
""""""
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.

Maybe denote that this is the control of the combined plant?

1 - self.gas_power_ratio
) * power_setpoint

# TODO: we probably want to add an actual controller for the gas turbine
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 looks like you did this TODO?

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.

No I didn't. I meant that right now it uses the basic _control logic defined in the thermal_component_base class, as there is no control method defined in the open_cycle_gas_turbine class. What I meant here is that we might want to add that at some point, or else rename _control in thermal_component_base to control.

Copy link
Copy Markdown
Collaborator

@dzalkind dzalkind left a comment

Choose a reason for hiding this comment

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

Overall, this looks good to me. Nice job!

I like the power set point input addition. It might be nice to have that documented for future reference, along with making sure your new docs are included.

Otherwise, I left some small comments in the files; they are pretty minor and often for my understanding.

@jfrederik-nrel
Copy link
Copy Markdown
Collaborator Author

@dzalkind it should follow #224. #225 is related, but a stand-alone PR I'd say.

I merged #224 into this branch recently, so I don't expect any major merge conflicts.

Added the missing combined_cycle_plant doc.

@genevievestarke
Copy link
Copy Markdown
Collaborator

Ok, I've merged in develop but I have a few questions:

  1. We now have a hard_coal_steam_turbine model and a steam_turbine model. Are these two meaningfully different?
  2. There's some code on lines 632-638 in thermal_component_base.py that I've commented out that I'm not sure if we need anymore. @jfrederik-nrel, could you take a look at that

@jfrederik-nrel
Copy link
Copy Markdown
Collaborator Author

@genevievestarke

  1. They can probably be merged at some point, I agree. I created the class steam_turbine since I think the other class didn't exist yet when I started, and then it didn't seem applicable for the purpose of the multi-unit CCGT since it doesn't use hard coal as fuel. So I think we can probably remove the current steam_turbine model and rename the hard_coal_steam_turbine model to steam_turbine, while keeping everything in it the same. Do you want me to do that and check to see if that breaks anything?
  2. I think you're right that it can be removed because the exception is now captured in calculate_fuel_volume_rate.

@genevievestarke
Copy link
Copy Markdown
Collaborator

For #1, that would be great!

Also, there are two example 07s now, so I'll take a look at that, as well.


Similar to the `ThermalPlant` class, the `CombinedCyclePlant` class does not have many default parameters. Key attributes that must be provided in the YAML configuration file are the `OpenCycleGasTurbine` and `SteamTurbine` `units`, which is a list that is used to instantiate the individual thermal units that make up the plant, and `unit_names`, which is a list of unique names for each unit. The number of entries in `units` and `unit_names` must match.

However, unlike the base `ThermalPlant` class, it is recommended that some parameters are defined outside the individual thermal units. Since the gas turbine does not have its own individual fuel source, instead using the rest heat from gas turbine, it is not possible to specify the efficiency and fuel consumption of the steam turbine in the same way as done for individual components that are not linked. As a result, these outputs are instead calculated for the plant as a whole, necessitating an efficiency table for the unit as a whole. Note that this table is only used when both the gas and steam turbine are running. If only the gas turbine is running, the `OpenCycleGasTurbine` efficiency table is used instead.
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.

@jfrederik-nrel in the second sentence, should it be steam turbine first?

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 yaml file should contain a unit of OCGT and a unit of ST. The order doesn't matter, if I understand your question correctly.

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.

Ah, I'm specifically asking about the wording of the documentation: "Since the gas turbine does not have its own individual fuel source, instead using the rest heat from gas turbine, ..."
This sounds like one of the gas turbine references should be referring to the steam turbine?

Genevieve Starke added 2 commits June 2, 2026 17:28
Copy link
Copy Markdown
Collaborator

@genevievestarke genevievestarke left a comment

Choose a reason for hiding this comment

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

Really good work @jfrederik-nrel ! I just had a question about whether you can simulate multiple combined cycle units in the same plant or not? To create a whole plant, do you just scale the OCGT rating and the ST rating to account for all the units in the plant?


###
# Describe this simulation setup
description: Combined Cycle Gas Turbine (CCGT) Example
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 the current implementation simulating just one OCGT+ST? Can you simulate multiples of these pairs? It seems like only one can be defined per CombinedCyclePlant. If you can assign multiples of these in the multi-unit plant, then maybe CombinedCycleUnit would be a better name?

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.

Currently, you can only have one OCGT+ST, so yes, you would need to scale them to model a more complicated setup that for example has two steam turbines (which I do think is actually relatively common). I did consider making it generalizable, but this would severely complicate the control logic as there are many ways the different units could be linked. I therefore chose to keep it simple for now and stick to a single OCGT+ST setup. The nomenclature doesn't seem overly important to me personally, but if you want to change the name to CombinedCycleUnit, I won't fight you on it.

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.

Ok, since it's meant to represent the whole plant, I'll keep it as is for now!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants