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
@@ -10,7 +10,7 @@ class ImproveFanBeltEfficiency < OpenStudio::Measure::ModelMeasure
10
10
  # define the name that a user will see, this method may be deprecated as
11
11
  # the display name in PAT comes from the name field in measure.xml
12
12
  def name
13
- return 'Improve Fan Belt Efficiency'
13
+ 'Improve Fan Belt Efficiency'
14
14
  end
15
15
 
16
16
  # define the arguments that the user will input
@@ -33,15 +33,9 @@ class ImproveFanBeltEfficiency < OpenStudio::Measure::ModelMeasure
33
33
  show_loop = false
34
34
  components = value.supplyComponents
35
35
  components.each do |component|
36
- if !component.to_FanConstantVolume.empty?
37
- show_loop = true
38
- end
39
- if !component.to_FanVariableVolume.empty?
40
- show_loop = true
41
- end
42
- if !component.to_FanOnOff.empty?
43
- show_loop = true
44
- end
36
+ show_loop = true unless component.to_FanConstantVolume.empty?
37
+ show_loop = true unless component.to_FanVariableVolume.empty?
38
+ show_loop = true unless component.to_FanOnOff.empty?
45
39
  end
46
40
 
47
41
  # if loop as object of correct type then add to hash.
@@ -117,7 +111,7 @@ class ImproveFanBeltEfficiency < OpenStudio::Measure::ModelMeasure
117
111
  om_frequency.setDefaultValue(1)
118
112
  args << om_frequency
119
113
 
120
- return args
114
+ args
121
115
  end
122
116
 
123
117
  # define what happens when the measure is cop
@@ -125,9 +119,7 @@ class ImproveFanBeltEfficiency < OpenStudio::Measure::ModelMeasure
125
119
  super(model, runner, user_arguments)
126
120
 
127
121
  # use the built-in error checking
128
- if !runner.validateUserArguments(arguments(model), user_arguments)
129
- return false
130
- end
122
+ return false unless runner.validateUserArguments(arguments(model), user_arguments)
131
123
 
132
124
  # assign the user inputs to variables
133
125
  object = runner.getOptionalWorkspaceObjectChoiceValue('object', user_arguments, model) # model is passed in because of argument type
@@ -152,15 +144,13 @@ class ImproveFanBeltEfficiency < OpenStudio::Measure::ModelMeasure
152
144
  runner.registerError("The selected loop with handle '#{handle}' was not found in the model. It may have been removed by another measure.")
153
145
  end
154
146
  return false
147
+ elsif !object.get.to_Loop.empty?
148
+ loop = object.get.to_Loop.get
149
+ elsif !object.get.to_Building.empty?
150
+ apply_to_all_loops = true
155
151
  else
156
- if !object.get.to_Loop.empty?
157
- loop = object.get.to_Loop.get
158
- elsif !object.get.to_Building.empty?
159
- apply_to_all_loops = true
160
- else
161
- runner.registerError('Script Error - argument not showing up as loop.')
162
- return false
163
- end
152
+ runner.registerError('Script Error - argument not showing up as loop.')
153
+ return false
164
154
  end
165
155
 
166
156
  # check the user_name for reasonableness
@@ -193,17 +183,15 @@ class ImproveFanBeltEfficiency < OpenStudio::Measure::ModelMeasure
193
183
  if (expected_life < 1) && (expected_life > 100)
194
184
  runner.registerError('Choose an integer greater than 0 and less than or equal to 100 for Expected Life.')
195
185
  end
196
- if om_frequency < 1
197
- runner.registerError('Choose an integer greater than 0 for O & M Frequency.')
198
- end
186
+ runner.registerError('Choose an integer greater than 0 for O & M Frequency.') if om_frequency < 1
199
187
 
200
188
  # 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
201
189
  def neat_numbers(number, roundto = 2) # round to 0 or 2)
202
- if roundto == 2
203
- number = format '%.2f', number
204
- else
205
- number = number.round
206
- end
190
+ number = if roundto == 2
191
+ format '%.2f', number
192
+ else
193
+ number.round
194
+ end
207
195
  # regex to add commas
208
196
  number.to_s.reverse.gsub(/([0-9]{3}(?=([0-9])))/, '\\1,').reverse
209
197
  end
