honeybee-openstudio 2.22.2 → 2.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/honeybee-openstudio.gemspec +4 -4
  4. data/lib/from_openstudio/construction/air.rb +2 -2
  5. data/lib/from_openstudio/construction/opaque.rb +2 -2
  6. data/lib/from_openstudio/construction/shade.rb +2 -2
  7. data/lib/from_openstudio/construction/window.rb +2 -2
  8. data/lib/from_openstudio/construction_set.rb +14 -14
  9. data/lib/from_openstudio/geometry/aperture.rb +1 -1
  10. data/lib/from_openstudio/geometry/door.rb +1 -1
  11. data/lib/from_openstudio/geometry/face.rb +1 -1
  12. data/lib/from_openstudio/geometry/room.rb +1 -1
  13. data/lib/from_openstudio/geometry/shade.rb +1 -1
  14. data/lib/from_openstudio/material/opaque.rb +1 -1
  15. data/lib/from_openstudio/material/opaque_no_mass.rb +1 -1
  16. data/lib/from_openstudio/material/window_blind.rb +1 -1
  17. data/lib/from_openstudio/material/window_gas.rb +1 -1
  18. data/lib/from_openstudio/material/window_gas_custom.rb +1 -1
  19. data/lib/from_openstudio/material/window_gas_mixture.rb +1 -1
  20. data/lib/from_openstudio/material/window_glazing.rb +1 -1
  21. data/lib/from_openstudio/material/window_simpleglazsys.rb +1 -1
  22. data/lib/from_openstudio/model.rb +25 -0
  23. data/lib/from_openstudio/schedule/ruleset.rb +114 -0
  24. data/lib/from_openstudio/schedule/type_limit.rb +63 -0
  25. data/lib/from_openstudio.rb +5 -1
  26. data/lib/honeybee/_defaults/energy_default.json +8 -2
  27. data/lib/honeybee/model.rb +1 -0
  28. data/lib/honeybee/model_object.rb +11 -3
  29. data/lib/measures/from_honeybee_model_to_gbxml/measure.rb +1 -0
  30. data/lib/to_openstudio/construction/window.rb +18 -9
  31. data/lib/to_openstudio/geometry/face.rb +1 -1
  32. data/lib/to_openstudio/geometry/room.rb +12 -2
  33. data/lib/to_openstudio/ventcool/opening.rb +51 -25
  34. metadata +10 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5392435198119a686f3699148121914e8bd91ce5664c5b6499b9c992718655ae
4
- data.tar.gz: 41671a1887d378797a955d26d48211476754dcf31f178fa13ba8689a62e50826
3
+ metadata.gz: 8b1713bd43ce02933e6b62917cfd588f51b34474ab42cc964fac0707892ef6cb
4
+ data.tar.gz: 1b63c7e6ef5ef775b1c6312170fc11cb2117685141e6e6c00d39bc14a4dcb7e9
5
5
  SHA512:
6
- metadata.gz: 486f13b92b50320910c4612c91fa6baf1050f618e844253a3462652d969878cbb99dd67c31569eda343467dc29d10d969d88f626c49d814e4fcc96805ab60780
7
- data.tar.gz: e7baa65945989b5c72169530e40529a7ed2a598980ca3176c51c3fed079f75467353d408e605ae5b47e9a9566147b7ce1006346e9e8d4f3740c03f9cef9a7fff
6
+ metadata.gz: b2ce15cb4c8761569e16fae90f1a378a34d4a662abe027458714ed2c11004e84d833dec91ab7795d14d019ada20803a96969ac08c9eb0e8b8f9f725d60911fd5
7
+ data.tar.gz: 2ed1a4870310d697989c9af03079522af38459cba61280b2053e8b2e59cade74318e5ec43380ca85512ec74258d02b2f13305206c2a3a24e97395de428a95266
data/Gemfile CHANGED
@@ -7,7 +7,7 @@ gemspec
7
7
  if File.exist?('../OpenStudio-extension-gem') # local development copy
8
8
  gem 'openstudio-extension', path: '../OpenStudio-extension-gem'
9
9
  else # get it from rubygems.org
10
- gem 'openstudio-extension', '0.4.2'
10
+ gem 'openstudio-extension', '0.4.3'
11
11
  end
12
12
 
13
13
  # coveralls gem is used to generate coverage reports through CI
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'honeybee-openstudio'
7
- spec.version = '2.22.2'
7
+ spec.version = '2.23.0'
8
8
  spec.authors = ['Tanushree Charan', 'Dan Macumber', 'Chris Mackey', 'Mostapha Sadeghipour Roudsari']
9
9
  spec.email = ['tanushree.charan@nrel.gov', 'chris@ladybug.tools']
10
10
 
@@ -29,10 +29,10 @@ Gem::Specification.new do |spec|
29
29
  spec.add_development_dependency "json-schema", "~> 2.8.1"
30
30
  spec.add_development_dependency "rake", "~> 13.0"
31
31
  spec.add_development_dependency "rspec", "~> 3.9"
32
- spec.add_development_dependency "rubocop", "~> 0.54.0"
32
+ spec.add_development_dependency "rubocop", "~> 1.15.0"
33
33
  end
34
34
 
35
35
  spec.add_dependency 'json_pure'
