openstudio-extension 0.2.3 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fbd3f65a4f467a9beee5439e58dbeddc445da4dfeb606d23547865a57d461d06
4
- data.tar.gz: 4f7c9792f4f9bc5419caff2aa57a4bd8dcdb4252ad8d77b8e6b28b50eedeeb99
3
+ metadata.gz: 14382dd7b9d2ea113c334dc5d478fc543e03c8cfd187e5d1ed702414e1e878cb
4
+ data.tar.gz: 2943baf83593784439ef8e1e4c656bacc1042666eede5f4e2836351c160a5009
5
5
  SHA512:
6
- metadata.gz: 61f585def76ef5d6998892f74fe8338744df5c90cdb26b906a04dbc5c53e7cfa1524c23e6636b3fd08acfcb8a2a0b9378473c24253265a320585b576ac9c4692
7
- data.tar.gz: 6842e2d7eb60fd4d047d26e8b2e2e286819d3ed63a904f436bb1b8a28c2f469efcae2876eebf3372aad12716859d77350129f354a0336f8b4aedd31415cc953f
6
+ metadata.gz: 1b0ab92740d7232a7febfbea649b5d39a45f7b5a23b4f172ab0122c06aff38f6b6d692b3d0e7e44f85ca2f346b7afbc39de44c8b439431345a32b74b6cb3dadd
7
+ data.tar.gz: e81c0739957432be1ec8da8ea503a2daad939b36dc94faf21087c17c6871b4c633b02a788e84f7fff2faabbbda11c41b15220b62c2ad30b3d86e34601dea60c8
data/.gitignore CHANGED
@@ -1,6 +1,7 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
3
  /.ruby-version
4
+ /.python-version
4
5
  /Gemfile.lock
5
6
  /gems
6
7
  /_yardoc/
@@ -1,5 +1,38 @@
1
1
  # OpenStudio Extension Gem
2
2
 
