openstudio-extension 0.3.1 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/.rubocop.yml +2 -1
  4. data/CHANGELOG.md +38 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.md +1 -1
  7. data/Rakefile +4 -4
  8. data/doc_templates/LICENSE.md +1 -1
  9. data/doc_templates/copyright_erb.txt +1 -1
  10. data/doc_templates/copyright_js.txt +1 -1
  11. data/doc_templates/copyright_ruby.txt +1 -1
  12. data/init_templates/gemspec.txt +7 -5
  13. data/init_templates/openstudio_module.rb +1 -1
  14. data/init_templates/spec.rb +1 -1
  15. data/init_templates/spec_helper.rb +1 -1
  16. data/init_templates/template_gemfile.txt +1 -4
  17. data/init_templates/version.rb +1 -1
  18. data/lib/change_log.rb +2 -2
  19. data/lib/measures/openstudio_extension_test_measure/LICENSE.md +1 -1
  20. data/lib/measures/openstudio_extension_test_measure/measure.rb +1 -1
  21. data/lib/measures/openstudio_extension_test_measure/measure.xml +12 -12
  22. data/lib/measures/openstudio_extension_test_measure/resources/os_lib_helper_methods.rb +15 -2
  23. data/lib/openstudio-extension.rb +1 -1
  24. data/lib/openstudio/extension.rb +6 -10
  25. data/lib/openstudio/extension/core/CreateResults.rb +1 -1
  26. data/lib/openstudio/extension/core/check_air_sys_temps.rb +1 -1
  27. data/lib/openstudio/extension/core/check_calibration.rb +1 -1
  28. data/lib/openstudio/extension/core/check_cond_zns.rb +1 -1
  29. data/lib/openstudio/extension/core/check_domestic_hot_water.rb +1 -1
  30. data/lib/openstudio/extension/core/check_envelope_conductance.rb +1 -1
  31. data/lib/openstudio/extension/core/check_eui_by_end_use.rb +1 -1
  32. data/lib/openstudio/extension/core/check_eui_reasonableness.rb +1 -1
  33. data/lib/openstudio/extension/core/check_fan_pwr.rb +1 -1
  34. data/lib/openstudio/extension/core/check_internal_loads.rb +1 -1
  35. data/lib/openstudio/extension/core/check_mech_sys_capacity.rb +1 -1
  36. data/lib/openstudio/extension/core/check_mech_sys_efficiency.rb +1 -1
  37. data/lib/openstudio/extension/core/check_mech_sys_part_load_eff.rb +1 -1
  38. data/lib/openstudio/extension/core/check_mech_sys_type.rb +1 -1
  39. data/lib/openstudio/extension/core/check_part_loads.rb +1 -1
  40. data/lib/openstudio/extension/core/check_placeholder.rb +1 -1
  41. data/lib/openstudio/extension/core/check_plant_cap.rb +1 -1
  42. data/lib/openstudio/extension/core/check_plant_temps.rb +1 -1
  43. data/lib/openstudio/extension/core/check_plenum_loads.rb +1 -1
  44. data/lib/openstudio/extension/core/check_pump_pwr.rb +1 -1
  45. data/lib/openstudio/extension/core/check_sch_coord.rb +1 -1
  46. data/lib/openstudio/extension/core/check_schedules.rb +1 -1
  47. data/lib/openstudio/extension/core/check_simultaneous_heating_and_cooling.rb +1 -1
  48. data/lib/openstudio/extension/core/check_supply_air_and_thermostat_temp_difference.rb +1 -1
  49. data/lib/openstudio/extension/core/check_weather_files.rb +1 -1
  50. data/lib/openstudio/extension/core/deer_vintages.rb +1 -1
  51. data/lib/openstudio/extension/core/os_lib_aedg_measures.rb +5 -5
  52. data/lib/openstudio/extension/core/os_lib_constructions.rb +1 -1
  53. data/lib/openstudio/extension/core/os_lib_geometry.rb +1 -1
  54. data/lib/openstudio/extension/core/os_lib_helper_methods.rb +17 -3
  55. data/lib/openstudio/extension/core/os_lib_hvac.rb +1 -1
  56. data/lib/openstudio/extension/core/os_lib_lighting_and_equipment.rb +1 -1
  57. data/lib/openstudio/extension/core/os_lib_model_generation.rb +364 -207
  58. data/lib/openstudio/extension/core/os_lib_model_simplification.rb +1 -1
  59. data/lib/openstudio/extension/core/os_lib_outdoorair_and_infiltration.rb +1 -1
  60. data/lib/openstudio/extension/core/os_lib_reporting_qaqc.rb +1 -1
  61. data/lib/openstudio/extension/core/os_lib_schedules.rb +1 -1
  62. data/lib/openstudio/extension/rake_task.rb +17 -14
  63. data/lib/openstudio/extension/runner.rb +47 -35
  64. data/lib/openstudio/extension/runner_config.rb +1 -1
  65. data/lib/openstudio/extension/version.rb +2 -2
  66. data/openstudio-extension.gemspec +9 -8
  67. metadata +34 -19
@@ -1,5 +1,5 @@
1
1
  # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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 Façade Lighting'
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 Owners Project Requirements and Basis of Design'
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 Façade Lighting'
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 Owners Project Requirements (OPR) and Basis of Design (BoD)'
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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 = arg.valueAsVariant.to_s
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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-2020, Alliance for Sustainable Energy, LLC.
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 != nil
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 != nil
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 , story_height: 26.0 }
411
- hash['Gym - audience'] = { ratio: 0.0637, space_type_gen: true, default: false , story_height: 26.0 }
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 , story_height: 26.0 }
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
- # todo - add logic to determine which face naormal is reversed and which is correct
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 not new_spaces.include?(space)
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 ! space.buildingStory.is_initialized
1199
+ next if !space.buildingStory.is_initialized
1198
1200
  story = space.buildingStory.get
1199
- if ! sorted_stories.has_key?(name.to_s)
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 not new_spaces.include?(space)
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 == "Floor" && surface.outsideBoundaryCondition == "Ground"
1589
+ if surface.surfaceType == 'Floor' && surface.outsideBoundaryCondition == 'Ground'
1589
1590
  ground_floor_area += surface.netArea
1590
- elsif surface.surfaceType == "RoofCeiling" && surface.outsideBoundaryCondition == "Outdoors"
1591
+ elsif surface.surfaceType == 'RoofCeiling' && surface.outsideBoundaryCondition == 'Outdoors'
1591
1592
  roof_area += surface.netArea
1592
1593
  end
1593
1594
  end
1594
1595
  end