@@ -214,14 +202,12 @@ class ImproveFanBeltEfficiency < OpenStudio::Measure::ModelMeasure
214
202
  objects.each do |object|
215
203
  object_LCCs = object.lifeCycleCosts
216
204
  object_LCCs.each do |object_LCC|
217
- if (object_LCC.category == 'Construction') || (object_LCC.category == 'Salvage')
218
- if object_LCC.yearsFromStart == 0
219
- counter += object_LCC.totalCost
220
- end
221
- end
205
+ next unless (object_LCC.category == 'Construction') || (object_LCC.category == 'Salvage')
206
+
207
+ counter += object_LCC.totalCost if object_LCC.yearsFromStart == 0
222
208
  end
223
209
  end
224
- return counter
210
+ counter
225
211
  end
226
212
 
227
213
  # get loops for measure
@@ -243,67 +229,61 @@ class ImproveFanBeltEfficiency < OpenStudio::Measure::ModelMeasure
243
229
  # find fans on loop
244
230
  supply_components.each do |supply_component|
245
231
  hVACComponent = supply_component.to_FanConstantVolume
246
- if hVACComponent.empty?
247
- hVACComponent = supply_component.to_FanVariableVolume
248
- end
249
- if hVACComponent.empty?
250
- hVACComponent = supply_component.to_FanOnOff
251
- end
232
+ hVACComponent = supply_component.to_FanVariableVolume if hVACComponent.empty?
233
+ hVACComponent = supply_component.to_FanOnOff if hVACComponent.empty?
252
234
 
253
235
  # alter components of correct type
254
- if !hVACComponent.empty?
255
- hVACComponent = hVACComponent.get
256
-
257
- # change and report changes to fans and motors
258
- initial_motor_efficiency = hVACComponent.motorEfficiency
259
- target_motor_efficiency = initial_motor_efficiency + motor_eff * 0.01
260
- initial_motor_efficiency_values << initial_motor_efficiency
261
- if target_motor_efficiency > 1
262
- hVACComponent.setMotorEfficiency(1.0)
263
- runner.registerWarning("Requested efficiency of #{target_motor_efficiency * 100}% for #{hVACComponent.name} is not possible. Setting motor efficiency to 100%.")
264
- elsif target_motor_efficiency < 0
265
- hVACComponent.setMotorEfficiency(0.0)
266
- runner.registerWarning("Requested efficiency of #{target_motor_efficiency * 100}% for #{hVACComponent.name} is not possible. Setting motor efficiency to 0%.")
267
- else
268
- hVACComponent.setMotorEfficiency(target_motor_efficiency)
269
- runner.registerInfo("Changing the motor efficiency from #{initial_motor_efficiency * 100}% to #{target_motor_efficiency * 100}% for '#{hVACComponent.name}' onloop '#{loop.name}.'")
270
- if target_motor_efficiency > 0.96
271
- runner.registerWarning("Requested efficiency for #{hVACComponent.name} is greater than 96%.")
272
- end
273
- end
274
-
275
- # get initial year 0 cost
276
- yr0_capital_totalCosts_baseline += get_total_costs_for_objects([hVACComponent])
277
-
278
- # demo value of baseline costs associated with unit
279
- demo_LCCs = hVACComponent.lifeCycleCosts
280
- demo_LCCs.each do |demo_LCC|
281
- if demo_LCC.category == 'Salvage'
282
- demo_costs_of_baseline_objects += demo_LCC.totalCost
283
- end
236
+ next if hVACComponent.empty?
237
+
238
+ hVACComponent = hVACComponent.get
239
+
240
+ # change and report changes to fans and motors
241
+ initial_motor_efficiency = hVACComponent.motorEfficiency
242
+ target_motor_efficiency = initial_motor_efficiency + (motor_eff * 0.01)
243
+ initial_motor_efficiency_values << initial_motor_efficiency
244
+ if target_motor_efficiency > 1
245
+ hVACComponent.setMotorEfficiency(1.0)
246
+ runner.registerWarning("Requested efficiency of #{target_motor_efficiency * 100}% for #{hVACComponent.name} is not possible. Setting motor efficiency to 100%.")
247
+ elsif target_motor_efficiency < 0
248
+ hVACComponent.setMotorEfficiency(0.0)
249
+ runner.registerWarning("Requested efficiency of #{target_motor_efficiency * 100}% for #{hVACComponent.name} is not possible. Setting motor efficiency to 0%.")
250
+ else
251
+ hVACComponent.setMotorEfficiency(target_motor_efficiency)
252
+ runner.registerInfo("Changing the motor efficiency from #{initial_motor_efficiency * 100}% to #{target_motor_efficiency * 100}% for '#{hVACComponent.name}' onloop '#{loop.name}.'")
253
+ if target_motor_efficiency > 0.96
254
+ runner.registerWarning("Requested efficiency for #{hVACComponent.name} is greater than 96%.")
284
255
  end
