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.
@@ -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 "TestMapper1 currently cannot simulate more than one feature"
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
- feature_name = feature_names[0]
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
- if !timesteps_per_hour.empty?
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
- if !feature.begin_date.empty?
101
- # check date-only YYYY-MM-DD
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
- if !feature.end_date.empty?
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
- case building_type_1
136
- when 'Multifamily (5 or more units)'
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
- if building_hash.key?(:system_type)
231
- system_type = building_hash[:system_type]
232
- else
233
- system_type = "Inferred"
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
- return new_time
382
+ new_time
244
383
  end
245
384
 
246
-
247
385
  # ChangeBuildingLocation
248
- # set skip measure to false change building location
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
- if !cec_climate_zone.empty?
256
- cec_climate_zone = "T24-CEC" + 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
- if !cec_found
400
+ unless cec_found
263
401
  begin
264
402
  climate_zone = feature.climate_zone
265
- if !climate_zone.empty?
266
- climate_zone = "ASHRAE 169-2013-" + 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
- begin
274
- weather_filename = feature.weather_filename
275
- if !feature.weather_filename.empty?
276
- OpenStudio::Extension.set_measure_argument(osw, 'ChangeBuildingLocation', 'weather_file_name', weather_filename)
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
- if !feature.weekday_start_time.empty?
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
- if !feature.weekday_duration.empty?
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
- if !feature.weekend_start_time.empty?
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
- if !feature.weekend_duration.empty?
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
- if !feature.template.empty?
325
- OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'template', template)
326
- OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'template', feature.template, 'create_typical_building_from_model 1')
327
- OpenStudio::Extension.set_measure_argument(osw, 'create_typical_building_from_model', 'template', feature.template, 'create_typical_building_from_model 2')
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', building_type_1)
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
- OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_b', openstudio_mixed_type_2)
351
-
352
- OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_b_fract_bldg_area', mixed_type_2_fract_bldg_area)
353
-
354
- OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_c', openstudio_mixed_type_3)
355
-
356
- OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_c_fract_bldg_area', mixed_type_3_fract_bldg_area)
357
-
358
- OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_d', openstudio_mixed_type_4)
359
-
360
- OpenStudio::Extension.set_measure_argument(osw, 'create_bar_from_building_type_ratios', 'bldg_type_d_fract_bldg_area', mixed_type_4_fract_bldg_area)
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
- 'blended_space_type_from_model', '__SKIP__', false)
371
- OpenStudio::Extension.set_measure_argument(osw,
372
- 'blended_space_type_from_model', 'blend_method', 'Building Story')
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
- return osw
393
- end
394
-
395
- end #BaselineMapper
396
- end #Scenario
397
- end #URBANopt
547
+ end
548
+
549
+ osw
550
+ end
551
+ end # BaselineMapper
552
+ end # Scenario
553
+ end # URBANopt