openstudio-extension 0.4.4 → 0.5.0

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: 07fb8e05dbcb58025bd9f81eece27010cefe13ec967b48bdd307ccfe30bda2d0
4
- data.tar.gz: cec559244c8d8897765a220883af3249decd5faeca6feae5163708ff8f883a80
3
+ metadata.gz: 2e410744afb54a4a4c19ee59dd2d7a9edd77da75d67df9968f0ed2e0a304f0f7
4
+ data.tar.gz: 3949d1e1bb9a929b251e473aac854d50abff6da4800be4b10318f786b0c5c082
5
5
  SHA512:
6
- metadata.gz: 3e437dec7e77dbcfd30853384b16cc7791165a498f75ca96a016a24bf0cc01e83b5872aa1b2e95d062a082cdf9bf8aeed3a91fd7cb19be56e8113f37abd8a2cd
7
- data.tar.gz: 6234de082434647a2910623c9a1ae732088eb6706fc447883da09332dbd8704661583d23a8e02769bf90d5470bccf244ecde93a8411a1b1c2963c71e32f5ad7e
6
+ metadata.gz: 82b88a5b66d29367fca57cb38228ccf7f782a798b98e09a220c11eb6d7bfe6e959a947e4a44f97fd391a7eec123fb37c1894e7dfd04803108fca75fd02a0bccb
7
+ data.tar.gz: 451ea32b090a21701eda6df859714bb213e212c2fdcdab086de7c51dd71031e9eaab493b04df671eccc9c01483408f40595127246997c91e810e0b1d3f4b3847
data/.gitignore CHANGED
@@ -17,6 +17,7 @@
17
17
  /lib/measures/.rubocop*
18
18
  /lib/measures/staged