256
+ end
285
257
 
286
- # remove all old costs
287
- if !hVACComponent.lifeCycleCosts.empty? && (remove_costs == true)
288
- runner.registerInfo("Removing existing lifecycle cost objects associated with #{hVACComponent.name}")
289
- removed_costs = hVACComponent.removeLifeCycleCosts
290
- end
258
+ # get initial year 0 cost
259
+ yr0_capital_totalCosts_baseline += get_total_costs_for_objects([hVACComponent])
291
260
 
292
- # add new costs
293
- if costs_requested == true
261
+ # demo value of baseline costs associated with unit
262
+ demo_LCCs = hVACComponent.lifeCycleCosts
263
+ demo_LCCs.each do |demo_LCC|
264
+ demo_costs_of_baseline_objects += demo_LCC.totalCost if demo_LCC.category == 'Salvage'
265
+ end
294
266
 
295
- # adding new cost items
296
- lcc_mat = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_Mat - #{hVACComponent.name}", hVACComponent, material_cost, 'CostPerEach', 'Construction', expected_life, years_until_costs_start)
297
- # cost for if demo_initial_Construction == true is added at the end of the measure
298
- lcc_demo = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_Demo - #{hVACComponent.name}", hVACComponent, demolition_cost, 'CostPerEach', 'Salvage', expected_life, years_until_costs_start + expected_life)
299
- lcc_om = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_OM - #{hVACComponent.name}", hVACComponent, om_cost, 'CostPerEach', 'Maintenance', om_frequency, 0)
267
+ # remove all old costs
268
+ if !hVACComponent.lifeCycleCosts.empty? && (remove_costs == true)
269
+ runner.registerInfo("Removing existing lifecycle cost objects associated with #{hVACComponent.name}")
270
+ removed_costs = hVACComponent.removeLifeCycleCosts
271
+ end
300
272
 
301
- # get final year 0 cost
302
- yr0_capital_totalCosts_proposed += get_total_costs_for_objects([hVACComponent])
273
+ # add new costs
274
+ next unless costs_requested == true
303
275
 
304
- end
276
+ # adding new cost items
277
+ lcc_mat = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_Mat - #{hVACComponent.name}",
278
+ hVACComponent, material_cost, 'CostPerEach', 'Construction', expected_life, years_until_costs_start)
279
+ # cost for if demo_initial_Construction == true is added at the end of the measure
280
+ lcc_demo = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_Demo - #{hVACComponent.name}",
281
+ hVACComponent, demolition_cost, 'CostPerEach', 'Salvage', expected_life, years_until_costs_start + expected_life)
282
+ lcc_om = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_OM - #{hVACComponent.name}",
283
+ hVACComponent, om_cost, 'CostPerEach', 'Maintenance', om_frequency, 0)
305
284
 
306
- end
285
+ # get final year 0 cost
286
+ yr0_capital_totalCosts_proposed += get_total_costs_for_objects([hVACComponent])
307
287
  end
308
288
  end
309
289
 
@@ -311,12 +291,11 @@ class ImproveFanBeltEfficiency < OpenStudio::Measure::ModelMeasure
311
291
  if demo_cost_initial_const == true
312
292
  building = model.getBuilding
313
293
  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.
314
- runner.registerInfo("Adding one time cost of $#{neat_numbers(lcc_baseline_demo.totalCost, 0)} related to demolition of baseline objects.")
294
+ runner.registerInfo("Adding one time cost of $#{neat_numbers(lcc_baseline_demo.totalCost,
295
+ 0)} related to demolition of baseline objects.")
315
296
 
