openstudio-standards 0.1.11 → 0.1.12
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/standards/OpenStudio_Standards.xlsx +0 -0
- data/data/standards/OpenStudio_Standards_climate_zone_sets.json +96 -0
- data/data/standards/OpenStudio_Standards_climate_zones.json +96 -0
- data/data/standards/OpenStudio_Standards_construction_properties.json +11424 -0
- data/data/standards/OpenStudio_Standards_construction_sets.json +1746 -24
- data/data/standards/OpenStudio_Standards_constructions.json +409 -0
- data/data/standards/OpenStudio_Standards_curve_biquadratics.json +160 -0
- data/data/standards/OpenStudio_Standards_curve_quadratics.json +165 -0
- data/data/standards/OpenStudio_Standards_entryways.json +191 -0
- data/data/standards/OpenStudio_Standards_exterior_lighting.json +964 -0
- data/data/standards/OpenStudio_Standards_exterior_lighting_assumptions.json +191 -0
- data/data/standards/OpenStudio_Standards_ground_temperatures.json +11424 -0
- data/data/standards/OpenStudio_Standards_illuminated_parking_area.json +157 -0
- data/data/standards/OpenStudio_Standards_materials.json +2539 -745
- data/data/standards/OpenStudio_Standards_motors.json +420 -0
- data/data/standards/OpenStudio_Standards_parking.json +157 -0
- data/data/standards/OpenStudio_Standards_prototype_inputs.json +4410 -10
- data/data/standards/OpenStudio_Standards_schedules.json +13756 -8383
- data/data/standards/OpenStudio_Standards_space_types.json +8593 -907
- data/data/standards/OpenStudio_Standards_standards.json +9 -0
- data/data/standards/OpenStudio_Standards_templates.json +24 -0
- data/data/standards/OpenStudio_Standards_unitary_acs.json +924 -0
- data/data/standards/manage_OpenStudio_Standards.rb +1 -1
- data/lib/openstudio-standards/btap/btap.rb +0 -1
- data/lib/openstudio-standards/btap/compliance.rb +2 -5
- data/lib/openstudio-standards/btap/economics.rb +16 -16
- data/lib/openstudio-standards/btap/envelope.rb +1 -1
- data/lib/openstudio-standards/btap/equest.rb +7 -7
- data/lib/openstudio-standards/btap/fileio.rb +2 -2
- data/lib/openstudio-standards/btap/geometry.rb +1 -1
- data/lib/openstudio-standards/btap/measures.rb +16 -16
- data/lib/openstudio-standards/btap/mpc.rb +18 -18
- data/lib/openstudio-standards/btap/schedules.rb +35 -2
- data/lib/openstudio-standards/btap/simmanager.rb +1 -1
- data/lib/openstudio-standards/btap/spaceloads.rb +1 -1
- data/lib/openstudio-standards/btap/vintagizer.rb +1 -1
- data/lib/openstudio-standards/prototypes/Prototype.Model.elevators.rb +218 -0
- data/lib/openstudio-standards/prototypes/Prototype.Model.exterior_lights.rb +399 -0
- data/lib/openstudio-standards/prototypes/Prototype.Model.hvac.rb +2 -2
- data/lib/openstudio-standards/prototypes/Prototype.Model.rb +237 -0
- data/lib/openstudio-standards/prototypes/Prototype.Model.swh.rb +536 -0
- data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +6 -0
- data/lib/openstudio-standards/standards/Standards.Model.rb +249 -10
- data/lib/openstudio-standards/standards/Standards.SpaceType.rb +5 -5
- data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +161 -0
- data/lib/openstudio-standards/utilities/simulation.rb +6 -4
- data/lib/openstudio-standards/version.rb +1 -1
- metadata +223 -204
- data/lib/openstudio-standards/btap/os_lib_schedules.rb +0 -677
@@ -318,13 +318,13 @@ module BTAP
|
|
318
318
|
#Get the occupancy schedule.
|
319
319
|
occ_schedule = people.numberofPeopleSchedule.get
|
320
320
|
#Convert schedule to timeseries and sum up timeseries objects for this space / zone.
|
321
|
-
occ_time_series =
|
321
|
+
occ_time_series = create_timeseries_from_schedule_ruleset(model,occ_schedule)
|
322
322
|
timeseries = timeseries + occ_time_series
|
323
323
|
end
|
324
324
|
end
|
325
325
|
end
|
326
326
|
#return the timeseries converted to
|
327
|
-
return
|
327
|
+
return create_schedule_variable_interval_from_time_series(model,timeseries)
|
328
328
|
end
|
329
329
|
|
330
330
|
|
@@ -897,6 +897,39 @@ module BTAP
|
|
897
897
|
return create_annual_ruleset_schedule(model, name,type, [Array.new(24){value}, Array.new(24){value},Array.new(24){value}])
|
898
898
|
end
|
899
899
|
|
900
|
+
# Creates TimeSeries from ScheduleRuleset
|
901
|
+
# @author david.goldwasser@nrel.gov
|
902
|
+
# @param model [OpenStudio::Model::Model] A model object
|
903
|
+
# @param schedule_ruleset [OpenStudio::Model::ScheduleRuleset] A schedule ruleset
|
904
|
+
# @return [OpenStudio::TimeSeries] A TimeSeries object
|
905
|
+
def self.create_timeseries_from_schedule_ruleset(model, schedule_ruleset)
|
906
|
+
yd = model.getYearDescription
|
907
|
+
start_date = yd.makeDate(1, 1)
|
908
|
+
end_date = yd.makeDate(12, 31)
|
909
|
+
|
910
|
+
values = OpenStudio::DoubleVector.new
|
911
|
+
day = OpenStudio::Time.new(1.0)
|
912
|
+
interval = OpenStudio::Time.new(1.0 / 48.0)
|
913
|
+
day_schedules = schedule_ruleset.to_ScheduleRuleset.get.getDaySchedules(start_date, end_date)
|
914
|
+
day_schedules.each do |day_schedule|
|
915
|
+
time = interval
|
916
|
+
while time < day
|
917
|
+
values << day_schedule.getValue(time)
|
918
|
+
time += interval
|
919
|
+
end
|
920
|
+
end
|
921
|
+
time_series = OpenStudio::TimeSeries.new(start_date, interval, OpenStudio.createVector(values), "")
|
922
|
+
end
|
923
|
+
|
924
|
+
# Creates ScheduleVariableInterval from TimeSeries
|
925
|
+
# @author david.goldwasser@nrel.gov
|
926
|
+
# @param model [OpenStudio::model::Model] A model object
|
927
|
+
# @param time_series [OpenStudio::TimeSeries] A TimeSeries object
|
928
|
+
# @return [OpenStudio::Model::ScheduleInterval] An interval schedule
|
929
|
+
def self.create_schedule_variable_interval_from_time_series(model, time_series)
|
930
|
+
result = OpenStudio::Model::ScheduleInterval.fromTimeSeries(time_series, model).get
|
931
|
+
end
|
932
|
+
|
900
933
|
end #module Schedules
|
901
934
|
|
902
935
|
end #module Resources
|
@@ -231,7 +231,7 @@ module BTAP
|
|
231
231
|
#@return [String] self
|
232
232
|
def addModel(model, folder = @analysisFolder )
|
233
233
|
|
234
|
-
run_name = model.building.get.
|
234
|
+
run_name = model.building.get.name.get.to_s
|
235
235
|
working_folder = OpenStudio::Path.new(folder.to_s + "\\simulations\\" + run_name )
|
236
236
|
osm_save_path = OpenStudio::Path.new(folder.to_s + "\\simulations\\" + run_name + "\\" + run_name + ".osm" )
|
237
237
|
model.save(OpenStudio::Path.new(osm_save_path), true);
|
@@ -187,7 +187,7 @@ module BTAP
|
|
187
187
|
infiltration_load.setDesignFlowRate( setDesignFlowRate ) unless setDesignFlowRate.nil?
|
188
188
|
infiltration_load.setFlowperSpaceFloorArea(setFlowperSpaceFloorArea ) unless setFlowperSpaceFloorArea.nil?
|
189
189
|
infiltration_load.setFlowperExteriorSurfaceArea(setFlowperExteriorSurfaceArea ) unless setFlowperExteriorSurfaceArea.nil?
|
190
|
-
table << infiltration_load.
|
190
|
+
table << infiltration_load.name.get.to_s << ","
|
191
191
|
table << infiltration_load.designFlowRateCalculationMethod << ","
|
192
192
|
infiltration_load.airChangesperHour.empty? ? ach = "NA" : ach = infiltration_load.airChangesperHour.get
|
193
193
|
infiltration_load.designFlowRate.empty? ? dfr = "NA" : dfr = infiltration_load.designFlowRate.get
|
@@ -96,7 +96,7 @@ class Vintagizer
|
|
96
96
|
#Remove all existing constructions from model.
|
97
97
|
BTAP::Resources::Envelope::remove_all_envelope_information( constructions_model )
|
98
98
|
#Save to model.
|
99
|
-
new_construction_set.
|
99
|
+
new_construction_set.setName(construction_id)
|
100
100
|
constructions_model.building.get.setDefaultConstructionSet( new_construction_set.clone( constructions_model ).to_DefaultConstructionSet.get )
|
101
101
|
|
102
102
|
#Give adiabatic surfaces a construction. Does not matter what. This is a bug in Openstudio that leave these surfaces unassigned by the default construction set.
|
@@ -0,0 +1,218 @@
|
|
1
|
+
# open the class to add methods to add elevators
|
2
|
+
class OpenStudio::Model::Model
|
3
|
+
|
4
|
+
# Add elevators to the model
|
5
|
+
#
|
6
|
+
# @param template [String] Valid choices are
|
7
|
+
# @return [OpenStudio::Model::ElectricEquipment] the resulting elevator
|
8
|
+
def add_elevators(template)
|
9
|
+
|
10
|
+
# determine effective number of stories
|
11
|
+
effective_num_stories = self.effective_num_stories
|
12
|
+
|
13
|
+
# determine elevator type
|
14
|
+
# todo - add logic here or upstream to have some multi-story buildings without elevators (e.g. small multi-family and small hotels)
|
15
|
+
elevator_type = nil
|
16
|
+
if effective_num_stories[:below_grade] + effective_num_stories[:above_grade] < 2
|
17
|
+
return nil # don't add elevators
|
18
|
+
elsif effective_num_stories[:below_grade] + effective_num_stories[:above_grade] < 6
|
19
|
+
elevator_type = "Hydraulic"
|
20
|
+
else
|
21
|
+
elevator_type = "Traction"
|
22
|
+
end
|
23
|
+
|
24
|
+
# determine space to put elevator load in
|
25
|
+
# largest bottom story (including basement) space that has multiplier of 1
|
26
|
+
bottom_spaces = {}
|
27
|
+
bottom_story = effective_num_stories[:story_hash].keys.first
|
28
|
+
bottom_story.spaces.each do |space|
|
29
|
+
next if space.multiplier > 1
|
30
|
+
bottom_spaces[space] = space.floorArea
|
31
|
+
end
|
32
|
+
target_space = bottom_spaces.key(bottom_spaces.values.max)
|
33
|
+
|
34
|
+
# determine number of elevators
|
35
|
+
number_of_pass_elevators = 0.0
|
36
|
+
number_of_freight_elevators = 0.0
|
37
|
+
building_type_hash = {}
|
38
|
+
|
39
|
+
# apply building type specific log to add to number of elevators based on Beyer (2009) rules of thumb
|
40
|
+
space_type_hash = self.create_space_type_hash(template)
|
41
|
+
space_type_hash.each do |space_type,hash|
|
42
|
+
|
43
|
+
# update building_type_hash
|
44
|
+
if building_type_hash.has_key?(hash[:stds_bldg_type])
|
45
|
+
building_type_hash[hash[:stds_bldg_type]] += hash[:floor_area]
|
46
|
+
else
|
47
|
+
building_type_hash[hash[:stds_bldg_type]] = hash[:floor_area]
|
48
|
+
end
|
49
|
+
|
50
|
+
# building type specific notes; prototype uses Beyer (2009) rules fo thumb
|
51
|
+
if ["Office","SmallOffice","MediumOffice","LargeOffice"].include?(hash[:stds_bldg_type])
|
52
|
+
# The office buildings have one elevator for every 45,000 ft2 (4,181 m2),
|
53
|
+
# plus one service elevator for the large office building.
|
54
|
+
pass_elevator_per_area = OpenStudio::convert(45000.0,"ft^2","m^2").get
|
55
|
+
number_of_pass_elevators += hash[:floor_area]/pass_elevator_per_area
|
56
|
+
# add freight elevators as separate step 1 if over 5k m^2 but more than one if over 50k m^2
|
57
|
+
if self.getBuilding.floorArea > 45000.0 # m^2
|
58
|
+
number_of_freight_elevators += self.getBuilding.floorArea/500000.0 # m^2
|
59
|
+
end
|
60
|
+
elsif["SmallHotel","LargeHotel"].include?(hash[:stds_bldg_type]) && hash[:stds_space_type].include?("GuestRoom")
|
61
|
+
# The hotels have one elevator for every 75 rooms, and the large hotel includes one service elevator for every two public elevators,
|
62
|
+
# plus one additional elevator for the dining and banquet facilities on the top floor.
|
63
|
+
units_per_pass_elevator = 75.0
|
64
|
+
freight_elevators_per_unit = units_per_pass_elevator/2.0
|
65
|
+
number_of_pass_elevators += hash[:num_units]/units_per_pass_elevator
|
66
|
+
number_of_freight_elevators += hash[:num_units]/freight_elevators_per_unit
|
67
|
+
elsif["LargeHotel"].include?(hash[:stds_bldg_type]) && ["Banquet","Cafe"].include?(hash[:stds_space_type])
|
68
|
+
pass_elevator_per_area = OpenStudio::convert(10000.0,"ft^2","m^2").get
|
69
|
+
number_of_pass_elevators += hash[:floor_area]/pass_elevator_per_area
|
70
|
+
elsif["MidriseApartment","HighriseApartment"].include?(hash[:stds_bldg_type]) && hash[:stds_space_type].include?("Apartment")
|
71
|
+
# The apartment building has one elevator for every 90 units
|
72
|
+
units_per_pass_elevator = 90.0
|
73
|
+
number_of_pass_elevators += hash[:num_units]/units_per_pass_elevator
|
74
|
+
elsif["Hospital"].include?(hash[:stds_bldg_type]) && ["PatRoom","ICU_PatRm","ICU_Open"].include?(hash[:stds_space_type])
|
75
|
+
# The hospital has one public and one service elevator for every 100 beds (250 total),
|
76
|
+
# plus two elevators for the offices and cafeteria on the top floor.
|
77
|
+
beds_per_pass_elevator = 100.0
|
78
|
+
number_of_pass_elevators += hash[:num_beds]/beds_per_pass_elevator
|
79
|
+
number_of_freight_elevators += hash[:num_beds]/beds_per_pass_elevator
|
80
|
+
elsif["Hospital"].include?(hash[:stds_bldg_type]) && ["Dining","Kitchen","Office"].include?(hash[:stds_space_type])
|
81
|
+
pass_elevator_per_area = OpenStudio::convert(12500.0,"ft^2","m^2").get
|
82
|
+
number_of_pass_elevators += hash[:floor_area]/pass_elevator_per_area
|
83
|
+
elsif ["PrimarySchool","SecondarySchool"].include?(hash[:stds_bldg_type])
|
84
|
+
# 210,887 ft^2 secondary school prototype has 2 elevators
|
85
|
+
pass_elevator_per_area = OpenStudio::convert(100000.0,"ft^2","m^2").get
|
86
|
+
number_of_pass_elevators += hash[:floor_area]/(pass_elevator_per_area) # freight and passenger combined
|
87
|
+
elsif ["Outpatient"].include?(hash[:stds_bldg_type])
|
88
|
+
# 210,887 ft^2 secondary school prototype has 2 elevators
|
89
|
+
#pass_elevator_per_area = OpenStudio::convert(15000.0,"ft^2","m^2").get
|
90
|
+
#number_of_pass_elevators += hash[:floor_area]/(pass_elevator_per_area) # freight and passenger combined
|
91
|
+
elsif ["Warehouse"].include?(hash[:stds_bldg_type])
|
92
|
+
freight_elevator_per_area = OpenStudio::convert(250000.0,"ft^2","m^2").get
|
93
|
+
number_of_freight_elevators += hash[:floor_area]/freight_elevator_per_area
|
94
|
+
else
|
95
|
+
# todo - improve catchall for building types without elevator data, using same value as what Outpatient would be if not already in space type
|
96
|
+
# includes RetailStandalone, RetailStripmall, QuickServiceRestaurant, FullServiceRestaurant, SuperMarket (made unique logic above for warehouse)
|
97
|
+
|
98
|
+
pass_elevator_per_area = OpenStudio::convert(15000.0,"ft^2","m^2").get
|
99
|
+
number_of_pass_elevators += hash[:floor_area]/pass_elevator_per_area
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
# adjust number of elevators (can be double but if not 0 must be at least 1.0)
|
105
|
+
if number_of_pass_elevators > 0.0 and number_of_pass_elevators < 1.0
|
106
|
+
number_of_pass_elevators = 1.0
|
107
|
+
end
|
108
|
+
if number_of_freight_elevators > 0.0 and number_of_freight_elevators < 1.0
|
109
|
+
number_of_freight_elevators = 1.0
|
110
|
+
end
|
111
|
+
number_of_elevators = number_of_pass_elevators + number_of_freight_elevators
|
112
|
+
|
113
|
+
|
114
|
+
building_type = building_type_hash.key(building_type_hash.values.max)
|
115
|
+
# rename space types as needed
|
116
|
+
if building_type == "Office"
|
117
|
+
building_type = self.remap_office(building_type_hash["Office"])
|
118
|
+
end
|
119
|
+
if building_type == "SmallHotel" then building_type = "LargeHotel" end # no elevator schedules for SmallHotel
|
120
|
+
if building_type == "PrimarySchool" then building_type = "SecondarySchool" end # no elevator schedules for PrimarySchool
|
121
|
+
if building_type == "Retail" then building_type = "RetailStandalone" end # no elevator schedules for PrimarySchool
|
122
|
+
if building_type == "StripMall" then building_type = "RetailStripmall" end # no elevator schedules for PrimarySchool
|
123
|
+
if building_type == "Outpatient"
|
124
|
+
OpenStudio.logFree(OpenStudio::Info, 'Prototype.Model.elevators', "Outpatient ElevatorPumpRoom plug loads contain the elevator loads. Not adding extra elevator loads on top of it.")
|
125
|
+
end
|
126
|
+
|
127
|
+
# Retrieve the Prototype Inputs from JSON
|
128
|
+
search_criteria = {
|
129
|
+
'template' => template,
|
130
|
+
'building_type' => building_type
|
131
|
+
}
|
132
|
+
|
133
|
+
prototype_input = find_object($os_standards['prototype_inputs'], search_criteria, nil)
|
134
|
+
if prototype_input.nil?
|
135
|
+
OpenStudio.logFree(OpenStudio::Error, 'Prototype.Model.elevators', "Could not find prototype inputs for #{search_criteria}.")
|
136
|
+
return false
|
137
|
+
end
|
138
|
+
|
139
|
+
# assign schedules
|
140
|
+
if ["Office","SmallOffice","MediumOffice","LargeOffice","MidriseApartment","HighriseApartment","SecondarySchool"].include?(building_type)
|
141
|
+
elevator_schedule = prototype_input['elevator_schedule']
|
142
|
+
elevator_fan_schedule = prototype_input['elevator_fan_schedule']
|
143
|
+
elevator_lights_schedule = prototype_input['elevator_fan_schedule']
|
144
|
+
elsif ["LargeHotel","Hospital"].include?(building_type)
|
145
|
+
elevator_schedule = prototype_input['exterior_fuel_equipment1_schedule']
|
146
|
+
elevator_fan_schedule = prototype_input['exterior_fuel_equipment2_schedule']
|
147
|
+
elevator_lights_schedule = prototype_input['exterior_fuel_equipment2_schedule']
|
148
|
+
else
|
149
|
+
|
150
|
+
# identify occupancy schedule from largest space type of this building type
|
151
|
+
space_type_size = {}
|
152
|
+
space_type_hash.each do |space_type,hash|
|
153
|
+
next if not building_type.include?(hash[:stds_bldg_type])
|
154
|
+
space_type_size[space_type] = hash[:floor_area]
|
155
|
+
end
|
156
|
+
occ_sch = space_type_size.key(space_type_size.values.max).defaultScheduleSet.get.numberofPeopleSchedule.get
|
157
|
+
|
158
|
+
# clone and assign to elevator
|
159
|
+
elev_sch = occ_sch.clone(self)
|
160
|
+
elevator_schedule = elev_sch.name.to_s
|
161
|
+
elevator_fan_schedule = elev_sch.name.to_s
|
162
|
+
elevator_lights_schedule = elev_sch.name.to_s
|
163
|
+
|
164
|
+
# todo - scale down peak value based on building type lookup, or make parametric schedule based on hours of operation
|
165
|
+
# includes RetailStandalone, RetailStripmall, QuickServiceRestaurant, FullServiceRestaurant, SuperMarket (made unique logic above for warehouse)
|
166
|
+
|
167
|
+
if building_type == "Warehouse"
|
168
|
+
# alter default profile, summer, winter, and rules
|
169
|
+
max_value = 0.2
|
170
|
+
elev_sch = elev_sch.to_ScheduleRuleset.get
|
171
|
+
day_schedules = []
|
172
|
+
elev_sch.scheduleRules.each do |rule|
|
173
|
+
day_schedules << rule.daySchedule
|
174
|
+
end
|
175
|
+
day_schedules << elev_sch.defaultDaySchedule
|
176
|
+
day_schedules << elev_sch.summerDesignDaySchedule
|
177
|
+
day_schedules << elev_sch.winterDesignDaySchedule
|
178
|
+
|
179
|
+
day_schedules.each do |day_schedule|
|
180
|
+
values = day_schedule.values
|
181
|
+
times = day_schedule.times
|
182
|
+
values.each_with_index do |value,i|
|
183
|
+
if value > max_value
|
184
|
+
day_schedule.addValue(times[i],max_value)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
# todo - currently add elevator doesn't allow me to choose the size of the elevator?
|
193
|
+
# ref bldg pdf has formula for motor hp based on weight, speed, counterweight fraction and mech eff (in 5.1.4)
|
194
|
+
|
195
|
+
# todo - should schedules change based on traction vs. hydraulic vs. just taking what is in prototype.
|
196
|
+
|
197
|
+
# call add_elevator in Prototype.hvac_systems.rb to create elevator objects
|
198
|
+
elevator = self.add_elevator(template,
|
199
|
+
target_space,
|
200
|
+
number_of_elevators,
|
201
|
+
elevator_type,
|
202
|
+
elevator_schedule,
|
203
|
+
elevator_fan_schedule,
|
204
|
+
elevator_lights_schedule,
|
205
|
+
building_type)
|
206
|
+
|
207
|
+
OpenStudio.logFree(OpenStudio::Info, 'Prototype.Model.elevators', "Adding #{elevator.multiplier} #{elevator_type} elevators to the model in #{target_space.name}.")
|
208
|
+
|
209
|
+
# check fraction lost on heat from elevator if traction, change to 100% lost if not setup that way.
|
210
|
+
if elevator_type == "Traction"
|
211
|
+
elevator.definition.to_ElectricEquipmentDefinition.get.setFractionLost(1.0)
|
212
|
+
end
|
213
|
+
|
214
|
+
return elevator
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
@@ -0,0 +1,399 @@
|
|
1
|
+
# open the class to add methods to add exterior lighting
|
2
|
+
class OpenStudio::Model::Model
|
3
|
+
|
4
|
+
# Add exterior lighting to the model
|
5
|
+
#
|
6
|
+
# @param template [String] Valid choices are
|
7
|
+
# @param exterior_lighting_zone_number [Integer] Valid choices are
|
8
|
+
# @return [Hash] the resulting exterior lights
|
9
|
+
# @todo - would be nice to add argument for some building types (SmallHotel, MidriseApartment, PrimarySchool, SecondarySchool, RetailStripmall) if it has interior or exterior circulation.
|
10
|
+
def add_typical_exterior_lights(template,exterior_lighting_zone_number,onsite_parking_fraction = 1.0, add_base_site_allowance = false, use_model_for_entries_and_canopies = false)
|
11
|
+
|
12
|
+
exterior_lights = {}
|
13
|
+
installed_power = 0.0
|
14
|
+
|
15
|
+
# populate search hash
|
16
|
+
search_criteria = {
|
17
|
+
'template' => template,
|
18
|
+
'exterior_lighting_zone_number' => exterior_lighting_zone_number,
|
19
|
+
}
|
20
|
+
|
21
|
+
# load exterior_lighting_properties
|
22
|
+
exterior_lighting_properties = self.find_object($os_standards['exterior_lighting'], search_criteria)
|
23
|
+
|
24
|
+
# get building types and ratio (needed to get correct schedules, parking area, entries, canopies, and drive throughs)
|
25
|
+
space_type_hash = self.create_space_type_hash(template)
|
26
|
+
|
27
|
+
# get model specific values to map to exterior_lighting_properties
|
28
|
+
area_length_count_hash = self.create_exterior_lighting_area_length_count_hash(template,space_type_hash,use_model_for_entries_and_canopies)
|
29
|
+
|
30
|
+
# using midnight to 6am setback or shutdown
|
31
|
+
start_setback_shutoff = {:hr => 24, :min => 0}
|
32
|
+
end_setback_shutoff = {:hr => 6, :min => 0}
|
33
|
+
shuttoff = false
|
34
|
+
setback = false
|
35
|
+
if exterior_lighting_properties["building_facade_and_landscape_automatic_shut_off"] == 1
|
36
|
+
ext_lights_sch_facade_and_landscape = OpenStudio::Model::ScheduleRuleset.new(self)
|
37
|
+
default_day = ext_lights_sch_facade_and_landscape.defaultDaySchedule
|
38
|
+
default_day.addValue(OpenStudio::Time.new(0, end_setback_shutoff[:hr], end_setback_shutoff[:min], 0), 0.0)
|
39
|
+
default_day.addValue(OpenStudio::Time.new(0, start_setback_shutoff[:hr], start_setback_shutoff[:min], 0), 1.0)
|
40
|
+
OpenStudio.logFree(OpenStudio::Info, 'Prototype.Model.exterior_lights', "Facade and Landscape exterior lights shut off from #{start_setback_shutoff} to #{end_setback_shutoff}")
|
41
|
+
else
|
42
|
+
ext_lights_sch_facade_and_landscape = self.alwaysOnDiscreteSchedule
|
43
|
+
end
|
44
|
+
if not exterior_lighting_properties["occupancy_setback_reduction"].nil? and exterior_lighting_properties["occupancy_setback_reduction"] > 0.0
|
45
|
+
ext_lights_sch_other = OpenStudio::Model::ScheduleRuleset.new(self)
|
46
|
+
setback_value = 1.0 - exterior_lighting_properties["occupancy_setback_reduction"]
|
47
|
+
default_day = ext_lights_sch_other.defaultDaySchedule
|
48
|
+
default_day.addValue(OpenStudio::Time.new(0, end_setback_shutoff[:hr], end_setback_shutoff[:min], 0), setback_value)
|
49
|
+
default_day.addValue(OpenStudio::Time.new(0, start_setback_shutoff[:hr], start_setback_shutoff[:min], 0), 1.0)
|
50
|
+
OpenStudio.logFree(OpenStudio::Info, 'Prototype.Model.exterior_lights', "Non Facade and Landscape lights reduce by #{exterior_lighting_properties["occupancy_setback_reduction"]*100} % from #{start_setback_shutoff} to #{end_setback_shutoff}")
|
51
|
+
else
|
52
|
+
ext_lights_sch_other = self.alwaysOnDiscreteSchedule
|
53
|
+
end
|
54
|
+
|
55
|
+
# add exterior lights for parking area
|
56
|
+
if area_length_count_hash[:parking_area_and_drives_area] > 0
|
57
|
+
|
58
|
+
# lighting values
|
59
|
+
multiplier = area_length_count_hash[:parking_area_and_drives_area] * onsite_parking_fraction
|
60
|
+
power = exterior_lighting_properties["parking_areas_and_drives"]
|
61
|
+
name_prefix = "Parking Areas and Drives"
|
62
|
+
|
63
|
+
# create ext light def
|
64
|
+
OpenStudio.logFree(OpenStudio::Info, 'Prototype.Model.exterior_lights', "Added #{power} W/ft^2 of lighting for #{multiplier} ft^2 of parking area.")
|
65
|
+
ext_lights_def = OpenStudio::Model::ExteriorLightsDefinition.new(self)
|
66
|
+
ext_lights_def.setName("#{name_prefix} Def (W/ft^2)")
|
67
|
+
ext_lights_def.setDesignLevel(power)
|
68
|
+
|
69
|
+
# create ext light inst
|
70
|
+
#creating exterior lights object
|
71
|
+
ext_lights = OpenStudio::Model::ExteriorLights.new(ext_lights_def,ext_lights_sch_other)
|
72
|
+
ext_lights.setMultiplier(multiplier)
|
73
|
+
ext_lights.setName(name_prefix)
|
74
|
+
ext_lights.setControlOption(exterior_lighting_properties["control_option"])
|
75
|
+
ext_lights.setEndUseSubcategory(name_prefix)
|
76
|
+
exterior_lights[name_prefix] = ext_lights
|
77
|
+
|
78
|
+
# update installed power
|
79
|
+
installed_power += power * multiplier
|
80
|
+
end
|
81
|
+
|
82
|
+
# add exterior lights for facades
|
83
|
+
if area_length_count_hash[:building_facades] > 0
|
84
|
+
|
85
|
+
# lighting values
|
86
|
+
multiplier = area_length_count_hash[:building_facades]
|
87
|
+
power = exterior_lighting_properties["building_facades"]
|
88
|
+
name_prefix = "Building Facades"
|
89
|
+
|
90
|
+
# create ext light def
|
91
|
+
OpenStudio.logFree(OpenStudio::Info, 'Prototype.Model.exterior_lights', "Added #{power} W/ft^2 of lighting for #{multiplier} ft^2 of building facade area.")
|
92
|
+
ext_lights_def = OpenStudio::Model::ExteriorLightsDefinition.new(self)
|
93
|
+
ext_lights_def.setName("#{name_prefix} Def (W/ft^2)")
|
94
|
+
ext_lights_def.setDesignLevel(power)
|
95
|
+
|
96
|
+
# create ext light inst
|
97
|
+
#creating exterior lights object
|
98
|
+
ext_lights = OpenStudio::Model::ExteriorLights.new(ext_lights_def,ext_lights_sch_facade_and_landscape)
|
99
|
+
ext_lights.setMultiplier(multiplier)
|
100
|
+
ext_lights.setName(name_prefix)
|
101
|
+
ext_lights.setControlOption(exterior_lighting_properties["control_option"])
|
102
|
+
ext_lights.setEndUseSubcategory(name_prefix)
|
103
|
+
exterior_lights[name_prefix] = ext_lights
|
104
|
+
|
105
|
+
# update installed power
|
106
|
+
installed_power += power * multiplier
|
107
|
+
end
|
108
|
+
|
109
|
+
# add exterior lights for main entries
|
110
|
+
if area_length_count_hash[:main_entries] > 0
|
111
|
+
|
112
|
+
# lighting values
|
113
|
+
multiplier = area_length_count_hash[:main_entries]
|
114
|
+
power = exterior_lighting_properties["main_entries"]
|
115
|
+
name_prefix = "Main Entries"
|
116
|
+
|
117
|
+
# create ext light def
|
118
|
+
OpenStudio.logFree(OpenStudio::Info, 'Prototype.Model.exterior_lights', "Added #{power} W/ft of lighting for #{multiplier} ft of main entry length.")
|
119
|
+
ext_lights_def = OpenStudio::Model::ExteriorLightsDefinition.new(self)
|
120
|
+
ext_lights_def.setName("#{name_prefix} Def (W/ft)")
|
121
|
+
ext_lights_def.setDesignLevel(power)
|
122
|
+
|
123
|
+
# create ext light inst
|
124
|
+
#creating exterior lights object
|
125
|
+
ext_lights = OpenStudio::Model::ExteriorLights.new(ext_lights_def,ext_lights_sch_other)
|
126
|
+
ext_lights.setMultiplier(multiplier)
|
127
|
+
ext_lights.setName(name_prefix)
|
128
|
+
ext_lights.setControlOption(exterior_lighting_properties["control_option"])
|
129
|
+
ext_lights.setEndUseSubcategory(name_prefix)
|
130
|
+
exterior_lights[name_prefix] = ext_lights
|
131
|
+
|
132
|
+
# update installed power
|
133
|
+
installed_power += power * multiplier
|
134
|
+
end
|
135
|
+
|
136
|
+
# add exterior lights for other doors
|
137
|
+
if area_length_count_hash[:other_doors] > 0
|
138
|
+
|
139
|
+
# lighting values
|
140
|
+
multiplier = area_length_count_hash[:other_doors]
|
141
|
+
power = exterior_lighting_properties["other_doors"]
|
142
|
+
name_prefix = "Other Doors"
|
143
|
+
|
144
|
+
# create ext light def
|
145
|
+
OpenStudio.logFree(OpenStudio::Info, 'Prototype.Model.exterior_lights', "Added #{power} W/ft of lighting for #{multiplier} ft of other doors.")
|
146
|
+
ext_lights_def = OpenStudio::Model::ExteriorLightsDefinition.new(self)
|
147
|
+
ext_lights_def.setName("#{name_prefix} Def (W/ft)")
|
148
|
+
ext_lights_def.setDesignLevel(power)
|
149
|
+
|
150
|
+
# create ext light inst
|
151
|
+
#creating exterior lights object
|
152
|
+
ext_lights = OpenStudio::Model::ExteriorLights.new(ext_lights_def,ext_lights_sch_other)
|
153
|
+
ext_lights.setMultiplier(multiplier)
|
154
|
+
ext_lights.setName(name_prefix)
|
155
|
+
ext_lights.setControlOption(exterior_lighting_properties["control_option"])
|
156
|
+
ext_lights.setEndUseSubcategory(name_prefix)
|
157
|
+
exterior_lights[name_prefix] = ext_lights
|
158
|
+
|
159
|
+
# update installed power
|
160
|
+
installed_power += power * multiplier
|
161
|
+
end
|
162
|
+
|
163
|
+
# add exterior lights for entry canopies
|
164
|
+
if area_length_count_hash[:canopy_entry_area] > 0
|
165
|
+
|
166
|
+
# lighting values
|
167
|
+
multiplier = area_length_count_hash[:canopy_entry_area]
|
168
|
+
power = exterior_lighting_properties["entry_canopies"]
|
169
|
+
name_prefix = "Entry Canopies"
|
170
|
+
|
171
|
+
# create ext light def
|
172
|
+
OpenStudio.logFree(OpenStudio::Info, 'Prototype.Model.exterior_lights', "Added #{power} W/ft^2 of lighting for #{multiplier} ft^2 of building entry canopies.")
|
173
|
+
ext_lights_def = OpenStudio::Model::ExteriorLightsDefinition.new(self)
|
174
|
+
ext_lights_def.setName("#{name_prefix} Def (W/ft^2)")
|
175
|
+
ext_lights_def.setDesignLevel(power)
|
176
|
+
|
177
|
+
# create ext light inst
|
178
|
+
#creating exterior lights object
|
179
|
+
ext_lights = OpenStudio::Model::ExteriorLights.new(ext_lights_def,ext_lights_sch_other)
|
180
|
+
ext_lights.setMultiplier(multiplier)
|
181
|
+
ext_lights.setName(name_prefix)
|
182
|
+
ext_lights.setControlOption(exterior_lighting_properties["control_option"])
|
183
|
+
ext_lights.setEndUseSubcategory(name_prefix)
|
184
|
+
exterior_lights[name_prefix] = ext_lights
|
185
|
+
|
186
|
+
# update installed power
|
187
|
+
installed_power += power * multiplier
|
188
|
+
end
|
189
|
+
|
190
|
+
# add exterior lights for emergency canopies
|
191
|
+
if area_length_count_hash[:canopy_emergency_area] > 0
|
192
|
+
|
193
|
+
# lighting values
|
194
|
+
multiplier = area_length_count_hash[:canopy_emergency_area]
|
195
|
+
power = exterior_lighting_properties["loading_areas_for_emergency_vehicles"]
|
196
|
+
name_prefix = "Emergency Canopies"
|
197
|
+
|
198
|
+
# create ext light def
|
199
|
+
OpenStudio.logFree(OpenStudio::Info, 'Prototype.Model.exterior_lights', "Added #{power} W/ft^2 of lighting for #{multiplier} ft^2 of building emergency canopies.")
|
200
|
+
ext_lights_def = OpenStudio::Model::ExteriorLightsDefinition.new(self)
|
201
|
+
ext_lights_def.setName("#{name_prefix} Def (W/ft^2)")
|
202
|
+
ext_lights_def.setDesignLevel(power)
|
203
|
+
|
204
|
+
# create ext light inst
|
205
|
+
#creating exterior lights object
|
206
|
+
ext_lights = OpenStudio::Model::ExteriorLights.new(ext_lights_def,ext_lights_sch_other)
|
207
|
+
ext_lights.setMultiplier(multiplier)
|
208
|
+
ext_lights.setName(name_prefix)
|
209
|
+
ext_lights.setControlOption(exterior_lighting_properties["control_option"])
|
210
|
+
ext_lights.setEndUseSubcategory(name_prefix)
|
211
|
+
exterior_lights[name_prefix] = ext_lights
|
212
|
+
|
213
|
+
# update installed power
|
214
|
+
installed_power += power * multiplier
|
215
|
+
end
|
216
|
+
|
217
|
+
# add exterior lights for drive through windows
|
218
|
+
if area_length_count_hash[:drive_through_windows] > 0
|
219
|
+
|
220
|
+
# lighting values
|
221
|
+
multiplier = area_length_count_hash[:drive_through_windows]
|
222
|
+
power = exterior_lighting_properties["drive_through_windows_and_doors"]
|
223
|
+
name_prefix = "Drive Through Windows"
|
224
|
+
|
225
|
+
# create ext light def
|
226
|
+
OpenStudio.logFree(OpenStudio::Info, 'Prototype.Model.exterior_lights', "Added #{power} W/drive through window of lighting for #{multiplier} drie through windows.")
|
227
|
+
ext_lights_def = OpenStudio::Model::ExteriorLightsDefinition.new(self)
|
228
|
+
ext_lights_def.setName("#{name_prefix} Def (W/ft^2)")
|
229
|
+
ext_lights_def.setDesignLevel(power)
|
230
|
+
|
231
|
+
# create ext light inst
|
232
|
+
#creating exterior lights object
|
233
|
+
ext_lights = OpenStudio::Model::ExteriorLights.new(ext_lights_def,ext_lights_sch_other)
|
234
|
+
ext_lights.setMultiplier(multiplier)
|
235
|
+
ext_lights.setName(name_prefix)
|
236
|
+
ext_lights.setControlOption(exterior_lighting_properties["control_option"])
|
237
|
+
ext_lights.setEndUseSubcategory(name_prefix)
|
238
|
+
exterior_lights[name_prefix] = ext_lights
|
239
|
+
|
240
|
+
# update installed power
|
241
|
+
installed_power += power * multiplier
|
242
|
+
end
|
243
|
+
|
244
|
+
# todo - add_base_site_lighting_allowance (non landscaping tradable lighting)
|
245
|
+
# add exterior lights for drive through windows
|
246
|
+
if add_base_site_allowance
|
247
|
+
|
248
|
+
# lighting values
|
249
|
+
if not exterior_lighting_properties["base_site_allowance_power"].nil?
|
250
|
+
power = exterior_lighting_properties["base_site_allowance_power"]
|
251
|
+
elsif not exterior_lighting_properties["base_site_allowance_fraction"].nil?
|
252
|
+
power = exterior_lighting_properties["base_site_allowance_fraction"] * installed_power # shold be of allowed vs. installed, but hard to calculate
|
253
|
+
else
|
254
|
+
OpenStudio.logFree(OpenStudio::Info, 'Prototype.Model.exterior_lights', "Cannot determine target base site allowance power, will set to 0 W.")
|
255
|
+
power = 0.0
|
256
|
+
end
|
257
|
+
name_prefix = "Base Site Allowance"
|
258
|
+
|
259
|
+
# create ext light def
|
260
|
+
OpenStudio.logFree(OpenStudio::Info, 'Prototype.Model.exterior_lights', "Added #{power} W of non landscape tradable exterior lighting. Wil follow occupancy setback reduction.")
|
261
|
+
ext_lights_def = OpenStudio::Model::ExteriorLightsDefinition.new(self)
|
262
|
+
ext_lights_def.setName("#{name_prefix} Def (W)")
|
263
|
+
ext_lights_def.setDesignLevel(power)
|
264
|
+
|
265
|
+
# create ext light inst
|
266
|
+
#creating exterior lights object
|
267
|
+
ext_lights = OpenStudio::Model::ExteriorLights.new(ext_lights_def,ext_lights_sch_other)
|
268
|
+
ext_lights.setName(name_prefix)
|
269
|
+
ext_lights.setControlOption(exterior_lighting_properties["control_option"])
|
270
|
+
ext_lights.setEndUseSubcategory(name_prefix)
|
271
|
+
exterior_lights[name_prefix] = ext_lights
|
272
|
+
|
273
|
+
# don't need to update installed power for this
|
274
|
+
end
|
275
|
+
|
276
|
+
return exterior_lights
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
# get exterior lighting area's, distances, and counts
|
281
|
+
#
|
282
|
+
# @return [hash] hash of exterior lighting value types and building type and model specific values
|
283
|
+
# @todo - add code in to determine number of entries and canopy area from model geoemtry
|
284
|
+
# @todo - come up with better logic for entry widths
|
285
|
+
def create_exterior_lighting_area_length_count_hash(template,space_type_hash,use_model_for_entries_and_canopies)
|
286
|
+
|
287
|
+
area_length_count_hash = {}
|
288
|
+
|
289
|
+
# populate building_type_hash, used to remap office
|
290
|
+
building_type_hash = {}
|
291
|
+
space_type_hash.each do |space_type,hash|
|
292
|
+
|
293
|
+
# update building_type_hash
|
294
|
+
if building_type_hash.has_key?(hash[:stds_bldg_type])
|
295
|
+
building_type_hash[hash[:stds_bldg_type]] += hash[:floor_area]
|
296
|
+
else
|
297
|
+
building_type_hash[hash[:stds_bldg_type]] = hash[:floor_area]
|
298
|
+
end
|
299
|
+
end
|
300
|
+
# rename Office to SmallOffice MediumOffice or LargeOffice
|
301
|
+
office_type = nil
|
302
|
+
if building_type_hash.has_key?("Office")
|
303
|
+
office_type = self.remap_office(building_type_hash["Office"])
|
304
|
+
end
|
305
|
+
|
306
|
+
# parking areas and drives area
|
307
|
+
parking_area_and_drives_area = 0.0
|
308
|
+
main_entries = 0.0
|
309
|
+
other_doors = 0.0
|
310
|
+
canopy_entry_area = 0.0
|
311
|
+
canopy_emergency_area = 0.0
|
312
|
+
drive_through_windows = 0.0
|
313
|
+
# run space_type_hash to get number of students and units and building type floor area totals
|
314
|
+
space_type_hash.each do |space_type,hash|
|
315
|
+
|
316
|
+
# rename space types as needed
|
317
|
+
if hash[:stds_bldg_type] == "Office"
|
318
|
+
building_type = office_type
|
319
|
+
else
|
320
|
+
building_type = hash[:stds_bldg_type]
|
321
|
+
end
|
322
|
+
|
323
|
+
# store floor area ip
|
324
|
+
floor_area_ip = OpenStudio::convert(hash[:floor_area],"m^2","ft^2").get
|
325
|
+
num_spots = 0.0
|
326
|
+
|
327
|
+
# load illuminated_parking_area_properties
|
328
|
+
search_criteria = {'building_type' => building_type}
|
329
|
+
illuminated_parking_area_lookup = self.find_object($os_standards['parking'], search_criteria)
|
330
|
+
if not illuminated_parking_area_lookup["building_area_per_spot"].nil?
|
331
|
+
num_spots += floor_area_ip / illuminated_parking_area_lookup["building_area_per_spot"].to_f
|
332
|
+
elsif not illuminated_parking_area_lookup["units_per_spot"].nil?
|
333
|
+
num_spots += hash[:num_units] / illuminated_parking_area_lookup["units_per_spot"].to_f
|
334
|
+
elsif not illuminated_parking_area_lookup["students_per_spot"].nil?
|
335
|
+
num_spots += hash[:num_students] / illuminated_parking_area_lookup["students_per_spot"].to_f
|
336
|
+
elsif not illuminated_parking_area_lookup["beds_per_spot"].nil?
|
337
|
+
num_spots += hash[:num_beds] / illuminated_parking_area_lookup["beds_per_spot"].to_f
|
338
|
+
else
|
339
|
+
OpenStudio.logFree(OpenStudio::Info, 'Prototype.Model.exterior_lights', "Unexpected key, can't calculate number of parking spots from #{illuminated_parking_area_lookup.keys.first}.")
|
340
|
+
end
|
341
|
+
parking_area_and_drives_area += num_spots * illuminated_parking_area_lookup["parking_area_per_spot"]
|
342
|
+
|
343
|
+
# load illuninated_parking_area_properties
|
344
|
+
search_criteria = {'building_type' => building_type}
|
345
|
+
exterior_lighting_assumptions_lookup = self.find_object($os_standards['entryways'], search_criteria)
|
346
|
+
|
347
|
+
# lookup doors
|
348
|
+
if use_model_for_entries_and_canopies
|
349
|
+
# todo - get number of entries and canopy size from model geometry
|
350
|
+
else
|
351
|
+
|
352
|
+
# no source for width of different entry types
|
353
|
+
main_entry_width_ip = 8 # ft
|
354
|
+
other_doors_width_ip = 4 # ft
|
355
|
+
|
356
|
+
# rollup not used
|
357
|
+
main_entries += (floor_area_ip/10000.0) * exterior_lighting_assumptions_lookup["entrance_doors_per_10,000"] * main_entry_width_ip
|
358
|
+
other_doors += (floor_area_ip/10000.0) * exterior_lighting_assumptions_lookup["others_doors_per_10,000"] * other_doors_width_ip
|
359
|
+
if not exterior_lighting_assumptions_lookup["floor_area_per_drive_through_window"].nil?
|
360
|
+
drive_through_windows += floor_area_ip / exterior_lighting_assumptions_lookup["floor_area_per_drive_through_window"].to_f
|
361
|
+
end
|
362
|
+
|
363
|
+
|
364
|
+
# if any space types of building type that has canopy, then use that value, don't add to count for additional space types
|
365
|
+
if not exterior_lighting_assumptions_lookup["entrance_canopies"].nil? and not exterior_lighting_assumptions_lookup["canopy_size"].nil?
|
366
|
+
canopy_entry_area = exterior_lighting_assumptions_lookup["entrance_canopies"] * exterior_lighting_assumptions_lookup["canopy_size"]
|
367
|
+
end
|
368
|
+
if not exterior_lighting_assumptions_lookup["emergency_canopies"].nil? and not exterior_lighting_assumptions_lookup["canopy_size"].nil?
|
369
|
+
canopy_emergency_area = exterior_lighting_assumptions_lookup["emergency_canopies"]* exterior_lighting_assumptions_lookup["canopy_size"]
|
370
|
+
end
|
371
|
+
|
372
|
+
end
|
373
|
+
|
374
|
+
end
|
375
|
+
|
376
|
+
# populate hash
|
377
|
+
area_length_count_hash[:parking_area_and_drives_area] = parking_area_and_drives_area
|
378
|
+
area_length_count_hash[:main_entries] = main_entries
|
379
|
+
area_length_count_hash[:other_doors] = other_doors
|
380
|
+
area_length_count_hash[:canopy_entry_area] = canopy_entry_area
|
381
|
+
area_length_count_hash[:canopy_emergency_area] = canopy_emergency_area
|
382
|
+
area_length_count_hash[:drive_through_windows] = drive_through_windows
|
383
|
+
|
384
|
+
# determine effective number of stories to find first above grade story exterior wall area
|
385
|
+
effective_num_stories = self.effective_num_stories
|
386
|
+
ground_story = effective_num_stories[:story_hash].keys[effective_num_stories[:below_grade]]
|
387
|
+
ground_story_ext_wall_area_si = effective_num_stories[:story_hash][ground_story][:ext_wall_area]
|
388
|
+
ground_story_ext_wall_area_ip = OpenStudio::convert(ground_story_ext_wall_area_si,"m^2","ft^2").get
|
389
|
+
|
390
|
+
# building_facades
|
391
|
+
# reference buildings uses first story and plenum area all around
|
392
|
+
# prototype uses Table 4.19 by building type lit facde vs. total facade.
|
393
|
+
area_length_count_hash[:building_facades] = ground_story_ext_wall_area_ip
|
394
|
+
|
395
|
+
return area_length_count_hash
|
396
|
+
|
397
|
+
end
|
398
|
+
|
399
|
+
end
|