openstudio-geb 0.2.1 → 0.3.1r

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -2
  3. data/CHANGELOG.md +3 -0
  4. data/Gemfile +6 -1
  5. data/doc_templates/LICENSE.md +7 -21
  6. data/doc_templates/copyright_erb.txt +2 -32
  7. data/doc_templates/copyright_js.txt +2 -2
  8. data/doc_templates/copyright_ruby.txt +3 -33
  9. data/lib/measures/Add Output Variable/LICENSE.md +7 -21
  10. data/lib/measures/Add Output Variable/measure.rb +3 -33
  11. data/lib/measures/Add Output Variable/measure.xml +128 -125
  12. data/lib/measures/Add Output Variable/tests/AddOutputVariable_Test.rb +2 -32
  13. data/lib/measures/AddElectricVehicleChargingLoad/LICENSE.md +13 -1
  14. data/lib/measures/AddElectricVehicleChargingLoad/measure.rb +16 -52
  15. data/lib/measures/AddElectricVehicleChargingLoad/measure.xml +24 -23
  16. data/lib/measures/AddElectricVehicleChargingLoad/tests/add_electric_vehicle_charging_load_test.rb +2 -32
  17. data/lib/measures/AdjustThermostatSetpointsByDegreesForPeakHours/LICENSE.md +7 -21
  18. data/lib/measures/AdjustThermostatSetpointsByDegreesForPeakHours/README.md +22 -16
  19. data/lib/measures/AdjustThermostatSetpointsByDegreesForPeakHours/measure.rb +14 -35
  20. data/lib/measures/AdjustThermostatSetpointsByDegreesForPeakHours/measure.xml +41 -30
  21. data/lib/measures/AdjustThermostatSetpointsByDegreesForPeakHours/tests/AdjustThermostatSetpointsByDegreesForPeakHours_Test.rb +2 -32
  22. data/lib/measures/Enable Demand Controlled Ventilation/LICENSE.md +7 -21
  23. data/lib/measures/Enable Demand Controlled Ventilation/measure.rb +2 -32
  24. data/lib/measures/Enable Demand Controlled Ventilation/measure.xml +14 -13
  25. data/lib/measures/Enable Demand Controlled Ventilation/tests/EnableDemandControlledVentilation_Test.rb +2 -32
  26. data/lib/measures/GEB Metrics Report/LICENSE.md +13 -1
  27. data/lib/measures/GEB Metrics Report/measure.rb +2 -37
  28. data/lib/measures/GEB Metrics Report/measure.xml +238 -23
  29. data/lib/measures/GEB Metrics Report/resources/os_lib_helper_methods.rb +2 -32
  30. data/lib/measures/GEB Metrics Report/resources/os_lib_reporting.rb +2 -32
  31. data/lib/measures/GEB Metrics Report/tests/geb_metrics_report_test.rb +2 -32
  32. data/lib/measures/add_ceiling_fan/LICENSE.md +13 -0
  33. data/lib/measures/add_ceiling_fan/README.md +119 -0
  34. data/lib/measures/add_ceiling_fan/README.md.erb +45 -0
  35. data/lib/measures/add_ceiling_fan/docs/.gitkeep +0 -0
  36. data/lib/measures/add_ceiling_fan/measure.rb +565 -0
  37. data/lib/measures/add_ceiling_fan/measure.xml +226 -0
  38. data/lib/measures/add_ceiling_fan/tests/CZ06RV2.epw +8768 -0
  39. data/lib/measures/add_ceiling_fan/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A.osm +13669 -0
  40. data/lib/measures/add_ceiling_fan/tests/SFD_1story_UB_UA_ASHP2_HPWH.osm +13110 -0
  41. data/lib/measures/add_ceiling_fan/tests/add_ceiling_fan_test.rb +82 -0
  42. data/lib/measures/add_chilled_water_storage_tank/LICENSE.md +13 -1
  43. data/lib/measures/add_chilled_water_storage_tank/measure.rb +56 -56
  44. data/lib/measures/add_chilled_water_storage_tank/measure.xml +201 -28
  45. data/lib/measures/add_chilled_water_storage_tank/tests/add_chilled_water_storage_tank_test.rb +4 -34
  46. data/lib/measures/add_chilled_water_storage_tank/tests/example_model.osm +8077 -21624
  47. data/lib/measures/add_electrochromic_window/LICENSE.md +13 -1
  48. data/lib/measures/add_electrochromic_window/measure.rb +2 -32
  49. data/lib/measures/add_electrochromic_window/measure.xml +28 -27
  50. data/lib/measures/add_electrochromic_window/tests/add_electrochromic_window_test.rb +2 -32
  51. data/lib/measures/add_exterior_blinds_and_control/LICENSE.md +13 -1
  52. data/lib/measures/add_exterior_blinds_and_control/measure.rb +2 -34
  53. data/lib/measures/add_exterior_blinds_and_control/measure.xml +15 -26
  54. data/lib/measures/add_exterior_blinds_and_control/tests/add_exterior_blinds_and_control_test.rb +2 -34
  55. data/lib/measures/add_heat_pump_water_heater/LICENSE.md +7 -21
  56. data/lib/measures/add_heat_pump_water_heater/measure.rb +2 -32
  57. data/lib/measures/add_heat_pump_water_heater/measure.xml +89 -17
  58. data/lib/measures/add_heat_pump_water_heater/tests/add_hpwh_test.rb +2 -32
  59. data/lib/measures/add_interior_blinds_and_control/LICENSE.md +13 -1
  60. data/lib/measures/add_interior_blinds_and_control/measure.rb +2 -32
  61. data/lib/measures/add_interior_blinds_and_control/measure.xml +21 -33
  62. data/lib/measures/add_interior_blinds_and_control/tests/add_exterior_blinds_and_control_test.rb +2 -32
  63. data/lib/measures/add_natural_ventilation_with_hybrid_control/LICENSE.md +13 -0
  64. data/lib/measures/add_natural_ventilation_with_hybrid_control/README.md +133 -0
  65. data/lib/measures/add_natural_ventilation_with_hybrid_control/README.md.erb +45 -0
  66. data/lib/measures/add_natural_ventilation_with_hybrid_control/docs/.gitkeep +0 -0
  67. data/lib/measures/add_natural_ventilation_with_hybrid_control/measure.rb +453 -0
  68. data/lib/measures/add_natural_ventilation_with_hybrid_control/measure.xml +247 -0
  69. data/lib/measures/add_natural_ventilation_with_hybrid_control/tests/CZ06RV2.epw +8768 -0
  70. data/lib/measures/add_natural_ventilation_with_hybrid_control/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A.osm +13669 -0
  71. data/lib/measures/add_natural_ventilation_with_hybrid_control/tests/SmallHotel-2A.osm +42899 -0
  72. data/lib/measures/add_natural_ventilation_with_hybrid_control/tests/USA_NY_Buffalo.Niagara.Intl.AP.725280_TMY3.epw +8768 -0
  73. data/lib/measures/add_natural_ventilation_with_hybrid_control/tests/USA_TX_Houston-Bush.Intercontinental.AP.722430_TMY3.epw +8768 -0
  74. data/lib/measures/add_natural_ventilation_with_hybrid_control/tests/add_natural_ventilation_with_hybrid_control_test.rb +95 -0
  75. data/lib/measures/add_rooftop_pv_simple/LICENSE.md +7 -21
  76. data/lib/measures/add_rooftop_pv_simple/measure.rb +2 -32
  77. data/lib/measures/add_rooftop_pv_simple/measure.xml +11 -5
  78. data/lib/measures/add_rooftop_pv_simple/tests/add_rooftop_pv_test.rb +2 -32
  79. data/lib/measures/adjust_dhw_setpoint/LICENSE.md +13 -1
  80. data/lib/measures/adjust_dhw_setpoint/measure.rb +2 -32
  81. data/lib/measures/adjust_dhw_setpoint/measure.xml +34 -21
  82. data/lib/measures/adjust_dhw_setpoint/tests/adjust_dhw_setpoint_test.rb +2 -32
  83. data/lib/measures/average_ventilation_for_peak_hours/LICENSE.md +13 -1
  84. data/lib/measures/average_ventilation_for_peak_hours/README.md +5 -45
  85. data/lib/measures/average_ventilation_for_peak_hours/measure.rb +2 -32
  86. data/lib/measures/average_ventilation_for_peak_hours/measure.xml +24 -79
  87. data/lib/measures/average_ventilation_for_peak_hours/tests/average_ventilation_for_peak_hours_test.rb +2 -32
  88. data/lib/measures/enable_occupancy_driven_lighting/LICENSE.md +13 -1
  89. data/lib/measures/enable_occupancy_driven_lighting/measure.rb +2 -32
  90. data/lib/measures/enable_occupancy_driven_lighting/measure.xml +28 -27
  91. data/lib/measures/enable_occupancy_driven_lighting/tests/enable_occupancy_driven_lighting_test.rb +2 -32
  92. data/lib/measures/precooling/LICENSE.md +7 -21
  93. data/lib/measures/precooling/measure.rb +2 -33
  94. data/lib/measures/precooling/measure.xml +12 -11
  95. data/lib/measures/preheating/LICENSE.md +7 -21
  96. data/lib/measures/preheating/measure.rb +2 -33
  97. data/lib/measures/preheating/measure.xml +18 -17
  98. data/lib/measures/reduce_domestic_hot_water_use_for_peak_hours/LICENSE.md +13 -1
  99. data/lib/measures/reduce_domestic_hot_water_use_for_peak_hours/measure.rb +2 -32
  100. data/lib/measures/reduce_domestic_hot_water_use_for_peak_hours/measure.xml +34 -27
  101. data/lib/measures/reduce_domestic_hot_water_use_for_peak_hours/tests/reduce_domestic_hot_water_use_for_peak_hours_test.rb +2 -32
  102. data/lib/measures/reduce_epd_by_percentage_for_peak_hours/LICENSE.md +13 -1
  103. data/lib/measures/reduce_epd_by_percentage_for_peak_hours/README.md +3 -3
  104. data/lib/measures/reduce_epd_by_percentage_for_peak_hours/measure.rb +2 -32
  105. data/lib/measures/reduce_epd_by_percentage_for_peak_hours/measure.xml +25 -18
  106. data/lib/measures/reduce_epd_by_percentage_for_peak_hours/tests/reduce_epd_by_percentage_for_peak_hours_copy_test.rb +2 -32
  107. data/lib/measures/reduce_exterior_lighting_loads/LICENSE.md +13 -0
  108. data/lib/measures/reduce_exterior_lighting_loads/README.md +79 -0
  109. data/lib/measures/reduce_exterior_lighting_loads/README.md.erb +45 -0
  110. data/lib/measures/reduce_exterior_lighting_loads/docs/.gitkeep +0 -0
  111. data/lib/measures/reduce_exterior_lighting_loads/measure.rb +385 -0
  112. data/lib/measures/reduce_exterior_lighting_loads/measure.xml +195 -0
  113. data/lib/measures/reduce_exterior_lighting_loads/tests/CZ06RV2.epw +8768 -0
  114. data/lib/measures/reduce_exterior_lighting_loads/tests/SFD_1story_UB_UA_ASHP2_HPWH.osm +13110 -0
  115. data/lib/measures/reduce_exterior_lighting_loads/tests/example_model.osm +8077 -0
  116. data/lib/measures/reduce_exterior_lighting_loads/tests/reduce_exterior_lighting_loads_test.rb +81 -0
  117. data/lib/measures/reduce_lpd_by_percentage_for_peak_hours/LICENSE.md +13 -1
  118. data/lib/measures/reduce_lpd_by_percentage_for_peak_hours/measure.rb +2 -32
  119. data/lib/measures/reduce_lpd_by_percentage_for_peak_hours/measure.xml +30 -23
  120. data/lib/measures/reduce_lpd_by_percentage_for_peak_hours/tests/reduce_lpd_by_percentage_for_peak_hours_test.rb +2 -32
  121. data/lib/openstudio/geb/extension.rb +2 -32
  122. data/lib/openstudio/geb/logging.rb +2 -32
  123. data/lib/openstudio/geb/run.rb +2 -32
  124. data/lib/openstudio/geb/utilities.rb +2 -32
  125. data/lib/openstudio/geb/version.rb +3 -33
  126. data/lib/openstudio/geb.rb +2 -32
  127. data/lib/openstudio-geb.rb +5 -0
  128. data/openstudio-geb.gemspec +2 -3
  129. metadata +41 -8