316
297
  # if demo occurs on year 0 then add to initial capital cost counter
317
- if lcc_baseline_demo.yearsFromStart == 0
318
- yr0_capital_totalCosts_proposed += lcc_baseline_demo.totalCost
319
- end
298
+ yr0_capital_totalCosts_proposed += lcc_baseline_demo.totalCost if lcc_baseline_demo.yearsFromStart == 0
320
299
  end
321
300
 
322
301
  if initial_motor_efficiency_values.size + missing_initial_motor_efficiency == 0
@@ -325,12 +304,16 @@ class ImproveFanBeltEfficiency < OpenStudio::Measure::ModelMeasure
325
304
  end
326
305
 
327
306
  # reporting initial condition of model
328
- runner.registerInitialCondition("The starting motor efficiency values in affected loop(s) range from #{initial_motor_efficiency_values.min * 100}% to #{initial_motor_efficiency_values.max * 100}%. Initial year 0 capital costs for affected fans is $#{neat_numbers(yr0_capital_totalCosts_baseline, 0)}.")
307
+ runner.registerInitialCondition("The starting motor efficiency values in affected loop(s) range from #{initial_motor_efficiency_values.min * 100}% to #{initial_motor_efficiency_values.max * 100}%. Initial year 0 capital costs for affected fans is $#{neat_numbers(
308
+ yr0_capital_totalCosts_baseline, 0
309
+ )}.")
329
310
 
330
311
  # reporting final condition of model
331
- runner.registerFinalCondition("#{initial_motor_efficiency_values.size + missing_initial_motor_efficiency} fans had motor efficiency values set to altered. Final year 0 capital costs for affected fans is $#{neat_numbers(yr0_capital_totalCosts_proposed, 0)}.")
312
+ runner.registerFinalCondition("#{initial_motor_efficiency_values.size + missing_initial_motor_efficiency} fans had motor efficiency values set to altered. Final year 0 capital costs for affected fans is $#{neat_numbers(
313
+ yr0_capital_totalCosts_proposed, 0
314
+ )}.")
332
315
 
333
- return true
316
+ true
334
317
  end
335
318
  end
336
319
 
@@ -3,8 +3,8 @@
3
3
  <schema_version>3.1</schema_version>
4
4
  <name>improve_fan_belt_efficiency</name>
5
5
  <uid>ebeca0aa-a432-4283-a714-17116f7c8f8c</uid>
6
- <version_id>3648c506-be6e-42b1-acfb-6ad1d2c6e203</version_id>
7
- <version_modified>2025-08-08T15:15:58Z</version_modified>
6
+ <version_id>b8f329e9-87df-4d83-96b2-9358e169a121</version_id>
7
+ <version_modified>2025-09-25T15:33:44Z</version_modified>
8
8
  <xml_checksum>F78494F2</xml_checksum>
9
9
  <class_name>ImproveFanBeltEfficiency</class_name>
10
10
  <display_name>Improve Fan Belt Efficiency</display_name>
@@ -47,10 +47,10 @@ Well-adjusted belts run cooler, last longer, and operate at higher efficiency th
47
47
  <type>Choice</type>
48
48
  <required>true</required>
49
49
  <model_dependent>false</model_dependent>
50
- <default_value>{c0101731-e87e-4af9-8f1f-cc53448e4105}</default_value>
50
+ <default_value>{eb63161e-e882-4957-a540-b6e7bb7abfd4}</default_value>
51
51
  <choices>
52
52
  <choice>
53
- <value>{c0101731-e87e-4af9-8f1f-cc53448e4105}</value>
53
+ <value>{eb63161e-e882-4957-a540-b6e7bb7abfd4}</value>
54
54
  <display_name>*All Air Loops*</display_name>
55
55
  </choice>
56
56
  </choices>
@@ -193,7 +193,7 @@ Well-adjusted belts run cooler, last longer, and operate at higher efficiency th
193
193
  <filename>measure.rb</filename>
194
194
  <filetype>rb</filetype>
195
195
  <usage_type>script</usage_type>
196
- <checksum>DC853729</checksum>
196
+ <checksum>1691AE3F</checksum>
197
197
  </file>
198
198
  <file>
199
199
  <filename>0320_ModelWithHVAC_01.osm</filename>
