openstudio-load-flexibility-measures 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +4 -0
- data/LICENSE.md +1 -1
- data/doc_templates/LICENSE.md +1 -1
- data/doc_templates/copyright_erb.txt +1 -1
- data/doc_templates/copyright_js.txt +1 -1
- data/doc_templates/copyright_ruby.txt +1 -1
- data/lib/measures/ShiftScheduleByType/LICENSE.md +27 -0
- data/lib/measures/ShiftScheduleByType/README.md +40 -0
- data/lib/measures/ShiftScheduleByType/README.md.erb +42 -0
- data/lib/measures/ShiftScheduleByType/measure.rb +385 -0
- data/lib/measures/ShiftScheduleByType/measure.xml +115 -0
- data/lib/measures/ShiftScheduleByType/tests/3Story2Space.osm +3030 -0
- data/lib/measures/ShiftScheduleByType/tests/ShiftScheduleByType_Test.rb +193 -0
- data/lib/measures/add_central_ice_storage/LICENSE.md +1 -1
- data/lib/measures/add_central_ice_storage/measure.rb +1 -1
- data/lib/measures/add_central_ice_storage/measure.xml +6 -6
- data/lib/measures/add_central_ice_storage/resources/OsLib_Schedules.rb +1 -1
- data/lib/measures/add_central_ice_storage/tests/add_central_ice_storage_test.rb +1 -1
- data/lib/measures/add_hpwh/LICENSE.md +1 -1
- data/lib/measures/add_hpwh/measure.rb +1 -1
- data/lib/measures/add_hpwh/measure.xml +5 -5
- data/lib/measures/add_hpwh/tests/add_hpwh_test.rb +1 -1
- data/lib/measures/add_packaged_ice_storage/LICENSE.md +1 -1
- data/lib/measures/add_packaged_ice_storage/measure.rb +1 -1
- data/lib/measures/add_packaged_ice_storage/measure.xml +5 -5
- data/lib/measures/add_packaged_ice_storage/tests/add_packaged_ice_storage_test.rb +1 -1
- data/lib/openstudio/load_flexibility_measures/version.rb +2 -2
- data/lib/openstudio/load_flexibility_measures.rb +1 -1
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f82406e85fdfe5b319faece1421d911dc44a19d5c027353dcf067f43fcc36ba0
|
4
|
+
data.tar.gz: 85c43e9c24d407e2c1f56932ff96eac28b12344396d5ae6e0ac86d6d16c36ae6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19a523c49d23e17579ee80cd5c71d3895a749663fce80302ac93b92ac74834c0932bc4475851e8b6a400585803b9ff08d46eae68bf007c00acc27c147501ddf0
|
7
|
+
data.tar.gz: 6e8cbcc894b9d68c55a70274f4044d8e7c19dfc6b853891103d20c10120224759ba00d62b6367446a74a3670d90947891cdc9d540f360ff91f22e4e1ebd69583
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# OpenStudio Load Flexibility Measures Gem
|
2
2
|
|
3
|
+
## Version 0.5.1
|
4
|
+
- Added the ShiftScheduleByType measure - [#47](https://github.com/NREL/openstudio-load-flexibility-measures-gem/issues/47)
|
5
|
+
- Updating licenses and measure versions / checksums for 2022
|
6
|
+
|
3
7
|
## Version 0.5.0
|
4
8
|
* Updated OS Standards dependency to 0.2.16
|
5
9
|
* Fixed [#41](https://github.com/NREL/openstudio-load-flexibility-measures-gem/issues/41), Error in applying add_hpwh measure with "non-simplified" options to MF prototype building in OS 3.3
|
data/LICENSE.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
OpenStudio(R), Copyright (c) 2008-
|
1
|
+
OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC. All rights reserved.
|
2
2
|
|
3
3
|
Redistribution and use in source and binary forms, with or without modification, are permitted
|
4
4
|
provided that the following conditions are met:
|
data/doc_templates/LICENSE.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
OpenStudio(R), Copyright (c) 2008-
|
1
|
+
OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC. All rights reserved.
|
2
2
|
|
3
3
|
Redistribution and use in source and binary forms, with or without modification, are permitted
|
4
4
|
provided that the following conditions are met:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<%
|
2
2
|
# *******************************************************************************
|
3
|
-
# OpenStudio(R), Copyright (c) 2008-
|
3
|
+
# OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC.
|
4
4
|
# All rights reserved.
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
6
6
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,4 +1,4 @@
|
|
1
1
|
/* @preserve
|
2
|
-
* OpenStudio(R), Copyright (c) 2008-
|
2
|
+
* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC. All rights reserved.
|
3
3
|
* Use of this source code is governed by a BSD-style license that can be found at openstudio.net/license.
|
4
4
|
*/
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -0,0 +1,27 @@
|
|
1
|
+
OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted
|
4
|
+
provided that the following conditions are met:
|
5
|
+
|
6
|
+
(1) Redistributions of source code must retain the above copyright notice, this list of conditions
|
7
|
+
and the following disclaimer.
|
8
|
+
|
9
|
+
(2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
10
|
+
and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
11
|
+
|
12
|
+
(3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse
|
13
|
+
or promote products derived from this software without specific prior written permission from the
|
14
|
+
respective party.
|
15
|
+
|
16
|
+
(4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other
|
17
|
+
derivative works may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar
|
18
|
+
designation without specific prior written permission from Alliance for Sustainable Energy, LLC.
|
19
|
+
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
21
|
+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
22
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES GOVERNMENT,
|
23
|
+
OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
25
|
+
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
26
|
+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
27
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
###### (Automatically generated documentation)
|
4
|
+
|
5
|
+
# ShiftScheduleByType
|
6
|
+
|
7
|
+
## Description
|
8
|
+
This measure was developed for the URBANopt Class Project and shifts specific building schedules if they include cooling ("CLG"), heating ("HTG"), or air ("Air") strings. The measure will shift these chosen schedules by an amount specified by the user and will also output a .csv file of the schedules before and after the shift.
|
9
|
+
|
10
|
+
## Modeler Description
|
11
|
+
Depending on the model's thermostat deadband settings, shifting of exclusively cooling or heating schedules can result in EnergyPlus deadband errors. It is recommended to shift both cooling and heating schedules using the 'coolheat' option for schedchoice. If no schedules for the current model include the cooling, heating, or air strings, none will be shifted. Schedules including the string 'setback' are intentionally excluded from shifts in order to prevent EnergyPlus errors.
|
12
|
+
|
13
|
+
## Measure Type
|
14
|
+
ModelMeasure
|
15
|
+
|
16
|
+
## Taxonomy
|
17
|
+
|
18
|
+
|
19
|
+
## Arguments
|
20
|
+
|
21
|
+
|
22
|
+
### Shift Schedule Profiles Forward (24hr, use decimal for sub hour and negative values for backward shift).
|
23
|
+
|
24
|
+
**Name:** shift_value,
|
25
|
+
**Type:** Double,
|
26
|
+
**Units:** ,
|
27
|
+
**Required:** true,
|
28
|
+
**Model Dependent:** false
|
29
|
+
|
30
|
+
### Choose which schedule class(es) to shift by the specified shift value
|
31
|
+
|
32
|
+
**Name:** schedchoice,
|
33
|
+
**Type:** Choice,
|
34
|
+
**Units:** ,
|
35
|
+
**Required:** true,
|
36
|
+
**Model Dependent:** false
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<%#= README.md.erb is used to auto-generate README.md. %>
|
2
|
+
<%#= To manually maintain README.md throw away README.md.erb and manually edit README.md %>
|
3
|
+
###### (Automatically generated documentation)
|
4
|
+
|
5
|
+
# <%= name %>
|
6
|
+
|
7
|
+
## Description
|
8
|
+
<%= description %>
|
9
|
+
|
10
|
+
## Modeler Description
|
11
|
+
<%= modelerDescription %>
|
12
|
+
|
13
|
+
## Measure Type
|
14
|
+
<%= measureType %>
|
15
|
+
|
16
|
+
## Taxonomy
|
17
|
+
<%= taxonomy %>
|
18
|
+
|
19
|
+
## Arguments
|
20
|
+
|
21
|
+
<% arguments.each do |argument| %>
|
22
|
+
### <%= argument[:display_name] %>
|
23
|
+
<%= argument[:description] %>
|
24
|
+
**Name:** <%= argument[:name] %>,
|
25
|
+
**Type:** <%= argument[:type] %>,
|
26
|
+
**Units:** <%= argument[:units] %>,
|
27
|
+
**Required:** <%= argument[:required] %>,
|
28
|
+
**Model Dependent:** <%= argument[:model_dependent] %>
|
29
|
+
<% end %>
|
30
|
+
|
31
|
+
<% if arguments.size == 0 %>
|
32
|
+
<%= "This measure does not have any user arguments" %>
|
33
|
+
<% end %>
|
34
|
+
|
35
|
+
<% if outputs.size > 0 %>
|
36
|
+
## Outputs
|
37
|
+
<% output_names = [] %>
|
38
|
+
<% outputs.each do |output| %>
|
39
|
+
<% output_names << output[:display_name] %>
|
40
|
+
<% end %>
|
41
|
+
<%= output_names.join(", ") %>
|
42
|
+
<% end %>
|
@@ -0,0 +1,385 @@
|
|
1
|
+
# *******************************************************************************
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
+
# may be used to endorse or promote products derived from this software without
|
16
|
+
# specific prior written permission from the respective party.
|
17
|
+
#
|
18
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
24
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
25
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
26
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
27
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
28
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
29
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
30
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
31
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
32
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
33
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
# *******************************************************************************
|
35
|
+
|
36
|
+
# see the URL below for information on how to write OpenStudio measures
|
37
|
+
# http://openstudio.nrel.gov/openstudio-measure-writing-guide
|
38
|
+
|
39
|
+
# see the URL below for access to C++ documentation on model objects (click on "model" in the main window to view model objects)
|
40
|
+
# http://openstudio.nrel.gov/sites/openstudio.nrel.gov/files/nv_data/cpp_documentation_it/model/html/namespaces.html
|
41
|
+
|
42
|
+
# This measure was created as an adaptation of the "ShiftScheduleProfileTime" common
|
43
|
+
# measure. This measure adds the ability to choose types (Cooling/Heating) of
|
44
|
+
# schedules to shift instead of choosing all schedules or one schedule.
|
45
|
+
|
46
|
+
# Start the measure
|
47
|
+
class ShiftScheduleByType < OpenStudio::Measure::ModelMeasure
|
48
|
+
# define the name that a user will see, this method may be deprecated as
|
49
|
+
# the display name in PAT comes from the name field in measure.xml
|
50
|
+
def name
|
51
|
+
return 'ShiftScheduleByType'
|
52
|
+
end
|
53
|
+
|
54
|
+
# human readable description
|
55
|
+
def description
|
56
|
+
return 'This measure was developed for the URBANopt Class Project and shifts specific building schedules if they include cooling ("CLG"), heating ("HTG"), or air ("Air") strings. The measure will shift these chosen schedules by an amount specified by the user and will also output a .csv file of the schedules before and after the shift.'
|
57
|
+
end
|
58
|
+
|
59
|
+
# human readable description of modeling approach
|
60
|
+
def modeler_description
|
61
|
+
return "Depending on the model's thermostat deadband settings, shifting of exclusively cooling or heating schedules can result in EnergyPlus deadband errors. It is recommended to shift both cooling and heating schedules using the 'coolheat' option for schedchoice. If no schedules for the current model include the cooling, heating, or air strings, none will be shifted. Schedules including the string 'setback' are intentionally excluded from shifts in order to prevent EnergyPlus errors."
|
62
|
+
end
|
63
|
+
|
64
|
+
# Define the arguments that the user will input
|
65
|
+
def arguments(model)
|
66
|
+
args = OpenStudio::Measure::OSArgumentVector.new
|
67
|
+
|
68
|
+
# Argument to specify the amount of time by which the chosen schedule(s) will be shifted
|
69
|
+
shift_value = OpenStudio::Measure::OSArgument.makeDoubleArgument('shift_value', true)
|
70
|
+
shift_value.setDisplayName('Shift Schedule Profiles Forward (24hr, use decimal for sub hour and negative values for backward shift).')
|
71
|
+
shift_value.setDefaultValue(1)
|
72
|
+
args << shift_value
|
73
|
+
|
74
|
+
# Argument to choose which schedules will be shifted
|
75
|
+
choices = OpenStudio::StringVector.new
|
76
|
+
choices << 'Cooling'
|
77
|
+
choices << 'Heating'
|
78
|
+
choices << 'CoolHeat'
|
79
|
+
schedchoice = OpenStudio::Measure::OSArgument.makeChoiceArgument('schedchoice', choices)
|
80
|
+
schedchoice.setDisplayName('Choose which schedule class(es) to shift by the specified shift value')
|
81
|
+
schedchoice.setDefaultValue('CoolHeat')
|
82
|
+
args << schedchoice
|
83
|
+
|
84
|
+
return args
|
85
|
+
end
|
86
|
+
|
87
|
+
# define what happens when the measure is run
|
88
|
+
def run(model, runner, user_arguments)
|
89
|
+
super(model, runner, user_arguments)
|
90
|
+
|
91
|
+
# use the built-in error checking
|
92
|
+
if !runner.validateUserArguments(arguments(model), user_arguments)
|
93
|
+
return false
|
94
|
+
end
|
95
|
+
|
96
|
+
# Export CSV file with Schedule setpoints before schedule shifts
|
97
|
+
#model1 = runner.lastOpenStudioModel
|
98
|
+
#model = model1.get
|
99
|
+
interval = 60
|
100
|
+
header = []
|
101
|
+
header << 'Time'
|
102
|
+
schedules = []
|
103
|
+
model.getScheduleDays.each do |schedule|
|
104
|
+
header << schedule.name.get
|
105
|
+
schedules << schedule
|
106
|
+
end
|
107
|
+
|
108
|
+
dt = OpenStudio::Time.new(0, 0, interval, 0)
|
109
|
+
time = OpenStudio::Time.new(0, 0, 0, 0)
|
110
|
+
stop = OpenStudio::Time.new(1, 0, 0, 0)
|
111
|
+
values = []
|
112
|
+
while time <= stop
|
113
|
+
row = []
|
114
|
+
row << time.to_s
|
115
|
+
schedules.each do |schedule|
|
116
|
+
row << schedule.getValue(time)
|
117
|
+
end
|
118
|
+
values << row
|
119
|
+
|
120
|
+
time += dt
|
121
|
+
end
|
122
|
+
|
123
|
+
runner.registerInfo("Writing CSV report 'schedulereportbefore.csv'")
|
124
|
+
File.open('schedulereportbefore.csv', 'w') do |file|
|
125
|
+
file.puts header.join(',')
|
126
|
+
values.each do |row|
|
127
|
+
file.puts row.join(',')
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# populate choice argument for schedules that are applied to surfaces in the model
|
132
|
+
schedule_handles = OpenStudio::StringVector.new
|
133
|
+
schedule_display_names = OpenStudio::StringVector.new
|
134
|
+
|
135
|
+
# putting space types and names into hash
|
136
|
+
schedule_args = model.getScheduleRulesets
|
137
|
+
schedule_args_hash = {}
|
138
|
+
schedule_args.each do |schedule_arg|
|
139
|
+
schedule_args_hash[schedule_arg.name.to_s] = schedule_arg
|
140
|
+
end
|
141
|
+
|
142
|
+
# looping through sorted hash of schedules
|
143
|
+
schedule_args_hash.sort.map do |key, value|
|
144
|
+
# only include if schedule use count > 0
|
145
|
+
if value.directUseCount > 0
|
146
|
+
schedule_handles << value.handle.to_s
|
147
|
+
schedule_display_names << key
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Assign the user inputs to variables
|
152
|
+
shift_value = runner.getDoubleArgumentValue('shift_value', user_arguments)
|
153
|
+
schedchoice = runner.getStringArgumentValue('schedchoice', user_arguments)
|
154
|
+
|
155
|
+
apply_to_all_schedules = true
|
156
|
+
|
157
|
+
# Check shift value for reasonableness
|
158
|
+
if (shift_value / 24) == (shift_value / 24).to_i
|
159
|
+
runner.registerAsNotApplicable('No schedule shift was requested, the model was not changed.')
|
160
|
+
end
|
161
|
+
|
162
|
+
# Get schedules for measure
|
163
|
+
schedules = []
|
164
|
+
if apply_to_all_schedules
|
165
|
+
raw_schedules = model.getScheduleRulesets
|
166
|
+
raw_schedules_hash = {}
|
167
|
+
raw_schedules.each do |raw_schedule|
|
168
|
+
raw_schedules_hash[raw_schedule.name.to_s] = raw_schedule
|
169
|
+
end
|
170
|
+
|
171
|
+
# Looping through sorted hash of schedules
|
172
|
+
raw_schedules_hash.sort.map do |name, value|
|
173
|
+
# Only include if the schedule is used in the model
|
174
|
+
if value.directUseCount > 0
|
175
|
+
schedule_handles << value.handle.to_s
|
176
|
+
schedule_display_names << name
|
177
|
+
runner.registerInfo("Searching Schedule: #{name}")
|
178
|
+
if !name.downcase.include?("setback")
|
179
|
+
if schedchoice == "Cool" # Cooling and Air Only
|
180
|
+
if (name.to_s.include?("CLG") || name.to_s.include?("Air"))
|
181
|
+
# ADD v to Cooling list
|
182
|
+
schedules << value
|
183
|
+
runner.registerInfo("Schedule #{name} does contain 'CLG' or 'Air'")
|
184
|
+
else
|
185
|
+
runner.registerInfo("Schedule #{name} does not contain 'CLG' or 'Air'")
|
186
|
+
end
|
187
|
+
elsif schedchoice == "Heat" # Heating and Air Only
|
188
|
+
if (name.to_s.include?("HTG") || name.to_s.include?("Air"))
|
189
|
+
# ADD v to Heating list
|
190
|
+
schedules << value
|
191
|
+
runner.registerInfo("Schedule #{name} does contain 'HTG' or 'Air'")
|
192
|
+
else
|
193
|
+
runner.registerInfo("Schedule #{name} does not contain 'HTG' or 'Air'")
|
194
|
+
end
|
195
|
+
elsif schedchoice == "CoolHeat" # Cooling, Heating, and Air
|
196
|
+
if (name.to_s.include?("CLG") || name.to_s.include?("HTG") || name.to_s.include?("Air"))
|
197
|
+
# ADD v to Cooling/Heating list
|
198
|
+
schedules << value
|
199
|
+
runner.registerInfo("Schedule #{name} does contain 'CLG' or 'HTG' or 'Air'")
|
200
|
+
else
|
201
|
+
runner.registerInfo("Schedule #{name} does not contain 'CLG' or 'HTG' or 'Air'")
|
202
|
+
end
|
203
|
+
else
|
204
|
+
runner.registerError('Unexpected value of schedchoice: ' + schedchoice + '.')
|
205
|
+
return false
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
else
|
212
|
+
runner.registerAsNotApplicable('No schedules included in shift')
|
213
|
+
end
|
214
|
+
|
215
|
+
# Loop through all chosen schedules
|
216
|
+
schedules.each do |schedule|
|
217
|
+
# Array of all profiles to change
|
218
|
+
profiles = []
|
219
|
+
|
220
|
+
# Push default profiles to array
|
221
|
+
default_rule = schedule.defaultDaySchedule
|
222
|
+
profiles << default_rule
|
223
|
+
|
224
|
+
# Push profiles to array
|
225
|
+
rules = schedule.scheduleRules
|
226
|
+
rules.each do |rule|
|
227
|
+
day_sch = rule.daySchedule
|
228
|
+
profiles << day_sch
|
229
|
+
end
|
230
|
+
|
231
|
+
# Add design days to array
|
232
|
+
summer_design = schedule.summerDesignDaySchedule
|
233
|
+
winter_design = schedule.winterDesignDaySchedule
|
234
|
+
profiles << summer_design
|
235
|
+
profiles << winter_design
|
236
|
+
|
237
|
+
# Reporting initial condition of model
|
238
|
+
if apply_to_all_schedules
|
239
|
+
runner.registerInitialCondition("#{schedules.size} schedules are shifted in this model.")
|
240
|
+
else
|
241
|
+
runner.registerInitialCondition("Schedule #{schedule.name} has #{profiles.size} profiles including design days.")
|
242
|
+
end
|
243
|
+
|
244
|
+
# Rename schedule
|
245
|
+
schedule.setName("#{schedule.name} - (shifted #{shift_value} hours)")
|
246
|
+
|
247
|
+
shift_hours = shift_value.to_i
|
248
|
+
shift_minutes = ((shift_value - shift_value.to_i) * 60).to_i
|
249
|
+
|
250
|
+
# Give info messages as I change specific profiles
|
251
|
+
runner.registerInfo("Adjusting #{schedule.name}")
|
252
|
+
|
253
|
+
# Edit profiles
|
254
|
+
profiles.each do |day_sch|
|
255
|
+
times = day_sch.times
|
256
|
+
values = day_sch.values
|
257
|
+
|
258
|
+
runner.registerInfo("Old day_sch: #{day_sch}")
|
259
|
+
runner.registerInfo("Old Times: #{times}")
|
260
|
+
runner.registerInfo("Old Values: #{values}")
|
261
|
+
|
262
|
+
# Time objects to use in measure
|
263
|
+
time_0 = OpenStudio::Time.new(0, 0, 0, 0)
|
264
|
+
time_24 = OpenStudio::Time.new(0, 24, 0, 0)
|
265
|
+
shift_time = OpenStudio::Time.new(0, shift_hours, shift_minutes, 0)
|
266
|
+
|
267
|
+
# Arrays for values to avoid overlap conflict of times
|
268
|
+
new_times = []
|
269
|
+
new_values = []
|
270
|
+
|
271
|
+
if values.length < 2 # Avoid adjusting schedules with only one cooling/heating/air setpoint
|
272
|
+
new_times = times
|
273
|
+
new_values = values
|
274
|
+
else # Adjust schedules with more than 3 setpoints
|
275
|
+
# Create a pair of times and values for what will be 0 time after adjustment
|
276
|
+
new_times << time_24
|
277
|
+
if shift_time > time_0
|
278
|
+
new_values << day_sch.getValue(time_24 - shift_time)
|
279
|
+
else
|
280
|
+
new_values << day_sch.getValue(time_0 - shift_time)
|
281
|
+
end
|
282
|
+
|
283
|
+
# Clear values
|
284
|
+
day_sch.clearValues
|
285
|
+
|
286
|
+
# Unfreeze arrays before editing
|
287
|
+
times = times.clone(freeze: false) if times.frozen?
|
288
|
+
values = values.clone(freeze: false) if values.frozen?
|
289
|
+
|
290
|
+
if values.length == 2
|
291
|
+
timeschg = values.length - 2
|
292
|
+
else
|
293
|
+
timeschg = values.length - 3
|
294
|
+
end
|
295
|
+
|
296
|
+
# Count number of arrays
|
297
|
+
for i in 0..timeschg
|
298
|
+
new_time = times[i] + shift_time
|
299
|
+
# Adjust wrap around times for times that are t > 24 or t < 0
|
300
|
+
if new_time < time_0
|
301
|
+
new_time = new_time + time_24
|
302
|
+
values.rotate(1) # Move first value to last value in array
|
303
|
+
runner.registerWarning("Times adjusted for wrap around due to new time < 0.")
|
304
|
+
elsif new_time > time_24
|
305
|
+
new_time = new_time - time_24
|
306
|
+
values.rotate(-1) # Move last value to first value in array
|
307
|
+
runner.registerWarning("Times adjusted for wrap around due to new time > 24.")
|
308
|
+
else # If 0 < new_time < 24
|
309
|
+
new_time = new_time
|
310
|
+
end
|
311
|
+
# Make new values
|
312
|
+
new_times = times.insert(i, new_time)
|
313
|
+
new_times.delete_at(i+1)
|
314
|
+
end
|
315
|
+
|
316
|
+
new_values = values # Set new values equal to original schedule values
|
317
|
+
new_times.freeze
|
318
|
+
|
319
|
+
end
|
320
|
+
|
321
|
+
if values.length <= 4
|
322
|
+
timeschg = values.length - 1
|
323
|
+
else
|
324
|
+
timeschg = values.length - 2
|
325
|
+
end
|
326
|
+
|
327
|
+
for i in 0..(timeschg)
|
328
|
+
day_sch.addValue(new_times[i], new_values[i])
|
329
|
+
end
|
330
|
+
runner.registerInfo("New day_sch: #{day_sch}")
|
331
|
+
runner.registerInfo("New Times: #{new_times}")
|
332
|
+
runner.registerInfo("New Values: #{new_values}")
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
# Report final condition of model
|
337
|
+
if apply_to_all_schedules
|
338
|
+
runner.registerFinalCondition('Shifted time for all profiles for all schedules.')
|
339
|
+
else
|
340
|
+
runner.registerFinalCondition("Shifted time for all profiles used by this schedule.")
|
341
|
+
end
|
342
|
+
|
343
|
+
# Export CSV file with Schedule setpoints after schedule shifts
|
344
|
+
#model = runner.lastOpenStudioModel
|
345
|
+
#model = model.get
|
346
|
+
interval = 60
|
347
|
+
|
348
|
+
header = []
|
349
|
+
header << 'Time'
|
350
|
+
schedules = []
|
351
|
+
|
352
|
+
model.getScheduleDays.each do |schedule|
|
353
|
+
header << schedule.name.get
|
354
|
+
schedules << schedule
|
355
|
+
end
|
356
|
+
|
357
|
+
dt = OpenStudio::Time.new(0, 0, interval, 0)
|
358
|
+
time = OpenStudio::Time.new(0, 0, 0, 0)
|
359
|
+
stop = OpenStudio::Time.new(1, 0, 0, 0)
|
360
|
+
values = []
|
361
|
+
while time <= stop
|
362
|
+
row = []
|
363
|
+
row << time.to_s
|
364
|
+
schedules.each do |schedule|
|
365
|
+
row << schedule.getValue(time)
|
366
|
+
end
|
367
|
+
values << row
|
368
|
+
|
369
|
+
time += dt
|
370
|
+
end
|
371
|
+
|
372
|
+
runner.registerInfo("Writing CSV report 'schedulereportafter.csv'")
|
373
|
+
File.open('schedulereportafter.csv', 'w') do |file|
|
374
|
+
file.puts header.join(',')
|
375
|
+
values.each do |row|
|
376
|
+
file.puts row.join(',')
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
return true
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
# Allow the measure to be used by the application
|
385
|
+
ShiftScheduleByType.new.registerWithApplication
|