Module: OpenstudioStandards::ExteriorLighting

Defined in:
lib/openstudio-standards/exterior_lighting/create.rb,
lib/openstudio-standards/exterior_lighting/information.rb

Overview

The Exterior Lighting module provides methods create, modify, and get information about model exterior lighting

Create collapse

Information collapse

Class Method Details

.model_create_exterior_lights(model, name: nil, power: 1.0, units: 'W', multiplier: 1.0, schedule: nil, control_option: 'AstronomicalClock') ⇒ OpenStudio::Model::ExteriorLights

create an ExtertiorLights object from inputs

Parameters:

  • model (OpenStudio::Model::Model)

    OpenStudio model object

  • name (String) (defaults to: nil)

    the name of the exterior lights

  • power (Double) (defaults to: 1.0)

    the watts value, can be watts or watts per area or length

  • units (String) (defaults to: 'W')

    units for the power, either ‘W’, ‘W/ft’ or ‘W/ft^2’

  • multiplier (Double) (defaults to: 1.0)

    the multiplier for the lighting, representing ft or ft^2

  • schedule (OpenStudio::Model::Schedule) (defaults to: nil)

    OpenStudio Schedule object. If nil, will default to always on.

  • control_option (String) (defaults to: 'AstronomicalClock')

    Options are ‘ScheduleNameOnly’ and ‘AstronomicalClock’. ‘ScheduleNameOnly’ will follow the schedule. ‘AstronomicalClock’ will follow the schedule, but turn off lights when the sun is up.

Returns:

  • (OpenStudio::Model::ExteriorLights)

    OpenStudio ExteriorLights object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/openstudio-standards/exterior_lighting/create.rb', line 17

def self.model_create_exterior_lights(model,
                                      name: nil,
                                      power: 1.0,
                                      units: 'W',
                                      multiplier: 1.0,
                                      schedule: nil,
                                      control_option: 'AstronomicalClock')
  # default name
  if name.nil?
    name = "Exterior Lights #{power.round(2)} #{units}"
  else
    end_use_category = name
    name = "#{name} #{power.round(2)} #{units}"
  end

  # warn if incorrect control option
  unless OpenStudio::Model::ExteriorLights::validControlOptionValues.include? control_option
    OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.ExteriorLighting', "Invalid control option #{control_option}. Use either ScheduleNameOnly' or 'AstronomicalClock'. Defaulting to 'AstronomicalClock'.")
    control_option = 'AstronomicalClock'
  end

  # default schedule
  schedule = model.alwaysOnDiscreteSchedule if schedule.nil?

  # create exterior light definition
  exterior_lights_definition = OpenStudio::Model::ExteriorLightsDefinition.new(model)
  exterior_lights_definition.setName("#{name} Def (#{units})")
  exterior_lights_definition.setDesignLevel(power)

  # creating exterior lights object
  exterior_lights = OpenStudio::Model::ExteriorLights.new(exterior_lights_definition, schedule)
  exterior_lights.setMultiplier(multiplier)
  exterior_lights.setName(name)
  exterior_lights.setControlOption(control_option)
  exterior_lights.setEndUseSubcategory(end_use_category)

  return exterior_lights
end

.model_create_typical_exterior_lighting(model, standard: nil, lighting_generation: 'default', lighting_zone: 3, onsite_parking_fraction: 1.0, add_base_site_allowance: false, use_model_for_entries_and_canopies: false, control_option: 'AstronomicalClock') ⇒ Array<OpenStudio::Model::ExteriorLights>

Create typical exterior lighting in a model