36
- spec.add_dependency 'openstudio-extension', '0.4.2'
37
- spec.add_dependency 'openstudio-standards', '~> 0.2.13'
36
+ spec.add_dependency 'openstudio-extension', '0.4.3'
37
+ spec.add_dependency 'openstudio-standards', '~> 0.2.14'
38
38
  end
@@ -40,11 +40,11 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'AirBoundaryConstructionAbridged'
42
42
  # set hash values from OpenStudio Object
43
- hash[:identifier] = construction.nameString
43
+ hash[:identifier] = clean_name(construction.nameString)
44
44
  # check if boost optional object is empty
45
45
  unless construction.simpleMixingSchedule.empty?
46
46
  schedule = construction.simpleMixingSchedule.get
47
- hash[:air_mixing_schedule] = schedule.nameString
47
+ hash[:air_mixing_schedule] = clean_name(schedule.nameString)
48
48
  end
49
49
  #TODO: Add air_mixing_per_area
50
50
 
@@ -40,12 +40,12 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'OpaqueConstructionAbridged'
42
42
  # set hash values from OpenStudio Object
43
- hash[:identifier] = construction.nameString
43
+ hash[:identifier] = clean_name(construction.nameString)
44
44
  hash[:materials] = []
45
45
  # get construction layers
46
46
  layers = construction.layers
47
47
  layers.each do |layer|
48
- name = layer.nameString
48
+ name = clean_name(layer.nameString)
49
49
  hash[:materials] << name
50
50
  end
51
51
 
@@ -40,7 +40,7 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'ShadeConstruction'
42
42
  # set hash values from OpenStudio Object
43
- hash[:identifier] = construction.nameString
43
+ hash[:identifier] = clean_name(construction.nameString)
44
44
  # get outermost construction layers
45
45
  layer = construction.layers[0]
46
46
  if layer.to_StandardGlazing.is_initialized
@@ -61,7 +61,7 @@ module Honeybee
61
61
  hash[:solar_reflectance] = layer.solarReflectance.get
62
62
  end
63
63
  unless layer.visibleReflectance.empty?
64
- hash[:visible_reflectance] = layer.visibleReflectance
64
+ hash[:visible_reflectance] = layer.visibleReflectance.get
65
65
  end
66
66
  elsif layer.to_MasslessOpaqueMaterial.is_initialized
67
67
  layer = layer.to_MasslessOpaqueMaterial.get
@@ -40,12 +40,12 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'WindowConstructionAbridged'
42
42
  # set hash values from OpenStudio Object
43
- hash[:identifier] = construction.nameString
43
+ hash[:identifier] = clean_name(construction.nameString)
44
44
  hash[:materials] = []
45
45
  # get construction layers
46
46
  layers = construction.layers
47
47
  layers.each do |layer|
48
- name = layer.nameString
48
+ name = clean_name(layer.nameString)
49
49
  hash[:materials] << name
50
50
  end
51
51
 
@@ -40,7 +40,7 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'ConstructionSetAbridged'
42
42
  # set hash values from OpenStudio Object
43
- hash[:identifier] = construction_set.nameString
43
+ hash[:identifier] = clean_name(construction_set.nameString)
44
44
  hash[:wall_set] = {}
45
45
  hash[:floor_set] = {}
46
46
  hash[:aperture_set] = {}
@@ -53,17 +53,17 @@ module Honeybee
53
53
  # get interior wall construction
54
54
  unless int_surf_construction.wallConstruction.empty?
55
55
  int_wall_const = int_surf_construction.wallConstruction.get
56
- hash[:wall_set][:interior_construction] = int_wall_const.nameString
56
+ hash[:wall_set][:interior_construction] = clean_name(int_wall_const.nameString)
57
57
  end
58
58
  # get interior floor construction
59
59
  unless int_surf_construction.floorConstruction.empty?
60
60
  int_floor_const = int_surf_construction.floorConstruction.get
61
- hash[:floor_set][:interior_construction] = int_floor_const.nameString
61
+ hash[:floor_set][:interior_construction] = clean_name(int_floor_const.nameString)
62
62
  end
63
63
  # get interior roofceiling construction
64
64
  unless int_surf_construction.roofCeilingConstruction.empty?
65
65
  int_roof_const = int_surf_construction.roofCeilingConstruction.get
66
- hash[:roof_ceiling_set][:interior_construction] = int_roof_const.nameString
66
+ hash[:roof_ceiling_set][:interior_construction] = clean_name(int_roof_const.nameString)
67
67
  end
68
68
  end
69
69
 
@@ -72,17 +72,17 @@ module Honeybee
72
72
  int_subsurf_const = construction_set.defaultInteriorSubSurfaceConstructions.get
73
73
  unless int_subsurf_const.fixedWindowConstruction.empty?
74
74
  int_wind_const = int_subsurf_const.fixedWindowConstruction.get
75
- hash[:aperture_set][:window_construction] = int_wind_const.nameString
75
+ hash[:aperture_set][:window_construction] = clean_name(int_wind_const.nameString)
76
76
  end
77
77
  # get interior door construction
78
78
  unless int_subsurf_const.doorConstruction.empty?
79
79
  int_door_const = int_subsurf_const.doorConstruction.get
80
- hash[:door_set][:interior_construction] = int_door_const.nameString
80
+ hash[:door_set][:interior_construction] = clean_name(int_door_const.nameString)
81
81
  end
82
82
  # get interior glass door construction
83
83
  unless int_subsurf_const.glassDoorConstruction.empty?
