openstudio-geb 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/Rakefile +1 -1
- data/doc_templates/LICENSE.md +7 -21
- data/doc_templates/copyright_erb.txt +2 -32
- data/doc_templates/copyright_js.txt +2 -2
- data/doc_templates/copyright_ruby.txt +3 -33
- data/lib/measures/Add Output Variable/LICENSE.md +7 -21
- data/lib/measures/Add Output Variable/measure.rb +3 -33
- data/lib/measures/Add Output Variable/tests/AddOutputVariable_Test.rb +2 -32
- data/lib/measures/AddElectricVehicleChargingLoad/LICENSE.md +13 -1
- data/lib/measures/AddElectricVehicleChargingLoad/measure.rb +16 -52
- data/lib/measures/AddElectricVehicleChargingLoad/tests/add_electric_vehicle_charging_load_test.rb +2 -32
- data/lib/measures/AdjustThermostatSetpointsByDegreesForPeakHours/LICENSE.md +7 -21
- data/lib/measures/AdjustThermostatSetpointsByDegreesForPeakHours/measure.rb +14 -35
- data/lib/measures/AdjustThermostatSetpointsByDegreesForPeakHours/tests/AdjustThermostatSetpointsByDegreesForPeakHours_Test.rb +2 -32
- data/lib/measures/Enable Demand Controlled Ventilation/LICENSE.md +7 -21
- data/lib/measures/Enable Demand Controlled Ventilation/measure.rb +2 -32
- data/lib/measures/Enable Demand Controlled Ventilation/tests/EnableDemandControlledVentilation_Test.rb +2 -32
- data/lib/measures/GEB Metrics Report/LICENSE.md +13 -1
- data/lib/measures/GEB Metrics Report/measure.rb +4 -39
- data/lib/measures/GEB Metrics Report/resources/os_lib_helper_methods.rb +2 -32
- data/lib/measures/GEB Metrics Report/resources/os_lib_reporting.rb +2 -32
- data/lib/measures/GEB Metrics Report/tests/geb_metrics_report_test.rb +2 -32
- data/lib/measures/add_ceiling_fan/LICENSE.md +13 -0
- data/lib/measures/add_ceiling_fan/README.md +119 -0
- data/lib/measures/add_ceiling_fan/README.md.erb +45 -0
- data/lib/measures/add_ceiling_fan/docs/.gitkeep +0 -0
- data/lib/measures/add_ceiling_fan/measure.rb +565 -0
- data/lib/measures/add_ceiling_fan/measure.xml +226 -0
- data/lib/measures/add_ceiling_fan/tests/CZ06RV2.epw +8768 -0
- data/lib/measures/add_ceiling_fan/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A.osm +13669 -0
- data/lib/measures/add_ceiling_fan/tests/SFD_1story_UB_UA_ASHP2_HPWH.osm +13110 -0
- data/lib/measures/add_ceiling_fan/tests/add_ceiling_fan_test.rb +82 -0
- data/lib/measures/add_chilled_water_storage_tank/LICENSE.md +13 -1
- data/lib/measures/add_chilled_water_storage_tank/measure.rb +56 -56
- data/lib/measures/add_chilled_water_storage_tank/tests/add_chilled_water_storage_tank_test.rb +4 -34
- data/lib/measures/add_electrochromic_window/LICENSE.md +13 -1
- data/lib/measures/add_electrochromic_window/measure.rb +2 -32
- data/lib/measures/add_electrochromic_window/tests/add_electrochromic_window_test.rb +2 -32
- data/lib/measures/add_exterior_blinds_and_control/LICENSE.md +13 -1
- data/lib/measures/add_exterior_blinds_and_control/measure.rb +2 -34
- data/lib/measures/add_exterior_blinds_and_control/tests/add_exterior_blinds_and_control_test.rb +2 -34
- data/lib/measures/add_heat_pump_water_heater/LICENSE.md +7 -21
- data/lib/measures/add_heat_pump_water_heater/measure.rb +2 -32
- data/lib/measures/add_heat_pump_water_heater/tests/add_hpwh_test.rb +2 -32
- data/lib/measures/add_interior_blinds_and_control/LICENSE.md +13 -1
- data/lib/measures/add_interior_blinds_and_control/measure.rb +2 -32
- data/lib/measures/add_interior_blinds_and_control/tests/add_exterior_blinds_and_control_test.rb +2 -32
- data/lib/measures/add_natural_ventilation_with_hybrid_control/LICENSE.md +13 -0
- data/lib/measures/add_natural_ventilation_with_hybrid_control/README.md +133 -0
- data/lib/measures/add_natural_ventilation_with_hybrid_control/README.md.erb +45 -0
- data/lib/measures/add_natural_ventilation_with_hybrid_control/docs/.gitkeep +0 -0
- data/lib/measures/add_natural_ventilation_with_hybrid_control/measure.rb +453 -0
- data/lib/measures/add_natural_ventilation_with_hybrid_control/measure.xml +241 -0
- data/lib/measures/add_natural_ventilation_with_hybrid_control/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A.osm +13669 -0
- data/lib/measures/add_natural_ventilation_with_hybrid_control/tests/SmallHotel-2A.osm +42899 -0
- data/lib/measures/add_natural_ventilation_with_hybrid_control/tests/USA_NY_Buffalo.Niagara.Intl.AP.725280_TMY3.epw +8768 -0
- data/lib/measures/add_natural_ventilation_with_hybrid_control/tests/USA_TX_Houston-Bush.Intercontinental.AP.722430_TMY3.epw +8768 -0
- data/lib/measures/add_natural_ventilation_with_hybrid_control/tests/add_natural_ventilation_with_hybrid_control_test.rb +95 -0
- data/lib/measures/add_rooftop_pv_simple/LICENSE.md +7 -21
- data/lib/measures/add_rooftop_pv_simple/measure.rb +2 -32
- data/lib/measures/add_rooftop_pv_simple/tests/add_rooftop_pv_test.rb +2 -32
- data/lib/measures/adjust_dhw_setpoint/LICENSE.md +13 -1
- data/lib/measures/adjust_dhw_setpoint/measure.rb +2 -32
- data/lib/measures/adjust_dhw_setpoint/tests/adjust_dhw_setpoint_test.rb +2 -32
- data/lib/measures/average_ventilation_for_peak_hours/LICENSE.md +13 -1
- data/lib/measures/average_ventilation_for_peak_hours/measure.rb +2 -32
- data/lib/measures/average_ventilation_for_peak_hours/tests/average_ventilation_for_peak_hours_test.rb +2 -32
- data/lib/measures/enable_occupancy_driven_lighting/LICENSE.md +13 -1
- data/lib/measures/enable_occupancy_driven_lighting/measure.rb +2 -32
- data/lib/measures/enable_occupancy_driven_lighting/tests/enable_occupancy_driven_lighting_test.rb +2 -32
- data/lib/measures/precooling/LICENSE.md +7 -21
- data/lib/measures/precooling/measure.rb +2 -33
- data/lib/measures/preheating/LICENSE.md +7 -21
- data/lib/measures/preheating/measure.rb +2 -33
- data/lib/measures/reduce_domestic_hot_water_use_for_peak_hours/LICENSE.md +13 -1
- data/lib/measures/reduce_domestic_hot_water_use_for_peak_hours/measure.rb +2 -32
- data/lib/measures/reduce_domestic_hot_water_use_for_peak_hours/tests/reduce_domestic_hot_water_use_for_peak_hours_test.rb +2 -32
- data/lib/measures/reduce_epd_by_percentage_for_peak_hours/LICENSE.md +13 -1
- data/lib/measures/reduce_epd_by_percentage_for_peak_hours/measure.rb +2 -32
- data/lib/measures/reduce_epd_by_percentage_for_peak_hours/tests/reduce_epd_by_percentage_for_peak_hours_copy_test.rb +2 -32
- data/lib/measures/reduce_exterior_lighting_loads/LICENSE.md +13 -0
- data/lib/measures/reduce_exterior_lighting_loads/README.md +79 -0
- data/lib/measures/reduce_exterior_lighting_loads/README.md.erb +45 -0
- data/lib/measures/reduce_exterior_lighting_loads/docs/.gitkeep +0 -0
- data/lib/measures/reduce_exterior_lighting_loads/measure.rb +385 -0
- data/lib/measures/reduce_exterior_lighting_loads/measure.xml +195 -0
- data/lib/measures/reduce_exterior_lighting_loads/tests/CZ06RV2.epw +8768 -0
- data/lib/measures/reduce_exterior_lighting_loads/tests/SFD_1story_UB_UA_ASHP2_HPWH.osm +13110 -0
- data/lib/measures/reduce_exterior_lighting_loads/tests/example_model.osm +8077 -0
- data/lib/measures/reduce_exterior_lighting_loads/tests/reduce_exterior_lighting_loads_test.rb +81 -0
- data/lib/measures/reduce_lpd_by_percentage_for_peak_hours/LICENSE.md +13 -1
- data/lib/measures/reduce_lpd_by_percentage_for_peak_hours/measure.rb +2 -32
- data/lib/measures/reduce_lpd_by_percentage_for_peak_hours/tests/reduce_lpd_by_percentage_for_peak_hours_test.rb +2 -32
- data/lib/openstudio/geb/extension.rb +2 -50
- data/lib/openstudio/geb/logging.rb +2 -32
- data/lib/openstudio/geb/run.rb +2 -32
- data/lib/openstudio/geb/utilities.rb +2 -32
- data/lib/openstudio/geb/version.rb +3 -33
- data/lib/openstudio/geb.rb +3 -51
- data/lib/openstudio-geb.rb +6 -0
- data/openstudio-geb.gemspec +2 -3
- metadata +40 -7
@@ -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>9109f446-43d4-405a-a0b7-c6cd78b12356</version_id>
|
7
|
+
<version_modified>20230209T213337Z</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 (<1) during user designated event period</display_name>
|
63
|
+
<description>Enter a value >=0 and <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>LICENSE.md</filename>
|
137
|
+
<filetype>md</filetype>
|
138
|
+
<usage_type>license</usage_type>
|
139
|
+
<checksum>CD7F5672</checksum>
|
140
|
+
</file>
|
141
|
+
<file>
|
142
|
+
<filename>README.md.erb</filename>
|
143
|
+
<filetype>erb</filetype>
|
144
|
+
<usage_type>readmeerb</usage_type>
|
145
|
+
<checksum>F1C26127</checksum>
|
146
|
+
</file>
|
147
|
+
<file>
|
148
|
+
<filename>.gitkeep</filename>
|
149
|
+
<filetype>gitkeep</filetype>
|
150
|
+
<usage_type>doc</usage_type>
|
151
|
+
<checksum>00000000</checksum>
|
152
|
+
</file>
|
153
|
+
<file>
|
154
|
+
<filename>example_model.osm</filename>
|
155
|
+
<filetype>osm</filetype>
|
156
|
+
<usage_type>test</usage_type>
|
157
|
+
<checksum>53D14E69</checksum>
|
158
|
+
</file>
|
159
|
+
<file>
|
160
|
+
<version>
|
161
|
+
<software_program>OpenStudio</software_program>
|
162
|
+
<identifier>3.4.0</identifier>
|
163
|
+
<min_compatible>3.4.0</min_compatible>
|
164
|
+
</version>
|
165
|
+
<filename>measure.rb</filename>
|
166
|
+
<filetype>rb</filetype>
|
167
|
+
<usage_type>script</usage_type>
|
168
|
+
<checksum>C4C6ADF9</checksum>
|
169
|
+
</file>
|
170
|
+
<file>
|
171
|
+
<filename>reduce_exterior_lighting_loads_test.rb</filename>
|
172
|
+
<filetype>rb</filetype>
|
173
|
+
<usage_type>test</usage_type>
|
174
|
+
<checksum>E5B57905</checksum>
|
175
|
+
</file>
|
176
|
+
<file>
|
177
|
+
<filename>CZ06RV2.epw</filename>
|
178
|
+
<filetype>epw</filetype>
|
179
|
+
<usage_type>test</usage_type>
|
180
|
+
<checksum>52282D70</checksum>
|
181
|
+
</file>
|
182
|
+
<file>
|
183
|
+
<filename>SFD_1story_UB_UA_ASHP2_HPWH.osm</filename>
|
184
|
+
<filetype>osm</filetype>
|
185
|
+
<usage_type>test</usage_type>
|
186
|
+
<checksum>F0332415</checksum>
|
187
|
+
</file>
|
188
|
+
<file>
|
189
|
+
<filename>README.md</filename>
|
190
|
+
<filetype>md</filetype>
|
191
|
+
<usage_type>readme</usage_type>
|
192
|
+
<checksum>2D0ED49C</checksum>
|
193
|
+
</file>
|
194
|
+
</files>
|
195
|
+
</measure>
|