openstudio-standards 0.2.8 → 0.2.9
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.
- checksums.yaml +4 -4
- data/data/geometry/ASHRAEPrimarySchool.osm +36 -2
- data/data/geometry/ASHRAESecondarySchool.osm +19 -2
- data/data/standards/OpenStudio_Standards_elevators.json +10756 -0
- data/lib/openstudio-standards.rb +0 -2
- data/lib/openstudio-standards/hvac_sizing/Siz.HVACComponent.rb +36 -0
- data/lib/openstudio-standards/hvac_sizing/Siz.Model.rb +3 -0
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.elevators.rb +175 -164
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.swh.rb +268 -476
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.ServiceWaterHeating.rb +625 -116
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +4 -0
- data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +2 -19
- data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +112 -68
- data/lib/openstudio-standards/standards/Standards.WaterHeaterMixed.rb +10 -2
- data/lib/openstudio-standards/standards/necb/necb_2011/data/space_types.json +224 -224
- data/lib/openstudio-standards/standards/necb/necb_2011/service_water_heating.rb +8 -16
- data/lib/openstudio-standards/standards/necb/necb_2015/data/space_types.json +318 -318
- data/lib/openstudio-standards/standards/standard.rb +1 -0
- data/lib/openstudio-standards/version.rb +1 -1
- metadata +4 -4
- data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.hvac_systems.rb +0 -15
- data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.hvac_systems.rb +0 -15
data/lib/openstudio-standards.rb
CHANGED
@@ -286,13 +286,11 @@ module OpenstudioStandards
|
|
286
286
|
# DOE Ref 1980-2004
|
287
287
|
require_relative "#{proto}/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.AirTerminalSingleDuctVAVReheat"
|
288
288
|
require_relative "#{proto}/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.Model.elevators"
|
289
|
-
require_relative "#{proto}/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.hvac_systems"
|
290
289
|
require_relative "#{proto}/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.refrigeration"
|
291
290
|
# DOE Ref Pre-1980
|
292
291
|
require_relative "#{proto}/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.AirTerminalSingleDuctVAVReheat"
|
293
292
|
require_relative "#{proto}/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.CoilHeatingGas"
|
294
293
|
require_relative "#{proto}/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.Model.elevators"
|
295
|
-
require_relative "#{proto}/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.hvac_systems"
|
296
294
|
require_relative "#{proto}/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.refrigeration"
|
297
295
|
# NREL ZNE Ready 2017
|
298
296
|
require_relative "#{proto}/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.AirTerminalSingleDuctVAVReheat"
|
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
###### IMPORTANT NOTE ######
|
3
|
+
# These methods should be done via extension to OS model objects
|
4
|
+
# directly in the C++ SDK.
|
5
|
+
###### IMPORTANT NOTE ######
|
6
|
+
|
7
|
+
class OpenStudio::Model::HVACComponent
|
8
|
+
# Returns the number of individual pieces of equipment
|
9
|
+
# represented by a particular HVAC component. Pulls from
|
10
|
+
# the additionalProperties object attached to the component.
|
11
|
+
# This can be used during the application of efficiency
|
12
|
+
# levels that are based on component capacities, flowrates, etc.
|
13
|
+
# @return [Integer] the number of components, 1 if not set
|
14
|
+
def component_quantity
|
15
|
+
addl_props = self.additionalProperties
|
16
|
+
if addl_props.getFeatureAsInteger('component_quantity').is_initialized
|
17
|
+
comp_qty = addl_props.getFeatureAsInteger('component_quantity').get
|
18
|
+
else
|
19
|
+
comp_qty = 1
|
20
|
+
end
|
21
|
+
|
22
|
+
return comp_qty
|
23
|
+
end
|
24
|
+
|
25
|
+
# Sets the number of individual pieces of equipment
|
26
|
+
# represented by a particular HVAC component. Uses the
|
27
|
+
# additionalProperties object attached to the component.
|
28
|
+
# This can be used during the application of efficiency
|
29
|
+
# levels that are based on component capacities, flowrates, etc.
|
30
|
+
# @param comp_qty [Integer] the number of individual pieces of equipment
|
31
|
+
# represented by this HVAC component
|
32
|
+
# @return [Bool] true if successful, false if not
|
33
|
+
def set_component_quantity(comp_qty)
|
34
|
+
return self.additionalProperties.setFeature('component_quantity', comp_qty)
|
35
|
+
end
|
36
|
+
end
|
@@ -57,6 +57,9 @@ class OpenStudio::Model::Model
|
|
57
57
|
# Heating and cooling fuel methods
|
58
58
|
require_relative 'Siz.HeatingCoolingFuels'
|
59
59
|
|
60
|
+
# Component quantity methods
|
61
|
+
require_relative 'Siz.HVACComponent'
|
62
|
+
|
60
63
|
# Takes the values calculated by the EnergyPlus sizing routines
|
61
64
|
# and puts them into all objects model in place of the autosized fields.
|
62
65
|
# Must have previously completed a run with sql output for this to work.
|
@@ -107,11 +107,11 @@ class Standard
|
|
107
107
|
def model_elevator_lift_power(model, elevator_type, building_type)
|
108
108
|
lift_pwr_w = 0
|
109
109
|
if elevator_type == 'Traction'
|
110
|
-
lift_pwr_w
|
110
|
+
lift_pwr_w += 20_370.0
|
111
111
|
elsif elevator_type == 'Hydraulic'
|
112
|
-
lift_pwr_w
|
112
|
+
lift_pwr_w += 16_055.0
|
113
113
|
else
|
114
|
-
lift_pwr_w
|
114
|
+
lift_pwr_w += 16_055.0
|
115
115
|
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.model.Model', "Elevator type '#{elevator_type}', not recognized, will assume Hydraulic elevator, #{lift_pwr_w} W.")
|
116
116
|
end
|
117
117
|
|
@@ -130,7 +130,7 @@ class Standard
|
|
130
130
|
# Determines the power of the elevator ventilation fan.
|
131
131
|
# Defaults to 90.1-2010, which had no requirement
|
132
132
|
# for ventilation fan efficiency.
|
133
|
-
# @return [Double] the
|
133
|
+
# @return [Double] the ventilation fan power (W)
|
134
134
|
def model_elevator_fan_pwr(model, vent_rate_cfm)
|
135
135
|
vent_pwr_per_flow_w_per_cfm = 0.33
|
136
136
|
vent_pwr_w = vent_pwr_per_flow_w_per_cfm * vent_rate_cfm
|
@@ -149,13 +149,14 @@ class Standard
|
|
149
149
|
|
150
150
|
# determine elevator type
|
151
151
|
# todo - add logic here or upstream to have some multi-story buildings without elevators (e.g. small multi-family and small hotels)
|
152
|
-
elevator_type = nil
|
153
152
|
if effective_num_stories[:below_grade] + effective_num_stories[:above_grade] < 2
|
154
153
|
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', 'The building only has 1 story, no elevators will be added.')
|
155
154
|
return nil # don't add elevators
|
156
155
|
elsif effective_num_stories[:below_grade] + effective_num_stories[:above_grade] < 6
|
156
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', 'The building has fewer than 6 effective stories; assuming Hydraulic elevators.')
|
157
157
|
elevator_type = 'Hydraulic'
|
158
158
|
else
|
159
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', 'The building has 6 or more effective stories; assuming Traction elevators.')
|
159
160
|
elevator_type = 'Traction'
|
160
161
|
end
|
161
162
|
|
@@ -169,6 +170,8 @@ class Standard
|
|
169
170
|
end
|
170
171
|
target_space = bottom_spaces.key(bottom_spaces.values.max)
|
171
172
|
|
173
|
+
building_types = []
|
174
|
+
|
172
175
|
# determine number of elevators
|
173
176
|
number_of_pass_elevators = 0.0
|
174
177
|
number_of_freight_elevators = 0.0
|
@@ -184,98 +187,70 @@ class Standard
|
|
184
187
|
building_type_hash[hash[:stds_bldg_type]] = hash[:floor_area]
|
185
188
|
end
|
186
189
|
|
187
|
-
|
188
|
-
|
189
|
-
units_per_pass_elevator = nil
|
190
|
-
beds_per_pass_elevator = nil
|
191
|
-
area_per_freight_elev_ft2 = nil
|
192
|
-
units_per_freight_elevator = nil
|
193
|
-
beds_per_freight_elevator = nil
|
194
|
-
if ['Office', 'SmallOffice', 'MediumOffice', 'LargeOffice','SmallOfficeDetailed','MediumOfficeDetailed','LargeOfficeDetailed'].include?(hash[:stds_bldg_type])
|
195
|
-
# The office buildings have one elevator for every 45,000 ft2 (4,181 m2),
|
196
|
-
# plus one service elevator for the large office building (500,000 ft^2).
|
197
|
-
area_per_pass_elev_ft2 = 45_000
|
198
|
-
bldg_area_ft2 = OpenStudio.convert(model.getBuilding.floorArea, 'm^2', 'ft^2').get
|
199
|
-
if bldg_area_ft2 > 500_000
|
200
|
-
area_per_freight_elev_ft2 = 500_000
|
201
|
-
end
|
202
|
-
elsif ['SmallHotel', 'LargeHotel'].include?(hash[:stds_bldg_type])
|
203
|
-
# The hotels have one elevator for every 75 rooms.
|
204
|
-
if hash[:stds_space_type].include?('GuestRoom')
|
205
|
-
units_per_pass_elevator = 75.0
|
206
|
-
end
|
207
|
-
# The large hotel includes one service elevator for every two public elevators,
|
208
|
-
# plus one additional elevator for the dining and banquet facilities on the top floor.
|
209
|
-
# None of the other space types generate elevators.
|
210
|
-
if ['LargeHotel'].include?(hash[:stds_bldg_type]) && hash[:stds_space_type].include?('GuestRoom')
|
211
|
-
units_per_freight_elevator = 150.0
|
212
|
-
elsif ['LargeHotel'].include?(hash[:stds_bldg_type]) && ['Banquet', 'Cafe'].include?(hash[:stds_space_type])
|
213
|
-
area_per_pass_elev_ft2 = 10_000
|
214
|
-
end
|
215
|
-
elsif ['MidriseApartment', 'HighriseApartment'].include?(hash[:stds_bldg_type]) && hash[:stds_space_type].include?('Apartment')
|
216
|
-
# The apartment building has one elevator for every 90 units
|
217
|
-
units_per_pass_elevator = 90.0
|
218
|
-
elsif ['Hospital'].include?(hash[:stds_bldg_type])
|
219
|
-
# The hospital has one public and one service elevator for every 100 beds (250 total),
|
220
|
-
# plus two elevators for the offices and cafeteria on the top floor.
|
221
|
-
# None of the other space types generate elevators.
|
222
|
-
if ['PatRoom', 'ICU_PatRm', 'ICU_Open'].include?(hash[:stds_space_type])
|
223
|
-
beds_per_pass_elevator = 100.0
|
224
|
-
beds_per_freight_elevator = 100.0
|
225
|
-
elsif ['Dining', 'Kitchen', 'Office'].include?(hash[:stds_space_type])
|
226
|
-
area_per_pass_elev_ft2 = 12_500
|
227
|
-
end
|
228
|
-
elsif ['PrimarySchool', 'SecondarySchool'].include?(hash[:stds_bldg_type])
|
229
|
-
# 210,887 ft^2 secondary school prototype has 2 elevators
|
230
|
-
area_per_pass_elev_ft2 = 100_000
|
231
|
-
elsif ['Outpatient'].include?(hash[:stds_bldg_type])
|
232
|
-
# 40,946 Outpatient has 3 elevators
|
233
|
-
area_per_pass_elev_ft2 = 15_000
|
234
|
-
elsif ['Warehouse'].include?(hash[:stds_bldg_type])
|
235
|
-
# Warehouse has no elevators, but assume some would be needed
|
236
|
-
area_per_freight_elev_ft2 = 250_000
|
237
|
-
else
|
238
|
-
# TODO: - improve catchall for building types without elevator data, using same value as what Outpatient would be if not already in space type
|
239
|
-
# includes RetailStandalone, RetailStripmall, QuickServiceRestaurant, FullServiceRestaurant, SuperMarket (made unique logic above for warehouse)
|
240
|
-
area_per_pass_elev_ft2 = 15_000
|
241
|
-
end
|
190
|
+
building_type = hash[:stds_bldg_type]
|
191
|
+
building_types << building_type
|
242
192
|
|
243
|
-
#
|
244
|
-
|
245
|
-
pass_elevs = hash[:floor_area] / OpenStudio.convert(area_per_pass_elev_ft2, 'ft^2', 'm^2').get
|
246
|
-
number_of_pass_elevators += pass_elevs
|
247
|
-
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', "For #{space_type.name}, adding #{pass_elevs.round(1)} passenger elevators at 1 per #{area_per_pass_elev_ft2.round} ft^2.")
|
248
|
-
end
|
193
|
+
# store floor area ip
|
194
|
+
floor_area_ip = OpenStudio.convert(hash[:floor_area], 'm^2', 'ft^2').get
|
249
195
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
196
|
+
# load elevator_data
|
197
|
+
search_criteria = { 'building_type' => building_type }
|
198
|
+
elevator_data_lookup = model_find_object(standards_data['elevators'], search_criteria)
|
199
|
+
if elevator_data_lookup.nil?
|
200
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.prototype.elevators', "Could not find elevator data for #{building_type}.")
|
254
201
|
end
|
255
202
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', "For #{space_type.name}, adding #{pass_elevs.round(1)} passenger elevators at 1 per #{
|
203
|
+
# determine number of passenger elevators
|
204
|
+
if !elevator_data_lookup['area_per_passenger_elevator'].nil?
|
205
|
+
pass_elevs = floor_area_ip / elevator_data_lookup['area_per_passenger_elevator'].to_f
|
206
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', "For #{space_type.name}, adding #{pass_elevs.round(1)} passenger elevators at 1 per #{elevator_data_lookup['area_per_passenger_elevator']} ft^2.")
|
207
|
+
elsif !elevator_data_lookup['units_per_passenger_elevator'].nil?
|
208
|
+
pass_elevs = hash[:num_units] / elevator_data_lookup['units_per_passenger_elevator'].to_f
|
209
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', "For #{space_type.name}, adding #{pass_elevs.round(1)} passenger elevators at 1 per #{elevator_data_lookup['units_per_passenger_elevator']} units.")
|
210
|
+
elsif !elevator_data_lookup['beds_per_passenger_elevator'].nil?
|
211
|
+
pass_elevs = hash[:num_beds] / elevator_data_lookup['beds_per_passenger_elevator'].to_f
|
212
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', "For #{space_type.name}, adding #{pass_elevs.round(1)} passenger elevators at 1 per #{elevator_data_lookup['beds_per_passenger_elevator']} beds.")
|
213
|
+
else
|
214
|
+
pass_elevs = 0.0
|
215
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', "Unexpected key, can't calculate number of passenger elevators from #{elevator_data_lookup.keys.first}.")
|
260
216
|
end
|
261
217
|
|
262
|
-
#
|
263
|
-
if
|
264
|
-
freight_elevs =
|
265
|
-
|
266
|
-
|
218
|
+
# determine number of freight elevators
|
219
|
+
if !elevator_data_lookup['area_per_freight_elevator'].nil?
|
220
|
+
freight_elevs = floor_area_ip / elevator_data_lookup['area_per_freight_elevator'].to_f
|
221
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', "For #{space_type.name}, adding #{freight_elevs.round(1)} freight/service elevators at 1 per #{elevator_data_lookup['area_per_freight_elevator']} ft^2.")
|
222
|
+
elsif !elevator_data_lookup['units_per_freight_elevator'].nil?
|
223
|
+
freight_elevs = hash[:num_units] / elevator_data_lookup['units_per_freight_elevator'].to_f
|
224
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', "For #{space_type.name}, adding #{freight_elevs.round(1)} freight/service elevators at 1 per #{elevator_data_lookup['units_per_freight_elevator']} units.")
|
225
|
+
elsif !elevator_data_lookup['beds_per_freight_elevator'].nil?
|
226
|
+
freight_elevs = hash[:num_beds] / elevator_data_lookup['beds_per_freight_elevator'].to_f
|
227
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', "For #{space_type.name}, adding #{freight_elevs.round(1)} freight/service elevators at 1 per #{elevator_data_lookup['beds_per_freight_elevator']} beds.")
|
228
|
+
else
|
229
|
+
freight_elevs = 0.0
|
230
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', "Unexpected key, can't calculate number of freight elevators from #{elevator_data_lookup.keys.first}.")
|
267
231
|
end
|
232
|
+
number_of_pass_elevators += pass_elevs
|
233
|
+
number_of_freight_elevators += freight_elevs
|
234
|
+
end
|
268
235
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
236
|
+
# additional passenger elevators (applicable for DOE LargeHotel and DOE Hospital only)
|
237
|
+
add_pass_elevs = 0.0
|
238
|
+
building_types.uniq.each do |building_type|
|
239
|
+
# load elevator_data
|
240
|
+
search_criteria = { 'building_type' => building_type }
|
241
|
+
elevator_data_lookup = model_find_object(standards_data['elevators'], search_criteria)
|
242
|
+
if elevator_data_lookup.nil?
|
243
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.prototype.elevators', "Could not find elevator data for #{building_type}.")
|
244
|
+
return nil
|
273
245
|
end
|
274
246
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', "
|
247
|
+
# determine number of additional passenger elevators
|
248
|
+
if !elevator_data_lookup['additional_passenger_elevators'].nil?
|
249
|
+
add_pass_elevs += elevator_data_lookup['additional_passenger_elevators']
|
250
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', "Adding #{elevator_data_lookup['additional_passenger_elevators']} additional passenger elevators.")
|
251
|
+
else
|
252
|
+
add_pass_elevs += 0.0
|
253
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', 'No additional passenger elevators added to model.')
|
279
254
|
end
|
280
255
|
end
|
281
256
|
|
@@ -286,98 +261,134 @@ class Standard
|
|
286
261
|
if (number_of_freight_elevators > 0.0) && (number_of_freight_elevators < 1.0)
|
287
262
|
number_of_freight_elevators = 1.0
|
288
263
|
end
|
264
|
+
|
265
|
+
# determine total number of elevators (rounding up to nearest whole number)
|
266
|
+
number_of_pass_elevators = number_of_pass_elevators.ceil + add_pass_elevs
|
267
|
+
number_of_freight_elevators = number_of_freight_elevators.ceil
|
289
268
|
number_of_elevators = number_of_pass_elevators + number_of_freight_elevators
|
290
269
|
|
291
270
|
building_type = building_type_hash.key(building_type_hash.values.max)
|
292
|
-
# rename space types as needed
|
293
|
-
if building_type == 'Office'
|
294
|
-
building_type = model_remap_office(model, building_type_hash['Office'])
|
295
|
-
end
|
296
|
-
if building_type == 'SmallHotel' then building_type = 'LargeHotel' end # no elevator schedules for SmallHotel
|
297
|
-
if building_type == 'PrimarySchool' then building_type = 'SecondarySchool' end # no elevator schedules for PrimarySchool
|
298
|
-
if building_type == 'Retail' then building_type = 'RetailStandalone' end # no elevator schedules for PrimarySchool
|
299
|
-
if building_type == 'StripMall' then building_type = 'RetailStripmall' end # no elevator schedules for PrimarySchool
|
300
|
-
if building_type == 'Outpatient'
|
301
|
-
OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.elevators', 'Outpatient ElevatorPumpRoom plug loads contain the elevator loads. Not adding extra elevator loads on top of it.')
|
302
|
-
end
|
303
|
-
|
304
|
-
# Retrieve the Prototype Inputs from JSON
|
305
|
-
search_criteria = {
|
306
|
-
'template' => template,
|
307
|
-
'building_type' => building_type
|
308
|
-
}
|
309
271
|
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
272
|
+
# determine blended occupancy schedule
|
273
|
+
occ_schedule = spaces_get_occupancy_schedule(model.getSpaces)
|
274
|
+
|
275
|
+
# get total number of people in building
|
276
|
+
max_occ_in_spaces = 0
|
277
|
+
model.getSpaces.each do |space|
|
278
|
+
# From the space type
|
279
|
+
if space.spaceType.is_initialized
|
280
|
+
space.spaceType.get.people.each do |people|
|
281
|
+
num_ppl = people.getNumberOfPeople(space.floorArea)
|
282
|
+
max_occ_in_spaces += num_ppl
|
283
|
+
end
|
284
|
+
end
|
285
|
+
# From the space
|
286
|
+
space.people.each do |people|
|
287
|
+
num_ppl = people.getNumberOfPeople(space.floorArea)
|
288
|
+
max_occ_in_spaces += num_ppl
|
289
|
+
end
|
314
290
|
end
|
315
291
|
|
316
|
-
#
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
292
|
+
# make elevator schedule based on change in occupancy for each timestep
|
293
|
+
day_schedules = []
|
294
|
+
default_day_schedule = occ_schedule.defaultDaySchedule
|
295
|
+
day_schedules << default_day_schedule
|
296
|
+
occ_schedule.scheduleRules.each do |rule|
|
297
|
+
day_schedules << rule.daySchedule
|
298
|
+
end
|
299
|
+
day_schedules.each do |day_schedule|
|
300
|
+
elevator_hourly_fractions = []
|
301
|
+
(0..23).each do |hr|
|
302
|
+
t = OpenStudio::Time.new(0, hr, 0, 0)
|
303
|
+
value = day_schedule.getValue(t)
|
304
|
+
t_plus = OpenStudio::Time.new(0, hr + 1, 0, 0)
|
305
|
+
value_plus = day_schedule.getValue(t_plus)
|
306
|
+
change_occupancy_fraction = (value_plus - value).abs
|
307
|
+
change_num_people = change_occupancy_fraction * max_occ_in_spaces * 1.2
|
308
|
+
# multiplication factor or 1.2 to account for interfloor traffic
|
309
|
+
|
310
|
+
# determine time per ride based on number of floors and elevator type
|
311
|
+
if elevator_type == 'Hydraulic'
|
312
|
+
time_per_ride = 8.7 + (effective_num_stories[:above_grade] * 5.6)
|
313
|
+
elsif elevator_type == 'Traction'
|
314
|
+
time_per_ride = 5.6 + (effective_num_stories[:above_grade] * 2.1)
|
315
|
+
else
|
316
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.prototype.elevators', "Elevator type #{elevator_type} not recognized.")
|
317
|
+
return nil
|
318
|
+
end
|
326
319
|
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
320
|
+
# determine elevator operation fraction for each timestep
|
321
|
+
people_per_ride = 5
|
322
|
+
rides_per_elevator = (change_num_people / people_per_ride) / number_of_elevators
|
323
|
+
operation_time = rides_per_elevator * time_per_ride
|
324
|
+
elevator_operation_fraction = operation_time / 3600
|
325
|
+
if elevator_operation_fraction > 1.00
|
326
|
+
elevator_operation_fraction = 1.00
|
327
|
+
end
|
328
|
+
elevator_hourly_fractions << elevator_operation_fraction
|
332
329
|
end
|
333
330
|
|
334
|
-
#
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
331
|
+
# replace hourly occupancy values with operating fractions
|
332
|
+
day_schedule.clearValues
|
333
|
+
(0..23).each do |hr|
|
334
|
+
t = OpenStudio::Time.new(0, hr, 0, 0)
|
335
|
+
value = elevator_hourly_fractions[hr]
|
336
|
+
value_plus = if hr <= 22
|
337
|
+
elevator_hourly_fractions[hr + 1]
|
338
|
+
else
|
339
|
+
elevator_hourly_fractions[0]
|
340
|
+
end
|
341
|
+
next if value == value_plus
|
342
|
+
day_schedule.addValue(t, elevator_hourly_fractions[hr])
|
346
343
|
end
|
344
|
+
end
|
347
345
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
346
|
+
occ_schedule.setName('Elevator Schedule')
|
347
|
+
|
348
|
+
# clone new elevator schedule and assign to elevator
|
349
|
+
elev_sch = occ_schedule.clone(model)
|
350
|
+
elevator_schedule = elev_sch.name.to_s
|
351
|
+
|
352
|
+
# For elevator lights and fan, assume 100% operation during hours that elevator fraction > 0 (when elevator is in operation).
|
353
|
+
# elevator lights
|
354
|
+
lights_sch = occ_schedule.clone(model)
|
355
|
+
lights_sch = lights_sch.to_ScheduleRuleset.get
|
356
|
+
profiles = []
|
357
|
+
profiles << lights_sch.defaultDaySchedule
|
358
|
+
rules = lights_sch.scheduleRules
|
359
|
+
rules.each do |rule|
|
360
|
+
profiles << rule.daySchedule
|
361
|
+
end
|
362
|
+
profiles.each do |profile|
|
363
|
+
times = profile.times
|
364
|
+
values = profile.values
|
365
|
+
values.each_with_index do |val, i|
|
366
|
+
if val > 0
|
367
|
+
profile.addValue(times[i], 1.0)
|
364
368
|
end
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
369
|
+
end
|
370
|
+
end
|
371
|
+
elevator_lights_schedule = lights_sch.name.to_s
|
372
|
+
|
373
|
+
# elevator fan
|
374
|
+
fan_sch = occ_schedule.clone(model)
|
375
|
+
fan_sch = fan_sch.to_ScheduleRuleset.get
|
376
|
+
profiles = []
|
377
|
+
profiles << fan_sch.defaultDaySchedule
|
378
|
+
rules = fan_sch.scheduleRules
|
379
|
+
rules.each do |rule|
|
380
|
+
profiles << rule.daySchedule
|
381
|
+
end
|
382
|
+
profiles.each do |profile|
|
383
|
+
times = profile.times
|
384
|
+
values = profile.values
|
385
|
+
values.each_with_index do |val, i|
|
386
|
+
if val > 0
|
387
|
+
profile.addValue(times[i], 1.0)
|
377
388
|
end
|
378
389
|
end
|
379
|
-
|
380
390
|
end
|
391
|
+
elevator_fan_schedule = fan_sch.name.to_s
|
381
392
|
|
382
393
|
# TODO: - currently add elevator doesn't allow me to choose the size of the elevator?
|
383
394
|
# ref bldg pdf has formula for motor hp based on weight, speed, counterweight fraction and mech eff (in 5.1.4)
|