1595
- # todo - extend to address when top and or bottom story are not exposed via argument
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("Ground exposed floor or Roof area is larger than footprint, likely inter-floor surface matching and intersection error.")
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("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
+ 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
- # 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
+ # 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 not surface.surfaceType == "Floor" && surface.outsideBoundaryCondition == "Ground"
1639
- surface.setOutsideBoundaryCondition("Adiabatic")
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 not surface.surfaceType == "RoofCeiling" && surface.outsideBoundaryCondition == "Outdoors"
1646
- surface.setOutsideBoundaryCondition("Adiabatic")
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
- # bar_from_building_type_ratios
1654
- # used for varieties of measures that create bar from building type ratios
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.has_key?("double_loaded_corridor")
1663
- args["double_loaded_corridor"] = "None" # use None when not in measure building type data may not contain this
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 ! args.has_key?("perim_mult")
1666
- args["perim_mult"] = 1.0 # will not make two bars for extended perimeter
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 = ['bldg_type_b_fract_bldg_area',
1693
- 'bldg_type_c_fract_bldg_area',
1694
- 'bldg_type_d_fract_bldg_area',
1695
- 'wwr', 'party_wall_fraction']
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 then return false end
1719
- if !non_neg then return false end
1720
-
1721
- # if aspect ratio, story height or wwr have argument value of 0 then use smart building type defaults
1722
- building_form_defaults = building_form_defaults(args['bldg_type_a'])
1720
+ return false if !one_or_greater
1721
+ return false if !non_neg
1723
1722
 
1724
- # store list of defaulted items
1725
- defaulted_args = []
1723
+ return args
1726
1724
 
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
- if args['perim_mult'] == 0.0
1733
- # if this is not defined then use default of 1.0
1734
- if !building_form_defaults.has_key?(:perim_mult)
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
- if args['floor_height'] == 0.0
1746
- args['floor_height'] = building_form_defaults[:typical_story]
1747
- runner.registerInfo("0.0 value for floor height will be replaced with smart default for #{args['bldg_type_a']} of #{building_form_defaults[:typical_story]}.")
1748
- defaulted_args << 'floor_height'
1749
- end
1750
- # because of this can't set wwr to 0.0. If that is desired then we can change this to check for 1.0 instead of 0.0
1751
- if args['wwr'] == 0.0
1752
- args['wwr'] = building_form_defaults[:wwr]
1753
- runner.registerInfo("0.0 value for window to wall ratio will be replaced with smart default for #{args['bldg_type_a']} of #{building_form_defaults[:wwr]}.")
1754
- end
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("#{args['template']}")
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
- # todo - once fixed in standards un-comment this
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("Cannot use custom height bar with single floor area method, will not create custom height bar.")
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]["Double Loaded Corridor"] = {}
1904
- double_loaded_st = building_type_hash[:space_types]["Double Loaded Corridor"]
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
- # only add wwr if 0 used for wwr arg and if space type has wwr as key
1940
- space_types_hash[space_type] = { floor_area: final_floor_area, space_type: space_type }
1941
- if hash.key?(:orig_ratio) then space_types_hash[space_type][:orig_ratio] = hash[:orig_ratio] end
1942
- if args['wwr'] == 0 && hash.key?(:wwr)
1943
- space_types_hash[space_type][:wwr] = hash[:wwr]
1944
- end
1945
- if hash[:double_loaded_corridor]
1946
- space_types_hash[space_type][:children] = hash[:children]
1947
- end
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'] == "Size"
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("Ignoring perimeter multiplier argument when non zero width argument is used")
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("User specified width results in a length that is too short, adjusting width to be narrower than specified.")
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
- # todo - update tests that hit this warning
2006
- runner.registerWarning("Ignoring perimeter multiplier for bar that represents custom height spaces.")
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("Second bar would be below minimum length, will model as single bar")
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("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.")
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("Ignoring perimeter multiplier argument and using use specified bar width.")
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("Unexpected values for dual rectangle adiabatic ends bar b.")
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("Unexpected values for dual rectangle.")
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("Unexpected values for rotated dual rectangle")
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("Unexpected values for rotated dual rectangle adiabatic ends bar b")
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("Unexpected values for single stretched")
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 = if hash_area >= pri_sec_min_area then true else false end
2197
- test_b = if projected_space_type_left >= pri_sec_min_area || projected_space_type_left == 0.0 then true else false end
2198
- test_c = if k == space_types_hash.keys.last then true else false end # if last space type accept sliver, no other space to infil
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.has_key?(k)
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.has_key?(:children)
2206
- space_types_hash_secondary[k] = {:floor_area => hash_area, :space_type => v[:space_type], :children => v[:children],}
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] = {:floor_area => hash_area, :space_type => v[:space_type]}
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.has_key?('bar_sep_dist_mult') && args['bar_sep_dist_mult'] > 0.0
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.has_key?('bar_sep_dist_mult')
2256
- runner.registerWarning("Positive valu eis required for bar_sep_dist_mult, ignoring input and using value of 0.1")
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.size > 0
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("Ignorning party wall inputs for custom height bar")
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.sort)
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 / (OsLib_Geometry.calculate_perimeter(model) * num_stories))
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("Target facade area by orientation not validated when party walls are applied")
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("Target facade area by orientation not validated when partial top story is used")
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("Target facade area by orientation not validated when single stretched bar has to be used to meet target minimum perimeter multiplier")
2409
- elsif defaulted_args.include?('floor_height') && args['custom_height_bar'] && multi_height_space_types_hash.size > 0
2410
- runner.registerInfo("Target facade area by orientation not validated when a dedicated bar is added for space types with custom heights")
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("Target facade area by orientation not validated when a dedicated custom bar width is defined")
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 * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
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.has_key?('climate_zone') || args['climate_zone'] == 'Lookup From Model'
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'
@@ -2838,13 +2978,13 @@ module OsLib_ModelGeneration
2838
2978
  end