84
84
  int_glass_door_const = int_subsurf_const.glassDoorConstruction.get
85
- hash[:door_set][:interior_glass_construction] = int_glass_door_const.nameString
85
+ hash[:door_set][:interior_glass_construction] = clean_name(int_glass_door_const.nameString)
86
86
  end
87
87
  end
88
88
 
@@ -92,17 +92,17 @@ module Honeybee
92
92
  # get exterior wall construction
93
93
  unless ext_surf_const.wallConstruction.empty?
94
94
  ext_wall_const = ext_surf_const.wallConstruction.get
95
- hash[:wall_set][:exterior_construction] = ext_wall_const.nameString
95
+ hash[:wall_set][:exterior_construction] = clean_name(ext_wall_const.nameString)
96
96
  end
97
97
  # get exterior floor construction
98
98
  unless ext_surf_const.floorConstruction.empty?
99
99
  ext_floor_const = ext_surf_const.floorConstruction.get
100
- hash[:floor_set][:exterior_construction] = ext_floor_const.nameString
100
+ hash[:floor_set][:exterior_construction] = clean_name(ext_floor_const.nameString)
101
101
  end
102
102
  # get exterior roofceiling construction
103
103
  unless ext_surf_const.roofCeilingConstruction.empty?
104
104
  ext_roof_const = ext_surf_const.roofCeilingConstruction.get
105
- hash[:roof_ceiling_set][:exterior_construction] = ext_roof_const.nameString
105
+ hash[:roof_ceiling_set][:exterior_construction] = clean_name(ext_roof_const.nameString)
106
106
  end
107
107
  end
108
108
 
@@ -112,22 +112,22 @@ module Honeybee
112
112
  # get exterior operable window construction
113
113
  unless ext_subsurf_const.operableWindowConstruction.empty?
114
114
  ext_wind_const = ext_subsurf_const.operableWindowConstruction.get
115
- hash[:aperture_set][:operable_construction] = ext_wind_const.nameString
115
+ hash[:aperture_set][:operable_construction] = clean_name(ext_wind_const.nameString)
116
116
  end
117
117
  # get exterior skylight construction
118
118
  unless ext_subsurf_const.skylightConstruction.empty?
119
119
  ext_skylight_const = ext_subsurf_const.skylightConstruction.get
120
- hash[:aperture_set][:skylight_construction] = ext_skylight_const.nameString
120
+ hash[:aperture_set][:skylight_construction] = clean_name(ext_skylight_const.nameString)
121
121
  end
122
122
  # get exterior door construction
123
123
  unless ext_subsurf_const.doorConstruction.empty?
124
124
  ext_door_const = ext_subsurf_const.doorConstruction.get
125
- hash[:door_set][:exterior_construction] = ext_door_const.nameString
125
+ hash[:door_set][:exterior_construction] = clean_name(ext_door_const.nameString)
126
126
  end
127
127
  # get exterior overhead door construction
128
128
  unless ext_subsurf_const.overheadDoorConstruction.empty?
129
129
  ext_ovhd_door_const = ext_subsurf_const.overheadDoorConstruction.get
130
- hash[:door_set][:overhead_construction] = ext_ovhd_door_const.nameString
130
+ hash[:door_set][:overhead_construction] = clean_name(ext_ovhd_door_const.nameString)
131
131
  end
132
132
  end
133
133
 
@@ -40,7 +40,7 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'Aperture'
42
42
  hash[:identifier] = clean_identifier(sub_surface.nameString)
43
- hash[:display_name] = clean_display_name(sub_surface.nameString)
43
+ hash[:display_name] = clean_name(sub_surface.nameString)
44
44
  hash[:user_data] = {handle: sub_surface.handle.to_s}
45
45
  hash[:properties] = properties_from_sub_surface(sub_surface)
46
46
  hash[:geometry] = geometry_from_sub_surface(sub_surface, site_transformation)
@@ -40,7 +40,7 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'Door'
42
42
  hash[:identifier] = clean_identifier(sub_surface.nameString)
43
- hash[:display_name] = clean_display_name(sub_surface.nameString)
43
+ hash[:display_name] = clean_name(sub_surface.nameString)
44
44
  hash[:user_data] = {handle: sub_surface.handle.to_s}
45
45
  hash[:properties] = properties_from_sub_surface(sub_surface)
46
46
  hash[:geometry] = geometry_from_sub_surface(sub_surface, site_transformation)
@@ -38,7 +38,7 @@ module Honeybee
38
38
  hash = {}
39
39
  hash[:type] = 'Face'
40
40
  hash[:identifier] = clean_identifier(surface.nameString)
41
- hash[:display_name] = clean_display_name(surface.nameString)
41
+ hash[:display_name] = clean_name(surface.nameString)
42
42
  hash[:user_data] = {handle: surface.handle.to_s}
43
43
  hash[:properties] = properties_from_surface(surface)
44
44
  hash[:geometry] = geometry_from_surface(surface, site_transformation)
@@ -38,7 +38,7 @@ module Honeybee
38
38
  hash = {}
39
39
  hash[:type] = 'Room'
40
40
  hash[:identifier] = clean_identifier(space.nameString)
41
- hash[:display_name] = clean_display_name(space.nameString)
41
+ hash[:display_name] = clean_name(space.nameString)
42
42
  hash[:user_data] = {space: space.handle.to_s}
