urbanopt-cli 0.2.0.pre6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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