openstudio-extension 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +36 -1
- data/Gemfile +0 -2
- data/README.md +10 -5
- data/Rakefile +1 -3
- data/bin/console +0 -1
- data/lib/change_log.rb +138 -129
- data/lib/measures/openstudio_extension_test_measure/measure.rb +0 -2
- data/lib/measures/openstudio_extension_test_measure/measure.xml +20 -19
- data/lib/openstudio-extension.rb +0 -2
- data/lib/openstudio/extension.rb +24 -4
- data/lib/openstudio/extension/core/os_lib_geometry.rb +3 -3
- data/lib/openstudio/extension/core/os_lib_hvac.rb +17 -17
- data/lib/openstudio/extension/core/os_lib_model_generation.rb +85 -48
- data/lib/openstudio/extension/core/os_lib_model_simplification.rb +9 -9
- data/lib/openstudio/extension/core/os_lib_outdoorair_and_infiltration.rb +2 -2
- data/lib/openstudio/extension/rake_task.rb +232 -20
- data/lib/openstudio/extension/runner.rb +25 -15
- data/lib/openstudio/extension/runner_config.rb +4 -4
- data/lib/openstudio/extension/version.rb +1 -3
- data/openstudio-extension.gemspec +5 -6
- metadata +30 -18
- data/lib/measures/openstudio_extension_test_measure/tests/openstudio_extension_test_measure_test.rb +0 -76
- data/lib/openstudio/extension/core/os_lib_reporting.rb +0 -4755
data/lib/openstudio-extension.rb
CHANGED
data/lib/openstudio/extension.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
# *******************************************************************************
|
4
2
|
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
5
3
|
# All rights reserved.
|
@@ -93,6 +91,7 @@ module OpenStudio
|
|
93
91
|
|
94
92
|
result << obj
|
95
93
|
end
|
94
|
+
|
96
95
|
return result.uniq
|
97
96
|
end
|
98
97
|
|
@@ -107,7 +106,7 @@ module OpenStudio
|
|
107
106
|
result << dir if dir
|
108
107
|
rescue StandardError
|
109
108
|
end
|
110
|
-
return result.uniq
|
109
|
+
return result.uniq.sort
|
111
110
|
end
|
112
111
|
|
113
112
|
##
|
@@ -121,7 +120,7 @@ module OpenStudio
|
|
121
120
|
result << dir if dir
|
122
121
|
rescue StandardError
|
123
122
|
end
|
124
|
-
return result.uniq
|
123
|
+
return result.uniq.sort
|
125
124
|
end
|
126
125
|
|
127
126
|
##
|
@@ -228,5 +227,26 @@ module OpenStudio
|
|
228
227
|
|
229
228
|
return osw
|
230
229
|
end
|
230
|
+
|
231
|
+
##
|
232
|
+
# Module method used to check whether a measure is present in an OSW file
|
233
|
+
##
|
234
|
+
# @param [Hash] in_osw Initial OSW object as a Hash, keys should be symbolized
|
235
|
+
# @param [String] measure_dir_name Directory name of measure to set argument on
|
236
|
+
# @param [String] step_name Optional argument, if present used to further identify the measure
|
237
|
+
#
|
238
|
+
# @return [Boolean] true or false
|
239
|
+
def self.measure_in_osw(osw, measure_dir_name, step_name = nil)
|
240
|
+
result = false
|
241
|
+
osw[:steps].each do |step|
|
242
|
+
if step[:measure_dir_name] == measure_dir_name
|
243
|
+
if step_name.nil? || step[:name] == step_name
|
244
|
+
result = true
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
return result
|
250
|
+
end
|
231
251
|
end
|
232
252
|
end
|
@@ -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
|
@@ -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
|
@@ -79,6 +79,11 @@ module OsLib_ModelGeneration
|
|
79
79
|
array << 'Hospital'
|
80
80
|
array << 'Outpatient'
|
81
81
|
array << 'SuperMarket'
|
82
|
+
array << 'Laboratory'
|
83
|
+
array << 'LargeDataCenterLowITE'
|
84
|
+
array << 'LargeDataCenterHighITE'
|
85
|
+
array << 'SmallDataCenterLowITE'
|
86
|
+
array << 'SmallDataCenterHighITE'
|
82
87
|
|
83
88
|
return array
|
84
89
|
end
|
@@ -328,7 +333,7 @@ module OsLib_ModelGeneration
|
|
328
333
|
supermarket_a = 45001.0
|
329
334
|
supermarket_p = 866.0
|
330
335
|
supermarket_wwr = 1880.0 / (supermarket_p * 20.0)
|
331
|
-
|
336
|
+
supermarket_aspect_ratio = calc_aspect_ratio(supermarket_a, supermarket_p)
|
332
337
|
|
333
338
|
hash['SmallOffice'] = { aspect_ratio: 1.5, wwr: 0.15, typical_story: 10.0, perim_mult: 1.0 }
|
334
339
|
hash['MediumOffice'] = { aspect_ratio: 1.5, wwr: 0.33, typical_story: 13.0, perim_mult: 1.0 }
|
@@ -351,7 +356,14 @@ module OsLib_ModelGeneration
|
|
351
356
|
hash['MidriseApartment'] = { aspect_ratio: 2.75, wwr: 0.15, typical_story: 10.0, perim_mult: 1.0 }
|
352
357
|
hash['HighriseApartment'] = { aspect_ratio: 2.75, wwr: 0.15, typical_story: 10.0, perim_mult: 1.0 }
|
353
358
|
# SuperMarket inputs come from prototype model
|
354
|
-
hash['SuperMarket'] = { aspect_ratio:
|
359
|
+
hash['SuperMarket'] = { aspect_ratio: supermarket_aspect_ratio.round(1), wwr: supermarket_wwr.round(2), typical_story: 20.0, perim_mult: 1.0 }
|
360
|
+
|
361
|
+
# Add Laboratory and Data Centers
|
362
|
+
hash['Laboratory'] = { aspect_ratio: 1.33, wwr: 0.12, typical_story: 10.0, perim_mult: 1.0 }
|
363
|
+
hash['LargeDataCenterLowITE'] = { aspect_ratio: 1.67, wwr: 0.0, typical_story: 14.0, perim_mult: 1.0 }
|
364
|
+
hash['LargeDataCenterHighITE'] = { aspect_ratio: 1.67, wwr: 0.0, typical_story: 14.0, perim_mult: 1.0 }
|
365
|
+
hash['SmallDataCenterLowITE'] = { aspect_ratio: 1.5, wwr: 0.0, typical_story: 14.0, perim_mult: 1.0 }
|
366
|
+
hash['SmallDataCenterHighITE'] = { aspect_ratio: 1.5, wwr: 0.0, typical_story: 14.0, perim_mult: 1.0 }
|
355
367
|
|
356
368
|
# DEER Prototypes
|
357
369
|
hash['Asm'] = { aspect_ratio: 1.0, wwr: 0.19, typical_story: 15.0 }
|
@@ -664,6 +676,19 @@ module OsLib_ModelGeneration
|
|
664
676
|
hash['Meeting'] = { ratio: 0.99, space_type_gen: true, default: true }
|
665
677
|
hash['Restroom'] = { ratio: 0.99, space_type_gen: true, default: true }
|
666
678
|
hash['Vestibule'] = { ratio: 0.99, space_type_gen: true, default: true }
|
679
|
+
elsif building_type == 'Laboratory'
|
680
|
+
hash['Office'] = { ratio: 0.50, space_type_gen: true, default: true }
|
681
|
+
hash['Open lab'] = { ratio: 0.35, space_type_gen: true, default: true }
|
682
|
+
hash['Equipment corridor'] = { ratio: 0.05, space_type_gen: true, default: true }
|
683
|
+
hash['Lab with fume hood'] = { ratio: 0.10, space_type_gen: true, default: true }
|
684
|
+
elsif building_type == 'LargeDataCenterHighITE'
|
685
|
+
hash['StandaloneDataCenter'] = { ratio: 1.0, space_type_gen: true, default: true }
|
686
|
+
elsif building_type == 'LargeDataCenterLowITE'
|
687
|
+
hash['StandaloneDataCenter'] = { ratio: 1.0, space_type_gen: true, default: true }
|
688
|
+
elsif building_type == 'SmallDataCenterHighITE'
|
689
|
+
hash['ComputerRoom'] = { ratio: 1.0, space_type_gen: true, default: true }
|
690
|
+
elsif building_type == 'SmallDataCenterLowITE'
|
691
|
+
hash['ComputerRoom'] = { ratio: 1.0, space_type_gen: true, default: true }
|
667
692
|
# DEER Prototypes
|
668
693
|
elsif building_type == 'Asm'
|
669
694
|
hash['Auditorium'] = { ratio: 0.7658, space_type_gen: true, default: true }
|
@@ -884,6 +909,7 @@ module OsLib_ModelGeneration
|
|
884
909
|
stories_flat = []
|
885
910
|
stories_flat_counter = 0
|
886
911
|
bar_hash[:stories].each_with_index do |(k, v), i|
|
912
|
+
#runner.registerInfo("STORY: k: #{k}, v: #{v}, index: #{i}")
|
887
913
|
# k is invalid in some cases, old story object that has been removed, should be from low to high including basement
|
888
914
|
# skip if source story insn't included in building area
|
889
915
|
if v[:story_included_in_building_area].nil? || (v[:story_included_in_building_area] == true)
|
@@ -1024,7 +1050,7 @@ module OsLib_ModelGeneration
|
|
1024
1050
|
# only intersect if make_mid_story_surfaces_adiabatic false
|
1025
1051
|
if diagnostic_intersect
|
1026
1052
|
|
1027
|
-
model.getPlanarSurfaces.each do |surface|
|
1053
|
+
model.getPlanarSurfaces.sort.each do |surface|
|
1028
1054
|
array = []
|
1029
1055
|
vertices = surface.vertices
|
1030
1056
|
fixed = false
|
@@ -1050,7 +1076,7 @@ module OsLib_ModelGeneration
|
|
1050
1076
|
end
|
1051
1077
|
|
1052
1078
|
# remove collinear points in a surface
|
1053
|
-
model.getPlanarSurfaces.each do |surface|
|
1079
|
+
model.getPlanarSurfaces.sort.each do |surface|
|
1054
1080
|
new_vertices = OpenStudio.removeCollinear(surface.vertices)
|
1055
1081
|
starting_count = surface.vertices.size
|
1056
1082
|
final_count = new_vertices.size
|
@@ -1061,7 +1087,7 @@ module OsLib_ModelGeneration
|
|
1061
1087
|
end
|
1062
1088
|
|
1063
1089
|
# remove duplicate surfaces in a space (should be done after remove duplicate and collinear points)
|
1064
|
-
model.getSpaces.each do |space|
|
1090
|
+
model.getSpaces.sort.each do |space|
|
1065
1091
|
|
1066
1092
|
# secondary array to compare against
|
1067
1093
|
surfaces_b = space.surfaces.sort
|
@@ -1105,7 +1131,7 @@ module OsLib_ModelGeneration
|
|
1105
1131
|
end
|
1106
1132
|
runner.registerInfo('Intersecting and matching surfaces in model, this will create additional geometry.')
|
1107
1133
|
else #elsif bar_hash[:double_loaded_corridor] # only intersect spaces in each story, not between wtory
|
1108
|
-
model.getBuilding.buildingStories.each do |story|
|
1134
|
+
model.getBuilding.buildingStories.sort.each do |story|
|
1109
1135
|
# intersect and surface match two pair by pair
|
1110
1136
|
spaces_b = story.spaces.sort
|
1111
1137
|
# looping through vector of each space
|
@@ -1136,7 +1162,7 @@ module OsLib_ModelGeneration
|
|
1136
1162
|
runner.registerInfo('Intersecting and matching surfaces in model, this will create additional geometry.')
|
1137
1163
|
end
|
1138
1164
|
else #elsif bar_hash[:double_loaded_corridor] # only intersect spaces in each story, not between wtory
|
1139
|
-
model.getBuilding.buildingStories.each do |story|
|
1165
|
+
model.getBuilding.buildingStories.sort.each do |story|
|
1140
1166
|
story_spaces = OpenStudio::Model::SpaceVector.new
|
1141
1167
|
story.spaces.sort.each do |space|
|
1142
1168
|
story_spaces << space
|
@@ -1152,11 +1178,11 @@ module OsLib_ModelGeneration
|
|
1152
1178
|
# set boundary conditions if not already set when geometry was created
|
1153
1179
|
# todo - update this to use space original z value vs. story name
|
1154
1180
|
if bar_hash[:num_stories_below_grade] > 0
|
1155
|
-
model.getBuildingStorys.each do |story|
|
1181
|
+
model.getBuildingStorys.sort.each do |story|
|
1156
1182
|
next if !story.name.to_s.include?('Story B')
|
1157
|
-
story.spaces.each do |space|
|
1183
|
+
story.spaces.sort.each do |space|
|
1158
1184
|
next if not new_spaces.include?(space)
|
1159
|
-
space.surfaces.each do |surface|
|
1185
|
+
space.surfaces.sort.each do |surface|
|
1160
1186
|
next if surface.surfaceType != 'Wall'
|
1161
1187
|
next if surface.outsideBoundaryCondition != 'Outdoors'
|
1162
1188
|
surface.setOutsideBoundaryCondition('Ground')
|
@@ -1621,10 +1647,7 @@ module OsLib_ModelGeneration
|
|
1621
1647
|
end
|
1622
1648
|
end
|
1623
1649
|
end
|
1624
|
-
|
1625
1650
|
end
|
1626
|
-
|
1627
|
-
|
1628
1651
|
end
|
1629
1652
|
|
1630
1653
|
# bar_from_building_type_ratios
|
@@ -2354,7 +2377,7 @@ module OsLib_ModelGeneration
|
|
2354
2377
|
if args['party_wall_fraction'] > 0
|
2355
2378
|
actual_ext_wall_area = model.getBuilding.exteriorWallArea
|
2356
2379
|
actual_party_wall_area = 0.0
|
2357
|
-
model.getSurfaces.each do |surface|
|
2380
|
+
model.getSurfaces.sort.each do |surface|
|
2358
2381
|
next if surface.outsideBoundaryCondition != 'Adiabatic'
|
2359
2382
|
next if surface.surfaceType != 'Wall'
|
2360
2383
|
actual_party_wall_area += surface.grossArea * surface.space.get.multiplier
|
@@ -2365,7 +2388,7 @@ module OsLib_ModelGeneration
|
|
2365
2388
|
end
|
2366
2389
|
|
2367
2390
|
# check ns/ew aspect ratio (harder to check when party walls are added)
|
2368
|
-
wall_and_window_by_orientation = OsLib_Geometry.getExteriorWindowAndWllAreaByOrientation(model,model.getSpaces)
|
2391
|
+
wall_and_window_by_orientation = OsLib_Geometry.getExteriorWindowAndWllAreaByOrientation(model,model.getSpaces.sort)
|
2369
2392
|
wall_ns = (wall_and_window_by_orientation['northWall'] + wall_and_window_by_orientation['southWall'])
|
2370
2393
|
wall_ew = wall_and_window_by_orientation['eastWall'] + wall_and_window_by_orientation['westWall']
|
2371
2394
|
wall_ns_ip = OpenStudio.convert(wall_ns,'m^2','ft^2').get
|
@@ -2560,6 +2583,19 @@ module OsLib_ModelGeneration
|
|
2560
2583
|
# Make the standard applier
|
2561
2584
|
standard = Standard.build((args['template']).to_s)
|
2562
2585
|
|
2586
|
+
# validate climate zone
|
2587
|
+
if !args.has_key?('climate_zone') || args['climate_zone'] == 'Lookup From Model'
|
2588
|
+
climate_zone = standard.model_get_building_climate_zone_and_building_type(model)['climate_zone']
|
2589
|
+
runner.registerInfo("Using climate zone #{climate_zone} from model")
|
2590
|
+
else
|
2591
|
+
climate_zone = args['climate_zone']
|
2592
|
+
runner.registerInfo("Using climate zone #{climate_zone} from user arguments")
|
2593
|
+
end
|
2594
|
+
if climate_zone == ''
|
2595
|
+
runner.registerError("Could not determine climate zone from measure arguments or model.")
|
2596
|
+
return false
|
2597
|
+
end
|
2598
|
+
|
2563
2599
|
# make sure daylight savings is turned on up prior to any sizing runs being done.
|
2564
2600
|
if args['enable_dst']
|
2565
2601
|
start_date = '2nd Sunday in March'
|
@@ -2575,7 +2611,7 @@ module OsLib_ModelGeneration
|
|
2575
2611
|
|
2576
2612
|
# remove internal loads
|
2577
2613
|
if args['remove_objects']
|
2578
|
-
model.getSpaceLoads.each do |instance|
|
2614
|
+
model.getSpaceLoads.sort.each do |instance|
|
2579
2615
|
next if instance.name.to_s.include?('Elevator') # most prototype building types model exterior elevators with name Elevator
|
2580
2616
|
next if instance.to_InternalMass.is_initialized
|
2581
2617
|
next if instance.to_WaterUseEquipment.is_initialized
|
@@ -2585,7 +2621,7 @@ module OsLib_ModelGeneration
|
|
2585
2621
|
model.getDefaultScheduleSets.each(&:remove)
|
2586
2622
|
end
|
2587
2623
|
|
2588
|
-
model.getSpaceTypes.each do |space_type|
|
2624
|
+
model.getSpaceTypes.sort.each do |space_type|
|
2589
2625
|
# Don't add infiltration here; will be added later in the script
|
2590
2626
|
test = standard.space_type_apply_internal_loads(space_type, true, true, true, true, true, false)
|
2591
2627
|
if test == false
|
@@ -2604,7 +2640,7 @@ module OsLib_ModelGeneration
|
|
2604
2640
|
|
2605
2641
|
# warn if spaces in model without space type
|
2606
2642
|
spaces_without_space_types = []
|
2607
|
-
model.getSpaces.each do |space|
|
2643
|
+
model.getSpaces.sort.each do |space|
|
2608
2644
|
next if space.spaceType.is_initialized
|
2609
2645
|
spaces_without_space_types << space
|
2610
2646
|
end
|
@@ -2615,7 +2651,7 @@ module OsLib_ModelGeneration
|
|
2615
2651
|
|
2616
2652
|
# identify primary building type (used for construction, and ideally HVAC as well)
|
2617
2653
|
building_types = {}
|
2618
|
-
model.getSpaceTypes.each do |space_type|
|
2654
|
+
model.getSpaceTypes.sort.each do |space_type|
|
2619
2655
|
# populate hash of building types
|
2620
2656
|
if space_type.standardsBuildingType.is_initialized
|
2621
2657
|
bldg_type = space_type.standardsBuildingType.get
|
@@ -2646,13 +2682,6 @@ module OsLib_ModelGeneration
|
|
2646
2682
|
else
|
2647
2683
|
is_residential = 'No'
|
2648
2684
|
end
|
2649
|
-
if !args.has_key?('climate_zone') || args['climate_zone'] == 'Lookup From Model'
|
2650
|
-
climate_zone = standard.model_get_building_climate_zone_and_building_type(model)['climate_zone']
|
2651
|
-
runner.registerInfo("Using climate zone #{climate_zone} from model")
|
2652
|
-
else
|
2653
|
-
climate_zone = args['climate_zone']
|
2654
|
-
runner.registerInfo("Using climate zone #{climate_zone} from user arguments")
|
2655
|
-
end
|
2656
2685
|
bldg_def_const_set = standard.model_add_construction_set(model, climate_zone, lookup_building_type, nil, is_residential)
|
2657
2686
|
if bldg_def_const_set.is_initialized
|
2658
2687
|
bldg_def_const_set = bldg_def_const_set.get
|
@@ -2666,7 +2695,7 @@ module OsLib_ModelGeneration
|
|
2666
2695
|
end
|
2667
2696
|
|
2668
2697
|
# address any adiabatic surfaces that don't have hard assigned constructions
|
2669
|
-
model.getSurfaces.each do |surface|
|
2698
|
+
model.getSurfaces.sort.each do |surface|
|
2670
2699
|
next if surface.outsideBoundaryCondition != 'Adiabatic'
|
2671
2700
|
next if surface.construction.is_initialized
|
2672
2701
|
surface.setAdjacentSurface(surface)
|
@@ -2690,11 +2719,11 @@ module OsLib_ModelGeneration
|
|
2690
2719
|
if args['add_elevators']
|
2691
2720
|
|
2692
2721
|
# remove elevators as spaceLoads or exteriorLights
|
2693
|
-
model.getSpaceLoads.each do |instance|
|
2722
|
+
model.getSpaceLoads.sort.each do |instance|
|
2694
2723
|
next if !instance.name.to_s.include?('Elevator') # most prototype building types model exterior elevators with name Elevator
|
2695
2724
|
instance.remove
|
2696
2725
|
end
|
2697
|
-
model.getExteriorLightss.each do |ext_light|
|
2726
|
+
model.getExteriorLightss.sort.each do |ext_light|
|
2698
2727
|
next if !ext_light.name.to_s.include?('Fuel equipment') # some prototype building types model exterior elevators by this name
|
2699
2728
|
ext_light.remove
|
2700
2729
|
end
|
@@ -2715,7 +2744,7 @@ module OsLib_ModelGeneration
|
|
2715
2744
|
if args['add_exterior_lights']
|
2716
2745
|
|
2717
2746
|
if args['remove_objects']
|
2718
|
-
model.getExteriorLightss.each do |ext_light|
|
2747
|
+
model.getExteriorLightss.sort.each do |ext_light|
|
2719
2748
|
next if ext_light.name.to_s.include?('Fuel equipment') # some prototype building types model exterior elevators by this name
|
2720
2749
|
ext_light.remove
|
2721
2750
|
end
|
@@ -2797,16 +2826,25 @@ module OsLib_ModelGeneration
|
|
2797
2826
|
end
|
2798
2827
|
end
|
2799
2828
|
|
2800
|
-
#
|
2829
|
+
# add_daylighting_controls (since outdated measure don't have this default to true if arg not found)
|
2830
|
+
if !args.has_key?('add_daylighting_controls')
|
2831
|
+
args['add_daylighting_controls'] = true
|
2832
|
+
end
|
2833
|
+
if args['add_daylighting_controls']
|
2834
|
+
# remove add_daylighting_controls objects
|
2835
|
+
if args['remove_objects']
|
2836
|
+
model.getDaylightingControls.each(&:remove)
|
2837
|
+
end
|
2801
2838
|
|
2802
|
-
|
2803
|
-
|
2804
|
-
|
2805
|
-
|
2806
|
-
|
2839
|
+
# add daylight controls, need to perform a sizing run for 2010
|
2840
|
+
if args['template'] == '90.1-2010'
|
2841
|
+
if standard.model_run_sizing_run(model, "#{Dir.pwd}/SRvt") == false
|
2842
|
+
log_messages_to_runner(runner, debug = true)
|
2843
|
+
return false
|
2844
|
+
end
|
2807
2845
|
end
|
2808
|
-
end
|
2809
2846
|
standard.model_add_daylighting_controls(model)
|
2847
|
+
end
|
2810
2848
|
|
2811
2849
|
# add refrigeration
|
2812
2850
|
if args['add_refrigeration']
|
@@ -2824,7 +2862,7 @@ module OsLib_ModelGeneration
|
|
2824
2862
|
if args['add_internal_mass']
|
2825
2863
|
|
2826
2864
|
if args['remove_objects']
|
2827
|
-
model.getSpaceLoads.each do |instance|
|
2865
|
+
model.getSpaceLoads.sort.each do |instance|
|
2828
2866
|
next unless instance.to_InternalMass.is_initialized
|
2829
2867
|
instance.remove
|
2830
2868
|
end
|
@@ -2847,7 +2885,7 @@ module OsLib_ModelGeneration
|
|
2847
2885
|
model.getThermostatSetpointDualSetpoints.each(&:remove)
|
2848
2886
|
end
|
2849
2887
|
|
2850
|
-
model.getSpaceTypes.each do |space_type|
|
2888
|
+
model.getSpaceTypes.sort.each do |space_type|
|
2851
2889
|
# create thermostat schedules
|
2852
2890
|
# skip un-recognized space types
|
2853
2891
|
next if standard.space_type_get_standards_data(space_type).empty?
|
@@ -2855,12 +2893,12 @@ module OsLib_ModelGeneration
|
|
2855
2893
|
standard.space_type_apply_internal_load_schedules(space_type, false, false, false, false, false, false, true)
|
2856
2894
|
|
2857
2895
|
# identify thermal thermostat and apply to zones (apply_internal_load_schedules names )
|
2858
|
-
model.getThermostatSetpointDualSetpoints.each do |thermostat|
|
2896
|
+
model.getThermostatSetpointDualSetpoints.sort.each do |thermostat|
|
2859
2897
|
next if thermostat.name.to_s != "#{space_type.name} Thermostat"
|
2860
2898
|
next if !thermostat.coolingSetpointTemperatureSchedule.is_initialized
|
2861
2899
|
next if !thermostat.heatingSetpointTemperatureSchedule.is_initialized
|
2862
2900
|
runner.registerInfo("Assigning #{thermostat.name} to thermal zones with #{space_type.name} assigned.")
|
2863
|
-
space_type.spaces.each do |space|
|
2901
|
+
space_type.spaces.sort.each do |space|
|
2864
2902
|
next if !space.thermalZone.is_initialized
|
2865
2903
|
space.thermalZone.get.setThermostatSetpointDualSetpoint(thermostat)
|
2866
2904
|
end
|
@@ -3038,7 +3076,7 @@ module OsLib_ModelGeneration
|
|
3038
3076
|
if args['add_internal_mass']
|
3039
3077
|
|
3040
3078
|
if args['remove_objects']
|
3041
|
-
model.getSpaceLoads.each do |instance|
|
3079
|
+
model.getSpaceLoads.sort.each do |instance|
|
3042
3080
|
next unless instance.to_InternalMass.is_initialized
|
3043
3081
|
instance.remove
|
3044
3082
|
end
|
@@ -3091,8 +3129,8 @@ module OsLib_ModelGeneration
|
|
3091
3129
|
set_building_defaults = runner.getBoolArgumentValue('set_building_defaults', user_arguments)
|
3092
3130
|
|
3093
3131
|
# reporting initial condition of model
|
3094
|
-
starting_spaceTypes = model.getSpaceTypes
|
3095
|
-
starting_constructionSets = model.getDefaultConstructionSets
|
3132
|
+
starting_spaceTypes = model.getSpaceTypes.sort
|
3133
|
+
starting_constructionSets = model.getDefaultConstructionSets.sort
|
3096
3134
|
runner.registerInitialCondition("The building started with #{starting_spaceTypes.size} space types and #{starting_constructionSets.size} construction sets.")
|
3097
3135
|
|
3098
3136
|
# lookup space types for specified building type (false indicates not to use whole building type only)
|
@@ -3129,7 +3167,7 @@ module OsLib_ModelGeneration
|
|
3129
3167
|
if create_space_types
|
3130
3168
|
|
3131
3169
|
# array of starting space types
|
3132
|
-
space_types_starting = model.getSpaceTypes
|
3170
|
+
space_types_starting = model.getSpaceTypes.sort
|
3133
3171
|
|
3134
3172
|
# create stub space types
|
3135
3173
|
space_type_hash.each do |space_type_name, hash|
|
@@ -3242,11 +3280,10 @@ module OsLib_ModelGeneration
|
|
3242
3280
|
end
|
3243
3281
|
|
3244
3282
|
# reporting final condition of model
|
3245
|
-
finishing_spaceTypes = model.getSpaceTypes
|
3246
|
-
finishing_constructionSets = model.getDefaultConstructionSets
|
3283
|
+
finishing_spaceTypes = model.getSpaceTypes.sort
|
3284
|
+
finishing_constructionSets = model.getDefaultConstructionSets.sort
|
3247
3285
|
runner.registerFinalCondition("The building finished with #{finishing_spaceTypes.size} space types and #{finishing_constructionSets.size} construction sets.")
|
3248
3286
|
|
3249
3287
|
return true
|
3250
3288
|
end
|
3251
|
-
|
3252
3289
|
end
|