19
19
  /lib/measures/staged/*
20
+ .DS_Store
20
21
 
21
22
  # rspec failure tracking
22
23
  .rspec_status
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # OpenStudio Extension Gem
2
2
 
3
+ ## Version 0.5.0
4
+
5
+ * Update OpenStudio Workflow Gem to 2.3.0 (support for epJSON)
6
+
7
+ - Fixed [#133]( https://github.com/NREL/openstudio-extension-gem/pull/133 ), cleanup readme and rework BCL tasks
8
+ - Fixed [#135]( https://github.com/NREL/openstudio-extension-gem/pull/135 ), Intersect tests 072021
9
+ - Fixed [#136]( https://github.com/NREL/openstudio-extension-gem/pull/136 ), Osm from haystack
10
+ - Fixed [#137]( https://github.com/NREL/openstudio-extension-gem/issues/137 ), Edge case error in hospital bar
11
+ - Fixed [#138]( https://github.com/NREL/openstudio-extension-gem/issues/138 ), os_lib_model_generation does not assign SWH type correctly
12
+ - Fixed [#139]( https://github.com/NREL/openstudio-extension-gem/pull/139 ), fix swh_src assignment operators
13
+ - Fixed [#142]( https://github.com/NREL/openstudio-extension-gem/pull/142 ), added arg for hoo_var_method and updated test to use it
14
+
3
15
  ## Version 0.4.4
4
16
 
5
17
  * Update BCL gem to version 0.7.1 which upgrades REXML and Spreadsheet with security patches
data/README.md CHANGED
@@ -10,10 +10,10 @@ Derivative extension gems should include this gem to access common functionality
10
10
  * OpenStudio CLI functionality such as list_measures and update_measures
11
11
  * adding documentation and license files to measures
12
12
  * adding core resource files to measures
13
- * pushing measures to BCL
13
+ * correct structure for contributing content to the Building Component Library (BCL)
14
14
 
15
15
  Extension gems will contain a small group of related measures. Each extension gem will be the unique location to find these measures, and will be responsible for
16
- testing and maintaining the measures as well as pushing them to BCL.
16
+ testing and maintaining the measures as well as indexing them on BCL.
17
17
 
18
18
  ## Usage
19
19
 
@@ -31,7 +31,7 @@ Each OpenStudio extension gem should define its own module name to ensure that t
31
31
 
32
32
  ## Installation
33
33
 
34
- To use the latest version of this and other extension gems, you will need Ruby 2.7.x and OpenStudio 3.1.0 or greater.
34
+ To use the latest version of this and other extension gems, you will need Ruby 2.7.x and OpenStudio 3.1.0 or greater. For earlier versions, view the [compatibility matrix](#compatibility-matrix) below.
35
35
 
36
36
  ### Windows Installation
37
37
  Install Ruby with Devkit using the [RubyInstaller](https://rubyinstaller.org/downloads/archives/) for [Ruby 2.7.2 (x64)](
@@ -81,6 +81,14 @@ the OpenStudio Application you just downloaded (replace 3.1.0 with the version y
81
81
  ```
82
82
  export RUBYLIB=/Applications/OpenStudio-3.1.0/Ruby
83
83
  ```
84
+ ## Compatibility Matrix
85
+
86
+ |OpenStudio Extension Gem|OpenStudio|Ruby|
87
+ |:--------------:|:----------:|:--------:|
88
+ | 0.4.0 - 0.4.4 | 3.2 | 2.7 |
89
+ | 0.3.0 - 0.3.2 | 3.1 | 2.5 |
90
+ | 0.2.0 - 0.2.6 | 3.0 | 2.5 |
91
+ | 0.1.6 and below | 2.9 and below | 2.2.4 |
84
92
 
85
93
 
86
94
  ## Contents
@@ -139,7 +147,7 @@ Note that this folder is for 'core' functionality; if a measure's requires a new
139
147
  Having a single repository for all measures, such as the OpenStudio-measures repo, can be cumbersome to test and keep up to date.
140
148
  In this new framework, each extension gem will contain one or more related measures. The gem will be the new 'home' of these measures, and the repo owner will be responsible for testing and keeping the measures up to date.
141
149
 
142
- In the short term, in order to preserve the PAT/OS App functionality, resource files will still be copied directly into the measures, and these measures will be pushed to BCL.
150
+ In the short term, in order to preserve the PAT/OS App functionality, resource files will still be copied directly into the measures, and these measures will be indexed on the BCL.
143
151
 
144
152
  ### Rake Tasks
145
153
 
@@ -147,10 +155,7 @@ Common Rake Tasks that are available to derivative extension gems include:
147
155
 
148
156
  | Rake Task | Description |
149
157
  | --------- | ----------- |
150
- | openstudio:bcl:test_login | Test BCL login |
151
158
  | openstudio:bcl:search_measures | Search BCL |
152
- | openstudio:bcl:stage[reset] | Copy the measures/components to a staging location |
153
- | openstudio:bcl:push | Upload measures from the staging location |
154
159
  | openstudio:change_log[start_date,end_date,apikey] | Print the change log from GitHub. Specify dates in yyyy-mm-dd format |
155
160
  | openstudio:list_measures | List all measures in the calling gem |
156
161
  | openstudio:measures:add_license | Add License File to measures in the calling gem |
@@ -210,12 +215,8 @@ The OpenStudio-extension gem can be used to easily initialize a new derivative e
210
215
  * All files and classes should have underscores (no dashes) and (lowercase snake_case)
211
216
  * Dashes should be used in module names
212
217
 
213
- ### Pushing to BCL
214
- Use the rake tasks listed above to stage and push measures to BCL.
215
- **Note of warning**: Use caution when pushing to the BCL. Public and private measures could be pushed to BCL from within an extension gem, even though the extension gem repo may be private.
216
-
217
- TODO: Add warning to rake task and lists what gems will be pushed
218
- TODO: Check that license files, etc. are present in each measure before pushing to BCL
218
+ ### Contributing measures to the BCL
219
+ Register your extension gem repo with the [BCL Manifest](https://github.com/BuildingComponentLibrary/bcl-manifest) and [follow the instructions](https://github.com/BuildingComponentLibrary/bcl-manifest#contribute-content) to contribute content to the BCL.
219
220
 
220
221
  ## Include in a project
221
222
 
@@ -234,6 +235,10 @@ Or install it yourself as:
234
235
 
235
236
  $ gem install 'openstudio-extension'
236
237
 
238
+ # Contributing
239
+
240
+ Please review the [OpenStudio Contribution Policy](https://openstudio.net/openstudio-contribution-policy) if you would like to contribute code to this gem.
241
+
237
242
  # Releasing the gem
238
243
 
239
244
  * Update CHANGELOG.md
@@ -327,8 +327,7 @@ module OsLib_Geometry
327
327
  end
328
328
 
329
329
  # sort array by floor area, this hash will be altered to reduce floor area for each space type to 0
330
- #space_types_running_count = space_types.sort_by { |k, v| v[:floor_area] }
331
- space_types_running_count = space_types
330
+ space_types_running_count = space_types.sort_by { |k, v| v[:floor_area] }
332
331
 
333
332
  # array entry for each story
334
333
  footprints = []
@@ -36,6 +36,9 @@
36
36
  # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
37
  # *******************************************************************************
38
38
 
39
+ # used to load haystack json in typical_building_from_model
40
+ require 'json'
41
+
39
42
  module OsLib_ModelGeneration
40
43
  # simple list of building types that are valid for get_space_types_from_building_type
41
44
  # for general public use use extended = false
@@ -1143,9 +1146,10 @@ module OsLib_ModelGeneration
1143
1146
  spaces_temp = OpenStudio::Model::SpaceVector.new
1144
1147
  spaces_temp << space_a
1145
1148
  spaces_temp << space_b
1149
+ # disable until enhanced intersectio nand matching, will make walls adiabatic and exterior within create_bar workflow
1146
1150
  # intersect and sort
1147
- OpenStudio::Model.intersectSurfaces(spaces_temp)
1148
- OpenStudio::Model.matchSurfaces(spaces_temp)
1151
+ # OpenStudio::Model.intersectSurfaces(spaces_temp)
1152
+ # OpenStudio::Model.matchSurfaces(spaces_temp)
1149
1153
  end
1150
1154
  end
1151
1155
  runner.registerInfo("Intersecting and matching surfaces in story #{story.name}, this will create additional geometry.")
@@ -1169,9 +1173,11 @@ module OsLib_ModelGeneration
1169
1173
  story.spaces.sort.each do |space|
1170
1174
  story_spaces << space
1171
1175
  end
1172
- OpenStudio::Model.intersectSurfaces(story_spaces)
1173
- OpenStudio::Model.matchSurfaces(story_spaces)
1174
- runner.registerInfo("Intersecting and matching surfaces in story #{story.name}, this will create additional geometry.")
1176
+ # disable until enhanced intersectio nand matching, will make walls adiabatic and exterior within create_bar workflow
1177
+ # intersect and sort
1178
+ # OpenStudio::Model.intersectSurfaces(story_spaces)
1179
+ # OpenStudio::Model.matchSurfaces(story_spaces)
1180
+ #runner.registerInfo("Intersecting and matching surfaces in story #{story.name}, this will create additional geometry.")
1175
1181
  end
1176
1182
  end
1177
1183
 
@@ -1193,6 +1199,66 @@ module OsLib_ModelGeneration
1193
1199
  end
1194
1200
  end
1195
1201
 
1202
+ # set wall boundary condtions to adiabatic if using make_mid_story_surfaces_adiabatic prior to windows being made
1203
+ if bar_hash[:make_mid_story_surfaces_adiabatic]
1204
+
1205
+ runner.registerInfo("Finding non-exterior walls and setting boundary condition to adiabatic")
1206
+
1207
+ # need to organize by story incase top story is partial story
1208
+ story_bounding = {}
1209
+
1210
+ # gather new spaces by story
1211
+ new_spaces.each do |space|
1212
+ story = space.buildingStory.get
1213
+ if story_bounding.has_key?(story)
1214
+ story_bounding[story][:spaces] << space
1215
+ else
1216
+ story_bounding[story] = {:spaces => [space]}
1217
+ end
1218
+ end
1219
+
1220
+ # get bounding box for each story
1221
+ story_bounding.each do |story,v|
1222
+
1223
+ # get bounding_box
1224
+ bounding_box = OpenStudio::BoundingBox.new
1225
+ v[:spaces].each do |space|
1226
+ space.surfaces.each do |space_surface|
1227
+ bounding_box.addPoints(space.transformation * space_surface.vertices)
1228
+ end
1229
+ end
1230
+ min_x = bounding_box.minX.get
1231
+ min_y = bounding_box.minY.get
1232
+ max_x = bounding_box.maxX.get
1233
+ max_y = bounding_box.maxY.get
1234
+ ext_wall_toll = 0.01
1235
+
1236
+ # check surfaces again against min/max and change to adiabatic if not fully on one min or max x or y
1237
+ # todo - may need to look at aidiabiatc constructions in downstream measure. Some may be exterior party wall others may be interior walls
1238
+ v[:spaces].each do |space|
1239
+ space.surfaces.each do |space_surface|
1240
+ next if not space_surface.surfaceType == "Wall"
1241
+ surface_bounding_box = OpenStudio::BoundingBox.new
1242
+ surface_bounding_box.addPoints(space.transformation * space_surface.vertices)
1243
+ surface_on_outside = false
1244
+ # check xmin
1245
+ if (surface_bounding_box.minX.get - min_x).abs < ext_wall_toll && (surface_bounding_box.maxX.get - min_x).abs < ext_wall_toll then surface_on_outside = true end
1246
+ # check xmax
1247
+ if (surface_bounding_box.minX.get - max_x).abs < ext_wall_toll && (surface_bounding_box.maxX.get - max_x).abs < ext_wall_toll then surface_on_outside = true end
1248
+ # check ymin
1249
+ if (surface_bounding_box.minY.get - min_y).abs < ext_wall_toll && (surface_bounding_box.maxY.get - min_y).abs < ext_wall_toll then surface_on_outside = true end
1250
+ # check ymax
1251
+ if (surface_bounding_box.minY.get - max_y).abs < ext_wall_toll && (surface_bounding_box.maxY.get - max_y).abs < ext_wall_toll then surface_on_outside = true end
1252
+
1253
+ # change if not exterior
1254
+ if !surface_on_outside
1255
+ space_surface.setOutsideBoundaryCondition("Adiabatic")
1256
+ end
1257
+ end
1258
+ end
1259
+ end
1260
+ end
1261
+
1196
1262
  # sort stories (by name for now but need better way)
1197
1263
  sorted_stories = {}
1198
1264
  new_spaces.each do |space|
@@ -1697,9 +1763,6 @@ module OsLib_ModelGeneration
1697
1763
  end
1698
1764
  fraction = OsLib_HelperMethods.checkDoubleAndIntegerArguments(runner, user_arguments, 'min' => 0.0, 'max' => 1.0, 'min_eq_bool' => true, 'max_eq_bool' => true, 'arg_array' => fraction_args)
1699
1765
 
1700
- positive_args = ['total_bldg_floor_area']
1701
- positive = OsLib_HelperMethods.checkDoubleAndIntegerArguments(runner, user_arguments, 'min' => 0.0, 'max' => nil, 'min_eq_bool' => false, 'max_eq_bool' => false, 'arg_array' => positive_args)
1702
-
1703
1766
  one_or_greater_args = ['num_stories_above_grade']
1704
1767
  one_or_greater = OsLib_HelperMethods.checkDoubleAndIntegerArguments(runner, user_arguments, 'min' => 1.0, 'max' => nil, 'min_eq_bool' => true, 'max_eq_bool' => false, 'arg_array' => one_or_greater_args)
1705
1768
 
@@ -1710,13 +1773,13 @@ module OsLib_ModelGeneration
1710
1773
  'party_wall_stories_south',
1711
1774
  'party_wall_stories_east',
1712
1775
  'party_wall_stories_west',
1776
+ 'total_bldg_floor_area',
1713
1777
  'single_floor_area',
1714
1778
  'bar_width']
1715
1779
  non_neg = OsLib_HelperMethods.checkDoubleAndIntegerArguments(runner, user_arguments, 'min' => 0.0, 'max' => nil, 'min_eq_bool' => true, 'max_eq_bool' => false, 'arg_array' => non_neg_args)
1716
1780
 
1717
1781
  # return false if any errors fail
1718
1782
  if !fraction then return false end
1719
- if !positive then return false end
1720
1783
  return false if !one_or_greater
1721
1784
  return false if !non_neg
1722
1785
 
@@ -1815,10 +1878,6 @@ module OsLib_ModelGeneration
1815
1878
  args = bar_arg_check_setup(model,runner,user_arguments,false) # false stops it from checking args on used in bar_from_building_type_ratios
1816
1879
  if !args then return false end
1817
1880
 
1818
- # identify primary building type for building form defaults
1819
- primary_building_type = "PrimarySchool" # see what building type represents the most floro area
1820
- building_form_defaults = building_form_defaults(primary_building_type)
1821
-
1822
1881
  # process arg into hash
1823
1882
  space_type_hash_name = {}
1824
1883
  args['space_type_hash_string'][0..-1].split(/, /).each { |entry| entryMap = entry.split(/=>/); value_str = entryMap[1]; space_type_hash_name[entryMap[0].strip[0..-1].to_s] = value_str.nil? ? '' : value_str.strip[0..-1].to_f }
@@ -1866,6 +1925,11 @@ module OsLib_ModelGeneration
1866
1925
  building_type_fraction_of_building += ratio
1867
1926
  end
1868
1927
 
1928
+ # identify primary building type for building form defaults
1929
+ primary_building_type = building_type_hash.keys.first # update to choose building with highest ratio
1930
+ runner.registerInfo("Creating bar with space type ratio proided as argument.")
1931
+ runner.registerInfo("Using building type from first ratio #{primary_building_type} as the primary building type. This is used for building form defaults.")
1932
+
1869
1933
  # todo - confirm if this will get normalized up/down later of if I should fix or stop here instead of just a warning
1870
1934
  if building_type_fraction_of_building > 1.0
1871
1935
  runner.registerWarning("Sum of Space Type Ratio of #{building_type_fraction_of_building} is greater than the expected value of 1.0")
@@ -1877,6 +1941,8 @@ module OsLib_ModelGeneration
1877
1941
 
1878
1942
  # if aspect ratio, story height or wwr have argument value of 0 then use smart building type defaults
1879
1943
  primary_building_type = args['bldg_type_a']
1944
+ runner.registerInfo("Creating bar space type ratios by building type based on ratios from prototype models.")
1945
+ runner.registerInfo("#{primary_building_type} will be used for building form defaults.")
1880
1946
 
1881
1947
  end
1882
1948
 
@@ -2512,7 +2578,7 @@ module OsLib_ModelGeneration
2512
2578
  runner.registerValue('ew_wall_area_ip', wall_ew_ip, 'ft^2')
2513
2579
  # for now using perimeter of ground floor and average story area (building area / num_stories)
2514
2580
  runner.registerValue('floor_area_to_perim_ratio', model.getBuilding.floorArea / (OsLib_Geometry.calculate_perimeter(model) * num_stories))
2515
- runner.registerValue('bar_width', OpenStudio.convert(bars['primary'][:width], 'm', 'ft').get, 'ft')
2581
+ runner.registerValue('bar_width_output', OpenStudio.convert(bars['primary'][:width], 'm', 'ft').get, 'ft')
2516
2582
 
2517
2583
  if args['party_wall_fraction'] > 0 || args['party_wall_stories_north'] > 0 || args['party_wall_stories_south'] > 0 || args['party_wall_stories_east'] > 0 || args['party_wall_stories_west'] > 0
2518
2584
  runner.registerInfo('Target facade area by orientation not validated when party walls are applied')
@@ -2709,6 +2775,29 @@ module OsLib_ModelGeneration
2709
2775
  return false
2710
2776
  end
2711
2777
 
2778
+ # if haystack_file used find the file
2779
+ # todo - may want to allow NA, empty string or some other value to skip so a measure can ake this optional witht using optional measure arguments
2780
+ if args['haystack_file']
2781
+ haystack_file = runner.workflow.findFile(args['haystack_file'])
2782
+ if haystack_file.is_initialized
2783
+ haystack_file = haystack_file.get.to_s
2784
+
2785
+ # load JSON file
2786
+ json = nil
2787
+ File.open(haystack_file, 'r') do |file|
2788
+ json = file.read
2789
+ # uncomment to inspect haystack json
2790
+ # puts json
2791
+ end
2792
+
2793
+ else
2794
+ runner.registerError("Did not find #{args['haystack_file']} in paths described in OSW file.")
2795
+ return false
2796
+ end
2797
+ else
2798
+ haystack_file = nil
2799
+ end
2800
+
2712
2801
  # make sure daylight savings is turned on up prior to any sizing runs being done.
2713
2802
  if args['enable_dst']
2714
2803
  start_date = '2nd Sunday in March'
@@ -2934,9 +3023,9 @@ module OsLib_ModelGeneration
2934
3023
  if args['htg_src'] == 'NaturalGas' || args['htg_src'] == 'DistrictHeating'
2935
3024
  args['swh_src'] = 'NaturalGas' # If building has gas service, probably uses natural gas for SWH
2936
3025
  elsif args['htg_src'] == 'Electricity'
2937
- args['swh_src'] == 'Electricity' # If building is doing space heating with electricity, probably used for SWH
3026
+ args['swh_src'] = 'Electricity' # If building is doing space heating with electricity, probably used for SWH
2938
3027
  elsif args['htg_src'] == 'DistrictAmbient'
2939
- args['swh_src'] == 'HeatPump' # If building has district ambient loop, it is fancy and probably uses HPs for SWH
3028
+ args['swh_src'] = 'HeatPump' # If building has district ambient loop, it is fancy and probably uses HPs for SWH
2940
3029
  else
2941
3030
  args['swh_src'] = nil # Use inferences built into OpenStudio Standards for each building and space type
2942
3031
  end
@@ -3092,12 +3181,20 @@ module OsLib_ModelGeneration
3092
3181
  sys_type # same as primary system type
3093
3182
  end
3094
3183
 
3095
- # Group zones by story
3096
- story_zone_lists = standard.model_group_zones_by_story(model, sys_group['zones'])
3184
+ # group zones
3185
+ if haystack_file.nil?
3186
+ # Group zones by story
3187
+ bldg_zone_lists = standard.model_group_zones_by_story(model, sys_group['zones'])
3188
+ else
3189
+ # todo - group zones using haystack file instead of building stories
3190
+ # todo - need to do something similar to use haystack to indentify secondary zones
3191
+ bldg_zone_lists = standard.model_group_zones_by_story(model, sys_group['zones'])
3192
+ runner.registerInfo("***This code will define which zones are on air loops for inferred system***")
3193
+ end
3097
3194
 
3098
3195
  # On each story, add the primary system to the primary zones
3099
3196
  # and add the secondary system to any zones that are different.
3100
- story_zone_lists.each do |story_group|
3197
+ bldg_zone_lists.each do |story_group|
3101
3198
  # Differentiate primary and secondary zones, based on
3102
3199
  # operating hours and internal loads (same as 90.1 PRM)
3103
3200
  pri_sec_zone_lists = standard.model_differentiate_primary_secondary_thermal_zones(model, story_group)
@@ -3137,12 +3234,21 @@ module OsLib_ModelGeneration
3137
3234
  # Group the zones by occupancy type. Only split out non-dominant groups if their total area exceeds the limit.
3138
3235
  sys_groups = standard.model_group_zones_by_type(model, OpenStudio.convert(20_000, 'ft^2', 'm^2').get)
3139
3236
  sys_groups.each do |sys_group|
3140
- # Group the zones by story
3141
- story_groups = standard.model_group_zones_by_story(model, sys_group['zones'])
3237
+
3238
+ # group zones
3239
+ if haystack_file.nil?
3240
+ # Group zones by story
3241
+ bldg_zone_groups = standard.model_group_zones_by_story(model, sys_group['zones'])
3242
+ else
3243
+ # todo - group zones using haystack file instead of building stories
3244
+ # todo - need to do something similar to use haystack to indentify secondary zones
3245
+ bldg_zone_groups = standard.model_group_zones_by_story(model, sys_group['zones'])
3246
+ runner.registerInfo("***This code will define which zones are on air loops for user specified system***")
3247
+ end
3142
3248
 
3143
3249
  # Add the user specified HVAC system for each story.
3144
3250
  # Single-zone systems will get one per zone.
3145
- story_groups.each do |zones|
3251
+ bldg_zone_groups.each do |zones|
3146
3252
  unless model.add_cbecs_hvac_system(standard, args['system_type'], zones)
3147
3253
  runner.registerError("HVAC system type '#{args['system_type']}' not recognized. Check input system type argument against Model.hvac.rb for valid hvac system type names.")
3148
3254
  return false
@@ -3157,8 +3263,17 @@ module OsLib_ModelGeneration
3157
3263
  # Infer the current hours of operation schedule for the building
3158
3264
  op_sch = standard.model_infer_hours_of_operation_building(model)
3159
3265
 
3266
+ # setup hoo_var_method (should be hours or fractional)
3267
+ if args.has_key?('hoo_var_method')
3268
+ hoo_var_method = args['hoo_var_method']
3269
+ else
3270
+ # support measures that don't supply this argument
3271
+ hoo_var_method = 'hours'
3272
+ end
3273
+
3160
3274
  # Convert existing schedules in the model to parametric schedules based on current hours of operation
3161
- standard.model_setup_parametric_schedules(model)
3275
+ runner.registerInfo("Generating parametric schedules from ruleset schedules using #{hoo_var_method} variable method for hours of operation fromula.")
3276
+ standard.model_setup_parametric_schedules(model, hoo_var_method: hoo_var_method)
3162
3277
 
3163
3278
  # Create start and end times from start time and duration supplied
3164
3279
  wkdy_start_time = nil
@@ -3254,11 +3369,11 @@ module OsLib_ModelGeneration
3254
3369
 
3255
3370
  # change night cycling control to "Thermostat" cycling and increase thermostat tolerance to 1.99999
3256
3371
  manager_night_cycles = model.getAvailabilityManagerNightCycles
3257
-
3372
+ runner.registerInfo("Changing thermostat tollerance to 1.99999 for #{manager_night_cycles.size} night cycle manager objects.")
3373
+
3258
3374
  manager_night_cycles.each do |night_cycle|
3259
3375
  night_cycle.setThermostatTolerance(1.9999)
3260
3376
  night_cycle.setCyclingRunTimeControlType("Thermostat")
3261
- runner.registerInfo(" night_cycle == #{night_cycle}")
3262
3377
  end
3263
3378
 
3264
3379
  # report final condition of model
@@ -147,19 +147,11 @@ module OpenStudio
147
147
  end
148
148
 
149
149
  namespace 'bcl' do
150
- desc 'Test BCL login'
151
- task :test_login do
152
- puts 'test BCL login'
153
- bcl = ::BCL::ComponentMethods.new
154
- bcl.login
155
- end
156
-
157
150
  # for custom search, populate env var: bcl_search_keyword
158
151
  desc 'Search BCL'
159
152
  task :search_measures do
160
153
  puts 'test search BCL'
161
154
  bcl = ::BCL::ComponentMethods.new
162
- bcl.login
163
155
 
164
156
  # check for env var specifying keyword first
165
157
  if ENV['bcl_search_keyword']
@@ -176,198 +168,6 @@ module OpenStudio
176
168
  puts(res[:measure][:name]).to_s
177
169
  end
178
170
  end
179
-
180
- # to call with argument: "openstudio:bcl:stage[true]" (true = remove existing staged content)
181
- desc 'Copy the measures/components to a location that can be uploaded to BCL'
182
- task :stage, [:reset] do |t, args|
183
- puts 'Staging measures for BCL'
184
- # initialize BCL and login
185
- bcl = ::BCL::ComponentMethods.new
186
- bcl.login
187
-
188
- # process reset options: true to clear out old staged content
189
- options = { reset: false }
190
- if args[:reset].to_s == 'true'
191
- options[:reset] = true
192
- end
193
-
194
- # ensure staged dir exists
195
- FileUtils.mkdir_p(@staged_path)
196
-
197
- # delete existing tarballs if reset is true
198
- if options[:reset]
199
- puts 'Deleting existing staged content'
200
- FileUtils.rm_rf(Dir.glob("#{@staged_path}/*"))
201
- end
202
-
203
- # create new and existing directories
204
- FileUtils.mkdir_p("#{@staged_path}/update")
205
- FileUtils.mkdir_p("#{@staged_path}/push/component")
206
- FileUtils.mkdir_p("#{@staged_path}/push/measure")
207
-
208
- # keep track of noop, update, push
209
- noops = 0
210
- new_ones = 0
211
- updates = 0
212
-
213
- # get all content directories to process
214
- dirs = Dir.glob("#{@measures_dir}/*")
215
-
216
- dirs.each do |dir|
217
- next if dir.include?('Rakefile') || File.basename(dir) == 'staged'
218
-
219
- current_d = Dir.pwd
220
- content_name = File.basename(dir)
221
- puts '', '---'
222
- puts "Generating #{content_name}"
223
-
224
- Dir.chdir(dir)
225
-
226
- # figure out whether to upload new or update existing
227
- files = Pathname.glob('**/*')
228
- uuid = nil
229
- vid = nil
230
- content_type = 'measure'
231
-
232
- paths = []
233
- files.each do |file|
234
- # don't tar tests/outputs directory
235
- next if file.to_s.start_with?('tests/output') # From measure testing process
236
- next if file.to_s.start_with?('tests/test') # From openstudio-measure-tester-gem
237
- next if file.to_s.start_with?('tests/coverage') # From openstudio-measure-tester-gem
238
- next if file.to_s.start_with?('test_results') # From openstudio-measure-tester-gem
239
-
240
- paths << file.to_s
241
- if file.to_s =~ /^.{0,2}component.xml$/ || file.to_s =~ /^.{0,2}measure.xml$/
242
- if file.to_s.match?(/^.{0,2}component.xml$/)
243
- content_type = 'component'
244
- end
245
- # extract uuid and vid
246
- uuid, vid = bcl.uuid_vid_from_xml(file)
247
- end
248
- end
249
- puts "UUID: #{uuid}, VID: #{vid}"
250
-
251
- # NOTE: if uuid is missing, will assume new content
252
- action = bcl.search_by_uuid(uuid, vid)
253
- puts "#{content_name} ACTION TO TAKE: #{action}"
254
- # new content functionality needs to know if measure or component. update is agnostic.
255
- case action
256
- when 'noop' # ignore up-to-date content
257
- puts " - WARNING: local #{content_name} uuid and vid match BCL... no update will be performed"
258
- noops += 1
259
- next
260
- when 'update'
261
- # puts "#{content_name} labeled as update for BCL"
262
- destination = "#{@staged_path}/#{action}/#{content_name}.tar.gz"
263
- updates += 1
264
- when 'push'
265
- # puts "#{content_name} labeled as new content for BCL"
266
- destination = "#{@staged_path}/#{action}/#{content_type}/#{content_name}.tar.gz"
267
- new_ones += 1
268
- end
269
-
270
- puts "destination: #{destination}"
271
-
272
- # copy over only if 'reset_receipts' is set to TRUE. otherwise ignore if file exists already
273
- if File.exist?(destination)
274
- if options[:reset]
275
- FileUtils.rm(destination)
276
- ::BCL.tarball(destination, paths)
277
- else
278
- puts "*** WARNING: File #{content_name}.tar.gz already exists in staged directory... keeping existing file. To overwrite, set reset_receipts arg to true ***"
279
- end
280
- else
281
- ::BCL.tarball(destination, paths)
282
- end
283
- Dir.chdir(current_d)
284
- end
285
- puts '', "****STAGING DONE**** #{new_ones} new content, #{updates} updates, #{noops} skipped (already up-to-date on BCL)", ''
286
- end
287
-
288
- desc 'Upload measures from the specified location.'
289
- task :push do
290
- puts 'Push measures to BCL'
291
-
292
- # initialize BCL and login
293
- bcl = ::BCL::ComponentMethods.new
294
- bcl.login
295
- reset = false
296
-
297
- total_count = 0
298
- successes = 0
299
- errors = 0
300
- skipped = 0
301
-
302
- # grab all the new measure and component tar files and push to bcl
303
- ['measure', 'component'].each do |content_type|
304
- items = []
305
- paths = Pathname.glob(@staged_path.to_s + "/push/#{content_type}/*.tar.gz")
306
- paths.each do |path|
307
- # puts path
308
- items << path.to_s
309
- end
310
-
311
- items.each do |item|
312
- puts item.split('/').last
313
- total_count += 1
314
-
315
- receipt_file = "#{File.dirname(item)}/#{File.basename(item, '.tar.gz')}.receipt"
316
- if !reset && File.exist?(receipt_file)
317
- skipped += 1
318
- puts 'SKIP: receipt file found'
319
- next
320
- end
321
-
322
- valid, res = bcl.push_content(item, true, "nrel_#{content_type}")
323
- if valid
324
- successes += 1
325
- else
326
- errors += 1
327
- if res.key?(:error)
328
- puts " ERROR MESSAGE: #{res[:error]}"
329
- else
330
- puts "ERROR: #{res.inspect.chomp}"
331
- end
332
- end
333
- puts '', '---'
334
- end
335
- end
336
-
337
- # grab all the updated content (measures and components) tar files and push to bcl
338
- items = []
339
- paths = Pathname.glob("#{@staged_path}/update/*.tar.gz")
340
- paths.each do |path|
341
- # puts path
342
- items << path.to_s
343
- end
344
- items.each do |item|
345
- puts item.split('/').last
346
- total_count += 1
347
-
348
- receipt_file = "#{File.dirname(item)}/#{File.basename(item, '.tar.gz')}.receipt"
349
- if !reset && File.exist?(receipt_file)
350
- skipped += 1
351
- puts 'SKIP: receipt file found'
352
- next
353
- end
354
-
355
- valid, res = bcl.update_content(item, true)
356
- if valid
357
- successes += 1
358
- else
359
- errors += 1
360
- if res.key?(:error)
361
- puts " ERROR MESSAGE: #{res[:error]}"
362
- else
363
- puts "ERROR MESSAGE: #{res.inspect.chomp}"
364
- end
365
- end
366
- puts '', '---'
367
- end
368
-
369
- puts "****UPLOAD DONE**** #{total_count} total, #{successes} success, #{errors} failures, #{skipped} skipped"
370
- end
371
171
  end