Parameters:

  • model (OpenStudio::Model::Model)

    OpenStudio model object

  • standard (Standard) (defaults to: nil)

    standard object to use for lighting properties. If set, will override lighting_generation.

  • lighting_generation (String) (defaults to: 'default')

    lighting generation to use for lighting properties. Currently defaulted to a mix of Metal Halide, High Pressure Sodium, and LEDs.

  • lighting_zone (Integer) (defaults to: 3)

    exterior lighting zone number, 0-4

  • onsite_parking_fraction (Double) (defaults to: 1.0)

    onsite parking fraction, 0-1

  • add_base_site_allowance (Boolean) (defaults to: false)

    whether to include the base site allowance

  • use_model_for_entries_and_canopies (Boolean) (defaults to: false)

    use building geometry for number of entries and canopy size

  • control_option (String) (defaults to: 'AstronomicalClock')

    Options are ‘ScheduleNameOnly’ and ‘AstronomicalClock’. ‘ScheduleNameOnly’ will follow the schedule. ‘AstronomicalClock’ will follow the schedule, but turn off lights when the sun is up.

Returns:

  • (Array<OpenStudio::Model::ExteriorLights>)

    Array of OpenStudio ExteriorLights object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
# File 'lib/openstudio-standards/exterior_lighting/create.rb', line 68

