Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
3ccb8e3
Add combustion turbine model
paulf81 Dec 17, 2025
b7b4696
add to hybrid plant
paulf81 Dec 17, 2025
0f65a52
add to utilities
paulf81 Dec 17, 2025
b9e8200
add first test
paulf81 Dec 17, 2025
9eb9535
add new example
paulf81 Dec 18, 2025
36d5493
add test dicts
paulf81 Dec 19, 2025
7cf9dca
Merge branch 'develop' into feature/add_ct
paulf81 Dec 22, 2025
24896c6
address comment
paulf81 Dec 22, 2025
1e386a1
standardize to min_stable_load_fraction
paulf81 Dec 22, 2025
cc58bd0
address comment
paulf81 Dec 22, 2025
dca6e13
clean up state_num error checks
paulf81 Dec 22, 2025
ce8d2c7
clean up step function
paulf81 Dec 22, 2025
494538d
add else case
paulf81 Dec 22, 2025
1bc2961
linting
paulf81 Dec 22, 2025
d75f6e0
fix long line
paulf81 Dec 22, 2025
eccc7a7
fix long line
paulf81 Dec 22, 2025
48594a7
fix comment
paulf81 Jan 30, 2026
8befd4d
adjust timing
paulf81 Jan 30, 2026
feaad7b
Add tests for Ct
paulf81 Jan 30, 2026
6537bb5
add combustion turbine docs
paulf81 Feb 2, 2026
5234a6d
Add 07 example
paulf81 Feb 2, 2026
eb56021
Merge branch 'develop' into feature/add_ct
paulf81 Feb 2, 2026
747a05d
remove combustion turbine model
paulf81 Feb 4, 2026
20e7b77
add thermal component base
paulf81 Feb 4, 2026
0f3870e
add tests
paulf81 Feb 4, 2026
c08227f
update h_dict
paulf81 Feb 4, 2026
bee19b2
linting
paulf81 Feb 4, 2026
6367251
add ocgt
paulf81 Feb 4, 2026
c3e2495
route ocgt
paulf81 Feb 4, 2026
c7d139c
rename example
paulf81 Feb 4, 2026
cf13402
linting
paulf81 Feb 4, 2026
e8b778b
update example 7
paulf81 Feb 4, 2026
bd367c6
update utilities
paulf81 Feb 4, 2026
5d20da4
bugfix
paulf81 Feb 4, 2026
0507d5d
add shell post-process test
paulf81 Feb 4, 2026
313a95f
update docs
paulf81 Feb 4, 2026
05cbc68
Merge branch 'develop' into pr/paulf81/189
paulf81 Feb 4, 2026
69b426a
Add 07 doc
paulf81 Feb 4, 2026
d5b2880
Update hercules/hybrid_plant.py
paulf81 Feb 4, 2026
f5551fe
Merge branch 'develop' into pr/paulf81/189
paulf81 Feb 4, 2026
8ab6150
harmonize comments
paulf81 Feb 4, 2026
5cca1bf
clarify comment
paulf81 Feb 4, 2026
84e1251
Fix comment
paulf81 Feb 4, 2026
055da8d
add warm start state and hard code start state time definitions
paulf81 Feb 5, 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
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_ocgt
66 changes: 66 additions & 0 deletions docs/examples/07_ocgt.md
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
121 changes: 121 additions & 0 deletions docs/open_cycle_gas_turbine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# 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. 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

In addition to the base class parameters, the OCGT model includes parameters for fuel consumption tracking:

| Parameter | Units | Default | Description |
|-----------|-------|---------|-------------|
| `part_load_factor` | dimensionless | 1.0 | Heat rate penalty at minimum load. Range: 1.0-2.0. A value of 1.0 means no penalty; higher values indicate decreased efficiency at part load |
| `heat_rate_at_rated_load` | kJ/kWh | 10000 | Fuel consumption rate at rated load |

## 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] |

## OCGT-Specific Outputs

In addition to the base class outputs (`power`, `state_num`), the OCGT model provides:

| Output | Units | Description |
|--------|-------|-------------|
| `fuel_consumption` | kJ | Fuel consumed during the timestep |
| `heat_rate` | kJ/kWh | Current heat rate (varies with load) |

### Heat Rate Calculation

The heat rate varies with load fraction to model part-load efficiency degradation:

- At rated load: `heat_rate = heat_rate_at_rated_load`
- At minimum load: `heat_rate = heat_rate_at_rated_load × part_load_factor`
- Between: Linear interpolation

Fuel consumption is calculated as:

$$
\text{fuel\_consumption} = \text{power} \times \text{heat\_rate} \times \frac{\Delta t}{3600}
$$

Where $\Delta t$ is the timestep in seconds.

## YAML Configuration

### Minimal Configuration

Only required parameters (uses all defaults):

```yaml
open_cycle_gas_turbine:
component_type: OpenCycleGasTurbine
rated_capacity: 100000 # kW (100 MW)
initial_conditions:
power: 0
state_num: 0 # 0 = off
```

### 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
part_load_factor: 1.25 # 25% heat rate penalty at min load
heat_rate_at_rated_load: 10000 # kJ/kWh at rated load
log_channels:
- power
- fuel_consumption
- state_num
- heat_rate
- power_setpoint
initial_conditions:
power: 0
state_num: 0 # 0 = off
```

## 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_num`: Operating state number (0-5)
- `fuel_consumption`: Fuel consumed per timestep in kJ
- `heat_rate`: Current heat rate in kJ/kWh
- `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.
Loading