2839
2979
 
2840
2980
  # add daylight controls, need to perform a sizing run for 2010
2841
- if args['template'] == '90.1-2010'
2981
+ if args['template'] == '90.1-2010' || args['template'] == 'ComStock 90.1-2010'
2842
2982
  if standard.model_run_sizing_run(model, "#{Dir.pwd}/SRvt") == false
2843
2983
  log_messages_to_runner(runner, debug = true)
2844
2984
  return false
2845
2985
  end
2846
2986
  end
2847
- standard.model_add_daylighting_controls(model)
2987
+ standard.model_add_daylighting_controls(model)
2848
2988
  end
2849
2989
 
2850
2990
  # add refrigeration
@@ -2971,7 +3111,10 @@ module OsLib_ModelGeneration
2971
3111
  end
2972
3112
 
2973
3113
  # Add the primary system to the primary zones
2974
- standard.model_add_hvac_system(model, sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, system_zones)
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
2975
3118
 
2976
3119
  # Add the secondary system to the secondary zones (if any)
2977
3120
  if !pri_sec_zone_lists['secondary'].empty?
@@ -2981,7 +3124,10 @@ module OsLib_ModelGeneration
2981
3124
  cooled_only_zones = system_zones.select { |zone| !standard.thermal_zone_heated?(zone) && standard.thermal_zone_cooled?(zone) }
2982
3125
  system_zones = heated_and_cooled_zones + cooled_only_zones
2983
3126
  end
2984
- 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
2985
3131
  end
2986
3132
  end
2987
3133
  end
@@ -2997,7 +3143,10 @@ module OsLib_ModelGeneration
2997
3143
  # Add the user specified HVAC system for each story.
2998
3144
  # Single-zone systems will get one per zone.
2999
3145
  story_groups.each do |zones|
3000
- 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
3001
3150
  end
3002
3151
  end
3003
3152
  end
@@ -3045,7 +3194,7 @@ module OsLib_ModelGeneration
3045
3194
  if args['add_hvac']
3046
3195
  # set additional properties for building
3047
3196
  props = model.getBuilding.additionalProperties
3048
- props.setFeature('hvac_system_type',"#{args['system_type']}")
3197
+ props.setFeature('hvac_system_type', (args['system_type']).to_s)
3049
3198
 
3050
3199
  case args['system_type']
3051
3200
  when 'Ideal Air Loads'
@@ -3103,6 +3252,15 @@ module OsLib_ModelGeneration
3103
3252
  end
3104
3253
  end
3105
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
+
3106
3264
  # report final condition of model
3107
3265
  runner.registerFinalCondition("The building finished with #{model.getModelObjects.size} objects.")
3108
3266
 
@@ -3115,7 +3273,6 @@ module OsLib_ModelGeneration
3115
3273
  # wizard
3116
3274
  # used for varieties of measures that create space type and construction set wizard
3117
3275
  def wizard(model, runner, user_arguments)
3118
-
3119
3276
  # use the built-in error checking
3120
3277
  if !runner.validateUserArguments(arguments(model), user_arguments)
3121
3278
  return false
@@ -3159,7 +3316,7 @@ module OsLib_ModelGeneration
3159
3316
  lookup_building_type = standard.model_get_lookup_name(building_type)
3160
3317
 
3161
3318
  # remap small medium and large office to office
3162
- if building_type.include?("Office") then building_type = "Office" end
3319
+ if building_type.include?('Office') then building_type = 'Office' end
3163
3320
 
3164
3321
  # get array of new space types
3165
3322
  space_types_new = []
@@ -3287,4 +3444,4 @@ module OsLib_ModelGeneration
3287
3444
 
3288
3445
  return true
3289
3446
  end
3290
- end
3447
+ end