Skip to content

Commit a2ec378

Browse files
authored
Merge pull request #1588 from NREL-Sienna/claude/update-hydro-docs-018cNnYDJhiyaEHCsTJbcWeJ
Update hydro datasets documentation
2 parents a344b01 + eafffa0 commit a2ec378

File tree

2 files changed

+263
-6
lines changed

2 files changed

+263
-6
lines changed

docs/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ TypeTree = "04da0e3b-1cad-4b2c-a963-fc1602baf1af"
1717

1818
[compat]
1919
CSV = "~0.10"
20-
Documenter = "^1.5"
20+
Documenter = "=1.15.0"
2121
julia = "^1.10"

docs/src/how_to/create_hydro_datasets.md

Lines changed: 262 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
In the current version of `PowerSystems.jl` there is support and testing for hydropower generation plants with the following structures:
44

5-
## Shared upstream reservoir
5+
## Shared Upstream Reservoir
66

77
```mermaid
88
flowchart TB
@@ -18,13 +18,127 @@ flowchart TB
1818
1919
```
2020

21-
For this model, attach an upstream [`HydroReservoir`](@ref) to any number of [`HydroTurbine`](@ref)s. This can model different power house elevations to consider the effect of the elevation and pressure heads
22-
on the specific turbines inside of a power plant.
21+
For this model, attach an upstream [`HydroReservoir`](@ref) to any number of [`HydroTurbine`](@ref)s. This can model different power house elevations to consider the effect of the elevation and pressure heads on the specific turbines inside of a power plant.
22+
23+
### Example: Single Turbine with Single Reservoir
24+
25+
```julia
26+
using PowerSystems
27+
const PSY = PowerSystems
28+
29+
# Create a system
30+
sys = System(100.0)
31+
set_units_base_system!(sys, "NATURAL_UNITS")
32+
33+
# Create and add a bus
34+
bus = ACBus(;
35+
number = 1,
36+
name = "bus1",
37+
available = true,
38+
bustype = ACBusTypes.PV,
39+
angle = 0.0,
40+
magnitude = 1.0,
41+
voltage_limits = (min = 0.9, max = 1.1),
42+
base_voltage = 230.0,
43+
area = nothing,
44+
load_zone = nothing,
45+
)
46+
add_component!(sys, bus)
47+
48+
# Create a HydroTurbine
49+
turbine = HydroTurbine(;
50+
name = "Turbine1",
51+
available = true,
52+
bus = bus,
53+
active_power = 50.0,
54+
reactive_power = 10.0,
55+
rating = 100.0,
56+
base_power = 100.0,
57+
active_power_limits = (min = 10.0, max = 100.0),
58+
reactive_power_limits = (min = -50.0, max = 50.0),
59+
powerhouse_elevation = 500.0, # meters above sea level
60+
efficiency = 0.9,
61+
conversion_factor = 1.0,
62+
outflow_limits = (min = 0.0, max = 1000.0), # m³/s
63+
travel_time = 0.5, # hours
64+
)
65+
add_component!(sys, turbine)
66+
67+
# Create a HydroReservoir
68+
reservoir = HydroReservoir(;
69+
name = "Reservoir1",
70+
available = true,
71+
storage_level_limits = (min = 1000.0, max = 10000.0), #
72+
initial_level = 0.8, # 80% of max
73+
spillage_limits = (min = 0.0, max = 500.0),
74+
inflow = 100.0, # m³/h
75+
outflow = 50.0, # m³/h
76+
level_targets = 0.7,
77+
intake_elevation = 600.0, # meters above sea level
78+
head_to_volume_factor = LinearCurve(1.0),
79+
)
80+
add_component!(sys, reservoir)
81+
82+
# Link the turbine to the reservoir as a downstream turbine
83+
set_downstream_turbine!(reservoir, turbine)
84+
85+
# Verify the connection
86+
@assert has_downstream_turbine(reservoir, turbine)
87+
@assert length(get_connected_head_reservoirs(sys, turbine)) == 1
88+
```
89+
90+
### Example: Multiple Turbines with Single Reservoir
91+
92+
```julia
93+
94+
sys = System(100.0)
95+
set_units_base_system!(sys, "NATURAL_UNITS")
96+
97+
# Create and add a bus
98+
bus = ACBus(;
99+
number = 1,
100+
name = "bus1",
101+
available = true,
102+
bustype = ACBusTypes.PV,
103+
angle = 0.0,
104+
magnitude = 1.0,
105+
voltage_limits = (min = 0.9, max = 1.1),
106+
base_voltage = 230.0,
107+
area = nothing,
108+
load_zone = nothing,
109+
)
110+
add_component!(sys, bus)
111+
# Create multiple turbines and connect them to a single reservoir
112+
turbines = []
113+
for i in 1:5
114+
turbine = HydroTurbine(;
115+
name = "Turbine$i",
116+
available = true,
117+
bus = bus,
118+
active_power = 20.0,
119+
reactive_power = 5.0,
120+
rating = 50.0,
121+
base_power = 100.0,
122+
active_power_limits = (min = 5.0, max = 50.0),
123+
reactive_power_limits = nothing,
124+
powerhouse_elevation = 500.0 + i * 10.0, # Different elevations
125+
efficiency = 0.85 + i * 0.02,
126+
)
127+
add_component!(sys, turbine)
128+
push!(turbines, turbine)
129+
end
130+
131+
# Link all turbines at once
132+
set_downstream_turbines!(reservoir, turbines)
133+
134+
# Verify connections
135+
@assert has_downstream_turbine(reservoir)
136+
@assert length(get_downstream_turbines(reservoir)) == 5
137+
```
23138

