openstudio-ee 0.12.3 → 0.12.4

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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.coverage +0 -0
  3. data/.github/workflows/test-with-openstudio.yml +109 -74
  4. data/.gitignore +21 -0
  5. data/.rubocop.yml +15 -2
  6. data/CHANGELOG.md +3 -0
  7. data/Gemfile +7 -8
  8. data/README.md +1 -0
  9. data/WORKFLOW_CHANGES.md +74 -0
  10. data/lib/measures/AddDaylightSensors/measure.rb +79 -79
  11. data/lib/measures/AddDaylightSensors/measure.xml +4 -4
  12. data/lib/measures/AddOverhangsByProjectionFactor/measure.rb +38 -41
  13. data/lib/measures/AddOverhangsByProjectionFactor/measure.xml +4 -4
  14. data/lib/measures/EnableDemandControlledVentilation/measure.rb +37 -40
  15. data/lib/measures/EnableDemandControlledVentilation/measure.xml +4 -4
  16. data/lib/measures/EnableEconomizerControl/measure.rb +36 -37
  17. data/lib/measures/EnableEconomizerControl/measure.xml +4 -4
  18. data/lib/measures/GLHEProExportLoadsforGroundHeatExchangerSizing/measure.rb +27 -41
  19. data/lib/measures/GLHEProExportLoadsforGroundHeatExchangerSizing/measure.xml +4 -4
  20. data/lib/measures/GLHEProGFunctionImport/measure.rb +11 -15
  21. data/lib/measures/GLHEProGFunctionImport/measure.xml +4 -4
  22. data/lib/measures/GLHEProSetupExportLoadsforGroundHeatExchangerSizing/measure.rb +5 -9
  23. data/lib/measures/GLHEProSetupExportLoadsforGroundHeatExchangerSizing/measure.xml +3 -3
  24. data/lib/measures/ImproveFanBeltEfficiency/measure.rb +78 -95
  25. data/lib/measures/ImproveFanBeltEfficiency/measure.xml +6 -6
  26. data/lib/measures/ImproveMotorEfficiency/measure.rb +75 -100
  27. data/lib/measures/ImproveMotorEfficiency/measure.xml +6 -6
  28. data/lib/measures/IncreaseInsulationRValueForExteriorWalls/measure.rb +137 -130
  29. data/lib/measures/IncreaseInsulationRValueForExteriorWalls/measure.xml +4 -4
  30. data/lib/measures/IncreaseInsulationRValueForExteriorWallsByPercentage/measure.rb +114 -115
  31. data/lib/measures/IncreaseInsulationRValueForExteriorWallsByPercentage/measure.xml +3 -3
  32. data/lib/measures/IncreaseInsulationRValueForRoofs/measure.rb +137 -130
  33. data/lib/measures/IncreaseInsulationRValueForRoofs/measure.xml +4 -4
  34. data/lib/measures/IncreaseInsulationRValueForRoofsByPercentage/measure.rb +114 -115
  35. data/lib/measures/IncreaseInsulationRValueForRoofsByPercentage/measure.xml +3 -3
  36. data/lib/measures/ReduceElectricEquipmentLoadsByPercentage/measure.rb +69 -63
  37. data/lib/measures/ReduceElectricEquipmentLoadsByPercentage/measure.xml +6 -6
  38. data/lib/measures/ReduceLightingLoadsByPercentage/measure.rb +77 -66
  39. data/lib/measures/ReduceLightingLoadsByPercentage/measure.xml +6 -6
  40. data/lib/measures/ReduceNightTimeElectricEquipmentLoads/measure.rb +45 -43
  41. data/lib/measures/ReduceNightTimeElectricEquipmentLoads/measure.xml +4 -4
  42. data/lib/measures/ReduceNightTimeLightingLoads/measure.rb +45 -43
  43. data/lib/measures/ReduceNightTimeLightingLoads/measure.xml +4 -4
  44. data/lib/measures/ReduceSpaceInfiltrationByPercentage/measure.rb +58 -52
  45. data/lib/measures/ReduceSpaceInfiltrationByPercentage/measure.xml +6 -6
  46. data/lib/measures/ReduceVentilationByPercentage/measure.rb +49 -46
  47. data/lib/measures/ReduceVentilationByPercentage/measure.xml +6 -6
  48. data/lib/measures/add_variable_speed_rtu_control_logic/measure.rb +31 -23
  49. data/lib/measures/add_variable_speed_rtu_control_logic/measure.xml +4 -4
  50. data/lib/measures/create_variable_speed_rtu/measure.rb +166 -174
  51. data/lib/measures/create_variable_speed_rtu/measure.xml +6 -6
  52. data/lib/measures/fan_assist_night_ventilation/measure.rb +33 -32
  53. data/lib/measures/fan_assist_night_ventilation/measure.xml +4 -4
  54. data/lib/measures/nze_hvac/measure.rb +72 -62
  55. data/lib/measures/nze_hvac/measure.xml +4 -4
  56. data/lib/measures/replace_water_heater_mixed_with_thermal_storage_chilled_water/measure.rb +16 -19
  57. data/lib/measures/replace_water_heater_mixed_with_thermal_storage_chilled_water/measure.xml +4 -4
  58. data/lib/measures/window_enhancement/LICENSE.md +14 -0
  59. data/lib/measures/window_enhancement/README.md +112 -0
  60. data/lib/measures/window_enhancement/docs/.gitkeep +0 -0
  61. data/lib/measures/window_enhancement/measure.py +386 -0
  62. data/lib/measures/window_enhancement/measure.xml +128 -0
  63. data/lib/measures/window_enhancement/resources/EC3_lookup.py +321 -0
  64. data/lib/measures/window_enhancement/resources/Test_API.py +32 -0
  65. data/lib/measures/window_enhancement/resources/__pycache__/EC3_lookup.cpython-39.pyc +0 -0
  66. data/lib/measures/window_enhancement/resources/__pycache__/Original_EC3_lookup.py +322 -0
  67. data/lib/measures/window_enhancement/resources/__pycache__/Test_API.cpython-39.pyc +0 -0
  68. data/lib/measures/window_enhancement/resources/calculate_perimeter.py +39 -0
  69. data/lib/measures/window_enhancement/test_output.log +39 -0
  70. data/lib/openstudio/ee_measures/version.rb +1 -1
  71. data/openstudio-ee.gemspec +10 -8
  72. data/test-workflow-locally.sh +152 -0
  73. metadata +64 -35
  74. data/Jenkinsfile +0 -11