43
43
  hash[:properties] = properties_from_space(space)
44
44
 
@@ -40,7 +40,7 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'Shade'
42
42
  hash[:identifier] = clean_identifier(shading_surface.nameString)
43
- hash[:display_name] = clean_display_name(shading_surface.nameString)
43
+ hash[:display_name] = clean_name(shading_surface.nameString)
44
44
  hash[:user_data] = {handle: shading_surface.handle.to_s}
45
45
  hash[:properties] = properties_from_shading_surface(shading_surface)
46
46
  hash[:geometry] = geometry_from_shading_surface(shading_surface, site_transformation)
@@ -40,7 +40,7 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'EnergyMaterial'
42
42
  # set hash values from OpenStudio Object
43
- hash[:identifier] = material.nameString
43
+ hash[:identifier] = clean_name(material.nameString)
44
44
  hash[:thickness] = material.thickness
45
45
  hash[:conductivity] = material.conductivity
46
46
  hash[:density] = material.density
@@ -40,7 +40,7 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'EnergyMaterialNoMass'
42
42
  # set hash values from OpenStudio Object
43
- hash[:identifier] = material.nameString
43
+ hash[:identifier] = clean_name(material.nameString)
44
44
  hash[:r_value] = material.thermalResistance
45
45
 
46
46
  if material.to_MasslessOpaqueMaterial.is_initialized
@@ -40,7 +40,7 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'EnergyWindowMaterialBlind'
42
42
  # set hash values from OpenStudio Object
43
- hash[:identifier] = material.nameString
43
+ hash[:identifier] = clean_name(material.nameString)
44
44
  hash[:slat_orientation] = material.slatOrientation
45
45
  hash[:slat_width] = material.slatWidth
46
46
  hash[:slat_separation] = material.slatSeparation
@@ -40,7 +40,7 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'EnergyWindowMaterialGas'
42
42
  # set hash values from OpenStudio Object
43
- hash[:identifier] = material.nameString
43
+ hash[:identifier] = clean_name(material.nameString)
44
44
  hash[:thickness] = material.thickness
45
45
  hash[:gas_type] = material.gasType
46
46
 
@@ -40,7 +40,7 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'EnergyWindowMaterialGasCustom'
42
42
  # set hash values from OpenStudio Object
43
- hash[:identifier] = material.nameString
43
+ hash[:identifier] = clean_name(material.nameString)
44
44
  hash[:thickness] = material.thickness
45
45
  # check if boost optional object is empty
46
46
  unless material.customConductivityCoefficientA.empty?
@@ -40,7 +40,7 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'EnergyWindowMaterialGasMixture'
42
42
  # set hash values from OpenStudio Object
43
- hash[:identifier] = material.nameString
43
+ hash[:identifier] = clean_name(material.nameString)
44
44
  hash[:thickness] = material.thickness
45
45
  hash[:gas_types] = []
46
46
  hash[:gas_fractions] = []
@@ -40,7 +40,7 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'EnergyWindowMaterialGlazing'
42
42
  # set hash values from OpenStudio Object
43
- hash[:identifier] = material.nameString
43
+ hash[:identifier] = clean_name(material.nameString)
44
44
  hash[:thickness] = material.thickness
45
45
  hash[:solar_transmittance] = material.solarTransmittance
46
46
  # check if boost optional object is empty
@@ -40,7 +40,7 @@ module Honeybee
40
40
  hash = {}
41
41
  hash[:type] = 'EnergyWindowMaterialSimpleGlazSys'
42
42
  # set hash values from OpenStudio Object
43
- hash[:identifier] = material.nameString
43
+ hash[:identifier] = clean_name(material.nameString)
44
44
  hash[:u_factor] = material.uFactor
45
45
  hash[:shgc] = material.solarHeatGainCoefficient
46
46
  # check if boost optional object is empty
@@ -46,6 +46,8 @@ require 'from_openstudio/construction/opaque'
46
46
  require 'from_openstudio/construction/window'
47
47
  require 'from_openstudio/construction/shade'
48
48
  require 'from_openstudio/construction_set'
49
+ require 'from_openstudio/schedule/type_limit'
50
+ require 'from_openstudio/schedule/ruleset'
49
51
 
50
52
  require 'openstudio'
51
53
 
@@ -131,6 +133,10 @@ module Honeybee
131
133
  hash[:materials] = materials_from_model(openstudio_model)
132
134
  hash[:construction_sets] = []
133
135
  hash[:construction_sets] = constructionsets_from_model(openstudio_model)
136
+ hash[:schedule_type_limits] = []
137
+ hash[:schedule_type_limits] = schedtypelimits_from_model(openstudio_model)
138
+ hash[:schedules] = []
139
+ hash[:schedules] = scheduleruleset_from_model(openstudio_model)
134
140
 
135
141
  hash
136
142
  end
@@ -266,5 +272,24 @@ module Honeybee
266
272
  result
267
273
  end
268
274
 
