openstudio-extension 0.2.3 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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