@@ -0,0 +1,385 @@
1
+ # *******************************************************************************
2
+ # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
+ # See also https://openstudio.net/license
4
+ # *******************************************************************************
5
+
6
+ # see the URL below for information on how to write OpenStudio measures
7
+ # http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/
8
+
9
+ # start the measure
10
+ class ReduceExteriorLightingLoads < OpenStudio::Measure::ModelMeasure
11
+ # human readable name
12
+ def name
13
+ # Measure name should be the title case of the class name.
14
+ return 'Reduce Exterior Lighting Loads'
15
+ end
16
+
17
+ # human readable description
18
+ def description
19
+ return 'This measure reduces exterior lighting loads by two ways: (1) upgrading the lighting fixtures '\
20
+ 'to be more efficient, which reduces the design level value, (2) reducing operational duration'\
21
+ 'and/or strength by adjusting control option and schedule based on daylight, occupancy, and/or user designated period.'
22
+ end
23
+
24
+ # human readable description of modeling approach
25
+ def modeler_description
26
+ return 'This measure can (1) reduce design level by percentage if given by the user, (2) update the control option '\
27
+ 'to AstronomicalClock, (3) adjust the schedule by replacing with occupancy schedule of '\
28
+ 'the majority space/spacetype, and/or turn off or dim during user designated period.'
29
+ end
30
+
31
+ # define the arguments that the user will input
32
+ def arguments(model)
33
+ args = OpenStudio::Measure::OSArgumentVector.new
34
+
35
+ # design level value reduction percentage specified by user, default is 0
36
+ design_val_reduce_percent = OpenStudio::Measure::OSArgument.makeDoubleArgument('design_val_reduce_percent', false)
37
+ design_val_reduce_percent.setDisplayName('Percentage Reduction of Exterior Lighting Design Power (%)')
38
+ design_val_reduce_percent.setDescription('Enter a value between 0 and 100')
39
+ args << design_val_reduce_percent
40
+
41
+ # Use daylight control, i.e., AstronomicalClock as control option.
42
+ # This makes sure that the exterior lights are turned off during the day
43
+ use_daylight_control = OpenStudio::Measure::OSArgument.makeBoolArgument('use_daylight_control', true)
44
+ use_daylight_control.setDisplayName('Use daylight control')
45
+ use_daylight_control.setDescription('If exterior lights will be turned off during the day')
46
+ use_daylight_control.setDefaultValue(false)
47
+ args << use_daylight_control
48
+
49
+ # Use occupancy sensing. This will turn off exterior lights when unoccupied, and dim with partial occupancy
50
+ use_occupancy_sensing = OpenStudio::Measure::OSArgument.makeBoolArgument('use_occupancy_sensing', true)
51
+ use_occupancy_sensing.setDisplayName('Use occupancy sensing')
52
+ use_occupancy_sensing.setDescription('If enabled, this will turn off exterior lights when unoccupied, and dim with partial occupancy')
53
+ use_occupancy_sensing.setDefaultValue(false)
54
+ args << use_occupancy_sensing
55
+
56
+ # schedule on fraction during user designated period
57
+ on_frac_in_defined_period = OpenStudio::Measure::OSArgument.makeDoubleArgument('on_frac_in_defined_period', false)
58
+ on_frac_in_defined_period.setDisplayName('Schedule value representing light on fraction to turn off (0) or dim (<1) during user designated event period')
59
+ on_frac_in_defined_period.setDescription('Enter a value >=0 and <1')
60
+ args << on_frac_in_defined_period
61
+
62
+ # user designated period start time
63
+ user_defined_start_time = OpenStudio::Measure::OSArgument.makeStringArgument('user_defined_start_time', false)
64
+ user_defined_start_time.setDisplayName('User Designated Event Start Time for the off/dimming')
65
+ user_defined_start_time.setDescription('In HH:MM:SS format')
66
+ user_defined_start_time.setDefaultValue('01:00:00')
67
+ args << user_defined_start_time
68
+
69
+ # user designated period end time
70
+ user_defined_end_time = OpenStudio::Measure::OSArgument.makeStringArgument('user_defined_end_time', false)
71
+ user_defined_end_time.setDisplayName('User Designated Event End Time for the off/dimming')
72
+ user_defined_end_time.setDescription('In HH:MM:SS format')
73
+ user_defined_end_time.setDefaultValue('04:00:00')
74
+ args << user_defined_end_time
75
+
76
+ return args
77
+ end
78
+
79
+ # define what happens when the measure is run
80
+ def run(model, runner, user_arguments)
81
+ super(model, runner, user_arguments)
82
+
83
+ # if no exterior lights in the building, measure not applicable
84
+ if model.getExteriorLightss.size == 0
85
+ runner.registerAsNotApplicable("No exterior lights in the building, measure not applicable.")
86
+ return true
87
+ end
88
+
89
+ # use the built-in error checking
90
+ if !runner.validateUserArguments(arguments(model), user_arguments)
91
+ return false
92
+ end
93
+
94
+ # assign the user inputs to variables
95
+ design_val_reduce_percent = runner.getOptionalDoubleArgumentValue('design_val_reduce_percent', user_arguments)
96
+ use_daylight_control = runner.getBoolArgumentValue('use_daylight_control', user_arguments)
97
+ use_occupancy_sensing = runner.getBoolArgumentValue('use_occupancy_sensing', user_arguments)
98
+ on_frac_in_defined_period = runner.getOptionalDoubleArgumentValue('on_frac_in_defined_period', user_arguments)
99
+ user_defined_start_time = runner.getOptionalStringArgumentValue('user_defined_start_time', user_arguments)
100
+ user_defined_end_time = runner.getOptionalStringArgumentValue('user_defined_end_time', user_arguments)
101
+
102
+ # ****** validate parameters *******
103
+ # validate design_val_reduce_percent
104
+ if design_val_reduce_percent.empty?
105
+ design_val_reduce_percent = 0
106
+ elsif design_val_reduce_percent.to_f <= 0 || design_val_reduce_percent.to_f > 100
107
+ runner.registerError("Invalid Percentage Reduction of Exterior Lighting Design Power (%) #{design_val_reduce_percent} entered. Value must be >0 and <=100.")
108
+ return false
109
+ else
110
+ design_val_reduce_percent = design_val_reduce_percent.to_f
111
+ end
112
+
113
+ # validate on_frac_in_defined_period
114
+ if on_frac_in_defined_period.empty?
115
+ has_user_defined_event = false
116
+ elsif on_frac_in_defined_period.to_f < 0 || on_frac_in_defined_period.to_f >= 1
117
+ runner.registerError("Invalid schedule fraction value #{on_frac_in_defined_period} entered. Value must be >=0 and <1.")
118
+ return false
119
+ else
120
+ on_frac_in_defined_period = on_frac_in_defined_period.to_f
121
+ has_user_defined_event = true
122
+ end
123
+
124
+ # if has user defined event, validate the start and end time, otherwise skip
125
+ if has_user_defined_event
126
+ if user_defined_start_time.empty?
127
+ runner.registerError('User defined event lacks start time, please provide input.')
128
+ return false
129
+ end
130
+
131
+ if user_defined_end_time.empty?
132
+ runner.registerError('User defined event lacks end time, please provide input.')
133
+ return false
134
+ end
135
+
136
+ if /(\d\d):(\d\d):(\d\d)/.match(user_defined_start_time.to_s)
137
+ os_start_time = OpenStudio::Time.new(user_defined_start_time.to_s)
138
+ else
139
+ runner.registerError('Start time must be in HH-MM-SS format.')
140
+ return false
141
+ end
142
+
143
+ if /(\d\d):(\d\d):(\d\d)/.match(user_defined_end_time.to_s)
144
+ os_end_time = OpenStudio::Time.new(user_defined_end_time.to_s)
145
+ else
146
+ runner.registerError('End time must be in HH-MM-SS format.')
147
+ return false
148
+ end
149
+
150
+ if os_start_time == os_end_time
151
+ runner.registerError('Start and end time can not be the same.')
152
+ return false
153
+ end
154
+ end
155
+
156
+ # report initial condition of model
157
+ runner.registerInitialCondition("There are #{model.getExteriorLightss.size} exterior lights objects in the building.")
158
+
159
+ # reduce design level by percentage
160
+ if design_val_reduce_percent > 0
161
+ model.getExteriorLightsDefinitions.each do |ext_light_def|
162
+ origin_design_level = ext_light_def.designLevel
163
+ ext_light_def.setDesignLevel(origin_design_level * (100-design_val_reduce_percent)/100.0)
164
+ end
165
+ runner.registerInfo("Exterior light load is reduced by #{design_val_reduce_percent}%.")
166
+ end
167
+
168
+ # update control option to AstronomicalClock if true
169
+ if use_daylight_control
170
+ model.getExteriorLightss.each do |ext_light|
171
+ ext_light.setControlOption('AstronomicalClock')
172
+ end
173
+ runner.registerInfo("Exterior light is using daylight control.")
174
+ end
175
+
176
+ # occupancy sensing
177
+ major_occ_sch = nil #initial
178
+ if use_occupancy_sensing
179
+ # get the occupancy schedule of the majority space/spacetype
180
+ # first try building level schedule set
181
+ if (not model.building.empty?) && (not model.building.get.defaultScheduleSet.empty?)
182
+ occ_sch = model.building.get.defaultScheduleSet.get.numberofPeopleSchedule
183
+ unless occ_sch.empty?
184
+ major_occ_sch = occ_sch.get
185
+ end
186
+ else
187
+ # then try spacetype
188
+ spc_type_max_area = 0 # initial
189
+ major_spc_stype = nil # initial
190
+ model.getSpaceTypes.each do |spc_type|
191
+ if spc_type_max_area == 0
192
+ spc_type_max_area = spc_type.floorArea
193
+ major_spc_stype = spc_type
194
+ elsif spc_type_max_area < spc_type.floorArea
195
+ spc_type_max_area = spc_type.floorArea
196
+ major_spc_stype = spc_type
197
+ end
198
+ end
199
+ major_spc_type_default_sch_set = major_spc_stype.defaultScheduleSet
200
+ if not major_spc_type_default_sch_set.empty?
201
+ occ_sch = major_spc_type_default_sch_set.get.numberofPeopleSchedule
202
+ unless occ_sch.empty?
203
+ major_occ_sch = occ_sch.get
204
+ end
205
+ end
206
+
207
+ # if no major occupancy schedule found from space type, then try space
208
+ if major_occ_sch.nil?
209
+ spc_max_area = 0 #initial
210
+ major_spc = nil #initial
211
+ model.getSpaces.each do |spc|
212
+ if spc_max_area == 0
213
+ spc_max_area = spc.floorArea
214
+ major_spc = spc
215
+ elsif spc_max_area < spc.floorArea
216
+ spc_max_area = spc.floorArea
217
+ major_spc = spc
218
+ end
219
+ end
220
+ major_spc_default_sch_set = major_spc.defaultScheduleSet
221
+ if not major_spc_default_sch_set.empty?
222
+ occ_sch = major_spc_default_sch_set.get.numberofPeopleSchedule
223
+ unless occ_sch.empty?
224
+ major_occ_sch = occ_sch.get
225
+ end
226
+ else
227
+ if major_spc.people.size > 0
228
+ occ_sch = major_spc.people[0].numberofPeopleSchedule
229
+ unless occ_sch.empty?
230
+ major_occ_sch = occ_sch.get
231
+ else
232
+ runner.registerWarning("No schedule defined for the people object of the major space #{major_spc.name.to_s}.")
233
+ end
234
+ else
235
+ runner.registerWarning("No people object found for the major space #{major_spc.name.to_s}.")
236
+ end
237
+ end
238
+ end
239
+ end
240
+
241
+ # check if a major_occ_sch is found
242
+ if major_occ_sch.nil?
243
+ runner.registerError("Occupancy sensing control is enabled, but no major occupancy schedule can be found.")
244
+ return false
245
+ else
246
+ model.getExteriorLightss.each do |ext_light|
247
+ ext_light.setSchedule(major_occ_sch)
248
+ end
249
+ runner.registerInfo("Exterior light is using occupancy sensing control.")
250
+ end
251
+ end
252
+
253
+ def add_event_to_sch(model, runner, sch, on_frac_in_defined_period, start_time, end_time)
254
+ new_sch = sch.get.clone(model)
255
+ new_sch = new_sch.to_Schedule.get
256
+ new_sch.setName("#{sch.get.name.to_s} add user defined event")
257
+
258
+ # make cooling schedule adjustments and rename. Put in check to skip and warn if schedule not ruleset
259
+ if !new_sch.to_ScheduleRuleset.empty?
260
+ schedule = new_sch.to_ScheduleRuleset.get
261
+ default_rule = schedule.defaultDaySchedule
262
+ rules = schedule.scheduleRules
263
+
264
+ # update default day schedule
265
+ default_day_time_vector = default_rule.times
266
+ default_day_value_vector = default_rule.values
267
+ default_rule.clearValues
268
+ updateDaySchedule(default_rule, default_day_time_vector, default_day_value_vector, start_time, end_time, on_frac_in_defined_period)
269
+
270
+ # update all schedule rules
271
+ if rules.length > 0
272
+ rules.each do |rule|
273
+ day_sch = rule.daySchedule
274
+ day_time_vector = day_sch.times
275
+ day_value_vector = day_sch.values
276
+ day_sch.clearValues
277
+ updateDaySchedule(day_sch, day_time_vector, day_value_vector, start_time, end_time, on_frac_in_defined_period)
278
+ end
279
+ else
280
+ runner.registerWarning("Exterior light schedule '#{sch.get.name.to_s}' is a ScheduleRuleSet, but has no ScheduleRules associated. It won't be altered by this measure.")
281
+ end
282
+ else
283
+ runner.registerWarning("Schedule '#{sch.get.name.to_s}' isn't a ScheduleRuleset object and won't be altered by this measure.")
284
+ new_sch.remove # remove un-used clone
285
+ end
286
+
287
+ return new_sch
288
+ end
289
+
290
+ def updateDaySchedule(sch_day, vec_time, vec_value, time_begin, time_end, new_value)
291
+ count = 0
292
+ if time_end > time_begin
293
+ vec_time.each_with_index do |exist_timestamp, i|
294
+ if exist_timestamp > time_begin && exist_timestamp < time_end && count == 0
295
+ sch_day.addValue(time_begin, vec_value[i])
296
+ sch_day.addValue(exist_timestamp, new_value)
297
+ count = 1
298
+ elsif exist_timestamp == time_end && count == 0
299
+ sch_day.addValue(time_begin, vec_value[i])
300
+ sch_day.addValue(exist_timestamp, new_value)
301
+ count = 2
302
+ elsif exist_timestamp == time_begin && count == 0
303
+ sch_day.addValue(exist_timestamp, vec_value[i])
304
+ count = 1
305
+ elsif exist_timestamp > time_end && count == 0
306
+ sch_day.addValue(time_begin, vec_value[i])
307
+ sch_day.addValue(time_end, new_value)
308
+ sch_day.addValue(exist_timestamp, vec_value[i])
309
+ count = 2
310
+ elsif exist_timestamp > time_begin && exist_timestamp < time_end && count==1
311
+ sch_day.addValue(exist_timestamp, new_value)
312
+ elsif exist_timestamp == time_end && count==1
313
+ sch_day.addValue(exist_timestamp, new_value)
314
+ count = 2
315
+ elsif exist_timestamp > time_end && count == 1
316
+ sch_day.addValue(time_end, new_value)
317
+ sch_day.addValue(exist_timestamp, vec_value[i])
318
+ count = 2
319
+ else
320
+ sch_day.addValue(exist_timestamp, vec_value[i])
321
+ end
322
+ end
323
+ else
324
+ # time_end < time_begin, event goes overnight
325
+ vec_time.each_with_index do |exist_timestamp, i|
326
+ if exist_timestamp < time_end
327
+ sch_day.addValue(exist_timestamp, new_value)
328
+ elsif exist_timestamp == time_end && count == 0
329
+ sch_day.addValue(exist_timestamp, new_value)
330
+ count = 1 # 1 represents time_end has been filled
331
+ elsif exist_timestamp > time_end && exist_timestamp < time_begin && count == 0
332
+ sch_day.addValue(time_end, new_value)
333
+ sch_day.addValue(exist_timestamp, vec_value[i])
334
+ count = 1
335
+ elsif exist_timestamp > time_end && exist_timestamp < time_begin && count == 1
336
+ sch_day.addValue(exist_timestamp, vec_value[i])
337
+ elsif exist_timestamp == time_begin && count == 0
338
+ sch_day.addValue(time_end, new_value)
339
+ sch_day.addValue(exist_timestamp, vec_value[i])
340
+ count = 2
341
+ elsif exist_timestamp == time_begin && count == 1
342
+ sch_day.addValue(exist_timestamp, vec_value[i])
343
+ count = 2 # 2 represents time_begin has been filled
344
+ elsif exist_timestamp > time_begin && count == 0
345
+ sch_day.addValue(time_end, new_value)
346
+ sch_day.addValue(time_begin, vec_value[i])
347
+ sch_day.addValue(exist_timestamp, new_value)
348
+ count = 2
349
+ elsif exist_timestamp > time_begin && count == 1
350
+ sch_day.addValue(time_begin, vec_value[i])
351
+ sch_day.addValue(exist_timestamp, new_value)
352
+ count = 2
353
+ elsif exist_timestamp > time_begin && count == 2
354
+ sch_day.addValue(exist_timestamp, new_value)
355
+ end
356
+ end
357
+ end
358
+
359
+ return sch_day
360
+ end
361
+
362
+ # user defined schedule update
363
+ # refer to add ceiling fan change thermostat setpoint
364
+ if has_user_defined_event
365
+ model.getExteriorLightss.each do |ext_light|
366
+ if ext_light.schedule.empty?
367
+ runner.registerError("Has user defined event, but lack existing schedule for exterior light #{ext_light.name.to_s}.")
368
+ return false
369
+ else
370
+ new_sch = add_event_to_sch(model, runner, ext_light.schedule, on_frac_in_defined_period, os_start_time, os_end_time)
371
+ ext_light.setSchedule(new_sch)
372
+ end
373
+ end
374
+ runner.registerInfo("Exterior light schedule is modified by adding user defined event.")
375
+ end
376
+
377
+ # report final condition of model
378
+ runner.registerFinalCondition("The exterior lighting load is reduced.")
379
+
380
+ return true
381
+ end
382
+ end
383
+
384
+ # register the measure to be used by the application
385
+ ReduceExteriorLightingLoads.new.registerWithApplication
@@ -0,0 +1,195 @@
1
+ <?xml version="1.0"?>
2
+ <measure>
3
+ <schema_version>3.0</schema_version>
4
+ <name>reduce_exterior_lighting_loads</name>
5
+ <uid>6d0fe16a-eab4-4dcc-9eb3-ad38536edf2f</uid>
6
+ <version_id>90618158-68a3-41a7-9f09-6e0d27194218</version_id>
7
+ <version_modified>20230718T215422Z</version_modified>
8
+ <xml_checksum>99A5D8AD</xml_checksum>
9
+ <class_name>ReduceExteriorLightingLoads</class_name>
10
+ <display_name>Reduce Exterior Lighting Loads</display_name>
11
+ <description>This measure reduces exterior lighting loads by two ways: (1) upgrading the lighting fixtures to be more efficient, which reduces the design level value, (2) reducing operational durationand/or strength by adjusting control option and schedule based on daylight, occupancy, and/or user designated period.</description>
12
+ <modeler_description>This measure can (1) reduce design level by percentage if given by the user, (2) update the control option to AstronomicalClock, (3) adjust the schedule by replacing with occupancy schedule of the majority space/spacetype, and/or turn off or dim during user designated period.</modeler_description>
13
+ <arguments>
14
+ <argument>
15
+ <name>design_val_reduce_percent</name>
16
+ <display_name>Percentage Reduction of Exterior Lighting Design Power (%)</display_name>
17
+ <description>Enter a value between 0 and 100</description>
18
+ <type>Double</type>
19
+ <required>false</required>
20
+ <model_dependent>false</model_dependent>
21
+ </argument>
22
+ <argument>
23
+ <name>use_daylight_control</name>
24
+ <display_name>Use daylight control</display_name>
25
+ <description>If exterior lights will be turned off during the day</description>
26
+ <type>Boolean</type>
27
+ <required>true</required>
28
+ <model_dependent>false</model_dependent>
29
+ <default_value>false</default_value>
30
+ <choices>
31
+ <choice>
32
+ <value>true</value>
33
+ <display_name>true</display_name>
34
+ </choice>
35
+ <choice>
36
+ <value>false</value>
37
+ <display_name>false</display_name>
38
+ </choice>
39
+ </choices>
40
+ </argument>
41
+ <argument>
42
+ <name>use_occupancy_sensing</name>
43
+ <display_name>Use occupancy sensing</display_name>
44
+ <description>If enabled, this will turn off exterior lights when unoccupied, and dim with partial occupancy</description>
45
+ <type>Boolean</type>
46
+ <required>true</required>
47
+ <model_dependent>false</model_dependent>
48
+ <default_value>false</default_value>
49
+ <choices>
50
+ <choice>
51
+ <value>true</value>
52
+ <display_name>true</display_name>
53
+ </choice>
54
+ <choice>
55
+ <value>false</value>
56
+ <display_name>false</display_name>
57
+ </choice>
58
+ </choices>
59
+ </argument>
60
+ <argument>
61
+ <name>on_frac_in_defined_period</name>
62
+ <display_name>Schedule value representing light on fraction to turn off (0) or dim (&lt;1) during user designated event period</display_name>
63
+ <description>Enter a value &gt;=0 and &lt;1</description>
64
+ <type>Double</type>
65
+ <required>false</required>
66
+ <model_dependent>false</model_dependent>
67
+ </argument>
68
+ <argument>
69
+ <name>user_defined_start_time</name>
70
+ <display_name>User Designated Event Start Time for the off/dimming</display_name>
71
+ <description>In HH:MM:SS format</description>
72
+ <type>String</type>
73
+ <required>false</required>
74
+ <model_dependent>false</model_dependent>
75
+ <default_value>01:00:00</default_value>
76
+ </argument>
77
+ <argument>
78
+ <name>user_defined_end_time</name>
79
+ <display_name>User Designated Event End Time for the off/dimming</display_name>
80
+ <description>In HH:MM:SS format</description>
81
+ <type>String</type>
82
+ <required>false</required>
83
+ <model_dependent>false</model_dependent>
84
+ <default_value>04:00:00</default_value>
85
+ </argument>
86
+ </arguments>
87
+ <outputs />
88
+ <provenances />
89
+ <tags>
90
+ <tag>Electric Lighting.Electric Lighting Controls</tag>
91
+ </tags>
92
+ <attributes>
93
+ <attribute>
94
+ <name>Measure Type</name>
95
+ <value>ModelMeasure</value>
96
+ <datatype>string</datatype>
97
+ </attribute>
98
+ <attribute>
99
+ <name>Intended Software Tool</name>
100
+ <value>Apply Measure Now</value>
101
+ <datatype>string</datatype>
102
+ </attribute>
103
+ <attribute>
104
+ <name>Intended Software Tool</name>
105
+ <value>OpenStudio Application</value>
106
+ <datatype>string</datatype>
107
+ </attribute>
108
+ <attribute>
109
+ <name>Intended Software Tool</name>
110
+ <value>Parametric Analysis Tool</value>
111
+ <datatype>string</datatype>
112
+ </attribute>
113
+ <attribute>
114
+ <name>Intended Use Case</name>
115
+ <value>Model Articulation</value>
116
+ <datatype>string</datatype>
117
+ </attribute>
118
+ <attribute>
119
+ <name>Intended Use Case</name>
120
+ <value>Calibration</value>
121
+ <datatype>string</datatype>
122
+ </attribute>
123
+ <attribute>
124
+ <name>Intended Use Case</name>
125
+ <value>New Construction EE</value>
126
+ <datatype>string</datatype>
127
+ </attribute>
128
+ <attribute>
129
+ <name>Intended Use Case</name>
130
+ <value>Retrofit EE</value>
131
+ <datatype>string</datatype>
132
+ </attribute>
133
+ </attributes>
134
+ <files>
135
+ <file>
136
+ <filename>README.md.erb</filename>
137
+ <filetype>erb</filetype>
138
+ <usage_type>readmeerb</usage_type>
139
+ <checksum>F1C26127</checksum>
140
+ </file>
141
+ <file>
142
+ <filename>.gitkeep</filename>
143
+ <filetype>gitkeep</filetype>
144
+ <usage_type>doc</usage_type>
145
+ <checksum>00000000</checksum>
146
+ </file>
147
+ <file>
148
+ <filename>example_model.osm</filename>
149
+ <filetype>osm</filetype>
150
+ <usage_type>test</usage_type>
151
+ <checksum>53D14E69</checksum>
152
+ </file>
153
+ <file>
154
+ <filename>CZ06RV2.epw</filename>
155
+ <filetype>epw</filetype>
156
+ <usage_type>test</usage_type>
157
+ <checksum>52282D70</checksum>
158
+ </file>
159
+ <file>
160
+ <filename>SFD_1story_UB_UA_ASHP2_HPWH.osm</filename>
161
+ <filetype>osm</filetype>
162
+ <usage_type>test</usage_type>
163
+ <checksum>F0332415</checksum>
164
+ </file>
165
+ <file>
166
+ <filename>README.md</filename>
167
+ <filetype>md</filetype>
168
+ <usage_type>readme</usage_type>
169
+ <checksum>2D0ED49C</checksum>
170
+ </file>
171
+ <file>
172
+ <filename>LICENSE.md</filename>
173
+ <filetype>md</filetype>
174
+ <usage_type>license</usage_type>
175
+ <checksum>BFFB1AA6</checksum>
176
+ </file>
177
+ <file>
178
+ <version>
179
+ <software_program>OpenStudio</software_program>
180
+ <identifier>3.4.0</identifier>
181
+ <min_compatible>3.4.0</min_compatible>
182
+ </version>
183
+ <filename>measure.rb</filename>
184
+ <filetype>rb</filetype>
185
+ <usage_type>script</usage_type>
186
+ <checksum>041DAB62</checksum>
187
+ </file>
188
+ <file>
189
+ <filename>reduce_exterior_lighting_loads_test.rb</filename>
190
+ <filetype>rb</filetype>
191
+ <usage_type>test</usage_type>
192
+ <checksum>08AC2876</checksum>
193
+ </file>
194
+ </files>
195
+ </measure>