275
+ # Create HB Schedule Type Limits from OpenStudio Schedule Type Limits
276
+ def self.schedtypelimits_from_model(openstudio_model)
277
+ result = []
278
+ openstudio_model.getScheduleTypeLimitss.each do |sch_typ_lim|
279
+ result << ScheduleTypeLimit.from_schedule_type_limit(sch_typ_lim)
280
+ end
281
+
282
+ result
283
+ end
284
+
285
+ # Create HB Schedule Ruleset from OpenStudio Ruleset
286
+ def self.scheduleruleset_from_model(openstudio_model)
287
+ result = []
288
+ openstudio_model.getScheduleRulesets.each do |sch_ruleset|
289
+ result << ScheduleRulesetAbridged.from_schedule_ruleset(sch_ruleset)
290
+ end
291
+ result
292
+ end
293
+
269
294
  end # Model
270
295
  end # Honeybee
@@ -0,0 +1,114 @@
1
+ # *******************************************************************************
2
+ # Honeybee OpenStudio Gem, Copyright (c) 2020, Alliance for Sustainable
3
+ # Energy, LLC, Ladybug Tools LLC and other contributors. All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # (1) Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # (3) Neither the name of the copyright holder nor the names of any contributors
16
+ # may be used to endorse or promote products derived from this software without
17
+ # specific prior written permission from the respective party.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
20
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
23
+ # UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
24
+ # THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26
+ # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ # *******************************************************************************
31
+
32
+ require 'honeybee/schedule/ruleset'
33
+ require 'from_openstudio/model_object'
34
+
35
+ module Honeybee
36
+ class ScheduleRulesetAbridged < ModelObject
37
+
38
+ def self.from_schedule_ruleset(schedule_ruleset)
39
+ # create an empty hash
40
+ hash = {}
41
+ hash[:type] = 'ScheduleRulesetAbridged'
42
+ # set hash values from OpenStudio Object
43
+ hash[:identifier] = schedule_ruleset.nameString
44
+ # check if boost optional object is empty
45
+ hash[:default_day_schedule] = schedule_ruleset.defaultDaySchedule.nameString
46
+ hash[:summer_designday_schedule] = schedule_ruleset.summerDesignDaySchedule.nameString
47
+ hash[:winter_designday_schedule] = schedule_ruleset.winterDesignDaySchedule.nameString
48
+ hash[:holiday_schedule] = schedule_ruleset.holidaySchedule.nameString
49
+
50
+ schedule_days = [schedule_ruleset.defaultDaySchedule, schedule_ruleset.summerDesignDaySchedule, schedule_ruleset.winterDesignDaySchedule, schedule_ruleset.holidaySchedule]
51
+ hash[:day_schedules] = []
52
+ schedule_days.each do |schedule_day|
53
+ hash[:day_schedules] << ScheduleRulesetAbridged.from_day_schedule(schedule_day)
54
+ end
55
+
56
+ hash[:schedule_rules] = []
57
+ schedule_ruleset.scheduleRules.each do |schedule_rule|
58
+ hash[:schedule_rules] << ScheduleRulesetAbridged.from_schedule_rule(schedule_rule)
59
+ end
60
+
61
+ hash
62
+ end
63
+
64
+ def self.from_day_schedule(day_schedule)
65
+ hash = {}
66
+ hash[:type] = 'ScheduleDay'
67
+ hash[:identifier] = day_schedule.nameString
68
+ hash[:interpolate] = day_schedule.interpolatetoTimestep
69
+ hash[:values] = day_schedule.values
70
+ time_until = [[0,0]]
71
+ day_schedule.times.each do |time|
72
+ time_until << [time.hours, time.minutes]
73
+ end
74
+ time_until.delete_at(-1)
75
+ hash[:times] = time_until
76
+
77
+ hash
78
+ end
79
+
80
+ def self.from_schedule_rule(schedule_rule)
81
+ hash = {}
82
+ hash[:type] = 'ScheduleRuleAbridged'
83
+ hash[:schedule_day] = schedule_rule.daySchedule.nameString
84
+ hash[:apply_sunday] = schedule_rule.applySunday
85
+ hash[:apply_monday] = schedule_rule.applyMonday
86
+ hash[:apply_tuesday] = schedule_rule.applyTuesday
87
+ hash[:apply_wednesday] = schedule_rule.applyWednesday
88
+ hash[:apply_thursday] = schedule_rule.applyThursday
89
+ hash[:apply_friday] = schedule_rule.applyFriday
90
+ hash[:apply_saturday] = schedule_rule.applySaturday
91
+
92
+ #boost optional
93
+ unless schedule_rule.startDate.empty?
94
+ start_date = schedule_rule.startDate.get
95
+ hash[:start_date] = [(start_date.monthOfYear).value, start_date.dayOfMonth]
96
+ if start_date.isLeapYear
97
+ hash[:start_date] << 1
98
+ end
99
+ end
100
+
101
+ #boost optional
102
+ unless schedule_rule.endDate.empty?
103
+ end_date = schedule_rule.endDate.get
104
+ hash[:end_date] = [(end_date.monthOfYear).value, end_date.dayOfMonth]
105
+ if start_date.isLeapYear
106
+ hash[:end_date] << 1
107
+ end
108
+ end
109
+
110
+ hash
111
+ end
112
+
113
+ end # ScheduleRulesetAbridged
114
+ end # Honeybee
@@ -0,0 +1,63 @@
1
+ # *******************************************************************************
2
+ # Honeybee OpenStudio Gem, Copyright (c) 2020, Alliance for Sustainable
3
+ # Energy, LLC, Ladybug Tools LLC and other contributors. All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # (1) Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # (3) Neither the name of the copyright holder nor the names of any contributors
16
+ # may be used to endorse or promote products derived from this software without
17
+ # specific prior written permission from the respective party.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
20
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
23
+ # UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
24
+ # THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26
+ # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ # *******************************************************************************
31
+
32
+ require 'honeybee/schedule/type_limit'
33
+ require 'to_openstudio/model_object'
34
+
35
+ module Honeybee
36
+ class ScheduleTypeLimit < ModelObject
37
+
38
+ def self.from_schedule_type_limit(schedule_type_limit)
39
+ # create an empty hash
40
+ hash = {}
41
+ hash[:type] = 'ScheduleTypeLimit'
42
+ # set hash values from OpenStudio Object
43
+ hash[:identifier] = schedule_type_limit.nameString
44
+ # check if boost optional object is empty
45
+ unless schedule_type_limit.lowerLimitValue.empty?
46
+ hash[:lower_limit] = schedule_type_limit.lowerLimitValue.get
47
+ end
48
+ # check if boost optional object is empty
49
+ unless schedule_type_limit.upperLimitValue.empty?
50
+ hash[:upper_limit] = schedule_type_limit.upperLimitValue.get
51
+ end
52
+ # check if boost optional object is empty
53
+ unless schedule_type_limit.numericType.empty?
54
+ numeric_type = schedule_type_limit.numericType.get
55
+ hash[:numeric_type] = numeric_type.titleize
56
+ end
57
+ hash[:unit_type] = schedule_type_limit.unitType
58
+
59
+ hash
60
+ end
61
+
62
+ end # ScheduleTypeLimit
63
+ end # Honeybee
@@ -63,4 +63,8 @@ require 'from_openstudio/material/window_simpleglazsys'
63
63
  # extend the simulation objects