@@ -205,7 +205,7 @@ Well-adjusted belts run cooler, last longer, and operate at higher efficiency th
205
205
  <filename>ImproveFanBeltEfficiency_Test.rb</filename>
206
206
  <filetype>rb</filetype>
207
207
  <usage_type>test</usage_type>
208
- <checksum>8E07B9DC</checksum>
208
+ <checksum>19994729</checksum>
209
209
  </file>
210
210
  </files>
211
211
  </measure>
@@ -10,7 +10,7 @@ class ImproveMotorEfficiency < OpenStudio::Measure::ModelMeasure
10
10
  # define the name that a user will see, this method may be deprecated as
11
11
  # the display name in PAT comes from the name field in measure.xml
12
12
  def name
13
- return 'Improve Motor Efficiency in Selected Fans and Pumps'
13
+ 'Improve Motor Efficiency in Selected Fans and Pumps'
14
14
  end
15
15
 
16
16
  # define the arguments that the user will input
@@ -33,21 +33,11 @@ class ImproveMotorEfficiency < OpenStudio::Measure::ModelMeasure
33
33
  show_loop = false
34
34
  components = value.supplyComponents
35
35
  components.each do |component|
36
- if !component.to_FanConstantVolume.empty?
37
- show_loop = true
38
- end
39
- if !component.to_FanVariableVolume.empty?
40
- show_loop = true
41
- end
42
- if !component.to_FanOnOff.empty?
43
- show_loop = true
44
- end
45
- if !component.to_PumpConstantSpeed.empty?
46
- show_loop = true
47
- end
48
- if !component.to_PumpVariableSpeed.empty?
49
- show_loop = true
50
- end
36
+ show_loop = true unless component.to_FanConstantVolume.empty?
37
+ show_loop = true unless component.to_FanVariableVolume.empty?
38
+ show_loop = true unless component.to_FanOnOff.empty?
39
+ show_loop = true unless component.to_PumpConstantSpeed.empty?
40
+ show_loop = true unless component.to_PumpVariableSpeed.empty?
51
41
  end
52
42
 
53
43
  # if loop as object of correct type then add to hash.
@@ -122,7 +112,7 @@ class ImproveMotorEfficiency < OpenStudio::Measure::ModelMeasure
122
112
  om_frequency.setDefaultValue(1)
123
113
  args << om_frequency
124
114
 
125
- return args
115
+ args
126
116
  end
127
117
 
128
118
  # define what happens when the measure is cop
@@ -130,9 +120,7 @@ class ImproveMotorEfficiency < OpenStudio::Measure::ModelMeasure
130
120
  super(model, runner, user_arguments)
131
121
 
132
122
  # use the built-in error checking
133
- if !runner.validateUserArguments(arguments(model), user_arguments)
134
- return false
135
- end
123
+ return false unless runner.validateUserArguments(arguments(model), user_arguments)
136
124
 
137
125
  # assign the user inputs to variables
138
126
  object = runner.getOptionalWorkspaceObjectChoiceValue('object', user_arguments, model) # model is passed in because of argument type
@@ -157,15 +145,13 @@ class ImproveMotorEfficiency < OpenStudio::Measure::ModelMeasure
157
145
  runner.registerError("The selected loop with handle '#{handle}' was not found in the model. It may have been removed by another measure.")
158
146
  end
159
147
  return false
148
+ elsif !object.get.to_Loop.empty?
149
+ loop = object.get.to_Loop.get
150
+ elsif !object.get.to_Building.empty?
151
+ apply_to_all_loops = true
160
152
  else
161
- if !object.get.to_Loop.empty?
162
- loop = object.get.to_Loop.get
163
- elsif !object.get.to_Building.empty?
164
- apply_to_all_loops = true
165
- else
166
- runner.registerError('Script Error - argument not showing up as loop.')
167
- return false
168
- end
153
+ runner.registerError('Script Error - argument not showing up as loop.')
154
+ return false
169
155
  end
170
156
 
171
157
  # check the user_name for reasonableness
@@ -198,17 +184,15 @@ class ImproveMotorEfficiency < OpenStudio::Measure::ModelMeasure
198
184
  if (expected_life < 1) && (expected_life > 100)
199
185
  runner.registerError('Choose an integer greater than 0 and less than or equal to 100 for Expected Life.')
