urbanopt-cli 0.2.0.pre6 → 0.2.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/.github/pull_request_template.md +0 -1
- data/.rubocop.yml +9 -0
- data/CHANGELOG.md +30 -1
- data/Gemfile +8 -6
- data/README.md +23 -4
- data/Rakefile +4 -2
- data/bin/console +3 -3
- data/developer_nrel_key.rb +31 -0
- data/example_files/Gemfile +4 -4
- data/example_files/mappers/Baseline.rb +360 -204
- data/example_files/mappers/HighEfficiency.rb +25 -29
- data/example_files/mappers/base_workflow.osw +2 -2
- data/example_files/reopt/base_assumptions.json +146 -0
- data/example_files/reopt/multiPV_assumptions.json +181 -0
- data/lib/change_log.rb +9 -4
- data/lib/uo_cli/version.rb +1 -1
- data/lib/uo_cli.rb +345 -295
- data/uo_cli.gemspec +26 -26
- metadata +31 -13
@@ -1,32 +1,32 @@
|
|
1
|
-
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
|
-
#
|
5
|
-
# Redistribution and use in source and binary forms, with or without modification,
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
6
|
# are permitted provided that the following conditions are met:
|
7
|
-
#
|
8
|
-
# Redistributions of source code must retain the above copyright notice, this list
|
7
|
+
#
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list
|
9
9
|
# of conditions and the following disclaimer.
|
10
|
-
#
|
11
|
-
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
-
# list of conditions and the following disclaimer in the documentation and/or other
|
10
|
+
#
|
11
|
+
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
+
# list of conditions and the following disclaimer in the documentation and/or other
|
13
13
|
# materials provided with the distribution.
|
14
|
-
#
|
15
|
-
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
-
# used to endorse or promote products derived from this software without specific
|
14
|
+
#
|
15
|
+
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without specific
|
17
17
|
# prior written permission.
|
18
|
-
#
|
19
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
|
-
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
|
-
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
22
|
-
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
23
|
-
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
24
|
-
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
-
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
26
|
-
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
27
|
-
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
22
|
+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
23
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
24
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
26
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
27
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
28
28
|
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
-
|
29
|
+
# *********************************************************************************
|
30
30
|
|
31
31
|
require 'urbanopt/scenario'
|
32
32
|
require 'openstudio/common_measures'
|
@@ -37,87 +37,258 @@ require 'json'
|
|
37
37
|
module URBANopt
|
38
38
|
module Scenario
|
39
39
|
class BaselineMapper < SimulationMapperBase
|
40
|
-
|
41
40
|
# class level variables
|
42
41
|
@@instance_lock = Mutex.new
|
43
42
|
@@osw = nil
|
44
43
|
@@geometry = nil
|
45
|
-
|
46
|
-
def initialize
|
47
|
-
|
44
|
+
|
45
|
+
def initialize
|
48
46
|
# do initialization of class variables in thread safe way
|
49
47
|
@@instance_lock.synchronize do
|
50
|
-
if @@osw.nil?
|
48
|
+
if @@osw.nil?
|
51
49
|
|
52
50
|
# load the OSW for this class
|
53
51
|
osw_path = File.join(File.dirname(__FILE__), 'base_workflow.osw')
|
54
52
|
File.open(osw_path, 'r') do |file|
|
55
53
|
@@osw = JSON.parse(file.read, symbolize_names: true)
|
56
54
|
end
|
57
|
-
|
55
|
+
|
58
56
|
# add any paths local to the project
|
59
57
|
@@osw[:file_paths] << File.join(File.dirname(__FILE__), '../weather/')
|
60
|
-
|
61
|
-
# configures OSW with extension gem paths for measures and files, all extension gems must be
|
58
|
+
|
59
|
+
# configures OSW with extension gem paths for measures and files, all extension gems must be
|
62
60
|
# required before this
|
63
61
|
@@osw = OpenStudio::Extension.configure_osw(@@osw)
|
64
62
|
end
|
65
63
|
end
|
66
64
|
end
|
67
|
-
|
65
|
+
|
66
|
+
def lookup_building_type(building_type, template, footprint_area, number_of_stories)
|
67
|
+
if template.include? 'DEER'
|
68
|
+
case building_type
|
69
|
+
when 'Education'
|
70
|
+
'EPr'
|
71
|
+
when 'Enclosed mall'
|
72
|
+
'RtL'
|
73
|
+
when 'Food sales'
|
74
|
+
'RSD'
|
75
|
+
when 'Food service'
|
76
|
+
'RSD'
|
77
|
+
when 'Inpatient health care'
|
78
|
+
'Nrs'
|
79
|
+
when 'Laboratory'
|
80
|
+
'Hsp'
|
81
|
+
when 'Lodging'
|
82
|
+
'Htl'
|
83
|
+
when 'Mixed use'
|
84
|
+
'ECC'
|
85
|
+
when 'Mobile Home'
|
86
|
+
'DMo'
|
87
|
+
when 'Multifamily (2 to 4 units)'
|
88
|
+
'MFm'
|
89
|
+
when 'Multifamily (5 or more units)'
|
90
|
+
'MFm'
|
91
|
+
when 'Nonrefrigerated warehouse'
|
92
|
+
'SUn'
|
93
|
+
when 'Nursing'
|
94
|
+
'Nrs'
|
95
|
+
when 'Office'
|
96
|
+
if footprint_area
|
97
|
+
if footprint_area.to_f > 100_000
|
98
|
+
'OfL'
|
99
|
+
else
|
100
|
+
'OfS'
|
101
|
+
end
|
102
|
+
else
|
103
|
+
raise 'footprint_area required to map office building type'
|
104
|
+
end
|
105
|
+
when 'Outpatient health care'
|
106
|
+
'Nrs'
|
107
|
+
when 'Public assembly'
|
108
|
+
'Asm'
|
109
|
+
when 'Public order and safety'
|
110
|
+
'Asm'
|
111
|
+
when 'Refrigerated warehouse'
|
112
|
+
'WRf'
|
113
|
+
when 'Religious worship'
|
114
|
+
'Asm'
|
115
|
+
when 'Retail other than mall'
|
116
|
+
'RtS'
|
117
|
+
when 'Service'
|
118
|
+
'MLI'
|
119
|
+
when 'Single-Family'
|
120
|
+
'MFm'
|
121
|
+
when 'Strip shopping mall'
|
122
|
+
'RtL'
|
123
|
+
when 'Vacant'
|
124
|
+
'SUn'
|
125
|
+
else
|
126
|
+
raise "building type #{building_type} cannot be mapped to a DEER building type"
|
127
|
+
end
|
128
|
+
|
129
|
+
else
|
130
|
+
# default: ASHRAE
|
131
|
+
case building_type
|
132
|
+
when 'Education'
|
133
|
+
'SecondarySchool'
|
134
|
+
when 'Enclosed mall'
|
135
|
+
'RetailStripmall'
|
136
|
+
when 'Food sales'
|
137
|
+
'FullServiceRestaurant'
|
138
|
+
when 'Food service'
|
139
|
+
'FullServiceRestaurant'
|
140
|
+
when 'Inpatient health care'
|
141
|
+
'Hospital'
|
142
|
+
when 'Laboratory'
|
143
|
+
'Hospital'
|
144
|
+
when 'Lodging'
|
145
|
+
if number_of_stories
|
146
|
+
if number_of_stories.to_i > 3
|
147
|
+
return 'LargeHotel'
|
148
|
+
else
|
149
|
+
return 'SmallHotel'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
'LargeHotel'
|
153
|
+
when 'Mixed use'
|
154
|
+
'Mixed use'
|
155
|
+
when 'Mobile Home'
|
156
|
+
'MidriseApartment'
|
157
|
+
when 'Multifamily (2 to 4 units)'
|
158
|
+
'MidriseApartment'
|
159
|
+
when 'Multifamily (5 or more units)'
|
160
|
+
'MidriseApartment'
|
161
|
+
when 'Nonrefrigerated warehouse'
|
162
|
+
'Warehouse'
|
163
|
+
when 'Nursing'
|
164
|
+
'Outpatient'
|
165
|
+
when 'Office'
|
166
|
+
if footprint_area
|
167
|
+
value = if footprint_area.to_f < 20_000
|
168
|
+
'SmallOffice'
|
169
|
+
elsif footprint_area.to_f > 100_000
|
170
|
+
'LargeOffice'
|
171
|
+
else
|
172
|
+
'MediumOffice'
|
173
|
+
end
|
174
|
+
else
|
175
|
+
raise 'Floor area required to map office building type'
|
176
|
+
end
|
177
|
+
when 'Outpatient health care'
|
178
|
+
'Outpatient'
|
179
|
+
when 'Public assembly'
|
180
|
+
'MediumOffice'
|
181
|
+
when 'Public order and safety'
|
182
|
+
'MediumOffice'
|
183
|
+
when 'Refrigerated warehouse'
|
184
|
+
'Warehouse'
|
185
|
+
when 'Religious worship'
|
186
|
+
'MediumOffice'
|
187
|
+
when 'Retail other than mall'
|
188
|
+
'RetailStandalone'
|
189
|
+
when 'Service'
|
190
|
+
'MediumOffice'
|
191
|
+
when 'Single-Family'
|
192
|
+
'MidriseApartment'
|
193
|
+
when 'Strip shopping mall'
|
194
|
+
'RetailStripmall'
|
195
|
+
when 'Vacant'
|
196
|
+
'Warehouse'
|
197
|
+
else
|
198
|
+
raise "building type #{building_type} cannot be mapped to an ASHRAE building type"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def lookup_template_by_year_built(template, year_built)
|
204
|
+
if template.include? 'DEER'
|
205
|
+
if year_built <= 1996
|
206
|
+
'DEER 1985'
|
207
|
+
elsif year_built <= 2003
|
208
|
+
'DEER 1996'
|
209
|
+
elsif year_built <= 2007
|
210
|
+
'DEER 2003'
|
211
|
+
elsif year_built <= 2011
|
212
|
+
'DEER 2007'
|
213
|
+
elsif year_built <= 2014
|
214
|
+
'DEER 2011'
|
215
|
+
elsif year_built <= 2015
|
216
|
+
'DEER 2014'
|
217
|
+
elsif year_built <= 2017
|
218
|
+
'DEER 2015'
|
219
|
+
elsif year_built <= 2020
|
220
|
+
'DEER 2017'
|
221
|
+
else
|
222
|
+
'DEER 2020'
|
223
|
+
end
|
224
|
+
else
|
225
|
+
# ASHRAE
|
226
|
+
if year_built < 1980
|
227
|
+
'DOE Ref Pre-1980'
|
228
|
+
elsif year_built <= 2004
|
229
|
+
'DOE Ref 1980-2004'
|
230
|
+
elsif year_built <= 2007
|
231
|
+
'90.1-2004'
|
232
|
+
elsif year_built <= 2010
|
233
|
+
'90.1-2007'
|
234
|
+
elsif year_built <= 2013
|
235
|
+
'90.1-2010'
|
236
|
+
else
|
237
|
+
'90.1-2013'
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
68
242
|
def create_osw(scenario, features, feature_names)
|
69
|
-
|
70
243
|
if features.size != 1
|
71
|
-
raise
|
244
|
+
raise 'TestMapper1 currently cannot simulate more than one feature'
|
72
245
|
end
|
73
246
|
feature = features[0]
|
74
247
|
feature_id = feature.id
|
75
|
-
feature_type = feature.type
|
248
|
+
feature_type = feature.type
|
76
249
|
feature_name = feature.name
|
77
|
-
if feature_names.size == 1
|
78
|
-
|
79
|
-
end
|
80
|
-
|
250
|
+
feature_name = feature_names[0] if feature_names.size == 1
|
251
|
+
|
81
252
|
# deep clone of @@osw before we configure it
|
82
253
|
osw = Marshal.load(Marshal.dump(@@osw))
|
83
|
-
|
254
|
+
|
84
255
|
# now we have the feature, we can look up its properties and set arguments in the OSW
|
85
256
|
osw[:name] = feature_name
|
86
257
|
osw[:description] = feature_name
|
87
|
-
|
258
|
+
|
88
259
|
if feature_type == 'Building'
|
89
260
|
|
90
261
|
# set_run_period
|
91
262
|
begin
|
92
|
-
timesteps_per_hour = feature.timesteps_per_hour
|
93
|
-
|
263
|
+
timesteps_per_hour = feature.timesteps_per_hour
|
264
|
+
unless timesteps_per_hour.empty?
|
94
265
|
OpenStudio::Extension.set_measure_argument(osw, 'set_run_period', 'timesteps_per_hour', timesteps_per_hour)
|
95
266
|
end
|
96
|
-
rescue
|
267
|
+
rescue StandardError
|
97
268
|
end
|
98
269
|
begin
|
99
270
|
begin_date = feature.begin_date
|
100
|
-
|
101
|
-
|
271
|
+
unless feature.begin_date.empty?
|
272
|
+
# check date-only YYYY-MM-DD
|
102
273
|
if feature.begin_date.length > 10
|
103
274
|
feature.begin_date = feature.begin_date[0, 10]
|
104
275
|
end
|
105
276
|
OpenStudio::Extension.set_measure_argument(osw, 'set_run_period', 'begin_date', begin_date)
|
106
277
|
end
|
107
|
-
rescue
|
278
|
+
rescue StandardError
|
108
279
|
end
|
109
280
|
begin
|
110
281
|
end_date = feature.end_date
|
111
|
-
|
282
|
+
unless feature.end_date.empty?
|
112
283
|
# check date-only YYYY-MM-DD
|
113
284
|
if feature.end_date.length > 10
|
114
285
|
feature.end_date = feature.end_date[0, 10]
|
115
286
|
end
|
116
287
|
OpenStudio::Extension.set_measure_argument(osw, 'set_run_period', 'end_date', end_date)
|
117
288
|
end
|
118
|
-
rescue
|
289
|
+
rescue StandardError
|
119
290
|
end
|
120
|
-
|
291
|
+
|
121
292
|
# convert to hash
|
122
293
|
building_hash = feature.to_hash
|
123
294
|
# check for detailed model filename
|
@@ -131,94 +302,10 @@ module URBANopt
|
|
131
302
|
|
132
303
|
# in case detailed model filename is not present
|
133
304
|
else
|
305
|
+
|
134
306
|
building_type_1 = building_hash[:building_type]
|
135
|
-
|
136
|
-
|
137
|
-
building_type_1 = 'MidriseApartment'
|
138
|
-
when 'Multifamily (2 to 4 units)'
|
139
|
-
building_type_1 = 'MidriseApartment'
|
140
|
-
when 'Single-Family'
|
141
|
-
building_type_1 = 'MidriseApartment'
|
142
|
-
when 'Office'
|
143
|
-
building_type_1 = 'MediumOffice'
|
144
|
-
when 'Outpatient health care'
|
145
|
-
building_type_1 = 'Outpatient'
|
146
|
-
when 'Inpatient health care'
|
147
|
-
building_type_1 = 'Hospital'
|
148
|
-
when 'Lodging'
|
149
|
-
building_type_1 = 'LargeHotel'
|
150
|
-
when 'Food service'
|
151
|
-
building_type_1 = 'FullServiceRestaurant'
|
152
|
-
when 'Strip shopping mall'
|
153
|
-
building_type_1 = 'RetailStripmall'
|
154
|
-
when 'Retail other than mall'
|
155
|
-
building_type_1 = 'RetailStandalone'
|
156
|
-
when 'Education'
|
157
|
-
building_type_1 = 'SecondarySchool'
|
158
|
-
when 'Nursing'
|
159
|
-
building_type_1 = 'MidriseApartment'
|
160
|
-
when 'Mixed use'
|
161
|
-
mixed_type_1 = building_hash[:mixed_type_1]
|
162
|
-
mixed_type_2 = building_hash[:mixed_type_2]
|
163
|
-
mixed_type_2_percentage = building_hash[:mixed_type_2_percentage]
|
164
|
-
mixed_type_2_fract_bldg_area = mixed_type_2_percentage*0.01
|
165
|
-
|
166
|
-
mixed_type_3 = building_hash[:mixed_type_3]
|
167
|
-
mixed_type_3_percentage = building_hash[:mixed_type_3_percentage]
|
168
|
-
mixed_type_3_fract_bldg_area = mixed_type_3_percentage*0.01
|
169
|
-
|
170
|
-
mixed_type_4 = building_hash[:mixed_type_4]
|
171
|
-
mixed_type_4_percentage = building_hash[:mixed_type_4_percentage]
|
172
|
-
mixed_type_4_fract_bldg_area = mixed_type_4_percentage*0.01
|
173
|
-
|
174
|
-
mixed_use_types = []
|
175
|
-
mixed_use_types << mixed_type_1
|
176
|
-
mixed_use_types << mixed_type_2
|
177
|
-
mixed_use_types << mixed_type_3
|
178
|
-
mixed_use_types << mixed_type_4
|
179
|
-
|
180
|
-
openstudio_mixed_use_types = []
|
181
|
-
|
182
|
-
mixed_use_types.each do |mixed_use_type|
|
183
|
-
|
184
|
-
case mixed_use_type
|
185
|
-
when 'Multifamily (5 or more units)'
|
186
|
-
mixed_use_type = 'MidriseApartment'
|
187
|
-
when 'Multifamily (2 to 4 units)'
|
188
|
-
mixed_use_type = 'MidriseApartment'
|
189
|
-
when 'Single-Family'
|
190
|
-
mixed_use_type = 'MidriseApartment'
|
191
|
-
when 'Office'
|
192
|
-
mixed_use_type = 'MediumOffice'
|
193
|
-
when 'Outpatient health care'
|
194
|
-
mixed_use_type = 'Outpatient'
|
195
|
-
when 'Inpatient health care'
|
196
|
-
mixed_use_type = 'Hospital'
|
197
|
-
when 'Lodging'
|
198
|
-
mixed_use_type = 'LargeHotel'
|
199
|
-
when 'Food service'
|
200
|
-
mixed_use_type = 'FullServiceRestaurant'
|
201
|
-
when 'Strip shopping mall'
|
202
|
-
mixed_use_type = 'RetailStripmall'
|
203
|
-
when 'Retail other than mall'
|
204
|
-
mixed_use_type = 'RetailStandalone'
|
205
|
-
when 'Education'
|
206
|
-
mixed_use_type = 'SecondarySchool'
|
207
|
-
when 'Nursing'
|
208
|
-
mixed_use_type = 'MidriseApartment'
|
209
|
-
end
|
210
|
-
|
211
|
-
openstudio_mixed_use_types << mixed_use_type
|
212
|
-
end
|
213
|
-
|
214
|
-
openstudio_mixed_type_1 = openstudio_mixed_use_types[0]
|
215
|
-
openstudio_mixed_type_2 = openstudio_mixed_use_types[1]
|
216
|
-
openstudio_mixed_type_3 = openstudio_mixed_use_types[2]
|
217
|
-
openstudio_mixed_type_4 = openstudio_mixed_use_types[3]
|
218
|
-
|
219
|
-
end
|
220
|
-
footprint_area = building_hash[:footprint_area]
|
221
|
-
floor_height = 10
|
307
|
+
|
308
|
+
# lookup/map building type
|
222
309
|
number_of_stories = building_hash[:number_of_stories]
|
223
310
|
if building_hash.key?(:number_of_stories_above_ground)
|
224
311
|
number_of_stories_above_ground = building_hash[:number_of_stories_above_ground]
|
@@ -227,111 +314,182 @@ module URBANopt
|
|
227
314
|
number_of_stories_above_ground = number_of_stories
|
228
315
|
number_of_stories_below_ground = 0
|
229
316
|
end
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
317
|
+
template = building_hash.key?(:template) ? building_hash[:template] : nil
|
318
|
+
footprint_area = building_hash[:footprint_area]
|
319
|
+
|
320
|
+
mapped_building_type_1 = lookup_building_type(building_type_1, template, footprint_area, number_of_stories)
|
321
|
+
|
322
|
+
# process Mixed Use (for create_bar measure)
|
323
|
+
if building_type_1 == 'Mixed use'
|
324
|
+
# map mixed use types
|
325
|
+
running_fraction = 0
|
326
|
+
mixed_type_1 = building_hash[:mixed_type_1]
|
327
|
+
mixed_type_2 = building_hash.key?(:mixed_type_2) ? building_hash[:mixed_type_2] : nil
|
328
|
+
unless mixed_type_2.nil?
|
329
|
+
mixed_type_2_percentage = building_hash[:mixed_type_2_percentage]
|
330
|
+
mixed_type_2_fract_bldg_area = mixed_type_2_percentage * 0.01
|
331
|
+
running_fraction += mixed_type_2_fract_bldg_area
|
332
|
+
end
|
333
|
+
|
334
|
+
mixed_type_3 = building_hash.key?(:mixed_type_3) ? building_hash[:mixed_type_3] : nil
|
335
|
+
unless mixed_type_3.nil?
|
336
|
+
mixed_type_3_percentage = building_hash[:mixed_type_3_percentage]
|
337
|
+
mixed_type_3_fract_bldg_area = mixed_type_3_percentage * 0.01
|
338
|
+
running_fraction += mixed_type_3_fract_bldg_area
|
339
|
+
end
|
340
|
+
|
341
|
+
mixed_type_4 = building_hash.key?(:mixed_type_4) ? building_hash[:mixed_type_4] : nil
|
342
|
+
unless mixed_type_4.nil?
|
343
|
+
mixed_type_4_percentage = building_hash[:mixed_type_4_percentage]
|
344
|
+
mixed_type_4_fract_bldg_area = mixed_type_4_percentage * 0.01
|
345
|
+
running_fraction += mixed_type_4_fract_bldg_area
|
346
|
+
end
|
347
|
+
|
348
|
+
# potentially calculate from other inputs
|
349
|
+
mixed_type_1_fract_bldg_area = building_hash.key?(:mixed_type_1_percentage) ? building_hash[:mixed_type_1_percentage] : (1 - running_fraction)
|
350
|
+
|
351
|
+
# lookup mixed_use types
|
352
|
+
footprint_1 = footprint_area * mixed_type_1_fract_bldg_area
|
353
|
+
openstudio_mixed_type_1 = lookup_building_type(mixed_type_1, template, footprint_1, number_of_stories)
|
354
|
+
unless mixed_type_2.nil?
|
355
|
+
footprint_2 = footprint_area * mixed_type_2_fract_bldg_area
|
356
|
+
openstudio_mixed_type_2 = lookup_building_type(mixed_type_2, template, footprint_2, number_of_stories)
|
357
|
+
end
|
358
|
+
unless mixed_type_3.nil?
|
359
|
+
footprint_3 = footprint_area * mixed_type_3_fract_bldg_area
|
360
|
+
openstudio_mixed_type_3 = lookup_building_type(mixed_type_3, template, footprint_3, number_of_stories)
|
361
|
+
end
|
362
|
+
unless mixed_type_4.nil?
|
363
|
+
footprint_4 = footprint_area * mixed_type_4_fract_bldg_area
|
364
|
+
openstudio_mixed_type_4 = lookup_building_type(mixed_type_4, template, footprint_4, number_of_stories)
|
365
|
+
end
|
234
366
|
end
|
235
367
|
|
368
|
+
floor_height = 10
|
369
|
+
system_type = if building_hash.key?(:system_type)
|
370
|
+
building_hash[:system_type]
|
371
|
+
else
|
372
|
+
'Inferred'
|
373
|
+
end
|
374
|
+
|
236
375
|
def time_mapping(time)
|
237
376
|
hour = time.split(':')[0]
|
238
377
|
minute = time.split(':')[1]
|
239
|
-
fraction = minute.to_f/60
|
378
|
+
fraction = minute.to_f / 60
|
240
379
|
fraction_roundup = fraction.round(2)
|
241
380
|
minute_fraction = fraction_roundup.to_s.split('.')[1]
|
242
381
|
new_time = [hour, minute_fraction].join('.')
|
243
|
-
|
382
|
+
new_time
|
244
383
|
end
|
245
384
|
|
246
|
-
|
247
385
|
# ChangeBuildingLocation
|
248
|
-
# set skip
|
386
|
+
# set skip to false for change building location
|
249
387
|
OpenStudio::Extension.set_measure_argument(osw, 'ChangeBuildingLocation', '__SKIP__', false)
|
250
388
|
|
251
389
|
# cec climate zone takes precedence
|
252
390
|
cec_found = false
|
253
391
|
begin
|
254
392
|
cec_climate_zone = feature.cec_climate_zone
|
255
|
-
|
256
|
-
cec_climate_zone =
|
393
|
+
unless cec_climate_zone.empty?
|
394
|
+
cec_climate_zone = 'T24-CEC' + cec_climate_zone
|
257
395
|
OpenStudio::Extension.set_measure_argument(osw, 'ChangeBuildingLocation', 'climate_zone', cec_climate_zone)
|
258
396
|
cec_found = true
|
259
397
|
end
|
260
|
-
rescue
|
398
|
+
rescue StandardError
|
261
399
|
end
|
262
|
-
|
400
|
+
unless cec_found
|
263
401
|
begin
|
264
402
|
climate_zone = feature.climate_zone
|
265
|
-
|
266
|
-
climate_zone =
|
403
|
+
unless climate_zone.empty?
|
404
|
+
climate_zone = 'ASHRAE 169-2013-' + climate_zone
|
267
405
|
OpenStudio::Extension.set_measure_argument(osw, 'ChangeBuildingLocation', 'climate_zone', climate_zone)
|
268
406
|
end
|
269
|
-
rescue
|
407
|
+
rescue StandardError
|
270
408
|
end
|
271
409
|
end
|
272
410
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
411
|
+
# set weather file
|
412
|
+
begin
|
413
|
+
weather_filename = feature.weather_filename
|
414
|
+
if !feature.weather_filename.nil? && !feature.weather_filename.empty?
|
415
|
+
OpenStudio::Extension.set_measure_argument(osw, 'ChangeBuildingLocation', 'weather_file_name', weather_filename)
|
416
|
+
puts "Setting weather_file_name to #{weather_filename} as specified in the FeatureFile"
|
417
|
+
end
|
418
|
+
rescue StandardError
|
419
|
+
puts 'No weather_file specified on feature'
|
420
|
+
epw_file_path = Dir.glob(File.join(File.dirname(__FILE__), '../weather/*.epw'))[0]
|
421
|
+
if !epw_file_path.nil? && !epw_file_path.empty?
|
422
|
+
epw_file_name = File.basename(epw_file_path)
|
423
|
+
OpenStudio::Extension.set_measure_argument(osw, 'ChangeBuildingLocation', 'weather_file_name', epw_file_name)
|
424
|
+
puts "Setting weather_file_name to first epw file found in the weather folder: #{epw_file_name}"
|
425
|
+
else
|
426
|
+
puts 'NO WEATHER FILES SPECIFIED...SIMULATIONS MAY FAIL'
|
427
|
+
end
|
277
428
|
end
|
278
|
-
rescue
|
279
|
-
end
|
280
429
|
|
281
|
-
#set weekday start time
|
430
|
+
# set weekday start time
|
282
431
|
begin
|
283
432
|
weekday_start_time = feature.weekday_start_time
|
284
|
-
|
433
|
+
unless feature.weekday_start_time.empty?
|
285
434
|
new_weekday_start_time = time_mapping(weekday_start_time)
|
286
435
|
OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'wkdy_op_hrs_start_time', new_weekday_start_time, 'create_typical_building_from_model 1')
|
287
436
|
end
|
288
|
-
rescue
|
437
|
+
rescue StandardError
|
289
438
|
end
|
290
439
|
|
291
440
|
# set weekday duration
|
292
441
|
begin
|
293
442
|
weekday_duration = feature.weekday_duration
|
294
|
-
|
443
|
+
unless feature.weekday_duration.empty?
|
295
444
|
new_weekday_duration = time_mapping(weekday_duration)
|
296
445
|
OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'wkdy_op_hrs_duration', new_weekday_duration, 'create_typical_building_from_model 1')
|
297
446
|
end
|
298
|
-
rescue
|
447
|
+
rescue StandardError
|
299
448
|
end
|
300
|
-
|
449
|
+
|
301
450
|
# set weekend start time
|
302
451
|
begin
|
303
452
|
weekend_start_time = feature.weekend_start_time
|
304
|
-
|
453
|
+
unless feature.weekend_start_time.empty?
|
305
454
|
new_weekend_start_time = time_mapping(weekend_start_time)
|
306
455
|
OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'wknd_op_hrs_start_time', new_weekend_start_time, 'create_typical_building_from_model 1')
|
307
456
|
end
|
308
|
-
rescue
|
457
|
+
rescue StandardError
|
309
458
|
end
|
310
|
-
|
459
|
+
|
311
460
|
# set weekend duration
|
312
461
|
begin
|
313
462
|
weekend_duration = feature.weekend_duration
|
314
|
-
|
463
|
+
unless feature.weekend_duration.empty?
|
315
464
|
new_weekend_duration = time_mapping(weekend_duration)
|
316
465
|
OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'wknd_op_hrs_duration', new_weekend_duration, 'create_typical_building_from_model 1')
|
317
466
|
end
|
318
|
-
rescue
|
467
|
+
rescue StandardError
|
319
468
|
end
|
320
469
|
|
321
470
|
# template
|
322
471
|
begin
|
472
|
+
new_template = nil
|
323
473
|
template = feature.template
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
474
|
+
|
475
|
+
# can we override template with year_built info? (keeping same template family)
|
476
|
+
if building_hash.key?(:year_built) && !building_hash[:year_built].nil? && !feature.template.empty?
|
477
|
+
new_template = lookup_template_by_year_built(template, year_built)
|
478
|
+
elsif !feature.template.empty?
|
479
|
+
new_template = template
|
480
|
+
end
|
481
|
+
|
482
|
+
if new_template
|
483
|
+
OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'template', new_template)
|
484
|
+
OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'template', new_template, 'create_typical_building_from_model 1')
|
485
|
+
OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'template', new_template, 'create_typical_building_from_model 2')
|
328
486
|
end
|
329
|
-
rescue
|
487
|
+
rescue StandardError
|
330
488
|
end
|
331
|
-
|
489
|
+
|
332
490
|
# TODO: surface_elevation has no current mapping
|
333
491
|
# TODO: tariff_filename has no current mapping
|
334
|
-
|
492
|
+
|
335
493
|
# create a bar building, will have spaces tagged with individual space types given the
|
336
494
|
# input building types
|
337
495
|
# set skip measure to false
|
@@ -341,24 +499,24 @@ module URBANopt
|
|
341
499
|
OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'num_stories_above_grade', number_of_stories_above_ground)
|
342
500
|
OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'num_stories_below_grade', number_of_stories_below_ground)
|
343
501
|
|
344
|
-
OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_a',
|
502
|
+
OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_a', mapped_building_type_1)
|
345
503
|
|
346
504
|
if building_type_1 == 'Mixed use'
|
347
505
|
|
348
506
|
OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_a', openstudio_mixed_type_1)
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
507
|
+
|
508
|
+
unless mixed_type_2.nil?
|
509
|
+
OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_b', openstudio_mixed_type_2)
|
510
|
+
OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_b_fract_bldg_area', mixed_type_2_fract_bldg_area)
|
511
|
+
end
|
512
|
+
unless mixed_type_3.nil?
|
513
|
+
OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_c', openstudio_mixed_type_3)
|
514
|
+
OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_c_fract_bldg_area', mixed_type_3_fract_bldg_area)
|
515
|
+
end
|
516
|
+
unless mixed_type_4.nil?
|
517
|
+
OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_d', openstudio_mixed_type_4)
|
518
|
+
OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_d_fract_bldg_area', mixed_type_4_fract_bldg_area)
|
519
|
+
end
|
362
520
|
end
|
363
521
|
|
364
522
|
# calling create typical building the first time will create space types
|
@@ -366,32 +524,30 @@ module URBANopt
|
|
366
524
|
OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'add_hvac', false, 'create_typical_building_from_model 1')
|
367
525
|
|
368
526
|
# create a blended space type for each story
|
369
|
-
OpenStudio::Extension.set_measure_argument(osw,
|
370
|
-
|
371
|
-
OpenStudio::Extension.set_measure_argument(osw,
|
372
|
-
|
527
|
+
OpenStudio::Extension.set_measure_argument(osw,
|
528
|
+
'blended_space_type_from_model', '__SKIP__', false)
|
529
|
+
OpenStudio::Extension.set_measure_argument(osw,
|
530
|
+
'blended_space_type_from_model', 'blend_method', 'Building Story')
|
373
531
|
|
374
532
|
# create geometry for the desired feature, this will reuse blended space types in the model for each story and remove the bar geometry
|
375
533
|
OpenStudio::Extension.set_measure_argument(osw, 'urban_geometry_creation', '__SKIP__', false)
|
376
534
|
OpenStudio::Extension.set_measure_argument(osw, 'urban_geometry_creation', 'geojson_file', scenario.feature_file.path)
|
377
535
|
OpenStudio::Extension.set_measure_argument(osw, 'urban_geometry_creation', 'feature_id', feature_id)
|
378
536
|
OpenStudio::Extension.set_measure_argument(osw, 'urban_geometry_creation', 'surrounding_buildings', 'ShadingOnly')
|
379
|
-
|
537
|
+
|
380
538
|
# call create typical building a second time, do not touch space types, only add hvac
|
381
539
|
OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', '__SKIP__', false)
|
382
540
|
OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'system_type', system_type, 'create_typical_building_from_model 2')
|
383
541
|
end
|
384
542
|
|
385
|
-
|
386
543
|
# call the default feature reporting measure
|
387
544
|
OpenStudio::Extension.set_measure_argument(osw, 'default_feature_reports', 'feature_id', feature_id)
|
388
545
|
OpenStudio::Extension.set_measure_argument(osw, 'default_feature_reports', 'feature_name', feature_name)
|
389
546
|
OpenStudio::Extension.set_measure_argument(osw, 'default_feature_reports', 'feature_type', feature_type)
|
390
|
-
end
|
391
|
-
|
392
|
-
|
393
|
-
end
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
end #URBANopt
|
547
|
+
end
|
548
|
+
|
549
|
+
osw
|
550
|
+
end
|
551
|
+
end # BaselineMapper
|
552
|
+
end # Scenario
|
553
|
+
end # URBANopt
|