honeybee-openstudio 1.8.1

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 (71) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +32 -0
  4. data/.releaserc.json +7 -0
  5. data/.travis.yml +41 -0
  6. data/Gemfile +18 -0
  7. data/LICENSE.md +23 -0
  8. data/README.md +95 -0
  9. data/Rakefile +21 -0
  10. data/doc_templates/LICENSE.md +23 -0
  11. data/doc_templates/copyright_erb.txt +32 -0
  12. data/doc_templates/copyright_js.txt +5 -0
  13. data/doc_templates/copyright_ruby.txt +30 -0
  14. data/honeybee-openstudio.gemspec +35 -0
  15. data/lib/files/Honeybee.rb +113 -0
  16. data/lib/files/honeybee_workflow.osw +48 -0
  17. data/lib/files/urbanopt_Gemfile +32 -0
  18. data/lib/from_honeybee.rb +86 -0
  19. data/lib/from_honeybee/_openapi/model.json +8127 -0
  20. data/lib/from_honeybee/_openapi/simulation-parameter.json +843 -0
  21. data/lib/from_honeybee/construction/air.rb +65 -0
  22. data/lib/from_honeybee/construction/opaque.rb +77 -0
  23. data/lib/from_honeybee/construction/shade.rb +108 -0
  24. data/lib/from_honeybee/construction/window.rb +80 -0
  25. data/lib/from_honeybee/construction_set.rb +278 -0
  26. data/lib/from_honeybee/extension.rb +109 -0
  27. data/lib/from_honeybee/geometry/aperture.rb +167 -0
  28. data/lib/from_honeybee/geometry/door.rb +160 -0
  29. data/lib/from_honeybee/geometry/face.rb +163 -0
  30. data/lib/from_honeybee/geometry/room.rb +392 -0
  31. data/lib/from_honeybee/geometry/shade.rb +89 -0
  32. data/lib/from_honeybee/hvac/ideal_air.rb +150 -0
  33. data/lib/from_honeybee/load/electric_equipment.rb +96 -0
  34. data/lib/from_honeybee/load/gas_equipment.rb +97 -0
  35. data/lib/from_honeybee/load/infiltration.rb +95 -0
  36. data/lib/from_honeybee/load/lighting.rb +98 -0
  37. data/lib/from_honeybee/load/people.rb +100 -0
  38. data/lib/from_honeybee/load/setpoint_humidistat.rb +75 -0
  39. data/lib/from_honeybee/load/setpoint_thermostat.rb +71 -0
  40. data/lib/from_honeybee/load/ventilation.rb +96 -0
  41. data/lib/from_honeybee/material/opaque.rb +94 -0
  42. data/lib/from_honeybee/material/opaque_no_mass.rb +94 -0
  43. data/lib/from_honeybee/material/window_blind.rb +238 -0
  44. data/lib/from_honeybee/material/window_gas.rb +76 -0
  45. data/lib/from_honeybee/material/window_gas_custom.rb +118 -0
  46. data/lib/from_honeybee/material/window_gas_mixture.rb +79 -0
  47. data/lib/from_honeybee/material/window_glazing.rb +166 -0
  48. data/lib/from_honeybee/material/window_shade.rb +160 -0
  49. data/lib/from_honeybee/material/window_simpleglazsys.rb +73 -0
  50. data/lib/from_honeybee/model.rb +434 -0
  51. data/lib/from_honeybee/model_object.rb +110 -0
  52. data/lib/from_honeybee/program_type.rb +124 -0
  53. data/lib/from_honeybee/schedule/fixed_interval.rb +115 -0
  54. data/lib/from_honeybee/schedule/ruleset.rb +164 -0
  55. data/lib/from_honeybee/schedule/type_limit.rb +88 -0
  56. data/lib/from_honeybee/simulation/designday.rb +105 -0
  57. data/lib/from_honeybee/simulation/extension.rb +46 -0
  58. data/lib/from_honeybee/simulation/parameter.rb +277 -0
  59. data/lib/from_honeybee/version.rb +34 -0
  60. data/lib/measures/.gitkeep +0 -0
  61. data/lib/measures/from_honeybee_model/LICENSE.md +27 -0
  62. data/lib/measures/from_honeybee_model/README.md +32 -0
  63. data/lib/measures/from_honeybee_model/measure.rb +91 -0
  64. data/lib/measures/from_honeybee_model/measure.xml +103 -0
  65. data/lib/measures/from_honeybee_model/tests/from_honeybee_model_test.rb +126 -0
  66. data/lib/measures/from_honeybee_simulation_parameter/LICENSE.md +27 -0
  67. data/lib/measures/from_honeybee_simulation_parameter/README.md +32 -0
  68. data/lib/measures/from_honeybee_simulation_parameter/measure.rb +95 -0
  69. data/lib/measures/from_honeybee_simulation_parameter/measure.xml +91 -0
  70. data/lib/measures/from_honeybee_simulation_parameter/tests/from_honeybee_simulation_parameter_test.rb +109 -0
  71. metadata +243 -0