def self.model_create_typical_exterior_lighting(model,
                                                standard: nil,
                                                lighting_generation: 'default',
                                                lighting_zone: 3,
                                                onsite_parking_fraction: 1.0,
                                                add_base_site_allowance: false,
                                                use_model_for_entries_and_canopies: false,
                                                control_option: 'AstronomicalClock')
  exterior_lights = []
  installed_power = 0.0
  # get the exterior lighting properties from standard or the lighting_generation
  if standard.nil?
    exterior_lighting_properties = OpenstudioStandards::ExteriorLighting.model_get_exterior_lighting_properties(lighting_generation: lighting_generation)
    lookup_key = lighting_generation
  else
    lookup_key = standard.template
    if ['90.1-2004', '90.1-2007', '90.1-2010', '90.1-2013', '90.1-2016', '90.1-2019 PRM'].include?(lookup_key)
      exterior_lighting_properties = {}
    else
      search_criteria = {
        'lighting_zone' => lighting_zone
      }
      exterior_lighting_properties = standard.standards_lookup_table_first(table_name: 'exterior_lighting', search_criteria: search_criteria)
    end
  end

  # make sure lighting properties were found
  if exterior_lighting_properties.nil?
    OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.ExteriorLighting', "Exterior lighting properties not found for #{lookup_key}, ext lighting zone #{lighting_zone}, none will be added to model.")
    return exterior_lights
  end

  # get model specific areas to for exterior lighting
  area_length_count_hash = OpenstudioStandards::ExteriorLighting.model_get_exterior_lighting_sizes(model)

  # create schedules for exterior lighting objects using midnight to 6am setback or shutdown
  start_setback_shutoff = { hr: 24, min: 0 }
  end_setback_shutoff = { hr: 6, min: 0 }
  shuttoff = false
  setback = false

  if exterior_lighting_properties.has_key?('building_facade_and_landscape_automatic_shut_off')
    if exterior_lighting_properties['building_facade_and_landscape_automatic_shut_off'] == 1
      facade_automatic_shut_off = true
    else
      facade_automatic_shut_off = false
    end
  else
    search_criteria = {
      'template' => lookup_key,
      'lighting_zone' => lighting_zone,
      'allowance_type' => 'building facades',
      'allowance_unit' => 'W/ft2'
    }
    exterior_lighting_building_facade_req = standard.standards_lookup_table_first(table_name: 'exterior_lighting', search_criteria: search_criteria)
    if exterior_lighting_building_facade_req['daylight_off_control'] == 'REQ'
      facade_automatic_shut_off = true
    else
      facade_automatic_shut_off = false
    end
  end

  if facade_automatic_shut_off
    ext_lights_sch_facade_and_landscape = OpenStudio::Model::ScheduleRuleset.new(model)
    default_day = ext_lights_sch_facade_and_landscape.defaultDaySchedule
    default_day.addValue(OpenStudio::Time.new(0, end_setback_shutoff[:hr], end_setback_shutoff[:min], 0), 0.0)
    default_day.addValue(OpenStudio::Time.new(0, start_setback_shutoff[:hr], start_setback_shutoff[:min], 0), 1.0)
    OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ExteriorLighting', "Facade and Landscape exterior lights shut off from #{start_setback_shutoff} to #{end_setback_shutoff}")
  else
    ext_lights_sch_facade_and_landscape = model.alwaysOnDiscreteSchedule
  end

  occupancy_setback_reduction = 0.0
  if exterior_lighting_properties.has_key?('occupancy_setback_reduction')
    if !exterior_lighting_properties['occupancy_setback_reduction'].nil? && (exterior_lighting_properties['occupancy_setback_reduction'] > 0.0)
      occupancy_setback_reduction = exterior_lighting_properties['occupancy_setback_reduction']
    end
  else
    unless ['90.1-2004', '90.1-2007', 'DOE Ref Pre-1980', 'DOE Ref 1980-2004', 'DEER 1985', 'DEER 1996', 'DEER 2003', 'DEER 2007', 'DEER Pre-1975'].include?(lookup_key)
      occupancy_setback_reduction = 0.3
    end
  end

  if occupancy_setback_reduction > 0
    ext_lights_sch_other = OpenStudio::Model::ScheduleRuleset.new(model)
    setback_value = 1.0 - occupancy_setback_reduction
    default_day = ext_lights_sch_other.defaultDaySchedule
    default_day.addValue(OpenStudio::Time.new(0, end_setback_shutoff[:hr], end_setback_shutoff[:min], 0), setback_value)
    default_day.addValue(OpenStudio::Time.new(0, start_setback_shutoff[:hr], start_setback_shutoff[:min], 0), 1.0)
    OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ExteriorLighting', "Non Facade and Landscape lights reduce by #{occupancy_setback_reduction * 100} % from #{start_setback_shutoff} to #{end_setback_shutoff}")
  else
    ext_lights_sch_other = model.alwaysOnDiscreteSchedule
  end

  # add exterior lights for parking area
  if !area_length_count_hash[:parking_area_and_drives_area].nil? && area_length_count_hash[:parking_area_and_drives_area] > 0
    # lighting values
    multiplier = area_length_count_hash[:parking_area_and_drives_area] * onsite_parking_fraction

    # get power
    if exterior_lighting_properties.has_key?('parking_areas_and_drives')
      power = exterior_lighting_properties['parking_areas_and_drives']
    else
      search_criteria = {
        'template' => lookup_key,
        'lighting_zone' => lighting_zone,
        'allowance_type' => 'parking lots and drives'
      }
      exterior_lighting_parking_req = standard.standards_lookup_table_first(table_name: 'exterior_lighting', search_criteria: search_criteria)
      power = exterior_lighting_parking_req['allowance']
    end

    # create exterior lights
    OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ExteriorLighting', "Added #{power.round(2)} W/ft^2 of lighting for #{multiplier} ft^2 of parking area.")
    ext_lights = OpenstudioStandards::ExteriorLighting.model_create_exterior_lights(model,
                                                                                    name: 'Parking Areas and Drives',
                                                                                    power: power,
                                                                                    units: 'W/ft^2',
                                                                                    multiplier: multiplier,
                                                                                    schedule: ext_lights_sch_other,
                                                                                    control_option: control_option)
    exterior_lights << ext_lights
    installed_power += power * multiplier
  end

  # add exterior lights for facades
  if !area_length_count_hash[:building_facades].nil? && area_length_count_hash[:building_facades] > 0
    # lighting values
    multiplier = area_length_count_hash[:building_facades]

    # get power
    if exterior_lighting_properties.has_key?('building_facades')
      power = exterior_lighting_properties['building_facades']
    else
      search_criteria = {
        'template' => lookup_key,
        'lighting_zone' => lighting_zone,
        'allowance_type' => 'building facades',
        'allowance_unit' => 'W/ft2'
      }
      exterior_lighting_facade_req = standard.standards_lookup_table_first(table_name: 'exterior_lighting', search_criteria: search_criteria)
      power = exterior_lighting_facade_req['allowance']
    end

    # create exterior lights
    OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ExteriorLighting', "Added #{power.round(2)} W/ft^2 of lighting for #{multiplier} ft^2 of building facade area.")
    ext_lights = OpenstudioStandards::ExteriorLighting.model_create_exterior_lights(model,
                                                                                    name: 'Building Facades',
                                                                                    power: power,
                                                                                    units: 'W/ft^2',
                                                                                    multiplier: multiplier,
                                                                                    schedule: ext_lights_sch_facade_and_landscape,
                                                                                    control_option: control_option)
    exterior_lights <<  ext_lights
    installed_power += power * multiplier
  end

  # add exterior lights for main entries
  if !area_length_count_hash[:main_entries].nil? && area_length_count_hash[:main_entries] > 0
    # lighting values
    multiplier = area_length_count_hash[:main_entries]

    # get power
    if exterior_lighting_properties.has_key?('main_entries')
      power = exterior_lighting_properties['main_entries']
    else
      search_criteria = {
        'template' => lookup_key,
        'lighting_zone' => lighting_zone,
        'allowance_type' => 'main entries'
      }
      exterior_lighting_entries_req = standard.standards_lookup_table_first(table_name: 'exterior_lighting', search_criteria: search_criteria)
      # change of reference for 90.1-2019 and onwards
      if exterior_lighting_entries_req.nil?
        search_criteria = {
          'template' => lookup_key,
          'lighting_zone' => lighting_zone,
          'allowance_type' => 'pedestrian and vehicular entrances and exists'
        }
        exterior_lighting_entries_req = standard.standards_lookup_table_first(table_name: 'exterior_lighting', search_criteria: search_criteria)
      end
      power = exterior_lighting_entries_req['allowance']
    end

    # create exterior lights
    OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ExteriorLighting', "Added #{power.round(2)} W/ft of lighting for #{multiplier} ft of main entry length.")
    ext_lights = OpenstudioStandards::ExteriorLighting.model_create_exterior_lights(model,
                                                                                    name: 'Main Entries',
                                                                                    power: power,
                                                                                    units: 'W/ft',
                                                                                    multiplier: multiplier,
                                                                                    schedule: ext_lights_sch_other,
                                                                                    control_option: control_option)
    exterior_lights << ext_lights
    installed_power += power * multiplier
  end

  # add exterior lights for other doors
  if !area_length_count_hash[:other_doors].nil? && area_length_count_hash[:other_doors] > 0
    # lighting values
    multiplier = area_length_count_hash[:other_doors]

    # get power
    if exterior_lighting_properties.has_key?('other_doors')
      power = exterior_lighting_properties['other_doors']
    else
      search_criteria = {
        'template' => lookup_key,
        'lighting_zone' => lighting_zone,
        'allowance_type' => 'other doors'
      }
      exterior_lighting_doors_req = standard.standards_lookup_table_first(table_name: 'exterior_lighting', search_criteria: search_criteria)
      # change of reference for 90.1-2019 and onwards
      if exterior_lighting_doors_req.nil?
        search_criteria = {
          'template' => lookup_key,
          'lighting_zone' => lighting_zone,
          'allowance_type' => 'pedestrian and vehicular entrances and exists'
        }
        exterior_lighting_doors_req = standard.standards_lookup_table_first(table_name: 'exterior_lighting', search_criteria: search_criteria)
      end
      power = exterior_lighting_doors_req['allowance']
    end

    # create exterior lights
    OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ExteriorLighting', "Added #{power.round(2)} W/ft of lighting for #{multiplier} ft of other doors.")
    ext_lights = OpenstudioStandards::ExteriorLighting.model_create_exterior_lights(model,
                                                                                    name: 'Other Doors',
                                                                                    power: power,
                                                                                    units: 'W/ft',
                                                                                    multiplier: multiplier,
                                                                                    schedule: ext_lights_sch_other,
                                                                                    control_option: control_option)
    exterior_lights << ext_lights
    installed_power += power * multiplier
  end

  # add exterior lights for entry canopies
  if !area_length_count_hash[:canopy_entry_area].nil? && area_length_count_hash[:canopy_entry_area] > 0
    # lighting values
    multiplier = area_length_count_hash[:canopy_entry_area]

    # get power
    if exterior_lighting_properties.has_key?('entry_canopies')
      power = exterior_lighting_properties['entry_canopies']
    else
      search_criteria = {
        'template' => lookup_key,
        'lighting_zone' => lighting_zone,
        'allowance_type' => 'canopies'
      }
      exterior_lighting_canopies_req = standard.standards_lookup_table_first(table_name: 'exterior_lighting', search_criteria: search_criteria)
      # change of reference for 90.1-2010 and onwards
      if exterior_lighting_parking_req.nil?
        search_criteria = {
          'template' => lookup_key,
          'lighting_zone' => lighting_zone,
          'allowance_type' => 'entry canopies'
        }
        exterior_lighting_canopies_req = standard.standards_lookup_table_first(table_name: 'exterior_lighting', search_criteria: search_criteria)
      end
      power = exterior_lighting_canopies_req['allowance']
    end

    # create exterior lights
    OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ExteriorLighting', "Added #{power} W/ft^2 of lighting for #{multiplier} ft^2 of building entry canopies.")
    ext_lights = OpenstudioStandards::ExteriorLighting.model_create_exterior_lights(model,
                                                                                    name: 'Entry Canopies',
                                                                                    power: power,
                                                                                    units: 'W/ft^2',
                                                                                    multiplier: multiplier,
                                                                                    schedule: ext_lights_sch_other,
                                                                                    control_option: control_option)
    exterior_lights << ext_lights
    installed_power += power * multiplier
  end

  # add exterior lights for emergency canopies
  if !area_length_count_hash[:canopy_emergency_area].nil? && area_length_count_hash[:canopy_emergency_area] > 0
    # lighting values
    multiplier = area_length_count_hash[:canopy_emergency_area]

    # get power
    if exterior_lighting_properties.has_key?('loading_areas_for_emergency_vehicles')
      power = exterior_lighting_properties['loading_areas_for_emergency_vehicles']
    else
      search_criteria = {
        'template' => lookup_key,
        'lighting_zone' => lighting_zone,
        'allowance_type' => 'loading areas for law enforcement, fire, ambulance and other emergency service vehicles (uncovered)'
      }
      exterior_lighting_emergency_canopies_req = standard.standards_lookup_table_first(table_name: 'exterior_lighting', search_criteria: search_criteria)
      power = exterior_lighting_emergency_canopies_req['allowance']
    end

    # create exterior lights
    OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ExteriorLighting', "Added #{power} W/ft^2 of lighting for #{multiplier} ft^2 of building emergency canopies.")
    ext_lights = OpenstudioStandards::ExteriorLighting.model_create_exterior_lights(model,
                                                                                    name: 'Emergency Canopies',
                                                                                    power: power,
                                                                                    units: 'W/ft^2',
                                                                                    multiplier: multiplier,
                                                                                    schedule: ext_lights_sch_other,
                                                                                    control_option: control_option)
    exterior_lights << ext_lights
    installed_power += power * multiplier
  end

  # add exterior lights for drive through windows
  if !area_length_count_hash[:drive_through_windows].nil? && area_length_count_hash[:drive_through_windows] > 0
    # lighting values
    multiplier = area_length_count_hash[:drive_through_windows]

    # get power
    if exterior_lighting_properties.has_key?('drive_through_windows_and_doors')
      power = exterior_lighting_properties['drive_through_windows_and_doors']
    else
      search_criteria = {
        'template' => lookup_key,
        'lighting_zone' => lighting_zone,
        'allowance_type' => 'drive-up windows at fast food restaurant'
      }
      exterior_lighting_emergency_drive_through_req = standard.standards_lookup_table_first(table_name: 'exterior_lighting', search_criteria: search_criteria)
      power = exterior_lighting_emergency_drive_through_req['allowance']
    end

    # create exterior lights
    OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ExteriorLighting', "Added #{power} W/drive through window of lighting for #{multiplier} drive through windows.")
    ext_lights = OpenstudioStandards::ExteriorLighting.model_create_exterior_lights(model,
                                                                                    name: 'Drive Through Windows',
                                                                                    power: power,
                                                                                    units: 'W/ft^2',
                                                                                    multiplier: multiplier,
                                                                                    schedule: ext_lights_sch_other,
                                                                                    control_option: control_option)
    exterior_lights << ext_lights
    installed_power += power * multiplier
  end

  # add base site allowance
  if add_base_site_allowance
    # lighting values
    if exterior_lighting_properties.has_key?('base_site_allowance_power')
      if !exterior_lighting_properties['base_site_allowance_power'].nil?
        power = exterior_lighting_properties['base_site_allowance_power']
      elsif !exterior_lighting_properties['base_site_allowance_fraction'].nil?
        power = exterior_lighting_properties['base_site_allowance_fraction'] * installed_power # should be of allowed vs. installed, but hard to calculate
      else
        OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ExteriorLighting', 'Cannot determine target base site allowance power, will set to 0 W.')
        power = 0.0
      end
    else
      search_criteria = {
        'template' => lookup_key,
        'lighting_zone' => lighting_zone,
        'allowance_type' => 'base site allowance'
      }
      exterior_lighting_base_allowance = standard.standards_lookup_table_first(table_name: 'exterior_lighting', search_criteria: search_criteria)
      power = exterior_lighting_base_allowance['allowance']

      search_criteria = {
        'template' => lookup_key,
        'lighting_zone' => lighting_zone,
        'allowance_type' => 'additional unrestricted allowance'
      }
      exterior_lighting_add_base_allowance = standard.standards_lookup_table_first(table_name: 'exterior_lighting', search_criteria: search_criteria)
      if !exterior_lighting_add_base_allowance.nil?
        power += exterior_lighting_add_base_allowance['allowance'] * installed_power / 100.0 # should be of allowed vs. installed, but hard to calculate
      end
    end

    # create exterior lights
    OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ExteriorLighting', "Added #{power} W of non landscape tradable exterior lighting. Will follow occupancy setback reduction.")
    ext_lights = OpenstudioStandards::ExteriorLighting.model_create_exterior_lights(model,
                                                                                    name: 'Base Site Allowance',
                                                                                    power: power,
                                                                                    units: 'W',
                                                                                    multiplier: 1.0,
                                                                                    schedule: ext_lights_sch_other,
                                                                                    control_option: control_option)
    exterior_lights << ext_lights
  end

  return exterior_lights
