openstudio-extension 0.3.0 → 0.4.2
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 +5 -0
- data/CHANGELOG.md +34 -0
- data/Gemfile +5 -0
- 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/gemspec.txt +7 -5
- 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/template_gemfile.txt +1 -4
- 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 +17 -3
- 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 +366 -208
- 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 +30 -14
- data/lib/openstudio/extension/runner_config.rb +1 -1
- data/lib/openstudio/extension/version.rb +2 -2
- data/openstudio-extension.gemspec +9 -8
- metadata +32 -17
|
@@ -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:
|
|
@@ -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:
|
|
@@ -233,7 +233,8 @@ module OsLib_HelperMethods
|
|
|
233
233
|
msg.logChannel.include?('runmanager') || # RunManager messages
|
|
234
234
|
msg.logChannel.include?('setFileExtension') || # .ddy extension unexpected
|
|
235
235
|
msg.logChannel.include?('Translator') || # Forward translator and geometry translator
|
|
236
|
-
msg.logMessage.include?('UseWeatherFile') # 'UseWeatherFile' is not yet a supported option for YearDescription
|
|
236
|
+
msg.logMessage.include?('UseWeatherFile') || # 'UseWeatherFile' is not yet a supported option for YearDescription
|
|
237
|
+
msg.logMessage.include?('has multiple parents') # 'has multiple parents' is thrown for various types of curves if used in multiple objects
|
|
237
238
|
|
|
238
239
|
# Report the message in the correct way
|
|
239
240
|
if msg.logLevel == OpenStudio::Info
|
|
@@ -265,7 +266,20 @@ module OsLib_HelperMethods
|
|
|
265
266
|
result = measure_step.result.get
|
|
266
267
|
result.stepValues.each do |arg|
|
|
267
268
|
name = arg.name
|
|
268
|
-
value
|
|
269
|
+
# check if value, double, int, or bool
|
|
270
|
+
value_type = arg.variantType.valueDescription
|
|
271
|
+
if value_type == "Double"
|
|
272
|
+
value = arg.valueAsDouble
|
|
273
|
+
elsif value_type == "Integer"
|
|
274
|
+
value = arg.valueAsInteger
|
|
275
|
+
elsif value_type == "Boolean"
|
|
276
|
+
value = arg.valueAsBoolean
|
|
277
|
+
elsif value_type == "String"
|
|
278
|
+
value = arg.valueAsString
|
|
279
|
+
else
|
|
280
|
+
# catchall for unexpected value types
|
|
281
|
+
value = arg.valueAsVariant.to_s
|
|
282
|
+
end
|
|
269
283
|
if name == arg_name
|
|
270
284
|
arg_name_value[:value] = value
|
|
271
285
|
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,14 @@ module OsLib_ModelGeneration
|
|
|
157
158
|
array << '90.1-2007'
|
|
158
159
|
array << '90.1-2010'
|
|
159
160
|
array << '90.1-2013'
|
|
161
|
+
array << '90.1-2016'
|
|
162
|
+
array << '90.1-2019'
|
|
163
|
+
array << 'ComStock DOE Ref Pre-1980'
|
|
164
|
+
array << 'ComStock DOE Ref 1980-2004'
|
|
165
|
+
array << 'ComStock 90.1-2004'
|
|
166
|
+
array << 'ComStock 90.1-2007'
|
|
167
|
+
array << 'ComStock 90.1-2010'
|
|
168
|
+
array << 'ComStock 90.1-2013'
|
|
160
169
|
if extended
|
|
161
170
|
# array << '189.1-2009' # if turn this on need to update space_type_array for RetailStripmall
|
|
162
171
|
array << 'NREL ZNE Ready 2017'
|
|
@@ -228,10 +237,9 @@ module OsLib_ModelGeneration
|
|
|
228
237
|
# get_doe_climate_zones
|
|
229
238
|
# for general public use use extended = false
|
|
230
239
|
def get_doe_climate_zones(extended = false, extra = nil)
|
|
231
|
-
|
|
232
240
|
# Lookup From Model should be added as an option where appropriate in the measure
|
|
233
241
|
cz_choices = OpenStudio::StringVector.new
|
|
234
|
-
if extra
|
|
242
|
+
if !extra.nil?
|
|
235
243
|
cz_choices << extra
|
|
236
244
|
end
|
|
237
245
|
cz_choices << 'ASHRAE 169-2013-1A'
|
|
@@ -262,10 +270,9 @@ module OsLib_ModelGeneration
|
|
|
262
270
|
# get_deer_climate_zones
|
|
263
271
|
# for general public use use extended = false
|
|
264
272
|
def get_deer_climate_zones(extended = false, extra = nil)
|
|
265
|
-
|
|
266
273
|
# Lookup From Model should be added as an option where appropriate in the measure
|
|
267
274
|
cz_choices = OpenStudio::StringVector.new
|
|
268
|
-
if extra
|
|
275
|
+
if !extra.nil?
|
|
269
276
|
cz_choices << extra
|
|
270
277
|
end
|
|
271
278
|
cz_choices << 'CEC T24-CEC1'
|
|
@@ -309,27 +316,27 @@ module OsLib_ModelGeneration
|
|
|
309
316
|
primary_footprint = 73958.0
|
|
310
317
|
primary_p = 619.0 # wrote measure using calculate_perimeter method in os_lib_geometry
|
|
311
318
|
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)
|
|
319
|
+
primary_width = Math.sqrt(primary_footprint / primary_ns_ew_ratio)
|
|
313
320
|
primary_p_min = 2 * (primary_width + primary_width / primary_footprint)
|
|
314
321
|
primary_p_mult = primary_p / primary_p_min
|
|
315
322
|
|
|
316
323
|
secondary_footprint = 210887.0 / 2.0 # floor area divided by area instead of true footprint 128112.0)
|
|
317
324
|
secondary_p = 708.0 # wrote measure using calculate_perimeter method in os_lib_geometry
|
|
318
325
|
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)
|
|
326
|
+
secondary_width = Math.sqrt(secondary_footprint / secondary_ns_ew_ratio)
|
|
320
327
|
secondary_p_min = 2 * (secondary_width + secondary_width / secondary_footprint)
|
|
321
328
|
secondary_p_mult = secondary_p / secondary_p_min
|
|
322
329
|
|
|
323
330
|
outpatient_footprint = 40946.0 / 3.0 # floor area divided by area instead of true footprint 17872.0)
|
|
324
331
|
outpatient_p = 537.0 # wrote measure using calculate_perimeter method in os_lib_geometry
|
|
325
332
|
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)
|
|
333
|
+
outpatient_width = Math.sqrt(outpatient_footprint / outpatient_ns_ew_ratio)
|
|
334
|
+
outpatient_p_min = 2 * (outpatient_width + outpatient_footprint / outpatient_width)
|
|
328
335
|
outpatient_p_mult = outpatient_p / outpatient_p_min
|
|
329
336
|
|
|
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)
|
|
337
|
+
# primary_aspet_ratio = calc_aspect_ratio(73958.0, 2060.0)
|
|
338
|
+
# secondary_aspet_ratio = calc_aspect_ratio(128112.0, 2447.0)
|
|
339
|
+
# outpatient_aspet_ratio = calc_aspect_ratio(14782.0, 588.0)
|
|
333
340
|
supermarket_a = 45001.0
|
|
334
341
|
supermarket_p = 866.0
|
|
335
342
|
supermarket_wwr = 1880.0 / (supermarket_p * 20.0)
|
|
@@ -402,13 +409,13 @@ module OsLib_ModelGeneration
|
|
|
402
409
|
# TODO: - Confirm that these work for all standards
|
|
403
410
|
# DOE Prototypes
|
|
404
411
|
if building_type == 'SecondarySchool'
|
|
405
|
-
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004'].include?(template)
|
|
412
|
+
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004', 'ComStock DOE Ref Pre-1980', 'ComStock DOE Ref 1980-2004'].include?(template)
|
|
406
413
|
hash['Auditorium'] = { ratio: 0.0504, space_type_gen: true, default: false, story_height: 26.0 }
|
|
407
414
|
hash['Cafeteria'] = { ratio: 0.0319, space_type_gen: true, default: false }
|
|
408
415
|
hash['Classroom'] = { ratio: 0.3528, space_type_gen: true, default: true }
|
|
409
416
|
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
|
|
417
|
+
hash['Gym'] = { ratio: 0.1009, space_type_gen: true, default: false, story_height: 26.0 }
|
|
418
|
+
hash['Gym - audience'] = { ratio: 0.0637, space_type_gen: true, default: false, story_height: 26.0 }
|
|
412
419
|
hash['Kitchen'] = { ratio: 0.0110, space_type_gen: true, default: false }
|
|
413
420
|
hash['Library'] = { ratio: 0.0429, space_type_gen: true, default: false }
|
|
414
421
|
hash['Lobby'] = { ratio: 0.0214, space_type_gen: true, default: false }
|
|
@@ -421,7 +428,7 @@ module OsLib_ModelGeneration
|
|
|
421
428
|
hash['Classroom'] = { ratio: 0.3041, space_type_gen: true, default: true }
|
|
422
429
|
hash['ComputerRoom'] = { ratio: 0.0487, space_type_gen: true, default: true }
|
|
423
430
|
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
|
|
431
|
+
hash['Gym'] = { ratio: 0.1646, space_type_gen: true, default: false, story_height: 26.0 }
|
|
425
432
|
hash['Kitchen'] = { ratio: 0.0110, space_type_gen: true, default: false }
|
|
426
433
|
hash['Library'] = { ratio: 0.0429, space_type_gen: true, default: false }
|
|
427
434
|
hash['Lobby'] = { ratio: 0.0214, space_type_gen: true, default: false }
|
|
@@ -430,7 +437,7 @@ module OsLib_ModelGeneration
|
|
|
430
437
|
hash['Restroom'] = { ratio: 0.0214, space_type_gen: true, default: false }
|
|
431
438
|
end
|
|
432
439
|
elsif building_type == 'PrimarySchool'
|
|
433
|
-
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004'].include?(template)
|
|
440
|
+
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004', 'ComStock DOE Ref Pre-1980', 'ComStock DOE Ref 1980-2004'].include?(template)
|
|
434
441
|
# updated to 2004 which includes library vs. pre-1980
|
|
435
442
|
hash['Cafeteria'] = { ratio: 0.0458, space_type_gen: true, default: false }
|
|
436
443
|
hash['Classroom'] = { ratio: 0.5610, space_type_gen: true, default: true }
|
|
@@ -448,7 +455,7 @@ module OsLib_ModelGeneration
|
|
|
448
455
|
hash['Classroom'] = { ratio: 0.4793, space_type_gen: true, default: true }
|
|
449
456
|
hash['ComputerRoom'] = { ratio: 0.0236, space_type_gen: true, default: true }
|
|
450
457
|
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}
|
|
458
|
+
hash['Gym'] = { ratio: 0.0520, space_type_gen: true, default: false }
|
|
452
459
|
hash['Kitchen'] = { ratio: 0.0244, space_type_gen: true, default: false }
|
|
453
460
|
hash['Library'] = { ratio: 0.0581, space_type_gen: true, default: false }
|
|
454
461
|
hash['Lobby'] = { ratio: 0.0249, space_type_gen: true, default: false }
|
|
@@ -494,7 +501,7 @@ module OsLib_ModelGeneration
|
|
|
494
501
|
hash['WholeBuilding - Md Office'] = { ratio: 0.0, space_type_gen: true, default: false }
|
|
495
502
|
end
|
|
496
503
|
elsif building_type == 'LargeOffice'
|
|
497
|
-
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004'].include?(template)
|
|
504
|
+
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004', 'ComStock DOE Ref Pre-1980', 'ComStock DOE Ref 1980-2004'].include?(template)
|
|
498
505
|
if whole_building
|
|
499
506
|
hash['WholeBuilding - Lg Office'] = { ratio: 1.0, space_type_gen: true, default: true }
|
|
500
507
|
else
|
|
@@ -538,7 +545,7 @@ module OsLib_ModelGeneration
|
|
|
538
545
|
end
|
|
539
546
|
end
|
|
540
547
|
elsif building_type == 'SmallHotel'
|
|
541
|
-
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004'].include?(template)
|
|
548
|
+
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004', 'ComStock DOE Ref Pre-1980', 'ComStock DOE Ref 1980-2004'].include?(template)
|
|
542
549
|
hash['Corridor'] = { ratio: 0.1313, space_type_gen: true, default: false, circ: true }
|
|
543
550
|
hash['Elec/MechRoom'] = { ratio: 0.0038, space_type_gen: true, default: false }
|
|
544
551
|
hash['ElevatorCore'] = { ratio: 0.0113, space_type_gen: true, default: false }
|
|
@@ -909,7 +916,6 @@ module OsLib_ModelGeneration
|
|
|
909
916
|
stories_flat = []
|
|
910
917
|
stories_flat_counter = 0
|
|
911
918
|
bar_hash[:stories].each_with_index do |(k, v), i|
|
|
912
|
-
#runner.registerInfo("STORY: k: #{k}, v: #{v}, index: #{i}")
|
|
913
919
|
# k is invalid in some cases, old story object that has been removed, should be from low to high including basement
|
|
914
920
|
# skip if source story insn't included in building area
|
|
915
921
|
if v[:story_included_in_building_area].nil? || (v[:story_included_in_building_area] == true)
|
|
@@ -1088,12 +1094,10 @@ module OsLib_ModelGeneration
|
|
|
1088
1094
|
|
|
1089
1095
|
# remove duplicate surfaces in a space (should be done after remove duplicate and collinear points)
|
|
1090
1096
|
model.getSpaces.sort.each do |space|
|
|
1091
|
-
|
|
1092
1097
|
# secondary array to compare against
|
|
1093
1098
|
surfaces_b = space.surfaces.sort
|
|
1094
1099
|
|
|
1095
1100
|
space.surfaces.sort.each do |surface_a|
|
|
1096
|
-
|
|
1097
1101
|
# delete from secondary array
|
|
1098
1102
|
surfaces_b.delete(surface_a)
|
|
1099
1103
|
|
|
@@ -1103,13 +1107,11 @@ module OsLib_ModelGeneration
|
|
|
1103
1107
|
runner.registerWarning("#{surface_a.name} and #{surface_b.name} in #{space.name} have duplicate geometry, removing #{surface_b.name}.")
|
|
1104
1108
|
surface_b.remove
|
|
1105
1109
|
elsif surface_a.reverseEqualVertices(surface_b)
|
|
1106
|
-
#
|
|
1110
|
+
# TODO: - add logic to determine which face naormal is reversed and which is correct
|
|
1107
1111
|
runner.registerWarning("#{surface_a.name} and #{surface_b.name} in #{space.name} have reversed geometry, removing #{surface_b.name}.")
|
|
1108
1112
|
surface_b.remove
|
|
1109
1113
|
end
|
|
1110
|
-
|
|
1111
1114
|
end
|
|
1112
|
-
|
|
1113
1115
|
end
|
|
1114
1116
|
end
|
|
1115
1117
|
|
|
@@ -1120,7 +1122,7 @@ module OsLib_ModelGeneration
|
|
|
1120
1122
|
model.getSpaces.sort.each do |space_a|
|
|
1121
1123
|
spaces_b.delete(space_a)
|
|
1122
1124
|
spaces_b.each do |space_b|
|
|
1123
|
-
#runner.registerInfo("Intersecting and matching surfaces between #{space_a.name} and #{space.name}")
|
|
1125
|
+
# runner.registerInfo("Intersecting and matching surfaces between #{space_a.name} and #{space.name}")
|
|
1124
1126
|
spaces_temp = OpenStudio::Model::SpaceVector.new
|
|
1125
1127
|
spaces_temp << space_a
|
|
1126
1128
|
spaces_temp << space_b
|
|
@@ -1130,7 +1132,7 @@ module OsLib_ModelGeneration
|
|
|
1130
1132
|
end
|
|
1131
1133
|
end
|
|
1132
1134
|
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
|
|
1135
|
+
else # elsif bar_hash[:double_loaded_corridor] # only intersect spaces in each story, not between wtory
|
|
1134
1136
|
model.getBuilding.buildingStories.sort.each do |story|
|
|
1135
1137
|
# intersect and surface match two pair by pair
|
|
1136
1138
|
spaces_b = story.spaces.sort
|
|
@@ -1161,7 +1163,7 @@ module OsLib_ModelGeneration
|
|
|
1161
1163
|
OpenStudio::Model.matchSurfaces(spaces)
|
|
1162
1164
|
runner.registerInfo('Intersecting and matching surfaces in model, this will create additional geometry.')
|
|
1163
1165
|
end
|
|
1164
|
-
else #elsif bar_hash[:double_loaded_corridor] # only intersect spaces in each story, not between wtory
|
|
1166
|
+
else # elsif bar_hash[:double_loaded_corridor] # only intersect spaces in each story, not between wtory
|
|
1165
1167
|
model.getBuilding.buildingStories.sort.each do |story|
|
|
1166
1168
|
story_spaces = OpenStudio::Model::SpaceVector.new
|
|
1167
1169
|
story.spaces.sort.each do |space|
|
|
@@ -1181,7 +1183,7 @@ module OsLib_ModelGeneration
|
|
|
1181
1183
|
model.getBuildingStorys.sort.each do |story|
|
|
1182
1184
|
next if !story.name.to_s.include?('Story B')
|
|
1183
1185
|
story.spaces.sort.each do |space|
|
|
1184
|
-
next if
|
|
1186
|
+
next if !new_spaces.include?(space)
|
|
1185
1187
|
space.surfaces.sort.each do |surface|
|
|
1186
1188
|
next if surface.surfaceType != 'Wall'
|
|
1187
1189
|
next if surface.outsideBoundaryCondition != 'Outdoors'
|
|
@@ -1194,9 +1196,9 @@ module OsLib_ModelGeneration
|
|
|
1194
1196
|
# sort stories (by name for now but need better way)
|
|
1195
1197
|
sorted_stories = {}
|
|
1196
1198
|
new_spaces.each do |space|
|
|
1197
|
-
next if !
|
|
1199
|
+
next if !space.buildingStory.is_initialized
|
|
1198
1200
|
story = space.buildingStory.get
|
|
1199
|
-
if !
|
|
1201
|
+
if !sorted_stories.key?(name.to_s)
|
|
1200
1202
|
sorted_stories[story.name.to_s] = story
|
|
1201
1203
|
end
|
|
1202
1204
|
end
|
|
@@ -1229,7 +1231,7 @@ module OsLib_ModelGeneration
|
|
|
1229
1231
|
party_wall_facades = stories_flat[i][:story_party_walls]
|
|
1230
1232
|
|
|
1231
1233
|
story.spaces.each do |space|
|
|
1232
|
-
next if
|
|
1234
|
+
next if !new_spaces.include?(space)
|
|
1233
1235
|
space.surfaces. each do |surface|
|
|
1234
1236
|
# set floor to adiabatic if requited
|
|
1235
1237
|
if adiabatic_floor && surface.surfaceType == 'Floor'
|
|
@@ -1325,7 +1327,6 @@ module OsLib_ModelGeneration
|
|
|
1325
1327
|
end
|
|
1326
1328
|
|
|
1327
1329
|
return new_spaces
|
|
1328
|
-
|
|
1329
1330
|
end
|
|
1330
1331
|
|
|
1331
1332
|
# make selected surfaces adiabatic
|
|
@@ -1393,7 +1394,7 @@ module OsLib_ModelGeneration
|
|
|
1393
1394
|
return bar
|
|
1394
1395
|
end
|
|
1395
1396
|
|
|
1396
|
-
def bar_hash_setup_run(runner,model,args,length,width,floor_height_si,center_of_footprint,space_types_hash,num_stories)
|
|
1397
|
+
def bar_hash_setup_run(runner, model, args, length, width, floor_height_si, center_of_footprint, space_types_hash, num_stories)
|
|
1397
1398
|
# create envelope
|
|
1398
1399
|
# populate bar_hash and create envelope with data from envelope_data_hash and user arguments
|
|
1399
1400
|
bar_hash = {}
|
|
@@ -1585,31 +1586,31 @@ module OsLib_ModelGeneration
|
|
|
1585
1586
|
roof_area = 0.0
|
|
1586
1587
|
new_spaces.each do |space|
|
|
1587
1588
|
space.surfaces.each do |surface|
|
|
1588
|
-
if surface.surfaceType ==
|
|
1589
|
+
if surface.surfaceType == 'Floor' && surface.outsideBoundaryCondition == 'Ground'
|
|
1589
1590
|
ground_floor_area += surface.netArea
|
|
1590
|
-
elsif surface.surfaceType ==
|
|
1591
|
+
elsif surface.surfaceType == 'RoofCeiling' && surface.outsideBoundaryCondition == 'Outdoors'
|
|
1591
1592
|
roof_area += surface.netArea
|
|
1592
1593
|
end
|
|
1593
1594
|
end
|
|
1594
1595
|
end
|
|
1595
|
-
#
|
|
1596
|
+
# TODO: - extend to address when top and or bottom story are not exposed via argument
|
|
1596
1597
|
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
|
|
1598
|
+
# runner.registerError("Ground exposed floor or Roof area is larger than footprint, likely inter-floor surface matching and intersection error.")
|
|
1599
|
+
# return false
|
|
1599
1600
|
|
|
1600
1601
|
# not providing adiabatic work around when top story is partial story.
|
|
1601
1602
|
if args['num_stories_above_grade'].to_f != args['num_stories_above_grade'].ceil
|
|
1602
|
-
runner.registerError(
|
|
1603
|
+
runner.registerError('Ground exposed floor or Roof area is larger than footprint, likely inter-floor surface matching and intersection error.')
|
|
1603
1604
|
return false
|
|
1604
1605
|
else
|
|
1605
|
-
runner.registerInfo(
|
|
1606
|
+
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
1607
|
match_error = true
|
|
1607
1608
|
end
|
|
1608
1609
|
else
|
|
1609
1610
|
match_error = false
|
|
1610
1611
|
end
|
|
1611
1612
|
|
|
1612
|
-
#
|
|
1613
|
+
# 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
1614
|
if match_error
|
|
1614
1615
|
|
|
1615
1616
|
# identify z value of top and bottom story
|
|
@@ -1635,35 +1636,34 @@ module OsLib_ModelGeneration
|
|
|
1635
1636
|
if space.buildingStory.get.nominalZCoordinate.get > bottom_story
|
|
1636
1637
|
# change floors
|
|
1637
1638
|
space.surfaces.each do |surface|
|
|
1638
|
-
next if
|
|
1639
|
-
surface.setOutsideBoundaryCondition(
|
|
1639
|
+
next if !(surface.surfaceType == 'Floor' && surface.outsideBoundaryCondition == 'Ground')
|
|
1640
|
+
surface.setOutsideBoundaryCondition('Adiabatic')
|
|
1640
1641
|
end
|
|
1641
1642
|
end
|
|
1642
1643
|
if space.buildingStory.get.nominalZCoordinate.get < top_story
|
|
1643
1644
|
# change ceilings
|
|
1644
1645
|
space.surfaces.each do |surface|
|
|
1645
|
-
next if
|
|
1646
|
-
surface.setOutsideBoundaryCondition(
|
|
1646
|
+
next if !(surface.surfaceType == 'RoofCeiling' && surface.outsideBoundaryCondition == 'Outdoors')
|
|
1647
|
+
surface.setOutsideBoundaryCondition('Adiabatic')
|
|
1647
1648
|
end
|
|
1648
1649
|
end
|
|
1649
1650
|
end
|
|
1650
1651
|
end
|
|
1651
1652
|
end
|
|
1652
1653
|
|
|
1653
|
-
#
|
|
1654
|
-
|
|
1655
|
-
def bar_from_building_type_ratios(model, runner, user_arguments)
|
|
1654
|
+
# bar_arg_check_setup
|
|
1655
|
+
def bar_arg_check_setup(model, runner, user_arguments, building_type_ratios = true)
|
|
1656
1656
|
|
|
1657
1657
|
# assign the user inputs to variables
|
|
1658
1658
|
args = OsLib_HelperMethods.createRunVariables(runner, model, user_arguments, arguments(model))
|
|
1659
1659
|
if !args then return false end
|
|
1660
1660
|
|
|
1661
1661
|
# add in arguments that may not be passed in
|
|
1662
|
-
if !args.
|
|
1663
|
-
args[
|
|
1662
|
+
if !args.key?('double_loaded_corridor')
|
|
1663
|
+
args['double_loaded_corridor'] = 'None' # use None when not in measure building type data may not contain this
|
|
1664
1664
|
end
|
|
1665
|
-
if !
|
|
1666
|
-
args[
|
|
1665
|
+
if !args.key?('perim_mult')
|
|
1666
|
+
args['perim_mult'] = 1.0 # will not make two bars for extended perimeter
|
|
1667
1667
|
end
|
|
1668
1668
|
|
|
1669
1669
|
# lookup and replace argument values from upstream measures
|
|
@@ -1689,10 +1689,12 @@ module OsLib_ModelGeneration
|
|
|
1689
1689
|
end
|
|
1690
1690
|
|
|
1691
1691
|
# check expected values of double arguments
|
|
1692
|
-
fraction_args = ['
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1692
|
+
fraction_args = ['wwr', 'party_wall_fraction']
|
|
1693
|
+
if building_type_ratios
|
|
1694
|
+
fraction_args << 'bldg_type_b_fract_bldg_area'
|
|
1695
|
+
fraction_args << 'bldg_type_c_fract_bldg_area'
|
|
1696
|
+
fraction_args << 'bldg_type_d_fract_bldg_area'
|
|
1697
|
+
end
|
|
1696
1698
|
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
1699
|
|
|
1698
1700
|
positive_args = ['total_bldg_floor_area']
|
|
@@ -1709,49 +1711,26 @@ module OsLib_ModelGeneration
|
|
|
1709
1711
|
'party_wall_stories_east',
|
|
1710
1712
|
'party_wall_stories_west',
|
|
1711
1713
|
'single_floor_area',
|
|
1712
|
-
'bar_width'
|
|
1714
|
+
'bar_width']
|
|
1713
1715
|
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
1716
|
|
|
1715
1717
|
# return false if any errors fail
|
|
1716
1718
|
if !fraction then return false end
|
|
1717
1719
|
if !positive then return false end
|
|
1718
|
-
if !one_or_greater
|
|
1719
|
-
if !non_neg
|
|
1720
|
+
return false if !one_or_greater
|
|
1721
|
+
return false if !non_neg
|
|
1720
1722
|
|
|
1721
|
-
|
|
1722
|
-
building_form_defaults = building_form_defaults(args['bldg_type_a'])
|
|
1723
|
+
return args
|
|
1723
1724
|
|
|
1724
|
-
|
|
1725
|
-
defaulted_args = []
|
|
1726
|
-
|
|
1727
|
-
if args['ns_to_ew_ratio'] == 0.0
|
|
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
|
|
1725
|
+
end
|
|
1731
1726
|
|
|
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
|
|
1727
|
+
# bar_from_building_type_ratios
|
|
1728
|
+
# used for varieties of measures that create bar from building type ratios
|
|
1729
|
+
def bar_from_building_type_ratios(model, runner, user_arguments)
|
|
1744
1730
|
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
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
|
|
1731
|
+
# prep arguments
|
|
1732
|
+
args = bar_arg_check_setup(model,runner,user_arguments)
|
|
1733
|
+
if !args then return false end
|
|
1755
1734
|
|
|
1756
1735
|
# check that sum of fractions for b,c, and d is less than 1.0 (so something is left for primary building type)
|
|
1757
1736
|
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 +1740,7 @@ module OsLib_ModelGeneration
|
|
|
1761
1740
|
end
|
|
1762
1741
|
|
|
1763
1742
|
# Make the standard applier
|
|
1764
|
-
standard = Standard.build(
|
|
1743
|
+
standard = Standard.build((args['template']).to_s)
|
|
1765
1744
|
|
|
1766
1745
|
# report initial condition of model
|
|
1767
1746
|
runner.registerInitialCondition("The building started with #{model.getSpaces.size} spaces.")
|
|
@@ -1791,14 +1770,14 @@ module OsLib_ModelGeneration
|
|
|
1791
1770
|
# gather data for bldg_type_a
|
|
1792
1771
|
building_type_hash[args['bldg_type_a']] = {}
|
|
1793
1772
|
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']
|
|
1773
|
+
# building_type_hash[args['bldg_type_a']][:num_units] = args['bldg_type_a_num_units']
|
|
1795
1774
|
building_type_hash[args['bldg_type_a']][:space_types] = get_space_types_from_building_type(args['bldg_type_a'], args['template'], true)
|
|
1796
1775
|
|
|
1797
1776
|
# gather data for bldg_type_b
|
|
1798
1777
|
if args['bldg_type_b_fract_bldg_area'] > 0
|
|
1799
1778
|
building_type_hash[args['bldg_type_b']] = {}
|
|
1800
1779
|
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']
|
|
1780
|
+
# building_type_hash[args['bldg_type_b']][:num_units] = args['bldg_type_b_num_units']
|
|
1802
1781
|
building_type_hash[args['bldg_type_b']][:space_types] = get_space_types_from_building_type(args['bldg_type_b'], args['template'], true)
|
|
1803
1782
|
end
|
|
1804
1783
|
|
|
@@ -1806,7 +1785,7 @@ module OsLib_ModelGeneration
|
|
|
1806
1785
|
if args['bldg_type_c_fract_bldg_area'] > 0
|
|
1807
1786
|
building_type_hash[args['bldg_type_c']] = {}
|
|
1808
1787
|
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']
|
|
1788
|
+
# building_type_hash[args['bldg_type_c']][:num_units] = args['bldg_type_c_num_units']
|
|
1810
1789
|
building_type_hash[args['bldg_type_c']][:space_types] = get_space_types_from_building_type(args['bldg_type_c'], args['template'], true)
|
|
1811
1790
|
end
|
|
1812
1791
|
|
|
@@ -1814,10 +1793,146 @@ module OsLib_ModelGeneration
|
|
|
1814
1793
|
if args['bldg_type_d_fract_bldg_area'] > 0
|
|
1815
1794
|
building_type_hash[args['bldg_type_d']] = {}
|
|
1816
1795
|
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']
|
|
1796
|
+
# building_type_hash[args['bldg_type_d']][:num_units] = args['bldg_type_d_num_units']
|
|
1818
1797
|
building_type_hash[args['bldg_type_d']][:space_types] = get_space_types_from_building_type(args['bldg_type_d'], args['template'], true)
|
|
1819
1798
|
end
|
|
1820
1799
|
|
|
1800
|
+
# call bar_from_building_space_type_ratios to generate bar
|
|
1801
|
+
bar_from_space_type_ratios(model, runner, user_arguments, args, building_type_hash)
|
|
1802
|
+
|
|
1803
|
+
return true
|
|
1804
|
+
|
|
1805
|
+
end
|
|
1806
|
+
|
|
1807
|
+
# bar_from_space_type_ratios
|
|
1808
|
+
# used for varieties of measures that create bar from space type or building type ratios
|
|
1809
|
+
# args and building_type_hash should both be nil or neither shoould be nill
|
|
1810
|
+
def bar_from_space_type_ratios(model, runner, user_arguments, args = nil, building_type_hash = nil)
|
|
1811
|
+
|
|
1812
|
+
# do not setup arguments if they were already passed in to this method
|
|
1813
|
+
if args.nil?
|
|
1814
|
+
# prep arguments
|
|
1815
|
+
args = bar_arg_check_setup(model,runner,user_arguments,false) # false stops it from checking args on used in bar_from_building_type_ratios
|
|
1816
|
+
if !args then return false end
|
|
1817
|
+
|
|
1818
|
+
# identify primary building type for building form defaults
|
|
1819
|
+
primary_building_type = "PrimarySchool" # see what building type represents the most floro area
|
|
1820
|
+
building_form_defaults = building_form_defaults(primary_building_type)
|
|
1821
|
+
|
|
1822
|
+
# process arg into hash
|
|
1823
|
+
space_type_hash_name = {}
|
|
1824
|
+
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 }
|
|
1825
|
+
|
|
1826
|
+
# create building type hasn from space type ratios
|
|
1827
|
+
building_type_hash = {}
|
|
1828
|
+
building_type_fraction_of_building = 0.0
|
|
1829
|
+
space_type_hash_name.each do |building_space_type,ratio|
|
|
1830
|
+
building_type = building_space_type.split("|")[0].strip
|
|
1831
|
+
space_type = building_space_type.split("|")[1].strip
|
|
1832
|
+
|
|
1833
|
+
# harvest height and circ info from get_space_types_from_building_type(building_type, template, whole_building = true)
|
|
1834
|
+
building_type_lookup_info = get_space_types_from_building_type(building_type,args['template'])
|
|
1835
|
+
if building_type_lookup_info.size == 0
|
|
1836
|
+
runner.registerWarning("#{building_type} looks like an invalid building type for #{args['template']}")
|
|
1837
|
+
end
|
|
1838
|
+
space_type_info_hash = {}
|
|
1839
|
+
if building_type_lookup_info.key?(space_type)
|
|
1840
|
+
if building_type_lookup_info[space_type].key?(:story_height)
|
|
1841
|
+
space_type_info_hash[:story_height] = building_type_lookup_info[space_type][:story_height]
|
|
1842
|
+
end
|
|
1843
|
+
if building_type_lookup_info[space_type].key?(:default)
|
|
1844
|
+
space_type_info_hash[:default] = building_type_lookup_info[space_type][:default]
|
|
1845
|
+
end
|
|
1846
|
+
if building_type_lookup_info[space_type].key?(:circ)
|
|
1847
|
+
space_type_info_hash[:circ] = building_type_lookup_info[space_type][:circ]
|
|
1848
|
+
end
|
|
1849
|
+
else
|
|
1850
|
+
runner.registerWarning("#{space_type} looks like an invalid space type for #{building_type}")
|
|
1851
|
+
end
|
|
1852
|
+
|
|
1853
|
+
# extend harvested data with custom ratios from space type ratio string argument.
|
|
1854
|
+
if building_type_hash.key?(building_type)
|
|
1855
|
+
building_type_hash[building_type][:frac_bldg_area] += ratio
|
|
1856
|
+
space_type_info_hash[:ratio] = ratio
|
|
1857
|
+
building_type_hash[building_type][:space_types][space_type] = space_type_info_hash
|
|
1858
|
+
else
|
|
1859
|
+
building_type_hash[building_type] = {}
|
|
1860
|
+
building_type_hash[building_type][:frac_bldg_area] = ratio
|
|
1861
|
+
space_type_info_hash[:ratio] = ratio
|
|
1862
|
+
space_types = {}
|
|
1863
|
+
space_types[space_type] = space_type_info_hash
|
|
1864
|
+
building_type_hash[building_type][:space_types] = space_types
|
|
1865
|
+
end
|
|
1866
|
+
building_type_fraction_of_building += ratio
|
|
1867
|
+
end
|
|
1868
|
+
|
|
1869
|
+
# todo - confirm if this will get normalized up/down later of if I should fix or stop here instead of just a warning
|
|
1870
|
+
if building_type_fraction_of_building > 1.0
|
|
1871
|
+
runner.registerWarning("Sum of Space Type Ratio of #{building_type_fraction_of_building} is greater than the expected value of 1.0")
|
|
1872
|
+
elsif building_type_fraction_of_building < 1.0
|
|
1873
|
+
runner.registerWarning("Sum of Space Type Ratio of #{building_type_fraction_of_building} is less than the expected value of 1.0")
|
|
1874
|
+
end
|
|
1875
|
+
|
|
1876
|
+
else # else is used when bar_from_building_type_ratio is used
|
|
1877
|
+
|
|
1878
|
+
# if aspect ratio, story height or wwr have argument value of 0 then use smart building type defaults
|
|
1879
|
+
primary_building_type = args['bldg_type_a']
|
|
1880
|
+
|
|
1881
|
+
end
|
|
1882
|
+
|
|
1883
|
+
# get defaults for the primary building type
|
|
1884
|
+
building_form_defaults = building_form_defaults(primary_building_type)
|
|
1885
|
+
|
|
1886
|
+
# store list of defaulted items
|
|
1887
|
+
defaulted_args = []
|
|
1888
|
+
|
|
1889
|
+
if args['ns_to_ew_ratio'] == 0.0
|
|
1890
|
+
args['ns_to_ew_ratio'] = building_form_defaults[:aspect_ratio]
|
|
1891
|
+
runner.registerInfo("0.0 value for aspect ratio will be replaced with smart default for #{primary_building_type} of #{building_form_defaults[:aspect_ratio]}.")
|
|
1892
|
+
end
|
|
1893
|
+
|
|
1894
|
+
if args['perim_mult'] == 0.0
|
|
1895
|
+
# if this is not defined then use default of 1.0
|
|
1896
|
+
if !building_form_defaults.has_key?(:perim_mult)
|
|
1897
|
+
args['perim_mult'] = 1.0
|
|
1898
|
+
else
|
|
1899
|
+
args['perim_mult'] = building_form_defaults[:perim_mult]
|
|
1900
|
+
end
|
|
1901
|
+
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]}.")
|
|
1902
|
+
elsif args['perim_mult'] < 1.0
|
|
1903
|
+
runner.registerError("Other than the smart default value of 0, the minimum perimeter multiplier should be equal to 1.0 or greater.")
|
|
1904
|
+
return false
|
|
1905
|
+
end
|
|
1906
|
+
|
|
1907
|
+
if args['floor_height'] == 0.0
|
|
1908
|
+
args['floor_height'] = building_form_defaults[:typical_story]
|
|
1909
|
+
runner.registerInfo("0.0 value for floor height will be replaced with smart default for #{primary_building_type} of #{building_form_defaults[:typical_story]}.")
|
|
1910
|
+
defaulted_args << 'floor_height'
|
|
1911
|
+
end
|
|
1912
|
+
# 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
|
|
1913
|
+
if args['wwr'] == 0.0
|
|
1914
|
+
args['wwr'] = building_form_defaults[:wwr]
|
|
1915
|
+
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]}.")
|
|
1916
|
+
end
|
|
1917
|
+
|
|
1918
|
+
# Make the standard applier
|
|
1919
|
+
standard = Standard.build("#{args['template']}")
|
|
1920
|
+
|
|
1921
|
+
# report initial condition of model
|
|
1922
|
+
runner.registerInitialCondition("The building started with #{model.getSpaces.size} spaces.")
|
|
1923
|
+
|
|
1924
|
+
# determine of ns_ew needs to be mirrored
|
|
1925
|
+
mirror_ns_ew = false
|
|
1926
|
+
rotation = model.getBuilding.northAxis
|
|
1927
|
+
if rotation > 45.0 && rotation < 135.0
|
|
1928
|
+
mirror_ns_ew = true
|
|
1929
|
+
elsif rotation > 45.0 && rotation < 135.0
|
|
1930
|
+
mirror_ns_ew = true
|
|
1931
|
+
end
|
|
1932
|
+
|
|
1933
|
+
# remove non-resource objects not removed by removing the building
|
|
1934
|
+
remove_non_resource_objects(runner, model)
|
|
1935
|
+
|
|
1821
1936
|
# creating space types for requested building types
|
|
1822
1937
|
building_type_hash.each do |building_type, building_type_hash|
|
|
1823
1938
|
runner.registerInfo("Creating Space Types for #{building_type}.")
|
|
@@ -1840,8 +1955,8 @@ module OsLib_ModelGeneration
|
|
|
1840
1955
|
# set color
|
|
1841
1956
|
test = standard.space_type_apply_rendering_color(space_type) # this uses openstudio-standards
|
|
1842
1957
|
if !test
|
|
1843
|
-
#
|
|
1844
|
-
#runner.registerWarning("Could not find color for #{args['template']} #{space_type.name}")
|
|
1958
|
+
# TODO: - once fixed in standards un-comment this
|
|
1959
|
+
# runner.registerWarning("Could not find color for #{args['template']} #{space_type.name}")
|
|
1845
1960
|
end
|
|
1846
1961
|
|
|
1847
1962
|
# extend hash to hold new space type object
|
|
@@ -1869,7 +1984,7 @@ module OsLib_ModelGeneration
|
|
|
1869
1984
|
runner.registerWarning('User-defined single floor area was used for calculation of total building floor area')
|
|
1870
1985
|
# add warning if custom_height_bar is true and applicable building type is selected
|
|
1871
1986
|
if args['custom_height_bar']
|
|
1872
|
-
runner.registerWarning(
|
|
1987
|
+
runner.registerWarning('Cannot use custom height bar with single floor area method, will not create custom height bar.')
|
|
1873
1988
|
args['custom_height_bar'] = false
|
|
1874
1989
|
end
|
|
1875
1990
|
else
|
|
@@ -1884,8 +1999,7 @@ module OsLib_ModelGeneration
|
|
|
1884
1999
|
building_type_hash = building_type_hash.sort_by { |k, v| v[:frac_bldg_area] }
|
|
1885
2000
|
end
|
|
1886
2001
|
building_type_hash.each do |building_type, building_type_hash|
|
|
1887
|
-
|
|
1888
|
-
if args["double_loaded_corridor"] == "Primary Space Type"
|
|
2002
|
+
if args['double_loaded_corridor'] == 'Primary Space Type'
|
|
1889
2003
|
|
|
1890
2004
|
# 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
2005
|
default_st = nil
|
|
@@ -1900,8 +2014,8 @@ module OsLib_ModelGeneration
|
|
|
1900
2014
|
runner.registerInfo("Combining #{default_st} and #{circ_st} into a group representing a double loaded corridor")
|
|
1901
2015
|
|
|
1902
2016
|
# add new item
|
|
1903
|
-
building_type_hash[:space_types][
|
|
1904
|
-
double_loaded_st = building_type_hash[:space_types][
|
|
2017
|
+
building_type_hash[:space_types]['Double Loaded Corridor'] = {}
|
|
2018
|
+
double_loaded_st = building_type_hash[:space_types]['Double Loaded Corridor']
|
|
1905
2019
|
double_loaded_st[:ratio] = building_type_hash[:space_types][default_st][:ratio] + building_type_hash[:space_types][circ_st][:ratio]
|
|
1906
2020
|
double_loaded_st[:double_loaded_corridor] = true
|
|
1907
2021
|
double_loaded_st[:space_type] = model.getBuilding
|
|
@@ -1936,21 +2050,21 @@ module OsLib_ModelGeneration
|
|
|
1936
2050
|
multi_height_space_types_hash[space_type][:wwr] = hash[:wwr]
|
|
1937
2051
|
end
|
|
1938
2052
|
else
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
2053
|
+
# only add wwr if 0 used for wwr arg and if space type has wwr as key
|
|
2054
|
+
space_types_hash[space_type] = { floor_area: final_floor_area, space_type: space_type }
|
|
2055
|
+
if hash.key?(:orig_ratio) then space_types_hash[space_type][:orig_ratio] = hash[:orig_ratio] end
|
|
2056
|
+
if args['wwr'] == 0 && hash.key?(:wwr)
|
|
2057
|
+
space_types_hash[space_type][:wwr] = hash[:wwr]
|
|
2058
|
+
end
|
|
2059
|
+
if hash[:double_loaded_corridor]
|
|
2060
|
+
space_types_hash[space_type][:children] = hash[:children]
|
|
2061
|
+
end
|
|
1948
2062
|
end
|
|
1949
2063
|
end
|
|
1950
2064
|
end
|
|
1951
2065
|
|
|
1952
2066
|
# resort if not sorted by building type
|
|
1953
|
-
if args['space_type_sort_logic'] ==
|
|
2067
|
+
if args['space_type_sort_logic'] == 'Size'
|
|
1954
2068
|
# added code to convert to hash. I use sort_by 3 other times, but those seem to be working fine as is now.
|
|
1955
2069
|
space_types_hash = Hash[space_types_hash.sort_by { |k, v| v[:floor_area] }]
|
|
1956
2070
|
end
|
|
@@ -1958,14 +2072,14 @@ module OsLib_ModelGeneration
|
|
|
1958
2072
|
# calculate targets for testing
|
|
1959
2073
|
target_areas = {} # used for checks
|
|
1960
2074
|
target_areas_cust_height = 0.0
|
|
1961
|
-
space_types_hash.each do |k,v|
|
|
2075
|
+
space_types_hash.each do |k, v|
|
|
1962
2076
|
if v.key?(:orig_ratio)
|
|
1963
2077
|
target_areas[k] = v[:orig_ratio] * total_bldg_floor_area_si
|
|
1964
2078
|
else
|
|
1965
2079
|
target_areas[k] = v[:floor_area]
|
|
1966
2080
|
end
|
|
1967
2081
|
end
|
|
1968
|
-
multi_height_space_types_hash.each do |k,v|
|
|
2082
|
+
multi_height_space_types_hash.each do |k, v|
|
|
1969
2083
|
if v.key?(:orig_ratio)
|
|
1970
2084
|
target_areas[k] = v[:orig_ratio] * total_bldg_floor_area_si
|
|
1971
2085
|
target_areas_cust_height += v[:orig_ratio] * total_bldg_floor_area_si
|
|
@@ -1980,19 +2094,19 @@ module OsLib_ModelGeneration
|
|
|
1980
2094
|
footprint_si = (total_bldg_floor_area_si - target_areas_cust_height) / num_stories.to_f
|
|
1981
2095
|
end
|
|
1982
2096
|
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
|
|
2097
|
+
min_allow_size = OpenStudio.convert(15.0, 'ft', 'm').get
|
|
2098
|
+
specified_bar_width_si = OpenStudio.convert(args['bar_width'], 'ft', 'm').get
|
|
1985
2099
|
|
|
1986
2100
|
# set custom width
|
|
1987
2101
|
if specified_bar_width_si > 0
|
|
1988
|
-
runner.registerInfo(
|
|
2102
|
+
runner.registerInfo('Ignoring perimeter multiplier argument when non zero width argument is used')
|
|
1989
2103
|
if footprint_si / specified_bar_width_si >= min_allow_size
|
|
1990
2104
|
width = specified_bar_width_si
|
|
1991
2105
|
length = footprint_si / width
|
|
1992
2106
|
else
|
|
1993
2107
|
length = min_allow_size
|
|
1994
2108
|
width = footprint_si / length
|
|
1995
|
-
runner.registerWarning(
|
|
2109
|
+
runner.registerWarning('User specified width results in a length that is too short, adjusting width to be narrower than specified.')
|
|
1996
2110
|
end
|
|
1997
2111
|
width_cust_height = specified_bar_width_si
|
|
1998
2112
|
else
|
|
@@ -2002,29 +2116,29 @@ module OsLib_ModelGeneration
|
|
|
2002
2116
|
end
|
|
2003
2117
|
length_cust_height = target_areas_cust_height / width_cust_height
|
|
2004
2118
|
if args['perim_mult'] > 1.0 && target_areas_cust_height > 0.0
|
|
2005
|
-
#
|
|
2006
|
-
runner.registerWarning(
|
|
2119
|
+
# TODO: - update tests that hit this warning
|
|
2120
|
+
runner.registerWarning('Ignoring perimeter multiplier for bar that represents custom height spaces.')
|
|
2007
2121
|
end
|
|
2008
2122
|
|
|
2009
2123
|
# check if dual bar is needed
|
|
2010
2124
|
dual_bar = false
|
|
2011
2125
|
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
|
|
2126
|
+
if length / width != args['ns_to_ew_ratio']
|
|
2127
|
+
|
|
2128
|
+
if args['ns_to_ew_ratio'] >= 1.0 && args['ns_to_ew_ratio'] > length / width
|
|
2129
|
+
runner.registerWarning("Can't meet target aspect ratio of #{args['ns_to_ew_ratio']}, Lowering it to #{length / width} ")
|
|
2130
|
+
args['ns_to_ew_ratio'] = length / width
|
|
2131
|
+
elsif args['ns_to_ew_ratio'] < 1.0 && args['ns_to_ew_ratio'] > length / width
|
|
2132
|
+
runner.registerWarning("Can't meet target aspect ratio of #{args['ns_to_ew_ratio']}, Increasing it to #{length / width} ")
|
|
2133
|
+
args['ns_to_ew_ratio'] = length / width
|
|
2020
2134
|
else
|
|
2021
2135
|
# 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'])
|
|
2136
|
+
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
2137
|
length_alt2 = length - length_alt1
|
|
2024
|
-
if [length_alt1,length_alt2].min >= min_allow_size
|
|
2138
|
+
if [length_alt1, length_alt2].min >= min_allow_size
|
|
2025
2139
|
dual_bar = true
|
|
2026
2140
|
else
|
|
2027
|
-
runner.registerInfo(
|
|
2141
|
+
runner.registerInfo('Second bar would be below minimum length, will model as single bar')
|
|
2028
2142
|
# swap length and width if single bar and aspect ratio less than 1
|
|
2029
2143
|
if args['ns_to_ew_ratio'] < 1.0
|
|
2030
2144
|
width = length
|
|
@@ -2034,7 +2148,7 @@ module OsLib_ModelGeneration
|
|
|
2034
2148
|
end
|
|
2035
2149
|
end
|
|
2036
2150
|
elsif args['perim_mult'] > 1.0 && args['bar_division_method'] == 'Multiple Space Types - Individual Stories Sliced'
|
|
2037
|
-
runner.registerInfo(
|
|
2151
|
+
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
2152
|
dual_bar = true
|
|
2039
2153
|
elsif args['perim_mult'] > 1.0
|
|
2040
2154
|
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 +2172,7 @@ module OsLib_ModelGeneration
|
|
|
2058
2172
|
# custom quadratic equation to solve two bars with common width 2l^2 - p*l + 4a = 0
|
|
2059
2173
|
if target_perim**2 - 32 * footprint_si > 0
|
|
2060
2174
|
if specified_bar_width_si > 0
|
|
2061
|
-
runner.registerInfo(
|
|
2175
|
+
runner.registerInfo('Ignoring perimeter multiplier argument and using use specified bar width.')
|
|
2062
2176
|
dual_double_end_width = specified_bar_width_si
|
|
2063
2177
|
dual_double_end_length = footprint_si / dual_double_end_width
|
|
2064
2178
|
else
|
|
@@ -2067,7 +2181,7 @@ module OsLib_ModelGeneration
|
|
|
2067
2181
|
end
|
|
2068
2182
|
|
|
2069
2183
|
# 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'])
|
|
2184
|
+
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
2185
|
bar_b_length = dual_double_end_length - bar_a_length
|
|
2072
2186
|
area_a = bar_a_length * dual_double_end_width
|
|
2073
2187
|
area_b = bar_b_length * dual_double_end_width
|
|
@@ -2086,15 +2200,15 @@ module OsLib_ModelGeneration
|
|
|
2086
2200
|
adiabatic_dual_double_end_width = footprint_si / adiabatic_dual_double_end_length
|
|
2087
2201
|
# test for unexpected
|
|
2088
2202
|
unexpected = false
|
|
2089
|
-
if (target_area - adiabatic_dual_double_end_length*adiabatic_dual_double_end_width).abs > tol_testing then unexpected = true end
|
|
2203
|
+
if (target_area - adiabatic_dual_double_end_length * adiabatic_dual_double_end_width).abs > tol_testing then unexpected = true end
|
|
2090
2204
|
if specified_bar_width_si == 0
|
|
2091
2205
|
if (target_perim - (adiabatic_dual_double_end_length * 2 + adiabatic_dual_double_end_width * 2)).abs > tol_testing then unexpected = true end
|
|
2092
2206
|
end
|
|
2093
2207
|
if unexpected
|
|
2094
|
-
runner.registerWarning(
|
|
2208
|
+
runner.registerWarning('Unexpected values for dual rectangle adiabatic ends bar b.')
|
|
2095
2209
|
end
|
|
2096
2210
|
# 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'])
|
|
2211
|
+
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
2212
|
adiabatic_bar_b_length = adiabatic_dual_double_end_length - adiabatic_bar_a_length
|
|
2099
2213
|
adiabatic_area_a = adiabatic_bar_a_length * adiabatic_dual_double_end_width
|
|
2100
2214
|
adiabatic_area_b = adiabatic_bar_b_length * adiabatic_dual_double_end_width
|
|
@@ -2113,28 +2227,28 @@ module OsLib_ModelGeneration
|
|
|
2113
2227
|
# apply prescribed approach for stretched or dual bar
|
|
2114
2228
|
if dual_bar_calc_approach == 'dual_bar'
|
|
2115
2229
|
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(
|
|
2230
|
+
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
|
|
2231
|
+
runner.registerWarning('Unexpected values for dual rectangle.')
|
|
2118
2232
|
end
|
|
2119
2233
|
|
|
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(
|
|
2234
|
+
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")
|
|
2235
|
+
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
|
|
2236
|
+
runner.registerWarning('Unexpected values for rotated dual rectangle')
|
|
2123
2237
|
end
|
|
2124
2238
|
elsif dual_bar_calc_approach == 'adiabatic_ends_bar_b'
|
|
2125
2239
|
runner.registerInfo("Can't hit target perimeter with two rectangles, need to make two ends adiabatic")
|
|
2126
2240
|
|
|
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(
|
|
2241
|
+
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")
|
|
2242
|
+
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
|
|
2243
|
+
runner.registerWarning('Unexpected values for rotated dual rectangle adiabatic ends bar b')
|
|
2130
2244
|
end
|
|
2131
2245
|
else # stretched bar
|
|
2132
2246
|
dual_bar = false
|
|
2133
2247
|
|
|
2134
2248
|
stretched_length = 0.25 * (target_perim + Math.sqrt(target_perim**2 - 16 * footprint_si))
|
|
2135
2249
|
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(
|
|
2250
|
+
if (target_area - stretched_length * stretched_width).abs > tol_testing || (target_perim - (stretched_length + stretched_width) * 2) > tol_testing
|
|
2251
|
+
runner.registerWarning('Unexpected values for single stretched')
|
|
2138
2252
|
end
|
|
2139
2253
|
|
|
2140
2254
|
width = stretched_width
|
|
@@ -2170,7 +2284,7 @@ module OsLib_ModelGeneration
|
|
|
2170
2284
|
end
|
|
2171
2285
|
bars['primary'][:floor_height_si] = floor_height_si # can make use of this when breaking out multi-height spaces
|
|
2172
2286
|
bars['primary'][:num_stories] = num_stories
|
|
2173
|
-
bars['primary'][:center_of_footprint] = OpenStudio::Point3d.new(0.0,0.0,0.0)
|
|
2287
|
+
bars['primary'][:center_of_footprint] = OpenStudio::Point3d.new(0.0, 0.0, 0.0)
|
|
2174
2288
|
space_types_hash_secondary = {}
|
|
2175
2289
|
if dual_bar
|
|
2176
2290
|
# loop through each story and move portion for other bar to its own hash
|
|
@@ -2179,9 +2293,9 @@ module OsLib_ModelGeneration
|
|
|
2179
2293
|
footprint_counter = primary_footprint
|
|
2180
2294
|
secondary_footprint_counter = secondary_footprint
|
|
2181
2295
|
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|
|
|
2296
|
+
pri_sec_tol = 0.0001 # m^2
|
|
2297
|
+
pri_sec_min_area = 0.0001 # m^2
|
|
2298
|
+
space_types_hash.each do |k, v|
|
|
2185
2299
|
space_type_left = v[:floor_area]
|
|
2186
2300
|
|
|
2187
2301
|
# do not go to next space type until this one is evaulate, which may span stories
|
|
@@ -2189,23 +2303,23 @@ module OsLib_ModelGeneration
|
|
|
2189
2303
|
|
|
2190
2304
|
# use secondary footprint if any left
|
|
2191
2305
|
if secondary_footprint_counter > 0.0
|
|
2192
|
-
hash_area = [space_type_left,secondary_footprint_counter].min
|
|
2306
|
+
hash_area = [space_type_left, secondary_footprint_counter].min
|
|
2193
2307
|
|
|
2194
2308
|
# confirm that the part of space type use or what is left is greater than min allowed value
|
|
2195
2309
|
projected_space_type_left = space_type_left - hash_area
|
|
2196
|
-
test_a =
|
|
2197
|
-
test_b =
|
|
2198
|
-
test_c =
|
|
2310
|
+
test_a = hash_area >= pri_sec_min_area
|
|
2311
|
+
test_b = projected_space_type_left >= pri_sec_min_area || projected_space_type_left == 0.0 ? true : false
|
|
2312
|
+
test_c = k == space_types_hash.keys.last # if last space type accept sliver, no other space to infil
|
|
2199
2313
|
if (test_a && test_b) || test_c
|
|
2200
|
-
if space_types_hash_secondary.
|
|
2314
|
+
if space_types_hash_secondary.key?(k)
|
|
2201
2315
|
# add to what was added for previous story
|
|
2202
2316
|
space_types_hash_secondary[k][:floor_area] += hash_area
|
|
2203
2317
|
else
|
|
2204
2318
|
# add new space type to hash
|
|
2205
|
-
if v.
|
|
2206
|
-
space_types_hash_secondary[k] = {:
|
|
2319
|
+
if v.key?(:children)
|
|
2320
|
+
space_types_hash_secondary[k] = { floor_area: hash_area, space_type: v[:space_type], children: v[:children] }
|
|
2207
2321
|
else
|
|
2208
|
-
space_types_hash_secondary[k] = {:
|
|
2322
|
+
space_types_hash_secondary[k] = { floor_area: hash_area, space_type: v[:space_type] }
|
|
2209
2323
|
end
|
|
2210
2324
|
end
|
|
2211
2325
|
space_types_hash[k][:floor_area] -= hash_area
|
|
@@ -2222,7 +2336,7 @@ module OsLib_ModelGeneration
|
|
|
2222
2336
|
space_type_left = 0.0
|
|
2223
2337
|
else
|
|
2224
2338
|
# then look at primary bar
|
|
2225
|
-
hash_area_pri = [space_type_left,footprint_counter].min
|
|
2339
|
+
hash_area_pri = [space_type_left, footprint_counter].min
|
|
2226
2340
|
footprint_counter -= hash_area_pri
|
|
2227
2341
|
space_type_left -= hash_area_pri
|
|
2228
2342
|
end
|
|
@@ -2247,13 +2361,13 @@ module OsLib_ModelGeneration
|
|
|
2247
2361
|
bars['primary'][:space_types_hash] = space_types_hash
|
|
2248
2362
|
bars['primary'][:args] = args
|
|
2249
2363
|
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])
|
|
2364
|
+
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
2365
|
|
|
2252
2366
|
# store offset value for multiple bars
|
|
2253
|
-
if args.
|
|
2367
|
+
if args.key?('bar_sep_dist_mult') && args['bar_sep_dist_mult'] > 0.0
|
|
2254
2368
|
offset_val = num_stories.ceil * floor_height_si * args['bar_sep_dist_mult']
|
|
2255
|
-
elsif args.
|
|
2256
|
-
runner.registerWarning(
|
|
2369
|
+
elsif args.key?('bar_sep_dist_mult')
|
|
2370
|
+
runner.registerWarning('Positive value is required for bar_sep_dist_mult, ignoring input and using value of 0.1')
|
|
2257
2371
|
offset_val = num_stories.ceil * floor_height_si * 0.1
|
|
2258
2372
|
else
|
|
2259
2373
|
offset_val = num_stories.ceil * floor_height_si * 10.0
|
|
@@ -2289,21 +2403,21 @@ module OsLib_ModelGeneration
|
|
|
2289
2403
|
else
|
|
2290
2404
|
runner.registerInfo('Adiabatic ends added to secondary bar because target perimeter multiplier could not be met with two full rectangular footprints.')
|
|
2291
2405
|
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)
|
|
2406
|
+
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
2407
|
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)
|
|
2408
|
+
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
2409
|
end
|
|
2296
2410
|
bars['secondary'][:args] = args2
|
|
2297
2411
|
|
|
2298
2412
|
# setup bar_hash and run create_bar
|
|
2299
2413
|
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])
|
|
2414
|
+
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
2415
|
|
|
2302
2416
|
end
|
|
2303
2417
|
|
|
2304
2418
|
# future development (up against primary bar run intersection and surface matching after add all bars, avoid interior windows)
|
|
2305
2419
|
# 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.
|
|
2420
|
+
if !multi_height_space_types_hash.empty?
|
|
2307
2421
|
args3 = args.clone
|
|
2308
2422
|
bars['custom_height'] = {}
|
|
2309
2423
|
if mirror_ns_ew
|
|
@@ -2314,7 +2428,7 @@ module OsLib_ModelGeneration
|
|
|
2314
2428
|
bars['custom_height'][:width] = width_cust_height
|
|
2315
2429
|
end
|
|
2316
2430
|
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(
|
|
2431
|
+
runner.registerWarning('Ignorning party wall inputs for custom height bar')
|
|
2318
2432
|
end
|
|
2319
2433
|
|
|
2320
2434
|
# disable party walls
|
|
@@ -2329,14 +2443,14 @@ module OsLib_ModelGeneration
|
|
|
2329
2443
|
|
|
2330
2444
|
bars['custom_height'][:floor_height_si] = floor_height_si # can make use of this when breaking out multi-height spaces
|
|
2331
2445
|
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
|
|
2446
|
+
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)
|
|
2447
|
+
bars['custom_height'][:floor_height_si] = OpenStudio.convert(custom_story_heights.max, 'ft', 'm').get
|
|
2334
2448
|
bars['custom_height'][:num_stories] = 1
|
|
2335
2449
|
bars['custom_height'][:space_types_hash] = multi_height_space_types_hash
|
|
2336
2450
|
bars['custom_height'][:args] = args3
|
|
2337
2451
|
|
|
2338
2452
|
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])
|
|
2453
|
+
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
2454
|
end
|
|
2341
2455
|
|
|
2342
2456
|
# diagnostic log
|
|
@@ -2388,37 +2502,37 @@ module OsLib_ModelGeneration
|
|
|
2388
2502
|
end
|
|
2389
2503
|
|
|
2390
2504
|
# 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
|
|
2505
|
+
wall_and_window_by_orientation = OsLib_Geometry.getExteriorWindowAndWllAreaByOrientation(model, model.getSpaces)
|
|
2392
2506
|
wall_ns = (wall_and_window_by_orientation['northWall'] + wall_and_window_by_orientation['southWall'])
|
|
2393
2507
|
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')
|
|
2508
|
+
wall_ns_ip = OpenStudio.convert(wall_ns, 'm^2', 'ft^2').get
|
|
2509
|
+
wall_ew_ip = OpenStudio.convert(wall_ew, 'm^2', 'ft^2').get
|
|
2510
|
+
runner.registerValue('wall_area_ip', wall_ns_ip + wall_ew_ip, 'ft^2')
|
|
2511
|
+
runner.registerValue('ns_wall_area_ip', wall_ns_ip, 'ft^2')
|
|
2512
|
+
runner.registerValue('ew_wall_area_ip', wall_ew_ip, 'ft^2')
|
|
2399
2513
|
# 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')
|
|
2514
|
+
runner.registerValue('floor_area_to_perim_ratio', model.getBuilding.floorArea / (OsLib_Geometry.calculate_perimeter(model) * num_stories))
|
|
2515
|
+
runner.registerValue('bar_width', OpenStudio.convert(bars['primary'][:width], 'm', 'ft').get, 'ft')
|
|
2402
2516
|
|
|
2403
2517
|
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(
|
|
2518
|
+
runner.registerInfo('Target facade area by orientation not validated when party walls are applied')
|
|
2405
2519
|
elsif args['num_stories_above_grade'] != args['num_stories_above_grade'].ceil
|
|
2406
|
-
runner.registerInfo(
|
|
2520
|
+
runner.registerInfo('Target facade area by orientation not validated when partial top story is used')
|
|
2407
2521
|
elsif dual_bar_calc_approach == 'stretched'
|
|
2408
|
-
runner.registerInfo(
|
|
2409
|
-
elsif defaulted_args.include?('floor_height')
|
|
2410
|
-
runner.registerInfo(
|
|
2522
|
+
runner.registerInfo('Target facade area by orientation not validated when single stretched bar has to be used to meet target minimum perimeter multiplier')
|
|
2523
|
+
elsif defaulted_args.include?('floor_height') && args['custom_height_bar'] && !multi_height_space_types_hash.empty?
|
|
2524
|
+
runner.registerInfo('Target facade area by orientation not validated when a dedicated bar is added for space types with custom heights')
|
|
2411
2525
|
elsif args['bar_width'] > 0
|
|
2412
|
-
runner.registerInfo(
|
|
2526
|
+
runner.registerInfo('Target facade area by orientation not validated when a dedicated custom bar width is defined')
|
|
2413
2527
|
else
|
|
2414
2528
|
|
|
2415
2529
|
# adjust length versus width based on building rotation
|
|
2416
2530
|
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
|
|
2531
|
+
wall_target_ns_ip = 2 * OpenStudio.convert(width, 'm', 'ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
|
2532
|
+
wall_target_ew_ip = 2 * OpenStudio.convert(length, 'm', 'ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
|
2419
2533
|
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']
|
|
2534
|
+
wall_target_ns_ip = 2 * OpenStudio.convert(length, 'm', 'ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
|
2535
|
+
wall_target_ew_ip = 2 * OpenStudio.convert(width, 'm', 'ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
|
2422
2536
|
end
|
|
2423
2537
|
flag_error = false
|
|
2424
2538
|
if (wall_target_ns_ip - wall_ns_ip).abs > 0.1
|
|
@@ -2458,7 +2572,6 @@ module OsLib_ModelGeneration
|
|
|
2458
2572
|
# typical
|
|
2459
2573
|
# used for varieties of measures that create typical building from model
|
|
2460
2574
|
def typical_building_from_model(model, runner, user_arguments)
|
|
2461
|
-
|
|
2462
2575
|
# assign the user inputs to variables
|
|
2463
2576
|
args = OsLib_HelperMethods.createRunVariables(runner, model, user_arguments, arguments(model))
|
|
2464
2577
|
if !args then return false end
|
|
@@ -2528,7 +2641,7 @@ module OsLib_ModelGeneration
|
|
|
2528
2641
|
end
|
|
2529
2642
|
|
|
2530
2643
|
# 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
|
|
2644
|
+
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
2645
|
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
2646
|
end
|
|
2534
2647
|
end
|
|
@@ -2568,7 +2681,7 @@ module OsLib_ModelGeneration
|
|
|
2568
2681
|
end
|
|
2569
2682
|
|
|
2570
2683
|
# 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
|
|
2684
|
+
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
2685
|
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
2686
|
end
|
|
2574
2687
|
end
|
|
@@ -2584,7 +2697,7 @@ module OsLib_ModelGeneration
|
|
|
2584
2697
|
standard = Standard.build((args['template']).to_s)
|
|
2585
2698
|
|
|
2586
2699
|
# validate climate zone
|
|
2587
|
-
if !args.
|
|
2700
|
+
if !args.key?('climate_zone') || args['climate_zone'] == 'Lookup From Model'
|
|
2588
2701
|
climate_zone = standard.model_get_building_climate_zone_and_building_type(model)['climate_zone']
|
|
2589
2702
|
runner.registerInfo("Using climate zone #{climate_zone} from model")
|
|
2590
2703
|
else
|
|
@@ -2679,8 +2792,10 @@ module OsLib_ModelGeneration
|
|
|
2679
2792
|
# TODO: - allow building type and space type specific constructions set selection.
|
|
2680
2793
|
if ['SmallHotel', 'LargeHotel', 'MidriseApartment', 'HighriseApartment'].include?(primary_bldg_type)
|
|
2681
2794
|
is_residential = 'Yes'
|
|
2795
|
+
occ_type = 'Residential'
|
|
2682
2796
|
else
|
|
2683
2797
|
is_residential = 'No'
|
|
2798
|
+
occ_type = 'Nonresidential'
|
|
2684
2799
|
end
|
|
2685
2800
|
bldg_def_const_set = standard.model_add_construction_set(model, climate_zone, lookup_building_type, nil, is_residential)
|
|
2686
2801
|
if bldg_def_const_set.is_initialized
|
|
@@ -2694,6 +2809,31 @@ module OsLib_ModelGeneration
|
|
|
2694
2809
|
return false
|
|
2695
2810
|
end
|
|
2696
2811
|
|
|
2812
|
+
# Replace the construction of any outdoor-facing "AtticFloor" surfaces
|
|
2813
|
+
# with the "ExteriorRoof" - "IEAD" construction for the specific climate zone and template.
|
|
2814
|
+
# This prevents creation of buildings where the DOE Prototype building construction set
|
|
2815
|
+
# assumes an attic but the supplied geometry used does not have an attic.
|
|
2816
|
+
new_construction = nil
|
|
2817
|
+
climate_zone_set = standard.model_find_climate_zone_set(model, climate_zone)
|
|
2818
|
+
model.getSurfaces.sort.each do |surf|
|
|
2819
|
+
next unless surf.outsideBoundaryCondition == 'Outdoors'
|
|
2820
|
+
next unless surf.surfaceType == 'RoofCeiling'
|
|
2821
|
+
next if surf.construction.empty?
|
|
2822
|
+
construction = surf.construction.get
|
|
2823
|
+
standards_info = construction.standardsInformation
|
|
2824
|
+
next if standards_info.intendedSurfaceType.empty?
|
|
2825
|
+
next unless standards_info.intendedSurfaceType.get == 'AtticFloor'
|
|
2826
|
+
if new_construction.nil?
|
|
2827
|
+
new_construction = standard.model_find_and_add_construction(model,
|
|
2828
|
+
climate_zone_set,
|
|
2829
|
+
'ExteriorRoof',
|
|
2830
|
+
'IEAD',
|
|
2831
|
+
occ_type)
|
|
2832
|
+
end
|
|
2833
|
+
surf.setConstruction(new_construction)
|
|
2834
|
+
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.")
|
|
2835
|
+
end
|
|
2836
|
+
|
|
2697
2837
|
# address any adiabatic surfaces that don't have hard assigned constructions
|
|
2698
2838
|
model.getSurfaces.sort.each do |surface|
|
|
2699
2839
|
next if surface.outsideBoundaryCondition != 'Adiabatic'
|
|
@@ -2735,8 +2875,9 @@ module OsLib_ModelGeneration
|
|
|
2735
2875
|
elevator_def = elevators.electricEquipmentDefinition
|
|
2736
2876
|
design_level = elevator_def.designLevel.get
|
|
2737
2877
|
runner.registerInfo("Adding #{elevators.multiplier.round(1)} elevators each with power of #{OpenStudio.toNeatString(design_level, 0, true)} (W), plus lights and fans.")
|
|
2738
|
-
elevator_def.
|
|
2878
|
+
elevator_def.setFractionLatent(0.0)
|
|
2739
2879
|
elevator_def.setFractionRadiant(0.0)
|
|
2880
|
+
elevator_def.setFractionLost(1.0)
|
|
2740
2881
|
end
|
|
2741
2882
|
end
|
|
2742
2883
|
|
|
@@ -2837,13 +2978,13 @@ module OsLib_ModelGeneration
|
|
|
2837
2978
|
end
|
|
2838
2979
|
|
|
2839
2980
|
# add daylight controls, need to perform a sizing run for 2010
|
|
2840
|
-
if args['template'] == '90.1-2010'
|
|
2981
|
+
if args['template'] == '90.1-2010' || args['template'] == 'ComStock 90.1-2010'
|
|
2841
2982
|
if standard.model_run_sizing_run(model, "#{Dir.pwd}/SRvt") == false
|
|
2842
2983
|
log_messages_to_runner(runner, debug = true)
|
|
2843
2984
|
return false
|
|
2844
2985
|
end
|
|
2845
2986
|
end
|
|
2846
|
-
|
|
2987
|
+
standard.model_add_daylighting_controls(model)
|
|
2847
2988
|
end
|
|
2848
2989
|
|
|
2849
2990
|
# add refrigeration
|
|
@@ -2970,7 +3111,10 @@ module OsLib_ModelGeneration
|
|
|
2970
3111
|
end
|
|
2971
3112
|
|
|
2972
3113
|
# Add the primary system to the primary zones
|
|
2973
|
-
standard.model_add_hvac_system(model, sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, system_zones)
|
|
3114
|
+
unless standard.model_add_hvac_system(model, sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, system_zones)
|
|
3115
|
+
runner.registerError("HVAC system type '#{sys_type}' not recognized. Check input system type argument against Model.hvac.rb for valid hvac system type names.")
|
|
3116
|
+
return false
|
|
3117
|
+
end
|
|
2974
3118
|
|
|
2975
3119
|
# Add the secondary system to the secondary zones (if any)
|
|
2976
3120
|
if !pri_sec_zone_lists['secondary'].empty?
|
|
@@ -2980,7 +3124,10 @@ module OsLib_ModelGeneration
|
|
|
2980
3124
|
cooled_only_zones = system_zones.select { |zone| !standard.thermal_zone_heated?(zone) && standard.thermal_zone_cooled?(zone) }
|
|
2981
3125
|
system_zones = heated_and_cooled_zones + cooled_only_zones
|
|
2982
3126
|
end
|
|
2983
|
-
standard.model_add_hvac_system(model, sec_sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, system_zones)
|
|
3127
|
+
unless standard.model_add_hvac_system(model, sec_sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, system_zones)
|
|
3128
|
+
runner.registerError("HVAC system type '#{sys_type}' not recognized. Check input system type argument against Model.hvac.rb for valid hvac system type names.")
|
|
3129
|
+
return false
|
|
3130
|
+
end
|
|
2984
3131
|
end
|
|
2985
3132
|
end
|
|
2986
3133
|
end
|
|
@@ -2996,7 +3143,10 @@ module OsLib_ModelGeneration
|
|
|
2996
3143
|
# Add the user specified HVAC system for each story.
|
|
2997
3144
|
# Single-zone systems will get one per zone.
|
|
2998
3145
|
story_groups.each do |zones|
|
|
2999
|
-
model.add_cbecs_hvac_system(standard, args['system_type'], zones)
|
|
3146
|
+
unless model.add_cbecs_hvac_system(standard, args['system_type'], zones)
|
|
3147
|
+
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.")
|
|
3148
|
+
return false
|
|
3149
|
+
end
|
|
3000
3150
|
end
|
|
3001
3151
|
end
|
|
3002
3152
|
end
|
|
@@ -3044,7 +3194,7 @@ module OsLib_ModelGeneration
|
|
|
3044
3194
|
if args['add_hvac']
|
|
3045
3195
|
# set additional properties for building
|
|
3046
3196
|
props = model.getBuilding.additionalProperties
|
|
3047
|
-
props.setFeature('hvac_system_type',
|
|
3197
|
+
props.setFeature('hvac_system_type', (args['system_type']).to_s)
|
|
3048
3198
|
|
|
3049
3199
|
case args['system_type']
|
|
3050
3200
|
when 'Ideal Air Loads'
|
|
@@ -3102,6 +3252,15 @@ module OsLib_ModelGeneration
|
|
|
3102
3252
|
end
|
|
3103
3253
|
end
|
|
3104
3254
|
|
|
3255
|
+
# change night cycling control to "Thermostat" cycling and increase thermostat tolerance to 1.99999
|
|
3256
|
+
manager_night_cycles = model.getAvailabilityManagerNightCycles
|
|
3257
|
+
|
|
3258
|
+
manager_night_cycles.each do |night_cycle|
|
|
3259
|
+
night_cycle.setThermostatTolerance(1.9999)
|
|
3260
|
+
night_cycle.setCyclingRunTimeControlType("Thermostat")
|
|
3261
|
+
runner.registerInfo(" night_cycle == #{night_cycle}")
|
|
3262
|
+
end
|
|
3263
|
+
|
|
3105
3264
|
# report final condition of model
|
|
3106
3265
|
runner.registerFinalCondition("The building finished with #{model.getModelObjects.size} objects.")
|
|
3107
3266
|
|
|
@@ -3114,7 +3273,6 @@ module OsLib_ModelGeneration
|
|
|
3114
3273
|
# wizard
|
|
3115
3274
|
# used for varieties of measures that create space type and construction set wizard
|
|
3116
3275
|
def wizard(model, runner, user_arguments)
|
|
3117
|
-
|
|
3118
3276
|
# use the built-in error checking
|
|
3119
3277
|
if !runner.validateUserArguments(arguments(model), user_arguments)
|
|
3120
3278
|
return false
|
|
@@ -3158,7 +3316,7 @@ module OsLib_ModelGeneration
|
|
|
3158
3316
|
lookup_building_type = standard.model_get_lookup_name(building_type)
|
|
3159
3317
|
|
|
3160
3318
|
# remap small medium and large office to office
|
|
3161
|
-
if building_type.include?(
|
|
3319
|
+
if building_type.include?('Office') then building_type = 'Office' end
|
|
3162
3320
|
|
|
3163
3321
|
# get array of new space types
|
|
3164
3322
|
space_types_new = []
|
|
@@ -3286,4 +3444,4 @@ module OsLib_ModelGeneration
|
|
|
3286
3444
|
|
|
3287
3445
|
return true
|
|
3288
3446
|
end
|
|
3289
|
-
end
|
|
3447
|
+
end
|