@@ -0,0 +1,166 @@
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 'from_honeybee/model_object'
33
+
34
+ require 'openstudio'
35
+
36
+ module FromHoneybee
37
+ class EnergyWindowMaterialGlazing < ModelObject
38
+ attr_reader :errors, :warnings
39
+
40
+ def initialize(hash = {})
41
+ super(hash)
42
+ end
43
+
44
+ def defaults
45
+ @@schema[:components][:schemas][:EnergyWindowMaterialGlazing][:properties]
46
+ end
47
+
48
+ def find_existing_openstudio_object(openstudio_model)
49
+ object = openstudio_model.getStandardGlazingByName(@hash[:identifier])
50
+ return object.get if object.is_initialized
51
+ nil
52
+ end
53
+
54
+ def to_openstudio(openstudio_model)
55
+ # create openstudio standard glazing object and set identifier
56
+ os_glazing = OpenStudio::Model::StandardGlazing.new(openstudio_model)
57
+ os_glazing.setName(@hash[:identifier])
58
+
59
+ # assign thickness
60
+ if @hash[:thickness]
61
+ os_glazing.setThickness(@hash[:thickness])
62
+ else
63
+ os_glazing.setThickness(defaults[:thickness][:default])
64
+ end
65
+
66
+ # assign solar transmittance
67
+ if @hash[:solar_transmittance]
68
+ os_glazing.setSolarTransmittanceatNormalIncidence(@hash[:solar_transmittance])
69
+ else
70
+ os_glazing.setSolarTransmittanceatNormalIncidence(
71
+ defaults[:solar_transmittance][:default])
72
+ end
73
+
74
+ # assign front solar reflectance
75
+ if @hash[:solar_reflectance]
76
+ os_glazing.setFrontSideSolarReflectanceatNormalIncidence(@hash[:solar_reflectance])
77
+ else
78
+ os_glazing.setFrontSideSolarReflectanceatNormalIncidence(
79
+ defaults[:solar_reflectance][:default])
80
+ end
81
+
82
+ # assign back solar reflectance
83
+ if @hash[:solar_reflectance_back]
84
+ os_glazing.setBackSideSolarReflectanceatNormalIncidence(@hash[:solar_reflectance_back])
85
+ else
86
+ os_glazing.setBackSideSolarReflectanceatNormalIncidence(
87
+ defaults[:solar_reflectance_back][:default])
88
+ end
89
+
90
+ # assign visible transmittance at normal incidence
91
+ if @hash[:visible_transmittance]
92
+ os_glazing.setVisibleTransmittanceatNormalIncidence(@hash[:visible_transmittance])
93
+ else
94
+ os_glazing.setVisibleTransmittanceatNormalIncidence(
95
+ defaults[:visible_transmittance][:default])
96
+ end
97
+
98
+ # assign front side visible reflectance
99
+ if @hash[:visible_reflectance]
100
+ os_glazing.setFrontSideVisibleReflectanceatNormalIncidence(@hash[:visible_reflectance])
101
+ else
102
+ os_glazing.setFrontSideVisibleReflectanceatNormalIncidence(
103
+ defaults[:visible_reflectance][:default])
104
+ end
105
+
106
+ # assign back side visible reflectance
107
+ if @hash[:visible_reflectance_back]
108
+ os_glazing.setBackSideVisibleReflectanceatNormalIncidence(@hash[:visible_reflectance_back])
109
+ else
110
+ os_glazing.setBackSideVisibleReflectanceatNormalIncidence(
111
+ defaults[:visible_reflectance_back][:default])
112
+ end
113
+
114
+ # assign infrared transmittance
115
+ if @hash[:infrared_transmittance]
116
+ os_glazing.setInfraredTransmittanceatNormalIncidence(@hash[:infrared_transmittance])
117
+ else
118
+ os_glazing.setInfraredTransmittanceatNormalIncidence(
119
+ defaults[:infrared_transmittance][:default])
120
+ end
121
+
122
+ # assign front side emissivity
123
+ if @hash[:emissivity]
124
+ os_glazing.setFrontSideInfraredHemisphericalEmissivity(@hash[:emissivity])
125
+ else
126
+ os_glazing.setFrontSideInfraredHemisphericalEmissivity(
127
+ defaults[:emissivity][:default])
128
+ end
129
+
130
+ # assign back side emissivity
131
+ if @hash[:emissivity_back]
132
+ os_glazing.setBackSideInfraredHemisphericalEmissivity(@hash[:emissivity_back])
133
+ else
134
+ os_glazing.setBackSideInfraredHemisphericalEmissivity(
135
+ defaults[:emissivity_back][:default])
136
+ end
137
+
138
+ # assign conductivity
139
+ if @hash[:conductivity]
140
+ os_glazing.setThermalConductivity(@hash[:conductivity])
141
+ else
142
+ os_glazing.setThermalConductivity(
143
+ defaults[:conductivity_glass][:default])
144
+ end
145
+
146
+ # assign dirt correction
147
+ if @hash[:dirt_correction]
148
+ os_glazing.setDirtCorrectionFactorforSolarandVisibleTransmittance(@hash[:dirt_correction])
149
+ else
150
+ os_glazing.setDirtCorrectionFactorforSolarandVisibleTransmittance(
151
+ defaults[:dirt_correction][:default])
152
+ end
153
+
154
+ # assign solar diffusing
155
+ if @hash[:solar_diffusing] == false
156
+ os_glazing.setSolarDiffusing(false)
157
+ elsif @hash[:solar_diffusing] == true
158
+ os_glazing.setSolarDiffusing(true)
159
+ else
160
+ os_glazing.setSolarDiffusing(defaults[:solar_diffusing][:default])
161
+ end
162
+
163
+ os_glazing
164
+ end
165
+ end # EnergyWindowMaterialGlazing
166
+ end # FromHoneybee
@@ -0,0 +1,160 @@
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 'from_honeybee/model_object'
33
+
34
+ require 'openstudio'
35
+
36
+ module FromHoneybee
37
+ class EnergyWindowMaterialShade < ModelObject
38
+ attr_reader :errors, :warnings
39
+
40
+ def initialize(hash)
41
+ super(hash)
42
+ end
43
+
44
+ def defaults
45
+ @@schema[:components][:schemas][:EnergyWindowMaterialShade][:properties]
46
+ end
47
+
48
+ def find_existing_openstudio_object(openstudio_model)
49
+ object = openstudio_model.getShadeByName(@hash[:identifier])
50
+ return object.get if object.is_initialized
51
+ nil
52
+ end
53
+
54
+ def to_openstudio(openstudio_model)
55
+ # create openstudio shade object
56
+ os_shade_mat = OpenStudio::Model::Shade.new(openstudio_model)
57
+ os_shade_mat.setName(@hash[:identifier])
58
+
59
+ # assign solar transmittance
60
+ if @hash[:solar_transmittance]
61
+ os_shade_mat.setSolarTransmittance(@hash[:solar_transmittance])
62
+ else
63
+ os_shade_mat.setSolarTransmittance(defaults[:solar_transmittance][:default])
64
+ end
65
+
66
+ # assign solar reflectance
67
+ if @hash[:solar_reflectance]
68
+ os_shade_mat.setSolarReflectance(@hash[:solar_reflectance])
69
+ else
70
+ os_shade_mat.setSolarReflectance(defaults[:solar_reflectance][:default])
71
+ end
72
+
73
+ # assign visible transmittance
74
+ if @hash[:visible_transmittance]
75
+ os_shade_mat.setVisibleTransmittance(@hash[:visible_transmittance])
76
+ else
77
+ os_shade_mat.setVisibleTransmittance(defaults[:visible_transmittance][:default])
78
+ end
79
+
80
+ # assign visible reflectance
81
+ if @hash[:visible_reflectance]
82
+ os_shade_mat.setVisibleReflectance(@hash[:visible_reflectance])
83
+ else
84
+ os_shade_mat.setVisibleReflectance(defaults[:visible_reflectance][:default])
85
+ end
86
+
87
+ # assign emissivity
88
+ if @hash[:emissivity]
89
+ os_shade_mat.setThermalHemisphericalEmissivity(@hash[:emissivity])
90
+ else
91
+ os_shade_mat.setThermalHemisphericalEmissivity(defaults[:emissivity][:default])
92
+ end
93
+
94
+ # assign infrared transmittance
95
+ if @hash[:infrared_transmittance]
96
+ os_shade_mat.setThermalTransmittance(@hash[:infrared_transmittance])
97
+ else
98
+ os_shade_mat.setThermalTransmittance(defaults[:infrared_transmittance][:default])
99
+ end
100
+
101
+ # assign thickness
102
+ if @hash[:thickness]
103
+ os_shade_mat.setThickness(@hash[:thickness])
104
+ else
105
+ os_shade_mat.setThickness(defaults[:thickness][:default])
106
+ end
107
+
108
+ # assign conductivity
109
+ if @hash[:conductivity]
110
+ os_shade_mat.setConductivity(@hash[:conductivity])
111
+ else
112
+ os_shade_mat.setConductivity(defaults[:conductivity][:default])
113
+ end
114
+
115
+ # assign distance to glass
116
+ if @hash[:distance_to_glass]
117
+ os_shade_mat.setShadetoGlassDistance(@hash[:distance_to_glass])
118
+ else
119
+ os_shade_mat.setShadetoGlassDistance(defaults[:distance_to_glass][:default])
120
+ end
121
+
122
+ # assign top opening multiplier
123
+ if @hash[:top_opening_multiplier]
124
+ os_shade_mat.setTopOpeningMultiplier(@hash[:top_opening_multiplier])
125
+ else
126
+ os_shade_mat.setTopOpeningMultiplier(defaults[:top_opening_multiplier][:default])
127
+ end
128
+
129
+ # assign bottom opening multiplier
130
+ if @hash[:bottom_opening_multiplier]
131
+ os_shade_mat.setBottomOpeningMultiplier(@hash[:bottom_opening_multiplier])
132
+ else
133
+ os_shade_mat.setBottomOpeningMultiplier(defaults[:bottom_opening_multiplier][:default])
134
+ end
135
+
136
+ # assign left opening multiplier
137
+ if @hash[:left_opening_multiplier]
138
+ os_shade_mat.setLeftSideOpeningMultiplier(@hash[:left_opening_multiplier])
139
+ else
140
+ os_shade_mat.setLeftSideOpeningMultiplier(defaults[:left_opening_multiplier][:default])
141
+ end
142
+
143
+ # assign right opening muliplier
144
+ if @hash[:right_opening_multiplier]
145
+ os_shade_mat.setRightSideOpeningMultiplier(@hash[:right_opening_multiplier])
146
+ else
147
+ os_shade_mat.setRightSideOpeningMultiplier(defaults[:right_opening_multiplier][:default])
148
+ end
149
+
150
+ # assign airflow permeability
151
+ if @hash[:airflow_permeability]
152
+ os_shade_mat.setAirflowPermeability(@hash[:airflow_permeability])
153
+ else
154
+ os_shade_mat.setAirflowPermeability(defaults[:airflow_permeability][:default])
155
+ end
156
+
157
+ os_shade_mat
158
+ end
159
+ end # EnergyWindowMaterialShade
160
+ end # FromHoneybee
@@ -0,0 +1,73 @@
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 'from_honeybee/model_object'
33
+
34
+ require 'openstudio'
35
+
36
+ module FromHoneybee
37
+ class EnergyWindowMaterialSimpleGlazSys < ModelObject
38
+ attr_reader :errors, :warnings
39
+
40
+ def initialize(hash = {})
41
+ super(hash)
42
+ end
43
+
44
+ def defaults
45
+ @@schema[:components][:schemas][:EnergyWindowMaterialSimpleGlazSys][:properties]
46
+ end
47
+
48
+ def find_existing_openstudio_object(openstudio_model)
49
+ object = openstudio_model.getSimpleGlazingByName(@hash[:identifier])
50
+ return object.get if object.is_initialized
51
+ nil
52
+ end
53
+
54
+ def to_openstudio(openstudio_model)
55
+ # create simple glazing openstudio object
56
+ os_simple_glazing = OpenStudio::Model::SimpleGlazing.new(openstudio_model)
57
+ os_simple_glazing.setName(@hash[:identifier])
58
+ os_simple_glazing.setUFactor(@hash[:u_factor])
59
+ os_simple_glazing.setSolarHeatGainCoefficient(@hash[:shgc])
60
+
61
+ # assign visible transmittance
62
+ if @hash[:vt]
63
+ os_simple_glazing.setVisibleTransmittance(@hash[:vt])
64
+ else
65
+ os_simple_glazing.setVisibleTransmittance(defaults[:vt][:default])
66
+ end
67
+
68
+ os_simple_glazing
69
+ end
70
+
71
+
72
+ end # EnergyWindowMaterialSimpleGlazSys
73
+ end # FromHoneybee
@@ -0,0 +1,434 @@
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
+ # import the core objects from which everything inherits
33
+ require 'from_honeybee/extension'
34
+ require 'from_honeybee/model_object'
35
+
36
+ # import the compound objects that house the other objects
37
+ require 'from_honeybee/construction_set'
38
+ require 'from_honeybee/program_type'
39
+
40
+ # import the geometry objects
41
+ require 'from_honeybee/geometry/shade'
42
+ require 'from_honeybee/geometry/door'
43
+ require 'from_honeybee/geometry/aperture'
44
+ require 'from_honeybee/geometry/face'
45
+ require 'from_honeybee/geometry/room'
46
+
47
+ # import the HVAC objects
48
+ require 'from_honeybee/hvac/ideal_air'
49
+
50
+ # import the construction objects
51
+ require 'from_honeybee/construction/opaque'
52
+ require 'from_honeybee/construction/window'
53
+ require 'from_honeybee/construction/shade'
54
+ require 'from_honeybee/construction/air'
55
+
56
+ # import the material objects
57
+ require 'from_honeybee/material/opaque'
58
+ require 'from_honeybee/material/opaque_no_mass'
59
+ require 'from_honeybee/material/window_gas'
60
+ require 'from_honeybee/material/window_gas_mixture'
61
+ require 'from_honeybee/material/window_gas_custom'
62
+ require 'from_honeybee/material/window_blind'
63
+ require 'from_honeybee/material/window_glazing'
64
+ require 'from_honeybee/material/window_shade'
65
+ require 'from_honeybee/material/window_simpleglazsys'
66
+
67
+ # import the schedule objects
68
+ require 'from_honeybee/schedule/type_limit'
69
+ require 'from_honeybee/schedule/fixed_interval'
70
+ require 'from_honeybee/schedule/ruleset'
71
+
72
+ # import the load objects
73
+ require 'from_honeybee/load/setpoint_thermostat'
74
+ require 'from_honeybee/load/setpoint_humidistat'
75
+
76
+ require 'openstudio'
77
+
78
+
79
+ module FromHoneybee
80
+ class Model
81
+ attr_reader :errors, :warnings
82
+
83
+ # Read Ladybug Energy Model JSON from disk
84
+ def self.read_from_disk(file)
85
+ hash = nil
86
+ File.open(File.join(file), 'r') do |f|
87
+ hash = JSON.parse(f.read, symbolize_names: true)
88
+ end
89
+ Model.new(hash)
90
+ end
91
+
92
+ # Load ModelObject from symbolized hash
93
+ def initialize(hash)
94
+ # initialize class variable @@extension only once
95
+ @@extension ||= Extension.new
96
+ @@schema ||= @@extension.schema
97
+
98
+ @hash = hash
99
+ @type = @hash[:type]
100
+ raise 'Unknown model type' if @type.nil?
101
+ raise "Incorrect model type '#{@type}'" unless @type == 'Model'
102
+
103
+ end
104
+
105
+ # check if the model is valid
106
+ def valid?
107
+ if Gem.loaded_specs.has_key?("json-schema")
108
+ return validation_errors.empty?
109
+ else
110
+ return true
111
+ end
112
+ end
113
+
114
+ # return detailed model validation errors
115
+ def validation_errors
116
+ if Gem.loaded_specs.has_key?("json-schema")
117
+ require 'json-schema'
118
+ JSON::Validator.fully_validate(@@schema, @hash)
119
+ end
120
+ end
121
+
122
+ def defaults
123
+ @@schema[:components][:schemas][:ModelEnergyProperties][:properties]
124
+ end
125
+
126
+ # convert to openstudio model, clears errors and warnings
127
+ def to_openstudio_model(openstudio_model=nil, log_report=true)
128
+ @errors = []
129
+ @warnings = []
130
+
131
+ if log_report
132
+ puts 'Starting Model translation from Honeybee to OpenStudio'
133
+ end
134
+
135
+ @openstudio_model = if openstudio_model
136
+ openstudio_model
137
+ else
138
+ OpenStudio::Model::Model.new
139
+ end
140
+
141
+ # create all openstudio objects in the model
142
+ create_openstudio_objects(log_report)
143
+
144
+ if log_report
145
+ puts 'Done with Model translation!'
146
+ end
147
+
148
+ @openstudio_model
149
+ end
150
+
151
+ private
152
+
153
+ # create OpenStudio objects in the OpenStudio model
154
+ def create_openstudio_objects(log_report=true)
155
+ # assign a standards building type so that David's measures can run
156
+ building = @openstudio_model.getBuilding
157
+ building.setStandardsBuildingType('MediumOffice')
158
+
159
+ # create all of the non-geometric model elements
160
+ if log_report
161
+ puts 'Translating Materials'
162
+ end
163
+ create_materials
164
+
165
+ if log_report
166
+ puts 'Translating Constructions'
167
+ end
168
+ create_constructions
169
+
170
+ if log_report
171
+ puts 'Translating ConstructionSets'
172
+ end
173
+ create_construction_set
174
+ create_global_construction_set
175
+
176
+ if log_report
177
+ puts 'Translating Schedules'
178
+ end
179
+ create_schedule_type_limits
180
+ create_schedules
181
+
182
+ if log_report
183
+ puts 'Translating ProgramTypes'
184
+ end
185
+ create_program_types
186
+
187
+ # create all of the model geometry
188
+ if log_report
189
+ puts 'Translating Room Geometry'
190
+ end
191
+ create_rooms
192
+
193
+ if log_report
194
+ puts 'Translating Context Shade Geometry'
195
+ end
196
+ create_orphaned_shades
197
+ create_orphaned_faces
198
+ create_orphaned_apertures
199
+ create_orphaned_doors
200
+
201
+ # create the hvac systems
202
+ if log_report
203
+ puts 'Translating HVAC Systems'
204
+ end
205
+ create_hvacs
206
+ end
207
+
208
+ def create_materials
209
+ @hash[:properties][:energy][:materials].each do |material|
210
+ material_type = material[:type]
211
+
212
+ case material_type
213
+ when 'EnergyMaterial'
214
+ material_object = EnergyMaterial.new(material)
215
+ when 'EnergyMaterialNoMass'
216
+ material_object = EnergyMaterialNoMass.new(material)
217
+ when 'EnergyWindowMaterialGas'
218
+ material_object = EnergyWindowMaterialGas.new(material)
219
+ when 'EnergyWindowMaterialGasCustom'
220
+ material_object = EnergyWindowMaterialGasCustom.new(material)
221
+ when 'EnergyWindowMaterialSimpleGlazSys'
222
+ material_object = EnergyWindowMaterialSimpleGlazSys.new(material)
223
+ when 'EnergyWindowMaterialBlind'
224
+ material_object = EnergyWindowMaterialBlind.new(material)
225
+ when 'EnergyWindowMaterialGlazing'
226
+ material_object = EnergyWindowMaterialGlazing.new(material)
227
+ when 'EnergyWindowMaterialShade'
228
+ material_object = EnergyWindowMaterialShade.new(material)
229
+ else
230
+ raise "Unknown material type #{material_type}"
231
+ end
232
+ material_object.to_openstudio(@openstudio_model)
233
+ end
234
+ end
235
+
236
+ def create_constructions
237
+ $air_boundary_hash = Hash.new # hash to track any air boundary constructions
238
+
239
+ @hash[:properties][:energy][:constructions].each do |construction|
240
+ identifier = construction[:identifier]
241
+ construction_type = construction[:type]
242
+
243
+ case construction_type
244
+ when 'OpaqueConstructionAbridged'
245
+ construction_object = OpaqueConstructionAbridged.new(construction)
246
+ when 'WindowConstructionAbridged'
247
+ construction_object = WindowConstructionAbridged.new(construction)
248
+ when 'ShadeConstruction'
249
+ construction_object = ShadeConstruction.new(construction)
250
+ when 'AirBoundaryConstructionAbridged'
251
+ construction_object = AirBoundaryConstructionAbridged.new(construction)
252
+ $air_boundary_hash[construction[:identifier]] = construction
253
+ else
254
+ raise "Unknown construction type #{construction_type}."
255
+ end
256
+ construction_object.to_openstudio(@openstudio_model)
257
+ end
258
+ end
259
+
260
+ def create_construction_set
261
+ if @hash[:properties][:energy][:construction_sets]
262
+ @hash[:properties][:energy][:construction_sets].each do |construction_set|
263
+ construction_set_object = ConstructionSetAbridged.new(construction_set)
264
+ construction_set_object.to_openstudio(@openstudio_model)
265
+ end
266
+ end
267
+ end
268
+
269
+ def create_global_construction_set
270
+ if @hash[:properties][:energy][:global_construction_set]
271
+ construction_id = @hash[:properties][:energy][:global_construction_set]
272
+ construction = @openstudio_model.getDefaultConstructionSetByName(construction_id)
273
+ unless construction.empty?
274
+ openstudio_construction = construction.get
275
+ end
276
+ @openstudio_model.getBuilding.setDefaultConstructionSet(openstudio_construction)
277
+ end
278
+ end
279
+
280
+ def create_schedule_type_limits
281
+ if @hash[:properties][:energy][:schedule_type_limits]
282
+ @hash[:properties][:energy][:schedule_type_limits].each do |schedule_type_limit|
283
+ schedule_type_limit_object = ScheduleTypeLimit.new(schedule_type_limit)
284
+ schedule_type_limit_object.to_openstudio(@openstudio_model)
285
+ end
286
+ end
287
+ end
288
+
289
+ def create_schedules
290
+ if @hash[:properties][:energy][:schedules]
291
+ @hash[:properties][:energy][:schedules].each do |schedule|
292
+ schedule_type = schedule[:type]
293
+
294
+ case schedule_type
295
+ when 'ScheduleRulesetAbridged'
296
+ schedule_object = ScheduleRulesetAbridged.new(schedule)
297
+ when 'ScheduleFixedIntervalAbridged'
298
+ schedule_object = ScheduleFixedIntervalAbridged.new(schedule)
299
+ else
300
+ raise("Unknown schedule type #{schedule_type}.")
301
+ end
302
+ schedule_object.to_openstudio(@openstudio_model)
303
+
304
+ end
305
+ end
306
+ end
307
+
308
+ def create_program_types
309
+ if @hash[:properties][:energy][:program_types]
310
+ $programtype_setpoint_hash = Hash.new # hash to track Setpoint objects
311
+ @hash[:properties][:energy][:program_types].each do |space_type|
312
+ space_type_object = ProgramTypeAbridged.new(space_type)
313
+ space_type_object.to_openstudio(@openstudio_model)
314
+ end
315
+ end
316
+ end
317
+
318
+ def create_rooms
319
+ if @hash[:rooms]
320
+ $air_mxing_array = [] # list to track any air mixing between Rooms
321
+
322
+ @hash[:rooms].each do |room|
323
+ room_object = Room.new(room)
324
+ openstudio_room = room_object.to_openstudio(@openstudio_model)
325
+
326
+ # for rooms with setpoint objects definied in the ProgramType, make a new thermostat
327
+ if room[:properties][:energy][:program_type] && !room[:properties][:energy][:setpoint]
328
+ thermal_zone = openstudio_room.thermalZone()
329
+ unless thermal_zone.empty?
330
+ thermal_zone_object = thermal_zone.get
331
+ program_type_id = room[:properties][:energy][:program_type]
332
+ setpoint_hash = $programtype_setpoint_hash[program_type_id]
333
+ if not setpoint_hash.nil? # program type has no setpoint
334
+ thermostat_object = SetpointThermostat.new(setpoint_hash)
335
+ openstudio_thermostat = thermostat_object.to_openstudio(@openstudio_model)
336
+ thermal_zone_object.setThermostatSetpointDualSetpoint(openstudio_thermostat)
337
+ if setpoint_hash[:humidifying_schedule] or setpoint_hash[:dehumidifying_schedule]
338
+ humidistat_object = ZoneControlHumidistat.new(setpoint_hash)
339
+ openstudio_humidistat = humidistat_object.to_openstudio(@openstudio_model)
340
+ thermal_zone_object.setZoneControlHumidistat(openstudio_humidistat)
341
+ end
342
+ end
343
+ end
344
+ end
345
+ end
346
+
347
+ # Create mixing objects between Rooms
348
+ $air_mxing_array.each do |air_mix_props|
349
+ zone_mixing = OpenStudio::Model::ZoneMixing.new(air_mix_props[0])
350
+ zone_mixing.setDesignFlowRate(air_mix_props[1])
351
+ flow_sch_ref = @openstudio_model.getScheduleByName(air_mix_props[2])
352
+ unless flow_sch_ref.empty?
353
+ flow_sched = flow_sch_ref.get
354
+ zone_mixing.setSchedule(flow_sched)
355
+ end
356
+ source_zone_ref = @openstudio_model.getThermalZoneByName(air_mix_props[3])
357
+ unless source_zone_ref.empty?
358
+ source_zone = source_zone_ref.get
359
+ zone_mixing.setSourceZone(source_zone)
360
+ end
361
+ end
362
+ end
363
+ end
364
+
365
+
366
+ def create_orphaned_shades
367
+ if @hash[:orphaned_shades]
368
+ shading_surface_group = OpenStudio::Model::ShadingSurfaceGroup.new(@openstudio_model)
369
+ shading_surface_group.setShadingSurfaceType('Building')
370
+ @hash[:orphaned_shades].each do |shade|
371
+ shade_object = Shade.new(shade)
372
+ openstudio_shade = shade_object.to_openstudio(@openstudio_model)
373
+ openstudio_shade.setShadingSurfaceGroup(shading_surface_group)
374
+ end
375
+ end
376
+ end
377
+
378
+ def create_orphaned_faces
379
+ if @hash[:orphaned_faces]
380
+ raise "Orphaned Faces are not translatable to OpenStudio."
381
+ end
382
+ end
383
+
384
+ def create_orphaned_apertures
385
+ if @hash[:orphaned_apertures]
386
+ raise "Orphaned Apertures are not translatable to OpenStudio."
387
+ end
388
+ end
389
+
390
+ def create_orphaned_doors
391
+ if @hash[:orphaned_doors]
392
+ raise "Orphaned Doors are not translatable to OpenStudio."
393
+ end
394
+ end
395
+
396
+ def create_hvacs
397
+ if @hash[:properties][:energy][:hvacs]
398
+ # gather all of the hashes of the HVACs
399
+ hvac_hashes = Hash.new
400
+ @hash[:properties][:energy][:hvacs].each do |hvac|
401
+ hvac_hashes[hvac[:identifier]] = hvac
402
+ hvac_hashes[hvac[:identifier]]['rooms'] = []
403
+ end
404
+ # loop through the rooms and trach which are assigned to each HVAC
405
+ if @hash[:rooms]
406
+ @hash[:rooms].each do |room|
407
+ if room[:properties][:energy][:hvac]
408
+ hvac_hashes[room[:properties][:energy][:hvac]]['rooms'] << room[:identifier]
409
+ end
410
+ end
411
+ end
412
+
413
+ hvac_hashes.each_value do |hvac|
414
+ system_type = hvac[:type]
415
+ case system_type
416
+ when 'IdealAirSystemAbridged'
417
+ ideal_air_system = IdealAirSystemAbridged.new(hvac)
418
+ os_ideal_air_system = ideal_air_system.to_openstudio(@openstudio_model)
419
+ hvac['rooms'].each do |room_id|
420
+ zone_get = @openstudio_model.getThermalZoneByName(room_id)
421
+ unless zone_get.empty?
422
+ os_thermal_zone = zone_get.get
423
+ os_ideal_air_system.addToThermalZone(os_thermal_zone)
424
+ end
425
+ end
426
+ end
427
+ end
428
+ end
429
+ end
430
+
431
+ #TODO: create runlog for errors.
432
+
433
+ end # Model
434
+ end # FromHoneybee