end

.model_get_exterior_lighting_properties(lighting_generation: 'default', lighting_zone: 3) ⇒ Hash

get exterior lighting properties by lighting generation

Parameters:

  • lighting_generation (String) (defaults to: 'default')

    lighting generation

Returns:

  • (Hash)

    hash of exterior lighting properties



187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/openstudio-standards/exterior_lighting/information.rb', line 187

def self.model_get_exterior_lighting_properties(lighting_generation: 'default',
                                                lighting_zone: 3)
  # load typical exterior lighting data
  data = JSON.parse(File.read("#{File.dirname(__FILE__)}/data/typical_exterior_lighting.json"))
  exterior_lighting_properties = data['exterior_lighting'].select { |hash| (hash['lighting_generation'] == lighting_generation) && (hash['lighting_zone'] == lighting_zone) }[0]

  # make sure lighting properties were found
  if exterior_lighting_properties.nil?
    OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.ExteriorLighting', "Exterior lighting properties not found for lighting generation #{lighting_generation}, exterior lighting zone #{lighting_zone}.")
    return nil
  end

  return exterior_lighting_properties
end

.model_get_exterior_lighting_sizes(model) ⇒ Hash

get exterior lighting areas, distances, and counts

Parameters:

  • model (OpenStudio::Model::Model)

    OpenStudio model object

