Skip to content

Commit f5109f6

Browse files
committed
Upgrade hydro module to allow hydro_timepoints.csv
1 parent 941c8e2 commit f5109f6

File tree

1 file changed

+83
-36
lines changed

1 file changed

+83
-36
lines changed

switch_model/generators/extensions/hydro_simple.py

Lines changed: 83 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,34 @@
2323
2424
INPUT FILE INFORMATION
2525
26-
The single file hydro_timeseries.csv needs to contain
27-
entries for each dispatchable hydro project. The set of hydro projects
28-
is derived from this file, and this file should cover all time periods
29-
in which the hydro plant can operate.
30-
31-
Run-of-River hydro projects should not be included in this file; RoR
32-
hydro is treated like any other variable renewable resource, and
33-
expects data in variable_capacity_factors.csv.
34-
35-
hydro_timeseries.csv
36-
hydro_generation_project, timeseries, hydro_min_flow_mw,
37-
hydro_avg_flow_mw
26+
The file hydro_timeseries.csv needs to contain
27+
entries for each dispatchable hydro project. The set of hydro projects
28+
is derived from this file, and this file should cover all time periods
29+
in which the hydro plant can operate.
30+
31+
Run-of-River hydro projects should not be included in this file; RoR
32+
hydro is treated like any other variable renewable resource, and
33+
expects data in variable_capacity_factors.csv.
34+
35+
hydro_timeseries.csv
36+
hydro_generation_project, timeseries, hydro_min_flow_mw,
37+
hydro_avg_flow_mw
38+
39+
The file hydro_timepoints.csv is an optional mapping of timepoints
40+
to a hydro timeseries. Hydro timeseries are different from the SWITCH
41+
timeseries (timeseries.csv) as this allows hydro constraints to be
42+
specified over a different time period.
43+
44+
hydro_timepoints.csv (optional)
45+
timepoint,tp_to_hts
3846
"""
3947
from __future__ import division
4048
# ToDo: Refactor this code to move the core components into a
4149
# switch_model.hydro.core module, the simplist components into
4250
# switch_model.hydro.simple, and the advanced components into
4351
# switch_model.hydro.water_network. That should set a good example
4452
# for other people who want to do other custom handling of hydro.
53+
import os.path
4554

4655
from pyomo.environ import *
4756

@@ -51,64 +60,98 @@
5160

5261
def define_components(mod):
5362
"""
54-
5563
HYDRO_GENS is the set of dispatchable hydro projects. This is a subet
5664
of GENERATION_PROJECTS, and is determined by the inputs file hydro_timeseries.csv.
5765
Members of this set can be called either g, or hydro_g.
5866
59-
HYDRO_GEN_TS is the set of Hydro projects and timeseries for which
67+
HYDRO_TS is the set of hydro timeseries over which the average flow constraint is defined.
68+
These hydro timeseries are different from the timeseries used in the reset of SWITCH
69+
and are defined by the input file hydro_timepoints.csv. If hydro_timepoints.csv doesn't exist,
70+
the default is for the timeseries to be the same as the SWITCH timeseries from timeseries.csv.
71+
Members of this set can be abbreviated as hts.
72+
73+
HYDRO_GEN_TS is the set of Hydro projects and hydro timeseries for which
6074
minimum and average flow are specified. Members of this set can be
61-
abbreviated as (project, timeseries) or (g, ts).
75+
abbreviated as (project, hydro_timeseries) or (g, hts).
6276
6377
HYDRO_GEN_TPS is the set of Hydro projects and available
6478
dispatch points. This is a filtered version of GEN_TPS that
6579
only includes hydro projects.
6680
67-
hydro_min_flow_mw[(g, ts) in HYDRO_GEN_TS] is a parameter that
81+
tp_to_hts[tp in TIMEPOINTS] is a parameter that returns the hydro timeseries
82+
for a given timepoint. It is defined in hydro_timepoints.csv and if unspecified
83+
it defaults to be equal to tp_ts.
84+
85+
hydro_min_flow_mw[(g, hts) in HYDRO_GEN_TS] is a parameter that
6886
determines minimum flow levels, specified in units of MW dispatch.
6987
70-
hydro_avg_flow_mw[(g, ts) in HYDRO_GEN_TS] is a parameter that
88+
hydro_avg_flow_mw[(g, hts) in HYDRO_GEN_TS] is a parameter that
7189
determines average flow levels, specified in units of MW dispatch.
7290
7391
Enforce_Hydro_Min_Flow[(g, t) in HYDRO_GEN_TPS] is a
7492
constraint that enforces minimum flow levels for each timepoint.
7593
76-
Enforce_Hydro_Avg_Flow[(g, ts) in HYDRO_GEN_TS] is a constraint
77-
that enforces average flow levels across each timeseries.
78-
94+
Enforce_Hydro_Avg_Flow[(g, hts) in HYDRO_GEN_TS] is a constraint
95+
that enforces average flow levels across each hydro timeseries.
7996
"""
97+
mod.tp_to_hts = Param(
98+
mod.TIMEPOINTS,
99+
input_file='hydro_timepoints.csv',
100+
default=lambda m, tp: m.tp_ts[tp],
101+
doc="Mapping of timepoints to a hydro series.",
102+
within=Any
103+
)
104+
105+
mod.HYDRO_TS = Set(
106+
dimen=1,
107+
ordered=False,
108+
initialize=lambda m: set(m.tp_to_hts[tp] for tp in m.TIMEPOINTS),
109+
doc="Set of hydro timeseries as defined in the mapping."
110+
)
111+
112+
mod.TPS_IN_HTS = Set(
113+
mod.HYDRO_TS,
114+
within=mod.TIMEPOINTS,
115+
ordered=False,
116+
initialize=lambda m, hts: set(t for t in m.TIMEPOINTS if m.tp_to_hts[t] == hts),
117+
doc="Set of timepoints in each hydro timeseries"
118+
)
119+
120+
mod.hydro_ts_duration = Param(
121+
mod.HYDRO_TS,
122+
initialize=lambda m, hts: sum(m.tp_duration_hrs[tp] for tp in m.TPS_IN_HTS[hts]),
123+
doc="Total duration in hours of each hydro timeseries."
124+
)
80125

81126
mod.HYDRO_GEN_TS_RAW = Set(
82127
dimen=2,
83128
input_file='hydro_timeseries.csv',
84129
input_optional=True,
85-
validate=lambda m, g, ts: (g in m.GENERATION_PROJECTS) & (ts in m.TIMESERIES))
130+
validate=lambda m, g, hts: (g in m.GENERATION_PROJECTS) & (hts in m.HYDRO_TS), )
86131

87132
mod.HYDRO_GENS = Set(
88133
dimen=1,
89134
ordered=False,
90-
initialize=lambda m: set(g for (g, ts) in m.HYDRO_GEN_TS_RAW),
135+
initialize=lambda m: set(g for (g, hts) in m.HYDRO_GEN_TS_RAW),
91136
doc="Dispatchable hydro projects")
92-
mod.HYDRO_GEN_TS = Set(
93-
dimen=2,
94-
initialize=lambda m: set(
95-
(g, m.tp_ts[tp])
96-
for g in m.HYDRO_GENS
97-
for tp in m.TPS_FOR_GEN[g]))
137+
98138
mod.HYDRO_GEN_TPS = Set(
99139
initialize=mod.GEN_TPS,
100140
filter=lambda m, g, t: g in m.HYDRO_GENS)
101141

142+
mod.HYDRO_GEN_TS = Set(
143+
dimen=2,
144+
initialize=lambda m: set((g, m.tp_to_hts[tp]) for (g, tp) in m.HYDRO_GEN_TPS))
145+
102146
# Validate that a timeseries data is specified for every hydro generator /
103147
# timeseries that we need. Extra data points (ex: outside of planning
104148
# horizon or beyond a plant's lifetime) can safely be ignored to make it
105149
# easier to create input files.
106150
mod.have_minimal_hydro_params = BuildCheck(
107151
mod.HYDRO_GEN_TS,
108-
rule=lambda m, g, ts: (g,ts) in m.HYDRO_GEN_TS_RAW)
152+
rule=lambda m, g, hts: (g, hts) in m.HYDRO_GEN_TS_RAW)
109153

110-
# To do: Add validation check that timeseries data are specified for every
111-
# valid timepoint.
154+
# Todo: Add validation check that timeseries data are specified for every valid timepoint.
112155

113156
mod.hydro_min_flow_mw = Param(
114157
mod.HYDRO_GEN_TS_RAW,
@@ -117,8 +160,9 @@ def define_components(mod):
117160
default=0.0)
118161
mod.Enforce_Hydro_Min_Flow = Constraint(
119162
mod.HYDRO_GEN_TPS,
120-
rule=lambda m, g, t: (
121-
m.DispatchGen[g, t] >= m.hydro_min_flow_mw[g, m.tp_ts[t]]))
163+
rule=lambda m, g, t: Constraint.Skip
164+
if m.hydro_min_flow_mw[g, m.tp_to_hts[t]] == 0
165+
else m.DispatchGen[g, t] >= m.hydro_min_flow_mw[g, m.tp_to_hts[t]])
122166

123167
mod.hydro_avg_flow_mw = Param(
124168
mod.HYDRO_GEN_TS_RAW,
@@ -133,8 +177,11 @@ def define_components(mod):
133177
enforce_hydro_avg_flow_scaling_factor = 1e1
134178
mod.Enforce_Hydro_Avg_Flow = Constraint(
135179
mod.HYDRO_GEN_TS,
136-
rule=lambda m, g, ts: (enforce_hydro_avg_flow_scaling_factor *
137-
sum(m.DispatchGen[g, t] for t in m.TPS_IN_TS[ts]) / m.ts_num_tps[ts]
138-
== m.hydro_avg_flow_mw[g, ts] * enforce_hydro_avg_flow_scaling_factor))
180+
rule=lambda m, g, hts:
181+
Constraint.Skip if m.hydro_avg_flow_mw[g, hts] == 0 else
182+
enforce_hydro_avg_flow_scaling_factor *
183+
sum(m.DispatchGen[g, t] * m.tp_duration_hrs[t] for t in m.TPS_IN_HTS[hts]) / m.hydro_ts_duration[hts]
184+
== m.hydro_avg_flow_mw[g, hts] * enforce_hydro_avg_flow_scaling_factor
185+
)
139186

140187
mod.min_data_check('hydro_min_flow_mw', 'hydro_avg_flow_mw')

0 commit comments

Comments
 (0)