372
172
  end
373
173
  end
@@ -35,6 +35,6 @@
35
35
 
36
36
  module OpenStudio
37
37
  module Extension
38
- VERSION = '0.4.4'.freeze
38
+ VERSION = '0.5.0'.freeze
39
39
  end
40
40
  end
@@ -32,12 +32,10 @@ Gem::Specification.new do |spec|
32
32
  spec.add_dependency 'bundler', '>= 2.1.0'
33
33
  spec.add_dependency 'octokit', '~> 4.18.0' # for change logs
34
34
  spec.add_dependency 'openstudio_measure_tester', '~> 0.3.1'
35
- spec.add_dependency 'openstudio-workflow', '~> 2.2.0'
35
+ spec.add_dependency 'openstudio-workflow', '~> 2.3.0'
36
36
  spec.add_dependency 'parallel', '~> 1.19.1'
37
37
 
38
38
  spec.add_development_dependency 'openstudio-standards', '~> 0.2.13' # for os_lib unit tests
39
39
  spec.add_development_dependency 'rake', '~> 13.0'
40
40
  spec.add_development_dependency 'rspec', '~> 3.9'
41
-
42
-
43
41
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openstudio-extension
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katherine Fleming
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2021-09-03 00:00:00.000000000 Z
14
+ date: 2021-10-21 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bcl
@@ -75,14 +75,14 @@ dependencies:
75
75
  requirements:
76
76
  - - "~>"
77
77
  - !ruby/object:Gem::Version
78
- version: 2.2.0
78
+ version: 2.3.0
79
79
  type: :runtime
80
80
  prerelease: false
81
81
  version_requirements: !ruby/object:Gem::Requirement
82
82
  requirements:
83
83
  - - "~>"
84
84
  - !ruby/object:Gem::Version
85
- version: 2.2.0
85
+ version: 2.3.0
86
86
  - !ruby/object:Gem::Dependency
87
87
  name: parallel
88
88
  requirement: !ruby/object:Gem::Requirement
@@ -233,7 +233,7 @@ licenses: []
233
233
  metadata:
234
234
  bug_tracker_uri: https://github.com/NREL/openstudio-extension-gem/issues
235
235
  changelog_uri: https://github.com/NREL/openstudio-extension-gem/blob/develop/CHANGELOG.md
236
- source_code_uri: https://github.com/NREL/openstudio-extension-gem/tree/v0.4.4
236
+ source_code_uri: https://github.com/NREL/openstudio-extension-gem/tree/v0.5.0
237
237
  post_install_message:
238
238
  rdoc_options: []
239
239
  require_paths: