openstudio-extension 0.3.2 → 0.4.0
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/.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
|