openstudio-extension 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +2 -0
- data/Jenkinsfile +1 -1
- data/LICENSE.md +1 -1
- data/Rakefile +1 -1
- data/doc_templates/LICENSE.md +1 -1
- data/doc_templates/copyright_erb.txt +1 -1
- data/doc_templates/copyright_js.txt +1 -1
- data/doc_templates/copyright_ruby.txt +1 -1
- data/init_templates/openstudio_module.rb +1 -1
- data/init_templates/spec.rb +1 -1
- data/init_templates/spec_helper.rb +1 -1
- data/init_templates/version.rb +1 -1
- data/lib/change_log.rb +1 -1
- data/lib/measures/openstudio_extension_test_measure/LICENSE.md +1 -1
- data/lib/measures/openstudio_extension_test_measure/measure.rb +1 -1
- data/lib/measures/openstudio_extension_test_measure/measure.xml +12 -12
- data/lib/measures/openstudio_extension_test_measure/resources/os_lib_helper_methods.rb +15 -2
- data/lib/openstudio-extension.rb +1 -1
- data/lib/openstudio/extension.rb +1 -1
- data/lib/openstudio/extension/core/CreateResults.rb +1 -1
- data/lib/openstudio/extension/core/check_air_sys_temps.rb +1 -1
- data/lib/openstudio/extension/core/check_calibration.rb +1 -1
- data/lib/openstudio/extension/core/check_cond_zns.rb +1 -1
- data/lib/openstudio/extension/core/check_domestic_hot_water.rb +1 -1
- data/lib/openstudio/extension/core/check_envelope_conductance.rb +1 -1
- data/lib/openstudio/extension/core/check_eui_by_end_use.rb +1 -1
- data/lib/openstudio/extension/core/check_eui_reasonableness.rb +1 -1
- data/lib/openstudio/extension/core/check_fan_pwr.rb +1 -1
- data/lib/openstudio/extension/core/check_internal_loads.rb +1 -1
- data/lib/openstudio/extension/core/check_mech_sys_capacity.rb +1 -1
- data/lib/openstudio/extension/core/check_mech_sys_efficiency.rb +1 -1
- data/lib/openstudio/extension/core/check_mech_sys_part_load_eff.rb +1 -1
- data/lib/openstudio/extension/core/check_mech_sys_type.rb +1 -1
- data/lib/openstudio/extension/core/check_part_loads.rb +1 -1
- data/lib/openstudio/extension/core/check_placeholder.rb +1 -1
- data/lib/openstudio/extension/core/check_plant_cap.rb +1 -1
- data/lib/openstudio/extension/core/check_plant_temps.rb +1 -1
- data/lib/openstudio/extension/core/check_plenum_loads.rb +1 -1
- data/lib/openstudio/extension/core/check_pump_pwr.rb +1 -1
- data/lib/openstudio/extension/core/check_sch_coord.rb +1 -1
- data/lib/openstudio/extension/core/check_schedules.rb +1 -1
- data/lib/openstudio/extension/core/check_simultaneous_heating_and_cooling.rb +1 -1
- data/lib/openstudio/extension/core/check_supply_air_and_thermostat_temp_difference.rb +1 -1
- data/lib/openstudio/extension/core/check_weather_files.rb +1 -1
- data/lib/openstudio/extension/core/deer_vintages.rb +1 -1
- data/lib/openstudio/extension/core/os_lib_aedg_measures.rb +5 -5
- data/lib/openstudio/extension/core/os_lib_constructions.rb +1 -1
- data/lib/openstudio/extension/core/os_lib_geometry.rb +1 -1
- data/lib/openstudio/extension/core/os_lib_helper_methods.rb +15 -2
- data/lib/openstudio/extension/core/os_lib_hvac.rb +1 -1
- data/lib/openstudio/extension/core/os_lib_lighting_and_equipment.rb +1 -1
- data/lib/openstudio/extension/core/os_lib_model_generation.rb +351 -207
- data/lib/openstudio/extension/core/os_lib_model_simplification.rb +1 -1
- data/lib/openstudio/extension/core/os_lib_outdoorair_and_infiltration.rb +1 -1
- data/lib/openstudio/extension/core/os_lib_reporting_qaqc.rb +1 -1
- data/lib/openstudio/extension/core/os_lib_schedules.rb +1 -1
- data/lib/openstudio/extension/rake_task.rb +1 -1
- data/lib/openstudio/extension/runner.rb +17 -5
- data/lib/openstudio/extension/runner_config.rb +1 -1
- data/lib/openstudio/extension/version.rb +2 -2
- data/openstudio-extension.gemspec +6 -5
- metadata +29 -16
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -204,7 +204,7 @@ module OsLib_AedgMeasures
|
|
204
204
|
@aedgK12HowToTipHash['EL20'] = 'EL20 Twenty-Four Hour Lighting'
|
205
205
|
@aedgK12HowToTipHash['EL21'] = 'EL21 Exterior Lighting Power-Parking Lots and Drives'
|
206
206
|
@aedgK12HowToTipHash['EL22'] = 'EL22 Exterior Lighting Power-Walkways'
|
207
|
-
@aedgK12HowToTipHash['EL23'] = 'EL23 Decorative
|
207
|
+
@aedgK12HowToTipHash['EL23'] = 'EL23 Decorative Facade Lighting'
|
208
208
|
@aedgK12HowToTipHash['EL24'] = 'EL24 Sources'
|
209
209
|
@aedgK12HowToTipHash['EL25'] = 'EL25 Controls'
|
210
210
|
|
@@ -273,7 +273,7 @@ module OsLib_AedgMeasures
|
|
273
273
|
|
274
274
|
# commissioning tips
|
275
275
|
@aedgK12HowToTipHash['QA01'] = 'QA1 Design and Construction Team'
|
276
|
-
@aedgK12HowToTipHash['QA02'] = 'QA2 Owner
|
276
|
+
@aedgK12HowToTipHash['QA02'] = 'QA2 Owner\'s Project Requirements and Basis of Design'
|
277
277
|
@aedgK12HowToTipHash['QA03'] = 'QA3 Selection of Quality Assurance Provider'
|
278
278
|
@aedgK12HowToTipHash['QA04'] = 'QA4 Design and Construction Schedule'
|
279
279
|
@aedgK12HowToTipHash['QA05'] = 'QA5 Design Review'
|
@@ -398,7 +398,7 @@ module OsLib_AedgMeasures
|
|
398
398
|
aedgSmMdOffHowToTipHash['EL20'] = 'EL20 Twenty-Four Hour Lighting'
|
399
399
|
aedgSmMdOffHowToTipHash['EL21'] = 'EL21 Exterior Lighting Power-Parking Lots and Drives'
|
400
400
|
aedgSmMdOffHowToTipHash['EL22'] = 'EL22 Exterior Lighting Power-Walkways'
|
401
|
-
aedgSmMdOffHowToTipHash['EL23'] = 'EL23 Decorative
|
401
|
+
aedgSmMdOffHowToTipHash['EL23'] = 'EL23 Decorative Facade Lighting'
|
402
402
|
aedgSmMdOffHowToTipHash['EL24'] = 'EL24 Sources'
|
403
403
|
aedgSmMdOffHowToTipHash['EL25'] = 'EL25 Controls'
|
404
404
|
|
@@ -463,7 +463,7 @@ Gas-Fired Boiler"
|
|
463
463
|
# commissioning tips
|
464
464
|
aedgSmMdOffHowToTipHash['QA01'] = 'QA1 Selecting the Design and Construction Team'
|
465
465
|
aedgSmMdOffHowToTipHash['QA02'] = 'QA2 Selecting the QA Provider'
|
466
|
-
aedgSmMdOffHowToTipHash['QA03'] = 'QA3 Owner
|
466
|
+
aedgSmMdOffHowToTipHash['QA03'] = 'QA3 Owner\'s Project Requirements (OPR) and Basis of Design (BoD)'
|
467
467
|
aedgSmMdOffHowToTipHash['QA04'] = 'QA4 Design and Construction Schedule'
|
468
468
|
aedgSmMdOffHowToTipHash['QA05'] = 'QA5 Design Review'
|
469
469
|
aedgSmMdOffHowToTipHash['QA06'] = 'QA6 Defining QA at Pre-Bid'
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -265,7 +265,20 @@ module OsLib_HelperMethods
|
|
265
265
|
result = measure_step.result.get
|
266
266
|
result.stepValues.each do |arg|
|
267
267
|
name = arg.name
|
268
|
-
value
|
268
|
+
# check if value, double, int, or bool
|
269
|
+
value_type = arg.variantType.valueDescription
|
270
|
+
if value_type == "Double"
|
271
|
+
value = arg.valueAsDouble
|
272
|
+
elsif value_type == "Integer"
|
273
|
+
value = arg.valueAsInteger
|
274
|
+
elsif value_type == "Boolean"
|
275
|
+
value = arg.valueAsBoolean
|
276
|
+
elsif value_type == "String"
|
277
|
+
value = arg.valueAsString
|
278
|
+
else
|
279
|
+
# catchall for unexpected value types
|
280
|
+
value = arg.valueAsVariant.to_s
|
281
|
+
end
|
269
282
|
if name == arg_name
|
270
283
|
arg_name_value[:value] = value
|
271
284
|
arg_name_value[:measure_name] = measure_name
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,8 @@
|
|
1
|
+
# ComStock(TM), Copyright (c) 2020 Alliance for Sustainable Energy, LLC. All rights reserved.
|
2
|
+
# See top level LICENSE.txt file for license terms.
|
3
|
+
|
1
4
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
5
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
6
|
# All rights reserved.
|
4
7
|
# Redistribution and use in source and binary forms, with or without
|
5
8
|
# modification, are permitted provided that the following conditions are met:
|
@@ -37,7 +40,6 @@ module OsLib_ModelGeneration
|
|
37
40
|
# simple list of building types that are valid for get_space_types_from_building_type
|
38
41
|
# for general public use use extended = false
|
39
42
|
def get_building_types(extended = false)
|
40
|
-
|
41
43
|
# get building_types
|
42
44
|
if extended
|
43
45
|
doe = get_doe_building_types(true)
|
@@ -127,7 +129,6 @@ module OsLib_ModelGeneration
|
|
127
129
|
# simple list of templates that are valid for get_space_types_from_building_type
|
128
130
|
# for general public use use extended = false
|
129
131
|
def get_templates(extended = false)
|
130
|
-
|
131
132
|
# get templates
|
132
133
|
if extended
|
133
134
|
doe = get_doe_templates(true)
|
@@ -157,6 +158,12 @@ module OsLib_ModelGeneration
|
|
157
158
|
array << '90.1-2007'
|
158
159
|
array << '90.1-2010'
|
159
160
|
array << '90.1-2013'
|
161
|
+
array << 'ComStock DOE Ref Pre-1980'
|
162
|
+
array << 'ComStock DOE Ref 1980-2004'
|
163
|
+
array << 'ComStock 90.1-2004'
|
164
|
+
array << 'ComStock 90.1-2007'
|
165
|
+
array << 'ComStock 90.1-2010'
|
166
|
+
array << 'ComStock 90.1-2013'
|
160
167
|
if extended
|
161
168
|
# array << '189.1-2009' # if turn this on need to update space_type_array for RetailStripmall
|
162
169
|
array << 'NREL ZNE Ready 2017'
|
@@ -228,10 +235,9 @@ module OsLib_ModelGeneration
|
|
228
235
|
# get_doe_climate_zones
|
229
236
|
# for general public use use extended = false
|
230
237
|
def get_doe_climate_zones(extended = false, extra = nil)
|
231
|
-
|
232
238
|
# Lookup From Model should be added as an option where appropriate in the measure
|
233
239
|
cz_choices = OpenStudio::StringVector.new
|
234
|
-
if extra
|
240
|
+
if !extra.nil?
|
235
241
|
cz_choices << extra
|
236
242
|
end
|
237
243
|
cz_choices << 'ASHRAE 169-2013-1A'
|
@@ -262,10 +268,9 @@ module OsLib_ModelGeneration
|
|
262
268
|
# get_deer_climate_zones
|
263
269
|
# for general public use use extended = false
|
264
270
|
def get_deer_climate_zones(extended = false, extra = nil)
|
265
|
-
|
266
271
|
# Lookup From Model should be added as an option where appropriate in the measure
|
267
272
|
cz_choices = OpenStudio::StringVector.new
|
268
|
-
if extra
|
273
|
+
if !extra.nil?
|
269
274
|
cz_choices << extra
|
270
275
|
end
|
271
276
|
cz_choices << 'CEC T24-CEC1'
|
@@ -309,27 +314,27 @@ module OsLib_ModelGeneration
|
|
309
314
|
primary_footprint = 73958.0
|
310
315
|
primary_p = 619.0 # wrote measure using calculate_perimeter method in os_lib_geometry
|
311
316
|
primary_ns_ew_ratio = 2.829268293 # estimated from ratio of ns/ew total wall area
|
312
|
-
primary_width = Math.sqrt(primary_footprint/primary_ns_ew_ratio)
|
317
|
+
primary_width = Math.sqrt(primary_footprint / primary_ns_ew_ratio)
|
313
318
|
primary_p_min = 2 * (primary_width + primary_width / primary_footprint)
|
314
319
|
primary_p_mult = primary_p / primary_p_min
|
315
320
|
|
316
321
|
secondary_footprint = 210887.0 / 2.0 # floor area divided by area instead of true footprint 128112.0)
|
317
322
|
secondary_p = 708.0 # wrote measure using calculate_perimeter method in os_lib_geometry
|
318
323
|
secondary_ns_ew_ratio = 2.069230769 # estimated from ratio of ns/ew total wall area
|
319
|
-
secondary_width = Math.sqrt(secondary_footprint/secondary_ns_ew_ratio)
|
324
|
+
secondary_width = Math.sqrt(secondary_footprint / secondary_ns_ew_ratio)
|
320
325
|
secondary_p_min = 2 * (secondary_width + secondary_width / secondary_footprint)
|
321
326
|
secondary_p_mult = secondary_p / secondary_p_min
|
322
327
|
|
323
328
|
outpatient_footprint = 40946.0 / 3.0 # floor area divided by area instead of true footprint 17872.0)
|
324
329
|
outpatient_p = 537.0 # wrote measure using calculate_perimeter method in os_lib_geometry
|
325
330
|
outpatient_ns_ew_ratio = 1.56448737 # estimated from ratio of ns/ew total wall area
|
326
|
-
outpatient_width = Math.sqrt(outpatient_footprint/outpatient_ns_ew_ratio)
|
327
|
-
outpatient_p_min = 2 * (outpatient_width + outpatient_footprint/outpatient_width)
|
331
|
+
outpatient_width = Math.sqrt(outpatient_footprint / outpatient_ns_ew_ratio)
|
332
|
+
outpatient_p_min = 2 * (outpatient_width + outpatient_footprint / outpatient_width)
|
328
333
|
outpatient_p_mult = outpatient_p / outpatient_p_min
|
329
334
|
|
330
|
-
#primary_aspet_ratio = calc_aspect_ratio(73958.0, 2060.0)
|
331
|
-
#secondary_aspet_ratio = calc_aspect_ratio(128112.0, 2447.0)
|
332
|
-
#outpatient_aspet_ratio = calc_aspect_ratio(14782.0, 588.0)
|
335
|
+
# primary_aspet_ratio = calc_aspect_ratio(73958.0, 2060.0)
|
336
|
+
# secondary_aspet_ratio = calc_aspect_ratio(128112.0, 2447.0)
|
337
|
+
# outpatient_aspet_ratio = calc_aspect_ratio(14782.0, 588.0)
|
333
338
|
supermarket_a = 45001.0
|
334
339
|
supermarket_p = 866.0
|
335
340
|
supermarket_wwr = 1880.0 / (supermarket_p * 20.0)
|
@@ -402,13 +407,13 @@ module OsLib_ModelGeneration
|
|
402
407
|
# TODO: - Confirm that these work for all standards
|
403
408
|
# DOE Prototypes
|
404
409
|
if building_type == 'SecondarySchool'
|
405
|
-
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004'].include?(template)
|
410
|
+
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004', 'ComStock DOE Ref Pre-1980', 'ComStock DOE Ref 1980-2004'].include?(template)
|
406
411
|
hash['Auditorium'] = { ratio: 0.0504, space_type_gen: true, default: false, story_height: 26.0 }
|
407
412
|
hash['Cafeteria'] = { ratio: 0.0319, space_type_gen: true, default: false }
|
408
413
|
hash['Classroom'] = { ratio: 0.3528, space_type_gen: true, default: true }
|
409
414
|
hash['Corridor'] = { ratio: 0.2144, space_type_gen: true, default: false, circ: true }
|
410
|
-
hash['Gym'] = { ratio: 0.1009, space_type_gen: true, default: false
|
411
|
-
hash['Gym - audience'] = { ratio: 0.0637, space_type_gen: true, default: false
|
415
|
+
hash['Gym'] = { ratio: 0.1009, space_type_gen: true, default: false, story_height: 26.0 }
|
416
|
+
hash['Gym - audience'] = { ratio: 0.0637, space_type_gen: true, default: false, story_height: 26.0 }
|
412
417
|
hash['Kitchen'] = { ratio: 0.0110, space_type_gen: true, default: false }
|
413
418
|
hash['Library'] = { ratio: 0.0429, space_type_gen: true, default: false }
|
414
419
|
hash['Lobby'] = { ratio: 0.0214, space_type_gen: true, default: false }
|
@@ -421,7 +426,7 @@ module OsLib_ModelGeneration
|
|
421
426
|
hash['Classroom'] = { ratio: 0.3041, space_type_gen: true, default: true }
|
422
427
|
hash['ComputerRoom'] = { ratio: 0.0487, space_type_gen: true, default: true }
|
423
428
|
hash['Corridor'] = { ratio: 0.2144, space_type_gen: true, default: false, circ: true }
|
424
|
-
hash['Gym'] = { ratio: 0.1646, space_type_gen: true, default: false
|
429
|
+
hash['Gym'] = { ratio: 0.1646, space_type_gen: true, default: false, story_height: 26.0 }
|
425
430
|
hash['Kitchen'] = { ratio: 0.0110, space_type_gen: true, default: false }
|
426
431
|
hash['Library'] = { ratio: 0.0429, space_type_gen: true, default: false }
|
427
432
|
hash['Lobby'] = { ratio: 0.0214, space_type_gen: true, default: false }
|
@@ -430,7 +435,7 @@ module OsLib_ModelGeneration
|
|
430
435
|
hash['Restroom'] = { ratio: 0.0214, space_type_gen: true, default: false }
|
431
436
|
end
|
432
437
|
elsif building_type == 'PrimarySchool'
|
433
|
-
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004'].include?(template)
|
438
|
+
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004', 'ComStock DOE Ref Pre-1980', 'ComStock DOE Ref 1980-2004'].include?(template)
|
434
439
|
# updated to 2004 which includes library vs. pre-1980
|
435
440
|
hash['Cafeteria'] = { ratio: 0.0458, space_type_gen: true, default: false }
|
436
441
|
hash['Classroom'] = { ratio: 0.5610, space_type_gen: true, default: true }
|
@@ -448,7 +453,7 @@ module OsLib_ModelGeneration
|
|
448
453
|
hash['Classroom'] = { ratio: 0.4793, space_type_gen: true, default: true }
|
449
454
|
hash['ComputerRoom'] = { ratio: 0.0236, space_type_gen: true, default: true }
|
450
455
|
hash['Corridor'] = { ratio: 0.1633, space_type_gen: true, default: false, circ: true }
|
451
|
-
hash['Gym'] = { ratio: 0.0520, space_type_gen: true, default: false}
|
456
|
+
hash['Gym'] = { ratio: 0.0520, space_type_gen: true, default: false }
|
452
457
|
hash['Kitchen'] = { ratio: 0.0244, space_type_gen: true, default: false }
|
453
458
|
hash['Library'] = { ratio: 0.0581, space_type_gen: true, default: false }
|
454
459
|
hash['Lobby'] = { ratio: 0.0249, space_type_gen: true, default: false }
|
@@ -494,7 +499,7 @@ module OsLib_ModelGeneration
|
|
494
499
|
hash['WholeBuilding - Md Office'] = { ratio: 0.0, space_type_gen: true, default: false }
|
495
500
|
end
|
496
501
|
elsif building_type == 'LargeOffice'
|
497
|
-
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004'].include?(template)
|
502
|
+
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004', 'ComStock DOE Ref Pre-1980', 'ComStock DOE Ref 1980-2004'].include?(template)
|
498
503
|
if whole_building
|
499
504
|
hash['WholeBuilding - Lg Office'] = { ratio: 1.0, space_type_gen: true, default: true }
|
500
505
|
else
|
@@ -538,7 +543,7 @@ module OsLib_ModelGeneration
|
|
538
543
|
end
|
539
544
|
end
|
540
545
|
elsif building_type == 'SmallHotel'
|
541
|
-
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004'].include?(template)
|
546
|
+
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004', 'ComStock DOE Ref Pre-1980', 'ComStock DOE Ref 1980-2004'].include?(template)
|
542
547
|
hash['Corridor'] = { ratio: 0.1313, space_type_gen: true, default: false, circ: true }
|
543
548
|
hash['Elec/MechRoom'] = { ratio: 0.0038, space_type_gen: true, default: false }
|
544
549
|
hash['ElevatorCore'] = { ratio: 0.0113, space_type_gen: true, default: false }
|
@@ -909,7 +914,6 @@ module OsLib_ModelGeneration
|
|
909
914
|
stories_flat = []
|
910
915
|
stories_flat_counter = 0
|
911
916
|
bar_hash[:stories].each_with_index do |(k, v), i|
|
912
|
-
#runner.registerInfo("STORY: k: #{k}, v: #{v}, index: #{i}")
|
913
917
|
# k is invalid in some cases, old story object that has been removed, should be from low to high including basement
|
914
918
|
# skip if source story insn't included in building area
|
915
919
|
if v[:story_included_in_building_area].nil? || (v[:story_included_in_building_area] == true)
|
@@ -1088,12 +1092,10 @@ module OsLib_ModelGeneration
|
|
1088
1092
|
|
1089
1093
|
# remove duplicate surfaces in a space (should be done after remove duplicate and collinear points)
|
1090
1094
|
model.getSpaces.sort.each do |space|
|
1091
|
-
|
1092
1095
|
# secondary array to compare against
|
1093
1096
|
surfaces_b = space.surfaces.sort
|
1094
1097
|
|
1095
1098
|
space.surfaces.sort.each do |surface_a|
|
1096
|
-
|
1097
1099
|
# delete from secondary array
|
1098
1100
|
surfaces_b.delete(surface_a)
|
1099
1101
|
|
@@ -1103,13 +1105,11 @@ module OsLib_ModelGeneration
|
|
1103
1105
|
runner.registerWarning("#{surface_a.name} and #{surface_b.name} in #{space.name} have duplicate geometry, removing #{surface_b.name}.")
|
1104
1106
|
surface_b.remove
|
1105
1107
|
elsif surface_a.reverseEqualVertices(surface_b)
|
1106
|
-
#
|
1108
|
+
# TODO: - add logic to determine which face naormal is reversed and which is correct
|
1107
1109
|
runner.registerWarning("#{surface_a.name} and #{surface_b.name} in #{space.name} have reversed geometry, removing #{surface_b.name}.")
|
1108
1110
|
surface_b.remove
|
1109
1111
|
end
|
1110
|
-
|
1111
1112
|
end
|
1112
|
-
|
1113
1113
|
end
|
1114
1114
|
end
|
1115
1115
|
|
@@ -1120,7 +1120,7 @@ module OsLib_ModelGeneration
|
|
1120
1120
|
model.getSpaces.sort.each do |space_a|
|
1121
1121
|
spaces_b.delete(space_a)
|
1122
1122
|
spaces_b.each do |space_b|
|
1123
|
-
#runner.registerInfo("Intersecting and matching surfaces between #{space_a.name} and #{space.name}")
|
1123
|
+
# runner.registerInfo("Intersecting and matching surfaces between #{space_a.name} and #{space.name}")
|
1124
1124
|
spaces_temp = OpenStudio::Model::SpaceVector.new
|
1125
1125
|
spaces_temp << space_a
|
1126
1126
|
spaces_temp << space_b
|
@@ -1130,7 +1130,7 @@ module OsLib_ModelGeneration
|
|
1130
1130
|
end
|
1131
1131
|
end
|
1132
1132
|
runner.registerInfo('Intersecting and matching surfaces in model, this will create additional geometry.')
|
1133
|
-
else #elsif bar_hash[:double_loaded_corridor] # only intersect spaces in each story, not between wtory
|
1133
|
+
else # elsif bar_hash[:double_loaded_corridor] # only intersect spaces in each story, not between wtory
|
1134
1134
|
model.getBuilding.buildingStories.sort.each do |story|
|
1135
1135
|
# intersect and surface match two pair by pair
|
1136
1136
|
spaces_b = story.spaces.sort
|
@@ -1161,7 +1161,7 @@ module OsLib_ModelGeneration
|
|
1161
1161
|
OpenStudio::Model.matchSurfaces(spaces)
|
1162
1162
|
runner.registerInfo('Intersecting and matching surfaces in model, this will create additional geometry.')
|
1163
1163
|
end
|
1164
|
-
else #elsif bar_hash[:double_loaded_corridor] # only intersect spaces in each story, not between wtory
|
1164
|
+
else # elsif bar_hash[:double_loaded_corridor] # only intersect spaces in each story, not between wtory
|
1165
1165
|
model.getBuilding.buildingStories.sort.each do |story|
|
1166
1166
|
story_spaces = OpenStudio::Model::SpaceVector.new
|
1167
1167
|
story.spaces.sort.each do |space|
|
@@ -1181,7 +1181,7 @@ module OsLib_ModelGeneration
|
|
1181
1181
|
model.getBuildingStorys.sort.each do |story|
|
1182
1182
|
next if !story.name.to_s.include?('Story B')
|
1183
1183
|
story.spaces.sort.each do |space|
|
1184
|
-
next if
|
1184
|
+
next if !new_spaces.include?(space)
|
1185
1185
|
space.surfaces.sort.each do |surface|
|
1186
1186
|
next if surface.surfaceType != 'Wall'
|
1187
1187
|
next if surface.outsideBoundaryCondition != 'Outdoors'
|
@@ -1194,9 +1194,9 @@ module OsLib_ModelGeneration
|
|
1194
1194
|
# sort stories (by name for now but need better way)
|
1195
1195
|
sorted_stories = {}
|
1196
1196
|
new_spaces.each do |space|
|
1197
|
-
next if !
|
1197
|
+
next if !space.buildingStory.is_initialized
|
1198
1198
|
story = space.buildingStory.get
|
1199
|
-
if !
|
1199
|
+
if !sorted_stories.key?(name.to_s)
|
1200
1200
|
sorted_stories[story.name.to_s] = story
|
1201
1201
|
end
|
1202
1202
|
end
|
@@ -1229,7 +1229,7 @@ module OsLib_ModelGeneration
|
|
1229
1229
|
party_wall_facades = stories_flat[i][:story_party_walls]
|
1230
1230
|
|
1231
1231
|
story.spaces.each do |space|
|
1232
|
-
next if
|
1232
|
+
next if !new_spaces.include?(space)
|
1233
1233
|
space.surfaces. each do |surface|
|
1234
1234
|
# set floor to adiabatic if requited
|
1235
1235
|
if adiabatic_floor && surface.surfaceType == 'Floor'
|
@@ -1325,7 +1325,6 @@ module OsLib_ModelGeneration
|
|
1325
1325
|
end
|
1326
1326
|
|
1327
1327
|
return new_spaces
|
1328
|
-
|
1329
1328
|
end
|
1330
1329
|
|
1331
1330
|
# make selected surfaces adiabatic
|
@@ -1393,7 +1392,7 @@ module OsLib_ModelGeneration
|
|
1393
1392
|
return bar
|
1394
1393
|
end
|
1395
1394
|
|
1396
|
-
def bar_hash_setup_run(runner,model,args,length,width,floor_height_si,center_of_footprint,space_types_hash,num_stories)
|
1395
|
+
def bar_hash_setup_run(runner, model, args, length, width, floor_height_si, center_of_footprint, space_types_hash, num_stories)
|
1397
1396
|
# create envelope
|
1398
1397
|
# populate bar_hash and create envelope with data from envelope_data_hash and user arguments
|
1399
1398
|
bar_hash = {}
|
@@ -1585,31 +1584,31 @@ module OsLib_ModelGeneration
|
|
1585
1584
|
roof_area = 0.0
|
1586
1585
|
new_spaces.each do |space|
|
1587
1586
|
space.surfaces.each do |surface|
|
1588
|
-
if surface.surfaceType ==
|
1587
|
+
if surface.surfaceType == 'Floor' && surface.outsideBoundaryCondition == 'Ground'
|
1589
1588
|
ground_floor_area += surface.netArea
|
1590
|
-
elsif surface.surfaceType ==
|
1589
|
+
elsif surface.surfaceType == 'RoofCeiling' && surface.outsideBoundaryCondition == 'Outdoors'
|
1591
1590
|
roof_area += surface.netArea
|
1592
1591
|
end
|
1593
1592
|
end
|
1594
1593
|
end
|
1595
|
-
#
|
1594
|
+
# TODO: - extend to address when top and or bottom story are not exposed via argument
|
1596
1595
|
if ground_floor_area > target_footprint + 0.001 || roof_area > target_footprint + 0.001
|
1597
|
-
#runner.registerError("Ground exposed floor or Roof area is larger than footprint, likely inter-floor surface matching and intersection error.")
|
1598
|
-
#return false
|
1596
|
+
# runner.registerError("Ground exposed floor or Roof area is larger than footprint, likely inter-floor surface matching and intersection error.")
|
1597
|
+
# return false
|
1599
1598
|
|
1600
1599
|
# not providing adiabatic work around when top story is partial story.
|
1601
1600
|
if args['num_stories_above_grade'].to_f != args['num_stories_above_grade'].ceil
|
1602
|
-
runner.registerError(
|
1601
|
+
runner.registerError('Ground exposed floor or Roof area is larger than footprint, likely inter-floor surface matching and intersection error.')
|
1603
1602
|
return false
|
1604
1603
|
else
|
1605
|
-
runner.registerInfo(
|
1604
|
+
runner.registerInfo('Ground exposed floor or Roof area is larger than footprint, likely inter-floor surface matching and intersection error, altering impacted surfaces boundary condition to be adiabatic.')
|
1606
1605
|
match_error = true
|
1607
1606
|
end
|
1608
1607
|
else
|
1609
1608
|
match_error = false
|
1610
1609
|
end
|
1611
1610
|
|
1612
|
-
#
|
1611
|
+
# TODO: - should be able to remove this fix after OpenStudio intersection issue is fixed. At that time turn the above message into an error with return false after it
|
1613
1612
|
if match_error
|
1614
1613
|
|
1615
1614
|
# identify z value of top and bottom story
|
@@ -1635,35 +1634,34 @@ module OsLib_ModelGeneration
|
|
1635
1634
|
if space.buildingStory.get.nominalZCoordinate.get > bottom_story
|
1636
1635
|
# change floors
|
1637
1636
|
space.surfaces.each do |surface|
|
1638
|
-
next if
|
1639
|
-
surface.setOutsideBoundaryCondition(
|
1637
|
+
next if !(surface.surfaceType == 'Floor' && surface.outsideBoundaryCondition == 'Ground')
|
1638
|
+
surface.setOutsideBoundaryCondition('Adiabatic')
|
1640
1639
|
end
|
1641
1640
|
end
|
1642
1641
|
if space.buildingStory.get.nominalZCoordinate.get < top_story
|
1643
1642
|
# change ceilings
|
1644
1643
|
space.surfaces.each do |surface|
|
1645
|
-
next if
|
1646
|
-
surface.setOutsideBoundaryCondition(
|
1644
|
+
next if !(surface.surfaceType == 'RoofCeiling' && surface.outsideBoundaryCondition == 'Outdoors')
|
1645
|
+
surface.setOutsideBoundaryCondition('Adiabatic')
|
1647
1646
|
end
|
1648
1647
|
end
|
1649
1648
|
end
|
1650
1649
|
end
|
1651
1650
|
end
|
1652
1651
|
|
1653
|
-
#
|
1654
|
-
|
1655
|
-
def bar_from_building_type_ratios(model, runner, user_arguments)
|
1652
|
+
# bar_arg_check_setup
|
1653
|
+
def bar_arg_check_setup(model, runner, user_arguments, building_type_ratios = true)
|
1656
1654
|
|
1657
1655
|
# assign the user inputs to variables
|
1658
1656
|
args = OsLib_HelperMethods.createRunVariables(runner, model, user_arguments, arguments(model))
|
1659
1657
|
if !args then return false end
|
1660
1658
|
|
1661
1659
|
# add in arguments that may not be passed in
|
1662
|
-
if !args.
|
1663
|
-
args[
|
1660
|
+
if !args.key?('double_loaded_corridor')
|
1661
|
+
args['double_loaded_corridor'] = 'None' # use None when not in measure building type data may not contain this
|
1664
1662
|
end
|
1665
|
-
if !
|
1666
|
-
args[
|
1663
|
+
if !args.key?('perim_mult')
|
1664
|
+
args['perim_mult'] = 1.0 # will not make two bars for extended perimeter
|
1667
1665
|
end
|
1668
1666
|
|
1669
1667
|
# lookup and replace argument values from upstream measures
|
@@ -1689,10 +1687,12 @@ module OsLib_ModelGeneration
|
|
1689
1687
|
end
|
1690
1688
|
|
1691
1689
|
# check expected values of double arguments
|
1692
|
-
fraction_args = ['
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1690
|
+
fraction_args = ['wwr', 'party_wall_fraction']
|
1691
|
+
if building_type_ratios
|
1692
|
+
fraction_args << 'bldg_type_b_fract_bldg_area'
|
1693
|
+
fraction_args << 'bldg_type_c_fract_bldg_area'
|
1694
|
+
fraction_args << 'bldg_type_d_fract_bldg_area'
|
1695
|
+
end
|
1696
1696
|
fraction = OsLib_HelperMethods.checkDoubleAndIntegerArguments(runner, user_arguments, 'min' => 0.0, 'max' => 1.0, 'min_eq_bool' => true, 'max_eq_bool' => true, 'arg_array' => fraction_args)
|
1697
1697
|
|
1698
1698
|
positive_args = ['total_bldg_floor_area']
|
@@ -1709,49 +1709,25 @@ module OsLib_ModelGeneration
|
|
1709
1709
|
'party_wall_stories_east',
|
1710
1710
|
'party_wall_stories_west',
|
1711
1711
|
'single_floor_area',
|
1712
|
-
'bar_width'
|
1712
|
+
'bar_width']
|
1713
1713
|
non_neg = OsLib_HelperMethods.checkDoubleAndIntegerArguments(runner, user_arguments, 'min' => 0.0, 'max' => nil, 'min_eq_bool' => true, 'max_eq_bool' => false, 'arg_array' => non_neg_args)
|
1714
1714
|
|
1715
1715
|
# return false if any errors fail
|
1716
1716
|
if !fraction then return false end
|
1717
1717
|
if !positive then return false end
|
1718
|
-
if !one_or_greater
|
1719
|
-
if !non_neg
|
1720
|
-
|
1721
|
-
# if aspect ratio, story height or wwr have argument value of 0 then use smart building type defaults
|
1722
|
-
building_form_defaults = building_form_defaults(args['bldg_type_a'])
|
1718
|
+
return false if !one_or_greater
|
1719
|
+
return false if !non_neg
|
1723
1720
|
|
1724
|
-
|
1725
|
-
defaulted_args = []
|
1721
|
+
return args
|
1726
1722
|
|
1727
|
-
|
1728
|
-
args['ns_to_ew_ratio'] = building_form_defaults[:aspect_ratio]
|
1729
|
-
runner.registerInfo("0.0 value for aspect ratio will be replaced with smart default for #{args['bldg_type_a']} of #{building_form_defaults[:aspect_ratio]}.")
|
1730
|
-
end
|
1723
|
+
end
|
1731
1724
|
|
1732
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
args['perim_mult'] = 1.0
|
1736
|
-
else
|
1737
|
-
args['perim_mult'] = building_form_defaults[:perim_mult]
|
1738
|
-
end
|
1739
|
-
runner.registerInfo("0.0 value for minimum perimeter multiplier will be replaced with smart default for #{args['bldg_type_a']} of #{building_form_defaults[:perim_mult]}.")
|
1740
|
-
elsif args['perim_mult'] < 1.0
|
1741
|
-
runner.registerError("Other than the smart default value of 0, the minimum perimeter multiplier should be equal to 1.0 or greater.")
|
1742
|
-
return false
|
1743
|
-
end
|
1725
|
+
# bar_from_building_type_ratios
|
1726
|
+
# used for varieties of measures that create bar from building type ratios
|
1727
|
+
def bar_from_building_type_ratios(model, runner, user_arguments)
|
1744
1728
|
|
1745
|
-
|
1746
|
-
|
1747
|
-
runner.registerInfo("0.0 value for floor height will be replaced with smart default for #{args['bldg_type_a']} of #{building_form_defaults[:typical_story]}.")
|
1748
|
-
defaulted_args << 'floor_height'
|
1749
|
-
end
|
1750
|
-
# because of this can't set wwr to 0.0. If that is desired then we can change this to check for 1.0 instead of 0.0
|
1751
|
-
if args['wwr'] == 0.0
|
1752
|
-
args['wwr'] = building_form_defaults[:wwr]
|
1753
|
-
runner.registerInfo("0.0 value for window to wall ratio will be replaced with smart default for #{args['bldg_type_a']} of #{building_form_defaults[:wwr]}.")
|
1754
|
-
end
|
1729
|
+
# prep arguments
|
1730
|
+
args = bar_arg_check_setup(model,runner,user_arguments)
|
1755
1731
|
|
1756
1732
|
# check that sum of fractions for b,c, and d is less than 1.0 (so something is left for primary building type)
|
1757
1733
|
bldg_type_a_fract_bldg_area = 1.0 - args['bldg_type_b_fract_bldg_area'] - args['bldg_type_c_fract_bldg_area'] - args['bldg_type_d_fract_bldg_area']
|
@@ -1761,7 +1737,7 @@ module OsLib_ModelGeneration
|
|
1761
1737
|
end
|
1762
1738
|
|
1763
1739
|
# Make the standard applier
|
1764
|
-
standard = Standard.build(
|
1740
|
+
standard = Standard.build((args['template']).to_s)
|
1765
1741
|
|
1766
1742
|
# report initial condition of model
|
1767
1743
|
runner.registerInitialCondition("The building started with #{model.getSpaces.size} spaces.")
|
@@ -1791,14 +1767,14 @@ module OsLib_ModelGeneration
|
|
1791
1767
|
# gather data for bldg_type_a
|
1792
1768
|
building_type_hash[args['bldg_type_a']] = {}
|
1793
1769
|
building_type_hash[args['bldg_type_a']][:frac_bldg_area] = bldg_type_a_fract_bldg_area
|
1794
|
-
#building_type_hash[args['bldg_type_a']][:num_units] = args['bldg_type_a_num_units']
|
1770
|
+
# building_type_hash[args['bldg_type_a']][:num_units] = args['bldg_type_a_num_units']
|
1795
1771
|
building_type_hash[args['bldg_type_a']][:space_types] = get_space_types_from_building_type(args['bldg_type_a'], args['template'], true)
|
1796
1772
|
|
1797
1773
|
# gather data for bldg_type_b
|
1798
1774
|
if args['bldg_type_b_fract_bldg_area'] > 0
|
1799
1775
|
building_type_hash[args['bldg_type_b']] = {}
|
1800
1776
|
building_type_hash[args['bldg_type_b']][:frac_bldg_area] = args['bldg_type_b_fract_bldg_area']
|
1801
|
-
#building_type_hash[args['bldg_type_b']][:num_units] = args['bldg_type_b_num_units']
|
1777
|
+
# building_type_hash[args['bldg_type_b']][:num_units] = args['bldg_type_b_num_units']
|
1802
1778
|
building_type_hash[args['bldg_type_b']][:space_types] = get_space_types_from_building_type(args['bldg_type_b'], args['template'], true)
|
1803
1779
|
end
|
1804
1780
|
|
@@ -1806,7 +1782,7 @@ module OsLib_ModelGeneration
|
|
1806
1782
|
if args['bldg_type_c_fract_bldg_area'] > 0
|
1807
1783
|
building_type_hash[args['bldg_type_c']] = {}
|
1808
1784
|
building_type_hash[args['bldg_type_c']][:frac_bldg_area] = args['bldg_type_c_fract_bldg_area']
|
1809
|
-
#building_type_hash[args['bldg_type_c']][:num_units] = args['bldg_type_c_num_units']
|
1785
|
+
# building_type_hash[args['bldg_type_c']][:num_units] = args['bldg_type_c_num_units']
|
1810
1786
|
building_type_hash[args['bldg_type_c']][:space_types] = get_space_types_from_building_type(args['bldg_type_c'], args['template'], true)
|
1811
1787
|
end
|
1812
1788
|
|
@@ -1814,10 +1790,145 @@ module OsLib_ModelGeneration
|
|
1814
1790
|
if args['bldg_type_d_fract_bldg_area'] > 0
|
1815
1791
|
building_type_hash[args['bldg_type_d']] = {}
|
1816
1792
|
building_type_hash[args['bldg_type_d']][:frac_bldg_area] = args['bldg_type_d_fract_bldg_area']
|
1817
|
-
#building_type_hash[args['bldg_type_d']][:num_units] = args['bldg_type_d_num_units']
|
1793
|
+
# building_type_hash[args['bldg_type_d']][:num_units] = args['bldg_type_d_num_units']
|
1818
1794
|
building_type_hash[args['bldg_type_d']][:space_types] = get_space_types_from_building_type(args['bldg_type_d'], args['template'], true)
|
1819
1795
|
end
|
1820
1796
|
|
1797
|
+
# call bar_from_building_space_type_ratios to generate bar
|
1798
|
+
bar_from_space_type_ratios(model, runner, user_arguments, args, building_type_hash)
|
1799
|
+
|
1800
|
+
return true
|
1801
|
+
|
1802
|
+
end
|
1803
|
+
|
1804
|
+
# bar_from_space_type_ratios
|
1805
|
+
# used for varieties of measures that create bar from space type or building type ratios
|
1806
|
+
# args and building_type_hash should both be nil or neither shoould be nill
|
1807
|
+
def bar_from_space_type_ratios(model, runner, user_arguments, args = nil, building_type_hash = nil)
|
1808
|
+
|
1809
|
+
# do not setup arguments if they were already passed in to this method
|
1810
|
+
if args.nil?
|
1811
|
+
# prep arguments
|
1812
|
+
args = bar_arg_check_setup(model,runner,user_arguments,false) # false stops it from checking args on used in bar_from_building_type_ratios
|
1813
|
+
|
1814
|
+
# identify primary building type for building form defaults
|
1815
|
+
primary_building_type = "PrimarySchool" # see what building type represents the most floro area
|
1816
|
+
building_form_defaults = building_form_defaults(primary_building_type)
|
1817
|
+
|
1818
|
+
# process arg into hash
|
1819
|
+
space_type_hash_name = {}
|
1820
|
+
args['space_type_hash_string'][0..-1].split(/, /).each { |entry| entryMap = entry.split(/=>/); value_str = entryMap[1]; space_type_hash_name[entryMap[0].strip[0..-1].to_s] = value_str.nil? ? '' : value_str.strip[0..-1].to_f }
|
1821
|
+
|
1822
|
+
# create building type hasn from space type ratios
|
1823
|
+
building_type_hash = {}
|
1824
|
+
building_type_fraction_of_building = 0.0
|
1825
|
+
space_type_hash_name.each do |building_space_type,ratio|
|
1826
|
+
building_type = building_space_type.split("|")[0].strip
|
1827
|
+
space_type = building_space_type.split("|")[1].strip
|
1828
|
+
|
1829
|
+
# harvest height and circ info from get_space_types_from_building_type(building_type, template, whole_building = true)
|
1830
|
+
building_type_lookup_info = get_space_types_from_building_type(building_type,args['template'])
|
1831
|
+
if building_type_lookup_info.size == 0
|
1832
|
+
runner.registerWarning("#{building_type} looks like an invalid building type for #{args['template']}")
|
1833
|
+
end
|
1834
|
+
space_type_info_hash = {}
|
1835
|
+
if building_type_lookup_info.key?(space_type)
|
1836
|
+
if building_type_lookup_info[space_type].key?(:story_height)
|
1837
|
+
space_type_info_hash[:story_height] = building_type_lookup_info[space_type][:story_height]
|
1838
|
+
end
|
1839
|
+
if building_type_lookup_info[space_type].key?(:default)
|
1840
|
+
space_type_info_hash[:default] = building_type_lookup_info[space_type][:default]
|
1841
|
+
end
|
1842
|
+
if building_type_lookup_info[space_type].key?(:circ)
|
1843
|
+
space_type_info_hash[:circ] = building_type_lookup_info[space_type][:circ]
|
1844
|
+
end
|
1845
|
+
else
|
1846
|
+
runner.registerWarning("#{space_type} looks like an invalid space type for #{building_type}")
|
1847
|
+
end
|
1848
|
+
|
1849
|
+
# extend harvested data with custom ratios from space type ratio string argument.
|
1850
|
+
if building_type_hash.key?(building_type)
|
1851
|
+
building_type_hash[building_type][:frac_bldg_area] += ratio
|
1852
|
+
space_type_info_hash[:ratio] = ratio
|
1853
|
+
building_type_hash[building_type][:space_types][space_type] = space_type_info_hash
|
1854
|
+
else
|
1855
|
+
building_type_hash[building_type] = {}
|
1856
|
+
building_type_hash[building_type][:frac_bldg_area] = ratio
|
1857
|
+
space_type_info_hash[:ratio] = ratio
|
1858
|
+
space_types = {}
|
1859
|
+
space_types[space_type] = space_type_info_hash
|
1860
|
+
building_type_hash[building_type][:space_types] = space_types
|
1861
|
+
end
|
1862
|
+
building_type_fraction_of_building += ratio
|
1863
|
+
end
|
1864
|
+
|
1865
|
+
# todo - confirm if this will get normalized up/down later of if I should fix or stop here instead of just a warning
|
1866
|
+
if building_type_fraction_of_building > 1.0
|
1867
|
+
runner.registerWarning("Sum of Space Type Ratio of #{building_type_fraction_of_building} is greater than the expected value of 1.0")
|
1868
|
+
elsif building_type_fraction_of_building < 1.0
|
1869
|
+
runner.registerWarning("Sum of Space Type Ratio of #{building_type_fraction_of_building} is less than the expected value of 1.0")
|
1870
|
+
end
|
1871
|
+
|
1872
|
+
else # else is used when bar_from_building_type_ratio is used
|
1873
|
+
|
1874
|
+
# if aspect ratio, story height or wwr have argument value of 0 then use smart building type defaults
|
1875
|
+
primary_building_type = args['bldg_type_a']
|
1876
|
+
|
1877
|
+
end
|
1878
|
+
|
1879
|
+
# get defaults for the primary building type
|
1880
|
+
building_form_defaults = building_form_defaults(primary_building_type)
|
1881
|
+
|
1882
|
+
# store list of defaulted items
|
1883
|
+
defaulted_args = []
|
1884
|
+
|
1885
|
+
if args['ns_to_ew_ratio'] == 0.0
|
1886
|
+
args['ns_to_ew_ratio'] = building_form_defaults[:aspect_ratio]
|
1887
|
+
runner.registerInfo("0.0 value for aspect ratio will be replaced with smart default for #{primary_building_type} of #{building_form_defaults[:aspect_ratio]}.")
|
1888
|
+
end
|
1889
|
+
|
1890
|
+
if args['perim_mult'] == 0.0
|
1891
|
+
# if this is not defined then use default of 1.0
|
1892
|
+
if !building_form_defaults.has_key?(:perim_mult)
|
1893
|
+
args['perim_mult'] = 1.0
|
1894
|
+
else
|
1895
|
+
args['perim_mult'] = building_form_defaults[:perim_mult]
|
1896
|
+
end
|
1897
|
+
runner.registerInfo("0.0 value for minimum perimeter multiplier will be replaced with smart default for #{primary_building_type} of #{building_form_defaults[:perim_mult]}.")
|
1898
|
+
elsif args['perim_mult'] < 1.0
|
1899
|
+
runner.registerError("Other than the smart default value of 0, the minimum perimeter multiplier should be equal to 1.0 or greater.")
|
1900
|
+
return false
|
1901
|
+
end
|
1902
|
+
|
1903
|
+
if args['floor_height'] == 0.0
|
1904
|
+
args['floor_height'] = building_form_defaults[:typical_story]
|
1905
|
+
runner.registerInfo("0.0 value for floor height will be replaced with smart default for #{primary_building_type} of #{building_form_defaults[:typical_story]}.")
|
1906
|
+
defaulted_args << 'floor_height'
|
1907
|
+
end
|
1908
|
+
# because of this can't set wwr to 0.0. If that is desired then we can change this to check for 1.0 instead of 0.0
|
1909
|
+
if args['wwr'] == 0.0
|
1910
|
+
args['wwr'] = building_form_defaults[:wwr]
|
1911
|
+
runner.registerInfo("0.0 value for window to wall ratio will be replaced with smart default for #{primary_building_type} of #{building_form_defaults[:wwr]}.")
|
1912
|
+
end
|
1913
|
+
|
1914
|
+
# Make the standard applier
|
1915
|
+
standard = Standard.build("#{args['template']}")
|
1916
|
+
|
1917
|
+
# report initial condition of model
|
1918
|
+
runner.registerInitialCondition("The building started with #{model.getSpaces.size} spaces.")
|
1919
|
+
|
1920
|
+
# determine of ns_ew needs to be mirrored
|
1921
|
+
mirror_ns_ew = false
|
1922
|
+
rotation = model.getBuilding.northAxis
|
1923
|
+
if rotation > 45.0 && rotation < 135.0
|
1924
|
+
mirror_ns_ew = true
|
1925
|
+
elsif rotation > 45.0 && rotation < 135.0
|
1926
|
+
mirror_ns_ew = true
|
1927
|
+
end
|
1928
|
+
|
1929
|
+
# remove non-resource objects not removed by removing the building
|
1930
|
+
remove_non_resource_objects(runner, model)
|
1931
|
+
|
1821
1932
|
# creating space types for requested building types
|
1822
1933
|
building_type_hash.each do |building_type, building_type_hash|
|
1823
1934
|
runner.registerInfo("Creating Space Types for #{building_type}.")
|
@@ -1840,8 +1951,8 @@ module OsLib_ModelGeneration
|
|
1840
1951
|
# set color
|
1841
1952
|
test = standard.space_type_apply_rendering_color(space_type) # this uses openstudio-standards
|
1842
1953
|
if !test
|
1843
|
-
#
|
1844
|
-
#runner.registerWarning("Could not find color for #{args['template']} #{space_type.name}")
|
1954
|
+
# TODO: - once fixed in standards un-comment this
|
1955
|
+
# runner.registerWarning("Could not find color for #{args['template']} #{space_type.name}")
|
1845
1956
|
end
|
1846
1957
|
|
1847
1958
|
# extend hash to hold new space type object
|
@@ -1869,7 +1980,7 @@ module OsLib_ModelGeneration
|
|
1869
1980
|
runner.registerWarning('User-defined single floor area was used for calculation of total building floor area')
|
1870
1981
|
# add warning if custom_height_bar is true and applicable building type is selected
|
1871
1982
|
if args['custom_height_bar']
|
1872
|
-
runner.registerWarning(
|
1983
|
+
runner.registerWarning('Cannot use custom height bar with single floor area method, will not create custom height bar.')
|
1873
1984
|
args['custom_height_bar'] = false
|
1874
1985
|
end
|
1875
1986
|
else
|
@@ -1884,8 +1995,7 @@ module OsLib_ModelGeneration
|
|
1884
1995
|
building_type_hash = building_type_hash.sort_by { |k, v| v[:frac_bldg_area] }
|
1885
1996
|
end
|
1886
1997
|
building_type_hash.each do |building_type, building_type_hash|
|
1887
|
-
|
1888
|
-
if args["double_loaded_corridor"] == "Primary Space Type"
|
1998
|
+
if args['double_loaded_corridor'] == 'Primary Space Type'
|
1889
1999
|
|
1890
2000
|
# see if building type has circulation space type, if so then merge that along with default space type into hash key in place of space type
|
1891
2001
|
default_st = nil
|
@@ -1900,8 +2010,8 @@ module OsLib_ModelGeneration
|
|
1900
2010
|
runner.registerInfo("Combining #{default_st} and #{circ_st} into a group representing a double loaded corridor")
|
1901
2011
|
|
1902
2012
|
# add new item
|
1903
|
-
building_type_hash[:space_types][
|
1904
|
-
double_loaded_st = building_type_hash[:space_types][
|
2013
|
+
building_type_hash[:space_types]['Double Loaded Corridor'] = {}
|
2014
|
+
double_loaded_st = building_type_hash[:space_types]['Double Loaded Corridor']
|
1905
2015
|
double_loaded_st[:ratio] = building_type_hash[:space_types][default_st][:ratio] + building_type_hash[:space_types][circ_st][:ratio]
|
1906
2016
|
double_loaded_st[:double_loaded_corridor] = true
|
1907
2017
|
double_loaded_st[:space_type] = model.getBuilding
|
@@ -1936,21 +2046,21 @@ module OsLib_ModelGeneration
|
|
1936
2046
|
multi_height_space_types_hash[space_type][:wwr] = hash[:wwr]
|
1937
2047
|
end
|
1938
2048
|
else
|
1939
|
-
|
1940
|
-
|
1941
|
-
|
1942
|
-
|
1943
|
-
|
1944
|
-
|
1945
|
-
|
1946
|
-
|
1947
|
-
|
2049
|
+
# only add wwr if 0 used for wwr arg and if space type has wwr as key
|
2050
|
+
space_types_hash[space_type] = { floor_area: final_floor_area, space_type: space_type }
|
2051
|
+
if hash.key?(:orig_ratio) then space_types_hash[space_type][:orig_ratio] = hash[:orig_ratio] end
|
2052
|
+
if args['wwr'] == 0 && hash.key?(:wwr)
|
2053
|
+
space_types_hash[space_type][:wwr] = hash[:wwr]
|
2054
|
+
end
|
2055
|
+
if hash[:double_loaded_corridor]
|
2056
|
+
space_types_hash[space_type][:children] = hash[:children]
|
2057
|
+
end
|
1948
2058
|
end
|
1949
2059
|
end
|
1950
2060
|
end
|
1951
2061
|
|
1952
2062
|
# resort if not sorted by building type
|
1953
|
-
if args['space_type_sort_logic'] ==
|
2063
|
+
if args['space_type_sort_logic'] == 'Size'
|
1954
2064
|
# added code to convert to hash. I use sort_by 3 other times, but those seem to be working fine as is now.
|
1955
2065
|
space_types_hash = Hash[space_types_hash.sort_by { |k, v| v[:floor_area] }]
|
1956
2066
|
end
|
@@ -1958,14 +2068,14 @@ module OsLib_ModelGeneration
|
|
1958
2068
|
# calculate targets for testing
|
1959
2069
|
target_areas = {} # used for checks
|
1960
2070
|
target_areas_cust_height = 0.0
|
1961
|
-
space_types_hash.each do |k,v|
|
2071
|
+
space_types_hash.each do |k, v|
|
1962
2072
|
if v.key?(:orig_ratio)
|
1963
2073
|
target_areas[k] = v[:orig_ratio] * total_bldg_floor_area_si
|
1964
2074
|
else
|
1965
2075
|
target_areas[k] = v[:floor_area]
|
1966
2076
|
end
|
1967
2077
|
end
|
1968
|
-
multi_height_space_types_hash.each do |k,v|
|
2078
|
+
multi_height_space_types_hash.each do |k, v|
|
1969
2079
|
if v.key?(:orig_ratio)
|
1970
2080
|
target_areas[k] = v[:orig_ratio] * total_bldg_floor_area_si
|
1971
2081
|
target_areas_cust_height += v[:orig_ratio] * total_bldg_floor_area_si
|
@@ -1980,19 +2090,19 @@ module OsLib_ModelGeneration
|
|
1980
2090
|
footprint_si = (total_bldg_floor_area_si - target_areas_cust_height) / num_stories.to_f
|
1981
2091
|
end
|
1982
2092
|
floor_height_si = OpenStudio.convert(args['floor_height'], 'ft', 'm').get
|
1983
|
-
min_allow_size = OpenStudio.convert(15.0,'ft','m').get
|
1984
|
-
specified_bar_width_si = OpenStudio.convert(args['bar_width'],'ft','m').get
|
2093
|
+
min_allow_size = OpenStudio.convert(15.0, 'ft', 'm').get
|
2094
|
+
specified_bar_width_si = OpenStudio.convert(args['bar_width'], 'ft', 'm').get
|
1985
2095
|
|
1986
2096
|
# set custom width
|
1987
2097
|
if specified_bar_width_si > 0
|
1988
|
-
runner.registerInfo(
|
2098
|
+
runner.registerInfo('Ignoring perimeter multiplier argument when non zero width argument is used')
|
1989
2099
|
if footprint_si / specified_bar_width_si >= min_allow_size
|
1990
2100
|
width = specified_bar_width_si
|
1991
2101
|
length = footprint_si / width
|
1992
2102
|
else
|
1993
2103
|
length = min_allow_size
|
1994
2104
|
width = footprint_si / length
|
1995
|
-
runner.registerWarning(
|
2105
|
+
runner.registerWarning('User specified width results in a length that is too short, adjusting width to be narrower than specified.')
|
1996
2106
|
end
|
1997
2107
|
width_cust_height = specified_bar_width_si
|
1998
2108
|
else
|
@@ -2002,29 +2112,29 @@ module OsLib_ModelGeneration
|
|
2002
2112
|
end
|
2003
2113
|
length_cust_height = target_areas_cust_height / width_cust_height
|
2004
2114
|
if args['perim_mult'] > 1.0 && target_areas_cust_height > 0.0
|
2005
|
-
#
|
2006
|
-
runner.registerWarning(
|
2115
|
+
# TODO: - update tests that hit this warning
|
2116
|
+
runner.registerWarning('Ignoring perimeter multiplier for bar that represents custom height spaces.')
|
2007
2117
|
end
|
2008
2118
|
|
2009
2119
|
# check if dual bar is needed
|
2010
2120
|
dual_bar = false
|
2011
2121
|
if specified_bar_width_si > 0.0 && args['bar_division_method'] == 'Multiple Space Types - Individual Stories Sliced'
|
2012
|
-
if length/width != args['ns_to_ew_ratio']
|
2013
|
-
|
2014
|
-
if args['ns_to_ew_ratio'] >= 1.0 && args['ns_to_ew_ratio'] > length/width
|
2015
|
-
runner.registerWarning("Can't meet target aspect ratio of #{args['ns_to_ew_ratio']}, Lowering it to #{length/width} ")
|
2016
|
-
args['ns_to_ew_ratio'] = length/width
|
2017
|
-
elsif args['ns_to_ew_ratio'] < 1.0 && args['ns_to_ew_ratio'] > length/width
|
2018
|
-
runner.registerWarning("Can't meet target aspect ratio of #{args['ns_to_ew_ratio']}, Increasing it to #{length/width} ")
|
2019
|
-
args['ns_to_ew_ratio'] = length/width
|
2122
|
+
if length / width != args['ns_to_ew_ratio']
|
2123
|
+
|
2124
|
+
if args['ns_to_ew_ratio'] >= 1.0 && args['ns_to_ew_ratio'] > length / width
|
2125
|
+
runner.registerWarning("Can't meet target aspect ratio of #{args['ns_to_ew_ratio']}, Lowering it to #{length / width} ")
|
2126
|
+
args['ns_to_ew_ratio'] = length / width
|
2127
|
+
elsif args['ns_to_ew_ratio'] < 1.0 && args['ns_to_ew_ratio'] > length / width
|
2128
|
+
runner.registerWarning("Can't meet target aspect ratio of #{args['ns_to_ew_ratio']}, Increasing it to #{length / width} ")
|
2129
|
+
args['ns_to_ew_ratio'] = length / width
|
2020
2130
|
else
|
2021
2131
|
# check if each bar would be longer then 15 feet, then set as dual bar and override perimeter multiplier
|
2022
|
-
length_alt1 = ((args['ns_to_ew_ratio'] * footprint_si) / width + 2 * args['ns_to_ew_ratio'] * width - 2 * width)/(1 + args['ns_to_ew_ratio'])
|
2132
|
+
length_alt1 = ((args['ns_to_ew_ratio'] * footprint_si) / width + 2 * args['ns_to_ew_ratio'] * width - 2 * width) / (1 + args['ns_to_ew_ratio'])
|
2023
2133
|
length_alt2 = length - length_alt1
|
2024
|
-
if [length_alt1,length_alt2].min >= min_allow_size
|
2134
|
+
if [length_alt1, length_alt2].min >= min_allow_size
|
2025
2135
|
dual_bar = true
|
2026
2136
|
else
|
2027
|
-
runner.registerInfo(
|
2137
|
+
runner.registerInfo('Second bar would be below minimum length, will model as single bar')
|
2028
2138
|
# swap length and width if single bar and aspect ratio less than 1
|
2029
2139
|
if args['ns_to_ew_ratio'] < 1.0
|
2030
2140
|
width = length
|
@@ -2034,7 +2144,7 @@ module OsLib_ModelGeneration
|
|
2034
2144
|
end
|
2035
2145
|
end
|
2036
2146
|
elsif args['perim_mult'] > 1.0 && args['bar_division_method'] == 'Multiple Space Types - Individual Stories Sliced'
|
2037
|
-
runner.registerInfo(
|
2147
|
+
runner.registerInfo('You selected a perimeter multiplier greater than 1.0 for a supported bar division method. This will result in two detached rectangular buildings if secondary bar meets minimum size requirements.')
|
2038
2148
|
dual_bar = true
|
2039
2149
|
elsif args['perim_mult'] > 1.0
|
2040
2150
|
runner.registerWarning("You selected a perimeter multiplier greater than 1.0 but didn't select a bar division method that supports this. The value for this argument will be ignored by the measure")
|
@@ -2058,7 +2168,7 @@ module OsLib_ModelGeneration
|
|
2058
2168
|
# custom quadratic equation to solve two bars with common width 2l^2 - p*l + 4a = 0
|
2059
2169
|
if target_perim**2 - 32 * footprint_si > 0
|
2060
2170
|
if specified_bar_width_si > 0
|
2061
|
-
runner.registerInfo(
|
2171
|
+
runner.registerInfo('Ignoring perimeter multiplier argument and using use specified bar width.')
|
2062
2172
|
dual_double_end_width = specified_bar_width_si
|
2063
2173
|
dual_double_end_length = footprint_si / dual_double_end_width
|
2064
2174
|
else
|
@@ -2067,7 +2177,7 @@ module OsLib_ModelGeneration
|
|
2067
2177
|
end
|
2068
2178
|
|
2069
2179
|
# now that stretched bar is made, determine where to split it and rotate
|
2070
|
-
bar_a_length = (args['ns_to_ew_ratio'] * (dual_double_end_length + dual_double_end_width) - dual_double_end_width)/(1 + args['ns_to_ew_ratio'])
|
2180
|
+
bar_a_length = (args['ns_to_ew_ratio'] * (dual_double_end_length + dual_double_end_width) - dual_double_end_width) / (1 + args['ns_to_ew_ratio'])
|
2071
2181
|
bar_b_length = dual_double_end_length - bar_a_length
|
2072
2182
|
area_a = bar_a_length * dual_double_end_width
|
2073
2183
|
area_b = bar_b_length * dual_double_end_width
|
@@ -2086,15 +2196,15 @@ module OsLib_ModelGeneration
|
|
2086
2196
|
adiabatic_dual_double_end_width = footprint_si / adiabatic_dual_double_end_length
|
2087
2197
|
# test for unexpected
|
2088
2198
|
unexpected = false
|
2089
|
-
if (target_area - adiabatic_dual_double_end_length*adiabatic_dual_double_end_width).abs > tol_testing then unexpected = true end
|
2199
|
+
if (target_area - adiabatic_dual_double_end_length * adiabatic_dual_double_end_width).abs > tol_testing then unexpected = true end
|
2090
2200
|
if specified_bar_width_si == 0
|
2091
2201
|
if (target_perim - (adiabatic_dual_double_end_length * 2 + adiabatic_dual_double_end_width * 2)).abs > tol_testing then unexpected = true end
|
2092
2202
|
end
|
2093
2203
|
if unexpected
|
2094
|
-
runner.registerWarning(
|
2204
|
+
runner.registerWarning('Unexpected values for dual rectangle adiabatic ends bar b.')
|
2095
2205
|
end
|
2096
2206
|
# now that stretched bar is made, determine where to split it and rotate
|
2097
|
-
adiabatic_bar_a_length = (args['ns_to_ew_ratio'] * (adiabatic_dual_double_end_length + adiabatic_dual_double_end_width))/(1 + args['ns_to_ew_ratio'])
|
2207
|
+
adiabatic_bar_a_length = (args['ns_to_ew_ratio'] * (adiabatic_dual_double_end_length + adiabatic_dual_double_end_width)) / (1 + args['ns_to_ew_ratio'])
|
2098
2208
|
adiabatic_bar_b_length = adiabatic_dual_double_end_length - adiabatic_bar_a_length
|
2099
2209
|
adiabatic_area_a = adiabatic_bar_a_length * adiabatic_dual_double_end_width
|
2100
2210
|
adiabatic_area_b = adiabatic_bar_b_length * adiabatic_dual_double_end_width
|
@@ -2113,28 +2223,28 @@ module OsLib_ModelGeneration
|
|
2113
2223
|
# apply prescribed approach for stretched or dual bar
|
2114
2224
|
if dual_bar_calc_approach == 'dual_bar'
|
2115
2225
|
runner.registerInfo("Stretched #{OpenStudio.toNeatString(OpenStudio.convert(dual_double_end_length, 'm', 'ft').get, 0, true)} ft x #{OpenStudio.toNeatString(OpenStudio.convert(dual_double_end_width, 'm', 'ft').get, 0, true)} ft rectangle has an area of #{OpenStudio.toNeatString(OpenStudio.convert(dual_double_end_length * dual_double_end_width, 'm^2', 'ft^2').get, 0, true)} ft^2. When split in two the perimeter will be #{OpenStudio.toNeatString(OpenStudio.convert(dual_double_end_length * 2 + dual_double_end_width * 4, 'm', 'ft').get, 0, true)} ft")
|
2116
|
-
if (target_area - dual_double_end_length*dual_double_end_width).abs > tol_testing || (target_perim - (dual_double_end_length * 2 + dual_double_end_width * 4)).abs > tol_testing
|
2117
|
-
runner.registerWarning(
|
2226
|
+
if (target_area - dual_double_end_length * dual_double_end_width).abs > tol_testing || (target_perim - (dual_double_end_length * 2 + dual_double_end_width * 4)).abs > tol_testing
|
2227
|
+
runner.registerWarning('Unexpected values for dual rectangle.')
|
2118
2228
|
end
|
2119
2229
|
|
2120
|
-
runner.registerInfo("For stretched split bar, to match target ns/ew aspect ratio #{OpenStudio.toNeatString(OpenStudio.convert(bar_a_length, 'm', 'ft').get, 0, true)} ft of bar should be horizontal, with #{OpenStudio.toNeatString(OpenStudio.convert(bar_b_length, 'm', 'ft').get, 0, true)} ft turned 90 degrees. Combined area is #{OpenStudio.toNeatString(OpenStudio.convert(area_a + area_b, 'm^2', 'ft^2').get, 0, true)} ft^2. Combined perimeter is #{OpenStudio.toNeatString(OpenStudio.convert(bar_a_length*2 + bar_b_length*2 + dual_double_end_width*4, 'm', 'ft').get, 0, true)} ft")
|
2121
|
-
if (target_area - (area_a + area_b)).abs > tol_testing || (target_perim - (bar_a_length*2 + bar_b_length*2 + dual_double_end_width*4)).abs > tol_testing
|
2122
|
-
runner.registerWarning(
|
2230
|
+
runner.registerInfo("For stretched split bar, to match target ns/ew aspect ratio #{OpenStudio.toNeatString(OpenStudio.convert(bar_a_length, 'm', 'ft').get, 0, true)} ft of bar should be horizontal, with #{OpenStudio.toNeatString(OpenStudio.convert(bar_b_length, 'm', 'ft').get, 0, true)} ft turned 90 degrees. Combined area is #{OpenStudio.toNeatString(OpenStudio.convert(area_a + area_b, 'm^2', 'ft^2').get, 0, true)} ft^2. Combined perimeter is #{OpenStudio.toNeatString(OpenStudio.convert(bar_a_length * 2 + bar_b_length * 2 + dual_double_end_width * 4, 'm', 'ft').get, 0, true)} ft")
|
2231
|
+
if (target_area - (area_a + area_b)).abs > tol_testing || (target_perim - (bar_a_length * 2 + bar_b_length * 2 + dual_double_end_width * 4)).abs > tol_testing
|
2232
|
+
runner.registerWarning('Unexpected values for rotated dual rectangle')
|
2123
2233
|
end
|
2124
2234
|
elsif dual_bar_calc_approach == 'adiabatic_ends_bar_b'
|
2125
2235
|
runner.registerInfo("Can't hit target perimeter with two rectangles, need to make two ends adiabatic")
|
2126
2236
|
|
2127
|
-
runner.registerInfo("For dual bar with adiabatic ends on bar b, to reach target aspect ratio #{OpenStudio.toNeatString(OpenStudio.convert(adiabatic_bar_a_length, 'm', 'ft').get, 0, true)} ft of bar should be north/south, with #{OpenStudio.toNeatString(OpenStudio.convert(adiabatic_bar_b_length, 'm', 'ft').get, 0, true)} ft turned 90 degrees. Combined area is #{OpenStudio.toNeatString(OpenStudio.convert(adiabatic_area_a + adiabatic_area_b, 'm^2', 'ft^2').get, 0, true)} ft^2}. Combined perimeter is #{OpenStudio.toNeatString(OpenStudio.convert(adiabatic_bar_a_length*2 + adiabatic_bar_b_length*2 + adiabatic_dual_double_end_width*2, 'm', 'ft').get, 0, true)} ft")
|
2128
|
-
if (target_area - (adiabatic_area_a + adiabatic_area_b)).abs > tol_testing || (target_perim - (adiabatic_bar_a_length*2 + adiabatic_bar_b_length*2 + adiabatic_dual_double_end_width*2)).abs > tol_testing
|
2129
|
-
runner.registerWarning(
|
2237
|
+
runner.registerInfo("For dual bar with adiabatic ends on bar b, to reach target aspect ratio #{OpenStudio.toNeatString(OpenStudio.convert(adiabatic_bar_a_length, 'm', 'ft').get, 0, true)} ft of bar should be north/south, with #{OpenStudio.toNeatString(OpenStudio.convert(adiabatic_bar_b_length, 'm', 'ft').get, 0, true)} ft turned 90 degrees. Combined area is #{OpenStudio.toNeatString(OpenStudio.convert(adiabatic_area_a + adiabatic_area_b, 'm^2', 'ft^2').get, 0, true)} ft^2}. Combined perimeter is #{OpenStudio.toNeatString(OpenStudio.convert(adiabatic_bar_a_length * 2 + adiabatic_bar_b_length * 2 + adiabatic_dual_double_end_width * 2, 'm', 'ft').get, 0, true)} ft")
|
2238
|
+
if (target_area - (adiabatic_area_a + adiabatic_area_b)).abs > tol_testing || (target_perim - (adiabatic_bar_a_length * 2 + adiabatic_bar_b_length * 2 + adiabatic_dual_double_end_width * 2)).abs > tol_testing
|
2239
|
+
runner.registerWarning('Unexpected values for rotated dual rectangle adiabatic ends bar b')
|
2130
2240
|
end
|
2131
2241
|
else # stretched bar
|
2132
2242
|
dual_bar = false
|
2133
2243
|
|
2134
2244
|
stretched_length = 0.25 * (target_perim + Math.sqrt(target_perim**2 - 16 * footprint_si))
|
2135
2245
|
stretched_width = footprint_si / stretched_length
|
2136
|
-
if (target_area - stretched_length*stretched_width).abs > tol_testing || (target_perim - (stretched_length + stretched_width)*2) > tol_testing
|
2137
|
-
runner.registerWarning(
|
2246
|
+
if (target_area - stretched_length * stretched_width).abs > tol_testing || (target_perim - (stretched_length + stretched_width) * 2) > tol_testing
|
2247
|
+
runner.registerWarning('Unexpected values for single stretched')
|
2138
2248
|
end
|
2139
2249
|
|
2140
2250
|
width = stretched_width
|
@@ -2170,7 +2280,7 @@ module OsLib_ModelGeneration
|
|
2170
2280
|
end
|
2171
2281
|
bars['primary'][:floor_height_si] = floor_height_si # can make use of this when breaking out multi-height spaces
|
2172
2282
|
bars['primary'][:num_stories] = num_stories
|
2173
|
-
bars['primary'][:center_of_footprint] = OpenStudio::Point3d.new(0.0,0.0,0.0)
|
2283
|
+
bars['primary'][:center_of_footprint] = OpenStudio::Point3d.new(0.0, 0.0, 0.0)
|
2174
2284
|
space_types_hash_secondary = {}
|
2175
2285
|
if dual_bar
|
2176
2286
|
# loop through each story and move portion for other bar to its own hash
|
@@ -2179,9 +2289,9 @@ module OsLib_ModelGeneration
|
|
2179
2289
|
footprint_counter = primary_footprint
|
2180
2290
|
secondary_footprint_counter = secondary_footprint
|
2181
2291
|
story_counter = 0
|
2182
|
-
pri_sec_tol = 0.0001 #m^2
|
2183
|
-
pri_sec_min_area = 0.0001 #m^2
|
2184
|
-
space_types_hash.each do |k,v|
|
2292
|
+
pri_sec_tol = 0.0001 # m^2
|
2293
|
+
pri_sec_min_area = 0.0001 # m^2
|
2294
|
+
space_types_hash.each do |k, v|
|
2185
2295
|
space_type_left = v[:floor_area]
|
2186
2296
|
|
2187
2297
|
# do not go to next space type until this one is evaulate, which may span stories
|
@@ -2189,23 +2299,23 @@ module OsLib_ModelGeneration
|
|
2189
2299
|
|
2190
2300
|
# use secondary footprint if any left
|
2191
2301
|
if secondary_footprint_counter > 0.0
|
2192
|
-
hash_area = [space_type_left,secondary_footprint_counter].min
|
2302
|
+
hash_area = [space_type_left, secondary_footprint_counter].min
|
2193
2303
|
|
2194
2304
|
# confirm that the part of space type use or what is left is greater than min allowed value
|
2195
2305
|
projected_space_type_left = space_type_left - hash_area
|
2196
|
-
test_a =
|
2197
|
-
test_b =
|
2198
|
-
test_c =
|
2306
|
+
test_a = hash_area >= pri_sec_min_area
|
2307
|
+
test_b = projected_space_type_left >= pri_sec_min_area || projected_space_type_left == 0.0 ? true : false
|
2308
|
+
test_c = k == space_types_hash.keys.last # if last space type accept sliver, no other space to infil
|
2199
2309
|
if (test_a && test_b) || test_c
|
2200
|
-
if space_types_hash_secondary.
|
2310
|
+
if space_types_hash_secondary.key?(k)
|
2201
2311
|
# add to what was added for previous story
|
2202
2312
|
space_types_hash_secondary[k][:floor_area] += hash_area
|
2203
2313
|
else
|
2204
2314
|
# add new space type to hash
|
2205
|
-
if v.
|
2206
|
-
space_types_hash_secondary[k] = {:
|
2315
|
+
if v.key?(:children)
|
2316
|
+
space_types_hash_secondary[k] = { floor_area: hash_area, space_type: v[:space_type], children: v[:children] }
|
2207
2317
|
else
|
2208
|
-
space_types_hash_secondary[k] = {:
|
2318
|
+
space_types_hash_secondary[k] = { floor_area: hash_area, space_type: v[:space_type] }
|
2209
2319
|
end
|
2210
2320
|
end
|
2211
2321
|
space_types_hash[k][:floor_area] -= hash_area
|
@@ -2222,7 +2332,7 @@ module OsLib_ModelGeneration
|
|
2222
2332
|
space_type_left = 0.0
|
2223
2333
|
else
|
2224
2334
|
# then look at primary bar
|
2225
|
-
hash_area_pri = [space_type_left,footprint_counter].min
|
2335
|
+
hash_area_pri = [space_type_left, footprint_counter].min
|
2226
2336
|
footprint_counter -= hash_area_pri
|
2227
2337
|
space_type_left -= hash_area_pri
|
2228
2338
|
end
|
@@ -2247,13 +2357,13 @@ module OsLib_ModelGeneration
|
|
2247
2357
|
bars['primary'][:space_types_hash] = space_types_hash
|
2248
2358
|
bars['primary'][:args] = args
|
2249
2359
|
v = bars['primary']
|
2250
|
-
bar_hash_setup_run(runner,model,v[:args],v[:length],v[:width],v[:floor_height_si],v[:center_of_footprint],v[:space_types_hash],v[:num_stories])
|
2360
|
+
bar_hash_setup_run(runner, model, v[:args], v[:length], v[:width], v[:floor_height_si], v[:center_of_footprint], v[:space_types_hash], v[:num_stories])
|
2251
2361
|
|
2252
2362
|
# store offset value for multiple bars
|
2253
|
-
if args.
|
2363
|
+
if args.key?('bar_sep_dist_mult') && args['bar_sep_dist_mult'] > 0.0
|
2254
2364
|
offset_val = num_stories.ceil * floor_height_si * args['bar_sep_dist_mult']
|
2255
|
-
elsif args.
|
2256
|
-
runner.registerWarning(
|
2365
|
+
elsif args.key?('bar_sep_dist_mult')
|
2366
|
+
runner.registerWarning('Positive value is required for bar_sep_dist_mult, ignoring input and using value of 0.1')
|
2257
2367
|
offset_val = num_stories.ceil * floor_height_si * 0.1
|
2258
2368
|
else
|
2259
2369
|
offset_val = num_stories.ceil * floor_height_si * 10.0
|
@@ -2289,21 +2399,21 @@ module OsLib_ModelGeneration
|
|
2289
2399
|
else
|
2290
2400
|
runner.registerInfo('Adiabatic ends added to secondary bar because target perimeter multiplier could not be met with two full rectangular footprints.')
|
2291
2401
|
end
|
2292
|
-
bars['secondary'][:center_of_footprint] = OpenStudio::Point3d.new(adiabatic_bar_a_length * 0.5 + adiabatic_dual_double_end_width * 0.5 + offset_val,adiabatic_bar_b_length * 0.5 + adiabatic_dual_double_end_width * 0.5 + offset_val,0.0)
|
2402
|
+
bars['secondary'][:center_of_footprint] = OpenStudio::Point3d.new(adiabatic_bar_a_length * 0.5 + adiabatic_dual_double_end_width * 0.5 + offset_val, adiabatic_bar_b_length * 0.5 + adiabatic_dual_double_end_width * 0.5 + offset_val, 0.0)
|
2293
2403
|
else
|
2294
|
-
bars['secondary'][:center_of_footprint] = OpenStudio::Point3d.new(bar_a_length * 0.5 + dual_double_end_width * 0.5 + offset_val,bar_b_length * 0.5 + dual_double_end_width * 0.5 + offset_val,0.0)
|
2404
|
+
bars['secondary'][:center_of_footprint] = OpenStudio::Point3d.new(bar_a_length * 0.5 + dual_double_end_width * 0.5 + offset_val, bar_b_length * 0.5 + dual_double_end_width * 0.5 + offset_val, 0.0)
|
2295
2405
|
end
|
2296
2406
|
bars['secondary'][:args] = args2
|
2297
2407
|
|
2298
2408
|
# setup bar_hash and run create_bar
|
2299
2409
|
v = bars['secondary']
|
2300
|
-
bar_hash_setup_run(runner,model,v[:args],v[:length],v[:width],v[:floor_height_si],v[:center_of_footprint],v[:space_types_hash],v[:num_stories])
|
2410
|
+
bar_hash_setup_run(runner, model, v[:args], v[:length], v[:width], v[:floor_height_si], v[:center_of_footprint], v[:space_types_hash], v[:num_stories])
|
2301
2411
|
|
2302
2412
|
end
|
2303
2413
|
|
2304
2414
|
# future development (up against primary bar run intersection and surface matching after add all bars, avoid interior windows)
|
2305
2415
|
# I could loop through each space type and give them unique height but for now will just take largest height and make bar of that height, which is fine for prototypes
|
2306
|
-
if multi_height_space_types_hash.
|
2416
|
+
if !multi_height_space_types_hash.empty?
|
2307
2417
|
args3 = args.clone
|
2308
2418
|
bars['custom_height'] = {}
|
2309
2419
|
if mirror_ns_ew
|
@@ -2314,7 +2424,7 @@ module OsLib_ModelGeneration
|
|
2314
2424
|
bars['custom_height'][:width] = width_cust_height
|
2315
2425
|
end
|
2316
2426
|
if args['party_wall_stories_east'] + args['party_wall_stories_west'] + args['party_wall_stories_south'] + args['party_wall_stories_north'] > 0.0
|
2317
|
-
runner.registerWarning(
|
2427
|
+
runner.registerWarning('Ignorning party wall inputs for custom height bar')
|
2318
2428
|
end
|
2319
2429
|
|
2320
2430
|
# disable party walls
|
@@ -2329,14 +2439,14 @@ module OsLib_ModelGeneration
|
|
2329
2439
|
|
2330
2440
|
bars['custom_height'][:floor_height_si] = floor_height_si # can make use of this when breaking out multi-height spaces
|
2331
2441
|
bars['custom_height'][:num_stories] = num_stories
|
2332
|
-
bars['custom_height'][:center_of_footprint] = OpenStudio::Point3d.new(bars['primary'][:length] * -0.5 - length_cust_height * 0.5 - offset_val,0.0,0.0)
|
2333
|
-
bars['custom_height'][:floor_height_si] = OpenStudio.convert(custom_story_heights.max,'ft','m').get
|
2442
|
+
bars['custom_height'][:center_of_footprint] = OpenStudio::Point3d.new(bars['primary'][:length] * -0.5 - length_cust_height * 0.5 - offset_val, 0.0, 0.0)
|
2443
|
+
bars['custom_height'][:floor_height_si] = OpenStudio.convert(custom_story_heights.max, 'ft', 'm').get
|
2334
2444
|
bars['custom_height'][:num_stories] = 1
|
2335
2445
|
bars['custom_height'][:space_types_hash] = multi_height_space_types_hash
|
2336
2446
|
bars['custom_height'][:args] = args3
|
2337
2447
|
|
2338
2448
|
v = bars['custom_height']
|
2339
|
-
bar_hash_setup_run(runner,model,v[:args],v[:length],v[:width],v[:floor_height_si],v[:center_of_footprint],v[:space_types_hash],v[:num_stories])
|
2449
|
+
bar_hash_setup_run(runner, model, v[:args], v[:length], v[:width], v[:floor_height_si], v[:center_of_footprint], v[:space_types_hash], v[:num_stories])
|
2340
2450
|
end
|
2341
2451
|
|
2342
2452
|
# diagnostic log
|
@@ -2388,37 +2498,37 @@ module OsLib_ModelGeneration
|
|
2388
2498
|
end
|
2389
2499
|
|
2390
2500
|
# check ns/ew aspect ratio (harder to check when party walls are added)
|
2391
|
-
wall_and_window_by_orientation = OsLib_Geometry.getExteriorWindowAndWllAreaByOrientation(model,model.getSpaces
|
2501
|
+
wall_and_window_by_orientation = OsLib_Geometry.getExteriorWindowAndWllAreaByOrientation(model, model.getSpaces)
|
2392
2502
|
wall_ns = (wall_and_window_by_orientation['northWall'] + wall_and_window_by_orientation['southWall'])
|
2393
2503
|
wall_ew = wall_and_window_by_orientation['eastWall'] + wall_and_window_by_orientation['westWall']
|
2394
|
-
wall_ns_ip = OpenStudio.convert(wall_ns,'m^2','ft^2').get
|
2395
|
-
wall_ew_ip = OpenStudio.convert(wall_ew,'m^2','ft^2').get
|
2396
|
-
runner.registerValue('wall_area_ip',wall_ns_ip + wall_ew_ip,'ft^2')
|
2397
|
-
runner.registerValue('ns_wall_area_ip',wall_ns_ip,'ft^2')
|
2398
|
-
runner.registerValue('ew_wall_area_ip',wall_ew_ip,'ft^2')
|
2504
|
+
wall_ns_ip = OpenStudio.convert(wall_ns, 'm^2', 'ft^2').get
|
2505
|
+
wall_ew_ip = OpenStudio.convert(wall_ew, 'm^2', 'ft^2').get
|
2506
|
+
runner.registerValue('wall_area_ip', wall_ns_ip + wall_ew_ip, 'ft^2')
|
2507
|
+
runner.registerValue('ns_wall_area_ip', wall_ns_ip, 'ft^2')
|
2508
|
+
runner.registerValue('ew_wall_area_ip', wall_ew_ip, 'ft^2')
|
2399
2509
|
# for now using perimeter of ground floor and average story area (building area / num_stories)
|
2400
|
-
runner.registerValue('floor_area_to_perim_ratio',model.getBuilding.floorArea /
|
2401
|
-
runner.registerValue('bar_width',OpenStudio.convert(bars['primary'][:width],'m','ft').get,'ft')
|
2510
|
+
runner.registerValue('floor_area_to_perim_ratio', model.getBuilding.floorArea / (OsLib_Geometry.calculate_perimeter(model) * num_stories))
|
2511
|
+
runner.registerValue('bar_width', OpenStudio.convert(bars['primary'][:width], 'm', 'ft').get, 'ft')
|
2402
2512
|
|
2403
2513
|
if args['party_wall_fraction'] > 0 || args['party_wall_stories_north'] > 0 || args['party_wall_stories_south'] > 0 || args['party_wall_stories_east'] > 0 || args['party_wall_stories_west'] > 0
|
2404
|
-
runner.registerInfo(
|
2514
|
+
runner.registerInfo('Target facade area by orientation not validated when party walls are applied')
|
2405
2515
|
elsif args['num_stories_above_grade'] != args['num_stories_above_grade'].ceil
|
2406
|
-
runner.registerInfo(
|
2516
|
+
runner.registerInfo('Target facade area by orientation not validated when partial top story is used')
|
2407
2517
|
elsif dual_bar_calc_approach == 'stretched'
|
2408
|
-
runner.registerInfo(
|
2409
|
-
elsif defaulted_args.include?('floor_height')
|
2410
|
-
runner.registerInfo(
|
2518
|
+
runner.registerInfo('Target facade area by orientation not validated when single stretched bar has to be used to meet target minimum perimeter multiplier')
|
2519
|
+
elsif defaulted_args.include?('floor_height') && args['custom_height_bar'] && !multi_height_space_types_hash.empty?
|
2520
|
+
runner.registerInfo('Target facade area by orientation not validated when a dedicated bar is added for space types with custom heights')
|
2411
2521
|
elsif args['bar_width'] > 0
|
2412
|
-
runner.registerInfo(
|
2522
|
+
runner.registerInfo('Target facade area by orientation not validated when a dedicated custom bar width is defined')
|
2413
2523
|
else
|
2414
2524
|
|
2415
2525
|
# adjust length versus width based on building rotation
|
2416
2526
|
if mirror_ns_ew
|
2417
|
-
wall_target_ns_ip = 2 * OpenStudio.convert(width,'m','ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
2418
|
-
wall_target_ew_ip = 2 * OpenStudio.convert(length,'m','ft').get
|
2527
|
+
wall_target_ns_ip = 2 * OpenStudio.convert(width, 'm', 'ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
2528
|
+
wall_target_ew_ip = 2 * OpenStudio.convert(length, 'm', 'ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
2419
2529
|
else
|
2420
|
-
wall_target_ns_ip = 2 * OpenStudio.convert(length,'m','ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
2421
|
-
wall_target_ew_ip = 2 * OpenStudio.convert(width,'m','ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
2530
|
+
wall_target_ns_ip = 2 * OpenStudio.convert(length, 'm', 'ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
2531
|
+
wall_target_ew_ip = 2 * OpenStudio.convert(width, 'm', 'ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
2422
2532
|
end
|
2423
2533
|
flag_error = false
|
2424
2534
|
if (wall_target_ns_ip - wall_ns_ip).abs > 0.1
|
@@ -2458,7 +2568,6 @@ module OsLib_ModelGeneration
|
|
2458
2568
|
# typical
|
2459
2569
|
# used for varieties of measures that create typical building from model
|
2460
2570
|
def typical_building_from_model(model, runner, user_arguments)
|
2461
|
-
|
2462
2571
|
# assign the user inputs to variables
|
2463
2572
|
args = OsLib_HelperMethods.createRunVariables(runner, model, user_arguments, arguments(model))
|
2464
2573
|
if !args then return false end
|
@@ -2528,7 +2637,7 @@ module OsLib_ModelGeneration
|
|
2528
2637
|
end
|
2529
2638
|
|
2530
2639
|
# check that weekday start time plus duration does not exceed 24 hrs
|
2531
|
-
if (wkdy_op_hrs_start_time_hr + wkdy_op_hrs_duration_hr + (wkdy_op_hrs_start_time_min + wkdy_op_hrs_duration_min)/60.0) > 24.0
|
2640
|
+
if (wkdy_op_hrs_start_time_hr + wkdy_op_hrs_duration_hr + (wkdy_op_hrs_start_time_min + wkdy_op_hrs_duration_min) / 60.0) > 24.0
|
2532
2641
|
runner.registerInfo("Weekday start time of #{args['wkdy_op_hrs_start']} plus duration of #{args['wkdy_op_hrs_duration']} is more than 24 hrs, hours of operation overlap midnight.")
|
2533
2642
|
end
|
2534
2643
|
end
|
@@ -2568,7 +2677,7 @@ module OsLib_ModelGeneration
|
|
2568
2677
|
end
|
2569
2678
|
|
2570
2679
|
# check that weekend start time plus duration does not exceed 24 hrs
|
2571
|
-
if (wknd_op_hrs_start_time_hr + wknd_op_hrs_duration_hr + (wknd_op_hrs_start_time_min + wknd_op_hrs_duration_min)/60.0) > 24.0
|
2680
|
+
if (wknd_op_hrs_start_time_hr + wknd_op_hrs_duration_hr + (wknd_op_hrs_start_time_min + wknd_op_hrs_duration_min) / 60.0) > 24.0
|
2572
2681
|
runner.registerInfo("Weekend start time of #{args['wknd_op_hrs_start']} plus duration of #{args['wknd_op_hrs_duration']} is more than 24 hrs, hours of operation overlap midnight.")
|
2573
2682
|
end
|
2574
2683
|
end
|
@@ -2584,7 +2693,7 @@ module OsLib_ModelGeneration
|
|
2584
2693
|
standard = Standard.build((args['template']).to_s)
|
2585
2694
|
|
2586
2695
|
# validate climate zone
|
2587
|
-
if !args.
|
2696
|
+
if !args.key?('climate_zone') || args['climate_zone'] == 'Lookup From Model'
|
2588
2697
|
climate_zone = standard.model_get_building_climate_zone_and_building_type(model)['climate_zone']
|
2589
2698
|
runner.registerInfo("Using climate zone #{climate_zone} from model")
|
2590
2699
|
else
|
@@ -2679,8 +2788,10 @@ module OsLib_ModelGeneration
|
|
2679
2788
|
# TODO: - allow building type and space type specific constructions set selection.
|
2680
2789
|
if ['SmallHotel', 'LargeHotel', 'MidriseApartment', 'HighriseApartment'].include?(primary_bldg_type)
|
2681
2790
|
is_residential = 'Yes'
|
2791
|
+
occ_type = 'Residential'
|
2682
2792
|
else
|
2683
2793
|
is_residential = 'No'
|
2794
|
+
occ_type = 'Nonresidential'
|
2684
2795
|
end
|
2685
2796
|
bldg_def_const_set = standard.model_add_construction_set(model, climate_zone, lookup_building_type, nil, is_residential)
|
2686
2797
|
if bldg_def_const_set.is_initialized
|
@@ -2694,6 +2805,31 @@ module OsLib_ModelGeneration
|
|
2694
2805
|
return false
|
2695
2806
|
end
|
2696
2807
|
|
2808
|
+
# Replace the construction of any outdoor-facing "AtticFloor" surfaces
|
2809
|
+
# with the "ExteriorRoof" - "IEAD" construction for the specific climate zone and template.
|
2810
|
+
# This prevents creation of buildings where the DOE Prototype building construction set
|
2811
|
+
# assumes an attic but the supplied geometry used does not have an attic.
|
2812
|
+
new_construction = nil
|
2813
|
+
climate_zone_set = standard.model_find_climate_zone_set(model, climate_zone)
|
2814
|
+
model.getSurfaces.sort.each do |surf|
|
2815
|
+
next unless surf.outsideBoundaryCondition == 'Outdoors'
|
2816
|
+
next unless surf.surfaceType == 'RoofCeiling'
|
2817
|
+
next if surf.construction.empty?
|
2818
|
+
construction = surf.construction.get
|
2819
|
+
standards_info = construction.standardsInformation
|
2820
|
+
next if standards_info.intendedSurfaceType.empty?
|
2821
|
+
next unless standards_info.intendedSurfaceType.get == 'AtticFloor'
|
2822
|
+
if new_construction.nil?
|
2823
|
+
new_construction = standard.model_find_and_add_construction(model,
|
2824
|
+
climate_zone_set,
|
2825
|
+
'ExteriorRoof',
|
2826
|
+
'IEAD',
|
2827
|
+
occ_type)
|
2828
|
+
end
|
2829
|
+
surf.setConstruction(new_construction)
|
2830
|
+
runner.registerInfo("Changed the construction for #{surf.name} from #{construction.name} to #{new_construction.name} to avoid outdoor-facing attic floor constructions in buildings with no attic space.")
|
2831
|
+
end
|
2832
|
+
|
2697
2833
|
# address any adiabatic surfaces that don't have hard assigned constructions
|
2698
2834
|
model.getSurfaces.sort.each do |surface|
|
2699
2835
|
next if surface.outsideBoundaryCondition != 'Adiabatic'
|
@@ -2838,13 +2974,13 @@ module OsLib_ModelGeneration
|
|
2838
2974
|
end
|
2839
2975
|
|
2840
2976
|
# add daylight controls, need to perform a sizing run for 2010
|
2841
|
-
if args['template'] == '90.1-2010'
|
2977
|
+
if args['template'] == '90.1-2010' || args['template'] == 'ComStock 90.1-2010'
|
2842
2978
|
if standard.model_run_sizing_run(model, "#{Dir.pwd}/SRvt") == false
|
2843
2979
|
log_messages_to_runner(runner, debug = true)
|
2844
2980
|
return false
|
2845
2981
|
end
|
2846
2982
|
end
|
2847
|
-
|
2983
|
+
standard.model_add_daylighting_controls(model)
|
2848
2984
|
end
|
2849
2985
|
|
2850
2986
|
# add refrigeration
|
@@ -2971,7 +3107,10 @@ module OsLib_ModelGeneration
|
|
2971
3107
|
end
|
2972
3108
|
|
2973
3109
|
# Add the primary system to the primary zones
|
2974
|
-
standard.model_add_hvac_system(model, sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, system_zones)
|
3110
|
+
unless standard.model_add_hvac_system(model, sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, system_zones)
|
3111
|
+
runner.registerError("HVAC system type '#{sys_type}' not recognized. Check input system type argument against Model.hvac.rb for valid hvac system type names.")
|
3112
|
+
return false
|
3113
|
+
end
|
2975
3114
|
|
2976
3115
|
# Add the secondary system to the secondary zones (if any)
|
2977
3116
|
if !pri_sec_zone_lists['secondary'].empty?
|
@@ -2981,7 +3120,10 @@ module OsLib_ModelGeneration
|
|
2981
3120
|
cooled_only_zones = system_zones.select { |zone| !standard.thermal_zone_heated?(zone) && standard.thermal_zone_cooled?(zone) }
|
2982
3121
|
system_zones = heated_and_cooled_zones + cooled_only_zones
|
2983
3122
|
end
|
2984
|
-
standard.model_add_hvac_system(model, sec_sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, system_zones)
|
3123
|
+
unless standard.model_add_hvac_system(model, sec_sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, system_zones)
|
3124
|
+
runner.registerError("HVAC system type '#{sys_type}' not recognized. Check input system type argument against Model.hvac.rb for valid hvac system type names.")
|
3125
|
+
return false
|
3126
|
+
end
|
2985
3127
|
end
|
2986
3128
|
end
|
2987
3129
|
end
|
@@ -2997,7 +3139,10 @@ module OsLib_ModelGeneration
|
|
2997
3139
|
# Add the user specified HVAC system for each story.
|
2998
3140
|
# Single-zone systems will get one per zone.
|
2999
3141
|
story_groups.each do |zones|
|
3000
|
-
model.add_cbecs_hvac_system(standard, args['system_type'], zones)
|
3142
|
+
unless model.add_cbecs_hvac_system(standard, args['system_type'], zones)
|
3143
|
+
runner.registerError("HVAC system type '#{args['system_type']}' not recognized. Check input system type argument against Model.hvac.rb for valid hvac system type names.")
|
3144
|
+
return false
|
3145
|
+
end
|
3001
3146
|
end
|
3002
3147
|
end
|
3003
3148
|
end
|
@@ -3045,7 +3190,7 @@ module OsLib_ModelGeneration
|
|
3045
3190
|
if args['add_hvac']
|
3046
3191
|
# set additional properties for building
|
3047
3192
|
props = model.getBuilding.additionalProperties
|
3048
|
-
props.setFeature('hvac_system_type',
|
3193
|
+
props.setFeature('hvac_system_type', (args['system_type']).to_s)
|
3049
3194
|
|
3050
3195
|
case args['system_type']
|
3051
3196
|
when 'Ideal Air Loads'
|
@@ -3115,7 +3260,6 @@ module OsLib_ModelGeneration
|
|
3115
3260
|
# wizard
|
3116
3261
|
# used for varieties of measures that create space type and construction set wizard
|
3117
3262
|
def wizard(model, runner, user_arguments)
|
3118
|
-
|
3119
3263
|
# use the built-in error checking
|
3120
3264
|
if !runner.validateUserArguments(arguments(model), user_arguments)
|
3121
3265
|
return false
|
@@ -3159,7 +3303,7 @@ module OsLib_ModelGeneration
|
|
3159
3303
|
lookup_building_type = standard.model_get_lookup_name(building_type)
|
3160
3304
|
|
3161
3305
|
# remap small medium and large office to office
|
3162
|
-
if building_type.include?(
|
3306
|
+
if building_type.include?('Office') then building_type = 'Office' end
|
3163
3307
|
|
3164
3308
|
# get array of new space types
|
3165
3309
|
space_types_new = []
|
@@ -3287,4 +3431,4 @@ module OsLib_ModelGeneration
|
|
3287
3431
|
|
3288
3432
|
return true
|
3289
3433
|
end
|
3290
|
-
end
|
3434
|
+
end
|