3
+ ## Version 0.3.2
4
+
5
+ * Update Extension Gem Template
6
+ * Add gemfile path instead of just dirname to the initialization
7
+ * Update to latest workflow gem to support URBANopt Workflow
8
+
9
+ ## Version 0.3.1
10
+
11
+ * This change first zeroes-out latent (for good measure) and radiant fractions before setting lost fraction to 1.0 to avoid this error.
12
+
13
+ ## Version 0.3.0
14
+
15
+ * remove the os_lib_reporting.rb helpers. This file is only used for OS reporting measure and should not be shared with other users.
16
+ * Upgrade dependency to openstudio-workflow gem to `~> 2.1.0`
17
+ * This version works only with EnergyPlus 9.4 since it depends on OpenStudio workflow `~> 2.1.0`
18
+
19
+ ## Version 0.2.5
20
+
21
+ * Support runner options for bundle_install_path and gemfile_path
22
+ * Laboratory and Data Center Support
23
+
24
+ - Fixed [#71]( https://github.com/NREL/openstudio-extension-gem/pull/71 ), another fix for bcl rake tasks
25
+ - Fixed [#72]( https://github.com/NREL/openstudio-extension-gem/pull/72 ), Add laboratory and data centers to os_lib_model_generation
26
+ - Fixed [#74]( https://github.com/NREL/openstudio-extension-gem/pull/74 ), adding bundle path and gemfile path options
27
+
28
+ ## Version 0.2.4
29
+
30
+ * Fixed upload of measures to BCL using rake tasks.
31
+ * Support economizer modeling when create_typical measure is split into two parts
32
+
33
+ Closed Issues: 1
34
+ - Fixed [#64]( https://github.com/NREL/openstudio-extension-gem/issues/64 ), README updates
35
+
3
36
  ## Version 0.2.3
4
37
 
5
38
  * Use new version of rubocop style from S3
data/README.md CHANGED
@@ -146,14 +146,17 @@ Common Rake Tasks that are available to derivative extension gems include:
146
146
 
147
147
  | Rake Task | Description |
148
148
  | --------- | ----------- |
149
+ | openstudio:bcl:test_login | Test BCL login |
150
+ | openstudio:bcl:search_measures | Search BCL |
151
+ | openstudio:bcl:stage[reset] | Copy the measures/components to a staging location |
152
+ | openstudio:bcl:push | Upload measures from the staging location |
153
+ | openstudio:change_log[start_date,end_date,apikey] | Print the change log from GitHub. Specify dates in yyyy-mm-dd format |
149
154
  | openstudio:list_measures | List all measures in the calling gem |
150
155
  | openstudio:measures:add_license | Add License File to measures in the calling gem |
151
156
  | openstudio:measures:add_readme | Add README.md.erb file if it and the README markdown file do not already exist for a measure |
152
157
  | openstudio:measures:copy_resources | Copy the resources files to individual measures in the calling gem |
153
158
  | openstudio:measures:update_copyright | Update copyright on measure files in the calling gem |
154
159
  | openstudio`:runner:`init | Create a runner.conf file running simulations |
155
- | openstudio:stage_bcl | Copy the measures to a location that can be uploaded to BCL |
156
- | openstudio:push_bcl | Upload measures from the specified location to the BCL |
157
160
  | openstudio:test_with_docker | Use openstudio docker image to run tests |
158
161
  | openstudio:test_with_openstudio | Use openstudio system ruby to run tests |
159
162
  | openstudio:update_measures | Run the CLI task to check for measure updates and update the measure xml files |
@@ -176,8 +179,12 @@ The following table contains all current extension gems.
176
179
  | OpenStudio Common Measures Gem | openstudio-common-measures | https://github.com/NREL/openstudio-common-measures-gem |
177
180
  | OpenStudio Model Articulation Gem | openstudio-model-articulation | https://github.com/NREL/openstudio-model-articulation-gem |
178
181
  | OpenStudio AEDG Gem | openstudio-aedg | https://github.com/NREL/openstudio-aedg-gem |
182
+ | OpenStudio Calibration Gem | openstudio-calibration | https://github.com/NREL/openstudio-calibration-gem |
183
+ | OpenStudio EE Gem | openstudio-ee | https://github.com/NREL/openstudio-ee-gem |
179
184
  | OpenStudio District Systems Gem | openstudio-district-systems | https://github.com/NREL/openstudio-district-systems-gem |
180
- | UrbanOpt GeoJSON Gem | urbanopt-geojson | https://github.com/urbanopt/urbanopt-geojson-gem |
185
+ | URBANopt Core Gem | urbanopt-core | https://github.com/urbanopt/urbanopt-core-gem |
186
+ | URBANopt GeoJSON Gem | urbanopt-geojson | https://github.com/urbanopt/urbanopt-geojson-gem |
187
+ | URBANopt Scenario Gem | urbanopt-scenario | https://github.com/urbanopt/urbanopt-scenario-gem |
181
188
  | BuildingSync Gem | buildingsync | https://github.com/BuildingSync/BuildingSync-gem |
182
189
 
183
190
  ### Initializing a new Extension Gem
@@ -236,8 +243,6 @@ Or install it yourself as:
236
243
 
237
244
  # TODO
238
245
 
239
- - [ ] Rake task ```stage_bcl``` _DLM: BCL gem should be a development dependency only until we can reduce its dependencies and remove native dependencies? should probably put it into a special group so we can bundle without it in openstudio-gems._
240
- - [ ] Rake task ```push_bcl``` _DLM: how do we want to test this?
241
246
  - [ ] Capture useful output from Travis (measure dashboard results, log files, zip of build products, etc) and put it somewhere (s3? naming convention?)
242
247
  - [ ] ```Extension::files_dir``` _DLM: I think this can have a default implementation, right?_
243
248
  - [ ] ```Extension::minimum_openstudio_version``` _DLM: should we rename? should people overwrite this in their class?_
@@ -22,11 +22,13 @@ Gem::Specification.new do |spec|
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ['lib']
24
24
 
25
- spec.add_development_dependency 'bundler', '~> 1.14'
26
- spec.add_development_dependency 'rake', '12.3.1'
27
- spec.add_development_dependency 'rspec', '3.7.0'
25
+ spec.required_ruby_version = '~> 2.5.0'
26
+
27
+ spec.add_development_dependency 'bundler', '~> 2.1'
28
+ spec.add_development_dependency 'rake', '~> 13.0'
29
+ spec.add_development_dependency 'rspec', '~> 3.9'
28
30
  spec.add_development_dependency 'rubocop', '~> 0.54.0'
29
31
 
30
- spec.add_dependency 'openstudio-extension', '~> 0.1.0'
31
- spec.add_dependency 'openstudio-standards', '~> 0.2.7'
32
+ spec.add_dependency 'openstudio-extension', '~> 0.3.1'
33
+ spec.add_dependency 'openstudio-standards', '~> 0.2.12'
32
34
  end
@@ -16,7 +16,4 @@ elsif allow_local
16
16
  gem 'openstudio-extension', github: 'NREL/OpenStudio-extension-gem', branch: 'develop'
17
17
  end
18
18
 
19
- gem 'openstudio_measure_tester', '= 0.1.7' # This includes the dependencies for running unit tests, coverage, and rubocop
20
-
21
- # simplecov has an unnecessary dependency on native json gem, use fork that does not require this
22
- gem 'simplecov', github: 'NREL/simplecov'
19
+ gem 'openstudio_measure_tester', '~> 0.2.3' # This includes the dependencies for running unit tests, coverage, and rubocop
@@ -91,6 +91,7 @@ module OpenStudio
91
91
 
92
92
  result << obj
93
93
  end
94
+
94
95
  return result.uniq
95
96
  end
96
97
 
@@ -105,7 +106,7 @@ module OpenStudio
105
106
  result << dir if dir
106
107
  rescue StandardError
107
108
  end
108
- return result.uniq
109
+ return result.uniq.sort
109
110
  end
110
111
 
111
112
  ##
@@ -119,7 +120,7 @@ module OpenStudio
119
120
  result << dir if dir
120
121
  rescue StandardError
121
122
  end
122
- return result.uniq
123
+ return result.uniq.sort
123
124
  end
124
125
 
125
126
  ##
@@ -226,5 +227,26 @@ module OpenStudio
226
227
 
227
228
  return osw
228
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
229
251
  end
230
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
- supermarket_aspet_ratio = calc_aspect_ratio(supermarket_a, supermarket_p)
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: supermarket_aspet_ratio.round(1), wwr: supermarket_wwr.round(2), typical_story: 20.0, perim_mult: 1.0 }
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
@@ -2706,8 +2735,9 @@ module OsLib_ModelGeneration
2706
2735
  elevator_def = elevators.electricEquipmentDefinition
2707
2736
  design_level = elevator_def.designLevel.get
2708
2737
  runner.registerInfo("Adding #{elevators.multiplier.round(1)} elevators each with power of #{OpenStudio.toNeatString(design_level, 0, true)} (W), plus lights and fans.")
2709
- elevator_def.setFractionLost(1.0)
2738
+ elevator_def.setFractionLatent(0.0)
2710
2739
  elevator_def.setFractionRadiant(0.0)
2740
+ elevator_def.setFractionLost(1.0)
2711
2741
  end
2712
2742
  end
2713
2743
 
@@ -2715,7 +2745,7 @@ module OsLib_ModelGeneration
2715
2745
  if args['add_exterior_lights']
2716
2746
 
2717
2747
  if args['remove_objects']
2718
- model.getExteriorLightss.each do |ext_light|
2748
+ model.getExteriorLightss.sort.each do |ext_light|
2719
2749
  next if ext_light.name.to_s.include?('Fuel equipment') # some prototype building types model exterior elevators by this name
2720
2750
  ext_light.remove
2721
2751
  end
@@ -2797,16 +2827,25 @@ module OsLib_ModelGeneration
2797
2827
  end
2798
2828
  end
2799
2829
 
2800
- # TODO: - when add methods below add bool to enable/disable them with default value to true
2830
+ # add_daylighting_controls (since outdated measure don't have this default to true if arg not found)
2831
+ if !args.has_key?('add_daylighting_controls')
2832
+ args['add_daylighting_controls'] = true
2833
+ end
2834
+ if args['add_daylighting_controls']
2835
+ # remove add_daylighting_controls objects
2836
+ if args['remove_objects']
2837
+ model.getDaylightingControls.each(&:remove)
2838
+ end
2801
2839
 
2802
- # add daylight controls, need to perform a sizing run for 2010
2803
- if args['template'] == '90.1-2010'
2804
- if standard.model_run_sizing_run(model, "#{Dir.pwd}/SRvt") == false
2805
- log_messages_to_runner(runner, debug = true)
2806
- return false
2840
+ # add daylight controls, need to perform a sizing run for 2010
2841
+ if args['template'] == '90.1-2010'
2842
+ if standard.model_run_sizing_run(model, "#{Dir.pwd}/SRvt") == false
2843
+ log_messages_to_runner(runner, debug = true)
2844
+ return false
2845
+ end
2807
2846
  end
2808
- end
2809
2847
  standard.model_add_daylighting_controls(model)
2848
+ end
2810
2849
 
2811
2850
  # add refrigeration
2812
2851
  if args['add_refrigeration']
@@ -2824,7 +2863,7 @@ module OsLib_ModelGeneration
2824
2863
  if args['add_internal_mass']
2825
2864
 
2826
2865
  if args['remove_objects']
2827
- model.getSpaceLoads.each do |instance|
2866
+ model.getSpaceLoads.sort.each do |instance|
2828
2867
  next unless instance.to_InternalMass.is_initialized
2829
2868
  instance.remove
2830
2869
  end
@@ -2847,7 +2886,7 @@ module OsLib_ModelGeneration
2847
2886
  model.getThermostatSetpointDualSetpoints.each(&:remove)
2848
2887
  end
2849
2888
 
2850
- model.getSpaceTypes.each do |space_type|
2889
+ model.getSpaceTypes.sort.each do |space_type|
2851
2890
  # create thermostat schedules
2852
2891
  # skip un-recognized space types
2853
2892
  next if standard.space_type_get_standards_data(space_type).empty?
@@ -2855,12 +2894,12 @@ module OsLib_ModelGeneration
2855
2894
  standard.space_type_apply_internal_load_schedules(space_type, false, false, false, false, false, false, true)
2856
2895
 
2857
2896
  # identify thermal thermostat and apply to zones (apply_internal_load_schedules names )
2858
- model.getThermostatSetpointDualSetpoints.each do |thermostat|
2897
+ model.getThermostatSetpointDualSetpoints.sort.each do |thermostat|
2859
2898
  next if thermostat.name.to_s != "#{space_type.name} Thermostat"
2860
2899
  next if !thermostat.coolingSetpointTemperatureSchedule.is_initialized
2861
2900
  next if !thermostat.heatingSetpointTemperatureSchedule.is_initialized
2862
2901
  runner.registerInfo("Assigning #{thermostat.name} to thermal zones with #{space_type.name} assigned.")
2863
- space_type.spaces.each do |space|
2902
+ space_type.spaces.sort.each do |space|
2864
2903
  next if !space.thermalZone.is_initialized
2865
2904
  space.thermalZone.get.setThermostatSetpointDualSetpoint(thermostat)
2866
2905
  end
@@ -3038,7 +3077,7 @@ module OsLib_ModelGeneration
3038
3077
  if args['add_internal_mass']
3039
3078
 
3040
3079
  if args['remove_objects']
3041
- model.getSpaceLoads.each do |instance|
3080
+ model.getSpaceLoads.sort.each do |instance|
3042
3081
  next unless instance.to_InternalMass.is_initialized
3043
3082
  instance.remove
3044
3083
  end
@@ -3091,8 +3130,8 @@ module OsLib_ModelGeneration
3091
3130
  set_building_defaults = runner.getBoolArgumentValue('set_building_defaults', user_arguments)
3092
3131
 
3093
3132
  # reporting initial condition of model
3094
- starting_spaceTypes = model.getSpaceTypes
3095
- starting_constructionSets = model.getDefaultConstructionSets
3133
+ starting_spaceTypes = model.getSpaceTypes.sort
3134
+ starting_constructionSets = model.getDefaultConstructionSets.sort
3096
3135
  runner.registerInitialCondition("The building started with #{starting_spaceTypes.size} space types and #{starting_constructionSets.size} construction sets.")
3097
3136
 
3098
3137
  # lookup space types for specified building type (false indicates not to use whole building type only)
@@ -3129,7 +3168,7 @@ module OsLib_ModelGeneration
3129
3168
  if create_space_types
3130
3169
 
3131
3170
  # array of starting space types
3132
- space_types_starting = model.getSpaceTypes
3171
+ space_types_starting = model.getSpaceTypes.sort
3133
3172
 
3134
3173
  # create stub space types
3135
3174
  space_type_hash.each do |space_type_name, hash|
@@ -3242,11 +3281,10 @@ module OsLib_ModelGeneration
3242
3281
  end
3243
3282
 
3244
3283
  # reporting final condition of model
3245
- finishing_spaceTypes = model.getSpaceTypes
3246
- finishing_constructionSets = model.getDefaultConstructionSets
3284
+ finishing_spaceTypes = model.getSpaceTypes.sort
3285
+ finishing_constructionSets = model.getDefaultConstructionSets.sort
3247
3286
  runner.registerFinalCondition("The building finished with #{finishing_spaceTypes.size} space types and #{finishing_constructionSets.size} construction sets.")
3248
3287
 
3249
3288
  return true
3250
3289
  end
3251
-
3252
3290
  end