openstudio-standards 0.2.8 → 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|