200
186
  end
201
- if om_frequency < 1
202
- runner.registerError('Choose an integer greater than 0 for O & M Frequency.')
203
- end
187
+ runner.registerError('Choose an integer greater than 0 for O & M Frequency.') if om_frequency < 1
204
188
 
205
189
  # 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
206
190
  def neat_numbers(number, roundto = 2) # round to 0 or 2)
207
- if roundto == 2
208
- number = format '%.2f', number
209
- else
210
- number = number.round
211
- end
191
+ number = if roundto == 2
192
+ format '%.2f', number
193
+ else
194
+ number.round
195
+ end
212
196
  # regex to add commas
213
197
  number.to_s.reverse.gsub(/([0-9]{3}(?=([0-9])))/, '\\1,').reverse
214
198
  end
@@ -219,14 +203,12 @@ class ImproveMotorEfficiency < OpenStudio::Measure::ModelMeasure
219
203
  objects.each do |object|
220
204
  object_LCCs = object.lifeCycleCosts
221
205
  object_LCCs.each do |object_LCC|
222
- if (object_LCC.category == 'Construction') || (object_LCC.category == 'Salvage')
223
- if object_LCC.yearsFromStart == 0
224
- counter += object_LCC.totalCost
225
- end
226
- end
206
+ next unless (object_LCC.category == 'Construction') || (object_LCC.category == 'Salvage')
207
+
208
+ counter += object_LCC.totalCost if object_LCC.yearsFromStart == 0
227
209
  end
228
210
  end
229
- return counter
211
+ counter
230
212
  end
231
213
 
232
214
  # get loops for measure
@@ -248,61 +230,51 @@ class ImproveMotorEfficiency < OpenStudio::Measure::ModelMeasure
248
230
  # find fans and pumps on loop
249
231
  supply_components.each do |supply_component|
250
232
  hVACComponent = supply_component.to_FanConstantVolume
251
- if hVACComponent.empty?
252
- hVACComponent = supply_component.to_FanVariableVolume
253
- end
254
- if hVACComponent.empty?
255
- hVACComponent = supply_component.to_FanOnOff
256
- end
257
- if hVACComponent.empty?
258
- hVACComponent = supply_component.to_PumpConstantSpeed
259
- end
260
- if hVACComponent.empty?
261
- hVACComponent = supply_component.to_PumpVariableSpeed
262
- end
233
+ hVACComponent = supply_component.to_FanVariableVolume if hVACComponent.empty?
234
+ hVACComponent = supply_component.to_FanOnOff if hVACComponent.empty?
235
+ hVACComponent = supply_component.to_PumpConstantSpeed if hVACComponent.empty?
236
+ hVACComponent = supply_component.to_PumpVariableSpeed if hVACComponent.empty?
263
237
 
264
238
  # alter components of correct type
