openstudio-extension 0.2.5 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +5 -0
- data/CHANGELOG.md +28 -0
- data/Gemfile +2 -0
- data/Jenkinsfile +1 -1
- data/LICENSE.md +1 -1
- data/Rakefile +1 -1
- data/doc_templates/LICENSE.md +1 -1
- data/doc_templates/copyright_erb.txt +1 -1
- data/doc_templates/copyright_js.txt +1 -1
- data/doc_templates/copyright_ruby.txt +1 -1
- data/init_templates/gemspec.txt +7 -5
- data/init_templates/openstudio_module.rb +1 -1
- data/init_templates/spec.rb +1 -1
- data/init_templates/spec_helper.rb +1 -1
- data/init_templates/template_gemfile.txt +1 -4
- data/init_templates/version.rb +1 -1
- data/lib/change_log.rb +1 -1
- data/lib/measures/openstudio_extension_test_measure/LICENSE.md +1 -1
- data/lib/measures/openstudio_extension_test_measure/measure.rb +1 -1
- data/lib/measures/openstudio_extension_test_measure/measure.xml +12 -12
- data/lib/measures/openstudio_extension_test_measure/resources/os_lib_helper_methods.rb +15 -2
- data/lib/openstudio-extension.rb +1 -1
- data/lib/openstudio/extension.rb +4 -3
- data/lib/openstudio/extension/core/CreateResults.rb +1 -1
- data/lib/openstudio/extension/core/check_air_sys_temps.rb +1 -1
- data/lib/openstudio/extension/core/check_calibration.rb +1 -1
- data/lib/openstudio/extension/core/check_cond_zns.rb +1 -1
- data/lib/openstudio/extension/core/check_domestic_hot_water.rb +1 -1
- data/lib/openstudio/extension/core/check_envelope_conductance.rb +1 -1
- data/lib/openstudio/extension/core/check_eui_by_end_use.rb +1 -1
- data/lib/openstudio/extension/core/check_eui_reasonableness.rb +1 -1
- data/lib/openstudio/extension/core/check_fan_pwr.rb +1 -1
- data/lib/openstudio/extension/core/check_internal_loads.rb +1 -1
- data/lib/openstudio/extension/core/check_mech_sys_capacity.rb +1 -1
- data/lib/openstudio/extension/core/check_mech_sys_efficiency.rb +1 -1
- data/lib/openstudio/extension/core/check_mech_sys_part_load_eff.rb +1 -1
- data/lib/openstudio/extension/core/check_mech_sys_type.rb +1 -1
- data/lib/openstudio/extension/core/check_part_loads.rb +1 -1
- data/lib/openstudio/extension/core/check_placeholder.rb +1 -1
- data/lib/openstudio/extension/core/check_plant_cap.rb +1 -1
- data/lib/openstudio/extension/core/check_plant_temps.rb +1 -1
- data/lib/openstudio/extension/core/check_plenum_loads.rb +1 -1
- data/lib/openstudio/extension/core/check_pump_pwr.rb +1 -1
- data/lib/openstudio/extension/core/check_sch_coord.rb +1 -1
- data/lib/openstudio/extension/core/check_schedules.rb +1 -1
- data/lib/openstudio/extension/core/check_simultaneous_heating_and_cooling.rb +1 -1
- data/lib/openstudio/extension/core/check_supply_air_and_thermostat_temp_difference.rb +1 -1
- data/lib/openstudio/extension/core/check_weather_files.rb +1 -1
- data/lib/openstudio/extension/core/deer_vintages.rb +1 -1
- data/lib/openstudio/extension/core/os_lib_aedg_measures.rb +5 -5
- data/lib/openstudio/extension/core/os_lib_constructions.rb +1 -1
- data/lib/openstudio/extension/core/os_lib_geometry.rb +4 -4
- data/lib/openstudio/extension/core/os_lib_helper_methods.rb +15 -2
- data/lib/openstudio/extension/core/os_lib_hvac.rb +18 -18
- data/lib/openstudio/extension/core/os_lib_lighting_and_equipment.rb +1 -1
- data/lib/openstudio/extension/core/os_lib_model_generation.rb +393 -237
- data/lib/openstudio/extension/core/os_lib_model_simplification.rb +10 -10
- data/lib/openstudio/extension/core/os_lib_outdoorair_and_infiltration.rb +3 -3
- data/lib/openstudio/extension/core/os_lib_reporting_qaqc.rb +1 -1
- data/lib/openstudio/extension/core/os_lib_schedules.rb +1 -1
- data/lib/openstudio/extension/rake_task.rb +1 -1
- data/lib/openstudio/extension/runner.rb +35 -19
- data/lib/openstudio/extension/runner_config.rb +1 -1
- data/lib/openstudio/extension/version.rb +2 -2
- data/openstudio-extension.gemspec +6 -5
- metadata +28 -15
- data/lib/openstudio/extension/core/os_lib_reporting.rb +0 -4755
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -204,7 +204,7 @@ module OsLib_AedgMeasures
|
|
204
204
|
@aedgK12HowToTipHash['EL20'] = 'EL20 Twenty-Four Hour Lighting'
|
205
205
|
@aedgK12HowToTipHash['EL21'] = 'EL21 Exterior Lighting Power-Parking Lots and Drives'
|
206
206
|
@aedgK12HowToTipHash['EL22'] = 'EL22 Exterior Lighting Power-Walkways'
|
207
|
-
@aedgK12HowToTipHash['EL23'] = 'EL23 Decorative
|
207
|
+
@aedgK12HowToTipHash['EL23'] = 'EL23 Decorative Facade Lighting'
|
208
208
|
@aedgK12HowToTipHash['EL24'] = 'EL24 Sources'
|
209
209
|
@aedgK12HowToTipHash['EL25'] = 'EL25 Controls'
|
210
210
|
|
@@ -273,7 +273,7 @@ module OsLib_AedgMeasures
|
|
273
273
|
|
274
274
|
# commissioning tips
|
275
275
|
@aedgK12HowToTipHash['QA01'] = 'QA1 Design and Construction Team'
|
276
|
-
@aedgK12HowToTipHash['QA02'] = 'QA2 Owner
|
276
|
+
@aedgK12HowToTipHash['QA02'] = 'QA2 Owner\'s Project Requirements and Basis of Design'
|
277
277
|
@aedgK12HowToTipHash['QA03'] = 'QA3 Selection of Quality Assurance Provider'
|
278
278
|
@aedgK12HowToTipHash['QA04'] = 'QA4 Design and Construction Schedule'
|
279
279
|
@aedgK12HowToTipHash['QA05'] = 'QA5 Design Review'
|
@@ -398,7 +398,7 @@ module OsLib_AedgMeasures
|
|
398
398
|
aedgSmMdOffHowToTipHash['EL20'] = 'EL20 Twenty-Four Hour Lighting'
|
399
399
|
aedgSmMdOffHowToTipHash['EL21'] = 'EL21 Exterior Lighting Power-Parking Lots and Drives'
|
400
400
|
aedgSmMdOffHowToTipHash['EL22'] = 'EL22 Exterior Lighting Power-Walkways'
|
401
|
-
aedgSmMdOffHowToTipHash['EL23'] = 'EL23 Decorative
|
401
|
+
aedgSmMdOffHowToTipHash['EL23'] = 'EL23 Decorative Facade Lighting'
|
402
402
|
aedgSmMdOffHowToTipHash['EL24'] = 'EL24 Sources'
|
403
403
|
aedgSmMdOffHowToTipHash['EL25'] = 'EL25 Controls'
|
404
404
|
|
@@ -463,7 +463,7 @@ Gas-Fired Boiler"
|
|
463
463
|
# commissioning tips
|
464
464
|
aedgSmMdOffHowToTipHash['QA01'] = 'QA1 Selecting the Design and Construction Team'
|
465
465
|
aedgSmMdOffHowToTipHash['QA02'] = 'QA2 Selecting the QA Provider'
|
466
|
-
aedgSmMdOffHowToTipHash['QA03'] = 'QA3 Owner
|
466
|
+
aedgSmMdOffHowToTipHash['QA03'] = 'QA3 Owner\'s Project Requirements (OPR) and Basis of Design (BoD)'
|
467
467
|
aedgSmMdOffHowToTipHash['QA04'] = 'QA4 Design and Construction Schedule'
|
468
468
|
aedgSmMdOffHowToTipHash['QA05'] = 'QA5 Design Review'
|
469
469
|
aedgSmMdOffHowToTipHash['QA06'] = 'QA6 Defining QA at Pre-Bid'
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -765,7 +765,7 @@ module OsLib_Geometry
|
|
765
765
|
story_hash.each_with_index do |(story_name, story_data), index|
|
766
766
|
# make new story unless story at requested height already exists.
|
767
767
|
story = nil
|
768
|
-
model.getBuildingStorys.each do |ext_story|
|
768
|
+
model.getBuildingStorys.sort.each do |ext_story|
|
769
769
|
if (ext_story.nominalZCoordinate.to_f - story_data[:space_origin_z].to_f).abs < 0.01
|
770
770
|
story = ext_story
|
771
771
|
end
|
@@ -1133,11 +1133,11 @@ module OsLib_Geometry
|
|
1133
1133
|
# todo - also odd with multi-height spaces
|
1134
1134
|
def self.calculate_perimeter(model)
|
1135
1135
|
perimeter = 0
|
1136
|
-
model.getSpaces.each do |space|
|
1136
|
+
model.getSpaces.sort.each do |space|
|
1137
1137
|
# counter to use later
|
1138
1138
|
edge_hash = {}
|
1139
1139
|
edge_counter = 0
|
1140
|
-
space.surfaces.each do |surface|
|
1140
|
+
space.surfaces.sort.each do |surface|
|
1141
1141
|
# get vertices
|
1142
1142
|
vertex_hash = {}
|
1143
1143
|
vertex_counter = 0
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -265,7 +265,20 @@ module OsLib_HelperMethods
|
|
265
265
|
result = measure_step.result.get
|
266
266
|
result.stepValues.each do |arg|
|
267
267
|
name = arg.name
|
268
|
-
value
|
268
|
+
# check if value, double, int, or bool
|
269
|
+
value_type = arg.variantType.valueDescription
|
270
|
+
if value_type == "Double"
|
271
|
+
value = arg.valueAsDouble
|
272
|
+
elsif value_type == "Integer"
|
273
|
+
value = arg.valueAsInteger
|
274
|
+
elsif value_type == "Boolean"
|
275
|
+
value = arg.valueAsBoolean
|
276
|
+
elsif value_type == "String"
|
277
|
+
value = arg.valueAsString
|
278
|
+
else
|
279
|
+
# catchall for unexpected value types
|
280
|
+
value = arg.valueAsVariant.to_s
|
281
|
+
end
|
269
282
|
if name == arg_name
|
270
283
|
arg_name_value[:value] = value
|
271
284
|
arg_name_value[:measure_name] = measure_name
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -117,7 +117,7 @@ module OsLib_HVAC
|
|
117
117
|
zonesUnconditioned = []
|
118
118
|
|
119
119
|
# get thermal zones
|
120
|
-
zones = model.getThermalZones
|
120
|
+
zones = model.getThermalZones.sort
|
121
121
|
zones.each do |zone|
|
122
122
|
# assign appropriate zones to zonesPlenum or zonesUnconditioned (those that don't have thermostats or zone HVAC equipment)
|
123
123
|
# if not conditioned then add to zonesPlenum or zonesUnconditioned
|
@@ -177,9 +177,9 @@ module OsLib_HVAC
|
|
177
177
|
|
178
178
|
def self.reportConditions(model, runner, condition,extra_string = '')
|
179
179
|
|
180
|
-
airloops = model.getAirLoopHVACs
|
181
|
-
plantLoops = model.getPlantLoops
|
182
|
-
zones = model.getThermalZones
|
180
|
+
airloops = model.getAirLoopHVACs.sort
|
181
|
+
plantLoops = model.getPlantLoops.sort
|
182
|
+
zones = model.getThermalZones.sort
|
183
183
|
|
184
184
|
# count up zone equipment (not counting zone exhaust fans)
|
185
185
|
zoneHasEquip = false
|
@@ -205,9 +205,9 @@ module OsLib_HVAC
|
|
205
205
|
end
|
206
206
|
|
207
207
|
def self.removeEquipment(model, runner)
|
208
|
-
airloops = model.getAirLoopHVACs
|
209
|
-
plantLoops = model.getPlantLoops
|
210
|
-
zones = model.getThermalZones
|
208
|
+
airloops = model.getAirLoopHVACs.sort
|
209
|
+
plantLoops = model.getPlantLoops.sort
|
210
|
+
zones = model.getThermalZones.sort
|
211
211
|
|
212
212
|
# remove all airloops
|
213
213
|
airloops.each(&:remove)
|
@@ -244,7 +244,7 @@ module OsLib_HVAC
|
|
244
244
|
require "#{File.dirname(__FILE__)}/os_lib_schedules"
|
245
245
|
|
246
246
|
schedulesHVAC = {}
|
247
|
-
airloops = model.getAirLoopHVACs
|
247
|
+
airloops = model.getAirLoopHVACs.sort
|
248
248
|
|
249
249
|
# find airloop with most primary spaces
|
250
250
|
max_primary_spaces = 0
|
@@ -628,7 +628,7 @@ module OsLib_HVAC
|
|
628
628
|
|
629
629
|
# check for water-cooled chillers
|
630
630
|
waterCooledChiller = false
|
631
|
-
model.getChillerElectricEIRs.each do |chiller|
|
631
|
+
model.getChillerElectricEIRs.sort.each do |chiller|
|
632
632
|
next if waterCooledChiller == true
|
633
633
|
if chiller.condenserType == 'WaterCooled'
|
634
634
|
waterCooledChiller = true
|
@@ -678,7 +678,7 @@ module OsLib_HVAC
|
|
678
678
|
pipe_supply_outlet.addToNode(condenser_loop.supplyOutletNode)
|
679
679
|
setpoint_manager_follow_oa.addToNode(condenser_loop.supplyOutletNode)
|
680
680
|
# demand side components
|
681
|
-
model.getChillerElectricEIRs.each do |chiller|
|
681
|
+
model.getChillerElectricEIRs.sort.each do |chiller|
|
682
682
|
if chiller.condenserType == 'WaterCooled' # works only if chillers not already connected to condenser loop(s)
|
683
683
|
condenser_loop.addDemandBranchForComponent(chiller)
|
684
684
|
end
|
@@ -771,7 +771,7 @@ module OsLib_HVAC
|
|
771
771
|
primary_airloops = []
|
772
772
|
# create primary airloop for each story
|
773
773
|
assignedThermalZones = []
|
774
|
-
model.getBuildingStorys.each do |building_story|
|
774
|
+
model.getBuildingStorys.sort.each do |building_story|
|
775
775
|
# ML stories need to be reordered from the ground up
|
776
776
|
thermalZonesToAdd = []
|
777
777
|
building_story.spaces.each do |space|
|
@@ -1069,7 +1069,7 @@ module OsLib_HVAC
|
|
1069
1069
|
def self.createSecondaryAirLoops(model, runner, options)
|
1070
1070
|
secondary_airloops = []
|
1071
1071
|
# create secondary airloop for each secondary zone
|
1072
|
-
model.getThermalZones.each do |zone|
|
1072
|
+
model.getThermalZones.sort.each do |zone|
|
1073
1073
|
if options['zonesSecondary'].include? zone
|
1074
1074
|
# create secondary airloop
|
1075
1075
|
airloop_secondary = OpenStudio::Model::AirLoopHVAC.new(model)
|
@@ -1314,7 +1314,7 @@ module OsLib_HVAC
|
|
1314
1314
|
end
|
1315
1315
|
|
1316
1316
|
def self.createPrimaryZoneEquipment(model, runner, options)
|
1317
|
-
model.getThermalZones.each do |zone|
|
1317
|
+
model.getThermalZones.sort.each do |zone|
|
1318
1318
|
if options['zonesPrimary'].include? zone
|
1319
1319
|
if options['zoneHVAC'] == 'FanCoil'
|
1320
1320
|
# create fan coil
|
@@ -1521,7 +1521,7 @@ module OsLib_HVAC
|
|
1521
1521
|
def self.get_or_add_hot_water_loop(model)
|
1522
1522
|
# How water loop
|
1523
1523
|
hw_loop = nil
|
1524
|
-
model.getLoops.each do |loop|
|
1524
|
+
model.getLoops.sort.each do |loop|
|
1525
1525
|
if loop.name.to_s == 'Hot Water Loop' # sizingPlant has loopType method to do this better
|
1526
1526
|
hw_loop = loop.to_PlantLoop.get
|
1527
1527
|
end
|
@@ -1580,7 +1580,7 @@ module OsLib_HVAC
|
|
1580
1580
|
# Chilled Water Plant
|
1581
1581
|
# todo - add in logic here that if existing chw_loop is air cooled, replace it with this one.
|
1582
1582
|
chw_loop = nil
|
1583
|
-
model.getLoops.each do |loop|
|
1583
|
+
model.getLoops.sort.each do |loop|
|
1584
1584
|
if loop.name.to_s == 'Chilled Water Loop'
|
1585
1585
|
chw_loop = loop.to_PlantLoop.get
|
1586
1586
|
end
|
@@ -1658,7 +1658,7 @@ module OsLib_HVAC
|
|
1658
1658
|
|
1659
1659
|
# Condenser System
|
1660
1660
|
cw_loop = nil
|
1661
|
-
model.getLoops.each do |loop|
|
1661
|
+
model.getLoops.sort.each do |loop|
|
1662
1662
|
if loop.name.to_s == 'Condenser Water Loop'
|
1663
1663
|
cw_loop = loop.to_PlantLoop.get
|
1664
1664
|
end
|
@@ -1702,7 +1702,7 @@ module OsLib_HVAC
|
|
1702
1702
|
def self.get_or_add_air_cooled_chiller_loop(model)
|
1703
1703
|
# Chilled Water Plant
|
1704
1704
|
chw_loop = nil
|
1705
|
-
model.getLoops.each do |loop|
|
1705
|
+
model.getLoops.sort.each do |loop|
|
1706
1706
|
if loop.name.to_s == 'Chilled Water Loop'
|
1707
1707
|
chw_loop = loop.to_PlantLoop.get
|
1708
1708
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
3
|
# All rights reserved.
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
5
5
|
# modification, are permitted provided that the following conditions are met:
|
@@ -1,5 +1,8 @@
|
|
1
|
+
# ComStock(TM), Copyright (c) 2020 Alliance for Sustainable Energy, LLC. All rights reserved.
|
2
|
+
# See top level LICENSE.txt file for license terms.
|
3
|
+
|
1
4
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
5
|
+
# OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC.
|
3
6
|
# All rights reserved.
|
4
7
|
# Redistribution and use in source and binary forms, with or without
|
5
8
|
# modification, are permitted provided that the following conditions are met:
|
@@ -37,7 +40,6 @@ module OsLib_ModelGeneration
|
|
37
40
|
# simple list of building types that are valid for get_space_types_from_building_type
|
38
41
|
# for general public use use extended = false
|
39
42
|
def get_building_types(extended = false)
|
40
|
-
|
41
43
|
# get building_types
|
42
44
|
if extended
|
43
45
|
doe = get_doe_building_types(true)
|
@@ -127,7 +129,6 @@ module OsLib_ModelGeneration
|
|
127
129
|
# simple list of templates that are valid for get_space_types_from_building_type
|
128
130
|
# for general public use use extended = false
|
129
131
|
def get_templates(extended = false)
|
130
|
-
|
131
132
|
# get templates
|
132
133
|
if extended
|
133
134
|
doe = get_doe_templates(true)
|
@@ -157,6 +158,12 @@ module OsLib_ModelGeneration
|
|
157
158
|
array << '90.1-2007'
|
158
159
|
array << '90.1-2010'
|
159
160
|
array << '90.1-2013'
|
161
|
+
array << 'ComStock DOE Ref Pre-1980'
|
162
|
+
array << 'ComStock DOE Ref 1980-2004'
|
163
|
+
array << 'ComStock 90.1-2004'
|
164
|
+
array << 'ComStock 90.1-2007'
|
165
|
+
array << 'ComStock 90.1-2010'
|
166
|
+
array << 'ComStock 90.1-2013'
|
160
167
|
if extended
|
161
168
|
# array << '189.1-2009' # if turn this on need to update space_type_array for RetailStripmall
|
162
169
|
array << 'NREL ZNE Ready 2017'
|
@@ -228,10 +235,9 @@ module OsLib_ModelGeneration
|
|
228
235
|
# get_doe_climate_zones
|
229
236
|
# for general public use use extended = false
|
230
237
|
def get_doe_climate_zones(extended = false, extra = nil)
|
231
|
-
|
232
238
|
# Lookup From Model should be added as an option where appropriate in the measure
|
233
239
|
cz_choices = OpenStudio::StringVector.new
|
234
|
-
if extra
|
240
|
+
if !extra.nil?
|
235
241
|
cz_choices << extra
|
236
242
|
end
|
237
243
|
cz_choices << 'ASHRAE 169-2013-1A'
|
@@ -262,10 +268,9 @@ module OsLib_ModelGeneration
|
|
262
268
|
# get_deer_climate_zones
|
263
269
|
# for general public use use extended = false
|
264
270
|
def get_deer_climate_zones(extended = false, extra = nil)
|
265
|
-
|
266
271
|
# Lookup From Model should be added as an option where appropriate in the measure
|
267
272
|
cz_choices = OpenStudio::StringVector.new
|
268
|
-
if extra
|
273
|
+
if !extra.nil?
|
269
274
|
cz_choices << extra
|
270
275
|
end
|
271
276
|
cz_choices << 'CEC T24-CEC1'
|
@@ -309,27 +314,27 @@ module OsLib_ModelGeneration
|
|
309
314
|
primary_footprint = 73958.0
|
310
315
|
primary_p = 619.0 # wrote measure using calculate_perimeter method in os_lib_geometry
|
311
316
|
primary_ns_ew_ratio = 2.829268293 # estimated from ratio of ns/ew total wall area
|
312
|
-
primary_width = Math.sqrt(primary_footprint/primary_ns_ew_ratio)
|
317
|
+
primary_width = Math.sqrt(primary_footprint / primary_ns_ew_ratio)
|
313
318
|
primary_p_min = 2 * (primary_width + primary_width / primary_footprint)
|
314
319
|
primary_p_mult = primary_p / primary_p_min
|
315
320
|
|
316
321
|
secondary_footprint = 210887.0 / 2.0 # floor area divided by area instead of true footprint 128112.0)
|
317
322
|
secondary_p = 708.0 # wrote measure using calculate_perimeter method in os_lib_geometry
|
318
323
|
secondary_ns_ew_ratio = 2.069230769 # estimated from ratio of ns/ew total wall area
|
319
|
-
secondary_width = Math.sqrt(secondary_footprint/secondary_ns_ew_ratio)
|
324
|
+
secondary_width = Math.sqrt(secondary_footprint / secondary_ns_ew_ratio)
|
320
325
|
secondary_p_min = 2 * (secondary_width + secondary_width / secondary_footprint)
|
321
326
|
secondary_p_mult = secondary_p / secondary_p_min
|
322
327
|
|
323
328
|
outpatient_footprint = 40946.0 / 3.0 # floor area divided by area instead of true footprint 17872.0)
|
324
329
|
outpatient_p = 537.0 # wrote measure using calculate_perimeter method in os_lib_geometry
|
325
330
|
outpatient_ns_ew_ratio = 1.56448737 # estimated from ratio of ns/ew total wall area
|
326
|
-
outpatient_width = Math.sqrt(outpatient_footprint/outpatient_ns_ew_ratio)
|
327
|
-
outpatient_p_min = 2 * (outpatient_width + outpatient_footprint/outpatient_width)
|
331
|
+
outpatient_width = Math.sqrt(outpatient_footprint / outpatient_ns_ew_ratio)
|
332
|
+
outpatient_p_min = 2 * (outpatient_width + outpatient_footprint / outpatient_width)
|
328
333
|
outpatient_p_mult = outpatient_p / outpatient_p_min
|
329
334
|
|
330
|
-
#primary_aspet_ratio = calc_aspect_ratio(73958.0, 2060.0)
|
331
|
-
#secondary_aspet_ratio = calc_aspect_ratio(128112.0, 2447.0)
|
332
|
-
#outpatient_aspet_ratio = calc_aspect_ratio(14782.0, 588.0)
|
335
|
+
# primary_aspet_ratio = calc_aspect_ratio(73958.0, 2060.0)
|
336
|
+
# secondary_aspet_ratio = calc_aspect_ratio(128112.0, 2447.0)
|
337
|
+
# outpatient_aspet_ratio = calc_aspect_ratio(14782.0, 588.0)
|
333
338
|
supermarket_a = 45001.0
|
334
339
|
supermarket_p = 866.0
|
335
340
|
supermarket_wwr = 1880.0 / (supermarket_p * 20.0)
|
@@ -402,13 +407,13 @@ module OsLib_ModelGeneration
|
|
402
407
|
# TODO: - Confirm that these work for all standards
|
403
408
|
# DOE Prototypes
|
404
409
|
if building_type == 'SecondarySchool'
|
405
|
-
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004'].include?(template)
|
410
|
+
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004', 'ComStock DOE Ref Pre-1980', 'ComStock DOE Ref 1980-2004'].include?(template)
|
406
411
|
hash['Auditorium'] = { ratio: 0.0504, space_type_gen: true, default: false, story_height: 26.0 }
|
407
412
|
hash['Cafeteria'] = { ratio: 0.0319, space_type_gen: true, default: false }
|
408
413
|
hash['Classroom'] = { ratio: 0.3528, space_type_gen: true, default: true }
|
409
414
|
hash['Corridor'] = { ratio: 0.2144, space_type_gen: true, default: false, circ: true }
|
410
|
-
hash['Gym'] = { ratio: 0.1009, space_type_gen: true, default: false
|
411
|
-
hash['Gym - audience'] = { ratio: 0.0637, space_type_gen: true, default: false
|
415
|
+
hash['Gym'] = { ratio: 0.1009, space_type_gen: true, default: false, story_height: 26.0 }
|
416
|
+
hash['Gym - audience'] = { ratio: 0.0637, space_type_gen: true, default: false, story_height: 26.0 }
|
412
417
|
hash['Kitchen'] = { ratio: 0.0110, space_type_gen: true, default: false }
|
413
418
|
hash['Library'] = { ratio: 0.0429, space_type_gen: true, default: false }
|
414
419
|
hash['Lobby'] = { ratio: 0.0214, space_type_gen: true, default: false }
|
@@ -421,7 +426,7 @@ module OsLib_ModelGeneration
|
|
421
426
|
hash['Classroom'] = { ratio: 0.3041, space_type_gen: true, default: true }
|
422
427
|
hash['ComputerRoom'] = { ratio: 0.0487, space_type_gen: true, default: true }
|
423
428
|
hash['Corridor'] = { ratio: 0.2144, space_type_gen: true, default: false, circ: true }
|
424
|
-
hash['Gym'] = { ratio: 0.1646, space_type_gen: true, default: false
|
429
|
+
hash['Gym'] = { ratio: 0.1646, space_type_gen: true, default: false, story_height: 26.0 }
|
425
430
|
hash['Kitchen'] = { ratio: 0.0110, space_type_gen: true, default: false }
|
426
431
|
hash['Library'] = { ratio: 0.0429, space_type_gen: true, default: false }
|
427
432
|
hash['Lobby'] = { ratio: 0.0214, space_type_gen: true, default: false }
|
@@ -430,7 +435,7 @@ module OsLib_ModelGeneration
|
|
430
435
|
hash['Restroom'] = { ratio: 0.0214, space_type_gen: true, default: false }
|
431
436
|
end
|
432
437
|
elsif building_type == 'PrimarySchool'
|
433
|
-
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004'].include?(template)
|
438
|
+
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004', 'ComStock DOE Ref Pre-1980', 'ComStock DOE Ref 1980-2004'].include?(template)
|
434
439
|
# updated to 2004 which includes library vs. pre-1980
|
435
440
|
hash['Cafeteria'] = { ratio: 0.0458, space_type_gen: true, default: false }
|
436
441
|
hash['Classroom'] = { ratio: 0.5610, space_type_gen: true, default: true }
|
@@ -448,7 +453,7 @@ module OsLib_ModelGeneration
|
|
448
453
|
hash['Classroom'] = { ratio: 0.4793, space_type_gen: true, default: true }
|
449
454
|
hash['ComputerRoom'] = { ratio: 0.0236, space_type_gen: true, default: true }
|
450
455
|
hash['Corridor'] = { ratio: 0.1633, space_type_gen: true, default: false, circ: true }
|
451
|
-
hash['Gym'] = { ratio: 0.0520, space_type_gen: true, default: false}
|
456
|
+
hash['Gym'] = { ratio: 0.0520, space_type_gen: true, default: false }
|
452
457
|
hash['Kitchen'] = { ratio: 0.0244, space_type_gen: true, default: false }
|
453
458
|
hash['Library'] = { ratio: 0.0581, space_type_gen: true, default: false }
|
454
459
|
hash['Lobby'] = { ratio: 0.0249, space_type_gen: true, default: false }
|
@@ -494,7 +499,7 @@ module OsLib_ModelGeneration
|
|
494
499
|
hash['WholeBuilding - Md Office'] = { ratio: 0.0, space_type_gen: true, default: false }
|
495
500
|
end
|
496
501
|
elsif building_type == 'LargeOffice'
|
497
|
-
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004'].include?(template)
|
502
|
+
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004', 'ComStock DOE Ref Pre-1980', 'ComStock DOE Ref 1980-2004'].include?(template)
|
498
503
|
if whole_building
|
499
504
|
hash['WholeBuilding - Lg Office'] = { ratio: 1.0, space_type_gen: true, default: true }
|
500
505
|
else
|
@@ -538,7 +543,7 @@ module OsLib_ModelGeneration
|
|
538
543
|
end
|
539
544
|
end
|
540
545
|
elsif building_type == 'SmallHotel'
|
541
|
-
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004'].include?(template)
|
546
|
+
if ['DOE Ref Pre-1980', 'DOE Ref 1980-2004', 'ComStock DOE Ref Pre-1980', 'ComStock DOE Ref 1980-2004'].include?(template)
|
542
547
|
hash['Corridor'] = { ratio: 0.1313, space_type_gen: true, default: false, circ: true }
|
543
548
|
hash['Elec/MechRoom'] = { ratio: 0.0038, space_type_gen: true, default: false }
|
544
549
|
hash['ElevatorCore'] = { ratio: 0.0113, space_type_gen: true, default: false }
|
@@ -1049,7 +1054,7 @@ module OsLib_ModelGeneration
|
|
1049
1054
|
# only intersect if make_mid_story_surfaces_adiabatic false
|
1050
1055
|
if diagnostic_intersect
|
1051
1056
|
|
1052
|
-
model.getPlanarSurfaces.each do |surface|
|
1057
|
+
model.getPlanarSurfaces.sort.each do |surface|
|
1053
1058
|
array = []
|
1054
1059
|
vertices = surface.vertices
|
1055
1060
|
fixed = false
|
@@ -1075,7 +1080,7 @@ module OsLib_ModelGeneration
|
|
1075
1080
|
end
|
1076
1081
|
|
1077
1082
|
# remove collinear points in a surface
|
1078
|
-
model.getPlanarSurfaces.each do |surface|
|
1083
|
+
model.getPlanarSurfaces.sort.each do |surface|
|
1079
1084
|
new_vertices = OpenStudio.removeCollinear(surface.vertices)
|
1080
1085
|
starting_count = surface.vertices.size
|
1081
1086
|
final_count = new_vertices.size
|
@@ -1086,13 +1091,11 @@ module OsLib_ModelGeneration
|
|
1086
1091
|
end
|
1087
1092
|
|
1088
1093
|
# remove duplicate surfaces in a space (should be done after remove duplicate and collinear points)
|
1089
|
-
model.getSpaces.each do |space|
|
1090
|
-
|
1094
|
+
model.getSpaces.sort.each do |space|
|
1091
1095
|
# secondary array to compare against
|
1092
1096
|
surfaces_b = space.surfaces.sort
|
1093
1097
|
|
1094
1098
|
space.surfaces.sort.each do |surface_a|
|
1095
|
-
|
1096
1099
|
# delete from secondary array
|
1097
1100
|
surfaces_b.delete(surface_a)
|
1098
1101
|
|
@@ -1102,13 +1105,11 @@ module OsLib_ModelGeneration
|
|
1102
1105
|
runner.registerWarning("#{surface_a.name} and #{surface_b.name} in #{space.name} have duplicate geometry, removing #{surface_b.name}.")
|
1103
1106
|
surface_b.remove
|
1104
1107
|
elsif surface_a.reverseEqualVertices(surface_b)
|
1105
|
-
#
|
1108
|
+
# TODO: - add logic to determine which face naormal is reversed and which is correct
|
1106
1109
|
runner.registerWarning("#{surface_a.name} and #{surface_b.name} in #{space.name} have reversed geometry, removing #{surface_b.name}.")
|
1107
1110
|
surface_b.remove
|
1108
1111
|
end
|
1109
|
-
|
1110
1112
|
end
|
1111
|
-
|
1112
1113
|
end
|
1113
1114
|
end
|
1114
1115
|
|
@@ -1119,7 +1120,7 @@ module OsLib_ModelGeneration
|
|
1119
1120
|
model.getSpaces.sort.each do |space_a|
|
1120
1121
|
spaces_b.delete(space_a)
|
1121
1122
|
spaces_b.each do |space_b|
|
1122
|
-
#runner.registerInfo("Intersecting and matching surfaces between #{space_a.name} and #{space.name}")
|
1123
|
+
# runner.registerInfo("Intersecting and matching surfaces between #{space_a.name} and #{space.name}")
|
1123
1124
|
spaces_temp = OpenStudio::Model::SpaceVector.new
|
1124
1125
|
spaces_temp << space_a
|
1125
1126
|
spaces_temp << space_b
|
@@ -1129,8 +1130,8 @@ module OsLib_ModelGeneration
|
|
1129
1130
|
end
|
1130
1131
|
end
|
1131
1132
|
runner.registerInfo('Intersecting and matching surfaces in model, this will create additional geometry.')
|
1132
|
-
else #elsif bar_hash[:double_loaded_corridor] # only intersect spaces in each story, not between wtory
|
1133
|
-
model.getBuilding.buildingStories.each do |story|
|
1133
|
+
else # elsif bar_hash[:double_loaded_corridor] # only intersect spaces in each story, not between wtory
|
1134
|
+
model.getBuilding.buildingStories.sort.each do |story|
|
1134
1135
|
# intersect and surface match two pair by pair
|
1135
1136
|
spaces_b = story.spaces.sort
|
1136
1137
|
# looping through vector of each space
|
@@ -1160,8 +1161,8 @@ module OsLib_ModelGeneration
|
|
1160
1161
|
OpenStudio::Model.matchSurfaces(spaces)
|
1161
1162
|
runner.registerInfo('Intersecting and matching surfaces in model, this will create additional geometry.')
|
1162
1163
|
end
|
1163
|
-
else #elsif bar_hash[:double_loaded_corridor] # only intersect spaces in each story, not between wtory
|
1164
|
-
model.getBuilding.buildingStories.each do |story|
|
1164
|
+
else # elsif bar_hash[:double_loaded_corridor] # only intersect spaces in each story, not between wtory
|
1165
|
+
model.getBuilding.buildingStories.sort.each do |story|
|
1165
1166
|
story_spaces = OpenStudio::Model::SpaceVector.new
|
1166
1167
|
story.spaces.sort.each do |space|
|
1167
1168
|
story_spaces << space
|
@@ -1177,11 +1178,11 @@ module OsLib_ModelGeneration
|
|
1177
1178
|
# set boundary conditions if not already set when geometry was created
|
1178
1179
|
# todo - update this to use space original z value vs. story name
|
1179
1180
|
if bar_hash[:num_stories_below_grade] > 0
|
1180
|
-
model.getBuildingStorys.each do |story|
|
1181
|
+
model.getBuildingStorys.sort.each do |story|
|
1181
1182
|
next if !story.name.to_s.include?('Story B')
|
1182
|
-
story.spaces.each do |space|
|
1183
|
-
next if
|
1184
|
-
space.surfaces.each do |surface|
|
1183
|
+
story.spaces.sort.each do |space|
|
1184
|
+
next if !new_spaces.include?(space)
|
1185
|
+
space.surfaces.sort.each do |surface|
|
1185
1186
|
next if surface.surfaceType != 'Wall'
|
1186
1187
|
next if surface.outsideBoundaryCondition != 'Outdoors'
|
1187
1188
|
surface.setOutsideBoundaryCondition('Ground')
|
@@ -1193,9 +1194,9 @@ module OsLib_ModelGeneration
|
|
1193
1194
|
# sort stories (by name for now but need better way)
|
1194
1195
|
sorted_stories = {}
|
1195
1196
|
new_spaces.each do |space|
|
1196
|
-
next if !
|
1197
|
+
next if !space.buildingStory.is_initialized
|
1197
1198
|
story = space.buildingStory.get
|
1198
|
-
if !
|
1199
|
+
if !sorted_stories.key?(name.to_s)
|
1199
1200
|
sorted_stories[story.name.to_s] = story
|
1200
1201
|
end
|
1201
1202
|
end
|
@@ -1228,7 +1229,7 @@ module OsLib_ModelGeneration
|
|
1228
1229
|
party_wall_facades = stories_flat[i][:story_party_walls]
|
1229
1230
|
|
1230
1231
|
story.spaces.each do |space|
|
1231
|
-
next if
|
1232
|
+
next if !new_spaces.include?(space)
|
1232
1233
|
space.surfaces. each do |surface|
|
1233
1234
|
# set floor to adiabatic if requited
|
1234
1235
|
if adiabatic_floor && surface.surfaceType == 'Floor'
|
@@ -1324,7 +1325,6 @@ module OsLib_ModelGeneration
|
|
1324
1325
|
end
|
1325
1326
|
|
1326
1327
|
return new_spaces
|
1327
|
-
|
1328
1328
|
end
|
1329
1329
|
|
1330
1330
|
# make selected surfaces adiabatic
|
@@ -1392,7 +1392,7 @@ module OsLib_ModelGeneration
|
|
1392
1392
|
return bar
|
1393
1393
|
end
|
1394
1394
|
|
1395
|
-
def bar_hash_setup_run(runner,model,args,length,width,floor_height_si,center_of_footprint,space_types_hash,num_stories)
|
1395
|
+
def bar_hash_setup_run(runner, model, args, length, width, floor_height_si, center_of_footprint, space_types_hash, num_stories)
|
1396
1396
|
# create envelope
|
1397
1397
|
# populate bar_hash and create envelope with data from envelope_data_hash and user arguments
|
1398
1398
|
bar_hash = {}
|
@@ -1584,31 +1584,31 @@ module OsLib_ModelGeneration
|
|
1584
1584
|
roof_area = 0.0
|
1585
1585
|
new_spaces.each do |space|
|
1586
1586
|
space.surfaces.each do |surface|
|
1587
|
-
if surface.surfaceType ==
|
1587
|
+
if surface.surfaceType == 'Floor' && surface.outsideBoundaryCondition == 'Ground'
|
1588
1588
|
ground_floor_area += surface.netArea
|
1589
|
-
elsif surface.surfaceType ==
|
1589
|
+
elsif surface.surfaceType == 'RoofCeiling' && surface.outsideBoundaryCondition == 'Outdoors'
|
1590
1590
|
roof_area += surface.netArea
|
1591
1591
|
end
|
1592
1592
|
end
|
1593
1593
|
end
|
1594
|
-
#
|
1594
|
+
# TODO: - extend to address when top and or bottom story are not exposed via argument
|
1595
1595
|
if ground_floor_area > target_footprint + 0.001 || roof_area > target_footprint + 0.001
|
1596
|
-
#runner.registerError("Ground exposed floor or Roof area is larger than footprint, likely inter-floor surface matching and intersection error.")
|
1597
|
-
#return false
|
1596
|
+
# runner.registerError("Ground exposed floor or Roof area is larger than footprint, likely inter-floor surface matching and intersection error.")
|
1597
|
+
# return false
|
1598
1598
|
|
1599
1599
|
# not providing adiabatic work around when top story is partial story.
|
1600
1600
|
if args['num_stories_above_grade'].to_f != args['num_stories_above_grade'].ceil
|
1601
|
-
runner.registerError(
|
1601
|
+
runner.registerError('Ground exposed floor or Roof area is larger than footprint, likely inter-floor surface matching and intersection error.')
|
1602
1602
|
return false
|
1603
1603
|
else
|
1604
|
-
runner.registerInfo(
|
1604
|
+
runner.registerInfo('Ground exposed floor or Roof area is larger than footprint, likely inter-floor surface matching and intersection error, altering impacted surfaces boundary condition to be adiabatic.')
|
1605
1605
|
match_error = true
|
1606
1606
|
end
|
1607
1607
|
else
|
1608
1608
|
match_error = false
|
1609
1609
|
end
|
1610
1610
|
|
1611
|
-
#
|
1611
|
+
# TODO: - should be able to remove this fix after OpenStudio intersection issue is fixed. At that time turn the above message into an error with return false after it
|
1612
1612
|
if match_error
|
1613
1613
|
|
1614
1614
|
# identify z value of top and bottom story
|
@@ -1634,38 +1634,34 @@ module OsLib_ModelGeneration
|
|
1634
1634
|
if space.buildingStory.get.nominalZCoordinate.get > bottom_story
|
1635
1635
|
# change floors
|
1636
1636
|
space.surfaces.each do |surface|
|
1637
|
-
next if
|
1638
|
-
surface.setOutsideBoundaryCondition(
|
1637
|
+
next if !(surface.surfaceType == 'Floor' && surface.outsideBoundaryCondition == 'Ground')
|
1638
|
+
surface.setOutsideBoundaryCondition('Adiabatic')
|
1639
1639
|
end
|
1640
1640
|
end
|
1641
1641
|
if space.buildingStory.get.nominalZCoordinate.get < top_story
|
1642
1642
|
# change ceilings
|
1643
1643
|
space.surfaces.each do |surface|
|
1644
|
-
next if
|
1645
|
-
surface.setOutsideBoundaryCondition(
|
1644
|
+
next if !(surface.surfaceType == 'RoofCeiling' && surface.outsideBoundaryCondition == 'Outdoors')
|
1645
|
+
surface.setOutsideBoundaryCondition('Adiabatic')
|
1646
1646
|
end
|
1647
1647
|
end
|
1648
1648
|
end
|
1649
|
-
|
1650
1649
|
end
|
1651
|
-
|
1652
|
-
|
1653
1650
|
end
|
1654
1651
|
|
1655
|
-
#
|
1656
|
-
|
1657
|
-
def bar_from_building_type_ratios(model, runner, user_arguments)
|
1652
|
+
# bar_arg_check_setup
|
1653
|
+
def bar_arg_check_setup(model, runner, user_arguments, building_type_ratios = true)
|
1658
1654
|
|
1659
1655
|
# assign the user inputs to variables
|
1660
1656
|
args = OsLib_HelperMethods.createRunVariables(runner, model, user_arguments, arguments(model))
|
1661
1657
|
if !args then return false end
|
1662
1658
|
|
1663
1659
|
# add in arguments that may not be passed in
|
1664
|
-
if !args.
|
1665
|
-
args[
|
1660
|
+
if !args.key?('double_loaded_corridor')
|
1661
|
+
args['double_loaded_corridor'] = 'None' # use None when not in measure building type data may not contain this
|
1666
1662
|
end
|
1667
|
-
if !
|
1668
|
-
args[
|
1663
|
+
if !args.key?('perim_mult')
|
1664
|
+
args['perim_mult'] = 1.0 # will not make two bars for extended perimeter
|
1669
1665
|
end
|
1670
1666
|
|
1671
1667
|
# lookup and replace argument values from upstream measures
|
@@ -1691,10 +1687,12 @@ module OsLib_ModelGeneration
|
|
1691
1687
|
end
|
1692
1688
|
|
1693
1689
|
# check expected values of double arguments
|
1694
|
-
fraction_args = ['
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1690
|
+
fraction_args = ['wwr', 'party_wall_fraction']
|
1691
|
+
if building_type_ratios
|
1692
|
+
fraction_args << 'bldg_type_b_fract_bldg_area'
|
1693
|
+
fraction_args << 'bldg_type_c_fract_bldg_area'
|
1694
|
+
fraction_args << 'bldg_type_d_fract_bldg_area'
|
1695
|
+
end
|
1698
1696
|
fraction = OsLib_HelperMethods.checkDoubleAndIntegerArguments(runner, user_arguments, 'min' => 0.0, 'max' => 1.0, 'min_eq_bool' => true, 'max_eq_bool' => true, 'arg_array' => fraction_args)
|
1699
1697
|
|
1700
1698
|
positive_args = ['total_bldg_floor_area']
|
@@ -1711,49 +1709,25 @@ module OsLib_ModelGeneration
|
|
1711
1709
|
'party_wall_stories_east',
|
1712
1710
|
'party_wall_stories_west',
|
1713
1711
|
'single_floor_area',
|
1714
|
-
'bar_width'
|
1712
|
+
'bar_width']
|
1715
1713
|
non_neg = OsLib_HelperMethods.checkDoubleAndIntegerArguments(runner, user_arguments, 'min' => 0.0, 'max' => nil, 'min_eq_bool' => true, 'max_eq_bool' => false, 'arg_array' => non_neg_args)
|
1716
1714
|
|
1717
1715
|
# return false if any errors fail
|
1718
1716
|
if !fraction then return false end
|
1719
1717
|
if !positive then return false end
|
1720
|
-
if !one_or_greater
|
1721
|
-
if !non_neg
|
1718
|
+
return false if !one_or_greater
|
1719
|
+
return false if !non_neg
|
1722
1720
|
|
1723
|
-
|
1724
|
-
building_form_defaults = building_form_defaults(args['bldg_type_a'])
|
1721
|
+
return args
|
1725
1722
|
|
1726
|
-
|
1727
|
-
defaulted_args = []
|
1728
|
-
|
1729
|
-
if args['ns_to_ew_ratio'] == 0.0
|
1730
|
-
args['ns_to_ew_ratio'] = building_form_defaults[:aspect_ratio]
|
1731
|
-
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]}.")
|
1732
|
-
end
|
1723
|
+
end
|
1733
1724
|
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1737
|
-
args['perim_mult'] = 1.0
|
1738
|
-
else
|
1739
|
-
args['perim_mult'] = building_form_defaults[:perim_mult]
|
1740
|
-
end
|
1741
|
-
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]}.")
|
1742
|
-
elsif args['perim_mult'] < 1.0
|
1743
|
-
runner.registerError("Other than the smart default value of 0, the minimum perimeter multiplier should be equal to 1.0 or greater.")
|
1744
|
-
return false
|
1745
|
-
end
|
1725
|
+
# bar_from_building_type_ratios
|
1726
|
+
# used for varieties of measures that create bar from building type ratios
|
1727
|
+
def bar_from_building_type_ratios(model, runner, user_arguments)
|
1746
1728
|
|
1747
|
-
|
1748
|
-
|
1749
|
-
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]}.")
|
1750
|
-
defaulted_args << 'floor_height'
|
1751
|
-
end
|
1752
|
-
# 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
|
1753
|
-
if args['wwr'] == 0.0
|
1754
|
-
args['wwr'] = building_form_defaults[:wwr]
|
1755
|
-
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]}.")
|
1756
|
-
end
|
1729
|
+
# prep arguments
|
1730
|
+
args = bar_arg_check_setup(model,runner,user_arguments)
|
1757
1731
|
|
1758
1732
|
# check that sum of fractions for b,c, and d is less than 1.0 (so something is left for primary building type)
|
1759
1733
|
bldg_type_a_fract_bldg_area = 1.0 - args['bldg_type_b_fract_bldg_area'] - args['bldg_type_c_fract_bldg_area'] - args['bldg_type_d_fract_bldg_area']
|
@@ -1763,7 +1737,7 @@ module OsLib_ModelGeneration
|
|
1763
1737
|
end
|
1764
1738
|
|
1765
1739
|
# Make the standard applier
|
1766
|
-
standard = Standard.build(
|
1740
|
+
standard = Standard.build((args['template']).to_s)
|
1767
1741
|
|
1768
1742
|
# report initial condition of model
|
1769
1743
|
runner.registerInitialCondition("The building started with #{model.getSpaces.size} spaces.")
|
@@ -1793,14 +1767,14 @@ module OsLib_ModelGeneration
|
|
1793
1767
|
# gather data for bldg_type_a
|
1794
1768
|
building_type_hash[args['bldg_type_a']] = {}
|
1795
1769
|
building_type_hash[args['bldg_type_a']][:frac_bldg_area] = bldg_type_a_fract_bldg_area
|
1796
|
-
#building_type_hash[args['bldg_type_a']][:num_units] = args['bldg_type_a_num_units']
|
1770
|
+
# building_type_hash[args['bldg_type_a']][:num_units] = args['bldg_type_a_num_units']
|
1797
1771
|
building_type_hash[args['bldg_type_a']][:space_types] = get_space_types_from_building_type(args['bldg_type_a'], args['template'], true)
|
1798
1772
|
|
1799
1773
|
# gather data for bldg_type_b
|
1800
1774
|
if args['bldg_type_b_fract_bldg_area'] > 0
|
1801
1775
|
building_type_hash[args['bldg_type_b']] = {}
|
1802
1776
|
building_type_hash[args['bldg_type_b']][:frac_bldg_area] = args['bldg_type_b_fract_bldg_area']
|
1803
|
-
#building_type_hash[args['bldg_type_b']][:num_units] = args['bldg_type_b_num_units']
|
1777
|
+
# building_type_hash[args['bldg_type_b']][:num_units] = args['bldg_type_b_num_units']
|
1804
1778
|
building_type_hash[args['bldg_type_b']][:space_types] = get_space_types_from_building_type(args['bldg_type_b'], args['template'], true)
|
1805
1779
|
end
|
1806
1780
|
|
@@ -1808,7 +1782,7 @@ module OsLib_ModelGeneration
|
|
1808
1782
|
if args['bldg_type_c_fract_bldg_area'] > 0
|
1809
1783
|
building_type_hash[args['bldg_type_c']] = {}
|
1810
1784
|
building_type_hash[args['bldg_type_c']][:frac_bldg_area] = args['bldg_type_c_fract_bldg_area']
|
1811
|
-
#building_type_hash[args['bldg_type_c']][:num_units] = args['bldg_type_c_num_units']
|
1785
|
+
# building_type_hash[args['bldg_type_c']][:num_units] = args['bldg_type_c_num_units']
|
1812
1786
|
building_type_hash[args['bldg_type_c']][:space_types] = get_space_types_from_building_type(args['bldg_type_c'], args['template'], true)
|
1813
1787
|
end
|
1814
1788
|
|
@@ -1816,10 +1790,145 @@ module OsLib_ModelGeneration
|
|
1816
1790
|
if args['bldg_type_d_fract_bldg_area'] > 0
|
1817
1791
|
building_type_hash[args['bldg_type_d']] = {}
|
1818
1792
|
building_type_hash[args['bldg_type_d']][:frac_bldg_area] = args['bldg_type_d_fract_bldg_area']
|
1819
|
-
#building_type_hash[args['bldg_type_d']][:num_units] = args['bldg_type_d_num_units']
|
1793
|
+
# building_type_hash[args['bldg_type_d']][:num_units] = args['bldg_type_d_num_units']
|
1820
1794
|
building_type_hash[args['bldg_type_d']][:space_types] = get_space_types_from_building_type(args['bldg_type_d'], args['template'], true)
|
1821
1795
|
end
|
1822
1796
|
|
1797
|
+
# call bar_from_building_space_type_ratios to generate bar
|
1798
|
+
bar_from_space_type_ratios(model, runner, user_arguments, args, building_type_hash)
|
1799
|
+
|
1800
|
+
return true
|
1801
|
+
|
1802
|
+
end
|
1803
|
+
|
1804
|
+
# bar_from_space_type_ratios
|
1805
|
+
# used for varieties of measures that create bar from space type or building type ratios
|
1806
|
+
# args and building_type_hash should both be nil or neither shoould be nill
|
1807
|
+
def bar_from_space_type_ratios(model, runner, user_arguments, args = nil, building_type_hash = nil)
|
1808
|
+
|
1809
|
+
# do not setup arguments if they were already passed in to this method
|
1810
|
+
if args.nil?
|
1811
|
+
# prep arguments
|
1812
|
+
args = bar_arg_check_setup(model,runner,user_arguments,false) # false stops it from checking args on used in bar_from_building_type_ratios
|
1813
|
+
|
1814
|
+
# identify primary building type for building form defaults
|
1815
|
+
primary_building_type = "PrimarySchool" # see what building type represents the most floro area
|
1816
|
+
building_form_defaults = building_form_defaults(primary_building_type)
|
1817
|
+
|
1818
|
+
# process arg into hash
|
1819
|
+
space_type_hash_name = {}
|
1820
|
+
args['space_type_hash_string'][0..-1].split(/, /).each { |entry| entryMap = entry.split(/=>/); value_str = entryMap[1]; space_type_hash_name[entryMap[0].strip[0..-1].to_s] = value_str.nil? ? '' : value_str.strip[0..-1].to_f }
|
1821
|
+
|
1822
|
+
# create building type hasn from space type ratios
|
1823
|
+
building_type_hash = {}
|
1824
|
+
building_type_fraction_of_building = 0.0
|
1825
|
+
space_type_hash_name.each do |building_space_type,ratio|
|
1826
|
+
building_type = building_space_type.split("|")[0].strip
|
1827
|
+
space_type = building_space_type.split("|")[1].strip
|
1828
|
+
|
1829
|
+
# harvest height and circ info from get_space_types_from_building_type(building_type, template, whole_building = true)
|
1830
|
+
building_type_lookup_info = get_space_types_from_building_type(building_type,args['template'])
|
1831
|
+
if building_type_lookup_info.size == 0
|
1832
|
+
runner.registerWarning("#{building_type} looks like an invalid building type for #{args['template']}")
|
1833
|
+
end
|
1834
|
+
space_type_info_hash = {}
|
1835
|
+
if building_type_lookup_info.key?(space_type)
|
1836
|
+
if building_type_lookup_info[space_type].key?(:story_height)
|
1837
|
+
space_type_info_hash[:story_height] = building_type_lookup_info[space_type][:story_height]
|
1838
|
+
end
|
1839
|
+
if building_type_lookup_info[space_type].key?(:default)
|
1840
|
+
space_type_info_hash[:default] = building_type_lookup_info[space_type][:default]
|
1841
|
+
end
|
1842
|
+
if building_type_lookup_info[space_type].key?(:circ)
|
1843
|
+
space_type_info_hash[:circ] = building_type_lookup_info[space_type][:circ]
|
1844
|
+
end
|
1845
|
+
else
|
1846
|
+
runner.registerWarning("#{space_type} looks like an invalid space type for #{building_type}")
|
1847
|
+
end
|
1848
|
+
|
1849
|
+
# extend harvested data with custom ratios from space type ratio string argument.
|
1850
|
+
if building_type_hash.key?(building_type)
|
1851
|
+
building_type_hash[building_type][:frac_bldg_area] += ratio
|
1852
|
+
space_type_info_hash[:ratio] = ratio
|
1853
|
+
building_type_hash[building_type][:space_types][space_type] = space_type_info_hash
|
1854
|
+
else
|
1855
|
+
building_type_hash[building_type] = {}
|
1856
|
+
building_type_hash[building_type][:frac_bldg_area] = ratio
|
1857
|
+
space_type_info_hash[:ratio] = ratio
|
1858
|
+
space_types = {}
|
1859
|
+
space_types[space_type] = space_type_info_hash
|
1860
|
+
building_type_hash[building_type][:space_types] = space_types
|
1861
|
+
end
|
1862
|
+
building_type_fraction_of_building += ratio
|
1863
|
+
end
|
1864
|
+
|
1865
|
+
# todo - confirm if this will get normalized up/down later of if I should fix or stop here instead of just a warning
|
1866
|
+
if building_type_fraction_of_building > 1.0
|
1867
|
+
runner.registerWarning("Sum of Space Type Ratio of #{building_type_fraction_of_building} is greater than the expected value of 1.0")
|
1868
|
+
elsif building_type_fraction_of_building < 1.0
|
1869
|
+
runner.registerWarning("Sum of Space Type Ratio of #{building_type_fraction_of_building} is less than the expected value of 1.0")
|
1870
|
+
end
|
1871
|
+
|
1872
|
+
else # else is used when bar_from_building_type_ratio is used
|
1873
|
+
|
1874
|
+
# if aspect ratio, story height or wwr have argument value of 0 then use smart building type defaults
|
1875
|
+
primary_building_type = args['bldg_type_a']
|
1876
|
+
|
1877
|
+
end
|
1878
|
+
|
1879
|
+
# get defaults for the primary building type
|
1880
|
+
building_form_defaults = building_form_defaults(primary_building_type)
|
1881
|
+
|
1882
|
+
# store list of defaulted items
|
1883
|
+
defaulted_args = []
|
1884
|
+
|
1885
|
+
if args['ns_to_ew_ratio'] == 0.0
|
1886
|
+
args['ns_to_ew_ratio'] = building_form_defaults[:aspect_ratio]
|
1887
|
+
runner.registerInfo("0.0 value for aspect ratio will be replaced with smart default for #{primary_building_type} of #{building_form_defaults[:aspect_ratio]}.")
|
1888
|
+
end
|
1889
|
+
|
1890
|
+
if args['perim_mult'] == 0.0
|
1891
|
+
# if this is not defined then use default of 1.0
|
1892
|
+
if !building_form_defaults.has_key?(:perim_mult)
|
1893
|
+
args['perim_mult'] = 1.0
|
1894
|
+
else
|
1895
|
+
args['perim_mult'] = building_form_defaults[:perim_mult]
|
1896
|
+
end
|
1897
|
+
runner.registerInfo("0.0 value for minimum perimeter multiplier will be replaced with smart default for #{primary_building_type} of #{building_form_defaults[:perim_mult]}.")
|
1898
|
+
elsif args['perim_mult'] < 1.0
|
1899
|
+
runner.registerError("Other than the smart default value of 0, the minimum perimeter multiplier should be equal to 1.0 or greater.")
|
1900
|
+
return false
|
1901
|
+
end
|
1902
|
+
|
1903
|
+
if args['floor_height'] == 0.0
|
1904
|
+
args['floor_height'] = building_form_defaults[:typical_story]
|
1905
|
+
runner.registerInfo("0.0 value for floor height will be replaced with smart default for #{primary_building_type} of #{building_form_defaults[:typical_story]}.")
|
1906
|
+
defaulted_args << 'floor_height'
|
1907
|
+
end
|
1908
|
+
# because of this can't set wwr to 0.0. If that is desired then we can change this to check for 1.0 instead of 0.0
|
1909
|
+
if args['wwr'] == 0.0
|
1910
|
+
args['wwr'] = building_form_defaults[:wwr]
|
1911
|
+
runner.registerInfo("0.0 value for window to wall ratio will be replaced with smart default for #{primary_building_type} of #{building_form_defaults[:wwr]}.")
|
1912
|
+
end
|
1913
|
+
|
1914
|
+
# Make the standard applier
|
1915
|
+
standard = Standard.build("#{args['template']}")
|
1916
|
+
|
1917
|
+
# report initial condition of model
|
1918
|
+
runner.registerInitialCondition("The building started with #{model.getSpaces.size} spaces.")
|
1919
|
+
|
1920
|
+
# determine of ns_ew needs to be mirrored
|
1921
|
+
mirror_ns_ew = false
|
1922
|
+
rotation = model.getBuilding.northAxis
|
1923
|
+
if rotation > 45.0 && rotation < 135.0
|
1924
|
+
mirror_ns_ew = true
|
1925
|
+
elsif rotation > 45.0 && rotation < 135.0
|
1926
|
+
mirror_ns_ew = true
|
1927
|
+
end
|
1928
|
+
|
1929
|
+
# remove non-resource objects not removed by removing the building
|
1930
|
+
remove_non_resource_objects(runner, model)
|
1931
|
+
|
1823
1932
|
# creating space types for requested building types
|
1824
1933
|
building_type_hash.each do |building_type, building_type_hash|
|
1825
1934
|
runner.registerInfo("Creating Space Types for #{building_type}.")
|
@@ -1842,8 +1951,8 @@ module OsLib_ModelGeneration
|
|
1842
1951
|
# set color
|
1843
1952
|
test = standard.space_type_apply_rendering_color(space_type) # this uses openstudio-standards
|
1844
1953
|
if !test
|
1845
|
-
#
|
1846
|
-
#runner.registerWarning("Could not find color for #{args['template']} #{space_type.name}")
|
1954
|
+
# TODO: - once fixed in standards un-comment this
|
1955
|
+
# runner.registerWarning("Could not find color for #{args['template']} #{space_type.name}")
|
1847
1956
|
end
|
1848
1957
|
|
1849
1958
|
# extend hash to hold new space type object
|
@@ -1871,7 +1980,7 @@ module OsLib_ModelGeneration
|
|
1871
1980
|
runner.registerWarning('User-defined single floor area was used for calculation of total building floor area')
|
1872
1981
|
# add warning if custom_height_bar is true and applicable building type is selected
|
1873
1982
|
if args['custom_height_bar']
|
1874
|
-
runner.registerWarning(
|
1983
|
+
runner.registerWarning('Cannot use custom height bar with single floor area method, will not create custom height bar.')
|
1875
1984
|
args['custom_height_bar'] = false
|
1876
1985
|
end
|
1877
1986
|
else
|
@@ -1886,8 +1995,7 @@ module OsLib_ModelGeneration
|
|
1886
1995
|
building_type_hash = building_type_hash.sort_by { |k, v| v[:frac_bldg_area] }
|
1887
1996
|
end
|
1888
1997
|
building_type_hash.each do |building_type, building_type_hash|
|
1889
|
-
|
1890
|
-
if args["double_loaded_corridor"] == "Primary Space Type"
|
1998
|
+
if args['double_loaded_corridor'] == 'Primary Space Type'
|
1891
1999
|
|
1892
2000
|
# see if building type has circulation space type, if so then merge that along with default space type into hash key in place of space type
|
1893
2001
|
default_st = nil
|
@@ -1902,8 +2010,8 @@ module OsLib_ModelGeneration
|
|
1902
2010
|
runner.registerInfo("Combining #{default_st} and #{circ_st} into a group representing a double loaded corridor")
|
1903
2011
|
|
1904
2012
|
# add new item
|
1905
|
-
building_type_hash[:space_types][
|
1906
|
-
double_loaded_st = building_type_hash[:space_types][
|
2013
|
+
building_type_hash[:space_types]['Double Loaded Corridor'] = {}
|
2014
|
+
double_loaded_st = building_type_hash[:space_types]['Double Loaded Corridor']
|
1907
2015
|
double_loaded_st[:ratio] = building_type_hash[:space_types][default_st][:ratio] + building_type_hash[:space_types][circ_st][:ratio]
|
1908
2016
|
double_loaded_st[:double_loaded_corridor] = true
|
1909
2017
|
double_loaded_st[:space_type] = model.getBuilding
|
@@ -1938,21 +2046,21 @@ module OsLib_ModelGeneration
|
|
1938
2046
|
multi_height_space_types_hash[space_type][:wwr] = hash[:wwr]
|
1939
2047
|
end
|
1940
2048
|
else
|
1941
|
-
|
1942
|
-
|
1943
|
-
|
1944
|
-
|
1945
|
-
|
1946
|
-
|
1947
|
-
|
1948
|
-
|
1949
|
-
|
2049
|
+
# only add wwr if 0 used for wwr arg and if space type has wwr as key
|
2050
|
+
space_types_hash[space_type] = { floor_area: final_floor_area, space_type: space_type }
|
2051
|
+
if hash.key?(:orig_ratio) then space_types_hash[space_type][:orig_ratio] = hash[:orig_ratio] end
|
2052
|
+
if args['wwr'] == 0 && hash.key?(:wwr)
|
2053
|
+
space_types_hash[space_type][:wwr] = hash[:wwr]
|
2054
|
+
end
|
2055
|
+
if hash[:double_loaded_corridor]
|
2056
|
+
space_types_hash[space_type][:children] = hash[:children]
|
2057
|
+
end
|
1950
2058
|
end
|
1951
2059
|
end
|
1952
2060
|
end
|
1953
2061
|
|
1954
2062
|
# resort if not sorted by building type
|
1955
|
-
if args['space_type_sort_logic'] ==
|
2063
|
+
if args['space_type_sort_logic'] == 'Size'
|
1956
2064
|
# added code to convert to hash. I use sort_by 3 other times, but those seem to be working fine as is now.
|
1957
2065
|
space_types_hash = Hash[space_types_hash.sort_by { |k, v| v[:floor_area] }]
|
1958
2066
|
end
|
@@ -1960,14 +2068,14 @@ module OsLib_ModelGeneration
|
|
1960
2068
|
# calculate targets for testing
|
1961
2069
|
target_areas = {} # used for checks
|
1962
2070
|
target_areas_cust_height = 0.0
|
1963
|
-
space_types_hash.each do |k,v|
|
2071
|
+
space_types_hash.each do |k, v|
|
1964
2072
|
if v.key?(:orig_ratio)
|
1965
2073
|
target_areas[k] = v[:orig_ratio] * total_bldg_floor_area_si
|
1966
2074
|
else
|
1967
2075
|
target_areas[k] = v[:floor_area]
|
1968
2076
|
end
|
1969
2077
|
end
|
1970
|
-
multi_height_space_types_hash.each do |k,v|
|
2078
|
+
multi_height_space_types_hash.each do |k, v|
|
1971
2079
|
if v.key?(:orig_ratio)
|
1972
2080
|
target_areas[k] = v[:orig_ratio] * total_bldg_floor_area_si
|
1973
2081
|
target_areas_cust_height += v[:orig_ratio] * total_bldg_floor_area_si
|
@@ -1982,19 +2090,19 @@ module OsLib_ModelGeneration
|
|
1982
2090
|
footprint_si = (total_bldg_floor_area_si - target_areas_cust_height) / num_stories.to_f
|
1983
2091
|
end
|
1984
2092
|
floor_height_si = OpenStudio.convert(args['floor_height'], 'ft', 'm').get
|
1985
|
-
min_allow_size = OpenStudio.convert(15.0,'ft','m').get
|
1986
|
-
specified_bar_width_si = OpenStudio.convert(args['bar_width'],'ft','m').get
|
2093
|
+
min_allow_size = OpenStudio.convert(15.0, 'ft', 'm').get
|
2094
|
+
specified_bar_width_si = OpenStudio.convert(args['bar_width'], 'ft', 'm').get
|
1987
2095
|
|
1988
2096
|
# set custom width
|
1989
2097
|
if specified_bar_width_si > 0
|
1990
|
-
runner.registerInfo(
|
2098
|
+
runner.registerInfo('Ignoring perimeter multiplier argument when non zero width argument is used')
|
1991
2099
|
if footprint_si / specified_bar_width_si >= min_allow_size
|
1992
2100
|
width = specified_bar_width_si
|
1993
2101
|
length = footprint_si / width
|
1994
2102
|
else
|
1995
2103
|
length = min_allow_size
|
1996
2104
|
width = footprint_si / length
|
1997
|
-
runner.registerWarning(
|
2105
|
+
runner.registerWarning('User specified width results in a length that is too short, adjusting width to be narrower than specified.')
|
1998
2106
|
end
|
1999
2107
|
width_cust_height = specified_bar_width_si
|
2000
2108
|
else
|
@@ -2004,29 +2112,29 @@ module OsLib_ModelGeneration
|
|
2004
2112
|
end
|
2005
2113
|
length_cust_height = target_areas_cust_height / width_cust_height
|
2006
2114
|
if args['perim_mult'] > 1.0 && target_areas_cust_height > 0.0
|
2007
|
-
#
|
2008
|
-
runner.registerWarning(
|
2115
|
+
# TODO: - update tests that hit this warning
|
2116
|
+
runner.registerWarning('Ignoring perimeter multiplier for bar that represents custom height spaces.')
|
2009
2117
|
end
|
2010
2118
|
|
2011
2119
|
# check if dual bar is needed
|
2012
2120
|
dual_bar = false
|
2013
2121
|
if specified_bar_width_si > 0.0 && args['bar_division_method'] == 'Multiple Space Types - Individual Stories Sliced'
|
2014
|
-
if length/width != args['ns_to_ew_ratio']
|
2015
|
-
|
2016
|
-
if args['ns_to_ew_ratio'] >= 1.0 && args['ns_to_ew_ratio'] > length/width
|
2017
|
-
runner.registerWarning("Can't meet target aspect ratio of #{args['ns_to_ew_ratio']}, Lowering it to #{length/width} ")
|
2018
|
-
args['ns_to_ew_ratio'] = length/width
|
2019
|
-
elsif args['ns_to_ew_ratio'] < 1.0 && args['ns_to_ew_ratio'] > length/width
|
2020
|
-
runner.registerWarning("Can't meet target aspect ratio of #{args['ns_to_ew_ratio']}, Increasing it to #{length/width} ")
|
2021
|
-
args['ns_to_ew_ratio'] = length/width
|
2122
|
+
if length / width != args['ns_to_ew_ratio']
|
2123
|
+
|
2124
|
+
if args['ns_to_ew_ratio'] >= 1.0 && args['ns_to_ew_ratio'] > length / width
|
2125
|
+
runner.registerWarning("Can't meet target aspect ratio of #{args['ns_to_ew_ratio']}, Lowering it to #{length / width} ")
|
2126
|
+
args['ns_to_ew_ratio'] = length / width
|
2127
|
+
elsif args['ns_to_ew_ratio'] < 1.0 && args['ns_to_ew_ratio'] > length / width
|
2128
|
+
runner.registerWarning("Can't meet target aspect ratio of #{args['ns_to_ew_ratio']}, Increasing it to #{length / width} ")
|
2129
|
+
args['ns_to_ew_ratio'] = length / width
|
2022
2130
|
else
|
2023
2131
|
# check if each bar would be longer then 15 feet, then set as dual bar and override perimeter multiplier
|
2024
|
-
length_alt1 = ((args['ns_to_ew_ratio'] * footprint_si) / width + 2 * args['ns_to_ew_ratio'] * width - 2 * width)/(1 + args['ns_to_ew_ratio'])
|
2132
|
+
length_alt1 = ((args['ns_to_ew_ratio'] * footprint_si) / width + 2 * args['ns_to_ew_ratio'] * width - 2 * width) / (1 + args['ns_to_ew_ratio'])
|
2025
2133
|
length_alt2 = length - length_alt1
|
2026
|
-
if [length_alt1,length_alt2].min >= min_allow_size
|
2134
|
+
if [length_alt1, length_alt2].min >= min_allow_size
|
2027
2135
|
dual_bar = true
|
2028
2136
|
else
|
2029
|
-
runner.registerInfo(
|
2137
|
+
runner.registerInfo('Second bar would be below minimum length, will model as single bar')
|
2030
2138
|
# swap length and width if single bar and aspect ratio less than 1
|
2031
2139
|
if args['ns_to_ew_ratio'] < 1.0
|
2032
2140
|
width = length
|
@@ -2036,7 +2144,7 @@ module OsLib_ModelGeneration
|
|
2036
2144
|
end
|
2037
2145
|
end
|
2038
2146
|
elsif args['perim_mult'] > 1.0 && args['bar_division_method'] == 'Multiple Space Types - Individual Stories Sliced'
|
2039
|
-
runner.registerInfo(
|
2147
|
+
runner.registerInfo('You selected a perimeter multiplier greater than 1.0 for a supported bar division method. This will result in two detached rectangular buildings if secondary bar meets minimum size requirements.')
|
2040
2148
|
dual_bar = true
|
2041
2149
|
elsif args['perim_mult'] > 1.0
|
2042
2150
|
runner.registerWarning("You selected a perimeter multiplier greater than 1.0 but didn't select a bar division method that supports this. The value for this argument will be ignored by the measure")
|
@@ -2060,7 +2168,7 @@ module OsLib_ModelGeneration
|
|
2060
2168
|
# custom quadratic equation to solve two bars with common width 2l^2 - p*l + 4a = 0
|
2061
2169
|
if target_perim**2 - 32 * footprint_si > 0
|
2062
2170
|
if specified_bar_width_si > 0
|
2063
|
-
runner.registerInfo(
|
2171
|
+
runner.registerInfo('Ignoring perimeter multiplier argument and using use specified bar width.')
|
2064
2172
|
dual_double_end_width = specified_bar_width_si
|
2065
2173
|
dual_double_end_length = footprint_si / dual_double_end_width
|
2066
2174
|
else
|
@@ -2069,7 +2177,7 @@ module OsLib_ModelGeneration
|
|
2069
2177
|
end
|
2070
2178
|
|
2071
2179
|
# now that stretched bar is made, determine where to split it and rotate
|
2072
|
-
bar_a_length = (args['ns_to_ew_ratio'] * (dual_double_end_length + dual_double_end_width) - dual_double_end_width)/(1 + args['ns_to_ew_ratio'])
|
2180
|
+
bar_a_length = (args['ns_to_ew_ratio'] * (dual_double_end_length + dual_double_end_width) - dual_double_end_width) / (1 + args['ns_to_ew_ratio'])
|
2073
2181
|
bar_b_length = dual_double_end_length - bar_a_length
|
2074
2182
|
area_a = bar_a_length * dual_double_end_width
|
2075
2183
|
area_b = bar_b_length * dual_double_end_width
|
@@ -2088,15 +2196,15 @@ module OsLib_ModelGeneration
|
|
2088
2196
|
adiabatic_dual_double_end_width = footprint_si / adiabatic_dual_double_end_length
|
2089
2197
|
# test for unexpected
|
2090
2198
|
unexpected = false
|
2091
|
-
if (target_area - adiabatic_dual_double_end_length*adiabatic_dual_double_end_width).abs > tol_testing then unexpected = true end
|
2199
|
+
if (target_area - adiabatic_dual_double_end_length * adiabatic_dual_double_end_width).abs > tol_testing then unexpected = true end
|
2092
2200
|
if specified_bar_width_si == 0
|
2093
2201
|
if (target_perim - (adiabatic_dual_double_end_length * 2 + adiabatic_dual_double_end_width * 2)).abs > tol_testing then unexpected = true end
|
2094
2202
|
end
|
2095
2203
|
if unexpected
|
2096
|
-
runner.registerWarning(
|
2204
|
+
runner.registerWarning('Unexpected values for dual rectangle adiabatic ends bar b.')
|
2097
2205
|
end
|
2098
2206
|
# now that stretched bar is made, determine where to split it and rotate
|
2099
|
-
adiabatic_bar_a_length = (args['ns_to_ew_ratio'] * (adiabatic_dual_double_end_length + adiabatic_dual_double_end_width))/(1 + args['ns_to_ew_ratio'])
|
2207
|
+
adiabatic_bar_a_length = (args['ns_to_ew_ratio'] * (adiabatic_dual_double_end_length + adiabatic_dual_double_end_width)) / (1 + args['ns_to_ew_ratio'])
|
2100
2208
|
adiabatic_bar_b_length = adiabatic_dual_double_end_length - adiabatic_bar_a_length
|
2101
2209
|
adiabatic_area_a = adiabatic_bar_a_length * adiabatic_dual_double_end_width
|
2102
2210
|
adiabatic_area_b = adiabatic_bar_b_length * adiabatic_dual_double_end_width
|
@@ -2115,28 +2223,28 @@ module OsLib_ModelGeneration
|
|
2115
2223
|
# apply prescribed approach for stretched or dual bar
|
2116
2224
|
if dual_bar_calc_approach == 'dual_bar'
|
2117
2225
|
runner.registerInfo("Stretched #{OpenStudio.toNeatString(OpenStudio.convert(dual_double_end_length, 'm', 'ft').get, 0, true)} ft x #{OpenStudio.toNeatString(OpenStudio.convert(dual_double_end_width, 'm', 'ft').get, 0, true)} ft rectangle has an area of #{OpenStudio.toNeatString(OpenStudio.convert(dual_double_end_length * dual_double_end_width, 'm^2', 'ft^2').get, 0, true)} ft^2. When split in two the perimeter will be #{OpenStudio.toNeatString(OpenStudio.convert(dual_double_end_length * 2 + dual_double_end_width * 4, 'm', 'ft').get, 0, true)} ft")
|
2118
|
-
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
|
2119
|
-
runner.registerWarning(
|
2226
|
+
if (target_area - dual_double_end_length * dual_double_end_width).abs > tol_testing || (target_perim - (dual_double_end_length * 2 + dual_double_end_width * 4)).abs > tol_testing
|
2227
|
+
runner.registerWarning('Unexpected values for dual rectangle.')
|
2120
2228
|
end
|
2121
2229
|
|
2122
|
-
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")
|
2123
|
-
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
|
2124
|
-
runner.registerWarning(
|
2230
|
+
runner.registerInfo("For stretched split bar, to match target ns/ew aspect ratio #{OpenStudio.toNeatString(OpenStudio.convert(bar_a_length, 'm', 'ft').get, 0, true)} ft of bar should be horizontal, with #{OpenStudio.toNeatString(OpenStudio.convert(bar_b_length, 'm', 'ft').get, 0, true)} ft turned 90 degrees. Combined area is #{OpenStudio.toNeatString(OpenStudio.convert(area_a + area_b, 'm^2', 'ft^2').get, 0, true)} ft^2. Combined perimeter is #{OpenStudio.toNeatString(OpenStudio.convert(bar_a_length * 2 + bar_b_length * 2 + dual_double_end_width * 4, 'm', 'ft').get, 0, true)} ft")
|
2231
|
+
if (target_area - (area_a + area_b)).abs > tol_testing || (target_perim - (bar_a_length * 2 + bar_b_length * 2 + dual_double_end_width * 4)).abs > tol_testing
|
2232
|
+
runner.registerWarning('Unexpected values for rotated dual rectangle')
|
2125
2233
|
end
|
2126
2234
|
elsif dual_bar_calc_approach == 'adiabatic_ends_bar_b'
|
2127
2235
|
runner.registerInfo("Can't hit target perimeter with two rectangles, need to make two ends adiabatic")
|
2128
2236
|
|
2129
|
-
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")
|
2130
|
-
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
|
2131
|
-
runner.registerWarning(
|
2237
|
+
runner.registerInfo("For dual bar with adiabatic ends on bar b, to reach target aspect ratio #{OpenStudio.toNeatString(OpenStudio.convert(adiabatic_bar_a_length, 'm', 'ft').get, 0, true)} ft of bar should be north/south, with #{OpenStudio.toNeatString(OpenStudio.convert(adiabatic_bar_b_length, 'm', 'ft').get, 0, true)} ft turned 90 degrees. Combined area is #{OpenStudio.toNeatString(OpenStudio.convert(adiabatic_area_a + adiabatic_area_b, 'm^2', 'ft^2').get, 0, true)} ft^2}. Combined perimeter is #{OpenStudio.toNeatString(OpenStudio.convert(adiabatic_bar_a_length * 2 + adiabatic_bar_b_length * 2 + adiabatic_dual_double_end_width * 2, 'm', 'ft').get, 0, true)} ft")
|
2238
|
+
if (target_area - (adiabatic_area_a + adiabatic_area_b)).abs > tol_testing || (target_perim - (adiabatic_bar_a_length * 2 + adiabatic_bar_b_length * 2 + adiabatic_dual_double_end_width * 2)).abs > tol_testing
|
2239
|
+
runner.registerWarning('Unexpected values for rotated dual rectangle adiabatic ends bar b')
|
2132
2240
|
end
|
2133
2241
|
else # stretched bar
|
2134
2242
|
dual_bar = false
|
2135
2243
|
|
2136
2244
|
stretched_length = 0.25 * (target_perim + Math.sqrt(target_perim**2 - 16 * footprint_si))
|
2137
2245
|
stretched_width = footprint_si / stretched_length
|
2138
|
-
if (target_area - stretched_length*stretched_width).abs > tol_testing || (target_perim - (stretched_length + stretched_width)*2) > tol_testing
|
2139
|
-
runner.registerWarning(
|
2246
|
+
if (target_area - stretched_length * stretched_width).abs > tol_testing || (target_perim - (stretched_length + stretched_width) * 2) > tol_testing
|
2247
|
+
runner.registerWarning('Unexpected values for single stretched')
|
2140
2248
|
end
|
2141
2249
|
|
2142
2250
|
width = stretched_width
|
@@ -2172,7 +2280,7 @@ module OsLib_ModelGeneration
|
|
2172
2280
|
end
|
2173
2281
|
bars['primary'][:floor_height_si] = floor_height_si # can make use of this when breaking out multi-height spaces
|
2174
2282
|
bars['primary'][:num_stories] = num_stories
|
2175
|
-
bars['primary'][:center_of_footprint] = OpenStudio::Point3d.new(0.0,0.0,0.0)
|
2283
|
+
bars['primary'][:center_of_footprint] = OpenStudio::Point3d.new(0.0, 0.0, 0.0)
|
2176
2284
|
space_types_hash_secondary = {}
|
2177
2285
|
if dual_bar
|
2178
2286
|
# loop through each story and move portion for other bar to its own hash
|
@@ -2181,9 +2289,9 @@ module OsLib_ModelGeneration
|
|
2181
2289
|
footprint_counter = primary_footprint
|
2182
2290
|
secondary_footprint_counter = secondary_footprint
|
2183
2291
|
story_counter = 0
|
2184
|
-
pri_sec_tol = 0.0001 #m^2
|
2185
|
-
pri_sec_min_area = 0.0001 #m^2
|
2186
|
-
space_types_hash.each do |k,v|
|
2292
|
+
pri_sec_tol = 0.0001 # m^2
|
2293
|
+
pri_sec_min_area = 0.0001 # m^2
|
2294
|
+
space_types_hash.each do |k, v|
|
2187
2295
|
space_type_left = v[:floor_area]
|
2188
2296
|
|
2189
2297
|
# do not go to next space type until this one is evaulate, which may span stories
|
@@ -2191,23 +2299,23 @@ module OsLib_ModelGeneration
|
|
2191
2299
|
|
2192
2300
|
# use secondary footprint if any left
|
2193
2301
|
if secondary_footprint_counter > 0.0
|
2194
|
-
hash_area = [space_type_left,secondary_footprint_counter].min
|
2302
|
+
hash_area = [space_type_left, secondary_footprint_counter].min
|
2195
2303
|
|
2196
2304
|
# confirm that the part of space type use or what is left is greater than min allowed value
|
2197
2305
|
projected_space_type_left = space_type_left - hash_area
|
2198
|
-
test_a =
|
2199
|
-
test_b =
|
2200
|
-
test_c =
|
2306
|
+
test_a = hash_area >= pri_sec_min_area
|
2307
|
+
test_b = projected_space_type_left >= pri_sec_min_area || projected_space_type_left == 0.0 ? true : false
|
2308
|
+
test_c = k == space_types_hash.keys.last # if last space type accept sliver, no other space to infil
|
2201
2309
|
if (test_a && test_b) || test_c
|
2202
|
-
if space_types_hash_secondary.
|
2310
|
+
if space_types_hash_secondary.key?(k)
|
2203
2311
|
# add to what was added for previous story
|
2204
2312
|
space_types_hash_secondary[k][:floor_area] += hash_area
|
2205
2313
|
else
|
2206
2314
|
# add new space type to hash
|
2207
|
-
if v.
|
2208
|
-
space_types_hash_secondary[k] = {:
|
2315
|
+
if v.key?(:children)
|
2316
|
+
space_types_hash_secondary[k] = { floor_area: hash_area, space_type: v[:space_type], children: v[:children] }
|
2209
2317
|
else
|
2210
|
-
space_types_hash_secondary[k] = {:
|
2318
|
+
space_types_hash_secondary[k] = { floor_area: hash_area, space_type: v[:space_type] }
|
2211
2319
|
end
|
2212
2320
|
end
|
2213
2321
|
space_types_hash[k][:floor_area] -= hash_area
|
@@ -2224,7 +2332,7 @@ module OsLib_ModelGeneration
|
|
2224
2332
|
space_type_left = 0.0
|
2225
2333
|
else
|
2226
2334
|
# then look at primary bar
|
2227
|
-
hash_area_pri = [space_type_left,footprint_counter].min
|
2335
|
+
hash_area_pri = [space_type_left, footprint_counter].min
|
2228
2336
|
footprint_counter -= hash_area_pri
|
2229
2337
|
space_type_left -= hash_area_pri
|
2230
2338
|
end
|
@@ -2249,13 +2357,13 @@ module OsLib_ModelGeneration
|
|
2249
2357
|
bars['primary'][:space_types_hash] = space_types_hash
|
2250
2358
|
bars['primary'][:args] = args
|
2251
2359
|
v = bars['primary']
|
2252
|
-
bar_hash_setup_run(runner,model,v[:args],v[:length],v[:width],v[:floor_height_si],v[:center_of_footprint],v[:space_types_hash],v[:num_stories])
|
2360
|
+
bar_hash_setup_run(runner, model, v[:args], v[:length], v[:width], v[:floor_height_si], v[:center_of_footprint], v[:space_types_hash], v[:num_stories])
|
2253
2361
|
|
2254
2362
|
# store offset value for multiple bars
|
2255
|
-
if args.
|
2363
|
+
if args.key?('bar_sep_dist_mult') && args['bar_sep_dist_mult'] > 0.0
|
2256
2364
|
offset_val = num_stories.ceil * floor_height_si * args['bar_sep_dist_mult']
|
2257
|
-
elsif args.
|
2258
|
-
runner.registerWarning(
|
2365
|
+
elsif args.key?('bar_sep_dist_mult')
|
2366
|
+
runner.registerWarning('Positive value is required for bar_sep_dist_mult, ignoring input and using value of 0.1')
|
2259
2367
|
offset_val = num_stories.ceil * floor_height_si * 0.1
|
2260
2368
|
else
|
2261
2369
|
offset_val = num_stories.ceil * floor_height_si * 10.0
|
@@ -2291,21 +2399,21 @@ module OsLib_ModelGeneration
|
|
2291
2399
|
else
|
2292
2400
|
runner.registerInfo('Adiabatic ends added to secondary bar because target perimeter multiplier could not be met with two full rectangular footprints.')
|
2293
2401
|
end
|
2294
|
-
bars['secondary'][:center_of_footprint] = OpenStudio::Point3d.new(adiabatic_bar_a_length * 0.5 + adiabatic_dual_double_end_width * 0.5 + offset_val,adiabatic_bar_b_length * 0.5 + adiabatic_dual_double_end_width * 0.5 + offset_val,0.0)
|
2402
|
+
bars['secondary'][:center_of_footprint] = OpenStudio::Point3d.new(adiabatic_bar_a_length * 0.5 + adiabatic_dual_double_end_width * 0.5 + offset_val, adiabatic_bar_b_length * 0.5 + adiabatic_dual_double_end_width * 0.5 + offset_val, 0.0)
|
2295
2403
|
else
|
2296
|
-
bars['secondary'][:center_of_footprint] = OpenStudio::Point3d.new(bar_a_length * 0.5 + dual_double_end_width * 0.5 + offset_val,bar_b_length * 0.5 + dual_double_end_width * 0.5 + offset_val,0.0)
|
2404
|
+
bars['secondary'][:center_of_footprint] = OpenStudio::Point3d.new(bar_a_length * 0.5 + dual_double_end_width * 0.5 + offset_val, bar_b_length * 0.5 + dual_double_end_width * 0.5 + offset_val, 0.0)
|
2297
2405
|
end
|
2298
2406
|
bars['secondary'][:args] = args2
|
2299
2407
|
|
2300
2408
|
# setup bar_hash and run create_bar
|
2301
2409
|
v = bars['secondary']
|
2302
|
-
bar_hash_setup_run(runner,model,v[:args],v[:length],v[:width],v[:floor_height_si],v[:center_of_footprint],v[:space_types_hash],v[:num_stories])
|
2410
|
+
bar_hash_setup_run(runner, model, v[:args], v[:length], v[:width], v[:floor_height_si], v[:center_of_footprint], v[:space_types_hash], v[:num_stories])
|
2303
2411
|
|
2304
2412
|
end
|
2305
2413
|
|
2306
2414
|
# future development (up against primary bar run intersection and surface matching after add all bars, avoid interior windows)
|
2307
2415
|
# I could loop through each space type and give them unique height but for now will just take largest height and make bar of that height, which is fine for prototypes
|
2308
|
-
if multi_height_space_types_hash.
|
2416
|
+
if !multi_height_space_types_hash.empty?
|
2309
2417
|
args3 = args.clone
|
2310
2418
|
bars['custom_height'] = {}
|
2311
2419
|
if mirror_ns_ew
|
@@ -2316,7 +2424,7 @@ module OsLib_ModelGeneration
|
|
2316
2424
|
bars['custom_height'][:width] = width_cust_height
|
2317
2425
|
end
|
2318
2426
|
if args['party_wall_stories_east'] + args['party_wall_stories_west'] + args['party_wall_stories_south'] + args['party_wall_stories_north'] > 0.0
|
2319
|
-
runner.registerWarning(
|
2427
|
+
runner.registerWarning('Ignorning party wall inputs for custom height bar')
|
2320
2428
|
end
|
2321
2429
|
|
2322
2430
|
# disable party walls
|
@@ -2331,14 +2439,14 @@ module OsLib_ModelGeneration
|
|
2331
2439
|
|
2332
2440
|
bars['custom_height'][:floor_height_si] = floor_height_si # can make use of this when breaking out multi-height spaces
|
2333
2441
|
bars['custom_height'][:num_stories] = num_stories
|
2334
|
-
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)
|
2335
|
-
bars['custom_height'][:floor_height_si] = OpenStudio.convert(custom_story_heights.max,'ft','m').get
|
2442
|
+
bars['custom_height'][:center_of_footprint] = OpenStudio::Point3d.new(bars['primary'][:length] * -0.5 - length_cust_height * 0.5 - offset_val, 0.0, 0.0)
|
2443
|
+
bars['custom_height'][:floor_height_si] = OpenStudio.convert(custom_story_heights.max, 'ft', 'm').get
|
2336
2444
|
bars['custom_height'][:num_stories] = 1
|
2337
2445
|
bars['custom_height'][:space_types_hash] = multi_height_space_types_hash
|
2338
2446
|
bars['custom_height'][:args] = args3
|
2339
2447
|
|
2340
2448
|
v = bars['custom_height']
|
2341
|
-
bar_hash_setup_run(runner,model,v[:args],v[:length],v[:width],v[:floor_height_si],v[:center_of_footprint],v[:space_types_hash],v[:num_stories])
|
2449
|
+
bar_hash_setup_run(runner, model, v[:args], v[:length], v[:width], v[:floor_height_si], v[:center_of_footprint], v[:space_types_hash], v[:num_stories])
|
2342
2450
|
end
|
2343
2451
|
|
2344
2452
|
# diagnostic log
|
@@ -2379,7 +2487,7 @@ module OsLib_ModelGeneration
|
|
2379
2487
|
if args['party_wall_fraction'] > 0
|
2380
2488
|
actual_ext_wall_area = model.getBuilding.exteriorWallArea
|
2381
2489
|
actual_party_wall_area = 0.0
|
2382
|
-
model.getSurfaces.each do |surface|
|
2490
|
+
model.getSurfaces.sort.each do |surface|
|
2383
2491
|
next if surface.outsideBoundaryCondition != 'Adiabatic'
|
2384
2492
|
next if surface.surfaceType != 'Wall'
|
2385
2493
|
actual_party_wall_area += surface.grossArea * surface.space.get.multiplier
|
@@ -2390,37 +2498,37 @@ module OsLib_ModelGeneration
|
|
2390
2498
|
end
|
2391
2499
|
|
2392
2500
|
# check ns/ew aspect ratio (harder to check when party walls are added)
|
2393
|
-
wall_and_window_by_orientation = OsLib_Geometry.getExteriorWindowAndWllAreaByOrientation(model,model.getSpaces)
|
2501
|
+
wall_and_window_by_orientation = OsLib_Geometry.getExteriorWindowAndWllAreaByOrientation(model, model.getSpaces)
|
2394
2502
|
wall_ns = (wall_and_window_by_orientation['northWall'] + wall_and_window_by_orientation['southWall'])
|
2395
2503
|
wall_ew = wall_and_window_by_orientation['eastWall'] + wall_and_window_by_orientation['westWall']
|
2396
|
-
wall_ns_ip = OpenStudio.convert(wall_ns,'m^2','ft^2').get
|
2397
|
-
wall_ew_ip = OpenStudio.convert(wall_ew,'m^2','ft^2').get
|
2398
|
-
runner.registerValue('wall_area_ip',wall_ns_ip + wall_ew_ip,'ft^2')
|
2399
|
-
runner.registerValue('ns_wall_area_ip',wall_ns_ip,'ft^2')
|
2400
|
-
runner.registerValue('ew_wall_area_ip',wall_ew_ip,'ft^2')
|
2504
|
+
wall_ns_ip = OpenStudio.convert(wall_ns, 'm^2', 'ft^2').get
|
2505
|
+
wall_ew_ip = OpenStudio.convert(wall_ew, 'm^2', 'ft^2').get
|
2506
|
+
runner.registerValue('wall_area_ip', wall_ns_ip + wall_ew_ip, 'ft^2')
|
2507
|
+
runner.registerValue('ns_wall_area_ip', wall_ns_ip, 'ft^2')
|
2508
|
+
runner.registerValue('ew_wall_area_ip', wall_ew_ip, 'ft^2')
|
2401
2509
|
# for now using perimeter of ground floor and average story area (building area / num_stories)
|
2402
|
-
runner.registerValue('floor_area_to_perim_ratio',model.getBuilding.floorArea /
|
2403
|
-
runner.registerValue('bar_width',OpenStudio.convert(bars['primary'][:width],'m','ft').get,'ft')
|
2510
|
+
runner.registerValue('floor_area_to_perim_ratio', model.getBuilding.floorArea / (OsLib_Geometry.calculate_perimeter(model) * num_stories))
|
2511
|
+
runner.registerValue('bar_width', OpenStudio.convert(bars['primary'][:width], 'm', 'ft').get, 'ft')
|
2404
2512
|
|
2405
2513
|
if args['party_wall_fraction'] > 0 || args['party_wall_stories_north'] > 0 || args['party_wall_stories_south'] > 0 || args['party_wall_stories_east'] > 0 || args['party_wall_stories_west'] > 0
|
2406
|
-
runner.registerInfo(
|
2514
|
+
runner.registerInfo('Target facade area by orientation not validated when party walls are applied')
|
2407
2515
|
elsif args['num_stories_above_grade'] != args['num_stories_above_grade'].ceil
|
2408
|
-
runner.registerInfo(
|
2516
|
+
runner.registerInfo('Target facade area by orientation not validated when partial top story is used')
|
2409
2517
|
elsif dual_bar_calc_approach == 'stretched'
|
2410
|
-
runner.registerInfo(
|
2411
|
-
elsif defaulted_args.include?('floor_height')
|
2412
|
-
runner.registerInfo(
|
2518
|
+
runner.registerInfo('Target facade area by orientation not validated when single stretched bar has to be used to meet target minimum perimeter multiplier')
|
2519
|
+
elsif defaulted_args.include?('floor_height') && args['custom_height_bar'] && !multi_height_space_types_hash.empty?
|
2520
|
+
runner.registerInfo('Target facade area by orientation not validated when a dedicated bar is added for space types with custom heights')
|
2413
2521
|
elsif args['bar_width'] > 0
|
2414
|
-
runner.registerInfo(
|
2522
|
+
runner.registerInfo('Target facade area by orientation not validated when a dedicated custom bar width is defined')
|
2415
2523
|
else
|
2416
2524
|
|
2417
2525
|
# adjust length versus width based on building rotation
|
2418
2526
|
if mirror_ns_ew
|
2419
|
-
wall_target_ns_ip = 2 * OpenStudio.convert(width,'m','ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
2420
|
-
wall_target_ew_ip = 2 * OpenStudio.convert(length,'m','ft').get
|
2527
|
+
wall_target_ns_ip = 2 * OpenStudio.convert(width, 'm', 'ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
2528
|
+
wall_target_ew_ip = 2 * OpenStudio.convert(length, 'm', 'ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
2421
2529
|
else
|
2422
|
-
wall_target_ns_ip = 2 * OpenStudio.convert(length,'m','ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
2423
|
-
wall_target_ew_ip = 2 * OpenStudio.convert(width,'m','ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
2530
|
+
wall_target_ns_ip = 2 * OpenStudio.convert(length, 'm', 'ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
2531
|
+
wall_target_ew_ip = 2 * OpenStudio.convert(width, 'm', 'ft').get * args['perim_mult'] * args['num_stories_above_grade'] * args['floor_height']
|
2424
2532
|
end
|
2425
2533
|
flag_error = false
|
2426
2534
|
if (wall_target_ns_ip - wall_ns_ip).abs > 0.1
|
@@ -2460,7 +2568,6 @@ module OsLib_ModelGeneration
|
|
2460
2568
|
# typical
|
2461
2569
|
# used for varieties of measures that create typical building from model
|
2462
2570
|
def typical_building_from_model(model, runner, user_arguments)
|
2463
|
-
|
2464
2571
|
# assign the user inputs to variables
|
2465
2572
|
args = OsLib_HelperMethods.createRunVariables(runner, model, user_arguments, arguments(model))
|
2466
2573
|
if !args then return false end
|
@@ -2530,7 +2637,7 @@ module OsLib_ModelGeneration
|
|
2530
2637
|
end
|
2531
2638
|
|
2532
2639
|
# check that weekday start time plus duration does not exceed 24 hrs
|
2533
|
-
if (wkdy_op_hrs_start_time_hr + wkdy_op_hrs_duration_hr + (wkdy_op_hrs_start_time_min + wkdy_op_hrs_duration_min)/60.0) > 24.0
|
2640
|
+
if (wkdy_op_hrs_start_time_hr + wkdy_op_hrs_duration_hr + (wkdy_op_hrs_start_time_min + wkdy_op_hrs_duration_min) / 60.0) > 24.0
|
2534
2641
|
runner.registerInfo("Weekday start time of #{args['wkdy_op_hrs_start']} plus duration of #{args['wkdy_op_hrs_duration']} is more than 24 hrs, hours of operation overlap midnight.")
|
2535
2642
|
end
|
2536
2643
|
end
|
@@ -2570,7 +2677,7 @@ module OsLib_ModelGeneration
|
|
2570
2677
|
end
|
2571
2678
|
|
2572
2679
|
# check that weekend start time plus duration does not exceed 24 hrs
|
2573
|
-
if (wknd_op_hrs_start_time_hr + wknd_op_hrs_duration_hr + (wknd_op_hrs_start_time_min + wknd_op_hrs_duration_min)/60.0) > 24.0
|
2680
|
+
if (wknd_op_hrs_start_time_hr + wknd_op_hrs_duration_hr + (wknd_op_hrs_start_time_min + wknd_op_hrs_duration_min) / 60.0) > 24.0
|
2574
2681
|
runner.registerInfo("Weekend start time of #{args['wknd_op_hrs_start']} plus duration of #{args['wknd_op_hrs_duration']} is more than 24 hrs, hours of operation overlap midnight.")
|
2575
2682
|
end
|
2576
2683
|
end
|
@@ -2586,7 +2693,7 @@ module OsLib_ModelGeneration
|
|
2586
2693
|
standard = Standard.build((args['template']).to_s)
|
2587
2694
|
|
2588
2695
|
# validate climate zone
|
2589
|
-
if !args.
|
2696
|
+
if !args.key?('climate_zone') || args['climate_zone'] == 'Lookup From Model'
|
2590
2697
|
climate_zone = standard.model_get_building_climate_zone_and_building_type(model)['climate_zone']
|
2591
2698
|
runner.registerInfo("Using climate zone #{climate_zone} from model")
|
2592
2699
|
else
|
@@ -2613,7 +2720,7 @@ module OsLib_ModelGeneration
|
|
2613
2720
|
|
2614
2721
|
# remove internal loads
|
2615
2722
|
if args['remove_objects']
|
2616
|
-
model.getSpaceLoads.each do |instance|
|
2723
|
+
model.getSpaceLoads.sort.each do |instance|
|
2617
2724
|
next if instance.name.to_s.include?('Elevator') # most prototype building types model exterior elevators with name Elevator
|
2618
2725
|
next if instance.to_InternalMass.is_initialized
|
2619
2726
|
next if instance.to_WaterUseEquipment.is_initialized
|
@@ -2623,7 +2730,7 @@ module OsLib_ModelGeneration
|
|
2623
2730
|
model.getDefaultScheduleSets.each(&:remove)
|
2624
2731
|
end
|
2625
2732
|
|
2626
|
-
model.getSpaceTypes.each do |space_type|
|
2733
|
+
model.getSpaceTypes.sort.each do |space_type|
|
2627
2734
|
# Don't add infiltration here; will be added later in the script
|
2628
2735
|
test = standard.space_type_apply_internal_loads(space_type, true, true, true, true, true, false)
|
2629
2736
|
if test == false
|
@@ -2642,7 +2749,7 @@ module OsLib_ModelGeneration
|
|
2642
2749
|
|
2643
2750
|
# warn if spaces in model without space type
|
2644
2751
|
spaces_without_space_types = []
|
2645
|
-
model.getSpaces.each do |space|
|
2752
|
+
model.getSpaces.sort.each do |space|
|
2646
2753
|
next if space.spaceType.is_initialized
|
2647
2754
|
spaces_without_space_types << space
|
2648
2755
|
end
|
@@ -2653,7 +2760,7 @@ module OsLib_ModelGeneration
|
|
2653
2760
|
|
2654
2761
|
# identify primary building type (used for construction, and ideally HVAC as well)
|
2655
2762
|
building_types = {}
|
2656
|
-
model.getSpaceTypes.each do |space_type|
|
2763
|
+
model.getSpaceTypes.sort.each do |space_type|
|
2657
2764
|
# populate hash of building types
|
2658
2765
|
if space_type.standardsBuildingType.is_initialized
|
2659
2766
|
bldg_type = space_type.standardsBuildingType.get
|
@@ -2681,8 +2788,10 @@ module OsLib_ModelGeneration
|
|
2681
2788
|
# TODO: - allow building type and space type specific constructions set selection.
|
2682
2789
|
if ['SmallHotel', 'LargeHotel', 'MidriseApartment', 'HighriseApartment'].include?(primary_bldg_type)
|
2683
2790
|
is_residential = 'Yes'
|
2791
|
+
occ_type = 'Residential'
|
2684
2792
|
else
|
2685
2793
|
is_residential = 'No'
|
2794
|
+
occ_type = 'Nonresidential'
|
2686
2795
|
end
|
2687
2796
|
bldg_def_const_set = standard.model_add_construction_set(model, climate_zone, lookup_building_type, nil, is_residential)
|
2688
2797
|
if bldg_def_const_set.is_initialized
|
@@ -2696,8 +2805,33 @@ module OsLib_ModelGeneration
|
|
2696
2805
|
return false
|
2697
2806
|
end
|
2698
2807
|
|
2808
|
+
# Replace the construction of any outdoor-facing "AtticFloor" surfaces
|
2809
|
+
# with the "ExteriorRoof" - "IEAD" construction for the specific climate zone and template.
|
2810
|
+
# This prevents creation of buildings where the DOE Prototype building construction set
|
2811
|
+
# assumes an attic but the supplied geometry used does not have an attic.
|
2812
|
+
new_construction = nil
|
2813
|
+
climate_zone_set = standard.model_find_climate_zone_set(model, climate_zone)
|
2814
|
+
model.getSurfaces.sort.each do |surf|
|
2815
|
+
next unless surf.outsideBoundaryCondition == 'Outdoors'
|
2816
|
+
next unless surf.surfaceType == 'RoofCeiling'
|
2817
|
+
next if surf.construction.empty?
|
2818
|
+
construction = surf.construction.get
|
2819
|
+
standards_info = construction.standardsInformation
|
2820
|
+
next if standards_info.intendedSurfaceType.empty?
|
2821
|
+
next unless standards_info.intendedSurfaceType.get == 'AtticFloor'
|
2822
|
+
if new_construction.nil?
|
2823
|
+
new_construction = standard.model_find_and_add_construction(model,
|
2824
|
+
climate_zone_set,
|
2825
|
+
'ExteriorRoof',
|
2826
|
+
'IEAD',
|
2827
|
+
occ_type)
|
2828
|
+
end
|
2829
|
+
surf.setConstruction(new_construction)
|
2830
|
+
runner.registerInfo("Changed the construction for #{surf.name} from #{construction.name} to #{new_construction.name} to avoid outdoor-facing attic floor constructions in buildings with no attic space.")
|
2831
|
+
end
|
2832
|
+
|
2699
2833
|
# address any adiabatic surfaces that don't have hard assigned constructions
|
2700
|
-
model.getSurfaces.each do |surface|
|
2834
|
+
model.getSurfaces.sort.each do |surface|
|
2701
2835
|
next if surface.outsideBoundaryCondition != 'Adiabatic'
|
2702
2836
|
next if surface.construction.is_initialized
|
2703
2837
|
surface.setAdjacentSurface(surface)
|
@@ -2721,11 +2855,11 @@ module OsLib_ModelGeneration
|
|
2721
2855
|
if args['add_elevators']
|
2722
2856
|
|
2723
2857
|
# remove elevators as spaceLoads or exteriorLights
|
2724
|
-
model.getSpaceLoads.each do |instance|
|
2858
|
+
model.getSpaceLoads.sort.each do |instance|
|
2725
2859
|
next if !instance.name.to_s.include?('Elevator') # most prototype building types model exterior elevators with name Elevator
|
2726
2860
|
instance.remove
|
2727
2861
|
end
|
2728
|
-
model.getExteriorLightss.each do |ext_light|
|
2862
|
+
model.getExteriorLightss.sort.each do |ext_light|
|
2729
2863
|
next if !ext_light.name.to_s.include?('Fuel equipment') # some prototype building types model exterior elevators by this name
|
2730
2864
|
ext_light.remove
|
2731
2865
|
end
|
@@ -2737,8 +2871,9 @@ module OsLib_ModelGeneration
|
|
2737
2871
|
elevator_def = elevators.electricEquipmentDefinition
|
2738
2872
|
design_level = elevator_def.designLevel.get
|
2739
2873
|
runner.registerInfo("Adding #{elevators.multiplier.round(1)} elevators each with power of #{OpenStudio.toNeatString(design_level, 0, true)} (W), plus lights and fans.")
|
2740
|
-
elevator_def.
|
2874
|
+
elevator_def.setFractionLatent(0.0)
|
2741
2875
|
elevator_def.setFractionRadiant(0.0)
|
2876
|
+
elevator_def.setFractionLost(1.0)
|
2742
2877
|
end
|
2743
2878
|
end
|
2744
2879
|
|
@@ -2746,7 +2881,7 @@ module OsLib_ModelGeneration
|
|
2746
2881
|
if args['add_exterior_lights']
|
2747
2882
|
|
2748
2883
|
if args['remove_objects']
|
2749
|
-
model.getExteriorLightss.each do |ext_light|
|
2884
|
+
model.getExteriorLightss.sort.each do |ext_light|
|
2750
2885
|
next if ext_light.name.to_s.include?('Fuel equipment') # some prototype building types model exterior elevators by this name
|
2751
2886
|
ext_light.remove
|
2752
2887
|
end
|
@@ -2839,13 +2974,13 @@ module OsLib_ModelGeneration
|
|
2839
2974
|
end
|
2840
2975
|
|
2841
2976
|
# add daylight controls, need to perform a sizing run for 2010
|
2842
|
-
if args['template'] == '90.1-2010'
|
2977
|
+
if args['template'] == '90.1-2010' || args['template'] == 'ComStock 90.1-2010'
|
2843
2978
|
if standard.model_run_sizing_run(model, "#{Dir.pwd}/SRvt") == false
|
2844
2979
|
log_messages_to_runner(runner, debug = true)
|
2845
2980
|
return false
|
2846
2981
|
end
|
2847
2982
|
end
|
2848
|
-
|
2983
|
+
standard.model_add_daylighting_controls(model)
|
2849
2984
|
end
|
2850
2985
|
|
2851
2986
|
# add refrigeration
|
@@ -2864,7 +2999,7 @@ module OsLib_ModelGeneration
|
|
2864
2999
|
if args['add_internal_mass']
|
2865
3000
|
|
2866
3001
|
if args['remove_objects']
|
2867
|
-
model.getSpaceLoads.each do |instance|
|
3002
|
+
model.getSpaceLoads.sort.each do |instance|
|
2868
3003
|
next unless instance.to_InternalMass.is_initialized
|
2869
3004
|
instance.remove
|
2870
3005
|
end
|
@@ -2887,7 +3022,7 @@ module OsLib_ModelGeneration
|
|
2887
3022
|
model.getThermostatSetpointDualSetpoints.each(&:remove)
|
2888
3023
|
end
|
2889
3024
|
|
2890
|
-
model.getSpaceTypes.each do |space_type|
|
3025
|
+
model.getSpaceTypes.sort.each do |space_type|
|
2891
3026
|
# create thermostat schedules
|
2892
3027
|
# skip un-recognized space types
|
2893
3028
|
next if standard.space_type_get_standards_data(space_type).empty?
|
@@ -2895,12 +3030,12 @@ module OsLib_ModelGeneration
|
|
2895
3030
|
standard.space_type_apply_internal_load_schedules(space_type, false, false, false, false, false, false, true)
|
2896
3031
|
|
2897
3032
|
# identify thermal thermostat and apply to zones (apply_internal_load_schedules names )
|
2898
|
-
model.getThermostatSetpointDualSetpoints.each do |thermostat|
|
3033
|
+
model.getThermostatSetpointDualSetpoints.sort.each do |thermostat|
|
2899
3034
|
next if thermostat.name.to_s != "#{space_type.name} Thermostat"
|
2900
3035
|
next if !thermostat.coolingSetpointTemperatureSchedule.is_initialized
|
2901
3036
|
next if !thermostat.heatingSetpointTemperatureSchedule.is_initialized
|
2902
3037
|
runner.registerInfo("Assigning #{thermostat.name} to thermal zones with #{space_type.name} assigned.")
|
2903
|
-
space_type.spaces.each do |space|
|
3038
|
+
space_type.spaces.sort.each do |space|
|
2904
3039
|
next if !space.thermalZone.is_initialized
|
2905
3040
|
space.thermalZone.get.setThermostatSetpointDualSetpoint(thermostat)
|
2906
3041
|
end
|
@@ -2972,7 +3107,10 @@ module OsLib_ModelGeneration
|
|
2972
3107
|
end
|
2973
3108
|
|
2974
3109
|
# Add the primary system to the primary zones
|
2975
|
-
standard.model_add_hvac_system(model, sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, system_zones)
|
3110
|
+
unless standard.model_add_hvac_system(model, sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, system_zones)
|
3111
|
+
runner.registerError("HVAC system type '#{sys_type}' not recognized. Check input system type argument against Model.hvac.rb for valid hvac system type names.")
|
3112
|
+
return false
|
3113
|
+
end
|
2976
3114
|
|
2977
3115
|
# Add the secondary system to the secondary zones (if any)
|
2978
3116
|
if !pri_sec_zone_lists['secondary'].empty?
|
@@ -2982,7 +3120,10 @@ module OsLib_ModelGeneration
|
|
2982
3120
|
cooled_only_zones = system_zones.select { |zone| !standard.thermal_zone_heated?(zone) && standard.thermal_zone_cooled?(zone) }
|
2983
3121
|
system_zones = heated_and_cooled_zones + cooled_only_zones
|
2984
3122
|
end
|
2985
|
-
standard.model_add_hvac_system(model, sec_sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, system_zones)
|
3123
|
+
unless standard.model_add_hvac_system(model, sec_sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, system_zones)
|
3124
|
+
runner.registerError("HVAC system type '#{sys_type}' not recognized. Check input system type argument against Model.hvac.rb for valid hvac system type names.")
|
3125
|
+
return false
|
3126
|
+
end
|
2986
3127
|
end
|
2987
3128
|
end
|
2988
3129
|
end
|
@@ -2998,7 +3139,10 @@ module OsLib_ModelGeneration
|
|
2998
3139
|
# Add the user specified HVAC system for each story.
|
2999
3140
|
# Single-zone systems will get one per zone.
|
3000
3141
|
story_groups.each do |zones|
|
3001
|
-
model.add_cbecs_hvac_system(standard, args['system_type'], zones)
|
3142
|
+
unless model.add_cbecs_hvac_system(standard, args['system_type'], zones)
|
3143
|
+
runner.registerError("HVAC system type '#{args['system_type']}' not recognized. Check input system type argument against Model.hvac.rb for valid hvac system type names.")
|
3144
|
+
return false
|
3145
|
+
end
|
3002
3146
|
end
|
3003
3147
|
end
|
3004
3148
|
end
|
@@ -3046,7 +3190,7 @@ module OsLib_ModelGeneration
|
|
3046
3190
|
if args['add_hvac']
|
3047
3191
|
# set additional properties for building
|
3048
3192
|
props = model.getBuilding.additionalProperties
|
3049
|
-
props.setFeature('hvac_system_type',
|
3193
|
+
props.setFeature('hvac_system_type', (args['system_type']).to_s)
|
3050
3194
|
|
3051
3195
|
case args['system_type']
|
3052
3196
|
when 'Ideal Air Loads'
|
@@ -3074,6 +3218,20 @@ module OsLib_ModelGeneration
|
|
3074
3218
|
end
|
3075
3219
|
end
|
3076
3220
|
|
3221
|
+
# add internal mass
|
3222
|
+
if args['add_internal_mass']
|
3223
|
+
|
3224
|
+
if args['remove_objects']
|
3225
|
+
model.getSpaceLoads.sort.each do |instance|
|
3226
|
+
next unless instance.to_InternalMass.is_initialized
|
3227
|
+
instance.remove
|
3228
|
+
end
|
3229
|
+
end
|
3230
|
+
|
3231
|
+
# add internal mass to conditioned spaces; needs to happen after thermostats are applied
|
3232
|
+
standard.model_add_internal_mass(model, primary_bldg_type)
|
3233
|
+
end
|
3234
|
+
|
3077
3235
|
# set unmet hours tolerance
|
3078
3236
|
unmet_hrs_tol_r = args['unmet_hours_tolerance']
|
3079
3237
|
unmet_hrs_tol_k = OpenStudio.convert(unmet_hrs_tol_r, 'R', 'K').get
|
@@ -3102,7 +3260,6 @@ module OsLib_ModelGeneration
|
|
3102
3260
|
# wizard
|
3103
3261
|
# used for varieties of measures that create space type and construction set wizard
|
3104
3262
|
def wizard(model, runner, user_arguments)
|
3105
|
-
|
3106
3263
|
# use the built-in error checking
|
3107
3264
|
if !runner.validateUserArguments(arguments(model), user_arguments)
|
3108
3265
|
return false
|
@@ -3117,8 +3274,8 @@ module OsLib_ModelGeneration
|
|
3117
3274
|
set_building_defaults = runner.getBoolArgumentValue('set_building_defaults', user_arguments)
|
3118
3275
|
|
3119
3276
|
# reporting initial condition of model
|
3120
|
-
starting_spaceTypes = model.getSpaceTypes
|
3121
|
-
starting_constructionSets = model.getDefaultConstructionSets
|
3277
|
+
starting_spaceTypes = model.getSpaceTypes.sort
|
3278
|
+
starting_constructionSets = model.getDefaultConstructionSets.sort
|
3122
3279
|
runner.registerInitialCondition("The building started with #{starting_spaceTypes.size} space types and #{starting_constructionSets.size} construction sets.")
|
3123
3280
|
|
3124
3281
|
# lookup space types for specified building type (false indicates not to use whole building type only)
|
@@ -3146,7 +3303,7 @@ module OsLib_ModelGeneration
|
|
3146
3303
|
lookup_building_type = standard.model_get_lookup_name(building_type)
|
3147
3304
|
|
3148
3305
|
# remap small medium and large office to office
|
3149
|
-
if building_type.include?(
|
3306
|
+
if building_type.include?('Office') then building_type = 'Office' end
|
3150
3307
|
|
3151
3308
|
# get array of new space types
|
3152
3309
|
space_types_new = []
|
@@ -3155,7 +3312,7 @@ module OsLib_ModelGeneration
|
|
3155
3312
|
if create_space_types
|
3156
3313
|
|
3157
3314
|
# array of starting space types
|
3158
|
-
space_types_starting = model.getSpaceTypes
|
3315
|
+
space_types_starting = model.getSpaceTypes.sort
|
3159
3316
|
|
3160
3317
|
# create stub space types
|
3161
3318
|
space_type_hash.each do |space_type_name, hash|
|
@@ -3268,11 +3425,10 @@ module OsLib_ModelGeneration
|
|
3268
3425
|
end
|
3269
3426
|
|
3270
3427
|
# reporting final condition of model
|
3271
|
-
finishing_spaceTypes = model.getSpaceTypes
|
3272
|
-
finishing_constructionSets = model.getDefaultConstructionSets
|
3428
|
+
finishing_spaceTypes = model.getSpaceTypes.sort
|
3429
|
+
finishing_constructionSets = model.getDefaultConstructionSets.sort
|
3273
3430
|
runner.registerFinalCondition("The building finished with #{finishing_spaceTypes.size} space types and #{finishing_constructionSets.size} construction sets.")
|
3274
3431
|
|
3275
3432
|
return true
|
3276
3433
|
end
|
3277
|
-
|
3278
|
-
end
|
3434
|
+
end
|