24139
## Head and Tail Reservoirs for Pumped Hydropower Plants
25140

26-
For this model, attach two [`HydroReservoir`](@ref)s to any number of [`HydroPumpTurbine`](@ref)s. The turbine and reservoirs structs store the elevations in each case calculate adequately the elevation and pressure heads for
27-
the facility.
141+
For this model, attach two [`HydroReservoir`](@ref)s to any number of [`HydroPumpTurbine`](@ref)s. The turbine and reservoir structs store the elevations to calculate the elevation and pressure heads for the facility.
28142

29143
```mermaid
30144
flowchart TB
@@ -37,3 +151,146 @@ flowchart TB
37151
C --- D
38152
B --- D["Tail Reservoir"]
39153
```
154+
155+
### Example: Pumped Hydro with Head and Tail Reservoirs
156+
157+
```julia
158+
# Create a HydroPumpTurbine
159+
pump_turbine = HydroPumpTurbine(;
160+
name = "PumpTurbine1",
161+
available = true,
162+
bus = bus,
163+
active_power = 50.0,
164+
reactive_power = 10.0,
165+
rating = 200.0,
166+
active_power_limits = (min = 20.0, max = 200.0), # Generation mode
167+
reactive_power_limits = (min = -100.0, max = 100.0),
168+
active_power_limits_pump = (min = 30.0, max = 180.0), # Pumping mode
169+
outflow_limits = (min = 0.0, max = 500.0),
170+
powerhouse_elevation = 400.0,
171+
base_power = 100.0,
172+
ramp_limits = (up = 20.0, down = 20.0),
173+
time_limits = nothing,
174+
status = PSY.PumpHydroStatusModule.PumpHydroStatus.OFF,
175+
time_at_status = 0.0,
176+
efficiency = (turbine = 0.9, pump = 0.85),
177+
transition_time = (turbine = 0.25, pump = 0.25), # hours
178+
minimum_time = (turbine = 1.0, pump = 1.0), # hours
179+
conversion_factor = 1.0,
180+
)
181+
add_component!(sys, pump_turbine)
182+
183+
# Create head (upper) reservoir
184+
head_reservoir = HydroReservoir(;
185+
name = "HeadReservoir",
186+
available = true,
187+
storage_level_limits = (min = 5000.0, max = 50000.0),
188+
initial_level = 0.6,
189+
spillage_limits = nothing,
190+
inflow = 200.0,
191+
outflow = 100.0,
192+
level_targets = 0.5,
193+
intake_elevation = 800.0,
194+
head_to_volume_factor = LinearCurve(1.0),
195+
)
196+
add_component!(sys, head_reservoir)
197+
198+
# Create tail (lower) reservoir
199+
tail_reservoir = HydroReservoir(;
200+
name = "TailReservoir",
201+
available = true,
202+
storage_level_limits = (min = 3000.0, max = 30000.0),
203+
initial_level = 0.4,
204+
spillage_limits = nothing,
205+
inflow = 50.0,
206+
outflow = 100.0,
207+
level_targets = 0.5,
208+
intake_elevation = 200.0,
209+
head_to_volume_factor = LinearCurve(1.0),
210+
)
211+
add_component!(sys, tail_reservoir)
212+
213+
# Link reservoirs to pump-turbine
214+
# Head reservoir feeds into the turbine (downstream)
215+
set_downstream_turbine!(head_reservoir, pump_turbine)
216+
217+
# Tail reservoir receives flow from the turbine (upstream)
218+
set_upstream_turbine!(tail_reservoir, pump_turbine)
219+
220+
# Verify connections
221+
@assert has_downstream_turbine(head_reservoir, pump_turbine)
222+
@assert has_upstream_turbine(tail_reservoir, pump_turbine)
223+
@assert length(get_connected_head_reservoirs(sys, pump_turbine)) == 1
224+
@assert length(get_connected_tail_reservoirs(sys, pump_turbine)) == 1
225+
```
226+
227+
## Key Component Fields
228+
229+
### HydroTurbine
230+
231+
Key fields for [`HydroTurbine`](@ref):
232+
233+
- `powerhouse_elevation::Float64`: Height in meters above sea level of the powerhouse
234+
- `efficiency::Float64`: Turbine efficiency [0, 1.0]
235+
- `turbine_type::HydroTurbineType`: Type of turbine (e.g., `HydroTurbineType.UNKNOWN`, `HydroTurbineType.FRANCIS`, `HydroTurbineType.PELTON`, `HydroTurbineType.KAPLAN`)
236+
- `conversion_factor::Float64`: Conversion factor from flow/volume to energy (m³ -> p.u-hr)
237+
- `outflow_limits::Union{Nothing, MinMax}`: Turbine outflow limits in m³/s
238+
- `travel_time::Union{Nothing, Float64}`: Downstream travel time in hours from reservoir to turbine
239+
240+
### HydroReservoir
241+
242+
Key fields for [`HydroReservoir`](@ref):
243+
244+
- `storage_level_limits::MinMax`: Storage level limits (in m³, m, or MWh based on `level_data_type`)
245+
- `initial_level::Float64`: Initial level as fraction of `storage_level_limits.max`
246+
- `inflow::Float64`: Water refilling the reservoir (m³/h or MW)
247+
- `outflow::Float64`: Water naturally leaving the reservoir (m³/h or MW)
248+
- `spillage_limits::Union{Nothing, MinMax}`: Water spillage limits
249+
- `level_targets::Union{Nothing, Float64}`: Target level at simulation end as fraction of max
250+
- `intake_elevation::Float64`: Height of intake in meters above sea level
251+
- `head_to_volume_factor::ValueCurve`: Head to volume relationship
252+
- `upstream_turbines::Vector{HydroUnit}`: Turbines feeding into this reservoir (tail reservoir)
253+
- `downstream_turbines::Vector{HydroUnit}`: Turbines fed by this reservoir (head reservoir)
254+
- `upstream_reservoirs::Vector{Device}`: Reservoirs feeding spillage into this reservoir
255+
- `level_data_type::ReservoirDataType`: Data type (e.g., `ReservoirDataType.USABLE_VOLUME`, `ReservoirDataType.HEAD`, `ReservoirDataType.ENERGY`)
256+
257+
### HydroPumpTurbine
258+
259+
Key fields specific to [`HydroPumpTurbine`](@ref):
260+
261+
- `active_power_limits::MinMax`: Power limits for turbine (generation) mode
262+
- `active_power_limits_pump::MinMax`: Power limits for pump mode
263+
- `status::PumpHydroStatus`: Operating status (`PumpHydroStatus.OFF`, `PumpHydroStatus.PUMP`, `PumpHydroStatus.GEN`)
264+
- `efficiency::TurbinePump`: Separate efficiencies for turbine and pump modes `(turbine = 0.9, pump = 0.85)`
265+
- `transition_time::TurbinePump`: Time to switch modes `(turbine = 0.25, pump = 0.25)`
266+
- `minimum_time::TurbinePump`: Minimum operating time in each mode `(turbine = 1.0, pump = 1.0)`
267+
268+
## Helper Functions
269+
270+
### Linking Turbines to Reservoirs
271+
272+
- `set_downstream_turbine!(reservoir, turbine)`: Link a single turbine as downstream of reservoir
273+
- `set_downstream_turbines!(reservoir, turbines)`: Link multiple turbines as downstream
274+
- `set_upstream_turbine!(reservoir, turbine)`: Link a single turbine as upstream of reservoir
275+
- `set_upstream_turbines!(reservoir, turbines)`: Link multiple turbines as upstream
276+
277+
### Checking Connections
278+
279+
- `has_downstream_turbine(reservoir)`: Check if any downstream turbines are attached
280+
- `has_downstream_turbine(reservoir, turbine)`: Check if specific turbine is downstream
281+
- `has_upstream_turbine(reservoir)`: Check if any upstream turbines are attached
282+
- `has_upstream_turbine(reservoir, turbine)`: Check if specific turbine is upstream
283+
284+
### Retrieving Connected Components
285+
286+
- `get_downstream_turbines(reservoir)`: Get vector of downstream turbines
287+
- `get_upstream_turbines(reservoir)`: Get vector of upstream turbines
288+
- `get_connected_head_reservoirs(sys, turbine)`: Get reservoirs where turbine is downstream
289+
- `get_connected_tail_reservoirs(sys, turbine)`: Get reservoirs where turbine is upstream
290+
- `get_turbine_head_reservoirs_mapping(sys)`: Get mapping of all turbines to head reservoirs
291+
- `get_turbine_tail_reservoirs_mapping(sys)`: Get mapping of all turbines to tail reservoirs
292+
293+
### Removing Connections
294+
295+
- `remove_turbine!(reservoir, turbine)`: Remove a specific turbine connection
296+
- `clear_turbines!(reservoir)`: Remove all turbine connections from reservoir

0 commit comments

Comments
 (0)