openstudio-geb 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +7 -3
- data/CHANGELOG.md +4 -0
- data/Gemfile +1 -12
- data/files/seasonal_shedding_peak_hours.json +1 -0
- data/files/seasonal_shifting_peak_hours.json +1 -0
- data/files/seasonal_shifting_take_hours.json +1 -0
- data/lib/measures/AdjustThermostatSetpointsByDegreesForPeakHours/measure.rb +963 -442
- data/lib/measures/add_ceiling_fan/measure.rb +2 -2
- data/lib/measures/add_rooftop_pv_simple/measure.rb +1 -1
- data/lib/measures/apply_dynamic_coating_to_roof_wall/measure.rb +2 -2
- data/lib/measures/precooling/measure.rb +964 -354
- data/lib/measures/preheating/measure.rb +940 -356
- data/lib/measures/reduce_epd_by_percentage_for_peak_hours/measure.rb +509 -300
- data/lib/measures/reduce_lpd_by_percentage_for_peak_hours/measure.rb +534 -309
- data/lib/openstudio/geb/version.rb +1 -1
- data/openstudio-geb.gemspec +4 -6
- metadata +17 -42
@@ -4,6 +4,7 @@
|
|
4
4
|
# *******************************************************************************
|
5
5
|
|
6
6
|
# start the measure
|
7
|
+
require 'json'
|
7
8
|
class AdjustThermostatSetpointsByDegreesForPeakHours < OpenStudio::Measure::ModelMeasure
|
8
9
|
# setup OpenStudio units that we will need
|
9
10
|
TEMP_IP_UNIT = OpenStudio.createUnit('F').get
|
@@ -28,101 +29,244 @@ class AdjustThermostatSetpointsByDegreesForPeakHours < OpenStudio::Measure::Mode
|
|
28
29
|
def arguments(model)
|
29
30
|
args = OpenStudio::Measure::OSArgumentVector.new
|
30
31
|
|
31
|
-
# make an argument for adjustment to cooling setpoint
|
32
|
-
cooling_adjustment = OpenStudio::Measure::OSArgument.makeDoubleArgument('cooling_adjustment', true)
|
33
|
-
cooling_adjustment.setDisplayName('Degrees Fahrenheit to Adjust Cooling Setpoint By')
|
34
|
-
cooling_adjustment.setDefaultValue(2.0)
|
35
|
-
args << cooling_adjustment
|
36
|
-
|
37
|
-
# make an argument for the start time of cooling adjustment
|
38
|
-
cooling_daily_starttime = OpenStudio::Measure::OSArgument.makeStringArgument('cooling_daily_starttime', false)
|
39
|
-
cooling_daily_starttime.setDisplayName('Daily Start Time for Cooling Adjustment')
|
40
|
-
cooling_daily_starttime.setDescription('Use 24 hour format HH:MM:SS')
|
41
|
-
cooling_daily_starttime.setDefaultValue('16:01:00')
|
42
|
-
args << cooling_daily_starttime
|
43
|
-
|
44
|
-
# make an argument for the end time of cooling adjustment
|
45
|
-
cooling_daily_endtime = OpenStudio::Measure::OSArgument.makeStringArgument('cooling_daily_endtime', false)
|
46
|
-
cooling_daily_endtime.setDisplayName('Daily End Time for Cooling Adjustment')
|
47
|
-
cooling_daily_endtime.setDescription('Use 24 hour format HH:MM:SS')
|
48
|
-
cooling_daily_endtime.setDefaultValue('20:00:00')
|
49
|
-
args << cooling_daily_endtime
|
50
|
-
|
51
|
-
# make an argument for the start date of cooling adjustment
|
52
|
-
cooling_startdate = OpenStudio::Measure::OSArgument.makeStringArgument('cooling_startdate', false)
|
53
|
-
cooling_startdate.setDisplayName('Start Date for Cooling Adjustment')
|
54
|
-
cooling_startdate.setDescription('In MM-DD format')
|
55
|
-
cooling_startdate.setDefaultValue('06-01')
|
56
|
-
args << cooling_startdate
|
57
|
-
|
58
|
-
# make an argument for the end date of cooling adjustment
|
59
|
-
cooling_enddate = OpenStudio::Measure::OSArgument.makeStringArgument('cooling_enddate', false)
|
60
|
-
cooling_enddate.setDisplayName('End Date for Cooling Adjustment')
|
61
|
-
cooling_enddate.setDescription('In MM-DD format')
|
62
|
-
cooling_enddate.setDefaultValue('09-30')
|
63
|
-
args << cooling_enddate
|
64
|
-
|
65
32
|
# make an argument for adjustment to heating setpoint
|
66
33
|
heating_adjustment = OpenStudio::Measure::OSArgument.makeDoubleArgument('heating_adjustment', true)
|
67
34
|
heating_adjustment.setDisplayName('Degrees Fahrenheit to Adjust heating Setpoint By')
|
68
35
|
heating_adjustment.setDefaultValue(-2.0)
|
69
36
|
args << heating_adjustment
|
70
37
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
args <<
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
38
|
+
heating_start_date1 = OpenStudio::Ruleset::OSArgument.makeStringArgument('heating_start_date1', true)
|
39
|
+
heating_start_date1.setDisplayName('First start date for heating setpoint adjustment')
|
40
|
+
heating_start_date1.setDescription('In MM-DD format')
|
41
|
+
heating_start_date1.setDefaultValue('01-01')
|
42
|
+
args << heating_start_date1
|
43
|
+
heating_end_date1 = OpenStudio::Ruleset::OSArgument.makeStringArgument('heating_end_date1', true)
|
44
|
+
heating_end_date1.setDisplayName('First end date for heating setpoint adjustment')
|
45
|
+
heating_end_date1.setDescription('In MM-DD format')
|
46
|
+
heating_end_date1.setDefaultValue('03-31')
|
47
|
+
args << heating_end_date1
|
48
|
+
|
49
|
+
heating_start_date2 = OpenStudio::Ruleset::OSArgument.makeStringArgument('heating_start_date2', false)
|
50
|
+
heating_start_date2.setDisplayName('Second start date for heating setpoint adjustment (optional)')
|
51
|
+
heating_start_date2.setDescription('Specify a date in MM-DD format if you want a second season of heating setpoint adjustment; leave blank if not needed.')
|
52
|
+
heating_start_date2.setDefaultValue('')
|
53
|
+
args << heating_start_date2
|
54
|
+
heating_end_date2 = OpenStudio::Ruleset::OSArgument.makeStringArgument('heating_end_date2', false)
|
55
|
+
heating_end_date2.setDisplayName('Second end date for heating setpoint adjustment')
|
56
|
+
heating_end_date2.setDescription('Specify a date in MM-DD format if you want a second season of heating setpoint adjustment; leave blank if not needed. If either the start or end date is blank, the period is considered not used.')
|
57
|
+
heating_end_date2.setDefaultValue('')
|
58
|
+
args << heating_end_date2
|
59
|
+
|
60
|
+
heating_start_date3 = OpenStudio::Ruleset::OSArgument.makeStringArgument('heating_start_date3', false)
|
61
|
+
heating_start_date3.setDisplayName('Third start date for heating setpoint adjustment (optional)')
|
62
|
+
heating_start_date3.setDescription('Specify a date in MM-DD format if you want a third season of heating setpoint adjustment; leave blank if not needed.')
|
63
|
+
heating_start_date3.setDefaultValue('')
|
64
|
+
args << heating_start_date3
|
65
|
+
heating_end_date3 = OpenStudio::Ruleset::OSArgument.makeStringArgument('heating_end_date3', false)
|
66
|
+
heating_end_date3.setDisplayName('Third end date for heating setpoint adjustment')
|
67
|
+
heating_end_date3.setDescription('Specify a date in MM-DD format if you want a third season of heating setpoint adjustment; leave blank if not needed. If either the start or end date is blank, the period is considered not used.')
|
68
|
+
heating_end_date3.setDefaultValue('')
|
69
|
+
args << heating_end_date3
|
70
|
+
|
71
|
+
heating_start_date4 = OpenStudio::Ruleset::OSArgument.makeStringArgument('heating_start_date4', false)
|
72
|
+
heating_start_date4.setDisplayName('Fourth start date for heating setpoint adjustment (optional)')
|
73
|
+
heating_start_date4.setDescription('Specify a date in MM-DD format if you want a fourth season of heating setpoint adjustment; leave blank if not needed.')
|
74
|
+
heating_start_date4.setDefaultValue('')
|
75
|
+
args << heating_start_date4
|
76
|
+
heating_end_date4 = OpenStudio::Ruleset::OSArgument.makeStringArgument('heating_end_date4', false)
|
77
|
+
heating_end_date4.setDisplayName('Fourth end date for heating setpoint adjustment')
|
78
|
+
heating_end_date4.setDescription('Specify a date in MM-DD format if you want a fourth season of heating setpoint adjustment; leave blank if not needed. If either the start or end date is blank, the period is considered not used.')
|
79
|
+
heating_end_date4.setDefaultValue('')
|
80
|
+
args << heating_end_date4
|
81
|
+
|
82
|
+
heating_start_date5 = OpenStudio::Ruleset::OSArgument.makeStringArgument('heating_start_date5', false)
|
83
|
+
heating_start_date5.setDisplayName('Fifth start date for heating setpoint adjustment (optional)')
|
84
|
+
heating_start_date5.setDescription('Specify a date in MM-DD format if you want a fifth season of heating setpoint adjustment; leave blank if not needed.')
|
85
|
+
heating_start_date5.setDefaultValue('')
|
86
|
+
args << heating_start_date5
|
87
|
+
heating_end_date5 = OpenStudio::Ruleset::OSArgument.makeStringArgument('heating_end_date5', false)
|
88
|
+
heating_end_date5.setDisplayName('Fifth end date for heating setpoint adjustment')
|
89
|
+
heating_end_date5.setDescription('Specify a date in MM-DD format if you want a fifth season of heating setpoint adjustment; leave blank if not needed. If either the start or end date is blank, the period is considered not used.')
|
90
|
+
heating_end_date5.setDefaultValue('')
|
91
|
+
args << heating_end_date5
|
92
|
+
|
93
|
+
heating_start_time1 = OpenStudio::Measure::OSArgument.makeStringArgument('heating_start_time1', true)
|
94
|
+
heating_start_time1.setDisplayName('Start time of heating setpoint adjustment for the first season')
|
95
|
+
heating_start_time1.setDescription('In HH:MM:SS format')
|
96
|
+
heating_start_time1.setDefaultValue('17:00:00')
|
97
|
+
args << heating_start_time1
|
98
|
+
heating_end_time1 = OpenStudio::Measure::OSArgument.makeStringArgument('heating_end_time1', true)
|
99
|
+
heating_end_time1.setDisplayName('End time of heating setpoint adjustment for the first season')
|
100
|
+
heating_end_time1.setDescription('In HH:MM:SS format')
|
101
|
+
heating_end_time1.setDefaultValue('21:00:00')
|
102
|
+
args << heating_end_time1
|
103
|
+
|
104
|
+
heating_start_time2 = OpenStudio::Measure::OSArgument.makeStringArgument('heating_start_time2', false)
|
105
|
+
heating_start_time2.setDisplayName('Start time of heating setpoint adjustment for the second season (optional)')
|
106
|
+
heating_start_time2.setDescription('In HH:MM:SS format')
|
107
|
+
heating_start_time2.setDefaultValue('')
|
108
|
+
args << heating_start_time2
|
109
|
+
heating_end_time2 = OpenStudio::Measure::OSArgument.makeStringArgument('heating_end_time2', false)
|
110
|
+
heating_end_time2.setDisplayName('End time of heating setpoint adjustment for the second season (optional)')
|
111
|
+
heating_end_time2.setDescription('In HH:MM:SS format')
|
112
|
+
heating_end_time2.setDefaultValue('')
|
113
|
+
args << heating_end_time2
|
114
|
+
|
115
|
+
heating_start_time3 = OpenStudio::Measure::OSArgument.makeStringArgument('heating_start_time3', false)
|
116
|
+
heating_start_time3.setDisplayName('Start time of heating setpoint adjustment for the third season (optional)')
|
117
|
+
heating_start_time3.setDescription('In HH:MM:SS format')
|
118
|
+
heating_start_time3.setDefaultValue('')
|
119
|
+
args << heating_start_time3
|
120
|
+
heating_end_time3 = OpenStudio::Measure::OSArgument.makeStringArgument('heating_end_time3', false)
|
121
|
+
heating_end_time3.setDisplayName('End time of heating setpoint adjustment for the third season (optional)')
|
122
|
+
heating_end_time3.setDescription('In HH:MM:SS format')
|
123
|
+
heating_end_time3.setDefaultValue('')
|
124
|
+
args << heating_end_time3
|
125
|
+
|
126
|
+
heating_start_time4 = OpenStudio::Measure::OSArgument.makeStringArgument('heating_start_time4', false)
|
127
|
+
heating_start_time4.setDisplayName('Start time of heating setpoint adjustment for the fourth season (optional)')
|
128
|
+
heating_start_time4.setDescription('In HH:MM:SS format')
|
129
|
+
heating_start_time4.setDefaultValue('')
|
130
|
+
args << heating_start_time4
|
131
|
+
heating_end_time4 = OpenStudio::Measure::OSArgument.makeStringArgument('heating_end_time4', false)
|
132
|
+
heating_end_time4.setDisplayName('End time of heating setpoint adjustment for the fourth season (optional)')
|
133
|
+
heating_end_time4.setDescription('In HH:MM:SS format')
|
134
|
+
heating_end_time4.setDefaultValue('')
|
135
|
+
args << heating_end_time4
|
136
|
+
|
137
|
+
heating_start_time5 = OpenStudio::Measure::OSArgument.makeStringArgument('heating_start_time5', false)
|
138
|
+
heating_start_time5.setDisplayName('Start time of heating setpoint adjustment for the fifth season (optional)')
|
139
|
+
heating_start_time5.setDescription('In HH:MM:SS format')
|
140
|
+
heating_start_time5.setDefaultValue('')
|
141
|
+
args << heating_start_time5
|
142
|
+
heating_end_time5 = OpenStudio::Measure::OSArgument.makeStringArgument('heating_end_time5', false)
|
143
|
+
heating_end_time5.setDisplayName('End time of heating setpoint adjustment for the fifth season (optional)')
|
144
|
+
heating_end_time5.setDescription('In HH:MM:SS format')
|
145
|
+
heating_end_time5.setDefaultValue('')
|
146
|
+
args << heating_end_time5
|
147
|
+
|
148
|
+
|
149
|
+
# make an argument for adjustment to cooling setpoint
|
150
|
+
cooling_adjustment = OpenStudio::Measure::OSArgument.makeDoubleArgument('cooling_adjustment', true)
|
151
|
+
cooling_adjustment.setDisplayName('Degrees Fahrenheit to Adjust Cooling Setpoint By')
|
152
|
+
cooling_adjustment.setDefaultValue(5.0)
|
153
|
+
args << cooling_adjustment
|
154
|
+
|
155
|
+
cooling_start_date1 = OpenStudio::Ruleset::OSArgument.makeStringArgument('cooling_start_date1', true)
|
156
|
+
cooling_start_date1.setDisplayName('First start date for cooling setpoint adjustment')
|
157
|
+
cooling_start_date1.setDescription('In MM-DD format')
|
158
|
+
cooling_start_date1.setDefaultValue('06-01')
|
159
|
+
args << cooling_start_date1
|
160
|
+
cooling_end_date1 = OpenStudio::Ruleset::OSArgument.makeStringArgument('cooling_end_date1', true)
|
161
|
+
cooling_end_date1.setDisplayName('First end date for cooling setpoint adjustment')
|
162
|
+
cooling_end_date1.setDescription('In MM-DD format')
|
163
|
+
cooling_end_date1.setDefaultValue('09-30')
|
164
|
+
args << cooling_end_date1
|
165
|
+
|
166
|
+
cooling_start_date2 = OpenStudio::Ruleset::OSArgument.makeStringArgument('cooling_start_date2', false)
|
167
|
+
cooling_start_date2.setDisplayName('Second start date for cooling setpoint adjustment (optional)')
|
168
|
+
cooling_start_date2.setDescription('Specify a date in MM-DD format if you want a second season of cooling setpoint adjustment; leave blank if not needed.')
|
169
|
+
cooling_start_date2.setDefaultValue('')
|
170
|
+
args << cooling_start_date2
|
171
|
+
cooling_end_date2 = OpenStudio::Ruleset::OSArgument.makeStringArgument('cooling_end_date2', false)
|
172
|
+
cooling_end_date2.setDisplayName('Second end date for cooling setpoint adjustment')
|
173
|
+
cooling_end_date2.setDescription('Specify a date in MM-DD format if you want a second season of cooling setpoint adjustment; leave blank if not needed. If either the start or end date is blank, the period is considered not used.')
|
174
|
+
cooling_end_date2.setDefaultValue('')
|
175
|
+
args << cooling_end_date2
|
176
|
+
|
177
|
+
cooling_start_date3 = OpenStudio::Ruleset::OSArgument.makeStringArgument('cooling_start_date3', false)
|
178
|
+
cooling_start_date3.setDisplayName('Third start date for cooling setpoint adjustment (optional)')
|
179
|
+
cooling_start_date3.setDescription('Specify a date in MM-DD format if you want a third season of cooling setpoint adjustment; leave blank if not needed.')
|
180
|
+
cooling_start_date3.setDefaultValue('')
|
181
|
+
args << cooling_start_date3
|
182
|
+
cooling_end_date3 = OpenStudio::Ruleset::OSArgument.makeStringArgument('cooling_end_date3', false)
|
183
|
+
cooling_end_date3.setDisplayName('Third end date for cooling setpoint adjustment')
|
184
|
+
cooling_end_date3.setDescription('Specify a date in MM-DD format if you want a third season of cooling setpoint adjustment; leave blank if not needed. If either the start or end date is blank, the period is considered not used.')
|
185
|
+
cooling_end_date3.setDefaultValue('')
|
186
|
+
args << cooling_end_date3
|
187
|
+
|
188
|
+
cooling_start_date4 = OpenStudio::Ruleset::OSArgument.makeStringArgument('cooling_start_date4', false)
|
189
|
+
cooling_start_date4.setDisplayName('Fourth start date for cooling setpoint adjustment (optional)')
|
190
|
+
cooling_start_date4.setDescription('Specify a date in MM-DD format if you want a fourth season of cooling setpoint adjustment; leave blank if not needed.')
|
191
|
+
cooling_start_date4.setDefaultValue('')
|
192
|
+
args << cooling_start_date4
|
193
|
+
cooling_end_date4 = OpenStudio::Ruleset::OSArgument.makeStringArgument('cooling_end_date4', false)
|
194
|
+
cooling_end_date4.setDisplayName('Fourth end date for cooling setpoint adjustment')
|
195
|
+
cooling_end_date4.setDescription('Specify a date in MM-DD format if you want a fourth season of cooling setpoint adjustment; leave blank if not needed. If either the start or end date is blank, the period is considered not used.')
|
196
|
+
cooling_end_date4.setDefaultValue('')
|
197
|
+
args << cooling_end_date4
|
198
|
+
|
199
|
+
cooling_start_date5 = OpenStudio::Ruleset::OSArgument.makeStringArgument('cooling_start_date5', false)
|
200
|
+
cooling_start_date5.setDisplayName('Fifth start date for cooling setpoint adjustment (optional)')
|
201
|
+
cooling_start_date5.setDescription('Specify a date in MM-DD format if you want a fifth season of cooling setpoint adjustment; leave blank if not needed.')
|
202
|
+
cooling_start_date5.setDefaultValue('')
|
203
|
+
args << cooling_start_date5
|
204
|
+
cooling_end_date5 = OpenStudio::Ruleset::OSArgument.makeStringArgument('cooling_end_date5', false)
|
205
|
+
cooling_end_date5.setDisplayName('Fifth end date for cooling setpoint adjustment')
|
206
|
+
cooling_end_date5.setDescription('Specify a date in MM-DD format if you want a fifth season of cooling setpoint adjustment; leave blank if not needed. If either the start or end date is blank, the period is considered not used.')
|
207
|
+
cooling_end_date5.setDefaultValue('')
|
208
|
+
args << cooling_end_date5
|
209
|
+
|
210
|
+
cooling_start_time1 = OpenStudio::Measure::OSArgument.makeStringArgument('cooling_start_time1', true)
|
211
|
+
cooling_start_time1.setDisplayName('Start time of cooling setpoint adjustment for the first season')
|
212
|
+
cooling_start_time1.setDescription('In HH:MM:SS format')
|
213
|
+
cooling_start_time1.setDefaultValue('17:00:00')
|
214
|
+
args << cooling_start_time1
|
215
|
+
cooling_end_time1 = OpenStudio::Measure::OSArgument.makeStringArgument('cooling_end_time1', true)
|
216
|
+
cooling_end_time1.setDisplayName('End time of cooling setpoint adjustment for the first season')
|
217
|
+
cooling_end_time1.setDescription('In HH:MM:SS format')
|
218
|
+
cooling_end_time1.setDefaultValue('21:00:00')
|
219
|
+
args << cooling_end_time1
|
220
|
+
|
221
|
+
cooling_start_time2 = OpenStudio::Measure::OSArgument.makeStringArgument('cooling_start_time2', false)
|
222
|
+
cooling_start_time2.setDisplayName('Start time of cooling setpoint adjustment for the second season (optional)')
|
223
|
+
cooling_start_time2.setDescription('In HH:MM:SS format')
|
224
|
+
cooling_start_time2.setDefaultValue('')
|
225
|
+
args << cooling_start_time2
|
226
|
+
cooling_end_time2 = OpenStudio::Measure::OSArgument.makeStringArgument('cooling_end_time2', false)
|
227
|
+
cooling_end_time2.setDisplayName('End time of cooling setpoint adjustment for the second season (optional)')
|
228
|
+
cooling_end_time2.setDescription('In HH:MM:SS format')
|
229
|
+
cooling_end_time2.setDefaultValue('')
|
230
|
+
args << cooling_end_time2
|
231
|
+
|
232
|
+
cooling_start_time3 = OpenStudio::Measure::OSArgument.makeStringArgument('cooling_start_time3', false)
|
233
|
+
cooling_start_time3.setDisplayName('Start time of cooling setpoint adjustment for the third season (optional)')
|
234
|
+
cooling_start_time3.setDescription('In HH:MM:SS format')
|
235
|
+
cooling_start_time3.setDefaultValue('')
|
236
|
+
args << cooling_start_time3
|
237
|
+
cooling_end_time3 = OpenStudio::Measure::OSArgument.makeStringArgument('cooling_end_time3', false)
|
238
|
+
cooling_end_time3.setDisplayName('End time of cooling setpoint adjustment for the third season (optional)')
|
239
|
+
cooling_end_time3.setDescription('In HH:MM:SS format')
|
240
|
+
cooling_end_time3.setDefaultValue('')
|
241
|
+
args << cooling_end_time3
|
242
|
+
|
243
|
+
cooling_start_time4 = OpenStudio::Measure::OSArgument.makeStringArgument('cooling_start_time4', false)
|
244
|
+
cooling_start_time4.setDisplayName('Start time of cooling setpoint adjustment for the fourth season (optional)')
|
245
|
+
cooling_start_time4.setDescription('In HH:MM:SS format')
|
246
|
+
cooling_start_time4.setDefaultValue('')
|
247
|
+
args << cooling_start_time4
|
248
|
+
cooling_end_time4 = OpenStudio::Measure::OSArgument.makeStringArgument('cooling_end_time4', false)
|
249
|
+
cooling_end_time4.setDisplayName('End time of cooling setpoint adjustment for the fourth season (optional)')
|
250
|
+
cooling_end_time4.setDescription('In HH:MM:SS format')
|
251
|
+
cooling_end_time4.setDefaultValue('')
|
252
|
+
args << cooling_end_time4
|
253
|
+
|
254
|
+
cooling_start_time5 = OpenStudio::Measure::OSArgument.makeStringArgument('cooling_start_time5', false)
|
255
|
+
cooling_start_time5.setDisplayName('Start time of cooling setpoint adjustment for the fifth season (optional)')
|
256
|
+
cooling_start_time5.setDescription('In HH:MM:SS format')
|
257
|
+
cooling_start_time5.setDefaultValue('')
|
258
|
+
args << cooling_start_time5
|
259
|
+
cooling_end_time5 = OpenStudio::Measure::OSArgument.makeStringArgument('cooling_end_time5', false)
|
260
|
+
cooling_end_time5.setDisplayName('End time of cooling setpoint adjustment for the fifth season (optional)')
|
261
|
+
cooling_end_time5.setDescription('In HH:MM:SS format')
|
262
|
+
cooling_end_time5.setDefaultValue('')
|
263
|
+
args << cooling_end_time5
|
264
|
+
|
265
|
+
|
266
|
+
# Use alternative default start and end time for different climate zone
|
267
|
+
alt_periods = OpenStudio::Measure::OSArgument.makeBoolArgument('alt_periods', true)
|
268
|
+
alt_periods.setDisplayName('Use alternative default start and end time based on the state of the model from the Cambium load profile peak period?')
|
269
|
+
alt_periods.setDescription('This will overwrite the start and end time and date provided by the user')
|
126
270
|
alt_periods.setDefaultValue(false)
|
127
271
|
args << alt_periods
|
128
272
|
|
@@ -139,191 +283,297 @@ class AdjustThermostatSetpointsByDegreesForPeakHours < OpenStudio::Measure::Mode
|
|
139
283
|
end
|
140
284
|
|
141
285
|
# assign the user inputs to variables
|
142
|
-
cooling_adjustment = runner.getDoubleArgumentValue('cooling_adjustment', user_arguments)
|
143
286
|
heating_adjustment = runner.getDoubleArgumentValue('heating_adjustment', user_arguments)
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
287
|
+
cooling_adjustment = runner.getDoubleArgumentValue('cooling_adjustment', user_arguments)
|
288
|
+
heating_start_time1 = runner.getStringArgumentValue('heating_start_time1', user_arguments)
|
289
|
+
heating_end_time1 = runner.getStringArgumentValue('heating_end_time1', user_arguments)
|
290
|
+
heating_start_time2 = runner.getStringArgumentValue('heating_start_time2', user_arguments)
|
291
|
+
heating_end_time2 = runner.getStringArgumentValue('heating_end_time2', user_arguments)
|
292
|
+
heating_start_time3 = runner.getStringArgumentValue('heating_start_time3', user_arguments)
|
293
|
+
heating_end_time3 = runner.getStringArgumentValue('heating_end_time3', user_arguments)
|
294
|
+
heating_start_time4 = runner.getStringArgumentValue('heating_start_time4', user_arguments)
|
295
|
+
heating_end_time4 = runner.getStringArgumentValue('heating_end_time4', user_arguments)
|
296
|
+
heating_start_time5 = runner.getStringArgumentValue('heating_start_time5', user_arguments)
|
297
|
+
heating_end_time5 = runner.getStringArgumentValue('heating_end_time5', user_arguments)
|
298
|
+
heating_start_date1 = runner.getStringArgumentValue('heating_start_date1', user_arguments)
|
299
|
+
heating_end_date1 = runner.getStringArgumentValue('heating_end_date1', user_arguments)
|
300
|
+
heating_start_date2 = runner.getStringArgumentValue('heating_start_date2', user_arguments)
|
301
|
+
heating_end_date2 = runner.getStringArgumentValue('heating_end_date2', user_arguments)
|
302
|
+
heating_start_date3 = runner.getStringArgumentValue('heating_start_date3', user_arguments)
|
303
|
+
heating_end_date3 = runner.getStringArgumentValue('heating_end_date3', user_arguments)
|
304
|
+
heating_start_date4 = runner.getStringArgumentValue('heating_start_date4', user_arguments)
|
305
|
+
heating_end_date4 = runner.getStringArgumentValue('heating_end_date4', user_arguments)
|
306
|
+
heating_start_date5 = runner.getStringArgumentValue('heating_start_date5', user_arguments)
|
307
|
+
heating_end_date5 = runner.getStringArgumentValue('heating_end_date5', user_arguments)
|
308
|
+
cooling_start_time1 = runner.getStringArgumentValue('cooling_start_time1', user_arguments)
|
309
|
+
cooling_end_time1 = runner.getStringArgumentValue('cooling_end_time1', user_arguments)
|
310
|
+
cooling_start_time2 = runner.getStringArgumentValue('cooling_start_time2', user_arguments)
|
311
|
+
cooling_end_time2 = runner.getStringArgumentValue('cooling_end_time2', user_arguments)
|
312
|
+
cooling_start_time3 = runner.getStringArgumentValue('cooling_start_time3', user_arguments)
|
313
|
+
cooling_end_time3 = runner.getStringArgumentValue('cooling_end_time3', user_arguments)
|
314
|
+
cooling_start_time4 = runner.getStringArgumentValue('cooling_start_time4', user_arguments)
|
315
|
+
cooling_end_time4 = runner.getStringArgumentValue('cooling_end_time4', user_arguments)
|
316
|
+
cooling_start_time5 = runner.getStringArgumentValue('cooling_start_time5', user_arguments)
|
317
|
+
cooling_end_time5 = runner.getStringArgumentValue('cooling_end_time5', user_arguments)
|
318
|
+
cooling_start_date1 = runner.getStringArgumentValue('cooling_start_date1', user_arguments)
|
319
|
+
cooling_end_date1 = runner.getStringArgumentValue('cooling_end_date1', user_arguments)
|
320
|
+
cooling_start_date2 = runner.getStringArgumentValue('cooling_start_date2', user_arguments)
|
321
|
+
cooling_end_date2 = runner.getStringArgumentValue('cooling_end_date2', user_arguments)
|
322
|
+
cooling_start_date3 = runner.getStringArgumentValue('cooling_start_date3', user_arguments)
|
323
|
+
cooling_end_date3 = runner.getStringArgumentValue('cooling_end_date3', user_arguments)
|
324
|
+
cooling_start_date4 = runner.getStringArgumentValue('cooling_start_date4', user_arguments)
|
325
|
+
cooling_end_date4 = runner.getStringArgumentValue('cooling_end_date4', user_arguments)
|
326
|
+
cooling_start_date5 = runner.getStringArgumentValue('cooling_start_date5', user_arguments)
|
327
|
+
cooling_end_date5 = runner.getStringArgumentValue('cooling_end_date5', user_arguments)
|
156
328
|
alt_periods = runner.getBoolArgumentValue('alt_periods', user_arguments)
|
157
329
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
330
|
+
|
331
|
+
# set the default start and end time based on state
|
332
|
+
if alt_periods
|
333
|
+
state = model.getWeatherFile.stateProvinceRegion
|
334
|
+
if state == ''
|
335
|
+
runner.registerError('Unable to find state in model WeatherFile. The measure cannot be applied.')
|
336
|
+
return false
|
337
|
+
end
|
338
|
+
file = File.open(File.join(File.dirname(__FILE__), "../../../files/seasonal_shedding_peak_hours.json"))
|
339
|
+
default_peak_periods = JSON.load(file)
|
340
|
+
file.close
|
341
|
+
unless default_peak_periods.key?state
|
342
|
+
runner.registerAsNotApplicable("No default inputs for the state of the WeatherFile #{state}")
|
343
|
+
return false
|
344
|
+
end
|
345
|
+
peak_periods = default_peak_periods[state]
|
346
|
+
cooling_start_time1 = heating_start_time1 = peak_periods["winter_peak_start"].split[1]
|
347
|
+
cooling_end_time1 = heating_end_time1 = peak_periods["winter_peak_end"].split[1]
|
348
|
+
cooling_start_time2 = heating_start_time2 = peak_periods["intermediate_peak_start"].split[1]
|
349
|
+
cooling_end_time2 = heating_end_time2 = peak_periods["intermediate_peak_end"].split[1]
|
350
|
+
cooling_start_time3 = heating_start_time3 = peak_periods["summer_peak_start"].split[1]
|
351
|
+
cooling_end_time3 = heating_end_time3 = peak_periods["summer_peak_end"].split[1]
|
352
|
+
cooling_start_time4 = heating_start_time4 = peak_periods["intermediate_peak_start"].split[1]
|
353
|
+
cooling_end_time4 = heating_end_time4 = peak_periods["intermediate_peak_end"].split[1]
|
354
|
+
cooling_start_time5 = heating_start_time5 = peak_periods["winter_peak_start"].split[1]
|
355
|
+
cooling_end_time5 = heating_end_time5 = peak_periods["winter_peak_end"].split[1]
|
356
|
+
cooling_start_date1 = heating_start_date1 = '01-01'
|
357
|
+
cooling_end_date1 = heating_end_date1 = '03-31'
|
358
|
+
cooling_start_date2 = heating_start_date2 = '04-01'
|
359
|
+
cooling_end_date2 = heating_end_date2 = '05-31'
|
360
|
+
cooling_start_date3 = heating_start_date3 = '06-01'
|
361
|
+
cooling_end_date3 = heating_end_date3 = '09-30'
|
362
|
+
cooling_start_date4 = heating_start_date4 = '10-01'
|
363
|
+
cooling_end_date4 = heating_end_date4 = '11-30'
|
364
|
+
cooling_start_date5 = heating_start_date5 = '12-01'
|
365
|
+
cooling_end_date5 = heating_end_date5 = '12-31'
|
167
366
|
end
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
367
|
+
|
368
|
+
def validate_time_format(star_time, end_time, runner)
|
369
|
+
time1 = /(\d\d):(\d\d):(\d\d)/.match(star_time)
|
370
|
+
time2 = /(\d\d):(\d\d):(\d\d)/.match(end_time)
|
371
|
+
if time1 and time2
|
372
|
+
os_starttime = OpenStudio::Time.new(star_time)
|
373
|
+
os_endtime = OpenStudio::Time.new(end_time)
|
374
|
+
if star_time >= end_time
|
375
|
+
runner.registerError('The start time needs to be earlier than the end time.')
|
376
|
+
return false
|
377
|
+
else
|
378
|
+
return os_starttime, os_endtime
|
379
|
+
end
|
380
|
+
else
|
381
|
+
runner.registerError('The provided time is not in HH-MM-SS format.')
|
382
|
+
return false
|
383
|
+
end
|
177
384
|
end
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
385
|
+
|
386
|
+
def validate_date_format(start_date1, end_date1, runner, model)
|
387
|
+
smd = /(\d\d)-(\d\d)/.match(start_date1)
|
388
|
+
emd = /(\d\d)-(\d\d)/.match(end_date1)
|
389
|
+
if smd.nil? or emd.nil?
|
390
|
+
runner.registerError('The provided date is not in MM-DD format.')
|
391
|
+
return false
|
392
|
+
else
|
393
|
+
start_month = smd[1].to_i
|
394
|
+
start_day = smd[2].to_i
|
395
|
+
end_month = emd[1].to_i
|
396
|
+
end_day = emd[2].to_i
|
397
|
+
if start_date1 > end_date1
|
398
|
+
runner.registerError('The start date cannot be later date the end time.')
|
399
|
+
return false
|
400
|
+
else
|
401
|
+
os_start_date = model.getYearDescription.makeDate(start_month, start_day)
|
402
|
+
os_end_date = model.getYearDescription.makeDate(end_month, end_day)
|
403
|
+
return os_start_date, os_end_date
|
404
|
+
end
|
405
|
+
end
|
187
406
|
end
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
if
|
192
|
-
|
193
|
-
heating_end_day_1 = md[2].to_i
|
407
|
+
|
408
|
+
# First time period for heating
|
409
|
+
heating_time_result1 = validate_time_format(heating_start_time1, heating_end_time1, runner)
|
410
|
+
if heating_time_result1
|
411
|
+
heating_shift_time_start1, heating_shift_time_end1 = heating_time_result1
|
194
412
|
else
|
195
|
-
runner.registerError('
|
413
|
+
runner.registerError('The required time period for the adjustment is not in correct format!')
|
196
414
|
return false
|
197
415
|
end
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
416
|
+
# The other optional time periods
|
417
|
+
heating_shift_time_start2,heating_shift_time_end2,heating_shift_time_start3,heating_shift_time_end3,heating_shift_time_start4,heating_shift_time_end4,heating_shift_time_start5,heating_shift_time_end5 = [nil]*8
|
418
|
+
if (not heating_start_time2.empty?) and (not heating_end_time2.empty?)
|
419
|
+
heating_time_result2 = validate_time_format(heating_start_time2, heating_end_time2, runner)
|
420
|
+
if heating_time_result2
|
421
|
+
heating_shift_time_start2, heating_shift_time_end2 = heating_time_result2
|
422
|
+
end
|
423
|
+
end
|
424
|
+
if (not heating_start_time3.empty?) and (not heating_end_time3.empty?)
|
425
|
+
heating_time_result3 = validate_time_format(heating_start_time3, heating_end_time3, runner)
|
426
|
+
if heating_time_result3
|
427
|
+
heating_shift_time_start3, heating_shift_time_end3 = heating_time_result3
|
428
|
+
end
|
429
|
+
end
|
430
|
+
if (not heating_start_time4.empty?) and (not heating_end_time4.empty?)
|
431
|
+
heating_time_result4 = validate_time_format(heating_start_time4, heating_end_time4, runner)
|
432
|
+
if heating_time_result4
|
433
|
+
heating_shift_time_start4, heating_shift_time_end4 = heating_time_result4
|
434
|
+
end
|
435
|
+
end
|
436
|
+
if (not heating_start_time5.empty?) and (not heating_end_time5.empty?)
|
437
|
+
heating_time_result5 = validate_time_format(heating_start_time5, heating_end_time5, runner)
|
438
|
+
if heating_time_result5
|
439
|
+
heating_shift_time_start5, heating_shift_time_end5 = heating_time_result5
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
# First time period for cooling
|
444
|
+
cooling_time_result1 = validate_time_format(cooling_start_time1, cooling_end_time1, runner)
|
445
|
+
if cooling_time_result1
|
446
|
+
cooling_shift_time_start1, cooling_shift_time_end1 = cooling_time_result1
|
204
447
|
else
|
205
|
-
runner.registerError('
|
448
|
+
runner.registerError('The required time period for the adjustment is not in correct format!')
|
206
449
|
return false
|
207
450
|
end
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
451
|
+
# The other optional time periods
|
452
|
+
cooling_shift_time_start2,cooling_shift_time_end2,cooling_shift_time_start3,cooling_shift_time_end3,cooling_shift_time_start4,cooling_shift_time_end4,cooling_shift_time_start5,cooling_shift_time_end5 = [nil]*8
|
453
|
+
if (not cooling_start_time2.empty?) and (not cooling_end_time2.empty?)
|
454
|
+
cooling_time_result2 = validate_time_format(cooling_start_time2, cooling_end_time2, runner)
|
455
|
+
if cooling_time_result2
|
456
|
+
cooling_shift_time_start2, cooling_shift_time_end2 = cooling_time_result2
|
457
|
+
end
|
458
|
+
end
|
459
|
+
if (not cooling_start_time3.empty?) and (not cooling_end_time3.empty?)
|
460
|
+
cooling_time_result3 = validate_time_format(cooling_start_time3, cooling_end_time3, runner)
|
461
|
+
if cooling_time_result3
|
462
|
+
cooling_shift_time_start3, cooling_shift_time_end3 = cooling_time_result3
|
463
|
+
end
|
464
|
+
end
|
465
|
+
if (not cooling_start_time4.empty?) and (not cooling_end_time4.empty?)
|
466
|
+
cooling_time_result4 = validate_time_format(cooling_start_time4, cooling_end_time4, runner)
|
467
|
+
if cooling_time_result4
|
468
|
+
cooling_shift_time_start4, cooling_shift_time_end4 = cooling_time_result4
|
469
|
+
end
|
470
|
+
end
|
471
|
+
if (not cooling_start_time5.empty?) and (not cooling_end_time5.empty?)
|
472
|
+
cooling_time_result5 = validate_time_format(cooling_start_time5, cooling_end_time5, runner)
|
473
|
+
if cooling_time_result5
|
474
|
+
cooling_shift_time_start5, cooling_shift_time_end5 = cooling_time_result5
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
# First date period
|
479
|
+
heating_date_result1 = validate_date_format(heating_start_date1, heating_end_date1, runner, model)
|
480
|
+
if heating_date_result1
|
481
|
+
os_heating_start_date1, os_heating_end_date1 = heating_date_result1
|
214
482
|
else
|
215
|
-
runner.registerError('
|
483
|
+
runner.registerError('The required date period for the heating setpoint adjustment is not in correct format!')
|
216
484
|
return false
|
217
485
|
end
|
486
|
+
# Other optional date period
|
487
|
+
os_heating_start_date2, os_heating_end_date2, os_heating_start_date3, os_heating_end_date3, os_heating_start_date4, os_heating_end_date4, os_heating_start_date5, os_heating_end_date5 = [nil]*8
|
488
|
+
if (not heating_start_date2.empty?) and (not heating_end_date2.empty?)
|
489
|
+
heating_date_result2 = validate_date_format(heating_start_date2, heating_end_date2, runner, model)
|
490
|
+
if heating_date_result2
|
491
|
+
os_heating_start_date2, os_heating_end_date2 = heating_date_result2
|
492
|
+
end
|
493
|
+
end
|
218
494
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
winterStartDate2 = OpenStudio::Date.new(OpenStudio::MonthOfYear.new(heating_start_month_2), heating_start_day_2)
|
224
|
-
winterEndDate2 = OpenStudio::Date.new(OpenStudio::MonthOfYear.new(heating_end_month_2), heating_end_day_2)
|
225
|
-
|
226
|
-
######### GET CLIMATE ZONES ################
|
227
|
-
if auto_date
|
228
|
-
ashraeClimateZone = ''
|
229
|
-
#climateZoneNUmber = ''
|
230
|
-
climateZones = model.getClimateZones
|
231
|
-
climateZones.climateZones.each do |climateZone|
|
232
|
-
if climateZone.institution == 'ASHRAE'
|
233
|
-
ashraeClimateZone = climateZone.value
|
234
|
-
runner.registerInfo("Using ASHRAE Climate zone #{ashraeClimateZone}.")
|
235
|
-
end
|
495
|
+
if (not heating_start_date3.empty?) and (not heating_end_date3.empty?)
|
496
|
+
heating_date_result3 = validate_date_format(heating_start_date3, heating_end_date3, runner, model)
|
497
|
+
if heating_date_result3
|
498
|
+
os_heating_start_date3, os_heating_end_date3 = heating_date_result3
|
236
499
|
end
|
500
|
+
end
|
237
501
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
if alt_periods
|
244
|
-
case ashraeClimateZone
|
245
|
-
when '3A', '4A'
|
246
|
-
cooling_daily_starttime = '18:01:00'
|
247
|
-
cooling_daily_endtime = '21:59:00'
|
248
|
-
heating_daily_starttime = '17:01:00'
|
249
|
-
heating_daily_endtime = '20:59:00'
|
250
|
-
when '5A'
|
251
|
-
cooling_daily_starttime = '14:01:00'
|
252
|
-
cooling_daily_endtime = '17:59:00'
|
253
|
-
heating_daily_starttime = '18:01:00'
|
254
|
-
heating_daily_endtime = '21:59:00'
|
255
|
-
when '6A'
|
256
|
-
cooling_daily_starttime = '13:01:00'
|
257
|
-
cooling_daily_endtime = '16:59:00'
|
258
|
-
heating_daily_starttime = '17:01:00'
|
259
|
-
heating_daily_endtime = '20:59:00'
|
260
|
-
end
|
261
|
-
else
|
262
|
-
case ashraeClimateZone
|
263
|
-
when '2A', '2B', '4B', '4C', '5B', '5C', '6B'
|
264
|
-
cooling_daily_starttime = '17:01:00'
|
265
|
-
cooling_daily_endtime = '20:59:00'
|
266
|
-
heating_daily_starttime = '17:01:00'
|
267
|
-
heating_daily_endtime = '20:59:00'
|
268
|
-
when '3A', '3C'
|
269
|
-
cooling_daily_starttime = '19:01:00'
|
270
|
-
cooling_daily_endtime = '22:59:00'
|
271
|
-
heating_daily_starttime = '17:01:00'
|
272
|
-
heating_daily_endtime = '20:59:00'
|
273
|
-
when '3B'
|
274
|
-
cooling_daily_starttime = '18:01:00'
|
275
|
-
cooling_daily_endtime = '21:59:00'
|
276
|
-
heating_daily_starttime = '19:01:00'
|
277
|
-
heating_daily_endtime = '22:59:00'
|
278
|
-
when '4A'
|
279
|
-
cooling_daily_starttime = '12:01:00'
|
280
|
-
cooling_daily_endtime = '15:59:00'
|
281
|
-
heating_daily_starttime = '16:01:00'
|
282
|
-
heating_daily_endtime = '19:59:00'
|
283
|
-
when '5A'
|
284
|
-
cooling_daily_starttime = '20:01:00'
|
285
|
-
cooling_daily_endtime = '23:59:00'
|
286
|
-
heating_daily_starttime = '17:01:00'
|
287
|
-
heating_daily_endtime = '20:59:00'
|
288
|
-
when '6A', '7A'
|
289
|
-
cooling_daily_starttime = '16:01:00'
|
290
|
-
cooling_daily_endtime = '19:59:00'
|
291
|
-
heating_daily_starttime = '18:01:00'
|
292
|
-
heating_daily_endtime = '21:59:00'
|
293
|
-
end
|
502
|
+
if (not heating_start_date4.empty?) and (not heating_end_date4.empty?)
|
503
|
+
heating_date_result4 = validate_date_format(heating_start_date4, heating_end_date4, runner, model)
|
504
|
+
if heating_date_result4
|
505
|
+
os_heating_start_date4, os_heating_end_date4 = heating_date_result4
|
294
506
|
end
|
295
507
|
end
|
296
508
|
|
297
|
-
if
|
298
|
-
|
299
|
-
|
509
|
+
if (not heating_start_date5.empty?) and (not heating_end_date5.empty?)
|
510
|
+
heating_date_result5 = validate_date_format(heating_start_date5, heating_end_date5, runner, model)
|
511
|
+
if heating_date_result5
|
512
|
+
os_heating_start_date5, os_heating_end_date5 = heating_date_result5
|
513
|
+
end
|
300
514
|
end
|
301
|
-
|
302
|
-
|
515
|
+
|
516
|
+
# First date period
|
517
|
+
cooling_date_result1 = validate_date_format(cooling_start_date1, cooling_end_date1, runner, model)
|
518
|
+
if cooling_date_result1
|
519
|
+
os_cooling_start_date1, os_cooling_end_date1 = cooling_date_result1
|
520
|
+
else
|
521
|
+
runner.registerError('The required date period for the cooling setpoint adjustment is not in correct format!')
|
303
522
|
return false
|
304
523
|
end
|
524
|
+
# Other optional date period
|
525
|
+
os_cooling_start_date2, os_cooling_end_date2, os_cooling_start_date3, os_cooling_end_date3, os_cooling_start_date4, os_cooling_end_date4, os_cooling_start_date5, os_cooling_end_date5 = [nil]*8
|
526
|
+
if (not cooling_start_date2.empty?) and (not cooling_end_date2.empty?)
|
527
|
+
cooling_date_result2 = validate_date_format(cooling_start_date2, cooling_end_date2, runner, model)
|
528
|
+
if cooling_date_result2
|
529
|
+
os_cooling_start_date2, os_cooling_end_date2 = cooling_date_result2
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
if (not cooling_start_date3.empty?) and (not cooling_end_date3.empty?)
|
534
|
+
cooling_date_result3 = validate_date_format(cooling_start_date3, cooling_end_date3, runner, model)
|
535
|
+
if cooling_date_result3
|
536
|
+
os_cooling_start_date3, os_cooling_end_date3 = cooling_date_result3
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
if (not cooling_start_date4.empty?) and (not cooling_end_date4.empty?)
|
541
|
+
cooling_date_result4 = validate_date_format(cooling_start_date4, cooling_end_date4, runner, model)
|
542
|
+
if cooling_date_result4
|
543
|
+
os_cooling_start_date4, os_cooling_end_date4 = cooling_date_result4
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
if (not cooling_start_date5.empty?) and (not cooling_end_date5.empty?)
|
548
|
+
cooling_date_result5 = validate_date_format(cooling_start_date5, cooling_end_date5, runner, model)
|
549
|
+
if cooling_date_result5
|
550
|
+
os_cooling_start_date5, os_cooling_end_date5 = cooling_date_result5
|
551
|
+
end
|
552
|
+
end
|
305
553
|
|
306
554
|
# ruby test to see if first charter of string is uppercase letter
|
307
555
|
if cooling_adjustment < 0
|
308
|
-
runner.
|
556
|
+
runner.registerWarning('Lowering the cooling setpoint will increase energy use. Please double check your input.')
|
309
557
|
elsif cooling_adjustment.abs > 500
|
310
|
-
runner.registerError("#{cooling_adjustment} is
|
558
|
+
runner.registerError("#{cooling_adjustment} is larger than typical setpoint adjustment. Please double check your input.")
|
311
559
|
return false
|
312
560
|
elsif cooling_adjustment.abs > 50
|
313
|
-
runner.registerWarning("#{cooling_adjustment} is
|
561
|
+
runner.registerWarning("#{cooling_adjustment} is larger than typical setpoint adjustment. Please double check your input.")
|
314
562
|
end
|
315
563
|
if heating_adjustment > 0
|
316
|
-
runner.
|
564
|
+
runner.registerWarning('Raising the heating setpoint will increase energy use. Please double check your input.')
|
317
565
|
elsif heating_adjustment.abs > 500
|
318
|
-
runner.registerError("#{heating_adjustment} is
|
566
|
+
runner.registerError("#{heating_adjustment} is larger than typical setpoint adjustment. Please double check your input.")
|
319
567
|
return false
|
320
568
|
elsif heating_adjustment.abs > 50
|
321
|
-
runner.registerWarning("#{heating_adjustment} is
|
569
|
+
runner.registerWarning("#{heating_adjustment} is larger than typical setpoint adjustment. Please double check your input.")
|
322
570
|
end
|
323
571
|
|
324
572
|
# define starting units
|
325
573
|
cooling_adjustment_ip = OpenStudio::Quantity.new(cooling_adjustment, TEMP_IP_UNIT)
|
574
|
+
cooling_adjustment_si = cooling_adjustment * 5 / 9.0
|
326
575
|
heating_adjustment_ip = OpenStudio::Quantity.new(heating_adjustment, TEMP_IP_UNIT)
|
576
|
+
heating_adjustment_si = heating_adjustment * 5 / 9.0
|
327
577
|
|
328
578
|
# push schedules to hash to avoid making unnecessary duplicates
|
329
579
|
clg_set_schs = {}
|
@@ -334,56 +584,61 @@ class AdjustThermostatSetpointsByDegreesForPeakHours < OpenStudio::Measure::Mode
|
|
334
584
|
# setup new cooling setpoint schedule
|
335
585
|
clg_set_sch = thermostat.coolingSetpointTemperatureSchedule
|
336
586
|
|
337
|
-
if
|
338
|
-
runner.
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
587
|
+
if clg_set_sch.empty?
|
588
|
+
runner.registerWarning("Thermostat '#{thermostat.name}' doesn't have a cooling setpoint schedule")
|
589
|
+
else
|
590
|
+
old_clg_schedule = clg_set_sch.get
|
591
|
+
old_schedule_name = old_clg_schedule.name.to_s
|
592
|
+
# clone if not already in hash
|
593
|
+
if old_clg_schedule.to_ScheduleRuleset.is_initialized
|
594
|
+
if clg_set_schs.key?(old_schedule_name)
|
595
|
+
new_clg_set_sch = clg_set_schs[old_schedule_name]
|
596
|
+
else
|
597
|
+
# active_indices = old_clg_schedule.to_ScheduleRuleset.get.getActiveRuleIndices(os_cooling_start_date5, os_cooling_end_date5)
|
598
|
+
# active_indices.each do |i|
|
599
|
+
# runner.registerInfo("Rule applied to the fifth cooling period: #{old_clg_schedule.to_ScheduleRuleset.get.scheduleRules[i].name.to_s}")
|
600
|
+
# end
|
601
|
+
new_clg_set_sch = old_clg_schedule.clone(model)
|
602
|
+
new_clg_set_sch = new_clg_set_sch.to_Schedule.get
|
603
|
+
new_clg_set_sch.setName("#{old_schedule_name} adjusted by #{cooling_adjustment_ip}")
|
604
|
+
runner.registerInfo("Cooling schedule #{old_schedule_name} is cloned to #{new_clg_set_sch.name.to_s}")
|
605
|
+
# add to the hash
|
606
|
+
clg_set_schs[old_schedule_name] = new_clg_set_sch
|
607
|
+
end
|
608
|
+
# hook up cloned schedule to thermostat
|
609
|
+
thermostat.setCoolingSetpointTemperatureSchedule(new_clg_set_sch)
|
346
610
|
else
|
347
|
-
|
348
|
-
new_clg_set_sch = new_clg_set_sch.to_Schedule.get
|
349
|
-
new_clg_set_sch.setName("#{clg_set_sch.get.name.to_s} adjusted by #{cooling_adjustment_ip}F")
|
350
|
-
|
351
|
-
puts "cloned new name: #{new_clg_set_sch.name.to_s}"
|
352
|
-
puts new_clg_set_sch
|
353
|
-
|
354
|
-
# add to the hash
|
355
|
-
clg_set_schs[clg_set_sch.get.name.to_s] = new_clg_set_sch
|
611
|
+
runner.registerWarning("Schedule '#{old_schedule_name}' isn't a ScheduleRuleset object and won't be altered by this measure.")
|
356
612
|
end
|
357
|
-
# hook up clone to thermostat
|
358
|
-
thermostat.setCoolingSetpointTemperatureSchedule(new_clg_set_sch)
|
359
|
-
#runner.registerInfo("#{new_clg_set_sch.get.name.to_s}")
|
360
|
-
else
|
361
|
-
runner.registerWarning("Thermostat '#{thermostat.name}' doesn't have a cooling setpoint schedule")
|
362
613
|
end
|
363
614
|
|
364
615
|
# setup new heating setpoint schedule
|
365
616
|
htg_set_sch = thermostat.heatingSetpointTemperatureSchedule
|
366
|
-
if
|
367
|
-
#
|
368
|
-
|
369
|
-
|
617
|
+
if htg_set_sch.empty?
|
618
|
+
runner.registerWarning("Thermostat '#{thermostat.name}' doesn't have a heating setpoint schedule.")
|
619
|
+
else
|
620
|
+
old_htg_schedule = htg_set_sch.get
|
621
|
+
old_schedule_name = old_htg_schedule.name.to_s
|
622
|
+
if old_htg_schedule.to_ScheduleRuleset.is_initialized
|
623
|
+
if htg_set_schs.key?(old_schedule_name)
|
624
|
+
new_htg_set_sch = htg_set_schs[old_schedule_name]
|
625
|
+
else
|
626
|
+
new_htg_set_sch = old_htg_schedule.clone(model)
|
627
|
+
new_htg_set_sch = new_htg_set_sch.to_Schedule.get
|
628
|
+
new_htg_set_sch.setName("#{old_schedule_name} adjusted by #{heating_adjustment_ip}")
|
629
|
+
runner.registerInfo("Cooling schedule #{old_schedule_name} is cloned to #{new_htg_set_sch.name.to_s}")
|
630
|
+
# add to the hash
|
631
|
+
htg_set_schs[old_schedule_name] = new_htg_set_sch
|
632
|
+
end
|
633
|
+
# hook up clone to thermostat
|
634
|
+
thermostat.setHeatingSetpointTemperatureSchedule(new_htg_set_sch)
|
370
635
|
else
|
371
|
-
|
372
|
-
new_htg_set_sch = new_htg_set_sch.to_Schedule.get
|
373
|
-
new_htg_set_sch.setName("#{htg_set_sch.get.name.to_s} adjusted by #{heating_adjustment_ip}")
|
374
|
-
|
375
|
-
# add to the hash
|
376
|
-
htg_set_schs[htg_set_sch.get.name.to_s] = new_htg_set_sch
|
636
|
+
runner.registerWarning("Schedule '#{old_schedule_name}' isn't a ScheduleRuleset object and won't be altered by this measure.")
|
377
637
|
end
|
378
|
-
|
379
|
-
thermostat.setHeatingSetpointTemperatureSchedule(new_htg_set_sch)
|
380
|
-
else
|
381
|
-
runner.registerWarning("Thermostat '#{thermostat.name}' doesn't have a heating setpoint schedule.")
|
638
|
+
|
382
639
|
end
|
383
640
|
end
|
384
641
|
|
385
|
-
puts "clg_set_schs: #{clg_set_schs.inspect}"
|
386
|
-
puts "htg_set_schs: #{htg_set_schs.inspect}"
|
387
642
|
|
388
643
|
# setting up variables to use for initial and final condition
|
389
644
|
clg_sch_set_values = [] # may need to flatten this
|
@@ -399,11 +654,6 @@ class AdjustThermostatSetpointsByDegreesForPeakHours < OpenStudio::Measure::Mode
|
|
399
654
|
runner.registerWarning("Thermal zone '#{zone.name}' has a thermostat but does not appear to be conditioned.")
|
400
655
|
end
|
401
656
|
end
|
402
|
-
shift_time_cooling_start = OpenStudio::Time.new(cooling_daily_starttime)
|
403
|
-
shift_time_cooling_end = OpenStudio::Time.new(cooling_daily_endtime)
|
404
|
-
shift_time3 = OpenStudio::Time.new(0, 24, 0, 0) # not used
|
405
|
-
shift_time_heating_start = OpenStudio::Time.new(heating_daily_starttime)
|
406
|
-
shift_time_heating_end = OpenStudio::Time.new(heating_daily_endtime)
|
407
657
|
|
408
658
|
# daylightsaving adjustment added in visualization, so deprecated here
|
409
659
|
# # Check model's daylight saving period, if cooling period is within daylight saving period, shift the cooling start time and end time by one hour later
|
@@ -417,177 +667,330 @@ class AdjustThermostatSetpointsByDegreesForPeakHours < OpenStudio::Measure::Mode
|
|
417
667
|
# end
|
418
668
|
# end
|
419
669
|
|
670
|
+
applicable_flag = false
|
671
|
+
cooling_adjust_period_inputs = { "period1" => {"date_start"=>os_cooling_start_date1, "date_end"=>os_cooling_end_date1,
|
672
|
+
"time_start"=>cooling_shift_time_start1, "time_end"=>cooling_shift_time_end1},
|
673
|
+
"period2" => {"date_start"=>os_cooling_start_date2, "date_end"=>os_cooling_end_date2,
|
674
|
+
"time_start"=>cooling_shift_time_start2, "time_end"=>cooling_shift_time_end2},
|
675
|
+
"period3" => {"date_start"=>os_cooling_start_date3, "date_end"=>os_cooling_end_date3,
|
676
|
+
"time_start"=>cooling_shift_time_start3, "time_end"=>cooling_shift_time_end3},
|
677
|
+
"period4" => {"date_start"=>os_cooling_start_date4, "date_end"=>os_cooling_end_date4,
|
678
|
+
"time_start"=>cooling_shift_time_start4, "time_end"=>cooling_shift_time_end4},
|
679
|
+
"period5" => {"date_start"=>os_cooling_start_date5, "date_end"=>os_cooling_end_date5,
|
680
|
+
"time_start"=>cooling_shift_time_start5, "time_end"=>cooling_shift_time_end5} }
|
420
681
|
# make cooling schedule adjustments and rename. Put in check to skip and warn if schedule not ruleset
|
421
|
-
clg_set_schs.each do |
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
682
|
+
clg_set_schs.each do |old_sch_name, os_sch| # old name and new object for schedule
|
683
|
+
schedule = os_sch.to_ScheduleRuleset.get
|
684
|
+
rules = schedule.scheduleRules
|
685
|
+
days_covered = Array.new(7, false)
|
686
|
+
current_index = 0
|
687
|
+
# TODO: when ruleset has multiple rules for each month or couple of months instead of a full year, should first see if the period overlaps with summer/winter
|
688
|
+
if rules.length <= 0
|
689
|
+
runner.registerWarning("Cooling setpoint schedule '#{old_sch_name}' is a ScheduleRuleSet, but has no ScheduleRules associated. It won't be altered by this measure.")
|
690
|
+
else
|
691
|
+
runner.registerInfo("schedule rule set #{old_sch_name} has #{rules.length} rules.")
|
692
|
+
rules.each do |rule|
|
693
|
+
runner.registerInfo("---- Rule No.#{rule.ruleIndex}: #{rule.name.to_s}")
|
694
|
+
if rule.dateSpecificationType == "SpecificDates"
|
695
|
+
## if the rule applies to SpecificDates, collect the dates that fall into each adjustment date period,
|
696
|
+
## and create a new rule for each date period with covered specific dates
|
697
|
+
runner.registerInfo("======= The rule #{rule.name.to_s} only covers specific dates.")
|
698
|
+
## the specificDates cannot be modified in place because it's a frozen array
|
699
|
+
all_specific_dates = []
|
700
|
+
rule.specificDates.each { |date| all_specific_dates << date }
|
701
|
+
cooling_adjust_period_inputs.each do |period, period_inputs|
|
702
|
+
period_inputs["specific_dates"] = []
|
703
|
+
os_start_date = period_inputs["date_start"]
|
704
|
+
os_end_date = period_inputs["date_end"]
|
705
|
+
shift_time_start = period_inputs["time_start"]
|
706
|
+
shift_time_end = period_inputs["time_end"]
|
707
|
+
if [os_start_date, os_end_date, shift_time_start, shift_time_end].all?
|
708
|
+
rule.specificDates.each do |covered_date|
|
709
|
+
if covered_date >= os_start_date and covered_date <= os_end_date
|
710
|
+
period_inputs["specific_dates"] << covered_date
|
711
|
+
all_specific_dates.delete(covered_date)
|
712
|
+
end
|
713
|
+
end
|
714
|
+
runner.registerInfo("========= Specific dates within date range #{os_start_date.to_s} to #{os_end_date.to_s}: #{period_inputs["specific_dates"].map(&:to_s)}")
|
715
|
+
runner.registerInfo("!!! Specific dates haven't been covered: #{all_specific_dates.map(&:to_s)}")
|
716
|
+
next if period_inputs["specific_dates"].empty?
|
717
|
+
rule_period = modify_rule_for_specific_dates(rule, os_start_date, os_end_date, shift_time_start, shift_time_end,
|
718
|
+
cooling_adjustment_si, period_inputs["specific_dates"])
|
719
|
+
if rule_period
|
720
|
+
applicable_flag = true
|
721
|
+
if period == "period1"
|
722
|
+
final_clg_sch_set_values << rule_period.daySchedule.values
|
723
|
+
end
|
724
|
+
if schedule.setScheduleRuleIndex(rule_period, current_index)
|
725
|
+
current_index += 1
|
726
|
+
runner.registerInfo("-------- The rule #{rule_period.name.to_s} for #{rule_period.dateSpecificationType} is added as priority #{current_index}")
|
727
|
+
else
|
728
|
+
runner.registerError("Fail to set rule index for #{rule_period.name.to_s}.")
|
729
|
+
end
|
730
|
+
end
|
731
|
+
end
|
732
|
+
end
|
733
|
+
if all_specific_dates.empty?
|
734
|
+
## if all specific dates have been covered by new rules for each adjustment date period, remove the original rule
|
735
|
+
runner.registerInfo("The original rule is removed since no specific date left")
|
736
|
+
else
|
737
|
+
## if there's still dates left to be covered, modify the original rule to only cover these dates
|
738
|
+
## (this is just in case that the rule order was not set correctly, and the original rule is still applied to all specific dates;
|
739
|
+
## also to make the logic in OSM more clearer)
|
740
|
+
## the specificDates cannot be modified in place, so create a new rule with the left dates to replace the original rule
|
741
|
+
original_rule_update = clone_rule_with_new_dayschedule(rule, rule.name.to_s + " - dates left")
|
742
|
+
schedule.setScheduleRuleIndex(original_rule_update, current_index)
|
743
|
+
current_index += 1
|
744
|
+
all_specific_dates.each do |date|
|
745
|
+
original_rule_update.addSpecificDate(date)
|
746
|
+
end
|
747
|
+
runner.registerInfo("-------- The original rule #{rule.name.to_s} is modified to only cover the rest of the dates: #{all_specific_dates.map(&:to_s)}")
|
748
|
+
runner.registerInfo("-------- and is shifted to priority #{current_index}")
|
749
|
+
end
|
750
|
+
rule.remove
|
751
|
+
|
752
|
+
|
753
|
+
else
|
754
|
+
## If the rule applies to a DateRange, check if the DateRange overlaps with each adjustment date period
|
755
|
+
## if so, create a new rule for that adjustment date period
|
756
|
+
runner.registerInfo("******* The rule #{rule.name.to_s} covers date range #{rule.startDate.get} - #{rule.endDate.get}.")
|
757
|
+
cooling_adjust_period_inputs.each do |period, period_inputs|
|
758
|
+
os_start_date = period_inputs["date_start"]
|
759
|
+
os_end_date = period_inputs["date_end"]
|
760
|
+
shift_time_start = period_inputs["time_start"]
|
761
|
+
shift_time_end = period_inputs["time_end"]
|
762
|
+
if [os_start_date, os_end_date, shift_time_start, shift_time_end].all?
|
763
|
+
## check if the original rule applied DateRange overlaps with the adjustment date period
|
764
|
+
overlapped, new_start_dates, new_end_dates = check_date_ranges_overlap(rule, os_start_date, os_end_date)
|
765
|
+
if overlapped
|
766
|
+
new_start_dates.each_with_index do |start_date, i|
|
767
|
+
rule_period = modify_rule_for_date_period(rule, start_date, new_end_dates[i], shift_time_start,
|
768
|
+
shift_time_end, cooling_adjustment_si)
|
769
|
+
if rule_period
|
770
|
+
applicable_flag = true
|
771
|
+
if period == "period1"
|
772
|
+
checkDaysCovered(rule_period, days_covered)
|
773
|
+
final_clg_sch_set_values << rule_period.daySchedule.values
|
774
|
+
end
|
775
|
+
if schedule.setScheduleRuleIndex(rule_period, current_index)
|
776
|
+
current_index += 1
|
777
|
+
runner.registerInfo("-------- The rule #{rule_period.name.to_s} is added as priority #{current_index}")
|
778
|
+
else
|
779
|
+
runner.registerError("Fail to set rule index for #{rule_period.name.to_s}.")
|
780
|
+
end
|
781
|
+
end
|
782
|
+
end
|
783
|
+
end
|
784
|
+
|
785
|
+
end
|
786
|
+
end
|
787
|
+
## The original rule will be shifted to the currently lowest priority
|
788
|
+
## Setting the rule to an existing index will automatically push all other rules after it down
|
789
|
+
if schedule.setScheduleRuleIndex(rule, current_index)
|
790
|
+
runner.registerInfo("-------- The original rule #{rule.name.to_s} is shifted to priority #{current_index}")
|
791
|
+
current_index += 1
|
792
|
+
else
|
793
|
+
runner.registerError("Fail to set rule index for #{rule.name.to_s}.")
|
794
|
+
end
|
447
795
|
end
|
448
|
-
else
|
449
|
-
runner.registerWarning("Cooling setpoint schedule '#{sch_name}' is a ScheduleRuleSet, but has no ScheduleRules associated. It won't be altered by this measure.")
|
450
|
-
end
|
451
|
-
|
452
796
|
|
453
|
-
if days_covered.include?(false)
|
454
|
-
winter_rule1 = create_sch_rule_from_default(model, schedule, default_rule, winterStartDate1, winterEndDate1)
|
455
|
-
winter_rule2 = create_sch_rule_from_default(model, schedule, default_rule, winterStartDate2, winterEndDate2)
|
456
|
-
|
457
|
-
coverMissingDays(winter_rule1, days_covered)
|
458
|
-
coverMissingDays(winter_rule2, days_covered) # need to cover missing days for both winter rules
|
459
|
-
checkDaysCovered(winter_rule1, days_covered)
|
460
|
-
|
461
|
-
summer_rule = copy_sch_rule_for_period(model, winter_rule1, default_rule, summerStartDate, summerEndDate)
|
462
|
-
|
463
|
-
summer_day = summer_rule.daySchedule
|
464
|
-
day_time_vector = summer_day.times
|
465
|
-
day_value_vector = summer_day.values
|
466
|
-
summer_day.clearValues
|
467
|
-
|
468
|
-
summer_day = updateDaySchedule(summer_day, day_time_vector, day_value_vector, shift_time_cooling_start, shift_time_cooling_end, cooling_adjustment_ip)
|
469
|
-
clg_sch_set_values << default_rule.values # original
|
470
|
-
final_clg_sch_set_values << summer_day.values # new
|
471
797
|
end
|
472
|
-
|
473
|
-
######################################################################
|
474
|
-
else
|
475
|
-
runner.registerWarning("Schedule '#{sch_name}' isn't a ScheduleRuleset object and won't be altered by this measure.")
|
476
|
-
os_sch.remove # remove un-used clone
|
477
798
|
end
|
478
|
-
end
|
479
|
-
|
480
|
-
# make heating schedule adjustments and rename. Put in check to skip and warn if schedule not ruleset
|
481
|
-
htg_set_schs.each do |sch_name, os_sch| # old name and new object for schedule
|
482
|
-
if !os_sch.to_ScheduleRuleset.empty?
|
483
|
-
schedule = os_sch.to_ScheduleRuleset.get
|
484
|
-
default_rule = schedule.defaultDaySchedule
|
485
|
-
rules = schedule.scheduleRules
|
486
|
-
days_covered = Array.new(7, false)
|
487
|
-
|
488
|
-
if rules.length > 0
|
489
|
-
rules.each do |rule|
|
490
|
-
summer_rule = copy_sch_rule_for_period(model, rule, rule.daySchedule, summerStartDate, summerEndDate)
|
491
|
-
|
492
|
-
checkDaysCovered(summer_rule, days_covered)
|
493
|
-
|
494
|
-
winter_rule1 = rule
|
495
|
-
winter_rule1.setStartDate(winterStartDate1)
|
496
|
-
winter_rule1.setEndDate(winterEndDate1)
|
497
|
-
htg_sch_set_values << rule.daySchedule.values # original
|
498
799
|
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
800
|
+
default_day = schedule.defaultDaySchedule
|
801
|
+
if days_covered.include?(false)
|
802
|
+
runner.registerInfo("Some days use default day. Adding new scheduleRule from defaultDaySchedule for applicable date period.")
|
803
|
+
cooling_adjust_period_inputs.each do |period, period_inputs|
|
804
|
+
os_start_date = period_inputs["date_start"]
|
805
|
+
os_end_date = period_inputs["date_end"]
|
806
|
+
shift_time_start = period_inputs["time_start"]
|
807
|
+
shift_time_end = period_inputs["time_end"]
|
808
|
+
if [os_start_date, os_end_date, shift_time_start, shift_time_end].all?
|
809
|
+
new_default_rule_period = modify_default_day_for_date_period(schedule, default_day, days_covered, os_start_date, os_end_date,
|
810
|
+
shift_time_start, shift_time_end, cooling_adjustment_si)
|
811
|
+
schedule.setScheduleRuleIndex(new_default_rule_period, current_index)
|
812
|
+
applicable_flag = true
|
813
|
+
if period == 'period1'
|
814
|
+
final_clg_sch_set_values << new_default_rule_period.daySchedule.values
|
815
|
+
end
|
508
816
|
end
|
509
|
-
else
|
510
|
-
runner.registerWarning("Cooling setpoint schedule '#{sch_name}' is a ScheduleRuleSet, but has no ScheduleRules associated. It won't be altered by this measure.")
|
511
817
|
end
|
512
818
|
|
819
|
+
end
|
513
820
|
|
514
|
-
|
515
|
-
summer_rule = create_sch_rule_from_default(model, schedule, default_rule, summerStartDate, summerEndDate)
|
516
|
-
|
517
|
-
coverMissingDays(summer_rule, days_covered)
|
518
|
-
checkDaysCovered(summer_rule, days_covered)
|
519
|
-
|
520
|
-
winter_rule1 = copy_sch_rule_for_period(model, summer_rule, default_rule, winterStartDate1, winterEndDate1)
|
521
|
-
winter_day1 = winter_rule1.daySchedule
|
522
|
-
day_time_vector = winter_day1.times
|
523
|
-
day_value_vector = winter_day1.values
|
524
|
-
winter_day1.clearValues
|
821
|
+
end
|
525
822
|
|
526
|
-
winter_day1 = updateDaySchedule(winter_day1, day_time_vector, day_value_vector, shift_time_heating_start, shift_time_heating_end, heating_adjustment_ip)
|
527
823
|
|
528
|
-
|
529
|
-
|
824
|
+
######################################################################
|
825
|
+
heating_adjust_period_inputs = { "period1" => {"date_start"=>os_heating_start_date1, "date_end"=>os_heating_end_date1,
|
826
|
+
"time_start"=>heating_shift_time_start1, "time_end"=>heating_shift_time_end1},
|
827
|
+
"period2" => {"date_start"=>os_heating_start_date2, "date_end"=>os_heating_end_date2,
|
828
|
+
"time_start"=>heating_shift_time_start2, "time_end"=>heating_shift_time_end2},
|
829
|
+
"period3" => {"date_start"=>os_heating_start_date3, "date_end"=>os_heating_end_date3,
|
830
|
+
"time_start"=>heating_shift_time_start3, "time_end"=>heating_shift_time_end3},
|
831
|
+
"period4" => {"date_start"=>os_heating_start_date4, "date_end"=>os_heating_end_date4,
|
832
|
+
"time_start"=>heating_shift_time_start4, "time_end"=>heating_shift_time_end4},
|
833
|
+
"period5" => {"date_start"=>os_heating_start_date5, "date_end"=>os_heating_end_date5,
|
834
|
+
"time_start"=>heating_shift_time_start5, "time_end"=>heating_shift_time_end5} }
|
835
|
+
# make heating schedule adjustments and rename. Put in check to skip and warn if schedule not ruleset
|
836
|
+
htg_set_schs.each do |old_sch_name, os_sch| # old name and new object for schedule
|
837
|
+
schedule = os_sch.to_ScheduleRuleset.get
|
838
|
+
rules = schedule.scheduleRules
|
839
|
+
days_covered = Array.new(7, false)
|
840
|
+
current_index = 0
|
841
|
+
if rules.length <= 0
|
842
|
+
runner.registerWarning("Heating setpoint schedule '#{old_sch_name}' is a ScheduleRuleSet, but has no ScheduleRules associated. It won't be altered by this measure.")
|
843
|
+
else
|
844
|
+
runner.registerInfo("schedule rule set #{old_sch_name} has #{rules.length} rules.")
|
845
|
+
rules.each do |rule|
|
846
|
+
runner.registerInfo("---- Rule No.#{rule.ruleIndex}: #{rule.name.to_s}")
|
847
|
+
if rule.dateSpecificationType == "SpecificDates"
|
848
|
+
## if the rule applies to SpecificDates, collect the dates that fall into each adjustment date period,
|
849
|
+
## and create a new rule for each date period with covered specific dates
|
850
|
+
runner.registerInfo("======= The rule #{rule.name.to_s} only covers specific dates.")
|
851
|
+
## the specificDates cannot be modified in place because it's a frozen array
|
852
|
+
all_specific_dates = []
|
853
|
+
rule.specificDates.each { |date| all_specific_dates << date }
|
854
|
+
heating_adjust_period_inputs.each do |period, period_inputs|
|
855
|
+
period_inputs["specific_dates"] = []
|
856
|
+
os_start_date = period_inputs["date_start"]
|
857
|
+
os_end_date = period_inputs["date_end"]
|
858
|
+
shift_time_start = period_inputs["time_start"]
|
859
|
+
shift_time_end = period_inputs["time_end"]
|
860
|
+
if [os_start_date, os_end_date, shift_time_start, shift_time_end].all?
|
861
|
+
rule.specificDates.each do |covered_date|
|
862
|
+
if covered_date >= os_start_date and covered_date <= os_end_date
|
863
|
+
period_inputs["specific_dates"] << covered_date
|
864
|
+
all_specific_dates.delete(covered_date)
|
865
|
+
end
|
866
|
+
end
|
867
|
+
runner.registerInfo("========= Specific dates within date range #{os_start_date.to_s} to #{os_end_date.to_s}: #{period_inputs["specific_dates"].map(&:to_s)}")
|
868
|
+
rule_period = modify_rule_for_specific_dates(rule, os_start_date, os_end_date, shift_time_start, shift_time_end,
|
869
|
+
heating_adjustment_si, period_inputs["specific_dates"])
|
870
|
+
if rule_period
|
871
|
+
applicable_flag = true
|
872
|
+
if period == "period1"
|
873
|
+
final_htg_sch_set_values << rule_period.daySchedule.values
|
874
|
+
end
|
875
|
+
if schedule.setScheduleRuleIndex(rule_period, current_index)
|
876
|
+
current_index += 1
|
877
|
+
runner.registerInfo("-------- The rule #{rule_period.name.to_s} for #{rule_period.dateSpecificationType} is added as priority #{current_index}")
|
878
|
+
else
|
879
|
+
runner.registerError("Fail to set rule index for #{rule_period.name.to_s}.")
|
880
|
+
end
|
881
|
+
end
|
882
|
+
end
|
883
|
+
end
|
884
|
+
if all_specific_dates.empty?
|
885
|
+
## if all specific dates have been covered by new rules for each adjustment date period, remove the original rule
|
886
|
+
runner.registerInfo("The original rule is removed since no specific date left")
|
887
|
+
else
|
888
|
+
## if there's still dates left to be covered, modify the original rule to only cover these dates
|
889
|
+
## (this is just in case that the rule order was not set correctly, and the original rule is still applied to all specific dates;
|
890
|
+
## also to make the logic in OSM more clearer)
|
891
|
+
## the specificDates cannot be modified in place, so create a new rule with the left dates to replace the original rule
|
892
|
+
original_rule_update = clone_rule_with_new_dayschedule(rule, rule.name.to_s + " - dates left")
|
893
|
+
schedule.setScheduleRuleIndex(original_rule_update, current_index)
|
894
|
+
current_index += 1
|
895
|
+
all_specific_dates.each do |date|
|
896
|
+
original_rule_update.addSpecificDate(date)
|
897
|
+
end
|
898
|
+
runner.registerInfo("-------- The original rule #{rule.name.to_s} is modified to only cover the rest of the dates: #{all_specific_dates.map(&:to_s)}")
|
899
|
+
runner.registerInfo("-------- and is shifted to priority #{current_index}")
|
900
|
+
end
|
901
|
+
rule.remove
|
902
|
+
|
903
|
+
else
|
904
|
+
heating_adjust_period_inputs.each do |period, period_inputs|
|
905
|
+
os_start_date = period_inputs["date_start"]
|
906
|
+
os_end_date = period_inputs["date_end"]
|
907
|
+
shift_time_start = period_inputs["time_start"]
|
908
|
+
shift_time_end = period_inputs["time_end"]
|
909
|
+
if [os_start_date, os_end_date, shift_time_start, shift_time_end].all?
|
910
|
+
overlapped, new_start_dates, new_end_dates = check_date_ranges_overlap(rule, os_start_date, os_end_date)
|
911
|
+
if overlapped
|
912
|
+
new_start_dates.each_with_index do |start_date, i|
|
913
|
+
rule_period = modify_rule_for_date_period(rule, start_date, new_end_dates[i], shift_time_start,
|
914
|
+
shift_time_end, heating_adjustment_si)
|
915
|
+
if rule_period
|
916
|
+
applicable_flag = true
|
917
|
+
if period == "period1"
|
918
|
+
checkDaysCovered(rule_period, days_covered)
|
919
|
+
final_htg_sch_set_values << rule_period.daySchedule.values
|
920
|
+
end
|
921
|
+
if schedule.setScheduleRuleIndex(rule_period, current_index)
|
922
|
+
current_index += 1
|
923
|
+
runner.registerInfo("-------- The rule #{rule_period.name.to_s} is added as priority #{current_index}")
|
924
|
+
else
|
925
|
+
runner.registerError("Fail to set rule index for #{rule_period.name.to_s}.")
|
926
|
+
end
|
927
|
+
end
|
928
|
+
end
|
929
|
+
end
|
930
|
+
end
|
931
|
+
end
|
932
|
+
# The original rule will be shifted to the currently lowest priority
|
933
|
+
# Setting the rule to an existing index will automatically push all other rules after it down
|
934
|
+
if schedule.setScheduleRuleIndex(rule, current_index)
|
935
|
+
runner.registerInfo("-------- The original rule #{rule.name.to_s} is shifted to priority #{current_index}")
|
936
|
+
current_index += 1
|
937
|
+
else
|
938
|
+
runner.registerError("Fail to set rule index for #{rule.name.to_s}.")
|
939
|
+
end
|
940
|
+
end
|
530
941
|
|
531
|
-
winter_rule2 = copy_sch_rule_for_period(model, winter_rule1, winter_rule1.daySchedule, winterStartDate2, winterEndDate2)
|
532
942
|
end
|
943
|
+
end
|
533
944
|
|
534
|
-
|
535
|
-
|
536
|
-
|
945
|
+
default_day = schedule.defaultDaySchedule
|
946
|
+
if days_covered.include?(false)
|
947
|
+
runner.registerInfo("Some days use default day. Adding new scheduleRule from defaultDaySchedule for applicable date period.")
|
948
|
+
heating_adjust_period_inputs.each do |period, period_inputs|
|
949
|
+
os_start_date = period_inputs["date_start"]
|
950
|
+
os_end_date = period_inputs["date_end"]
|
951
|
+
shift_time_start = period_inputs["time_start"]
|
952
|
+
shift_time_end = period_inputs["time_end"]
|
953
|
+
if [os_start_date, os_end_date, shift_time_start, shift_time_end].all?
|
954
|
+
new_default_rule_period = modify_default_day_for_date_period(schedule, default_day, days_covered, os_start_date, os_end_date,
|
955
|
+
shift_time_start, shift_time_end, heating_adjustment_si)
|
956
|
+
schedule.setScheduleRuleIndex(new_default_rule_period, current_index)
|
957
|
+
applicable_flag = true
|
958
|
+
if period == 'period1'
|
959
|
+
final_htg_sch_set_values << new_default_rule_period.daySchedule.values
|
960
|
+
end
|
961
|
+
end
|
962
|
+
end
|
537
963
|
end
|
538
964
|
end
|
539
965
|
|
540
|
-
# get min and max heating and cooling and convert to IP
|
541
|
-
clg_sch_set_values = clg_sch_set_values.flatten
|
542
|
-
htg_sch_set_values = htg_sch_set_values.flatten
|
543
|
-
|
544
|
-
puts "clg_sch_set_values: #{clg_sch_set_values.inspect}"
|
545
|
-
puts "htg_sch_set_values: #{htg_sch_set_values.inspect}"
|
546
|
-
|
547
|
-
# set NA flag if can't get values for schedules (e.g. if all compact)
|
548
|
-
applicable_flag = false
|
549
966
|
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
967
|
+
model.getEnergyManagementSystemActuators.each do |ems_actuator|
|
968
|
+
if ems_actuator.actuatedComponent.is_initialized
|
969
|
+
old_sch_name = ems_actuator.actuatedComponent.get.name.to_s
|
970
|
+
if clg_set_schs.key?old_sch_name
|
971
|
+
replaced_sch = clg_set_schs[old_sch_name]
|
972
|
+
ems_actuator.setActuatedComponent(replaced_sch)
|
973
|
+
runner.registerInfo("The actuator component for EMS actuator #{ems_actuator.name.to_s} has been changed from #{old_sch_name} to #{replaced_sch.name.to_s}")
|
974
|
+
elsif htg_set_schs.key?old_sch_name
|
975
|
+
replaced_sch = htg_set_schs[old_sch_name]
|
976
|
+
ems_actuator.setActuatedComponent(replaced_sch)
|
977
|
+
runner.registerInfo("The actuator component for EMS actuator #{ems_actuator.name.to_s} has been changed from #{old_sch_name} to #{replaced_sch.name.to_s}")
|
978
|
+
end
|
979
|
+
end
|
560
980
|
end
|
561
981
|
|
562
|
-
# get min and max if values exist
|
563
|
-
if !htg_sch_set_values.empty?
|
564
|
-
min_htg_si = OpenStudio::Quantity.new(htg_sch_set_values.min, TEMP_SI_UNIT)
|
565
|
-
max_htg_si = OpenStudio::Quantity.new(htg_sch_set_values.max, TEMP_SI_UNIT)
|
566
|
-
min_htg_ip = OpenStudio.convert(min_htg_si, TEMP_IP_UNIT).get
|
567
|
-
max_htg_ip = OpenStudio.convert(max_htg_si, TEMP_IP_UNIT).get
|
568
|
-
applicable_flag = true
|
569
|
-
else
|
570
|
-
min_htg_ip = 'NA'
|
571
|
-
max_htg_ip = 'NA'
|
572
|
-
end
|
573
982
|
|
574
983
|
# not applicable if no schedules can be altered
|
575
984
|
if applicable_flag == false
|
576
985
|
runner.registerAsNotApplicable('No thermostat schedules in the models could be altered.')
|
577
986
|
end
|
578
987
|
|
579
|
-
# reporting initial condition of model
|
580
|
-
starting_spaces = model.getSpaces
|
581
|
-
runner.registerInitialCondition("Initial cooling setpoints used in the model range from #{min_clg_ip} to #{max_clg_ip}. Initial heating setpoints used in the model range from #{min_htg_ip} to #{max_htg_ip}.")
|
582
|
-
|
583
988
|
# get min and max heating and cooling and convert to IP for final
|
584
989
|
final_clg_sch_set_values = final_clg_sch_set_values.flatten
|
585
990
|
final_htg_sch_set_values = final_htg_sch_set_values.flatten
|
586
991
|
|
587
|
-
puts "final_clg_sch_set_values: #{final_clg_sch_set_values.inspect}"
|
588
|
-
puts "final_htg_sch_set_values: #{final_htg_sch_set_values.inspect}"
|
589
992
|
|
590
|
-
if !
|
993
|
+
if !final_clg_sch_set_values.empty?
|
591
994
|
final_min_clg_si = OpenStudio::Quantity.new(final_clg_sch_set_values.min, TEMP_SI_UNIT)
|
592
995
|
final_max_clg_si = OpenStudio::Quantity.new(final_clg_sch_set_values.max, TEMP_SI_UNIT)
|
593
996
|
final_min_clg_ip = OpenStudio.convert(final_min_clg_si, TEMP_IP_UNIT).get
|
@@ -598,7 +1001,7 @@ class AdjustThermostatSetpointsByDegreesForPeakHours < OpenStudio::Measure::Mode
|
|
598
1001
|
end
|
599
1002
|
|
600
1003
|
# get min and max if values exist
|
601
|
-
if !
|
1004
|
+
if !final_htg_sch_set_values.empty?
|
602
1005
|
final_min_htg_si = OpenStudio::Quantity.new(final_htg_sch_set_values.min, TEMP_SI_UNIT)
|
603
1006
|
final_max_htg_si = OpenStudio::Quantity.new(final_htg_sch_set_values.max, TEMP_SI_UNIT)
|
604
1007
|
final_min_htg_ip = OpenStudio.convert(final_min_htg_si, TEMP_IP_UNIT).get
|
@@ -610,12 +1013,117 @@ class AdjustThermostatSetpointsByDegreesForPeakHours < OpenStudio::Measure::Mode
|
|
610
1013
|
|
611
1014
|
# reporting final condition of model
|
612
1015
|
finishing_spaces = model.getSpaces
|
613
|
-
runner.registerFinalCondition("Final cooling setpoints used in the model range from #{final_min_clg_ip} to #{final_max_clg_ip}. Final heating setpoints used in the model range from #{final_min_htg_ip} to #{final_max_htg_ip}
|
1016
|
+
runner.registerFinalCondition("Final cooling setpoints used in the model range from #{final_min_clg_ip} to #{final_max_clg_ip}. Final heating setpoints used in the model range from #{final_min_htg_ip} to #{final_max_htg_ip}.")
|
614
1017
|
|
615
1018
|
return true
|
616
1019
|
end
|
617
1020
|
|
618
1021
|
|
1022
|
+
def check_date_ranges_overlap(rule, adjust_start_date, adjust_end_date)
|
1023
|
+
## check if the original rule applied DateRange overlaps with the adjustment date period
|
1024
|
+
overlapped = false
|
1025
|
+
new_start_dates = []
|
1026
|
+
new_end_dates = []
|
1027
|
+
if rule.endDate.get >= rule.startDate.get and rule.startDate.get <= adjust_end_date and rule.endDate.get >= adjust_start_date
|
1028
|
+
overlapped = true
|
1029
|
+
new_start_dates << [adjust_start_date, rule.startDate.get].max
|
1030
|
+
new_end_dates << [adjust_end_date, rule.endDate.get].min
|
1031
|
+
elsif rule.endDate.get < rule.startDate.get
|
1032
|
+
## If the DateRange has a endDate < startDate, the range wraps around the year.
|
1033
|
+
if rule.endDate.get >= adjust_start_date
|
1034
|
+
overlapped = true
|
1035
|
+
new_start_dates << adjust_start_date
|
1036
|
+
new_end_dates << rule.endDate.get
|
1037
|
+
end
|
1038
|
+
if rule.startDate.get <= adjust_end_date
|
1039
|
+
overlapped = true
|
1040
|
+
new_start_dates << rule.startDate.get
|
1041
|
+
new_end_dates << adjust_end_date
|
1042
|
+
end
|
1043
|
+
end
|
1044
|
+
return overlapped, new_start_dates, new_end_dates
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
def clone_rule_with_new_dayschedule(original_rule, new_rule_name)
|
1048
|
+
## Cloning a scheduleRule will automatically clone the daySchedule associated with it, but it's a shallow copy,
|
1049
|
+
## because the daySchedule is a resource that can be used by many scheduleRule
|
1050
|
+
## Therefore, once the daySchedule is modified for the cloned scheduleRule, the original daySchedule is also changed
|
1051
|
+
## Also, there's no function to assign a new daySchedule to the existing scheduleRule,
|
1052
|
+
## so the only way to clone the scheduleRule but change the daySchedule is to construct a new scheduleRule with a daySchedule passed in
|
1053
|
+
## and copy all other settings from the original scheduleRule
|
1054
|
+
rule_period = OpenStudio::Model::ScheduleRule.new(original_rule.scheduleRuleset, original_rule.daySchedule)
|
1055
|
+
rule_period.setName(new_rule_name)
|
1056
|
+
rule_period.setApplySunday(original_rule.applySunday)
|
1057
|
+
rule_period.setApplyMonday(original_rule.applyMonday)
|
1058
|
+
rule_period.setApplyTuesday(original_rule.applyTuesday)
|
1059
|
+
rule_period.setApplyWednesday(original_rule.applyWednesday)
|
1060
|
+
rule_period.setApplyThursday(original_rule.applyThursday)
|
1061
|
+
rule_period.setApplyFriday(original_rule.applyFriday)
|
1062
|
+
rule_period.setApplySaturday(original_rule.applySaturday)
|
1063
|
+
return rule_period
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
def modify_rule_for_date_period(original_rule, os_start_date, os_end_date, shift_time_start, shift_time_end, adjustment)
|
1067
|
+
# The cloned scheduleRule will automatically belongs to the originally scheduleRuleSet
|
1068
|
+
# rule_period = original_rule.clone(model).to_ScheduleRule.get
|
1069
|
+
# rule_period.daySchedule = original_rule.daySchedule.clone(model)
|
1070
|
+
new_rule_name = "#{original_rule.name.to_s} with DF for #{os_start_date.to_s} to #{os_end_date.to_s}"
|
1071
|
+
rule_period = clone_rule_with_new_dayschedule(original_rule, new_rule_name)
|
1072
|
+
day_rule_period = rule_period.daySchedule
|
1073
|
+
day_time_vector = day_rule_period.times
|
1074
|
+
day_value_vector = day_rule_period.values
|
1075
|
+
if day_time_vector.empty?
|
1076
|
+
return false
|
1077
|
+
end
|
1078
|
+
day_rule_period.clearValues
|
1079
|
+
updateDaySchedule(day_rule_period, day_time_vector, day_value_vector, shift_time_start, shift_time_end, adjustment)
|
1080
|
+
if rule_period
|
1081
|
+
rule_period.setStartDate(os_start_date)
|
1082
|
+
rule_period.setEndDate(os_end_date)
|
1083
|
+
end
|
1084
|
+
return rule_period
|
1085
|
+
end
|
1086
|
+
|
1087
|
+
def modify_rule_for_specific_dates(original_rule, os_start_date, os_end_date, shift_time_start, shift_time_end,
|
1088
|
+
adjustment, applied_dates)
|
1089
|
+
new_rule_name = "#{original_rule.name.to_s} with DF for #{os_start_date.to_s} to #{os_end_date.to_s}"
|
1090
|
+
rule_period = clone_rule_with_new_dayschedule(original_rule, new_rule_name)
|
1091
|
+
day_rule_period = rule_period.daySchedule
|
1092
|
+
day_time_vector = day_rule_period.times
|
1093
|
+
day_value_vector = day_rule_period.values
|
1094
|
+
if day_time_vector.empty?
|
1095
|
+
return false
|
1096
|
+
end
|
1097
|
+
day_rule_period.clearValues
|
1098
|
+
updateDaySchedule(day_rule_period, day_time_vector, day_value_vector, shift_time_start, shift_time_end, adjustment)
|
1099
|
+
if rule_period
|
1100
|
+
applied_dates.each do |date|
|
1101
|
+
rule_period.addSpecificDate(date)
|
1102
|
+
end
|
1103
|
+
end
|
1104
|
+
return rule_period
|
1105
|
+
end
|
1106
|
+
|
1107
|
+
def modify_default_day_for_date_period(schedule_set, default_day, days_covered, os_start_date, os_end_date,
|
1108
|
+
shift_time_start, shift_time_end, adjustment)
|
1109
|
+
# the new rule created for the ScheduleRuleSet by default has the highest priority (ruleIndex=0)
|
1110
|
+
new_default_rule = OpenStudio::Model::ScheduleRule.new(schedule_set, default_day)
|
1111
|
+
new_default_rule.setName("#{schedule_set.name.to_s} default day with DF for #{os_start_date.to_s} to #{os_end_date.to_s}")
|
1112
|
+
new_default_rule.setStartDate(os_start_date)
|
1113
|
+
new_default_rule.setEndDate(os_end_date)
|
1114
|
+
coverMissingDays(new_default_rule, days_covered)
|
1115
|
+
new_default_day = new_default_rule.daySchedule
|
1116
|
+
day_time_vector = new_default_day.times
|
1117
|
+
day_value_vector = new_default_day.values
|
1118
|
+
new_default_day.clearValues
|
1119
|
+
new_default_day = updateDaySchedule(new_default_day, day_time_vector, day_value_vector, shift_time_start, shift_time_end, adjustment)
|
1120
|
+
# schedule_set.setScheduleRuleIndex(new_default_rule, 0)
|
1121
|
+
return new_default_rule
|
1122
|
+
# TODO: if the scheduleRuleSet has holidaySchedule (which is a ScheduleDay), it cannot be altered
|
1123
|
+
end
|
1124
|
+
|
1125
|
+
|
1126
|
+
|
619
1127
|
def checkDaysCovered(sch_rule, sch_day_covered)
|
620
1128
|
if sch_rule.applySunday
|
621
1129
|
sch_day_covered[0] = true
|
@@ -665,9 +1173,44 @@ class AdjustThermostatSetpointsByDegreesForPeakHours < OpenStudio::Measure::Mode
|
|
665
1173
|
|
666
1174
|
end
|
667
1175
|
|
1176
|
+
def updateDaySchedule(sch_day, vec_time, vec_value, time_begin, time_end, adjustment)
|
1177
|
+
count = 0
|
1178
|
+
vec_time.each_with_index do |exist_timestamp, i|
|
1179
|
+
adjusted_value = vec_value[i] + adjustment
|
1180
|
+
if exist_timestamp > time_begin && exist_timestamp < time_end && count == 0
|
1181
|
+
sch_day.addValue(time_begin, vec_value[i])
|
1182
|
+
sch_day.addValue(exist_timestamp, adjusted_value)
|
1183
|
+
count = 1
|
1184
|
+
elsif exist_timestamp == time_end && count == 0
|
1185
|
+
sch_day.addValue(time_begin, vec_value[i])
|
1186
|
+
sch_day.addValue(exist_timestamp, adjusted_value)
|
1187
|
+
count = 2
|
1188
|
+
elsif exist_timestamp == time_begin && count == 0
|
1189
|
+
sch_day.addValue(exist_timestamp, vec_value[i])
|
1190
|
+
count = 1
|
1191
|
+
elsif exist_timestamp > time_end && count == 0
|
1192
|
+
sch_day.addValue(time_begin, vec_value[i])
|
1193
|
+
sch_day.addValue(time_end, adjusted_value)
|
1194
|
+
sch_day.addValue(exist_timestamp, vec_value[i])
|
1195
|
+
count = 2
|
1196
|
+
elsif exist_timestamp > time_begin && exist_timestamp < time_end && count==1
|
1197
|
+
sch_day.addValue(exist_timestamp, adjusted_value)
|
1198
|
+
elsif exist_timestamp == time_end && count==1
|
1199
|
+
sch_day.addValue(exist_timestamp, adjusted_value)
|
1200
|
+
count = 2
|
1201
|
+
elsif exist_timestamp > time_end && count == 1
|
1202
|
+
sch_day.addValue(time_end, adjusted_value)
|
1203
|
+
sch_day.addValue(exist_timestamp, vec_value[i])
|
1204
|
+
count = 2
|
1205
|
+
else
|
1206
|
+
sch_day.addValue(exist_timestamp, vec_value[i])
|
1207
|
+
end
|
1208
|
+
end
|
1209
|
+
return sch_day
|
1210
|
+
end
|
668
1211
|
|
669
1212
|
# TODO check if this function works
|
670
|
-
def
|
1213
|
+
def updateDaySchedule_old(sch_day, vec_time, vec_value, time_begin, time_end, adjustment)
|
671
1214
|
# indicator: 0:schedule unchanged, 1:schedule changed at least once, 2:schedule change completed
|
672
1215
|
count = 0
|
673
1216
|
for i in 0..(vec_time.size - 1)
|
@@ -700,28 +1243,6 @@ class AdjustThermostatSetpointsByDegreesForPeakHours < OpenStudio::Measure::Mode
|
|
700
1243
|
return sch_day
|
701
1244
|
end
|
702
1245
|
|
703
|
-
# copy ScheduleRule sch_rule, copy ScheduleDay sch_day and assign to new schedule rule
|
704
|
-
def copy_sch_rule_for_period(model, sch_rule, sch_day, start_date, end_date)
|
705
|
-
new_rule = sch_rule.clone(model).to_ScheduleRule.get
|
706
|
-
new_rule.setStartDate(start_date)
|
707
|
-
new_rule.setEndDate(end_date)
|
708
|
-
|
709
|
-
new_day_sch = sch_day.clone(model)
|
710
|
-
new_day_sch.setParent(new_rule)
|
711
|
-
|
712
|
-
return new_rule
|
713
|
-
end
|
714
|
-
|
715
|
-
def create_sch_rule_from_default(model, sch_ruleset, default_sch_fule, start_date, end_date)
|
716
|
-
new_rule = OpenStudio::Model::ScheduleRule.new(sch_ruleset)
|
717
|
-
new_rule.setStartDate(start_date)
|
718
|
-
new_rule.setEndDate(end_date)
|
719
|
-
|
720
|
-
new_day_sch = default_sch_fule.clone(model)
|
721
|
-
new_day_sch.setParent(new_rule)
|
722
|
-
|
723
|
-
return new_rule
|
724
|
-
end
|
725
1246
|
end
|
726
1247
|
|
727
1248
|
|