Returns:

  • (Hash)

    hash of exterior lighting value types and building type and model specific values



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/openstudio-standards/exterior_lighting/information.rb', line 10

def self.model_get_exterior_lighting_sizes(model)
  # load parking file and convert to hash table
  parking_json = "#{File.dirname(__FILE__)}/data/parking.json"
  unless File.file?(parking_json)
    OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.ExteriorLighting', "Unable to find file: #{parking_json}")
    return false
  end
  parking_hsh = JSON.parse(File.read("#{File.dirname(__FILE__)}/data/parking.json"), symbolize_names: true)
  parking_hsh = parking_hsh[:parking]

  # load entryways file and convert to hash table
  entryways_json = "#{File.dirname(__FILE__)}/data/entryways.json"
  unless File.file?(entryways_json)
    OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.ExteriorLighting', "Unable to find file: #{entryways_json}")
    return false
  end
  entryways_hsh = JSON.parse(File.read("#{File.dirname(__FILE__)}/data/entryways.json"), symbolize_names: true)
  entryways_hsh = entryways_hsh[:entryways]

  # get space properties from the model
  space_type_hash = OpenstudioStandards::CreateTypical.model_get_space_type_information(model)

  # populate building_type_hashes from space_type_hash
  building_type_hashes = {}
  space_type_hash.each do |space_type, hash|
    # if space type standards building type already exists,
    # add data to that standards building type in building_type_hashes
    if building_type_hashes.key?(hash[:standards_building_type])
      building_type_hashes[hash[:standards_building_type]][:effective_number_of_spaces] += hash[:effective_number_of_spaces]
      building_type_hashes[hash[:standards_building_type]][:floor_area] += hash[:floor_area]
      building_type_hashes[hash[:standards_building_type]][:number_of_people] += hash[:number_of_people]
      building_type_hashes[hash[:standards_building_type]][:number_of_students] += hash[:number_of_students]
      building_type_hashes[hash[:standards_building_type]][:number_of_units] += hash[:number_of_units]
      building_type_hashes[hash[:standards_building_type]][:number_of_beds] += hash[:number_of_beds]
    else
      # initialize hash for this building type
      building_type_hash = {}
      building_type_hash[:effective_number_of_spaces] = hash[:effective_number_of_spaces]
      building_type_hash[:floor_area] = hash[:floor_area]
      building_type_hash[:number_of_people] = hash[:number_of_people]
      building_type_hash[:number_of_students] = hash[:number_of_students]
      building_type_hash[:number_of_units] = hash[:number_of_units]
      building_type_hash[:number_of_beds] = hash[:number_of_beds]
      building_type_hashes[hash[:standards_building_type]] = building_type_hash
    end
  end

  # rename Office to SmallOffice, MediumOffice or LargeOffice depending on size
  if building_type_hashes.key?('Office')
    floor_area = building_type_hashes['Office'][:floor_area]
    office_type = if floor_area < 2750
                    'SmallOffice'
                  elsif floor_area < 25_250
                    'MediumOffice'
                  else
                    'LargeOffice'
                  end
    building_type_hashes[office_type] = building_type_hashes.delete('Office')
  end

  # initialize parking areas and drives area variables
  parking_area_and_drives_area = 0.0
  main_entries = 0.0
  other_doors = 0.0
  rollup_doors = 0.0
  drive_through_windows = 0.0
  canopy_entry_area = 0.0
  canopy_emergency_area = 0.0
  ground_story_ext_wall_area = 0.0

  # temporary std for model_effective_num_stories method
  std = Standard.build('90.1-2013')

  # calculate exterior lighting properties for each building type
  building_type_hashes.each do |building_type, hash|
    # calculate floor area and ground floor area in IP units
    floor_area_ft2 = OpenStudio.convert(hash[:floor_area], 'm^2', 'ft^2').get
    effective_num_stories = std.model_effective_num_stories(model)
    ground_floor_area_ft2 = floor_area_ft2 / effective_num_stories[:above_grade]

    # load parking area properties for standards building type
    parking_properties = parking_hsh.select { |h| h[:building_type] == building_type }

    if parking_properties.nil? || parking_properties.empty?
      OpenStudio.logFree(OpenStudio::Warn, 'openstudio.prototype.ExteriorLighting', "Could not find parking data for #{building_type}. Will not add exterior parking lighting. The building type data needs to be added to the parking lighting data.")
      return {}
    end
    parking_properties = parking_properties[0]

    # calculate number of parking spots
    num_spots = 0.0
    if !parking_properties[:building_area_per_spot].nil?
      num_spots += floor_area_ft2 / parking_properties[:building_area_per_spot].to_f
    elsif !parking_properties[:units_per_spot].nil?
      num_spots += hash[:number_of_units] / parking_properties[:units_per_spot].to_f
    elsif !parking_properties[:students_per_spot].nil?
      num_spots += hash[:number_of_students] / parking_properties[:students_per_spot].to_f
    elsif !parking_properties[:beds_per_spot].nil?
      num_spots += hash[:number_of_beds] / parking_properties[:beds_per_spot].to_f
    end

    # add to cumulative parking area
    parking_area_and_drives_area += num_spots * parking_properties[:parking_area_per_spot]

    # load entryways properties for standards building type
    entryways_properties = entryways_hsh.select { |eh| eh[:building_type] == building_type }

    if entryways_properties.nil? || entryways_properties.empty?
      OpenStudio.logFree(OpenStudio::Error, 'openstudio.prototype.ExteriorLighting', "Could not find entryway data for #{building_type}.")
      return {}
    end
    entryways_properties = entryways_properties[0]

    # calculate door, window, and canopy length properties for exterior lighting
    # main entries
    unless entryways_properties[:entrance_doors_per_10000_ft2].nil?
      main_entries += (ground_floor_area_ft2 / 10_000.0) * entryways_properties[:entrance_doors_per_10000_ft2].to_f
    end

    # other doors
    unless entryways_properties[:other_doors_per_10000_ft2].nil?
      other_doors += (ground_floor_area_ft2 / 10_000.0) * entryways_properties[:other_doors_per_10000_ft2].to_f
    end

    # rollup doors
    unless entryways_properties[:rollup_doors_per_10000_ft2].nil?
      rollup_doors += (ground_floor_area_ft2 / 10_000.0) / entryways_properties[:rollup_doors_per_10000_ft2].to_f
    end

    # drive through windows
    unless entryways_properties[:floor_area_per_drive_through_window].nil?
      drive_through_windows += ground_floor_area_ft2 / entryways_properties[:floor_area_per_drive_through_window].to_f
    end

    # entrance canopies
    if !entryways_properties[:entrance_canopies].nil? && !entryways_properties[:canopy_size].nil?
      canopy_entry_area += entryways_properties[:entrance_canopies] * entryways_properties[:canopy_size].to_f
    end

    # emergency canopies
    if !entryways_properties[:emergency_canopies].nil? && !entryways_properties[:canopy_size].nil?
      canopy_emergency_area += entryways_properties[:emergency_canopies] * entryways_properties[:canopy_size].to_f
    end

    # building_facades
    # determine effective number of stories to find first above grade story exterior wall area
    ground_story = effective_num_stories[:story_hash].keys[effective_num_stories[:below_grade]]
    ground_story_ext_wall_area_m2 = effective_num_stories[:story_hash][ground_story][:ext_wall_area]
    ground_story_ext_wall_area += OpenStudio.convert(ground_story_ext_wall_area_m2, 'm^2', 'ft^2').get
  end

  # no source for width of different entry types
  main_entry_width_ft = 8.0
  other_doors_width_ft = 4.0
  rollup_door_width_ft = 8.0

  # ensure the building has at least 1 main entry
  main_entries = [1.0, main_entries].max

  # populate hash
  area_length_count_hash = {}
  area_length_count_hash[:parking_area_and_drives_area] = parking_area_and_drives_area
  area_length_count_hash[:main_entries] = main_entries * main_entry_width_ft
  area_length_count_hash[:other_doors] = other_doors * other_doors_width_ft
  area_length_count_hash[:rollup_doors] = rollup_doors * rollup_door_width_ft
  area_length_count_hash[:drive_through_windows] = drive_through_windows
  area_length_count_hash[:canopy_entry_area] = canopy_entry_area
  area_length_count_hash[:canopy_emergency_area] = canopy_emergency_area
  area_length_count_hash[:building_facades] = ground_story_ext_wall_area

  return area_length_count_hash
end