64
64
  require 'from_openstudio/simulation/design_day'
65
65
  require 'from_openstudio/simulation/parameter_model'
66
- require 'from_openstudio/simulation/simulation_output'
66
+ require 'from_openstudio/simulation/simulation_output'
67
+
68
+ # extend the schedule objects
69
+ require 'from_openstudio/schedule/type_limit'
70
+ require 'from_openstudio/schedule/ruleset'
@@ -54,7 +54,10 @@
54
54
  "identifier": "Generic Single Pane",
55
55
  "materials": [
56
56
  "Generic Clear Glass"
57
- ]
57
+ ],
58
+ "u_factor": 5.731373,
59
+ "shgc": 0.824407,
60
+ "vt": 0.88
58
61
  },
59
62
  {
60
63
  "type": "ShadeConstruction",
@@ -170,7 +173,10 @@
170
173
  "Generic Low-e Glass",
171
174
  "Generic Window Air Gap",
172
175
  "Generic Clear Glass"
173
- ]
176
+ ],
177
+ "u_factor": 1.687787,
178
+ "shgc": 0.43651,
179
+ "vt": 0.635473
174
180
  },
175
181
  {
176
182
  "type": "OpaqueConstructionAbridged",
@@ -51,6 +51,7 @@ module Honeybee
51
51
  @@extension ||= Extension.new
52
52
  @@schema ||= @@extension.schema
53
53
  @@standards ||= @@extension.standards
54
+ $simple_window_cons = false
54
55
 
55
56
  @hash = hash
56
57
  @type = @hash[:type]
@@ -36,6 +36,13 @@ module Honeybee
36
36
 
37
37
  attr_reader :errors, :warnings
38
38
 
39
+ @@encoding_options = {
40
+ :invalid => :replace, # Replace invalid byte sequences
41
+ :undef => :replace, # Replace anything not defined in ASCII
42
+ :replace => '', # Use a blank for those replacements
43
+ :universal_newline => true # Always break lines with \n
44
+ }
45
+
39
46
  def method_missing(sym, *args)
40
47
  name = sym.to_s
41
48
  aname = name.sub('=', '')
@@ -99,13 +106,14 @@ module Honeybee
99
106
  end
100
107
 
101
108
  # remove illegal characters in identifier
102
- def self.clean_display_name(str)
103
- str.gsub(/[^[:ascii:]]/, '')
109
+ def self.clean_name(str)
110
+ ascii = str.encode(Encoding.find('ASCII'), @@encoding_options)
104
111
  end
105
112
 
106
113
  # remove illegal characters in identifier
107
114
  def self.clean_identifier(str)
108
- str.gsub(/[^.A-Za-z0-9_-]/, '_').gsub(' ', '_')
115
+ encode_str = str.encode(Encoding.find('ASCII'), @@encoding_options)
116
+ encode_str.gsub(/[^.A-Za-z0-9_-]/, '_').gsub(' ', '_')
109
117
  end
110
118
 
111
119
 
@@ -86,6 +86,7 @@ class FromHoneybeeModelToGbxml < OpenStudio::Measure::ModelMeasure
86
86
  return false
87
87
  end
88
88
  honeybee_model = Honeybee::Model.read_from_disk(model_json)
89
+ $simple_window_cons = true
89
90
  STDOUT.flush
90
91
  os_model = honeybee_model.to_openstudio_model(model)
91
92
  STDOUT.flush
@@ -50,16 +50,25 @@ module Honeybee
50
50
  # create material vector
51
51
  os_materials = OpenStudio::Model::MaterialVector.new
52
52
  # loop through each layer and add to material vector
53
- if @hash.key?(:layers)
54
- mat_key = :layers
53
+ if $simple_window_cons && @hash[:u_factor]
54
+ os_simple_glazing = OpenStudio::Model::SimpleGlazing.new(openstudio_model)
55
+ os_simple_glazing.setName(@hash[:identifier] + '_SimpleGlazSys')
56
+ os_simple_glazing.setUFactor(@hash[:u_factor])
57
+ os_simple_glazing.setSolarHeatGainCoefficient(@hash[:shgc])
58
+ os_simple_glazing.setVisibleTransmittance(@hash[:vt])
59
+ os_materials << os_simple_glazing
55
60
  else
56
- mat_key = :materials
57
- end
58
- @hash[mat_key].each do |material_identifier|
59
- material = openstudio_model.getMaterialByName(material_identifier)
60
- unless material.empty?
61
- os_material = material.get
62
- os_materials << os_material
61
+ if @hash.key?(:layers)
62
+ mat_key = :layers
63
+ else
64
+ mat_key = :materials
65
+ end
66
+ @hash[mat_key].each do |material_identifier|
67
+ material = openstudio_model.getMaterialByName(material_identifier)
68
+ unless material.empty?
69
+ os_material = material.get
70
+ os_materials << os_material
71
+ end
63
72
  end
64
73
  end
65
74
  os_construction.setLayers(os_materials)
@@ -77,7 +77,7 @@ module Honeybee
77
77
 
78
78
  # assign the flow exponent if it's specified
79
79
  if vent_crack[:flow_exponent]
80
- os_crack. setAirMassFlowExponent(vent_crack[:flow_exponent])
80
+ os_crack.setAirMassFlowExponent(vent_crack[:flow_exponent])
81
81
  end
82
82
 
83
83
  # if it's a Surface boundary condition ensure the neighbor is not written as a duplicate
@@ -105,6 +105,14 @@ module Honeybee
105
105
  os_thermal_zone.setMultiplier(@hash[:multiplier])
106
106
  end
107
107
 
108
+ # assign the geometry properties if they exist
109
+ if @hash[:ceiling_height]
110
+ os_thermal_zone.setCeilingHeight(@hash[:ceiling_height])
111
+ end
112
+ if @hash[:volume]
113
+ os_thermal_zone.setVolume(@hash[:volume])
114
+ end
115
+
108
116
  # assign the story
109
117
  if @hash[:story] # the users has specified the name of the story
110
118
  story = openstudio_model.getBuildingStoryByName(@hash[:story])
@@ -349,8 +357,10 @@ module Honeybee
349
357
  if sub_f.adjacentSubSurface.empty? # not an interior window that's already in the AFN
350
358
  vent_open = VentilationOpening.new(opening)
351
359
  open_fac = vent_open.to_openstudio_afn(openstudio_model, sub_f)
352
- operable_subfs << sub_f
353
- opening_factors << open_fac
360
+ unless open_fac.nil? # nil is used for horizontal exterior skylights
361
+ operable_subfs << sub_f
362
+ opening_factors << open_fac
363
+ end
354
364
  end
355
365
  end
356
366
  end
@@ -128,43 +128,69 @@ module Honeybee
128
128
  end
129
129
 
130
130
  def to_openstudio_afn(openstudio_model, parent)
131
- # process the flow_coefficient_closed and set it to a very small number if it's 0
131
+ # get the tilt and BC of the parent so that we can use the correct AFN object
132
+ srf_tilt = parent.tilt.to_f * (180 / Math::PI)
133
+ srf_bc = parent.outsideBoundaryCondition.to_s
134
+
135
+ # process the flow_coefficient_closed and flow exponent
132
136
  if @hash[:flow_coefficient_closed] and @hash[:flow_coefficient_closed] != 0
133
137
  flow_coefficient = @hash[:flow_coefficient_closed]
134
138
  else
135
139
  flow_coefficient = 1.0e-09 # set it to a very small number
136
140
  end
137
-
138
- # create the simple opening object for the Aperture or Door using default values
139
141
  flow_exponent = defaults[:flow_exponent_closed][:default].to_f
140
- two_way_thresh = defaults[:two_way_threshold][:default].to_f
141
- discharge_coeff = defaults[:discharge_coefficient][:default].to_f
142
- os_opening = OpenStudio::Model::AirflowNetworkSimpleOpening.new(
143
- openstudio_model, flow_coefficient, flow_exponent, two_way_thresh, discharge_coeff)
144
-
145
- # assign the flow exponent when the opening is closed
146
- if @hash[:flow_exponent_closed]
147
- os_opening.setAirMassFlowExponentWhenOpeningisClosed(@hash[:flow_exponent_closed])
148
- end
149
- # assign the minimum difference for two-way flow
150
- if @hash[:two_way_threshold]
151
- os_opening.setMinimumDensityDifferenceforTwoWayFlow(@hash[:two_way_threshold])
152
- end
153
- # assign the discharge coefficient
154
- if @hash[:discharge_coefficient]
155
- os_opening.setDischargeCoefficient(@hash[:discharge_coefficient])
156
- end
157
-
158
- # create the AirflowNetworkSurface
159
- os_afn_srf = parent.getAirflowNetworkSurface(os_opening)
160
142
 
161
- # assign the opening area
143
+ # process the opening area
162
144
  if @hash[:fraction_area_operable]
163
145
  open_fac = @hash[:fraction_area_operable]
164
146
  else
165
147
  open_fac = defaults[:fraction_area_operable][:default]
166
148
  end
167
- os_afn_srf.setWindowDoorOpeningFactorOrCrackFactor(open_fac)
149
+
150
+ # create an opening obj
151
+ if srf_tilt < 10 || srf_tilt > 170
152
+ if srf_bc == 'Outdoors'
153
+ # create a crack object to represent an exterior in-operable horizontal skylight
154
+ open_fac = nil
155
+ os_opening = OpenStudio::Model::AirflowNetworkCrack.new(
156
+ openstudio_model, flow_coefficient, flow_exponent, $afn_reference_crack)
157
+ else
158
+ # create a HorizontalOpening object to represent the interior horizontal window
159
+ discharge_coeff = defaults[:discharge_coefficient][:default].to_f
160
+ if srf_tilt < 10
161
+ slope_ang = 90 - srf_tilt
162
+ else
163
+ slope_ang = 90 - (180 - srf_tilt)
164
+ end
165
+ os_opening = OpenStudio::Model::AirflowNetworkHorizontalOpening .new(
166
+ openstudio_model, flow_coefficient, flow_exponent, slope_ang, discharge_coeff)
167
+ end
168
+ else
169
+ # create the simple opening object for the Aperture or Door using default values
170
+ two_way_thresh = defaults[:two_way_threshold][:default].to_f
171
+ discharge_coeff = defaults[:discharge_coefficient][:default].to_f
172
+ os_opening = OpenStudio::Model::AirflowNetworkSimpleOpening.new(
173
+ openstudio_model, flow_coefficient, flow_exponent, two_way_thresh, discharge_coeff)
174
+
175
+ # assign the flow exponent when the opening is closed
176
+ if @hash[:flow_exponent_closed]
177
+ os_opening.setAirMassFlowExponentWhenOpeningisClosed(@hash[:flow_exponent_closed])
178
+ end
179
+ # assign the minimum difference for two-way flow
180
+ if @hash[:two_way_threshold]
181
+ os_opening.setMinimumDensityDifferenceforTwoWayFlow(@hash[:two_way_threshold])
182
+ end
183
+ # assign the discharge coefficient
184
+ if @hash[:discharge_coefficient]
185
+ os_opening.setDischargeCoefficient(@hash[:discharge_coefficient])
186
+ end
187
+ end
188
+
189
+ # create the AirflowNetworkSurface and assign the opening factor
190
+ os_afn_srf = parent.getAirflowNetworkSurface(os_opening)
191
+ unless open_fac.nil?
192
+ os_afn_srf.setWindowDoorOpeningFactorOrCrackFactor(open_fac)
193
+ end
168
194
 
169
195
  open_fac
170
196
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: honeybee-openstudio
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.22.2
4
+ version: 2.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tanushree Charan
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2021-08-20 00:00:00.000000000 Z
14
+ date: 2021-09-15 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -89,14 +89,14 @@ dependencies:
89
89
  requirements:
90
90
  - - "~>"
91
91
  - !ruby/object:Gem::Version
92
- version: 0.54.0
92
+ version: 1.15.0
93
93
  type: :development
94
94
  prerelease: false
95
95
  version_requirements: !ruby/object:Gem::Requirement
96
96
  requirements:
97
97
  - - "~>"
98
98
  - !ruby/object:Gem::Version
99
- version: 0.54.0
99
+ version: 1.15.0
100
100
  - !ruby/object:Gem::Dependency
101
101
  name: json_pure
102
102
  requirement: !ruby/object:Gem::Requirement
@@ -117,28 +117,28 @@ dependencies:
117
117
  requirements:
118
118
  - - '='
119
119
  - !ruby/object:Gem::Version
120
- version: 0.4.2
120
+ version: 0.4.3
121
121
  type: :runtime
122
122
  prerelease: false
123
123
  version_requirements: !ruby/object:Gem::Requirement
124
124
  requirements:
125
125
  - - '='
126
126
  - !ruby/object:Gem::Version
127
- version: 0.4.2
127
+ version: 0.4.3
128
128
  - !ruby/object:Gem::Dependency
129
129
  name: openstudio-standards
130
130
  requirement: !ruby/object:Gem::Requirement
131
131
  requirements:
132
132
  - - "~>"
133
133
  - !ruby/object:Gem::Version
134
- version: 0.2.13
134
+ version: 0.2.14
135
135
  type: :runtime
136
136
  prerelease: false
137
137
  version_requirements: !ruby/object:Gem::Requirement
138
138
  requirements:
139
139
  - - "~>"
140
140
  - !ruby/object:Gem::Version
141
- version: 0.2.13
141
+ version: 0.2.14
142
142
  description: Library and measures for translating between Honeybee JSON schema and
143
143
  OpenStudio Model schema (OSM).
144
144
  email:
@@ -187,6 +187,8 @@ files:
187
187
  - lib/from_openstudio/material/window_simpleglazsys.rb
188
188
  - lib/from_openstudio/model.rb
189
189
  - lib/from_openstudio/model_object.rb
190
+ - lib/from_openstudio/schedule/ruleset.rb
191
+ - lib/from_openstudio/schedule/type_limit.rb
190
192
  - lib/from_openstudio/simulation/design_day.rb
191
193
  - lib/from_openstudio/simulation/parameter_model.rb
192
194
  - lib/from_openstudio/simulation/simulation_output.rb