@@ -9,17 +9,17 @@
9
9
  class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
10
10
  # define the name that a user will see
11
11
  def name
12
- return 'Reduce Lighting Loads by Percentage'
12
+ 'Reduce Lighting Loads by Percentage'
13
13
  end
14
14
 
15
15
  # human readable description
16
16
  def description
17
- return 'The lighting system in this building uses more power per area than is required with the latest lighting technologies. Replace the lighting system with a newer, more efficient lighting technology. Newer technologies provide the same amount of light but use less energy in the process.'
17
+ 'The lighting system in this building uses more power per area than is required with the latest lighting technologies. Replace the lighting system with a newer, more efficient lighting technology. Newer technologies provide the same amount of light but use less energy in the process.'
18
18
  end
19
19
 
20
20
  # human readable description of modeling approach
21
21
  def modeler_description
22
- return 'This measure supports models which have a mixture of lighting assigned to spaces and space types. The lighting may be specified as individual luminaires, lighting equipment level, lighting power per area, or lighting power per person. Loop through all lights and luminaires in the specified space type or the entire building. Clone the definition if it is shared by other lights, rename and adjust the power based on the specified percentage. Link the new definition to the existing lights or luminaire instance. Adjust the power for lighting equipment assigned to a particular space but only if that space is part of the selected space type by looping through the objects first in space types and then in spaces, but again only for spaces that are in the specified space type (unless the entire building has been chosen). Material and installation cost increases will be applied to all costs related to both the definition and instance of the lighting object. If this measure includes baseline costs, then the material and installation costs of the lighting objects in the baseline model will be summed together and added as a capital cost on the building object.'
22
+ 'This measure supports models which have a mixture of lighting assigned to spaces and space types. The lighting may be specified as individual luminaires, lighting equipment level, lighting power per area, or lighting power per person. Loop through all lights and luminaires in the specified space type or the entire building. Clone the definition if it is shared by other lights, rename and adjust the power based on the specified percentage. Link the new definition to the existing lights or luminaire instance. Adjust the power for lighting equipment assigned to a particular space but only if that space is part of the selected space type by looping through the objects first in space types and then in spaces, but again only for spaces that are in the specified space type (unless the entire building has been chosen). Material and installation cost increases will be applied to all costs related to both the definition and instance of the lighting object. If this measure includes baseline costs, then the material and installation costs of the lighting objects in the baseline model will be summed together and added as a capital cost on the building object.'
23
23
  end
24
24
 
25
25
  # define the arguments that the user will input
@@ -40,7 +40,7 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
40
40
  # looping through sorted hash of model objects
41
41
  space_type_args_hash.sort.map do |key, value|
42
42
  # only include if space type is used in the model
43
- if !value.spaces.empty?
43
+ unless value.spaces.empty?
44
44
  space_type_handles << value.handle.to_s
45
45
  space_type_display_names << key
46
46
  end
@@ -52,20 +52,25 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
52
52
  space_type_display_names << '*Entire Building*'
53
53
 
54
54
  # make a choice argument for space type
55
- space_type = OpenStudio::Measure::OSArgument.makeChoiceArgument('space_type', space_type_handles, space_type_display_names)
55
+ space_type = OpenStudio::Measure::OSArgument.makeChoiceArgument('space_type', space_type_handles,
56
+ space_type_display_names)
56
57
  space_type.setDisplayName('Apply the Measure to a Specific Space Type or to the Entire Model')
57
58
  space_type.setDefaultValue('*Entire Building*') # if no space type is chosen this will run on the entire building
58
59
  args << space_type
59
60
 
60
61
  # make an argument for reduction percentage
61
- lighting_power_reduction_percent = OpenStudio::Measure::OSArgument.makeDoubleArgument('lighting_power_reduction_percent', true)
62
+ lighting_power_reduction_percent = OpenStudio::Measure::OSArgument.makeDoubleArgument(
63
+ 'lighting_power_reduction_percent', true
64
+ )
62
65
  lighting_power_reduction_percent.setDisplayName('Lighting Power Reduction')
63
66
  lighting_power_reduction_percent.setDefaultValue(30.0)
64
67
  lighting_power_reduction_percent.setUnits('%')
65
68
  args << lighting_power_reduction_percent
66
69
 
67
70
  # make an argument for material and installation cost
68
- material_and_installation_cost = OpenStudio::Measure::OSArgument.makeDoubleArgument('material_and_installation_cost', true)
71
+ material_and_installation_cost = OpenStudio::Measure::OSArgument.makeDoubleArgument(
72
+ 'material_and_installation_cost', true
73
+ )
69
74
  material_and_installation_cost.setDisplayName('Increase in Material and Installation Cost for Lighting per Floor Area')
70
75
  material_and_installation_cost.setDefaultValue(0.0)
71
76
  material_and_installation_cost.setUnits('%')
@@ -112,7 +117,7 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
112
117
  om_frequency.setUnits('whole years')
113
118
  args << om_frequency
114
119
 
115
- return args
120
+ args
116
121
  end
117
122
 
118
123
  # define what happens when the measure is run
@@ -120,9 +125,7 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
120
125
  super(model, runner, user_arguments)
121
126
 
122
127
  # use the built-in error checking
123
- if !runner.validateUserArguments(arguments(model), user_arguments)
124
- return false
125
- end
128
+ return false unless runner.validateUserArguments(arguments(model), user_arguments)
126
129
 
127
130
  # assign the user inputs to variables
128
131
  object = runner.getOptionalWorkspaceObjectChoiceValue('space_type', user_arguments, model)
@@ -146,15 +149,13 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
146
149
  runner.registerError("The selected space type with handle '#{handle}' was not found in the model. It may have been removed by another measure.")
147
150
  end
148
151
  return false
152
+ elsif !object.get.to_SpaceType.empty?
153
+ space_type = object.get.to_SpaceType.get
154
+ elsif !object.get.to_Building.empty?
155
+ apply_to_building = true
149
156
  else
150
- if !object.get.to_SpaceType.empty?
151
- space_type = object.get.to_SpaceType.get
152
- elsif !object.get.to_Building.empty?
153
- apply_to_building = true
154
- else
155
- runner.registerError('Script Error - argument not showing up as space type or building.')
156
- return false
157
- end
157
+ runner.registerError('Script Error - argument not showing up as space type or building.')
158
+ return false
158
159
  end
159
160
 
160
161
  # check the lighting_power_reduction_percent and for reasonableness
@@ -197,24 +198,25 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
197
198
  return false
198
199
  end
199
200
 
200
- if om_frequency < 1
201
- runner.registerError('Choose an integer greater than 0 for O & M Frequency.')
202
- end
201
+ runner.registerError('Choose an integer greater than 0 for O & M Frequency.') if om_frequency < 1
203
202
 
204
203
  # helper to make numbers pretty (converts 4125001.25641 to 4,125,001.26 or 4,125,001). The definition be called through this measure.
205
204
  def neat_numbers(number, roundto = 2) # round to 0 or 2)
206
- if roundto == 2
207
- number = format '%.2f', number
208
- else
209
- number = number.round
210
- end
205
+ number = if roundto == 2
206
+ format '%.2f', number
207
+ else
208
+ number.round
209
+ end
211
210
  # regex to add commas
212
211
  number.to_s.reverse.gsub(/([0-9]{3}(?=([0-9])))/, '\\1,').reverse
213
212
  end
214
213
 
215
214
  # helper to make it easier to do unit conversions on the fly. The definition be called through this measure.
216
215
  def unit_helper(number, from_unit_string, to_unit_string)
217
- converted_number = OpenStudio.convert(OpenStudio::Quantity.new(number, OpenStudio.createUnit(from_unit_string).get), OpenStudio.createUnit(to_unit_string).get).get.value
216
+ converted_number = OpenStudio.convert(
217
+ OpenStudio::Quantity.new(number,
218
+ OpenStudio.createUnit(from_unit_string).get), OpenStudio.createUnit(to_unit_string).get
219
+ ).get.value
218
220
  end
219
221
 
220
222
  # helper that loops through lifecycle costs getting total costs under "Construction" or "Salvage" category and add to counter if occurs during year 0
@@ -223,14 +225,12 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
223
225
  objects.each do |object|
224
226
  object_LCCs = object.lifeCycleCosts
225
227
  object_LCCs.each do |object_LCC|
226
- if (object_LCC.category == 'Construction') || (object_LCC.category == 'Salvage')
227
- if object_LCC.yearsFromStart == 0
228
- counter += object_LCC.totalCost
229
- end
230
- end
228
+ next unless (object_LCC.category == 'Construction') || (object_LCC.category == 'Salvage')
229
+
230
+ counter += object_LCC.totalCost if object_LCC.yearsFromStart == 0
231
231
  end
232
232
  end
233
- return counter
233
+ counter
234
234
  end
235
235
 
236
236
  # counter for demo cost of baseline objects
@@ -250,9 +250,13 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
250
250
  # method should always return double but this is work around for when it is nan because of 0 floor area
251
251
  if building.floorArea > 0.0
252
252
  building_LPD = unit_helper(building.lightingPowerPerFloorArea, 'W/m^2', 'W/ft^2')
253
- runner.registerInitialCondition("The model's initial building lighting power was #{neat_numbers(building_lighting_power, 0)} watts, a lighting power density of #{neat_numbers(building_LPD)} w/ft^2.")
253
+ runner.registerInitialCondition("The model's initial building lighting power was #{neat_numbers(
254
+ building_lighting_power, 0
255
+ )} watts, a lighting power density of #{neat_numbers(building_LPD)} w/ft^2.")
254
256
  else
255
- runner.registerInitialCondition("The model's initial building lighting power was #{neat_numbers(building_lighting_power, 0)} watts. Building Area is not greater than 0 so an LPD can't be calculated.")
257
+ runner.registerInitialCondition("The model's initial building lighting power was #{neat_numbers(
258
+ building_lighting_power, 0
259
+ )} watts. Building Area is not greater than 0 so an LPD can't be calculated.")
256
260
  end
257
261
 
258
262
  # get space types in model
@@ -269,24 +273,23 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
269
273
  if demo_cost_initial_const == true
270
274
  baseline_object_LCCs = baseline_object.lifeCycleCosts
271
275
  baseline_object_LCCs.each do |baseline_object_LCC|
272
- if baseline_object_LCC.category == 'Salvage'
273
- counter += baseline_object_LCC.totalCost
274
- end
276
+ counter += baseline_object_LCC.totalCost if baseline_object_LCC.category == 'Salvage'
275
277
  end
276
278
  end
277
- return counter
279
+ counter
278
280
  end
279
281
 
280
282
  # def to alter performance and life cycle costs of objects
281
- def alter_performance_and_lcc(object, lighting_power_reduction_percent, material_and_installation_cost, demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
283
+ def alter_performance_and_lcc(object, lighting_power_reduction_percent, material_and_installation_cost,
284
+ demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
282
285
  # edit clone based on percentage reduction
283
286
  new_def = object
284
287
  if !new_def.lightingLevel.empty?
285
- new_lighting_level = new_def.setLightingLevel(new_def.lightingLevel.get - new_def.lightingLevel.get * lighting_power_reduction_percent * 0.01)
288
+ new_lighting_level = new_def.setLightingLevel(new_def.lightingLevel.get - (new_def.lightingLevel.get * lighting_power_reduction_percent * 0.01))
286
289
  elsif !new_def.wattsperSpaceFloorArea.empty?
287
- new_lighting_per_area = new_def.setWattsperSpaceFloorArea(new_def.wattsperSpaceFloorArea.get - new_def.wattsperSpaceFloorArea.get * lighting_power_reduction_percent * 0.01)
290
+ new_lighting_per_area = new_def.setWattsperSpaceFloorArea(new_def.wattsperSpaceFloorArea.get - (new_def.wattsperSpaceFloorArea.get * lighting_power_reduction_percent * 0.01))
288
291
  elsif !new_def.wattsperPerson.empty?
289
- new_lighting_per_person = new_def.setWattsperPerson(new_def.wattsperPerson.get - new_def.wattsperPerson.get * lighting_power_reduction_percent * 0.01)
292
+ new_lighting_per_person = new_def.setWattsperPerson(new_def.wattsperPerson.get - (new_def.wattsperPerson.get * lighting_power_reduction_percent * 0.01))
290
293
  else
291
294
  runner.registerWarning("'#{new_def.name}' is used by one or more instances and has no load values. Its performance was not altered.")
292
295
  end
@@ -299,15 +302,15 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
299
302
  else
300
303
  new_def_LCCs.each do |new_def_LCC|
301
304
  if new_def_LCC.category == 'Construction'
302
- new_def_LCC.setCost(new_def_LCC.cost * (1 + material_and_installation_cost / 100))
305
+ new_def_LCC.setCost(new_def_LCC.cost * (1 + (material_and_installation_cost / 100)))
303
306
  new_def_LCC.setYearsFromStart(years_until_costs_start) # just uses argument value, does not need existing value
304
307
  new_def_LCC.setRepeatPeriodYears(expected_life) # just uses argument value, does not need existing value
305
308
  elsif new_def_LCC.category == 'Salvage'
306
- new_def_LCC.setCost(new_def_LCC.cost * (1 + demolition_cost / 100))
309
+ new_def_LCC.setCost(new_def_LCC.cost * (1 + (demolition_cost / 100)))
307
310
  new_def_LCC.setYearsFromStart(years_until_costs_start + expected_life) # just uses argument value, does not need existing value
308
311
  new_def_LCC.setRepeatPeriodYears(expected_life) # just uses argument value, does not need existing value
309
312
  elsif new_def_LCC.category == 'Maintenance'
310
- new_def_LCC.setCost(new_def_LCC.cost * (1 + om_cost / 100))
313
+ new_def_LCC.setCost(new_def_LCC.cost * (1 + (om_cost / 100)))
311
314
  new_def_LCC.setRepeatPeriodYears(om_frequency) # just uses argument value, does not need existing value
312
315
  end
313
316
 
@@ -326,11 +329,12 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
326
329
  # loop through space types
327
330
  space_types.each do |space_type|
328
331
  next if space_type.spaces.size <= 0
332
+
329
333
  space_type_lights = space_type.lights
330
334
  space_type_lights.each do |space_type_light|
331
335
  # clone def if it has not already been cloned
332
336
  exist_def = space_type_light.lightsDefinition
333
- if cloned_lights_defs.any? { |k, v| k.to_s == exist_def.name.to_s }
337
+ if cloned_lights_defs.any? { |k, _v| k.to_s == exist_def.name.to_s }
334
338
  new_def = cloned_lights_defs[exist_def.name.to_s]
335
339
  else
336
340
  # clone rename and add to hash
@@ -343,7 +347,8 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
343
347
  demo_costs_of_baseline_objects += add_to_baseline_demo_cost_counter(exist_def, demo_cost_initial_const)
344
348
 
345
349
  # call def to alter performance and life cycle costs
346
- alter_performance_and_lcc(new_def, lighting_power_reduction_percent, material_and_installation_cost, demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
350
+ alter_performance_and_lcc(new_def, lighting_power_reduction_percent, material_and_installation_cost,
351
+ demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
347
352
 
348
353
  end
349
354
 
@@ -356,7 +361,7 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
356
361
  space_type_luminaires.each do |space_type_luminaire|
357
362
  # clone def if it has not already been cloned
358
363
  exist_def = space_type_luminaire.luminaireDefinition
359
- if cloned_luminaire_defs.any? { |k, v| k.to_s == exist_def.name }
364
+ if cloned_luminaire_defs.any? { |k, _v| k.to_s == exist_def.name }
360
365
  new_def = cloned_luminaire_defs[exist_def.name]
361
366
  else
362
367
  # clone rename and add to hash
@@ -369,7 +374,8 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
369
374
  demo_costs_of_baseline_objects += add_to_baseline_demo_cost_counter(exist_def, demo_cost_initial_const)
370
375
 
371
376
  # call def to alter performance and life cycle costs
372
- alter_performance_and_lcc(new_def, lighting_power_reduction_percent, material_and_installation_cost, demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
377
+ alter_performance_and_lcc(new_def, lighting_power_reduction_percent, material_and_installation_cost,
378
+ demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
373
379
 
374
380
  end
375
381
 
@@ -385,10 +391,8 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
385
391
  # get space types in model
386
392
  if apply_to_building
387
393
  spaces = model.getSpaces
388
- else
389
- if !space_type.spaces.empty?
390
- spaces = space_type.spaces # only run on a single space type
391
- end
394
+ elsif !space_type.spaces.empty?
395
+ spaces = space_type.spaces
392
396
  end
393
397
 
394
398
  spaces.each do |space|
@@ -396,7 +400,7 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
396
400
  space_lights.each do |space_light|
397
401
  # clone def if it has not already been cloned
398
402
  exist_def = space_light.lightsDefinition
399
- if cloned_lights_defs.any? { |k, v| k.to_s == exist_def.name.to_s }
403
+ if cloned_lights_defs.any? { |k, _v| k.to_s == exist_def.name.to_s }
400
404
  new_def = cloned_lights_defs[exist_def.name.to_s]
401
405
  else
402
406
  # clone rename and add to hash
@@ -409,7 +413,8 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
409
413
  demo_costs_of_baseline_objects += add_to_baseline_demo_cost_counter(exist_def, demo_cost_initial_const)
410
414
 
411
415
  # call def to alter performance and life cycle costs
412
- alter_performance_and_lcc(new_def, lighting_power_reduction_percent, material_and_installation_cost, demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
416
+ alter_performance_and_lcc(new_def, lighting_power_reduction_percent, material_and_installation_cost,
417
+ demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
413
418
 
414
419
  end
415
420
 
@@ -422,7 +427,7 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
422
427
  space_luminaires.each do |space_luminaire|
423
428
  # clone def if it has not already been cloned
424
429
  exist_def = space_luminaire.luminaireDefinition
425
- if cloned_luminaire_defs.any? { |k, v| k.to_s == exist_def.name }
430
+ if cloned_luminaire_defs.any? { |k, _v| k.to_s == exist_def.name }
426
431
  new_def = cloned_luminaire_defs[exist_def.name]
427
432
  else
428
433
  # clone rename and add to hash
@@ -435,7 +440,8 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
435
440
  demo_costs_of_baseline_objects += add_to_baseline_demo_cost_counter(exist_def, demo_cost_initial_const)
436
441
 
437
442
  # call def to alter performance and life cycle costs
438
- alter_performance_and_lcc(new_def, lighting_power_reduction_percent, material_and_installation_cost, demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
443
+ alter_performance_and_lcc(new_def, lighting_power_reduction_percent, material_and_installation_cost,
444
+ demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
439
445
 
440
446
  end
441
447
 
@@ -457,12 +463,11 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
457
463
  if demo_cost_initial_const == true
458
464
  building = model.getBuilding
459
465
  lcc_baseline_demo = OpenStudio::Model::LifeCycleCost.createLifeCycleCost('LCC_baseline_demo', building, demo_costs_of_baseline_objects, 'CostPerEach', 'Salvage', 0, years_until_costs_start).get # using 0 for repeat period since one time cost.
460
- runner.registerInfo("Adding one time cost of $#{neat_numbers(lcc_baseline_demo.totalCost, 0)} related to demolition of baseline objects.")
466
+ runner.registerInfo("Adding one time cost of $#{neat_numbers(lcc_baseline_demo.totalCost,
467
+ 0)} related to demolition of baseline objects.")
461
468
 
462
469
  # if demo occurs on year 0 then add to initial capital cost counter
463
- if lcc_baseline_demo.yearsFromStart == 0
464
- yr0_capital_totalCosts += lcc_baseline_demo.totalCost
465
- end
470
+ yr0_capital_totalCosts += lcc_baseline_demo.totalCost if lcc_baseline_demo.yearsFromStart == 0
466
471
  end
467
472
 
468
473
  # report final condition
@@ -472,12 +477,18 @@ class ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
472
477
  # method should always return double but this is work around for when it is nan because of 0 floor area
473
478
  if building.floorArea > 0.0
474
479
  final_building_LPD = unit_helper(final_building.lightingPowerPerFloorArea, 'W/m^2', 'W/ft^2')
475
- runner.registerFinalCondition("The model's final final lighting power was #{neat_numbers(final_building_lighting_power, 0)} watts, a lighting power density of #{neat_numbers(final_building_LPD)} w/ft^2. Initial capital costs associated with the improvements are $#{neat_numbers(yr0_capital_totalCosts, 0)}.")
480
+ runner.registerFinalCondition("The model's final final lighting power was #{neat_numbers(
481
+ final_building_lighting_power, 0
482
+ )} watts, a lighting power density of #{neat_numbers(final_building_LPD)} w/ft^2. Initial capital costs associated with the improvements are $#{neat_numbers(
483
+ yr0_capital_totalCosts, 0
484
+ )}.")
476
485
  else
477
- runner.registerFinalCondition("The model's final final lighting power was #{neat_numbers(final_building_lighting_power, 0)} wattsBuilding Area is not greater than 0 so an LPD can't be calculated.")
486
+ runner.registerFinalCondition("The model's final final lighting power was #{neat_numbers(
487
+ final_building_lighting_power, 0
488
+ )} wattsBuilding Area is not greater than 0 so an LPD can't be calculated.")
478
489
  end
479
490
 
480
- return true
491
+ true
481
492
  end
482
493
  end
483
494
 
@@ -3,8 +3,8 @@
3
3
  <schema_version>3.1</schema_version>
4
4
  <name>reduce_lighting_loads_by_percentage</name>
5
5
  <uid>791f3404-a28b-4a80-ba3f-e15b339e39ea</uid>
6
- <version_id>47db4b69-1273-4e27-9e86-2643ad0d2bcc</version_id>
7
- <version_modified>2025-08-08T15:15:58Z</version_modified>
6
+ <version_id>0d447c49-6da8-40a0-ae1e-e40aa7d5844e</version_id>
7
+ <version_modified>2025-09-25T15:33:44Z</version_modified>
8
8
  <xml_checksum>293730A7</xml_checksum>
9
9
  <class_name>ReduceLightingLoadsByPercentage</class_name>
10
10
  <display_name>Reduce Lighting Loads by Percentage</display_name>
@@ -17,10 +17,10 @@
17
17
  <type>Choice</type>
18
18
  <required>true</required>
19
19
  <model_dependent>false</model_dependent>
20
- <default_value>{2950f03c-960d-47bd-aa9a-d6ee473b6395}</default_value>
20
+ <default_value>{99f185ba-0bd9-48d1-b66a-1cd70b749c8d}</default_value>
21
21
  <choices>
22
22
  <choice>
23
- <value>{2950f03c-960d-47bd-aa9a-d6ee473b6395}</value>
23
+ <value>{99f185ba-0bd9-48d1-b66a-1cd70b749c8d}</value>
24
24
  <display_name>*Entire Building*</display_name>
25
25
  </choice>
26
26
  </choices>
@@ -162,7 +162,7 @@
162
162
  <filename>measure.rb</filename>
163
163
  <filetype>rb</filetype>
164
164
  <usage_type>script</usage_type>
165
- <checksum>85F7B1BC</checksum>
165
+ <checksum>82DE91FC</checksum>
166
166
  </file>
167
167
  <file>
168
168
  <filename>EC_QAQC.osm</filename>
@@ -186,7 +186,7 @@
186
186
  <filename>ReduceLightingLoadsByPercentage_Test.rb</filename>
187
187
  <filetype>rb</filetype>
188
188
  <usage_type>test</usage_type>
189
- <checksum>9FA79011</checksum>
189
+ <checksum>8EE6A0F2</checksum>
190
190
  </file>
191
191
  </files>
192
192
  </measure>
@@ -9,7 +9,7 @@
9
9
  class ReduceNightTimeElectricEquipmentLoads < OpenStudio::Measure::ModelMeasure
10
10
  # define the name that a user will see
11
11
  def name
12
- return 'Reduce Night Time Electric Equipment Loads'
12
+ 'Reduce Night Time Electric Equipment Loads'
13
13
  end
14
14
 
15
15
  # define the arguments that the user will input
@@ -29,14 +29,15 @@ class ReduceNightTimeElectricEquipmentLoads < OpenStudio::Measure::ModelMeasure
29
29
 
30
30
  # looping through sorted hash of load defs
31
31
  elec_load_def_args_hash.sort.map do |key, value|
32
- if !value.instances.empty?
32
+ unless value.instances.empty?
33
33
  elec_load_def_handles << value.handle.to_s
34
34
  elec_load_def_display_names << key
35
35
  end
36
36
  end
37
37
 
38
38
  # make an argument for electric equipment definition
39
- elec_load_def = OpenStudio::Measure::OSArgument.makeChoiceArgument('elec_load_def', elec_load_def_handles, elec_load_def_display_names)
39
+ elec_load_def = OpenStudio::Measure::OSArgument.makeChoiceArgument('elec_load_def', elec_load_def_handles,
40
+ elec_load_def_display_names)
40
41
  elec_load_def.setDisplayName('Pick an Electric Equipment Definition(schedules using this will be altered)')
41
42
  args << elec_load_def
42
43
 
@@ -130,7 +131,7 @@ class ReduceNightTimeElectricEquipmentLoads < OpenStudio::Measure::ModelMeasure
130
131
  om_frequency.setDefaultValue(1)
131
132
  args << om_frequency
132
133
 
133
- return args
134
+ args
134
135
  end
135
136
 
136
137
  # define what happens when the measure is run
@@ -138,9 +139,7 @@ class ReduceNightTimeElectricEquipmentLoads < OpenStudio::Measure::ModelMeasure
138
139
  super(model, runner, user_arguments)
139
140
 
140
141
  # use the built-in error checking
141
- if !runner.validateUserArguments(arguments(model), user_arguments)
142
- return false
143
- end
142
+ return false unless runner.validateUserArguments(arguments(model), user_arguments)
144
143
 
145
144
  # assign the user inputs to variables
146
145
  elec_load_def = runner.getOptionalWorkspaceObjectChoiceValue('elec_load_def', user_arguments, model)
@@ -169,13 +168,11 @@ class ReduceNightTimeElectricEquipmentLoads < OpenStudio::Measure::ModelMeasure
169
168
  runner.registerError("An Electric Equipment Definition with handle '#{elec_load_def}' was not found in the model. It may have been removed by another measure.")
170
169
  end
171
170
  return false
171
+ elsif !elec_load_def.get.to_ElectricEquipmentDefinition.empty?
172
+ elec_load_def = elec_load_def.get.to_ElectricEquipmentDefinition.get
172
173
  else
173
- if !elec_load_def.get.to_ElectricEquipmentDefinition.empty?
174
- elec_load_def = elec_load_def.get.to_ElectricEquipmentDefinition.get
175
- else
176
- runner.registerError('Script Error - argument not showing up as electric equipment definition.')
177
- return false
178
- end
174
+ runner.registerError('Script Error - argument not showing up as electric equipment definition.')
175
+ return false
179
176
  end
180
177
 
181
178
  # check the fraction for reasonableness
@@ -294,17 +291,15 @@ class ReduceNightTimeElectricEquipmentLoads < OpenStudio::Measure::ModelMeasure
294
291
  if (expected_life < 1) && (expected_life > 100)
295
292
  runner.registerError('Choose an integer greater than 0 and less than or equal to 100 for Expected Life.')
296
293
  end
297
- if om_frequency < 1
298
- runner.registerError('Choose an integer greater than 0 for O & M Frequency.')
299
- end
294
+ runner.registerError('Choose an integer greater than 0 for O & M Frequency.') if om_frequency < 1
300
295
 
301
296
  # short def to make numbers pretty (converts 4125001.25641 to 4,125,001.26 or 4,125,001). The definition be called through this measure
302
297
  def neat_numbers(number, roundto = 2) # round to 0 or 2)
303
- if roundto == 2
304
- number = format '%.2f', number
305
- else
306
- number = number.round
307
- end
298
+ number = if roundto == 2
299
+ format '%.2f', number
300
+ else
301
+ number.round
302
+ end
308
303
  # regex to add commas
309
304
  number.to_s.reverse.gsub(/([0-9]{3}(?=([0-9])))/, '\\1,').reverse
310
305
  end
@@ -328,12 +323,13 @@ class ReduceNightTimeElectricEquipmentLoads < OpenStudio::Measure::ModelMeasure
328
323
  # get schedules for equipment instances that user the picked
329
324
  equipment_instances.each do |equip|
330
325
  next unless equip.electricEquipmentDefinition == elec_load_def
326
+
331
327
  equipment_instances_using_def << equip
332
- if !equip.schedule.empty?
333
- equip_sch = equip.schedule.get
334
- equip_schs[equip_sch.name.to_s] = equip_sch
335
- equip_sch_names << equip_sch.name.to_s
336
- end
328
+ next if equip.schedule.empty?
329
+
330
+ equip_sch = equip.schedule.get
331
+ equip_schs[equip_sch.name.to_s] = equip_sch
332
+ equip_sch_names << equip_sch.name.to_s
337
333
  end
338
334
 
339
335
  # reporting initial condition of model
@@ -343,7 +339,9 @@ class ReduceNightTimeElectricEquipmentLoads < OpenStudio::Measure::ModelMeasure
343
339
  # and reducing schedule fraction before and after the specified times
344
340
  equip_sch_names.uniq.each do |equip_sch_name|
345
341
  equip_sch = equip_schs[equip_sch_name]
346
- if !equip_sch.to_ScheduleRuleset.empty?
342
+ if equip_sch.to_ScheduleRuleset.empty?
343
+ runner.registerWarning("Schedule '#{equip_sch_name}' isn't a ScheduleRuleset object and won't be altered by this measure.")
344
+ else
347
345
  new_equip_sch = equip_sch.clone(model).to_ScheduleRuleset.get
348
346
  new_equip_sch.setName("#{equip_sch_name} NightLoadControl")
349
347
  reduced_equip_schs[equip_sch_name] = new_equip_sch
@@ -392,14 +390,16 @@ class ReduceNightTimeElectricEquipmentLoads < OpenStudio::Measure::ModelMeasure
392
390
  if new_equip_sch.scheduleRules.empty?
393
391
  runner.registerWarning("Schedule '#{new_equip_sch.name}' applies to all days. It has been treated as a Weekday schedule.")
394
392
  end
395
- reduce_schedule(new_equip_sch.defaultDaySchedule, wk_before_hour, wk_before_min, wk_before_value, wk_after_hour, wk_after_min, wk_after_value)
393
+ reduce_schedule(new_equip_sch.defaultDaySchedule, wk_before_hour, wk_before_min, wk_before_value,
394
+ wk_after_hour, wk_after_min, wk_after_value)
396
395
 
397
396
  # reduce weekdays
398
397
  new_equip_sch.scheduleRules.each do |sch_rule|
399
- if apply_weekday
400
- if sch_rule.applyMonday || sch_rule.applyTuesday || sch_rule.applyWednesday || sch_rule.applyThursday || sch_rule.applyFriday
401
- reduce_schedule(sch_rule.daySchedule, wk_before_hour, wk_before_min, wk_before_value, wk_after_hour, wk_after_min, wk_after_value)
402
- end
398
+ next unless apply_weekday
399
+
400
+ if sch_rule.applyMonday || sch_rule.applyTuesday || sch_rule.applyWednesday || sch_rule.applyThursday || sch_rule.applyFriday
401
+ reduce_schedule(sch_rule.daySchedule, wk_before_hour, wk_before_min, wk_before_value, wk_after_hour,
402
+ wk_after_min, wk_after_value)
403
403
  end
404
404
  end
405
405
 
@@ -409,7 +409,8 @@ class ReduceNightTimeElectricEquipmentLoads < OpenStudio::Measure::ModelMeasure
409
409
  if sch_rule.applyMonday || sch_rule.applyTuesday || sch_rule.applyWednesday || sch_rule.applyThursday || sch_rule.applyFriday
410
410
  runner.registerWarning("Rule '#{sch_rule.name}' for schedule '#{new_equip_sch.name}' applies to both Saturdays and Weekdays. It has been treated as a Weekday schedule.")
411
411
  else
412
- reduce_schedule(sch_rule.daySchedule, sat_before_hour, sat_before_min, sat_before_value, sat_after_hour, sat_after_min, sat_after_value)
412
+ reduce_schedule(sch_rule.daySchedule, sat_before_hour, sat_before_min, sat_before_value, sat_after_hour,
413
+ sat_after_min, sat_after_value)
413
414
  end
414
415
  end
415
416
  end
@@ -422,12 +423,11 @@ class ReduceNightTimeElectricEquipmentLoads < OpenStudio::Measure::ModelMeasure
422
423
  elsif sch_rule.applySaturday
423
424
  runner.registerWarning("Rule '#{sch_rule.name}' for schedule '#{new_equip_sch.name}' applies to both Saturdays and Sundays. It has been treated as a Saturday schedule.")
424
425
  else
425
- reduce_schedule(sch_rule.daySchedule, sun_before_hour, sun_before_min, sun_before_value, sun_after_hour, sun_after_min, sun_after_value)
426
+ reduce_schedule(sch_rule.daySchedule, sun_before_hour, sun_before_min, sun_before_value, sun_after_hour,
427
+ sun_after_min, sun_after_value)
426
428
  end
427
429
  end
428
430
  end
429
- else
430
- runner.registerWarning("Schedule '#{equip_sch_name}' isn't a ScheduleRuleset object and won't be altered by this measure.")
431
431
  end
432
432
  end
433
433
 
@@ -445,9 +445,7 @@ class ReduceNightTimeElectricEquipmentLoads < OpenStudio::Measure::ModelMeasure
445
445
  end
446
446
 
447
447
  # na if no schedules to change
448
- if equip_sch_names.uniq.empty?
449
- runner.registerNotAsApplicable('There are no schedules to change.')
450
- end
448
+ runner.registerNotAsApplicable('There are no schedules to change.') if equip_sch_names.uniq.empty?
451
449
 
452
450
  measure_cost = 0
453
451
 
@@ -456,15 +454,19 @@ class ReduceNightTimeElectricEquipmentLoads < OpenStudio::Measure::ModelMeasure
456
454
  if costs_requested == true
457
455
  quantity = elec_load_def.quantity
458
456
  # adding new cost items
459
- lcc_mat = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_Mat - #{elec_load_def.name} night reduction", building, material_cost * quantity, 'CostPerEach', 'Construction', expected_life, years_until_costs_start)
460
- lcc_om = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_OM - #{elec_load_def.name} night reduction", building, om_cost * quantity, 'CostPerEach', 'Maintenance', om_frequency, 0)
457
+ lcc_mat = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_Mat - #{elec_load_def.name} night reduction",
458
+ building, material_cost * quantity, 'CostPerEach', 'Construction', expected_life, years_until_costs_start)
459
+ lcc_om = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_OM - #{elec_load_def.name} night reduction",
460
+ building, om_cost * quantity, 'CostPerEach', 'Maintenance', om_frequency, 0)
461
461
  measure_cost = material_cost * quantity
462
462
  end
463
463
 
464
464
  # reporting final condition of model
465
- runner.registerFinalCondition("#{equip_sch_names.uniq.size} schedule(s) were edited. The cost for the measure is #{neat_numbers(measure_cost, 0)}.")
465
+ runner.registerFinalCondition("#{equip_sch_names.uniq.size} schedule(s) were edited. The cost for the measure is #{neat_numbers(
466
+ measure_cost, 0
467
+ )}.")
466
468
 
467
- return true
469
+ true
468
470
  end
469
471
  end
470
472
 
@@ -3,8 +3,8 @@
3
3
  <schema_version>3.1</schema_version>
4
4
  <name>reduce_night_time_electric_equipment_loads</name>
5
5
  <uid>7bde0d05-3714-43e2-91b4-aa1e12e714bf</uid>
6
- <version_id>fca5a911-5563-426e-8e19-da99ec1b7af1</version_id>
7
- <version_modified>2025-08-08T15:15:56Z</version_modified>
6
+ <version_id>ee1c5616-0abd-4c5e-9eb4-e539216911df</version_id>
7
+ <version_modified>2025-09-25T15:33:42Z</version_modified>
8
8
  <xml_checksum>F4EB279D</xml_checksum>
9
9
  <class_name>ReduceNightTimeElectricEquipmentLoads</class_name>
10
10
  <display_name>Reduce Night Time Electric Equipment Loads</display_name>
@@ -224,7 +224,7 @@
224
224
  <filename>measure.rb</filename>
225
225
  <filetype>rb</filetype>
226
226
  <usage_type>script</usage_type>
227
- <checksum>D3353B2E</checksum>
227
+ <checksum>E2A2BF6E</checksum>
228
228
  </file>
229
229
  <file>
230
230
  <filename>EnvelopeAndLoadTestModel_01.osm</filename>
@@ -236,7 +236,7 @@
236
236
  <filename>ReduceNightTimeElectricEquipmentLoads_Test.rb</filename>
237
237
  <filetype>rb</filetype>
238
238
  <usage_type>test</usage_type>
239
- <checksum>D5DE99F9</checksum>
239
+ <checksum>12B0B531</checksum>
240
240
  </file>
241
241
  </files>
242
242
  </measure>