Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
3ccb8e3
Add combustion turbine model
Dec 17, 2025
b7b4696
add to hybrid plant
Dec 17, 2025
0f65a52
add to utilities
Dec 17, 2025
b9e8200
add first test
Dec 17, 2025
9eb9535
add new example
Dec 18, 2025
36d5493
add test dicts
Dec 19, 2025
7cf9dca
Merge branch 'develop' into feature/add_ct
Dec 22, 2025
24896c6
address comment
Dec 22, 2025
1e386a1
standardize to min_stable_load_fraction
Dec 22, 2025
cc58bd0
address comment
Dec 22, 2025
dca6e13
clean up state_num error checks
Dec 22, 2025
ce8d2c7
clean up step function
Dec 22, 2025
494538d
add else case
Dec 22, 2025
1bc2961
linting
Dec 22, 2025
d75f6e0
fix long line
Dec 22, 2025
eccc7a7
fix long line
Dec 22, 2025
48594a7
fix comment
Jan 30, 2026
8befd4d
adjust timing
Jan 30, 2026
feaad7b
Add tests for Ct
Jan 30, 2026
6537bb5
add combustion turbine docs
Feb 2, 2026
5234a6d
Add 07 example
Feb 2, 2026
eb56021
Merge branch 'develop' into feature/add_ct
Feb 2, 2026
747a05d
remove combustion turbine model
Feb 4, 2026
20e7b77
add thermal component base
Feb 4, 2026
0f3870e
add tests
Feb 4, 2026
c08227f
update h_dict
Feb 4, 2026
bee19b2
linting
Feb 4, 2026
6367251
add ocgt
Feb 4, 2026
c3e2495
route ocgt
Feb 4, 2026
c7d139c
rename example
Feb 4, 2026
cf13402
linting
Feb 4, 2026
e8b778b
update example 7
Feb 4, 2026
bd367c6
update utilities
Feb 4, 2026
5d20da4
bugfix
Feb 4, 2026
0507d5d
add shell post-process test
Feb 4, 2026
313a95f
update docs
Feb 4, 2026
05cbc68
Merge branch 'develop' into pr/paulf81/189
Feb 4, 2026
69b426a
Add 07 doc
Feb 4, 2026
d5b2880
Update hercules/hybrid_plant.py
Feb 4, 2026
f5551fe
Merge branch 'develop' into pr/paulf81/189
Feb 4, 2026
8ab6150
harmonize comments
Feb 4, 2026
5cca1bf
clarify comment
Feb 4, 2026
84e1251
Fix comment
Feb 4, 2026
055da8d
add warm start state and hard code start state time definitions
Feb 5, 2026
07818bf
refactor from heat_rate to efficiency
Feb 7, 2026
96ed0ee
add tests
Feb 7, 2026
bb2b22b
update test defaults
Feb 7, 2026
ffb5f53
linting
Feb 7, 2026
4a50d3a
start shutdown behavior within on state
Feb 7, 2026
77b0db7
Fix test
Feb 7, 2026
6aaef2c
docstring fix
Feb 7, 2026
43b5d03
add limit to run up ramp
Feb 7, 2026
fa6befe
remove redundant line
Feb 7, 2026
9745eaa
Update tests/thermal_component_base_test.py
Feb 7, 2026
0aa3188
Merge branch 'feature/add_ct' of github.com:paulf81/hercules into pr/…
Feb 7, 2026
1480166
clearer controller name
Feb 7, 2026
7ce14ad
Update tests/thermal_component_base_test.py
Feb 9, 2026
dc2853a
Update examples/07_ocgt/hercules_input.yaml
Feb 9, 2026
5b89a94
Refactor states to an enum
Feb 10, 2026
8a27cfb
Remove .value
Feb 10, 2026
d9c058b
Change initial condition behavior
Feb 10, 2026
4bea937
rename fuel values
Feb 10, 2026
edaa598
Refactor to rate
Feb 10, 2026
ad8d6f2
specify effiency in HHV and provide defaults
Feb 10, 2026
eff4d9a
rename example 7
Feb 10, 2026
0af88bd
linting
Feb 10, 2026
48d5778
remove get initial conditions
Feb 10, 2026
65c45ab
add get initial conditions to base class
Feb 10, 2026
315c208
remove state names property
Feb 10, 2026
f652bc6
Make component_name and types to be class attributes
Feb 10, 2026
603e372
rename calc functions
Feb 10, 2026
53343b2
Update with minor notes on specific turbine
genevievestarke Feb 17, 2026
314fec2
Fix ruff formatting
genevievestarke Feb 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions docs/_static/thermal_startup_ramp.svg
Copy link
Collaborator

Choose a reason for hiding this comment

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

What is the _static/ folder for? Not something I'm familiar with

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I understand this is the conventional place to put images when building docs with jupyter-book

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions docs/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ parts:
- file: solar_pv
- file: battery
- file: electrolyzer
- file: thermal_component_base
- file: open_cycle_gas_turbine
- caption: Inputs
chapters:
- file: hercules_input
Expand All @@ -43,3 +45,4 @@ parts:
- file: examples/04_wind_and_storage
- file: examples/05_wind_and_storage_with_lmp
- file: examples/06_wind_and_hydrogen
- file: examples/07_open_cycle_gas_turbine
66 changes: 66 additions & 0 deletions docs/examples/07_open_cycle_gas_turbine.md
Copy link
Collaborator

Choose a reason for hiding this comment

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

Consider naming this, as well as the actual example directory, open_cycle_gas_turbine for clarity

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Renaming the example now

Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Example 07: Open Cycle Gas Turbine (OCGT)

## Description

This example demonstrates a standalone open-cycle gas turbine (OCGT) simulation. The example showcases the turbine's state machine behavior including startup sequences, power ramping, minimum stable load constraints, and shutdown sequences.

For details on OCGT parameters and configuration, see {doc}`../open_cycle_gas_turbine`. For details on the underlying state machine and ramp behavior, see {doc}`../thermal_component_base`.

## Scenario

The simulation runs for 6 hours with 1-minute time steps. A controller commands the turbine through several operating phases. The table below shows both **control commands** (setpoint changes) and **state transitions** (responses to commands based on constraints).

### Timeline

| Time (min) | Event Type | Setpoint | State | Description |
|------------|------------|----------|-------|-------------|
| 0 | Initial | 0 | OFF (0) | Turbine starts off, `time_in_state` begins counting |
| 40 | Command | → 100 MW | OFF (0) | Setpoint changes to full power, but `min_down_time` (60 min) not yet satisfied—turbine remains off |
| 60 | State | 100 MW | → HOT STARTING (1) | `min_down_time` satisfied, turbine begins hot starting sequence |
| ~64 | State | 100 MW | HOT STARTING (1) | `hot_readying_time` (~4.2 min) complete, run-up ramp begins |
| ~68 | State | 100 MW | → ON (4) | Power reaches P_min (20 MW) after `hot_startup_time` (~8.2 min), turbine now operational |
| ~76 | Ramp | 100 MW | ON (4) | Power reaches 100 MW (ramped at 10 MW/min from P_min) |
| 120 | Command | → 50 MW | ON (4) | Setpoint reduced to 50% capacity |
| ~125 | Ramp | 50 MW | ON (4) | Power reaches 50 MW (ramped down at 10 MW/min) |
| 180 | Command | → 10 MW | ON (4) | Setpoint reduced to 10% (below P_min), power clamped to P_min |
| ~183 | Ramp | 10 MW | ON (4) | Power reaches P_min (20 MW), cannot go lower |
| 210 | Command | → 100 MW | ON (4) | Setpoint increased to full power |
| ~218 | Ramp | 100 MW | ON (4) | Power reaches 100 MW |
| 240 | Command + State | → 0 | → STOPPING (5) | Shutdown command; `min_up_time` satisfied (~172 min on), begins stopping sequence |
| ~250 | State | 0 | → OFF (0) | Power reaches 0 (ramped down at 10 MW/min), turbine off |
| 360 | End | 0 | OFF (0) | Simulation ends |

### Key Behaviors Demonstrated

- **Minimum down time**: The turbine cannot start until `min_down_time` (60 min) is satisfied, even though the command is issued at 40 min
- **Hot startup sequence**: After `min_down_time`, the turbine enters HOT STARTING, waits through `hot_readying_time`, then ramps to P_min using `run_up_rate`
- **Ramp rate constraints**: All power changes in ON state are limited by `ramp_rate` (10 MW/min)
- **Minimum stable load**: When commanded to 10 MW (below P_min = 20 MW), power is clamped to P_min
- **Minimum up time**: Shutdown is allowed immediately at 240 min because `min_up_time` (60 min) was satisfied long ago
- **Stopping sequence**: The turbine ramps down to zero at `ramp_rate` before transitioning to OFF

## Setup

No manual setup is required. The example uses only the OCGT component which requires no external data files.

## Running

To run the example, execute the following command in the terminal:

```bash
python hercules_runscript.py
```

## Outputs

To plot the outputs, run:

```bash
python plot_outputs.py
```

The plot shows:
- Power output over time (demonstrating ramp constraints and minimum stable load)
- Operating state transitions
- Fuel consumption tracking
- Heat rate variation with load
162 changes: 162 additions & 0 deletions docs/open_cycle_gas_turbine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# Open Cycle Gas Turbine

The `OpenCycleGasTurbine` class models an open-cycle gas turbine (OCGT), also known as a peaker plant or simple-cycle gas turbine. Since this class is focused on peaker plant behavior, this class was developed based on aeroderivative engines. It is a subclass of {doc}`ThermalComponentBase <thermal_component_base>` and inherits all state machine behavior, ramp constraints, and operational logic from the base class.

For details on the state machine, startup/shutdown behavior, and base parameters, see {doc}`thermal_component_base`.

## OCGT-Specific Parameters

The OCGT class provides default values for natural gas properties from [6]:

| Parameter | Units | Default | Description |
|-----------|-------|---------|-------------|
| `hhv` | J/m³ | 39050000 | Higher heating value of natural gas (39.05 MJ/m³) [6] |
| `fuel_density` | kg/m³ | 0.768 | Fuel density for mass calculations [6] |

The `efficiency_table` parameter is **optional**. If not provided, default values based on approximate readings from the SC1A curve in Exhibit ES-4 of [5] are used. All efficiency values are **HHV (Higher Heating Value) net plant efficiencies**. See {doc}`thermal_component_base` for details on the efficiency table format.

## Default Parameter Values

The `OpenCycleGasTurbine` class provides default values for base class parameters based on References [1-5]. Only `rated_capacity` and `initial_conditions` are required in the YAML configuration.

| Parameter | Default Value | Source |
|-----------|---------------|--------|
| `min_stable_load_fraction` | 0.40 (40%) | [4] |
| `ramp_rate_fraction` | 0.10 (10%/min) | [1] |
| `run_up_rate_fraction` | Same as `ramp_rate_fraction` | — |
| `hot_startup_time` | 420 s (7 minutes) | [1], [5] |
| `warm_startup_time` | 480 s (8 minutes) | [1], [5] |
| `cold_startup_time` | 480 s (8 minutes) | [1], [5] |
| `min_up_time` | 1800 s (30 minutes) | [4] |
| `min_down_time` | 3600 s (1 hour) | [4] |
| `hhv` | 39050000 J/m³ (39.05 MJ/m³) | [6] |
| `fuel_density` | 0.768 kg/m³ | [6] |
| `efficiency_table` | SC1A HHV net efficiency (see below) | Exhibit ES-4 of [5] |

### Default Efficiency Table

The default HHV net plant efficiency table is based on approximate readings from the SC1A (simple cycle) curve in Exhibit ES-4 of [5]:

| Power Fraction | HHV Net Efficiency |
|---------------|-------------------|
| 1.00 | 0.39 (39%) |
| 0.75 | 0.37 (37%) |
| 0.50 | 0.325 (32.5%) |
| 0.25 | 0.245 (24.5%) |

## OCGT Outputs

The OCGT model provides the following outputs (inherited from base class):

| Output | Units | Description |
|--------|-------|-------------|
| `power` | kW | Actual power output |
| `state` | integer | Operating state number (0-5), corresponding to the `STATES` enum |
| `efficiency` | fraction (0-1) | Current HHV net plant efficiency |
| `fuel_volume_rate` | m³/s | Fuel volume flow rate |
| `fuel_mass_rate` | kg/s | Fuel mass flow rate (computed using `fuel_density` [6]) |

### Efficiency and Fuel Rate

HHV net plant efficiency varies with load based on the `efficiency_table`. The fuel volume rate is calculated as:

$$
\text{fuel\_volume\_rate} = \frac{\text{power}}{\text{efficiency} \times \text{hhv}}
$$

Where:
- `power` is in W (converted from kW internally)
- `efficiency` is the HHV net efficiency interpolated from the efficiency table
- `hhv` is the higher heating value in J/m³ (default 39.05 MJ/m³ for natural gas [6])
- Result is fuel volume rate in m³/s

The fuel mass rate is then computed from the volume rate using the fuel density [6]:

$$
\text{fuel\_mass\_rate} = \text{fuel\_volume\_rate} \times \text{fuel\_density}
$$

Where:
- `fuel_volume_rate` is in m³/s
- `fuel_density` is in kg/m³ (default 0.768 kg/m³ for natural gas [6])
- Result is fuel mass rate in kg/s

## YAML Configuration

### Minimal Configuration

Required parameters only (uses defaults for `hhv`, `efficiency_table`, and other parameters):

```yaml
open_cycle_gas_turbine:
component_type: OpenCycleGasTurbine
rated_capacity: 100000 # kW (100 MW)
initial_conditions:
power: 0 # 0 kW means OFF; power > 0 means ON
```

### Full Configuration

All parameters explicitly specified:

```yaml
open_cycle_gas_turbine:
component_type: OpenCycleGasTurbine
rated_capacity: 100000 # kW (100 MW)
min_stable_load_fraction: 0.4 # 40% minimum operating point
ramp_rate_fraction: 0.1 # 10%/min ramp rate
run_up_rate_fraction: 0.05 # 5%/min run up rate
hot_startup_time: 420.0 # 7 minutes
warm_startup_time: 480.0 # 8 minutes
cold_startup_time: 480.0 # 8 minutes
min_up_time: 1800 # 30 minutes
min_down_time: 3600 # 1 hour
hhv: 39050000 # J/m³ for natural gas (39.05 MJ/m³) [6]
fuel_density: 0.768 # kg/m³ for natural gas [6]
efficiency_table:
power_fraction:
- 1.0
- 0.75
- 0.50
- 0.25
efficiency: # HHV net plant efficiency from SC1A in Exhibit ES-4 of [5]
- 0.39
- 0.37
- 0.325
- 0.245
log_channels:
- power
- fuel_volume_rate
- fuel_mass_rate
- state
- efficiency
- power_setpoint
initial_conditions:
power: 0 # 0 kW means OFF; power > 0 means ON
```

## Logging Configuration

The `log_channels` parameter controls which outputs are written to the HDF5 output file.

**Available Channels:**
- `power`: Actual power output in kW (always logged)
- `state`: Operating state number (0-5), corresponding to the `STATES` enum
- `fuel_volume_rate`: Fuel volume flow rate in m³/s
- `fuel_mass_rate`: Fuel mass flow rate in kg/s (computed using `fuel_density` [6])
- `efficiency`: Current HHV net plant efficiency (0-1)
- `power_setpoint`: Requested power setpoint in kW

## References

1. Agora Energiewende (2017): "Flexibility in thermal power plants - With a focus on existing coal-fired power plants."

2. "Impact of Detailed Parameter Modeling of Open-Cycle Gas Turbines on Production Cost Simulation", NREL/CP-6A40-87554, National Renewable Energy Laboratory, 2024.

3. Deane, J.P., G. Drayton, and B.P. Ó Gallachóir. "The Impact of Sub-Hourly Modelling in Power Systems with Significant Levels of Renewable Generation." Applied Energy 113 (January 2014): 152–58. https://doi.org/10.1016/j.apenergy.2013.07.027.

4. IRENA (2019), Innovation landscape brief: Flexibility in conventional power plants, International Renewable Energy Agency, Abu Dhabi.

5. M. Oakes, M. Turner, "Cost and Performance Baseline for Fossil Energy Plants, Volume 5: Natural Gas Electricity Generating Units for Flexible Operation," National Energy Technology Laboratory, Pittsburgh, May 5, 2023.

6. I. Staffell, "The Energy and Fuel Data Sheet," University of Birmingham, March 2011. https://claverton-energy.com/cms4/wp-content/uploads/2012/08/the_energy_and_fuel_data_sheet.pdf
Loading