265
- if !hVACComponent.empty?
266
- hVACComponent = hVACComponent.get
267
-
268
- # change and report changes to fans and motors
269
- initial_motor_efficiency = hVACComponent.motorEfficiency
270
- runner.registerInfo("Changing the motor efficiency from #{initial_motor_efficiency * 100}% to #{motor_eff}% for '#{hVACComponent.name}' onloop '#{loop.name}.'")
271
- initial_motor_efficiency_values << initial_motor_efficiency
272
- hVACComponent.setMotorEfficiency(motor_eff * 0.01)
273
-
274
- # get initial year 0 cost
275
- yr0_capital_totalCosts_baseline += get_total_costs_for_objects([hVACComponent])
276
-
277
- # demo value of baseline costs associated with unit
278
- demo_LCCs = hVACComponent.lifeCycleCosts
279
- demo_LCCs.each do |demo_LCC|
280
- if demo_LCC.category == 'Salvage'
281
- demo_costs_of_baseline_objects += demo_LCC.totalCost
282
- end
283
- end
284
-
285
- # remove all old costs
286
- if !hVACComponent.lifeCycleCosts.empty? && (remove_costs == true)
287
- runner.registerInfo("Removing existing lifecycle cost objects associated with #{hVACComponent.name}")
288
- removed_costs = hVACComponent.removeLifeCycleCosts
289
- end
290
-
291
- # add new costs
292
- if costs_requested == true
293
-
294
- # adding new cost items
295
- lcc_mat = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_Mat - #{hVACComponent.name}", hVACComponent, material_cost, 'CostPerEach', 'Construction', expected_life, years_until_costs_start)
296
- # cost for if demo_initial_Construction == true is added at the end of the measure
297
- lcc_demo = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_Demo - #{hVACComponent.name}", hVACComponent, demolition_cost, 'CostPerEach', 'Salvage', expected_life, years_until_costs_start + expected_life)
298
- lcc_om = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_OM - #{hVACComponent.name}", hVACComponent, om_cost, 'CostPerEach', 'Maintenance', om_frequency, 0)
299
-
300
- # get final year 0 cost
301
- yr0_capital_totalCosts_proposed += get_total_costs_for_objects([hVACComponent])
302
-
303
- end
239
+ next if hVACComponent.empty?
240
+
241
+ hVACComponent = hVACComponent.get
242
+
243
+ # change and report changes to fans and motors
244
+ initial_motor_efficiency = hVACComponent.motorEfficiency
245
+ runner.registerInfo("Changing the motor efficiency from #{initial_motor_efficiency * 100}% to #{motor_eff}% for '#{hVACComponent.name}' onloop '#{loop.name}.'")
246
+ initial_motor_efficiency_values << initial_motor_efficiency
247
+ hVACComponent.setMotorEfficiency(motor_eff * 0.01)
248
+
249
+ # get initial year 0 cost
250
+ yr0_capital_totalCosts_baseline += get_total_costs_for_objects([hVACComponent])
304
251
 
252
+ # demo value of baseline costs associated with unit
253
+ demo_LCCs = hVACComponent.lifeCycleCosts
254
+ demo_LCCs.each do |demo_LCC|
255
+ demo_costs_of_baseline_objects += demo_LCC.totalCost if demo_LCC.category == 'Salvage'
305
256
  end
257
+
258
+ # remove all old costs
259
+ if !hVACComponent.lifeCycleCosts.empty? && (remove_costs == true)
260
+ runner.registerInfo("Removing existing lifecycle cost objects associated with #{hVACComponent.name}")
261
+ removed_costs = hVACComponent.removeLifeCycleCosts
262
+ end
263
+
264
+ # add new costs
265
+ next unless costs_requested == true
266
+
267
+ # adding new cost items
268
+ lcc_mat = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_Mat - #{hVACComponent.name}",
269
+ hVACComponent, material_cost, 'CostPerEach', 'Construction', expected_life, years_until_costs_start)
270
+ # cost for if demo_initial_Construction == true is added at the end of the measure
271
+ lcc_demo = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_Demo - #{hVACComponent.name}",
272
+ hVACComponent, demolition_cost, 'CostPerEach', 'Salvage', expected_life, years_until_costs_start + expected_life)
273
+ lcc_om = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_OM - #{hVACComponent.name}",
274
+ hVACComponent, om_cost, 'CostPerEach', 'Maintenance', om_frequency, 0)
275
+
276
+ # get final year 0 cost
277
+ yr0_capital_totalCosts_proposed += get_total_costs_for_objects([hVACComponent])
306
278
  end
307
279
  end
308
280
 
@@ -310,12 +282,11 @@ class ImproveMotorEfficiency < OpenStudio::Measure::ModelMeasure
310
282
  if demo_cost_initial_const == true
311
283
  building = model.getBuilding
312
284
  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.
313
- runner.registerInfo("Adding one time cost of $#{neat_numbers(lcc_baseline_demo.totalCost, 0)} related to demolition of baseline objects.")
285
+ runner.registerInfo("Adding one time cost of $#{neat_numbers(lcc_baseline_demo.totalCost,
286
+ 0)} related to demolition of baseline objects.")
314
287
 
315
288
  # if demo occurs on year 0 then add to initial capital cost counter
316
- if lcc_baseline_demo.yearsFromStart == 0
317
- yr0_capital_totalCosts_proposed += lcc_baseline_demo.totalCost
318
- end
289
+ yr0_capital_totalCosts_proposed += lcc_baseline_demo.totalCost if lcc_baseline_demo.yearsFromStart == 0
319
290
  end
320
291
 
321
292
  if initial_motor_efficiency_values.size + missing_initial_motor_efficiency == 0
@@ -324,12 +295,16 @@ class ImproveMotorEfficiency < OpenStudio::Measure::ModelMeasure
324
295
  end
325
296
 
326
297
  # reporting initial condition of model
327
- runner.registerInitialCondition("The starting motor efficiency values in affected loop(s) range from #{initial_motor_efficiency_values.min * 100}% to #{initial_motor_efficiency_values.max * 100}%. Initial year 0 capital costs for affected fans or pumps is $#{neat_numbers(yr0_capital_totalCosts_baseline, 0)}.")
298
+ runner.registerInitialCondition("The starting motor efficiency values in affected loop(s) range from #{initial_motor_efficiency_values.min * 100}% to #{initial_motor_efficiency_values.max * 100}%. Initial year 0 capital costs for affected fans or pumps is $#{neat_numbers(
299
+ yr0_capital_totalCosts_baseline, 0
300
+ )}.")
328
301
 
329
302
  # reporting final condition of model
330
- runner.registerFinalCondition("#{initial_motor_efficiency_values.size + missing_initial_motor_efficiency} fans or pumps had motor efficiency values set to #{motor_eff}%. Final year 0 capital costs for affected fans and pumps is $#{neat_numbers(yr0_capital_totalCosts_proposed, 0)}.")
303
+ runner.registerFinalCondition("#{initial_motor_efficiency_values.size + missing_initial_motor_efficiency} fans or pumps had motor efficiency values set to #{motor_eff}%. Final year 0 capital costs for affected fans and pumps is $#{neat_numbers(
304
+ yr0_capital_totalCosts_proposed, 0
305
+ )}.")
331
306
 
332
- return true
307
+ true
333
308
  end
334
309
  end
335
310
 
@@ -3,8 +3,8 @@
3
3
  <schema_version>3.1</schema_version>
4
4
  <name>improve_motor_efficiency</name>
5
5
  <uid>52013ba9-7b9b-4ffd-bc67-d4c0fa05d7ae</uid>
6
- <version_id>f10a9555-aef0-4ca0-b1de-285d32d5561c</version_id>
7
- <version_modified>2025-08-08T15:15:57Z</version_modified>
6
+ <version_id>b489d3b7-146d-4ef3-95b3-02fbed79c46b</version_id>
7
+ <version_modified>2025-09-25T15:33:44Z</version_modified>
8
8
  <xml_checksum>F78494F2</xml_checksum>
9
9
  <class_name>ImproveMotorEfficiency</class_name>
10
10
  <display_name>Improve Motor Efficiency in Selected Fans and Pumps</display_name>
@@ -31,10 +31,10 @@ The cost arguments are user arguments that start with a default of $0. Operation
31
31
  <type>Choice</type>
32
32
  <required>true</required>
33
33
  <model_dependent>false</model_dependent>
34
- <default_value>{783d4a71-fb33-4da4-8fea-0f5801bac4eb}</default_value>
34
+ <default_value>{477f3286-308d-43c0-8e7f-483284eb60d1}</default_value>
35
35
  <choices>
36
36
  <choice>
37
- <value>{783d4a71-fb33-4da4-8fea-0f5801bac4eb}</value>
37
+ <value>{477f3286-308d-43c0-8e7f-483284eb60d1}</value>
38
38
  <display_name>*All Plant and Air Loops*</display_name>
39
39
  </choice>
40
40
  </choices>
@@ -177,7 +177,7 @@ The cost arguments are user arguments that start with a default of $0. Operation
177
177
  <filename>measure.rb</filename>
178
178
  <filetype>rb</filetype>
179
179
  <usage_type>script</usage_type>
180
- <checksum>CB567949</checksum>
180
+ <checksum>09B3E503</checksum>
181
181
  </file>
182
182
  <file>
183
183
  <filename>0320_ModelWithHVAC_01.osm</filename>
@@ -189,7 +189,7 @@ The cost arguments are user arguments that start with a default of $0. Operation
189
189
  <filename>ImproveMotorEfficiency_Test.rb</filename>
190
190
  <filetype>rb</filetype>
191
191
  <usage_type>test</usage_type>
192
- <checksum>087B8F20</checksum>
192
+ <checksum>E64A2125</checksum>
193
193
  </file>
194
194
  </files>
195
195
  </measure>