honeybee-openstudio 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 (130) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yaml +88 -0
  3. data/.gitignore +33 -0
  4. data/.releaserc.json +7 -0
  5. data/Gemfile +14 -0
  6. data/LICENSE.md +23 -0
  7. data/README.md +95 -0
  8. data/Rakefile +16 -0
  9. data/doc_templates/LICENSE.md +23 -0
  10. data/doc_templates/README.md.erb +42 -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 +38 -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_openstudio.rb +49 -0
  19. data/lib/from_openstudio/geometry/aperture.rb +136 -0
  20. data/lib/from_openstudio/geometry/door.rb +136 -0
  21. data/lib/from_openstudio/geometry/face.rb +174 -0
  22. data/lib/from_openstudio/geometry/room.rb +121 -0
  23. data/lib/from_openstudio/geometry/shade.rb +87 -0
  24. data/lib/from_openstudio/model.rb +123 -0
  25. data/lib/from_openstudio/model_object.rb +43 -0
  26. data/lib/from_openstudio/simulation/design_day.rb +123 -0
  27. data/lib/from_openstudio/simulation/parameter_model.rb +93 -0
  28. data/lib/from_openstudio/simulation/simulation_output.rb +67 -0
  29. data/lib/honeybee.rb +93 -0
  30. data/lib/honeybee/_defaults/energy_default.json +1682 -0
  31. data/lib/honeybee/_defaults/model.json +11311 -0
  32. data/lib/honeybee/_defaults/simulation-parameter.json +973 -0
  33. data/lib/honeybee/construction/air.rb +42 -0
  34. data/lib/honeybee/construction/opaque.rb +42 -0
  35. data/lib/honeybee/construction/shade.rb +42 -0
  36. data/lib/honeybee/construction/window.rb +51 -0
  37. data/lib/honeybee/construction/windowshade.rb +43 -0
  38. data/lib/honeybee/construction_set.rb +42 -0
  39. data/lib/honeybee/extension.rb +129 -0
  40. data/lib/honeybee/geometry/aperture.rb +42 -0
  41. data/lib/honeybee/geometry/door.rb +42 -0
  42. data/lib/honeybee/geometry/face.rb +48 -0
  43. data/lib/honeybee/geometry/room.rb +56 -0
  44. data/lib/honeybee/geometry/shade.rb +42 -0
  45. data/lib/honeybee/hvac/ideal_air.rb +42 -0
  46. data/lib/honeybee/hvac/template.rb +73 -0
  47. data/lib/honeybee/load/electric_equipment.rb +42 -0
  48. data/lib/honeybee/load/gas_equipment.rb +42 -0
  49. data/lib/honeybee/load/infiltration.rb +42 -0
  50. data/lib/honeybee/load/lighting.rb +43 -0
  51. data/lib/honeybee/load/people.rb +42 -0
  52. data/lib/honeybee/load/setpoint_humidistat.rb +46 -0
  53. data/lib/honeybee/load/setpoint_thermostat.rb +46 -0
  54. data/lib/honeybee/load/ventilation.rb +42 -0
  55. data/lib/honeybee/material/opaque.rb +42 -0
  56. data/lib/honeybee/material/opaque_no_mass.rb +42 -0
  57. data/lib/honeybee/material/window_blind.rb +42 -0
  58. data/lib/honeybee/material/window_gas.rb +42 -0
  59. data/lib/honeybee/material/window_gas_custom.rb +42 -0
  60. data/lib/honeybee/material/window_gas_mixture.rb +42 -0
  61. data/lib/honeybee/material/window_glazing.rb +42 -0
  62. data/lib/honeybee/material/window_shade.rb +42 -0
  63. data/lib/honeybee/material/window_simpleglazsys.rb +42 -0
  64. data/lib/honeybee/model.rb +87 -0
  65. data/lib/honeybee/model_object.rb +108 -0
  66. data/lib/honeybee/program_type.rb +56 -0
  67. data/lib/honeybee/schedule/fixed_interval.rb +42 -0
  68. data/lib/honeybee/schedule/ruleset.rb +42 -0
  69. data/lib/honeybee/schedule/type_limit.rb +42 -0
  70. data/lib/honeybee/simulation/design_day.rb +42 -0
  71. data/lib/honeybee/simulation/parameter_model.rb +86 -0
  72. data/lib/honeybee/simulation/simulation_output.rb +42 -0
  73. data/lib/honeybee/ventcool/control.rb +42 -0
  74. data/lib/honeybee/ventcool/opening.rb +46 -0
  75. data/lib/honeybee/ventcool/simulation.rb +42 -0
  76. data/lib/measures/.gitkeep +0 -0
  77. data/lib/measures/from_honeybee_model/LICENSE.md +23 -0
  78. data/lib/measures/from_honeybee_model/README.md +32 -0
  79. data/lib/measures/from_honeybee_model/measure.rb +91 -0
  80. data/lib/measures/from_honeybee_model/measure.xml +80 -0
  81. data/lib/measures/from_honeybee_model/tests/from_honeybee_model_test.rb +126 -0
  82. data/lib/measures/from_honeybee_simulation_parameter/LICENSE.md +23 -0
  83. data/lib/measures/from_honeybee_simulation_parameter/README.md +32 -0
  84. data/lib/measures/from_honeybee_simulation_parameter/measure.rb +95 -0
  85. data/lib/measures/from_honeybee_simulation_parameter/measure.xml +86 -0
  86. data/lib/measures/from_honeybee_simulation_parameter/tests/from_honeybee_simulation_parameter_test.rb +109 -0
  87. data/lib/to_openstudio.rb +92 -0
  88. data/lib/to_openstudio/construction/air.rb +56 -0
  89. data/lib/to_openstudio/construction/opaque.rb +67 -0
  90. data/lib/to_openstudio/construction/shade.rb +99 -0
  91. data/lib/to_openstudio/construction/window.rb +70 -0
  92. data/lib/to_openstudio/construction/windowshade.rb +196 -0
  93. data/lib/to_openstudio/construction_set.rb +266 -0
  94. data/lib/to_openstudio/geometry/aperture.rb +157 -0
  95. data/lib/to_openstudio/geometry/door.rb +150 -0
  96. data/lib/to_openstudio/geometry/face.rb +178 -0
  97. data/lib/to_openstudio/geometry/room.rb +442 -0
  98. data/lib/to_openstudio/geometry/shade.rb +79 -0
  99. data/lib/to_openstudio/hvac/Model.hvac.rb +641 -0
  100. data/lib/to_openstudio/hvac/ideal_air.rb +141 -0
  101. data/lib/to_openstudio/hvac/template.rb +169 -0
  102. data/lib/to_openstudio/load/electric_equipment.rb +87 -0
  103. data/lib/to_openstudio/load/gas_equipment.rb +88 -0
  104. data/lib/to_openstudio/load/infiltration.rb +86 -0
  105. data/lib/to_openstudio/load/lighting.rb +89 -0
  106. data/lib/to_openstudio/load/people.rb +91 -0
  107. data/lib/to_openstudio/load/setpoint_humidistat.rb +66 -0
  108. data/lib/to_openstudio/load/setpoint_thermostat.rb +62 -0
  109. data/lib/to_openstudio/load/ventilation.rb +87 -0
  110. data/lib/to_openstudio/material/opaque.rb +85 -0
  111. data/lib/to_openstudio/material/opaque_no_mass.rb +85 -0
  112. data/lib/to_openstudio/material/window_blind.rb +229 -0
  113. data/lib/to_openstudio/material/window_gas.rb +67 -0
  114. data/lib/to_openstudio/material/window_gas_custom.rb +108 -0
  115. data/lib/to_openstudio/material/window_gas_mixture.rb +70 -0
  116. data/lib/to_openstudio/material/window_glazing.rb +157 -0
  117. data/lib/to_openstudio/material/window_shade.rb +151 -0
  118. data/lib/to_openstudio/material/window_simpleglazsys.rb +64 -0
  119. data/lib/to_openstudio/model.rb +497 -0
  120. data/lib/to_openstudio/model_object.rb +52 -0
  121. data/lib/to_openstudio/program_type.rb +104 -0
  122. data/lib/to_openstudio/schedule/fixed_interval.rb +105 -0
  123. data/lib/to_openstudio/schedule/ruleset.rb +164 -0
  124. data/lib/to_openstudio/schedule/type_limit.rb +76 -0
  125. data/lib/to_openstudio/simulation/design_day.rb +96 -0
  126. data/lib/to_openstudio/simulation/parameter_model.rb +243 -0
  127. data/lib/to_openstudio/ventcool/control.rb +185 -0
  128. data/lib/to_openstudio/ventcool/opening.rb +189 -0
  129. data/lib/to_openstudio/ventcool/simulation.rb +101 -0
  130. metadata +301 -0
@@ -0,0 +1,96 @@
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/simulation/design_day'
33
+
34
+ require 'to_openstudio/model_object'
35
+
36
+ module Honeybee
37
+ class DesignDay
38
+
39
+ def find_existing_openstudio_object(openstudio_model)
40
+ object = openstudio_model.getDesignDayByName(@hash[:name])
41
+ return object.get if object.is_initialized
42
+ nil
43
+ end
44
+
45
+ def to_openstudio(openstudio_model)
46
+ # create the DesignDay object
47
+ os_des_day = OpenStudio::Model::DesignDay.new(openstudio_model)
48
+ os_des_day.setName(@hash[:name])
49
+ os_des_day.setDayType(@hash[:day_type])
50
+
51
+ # set the DryBulbCondition properties
52
+ os_des_day.setMaximumDryBulbTemperature(@hash[:dry_bulb_condition][:dry_bulb_max])
53
+ os_des_day.setDailyDryBulbTemperatureRange(@hash[:dry_bulb_condition][:dry_bulb_range])
54
+
55
+ # set the HumidityCondition properties
56
+ os_des_day.setHumidityIndicatingType(@hash[:humidity_condition][:humidity_type])
57
+ os_des_day.setHumidityIndicatingConditionsAtMaximumDryBulb(@hash[:humidity_condition][:humidity_value])
58
+ if @hash[:humidity_condition][:barometric_pressure]
59
+ os_des_day.setBarometricPressure(@hash[:humidity_condition][:barometric_pressure])
60
+ end
61
+ if @hash[:humidity_condition][:rain]
62
+ os_des_day.setRainIndicator(@hash[:humidity_condition][:rain])
63
+ end
64
+ if @hash[:humidity_condition][:snow_on_ground]
65
+ os_des_day.setSnowIndicator(@hash[:humidity_condition][:snow_on_ground])
66
+ end
67
+
68
+ # set the WindCondition properties
69
+ os_des_day.setWindSpeed(@hash[:wind_condition][:wind_speed])
70
+ if @hash[:wind_condition][:wind_direction]
71
+ os_des_day.setWindDirection(@hash[:wind_condition][:wind_direction])
72
+ end
73
+
74
+ # set the SkyCondition properties
75
+ os_des_day.setMonth(@hash[:sky_condition][:date][0])
76
+ os_des_day.setDayOfMonth(@hash[:sky_condition][:date][1])
77
+ os_des_day.setSolarModelIndicator(@hash[:sky_condition][:type])
78
+ if @hash[:sky_condition][:daylight_savings]
79
+ os_des_day.setDaylightSavingTimeIndicator(@hash[:sky_condition][:daylight_savings])
80
+ end
81
+
82
+ # ASHRAEClearSky SkyCondition
83
+ if @hash[:sky_condition][:type] == "ASHRAEClearSky"
84
+ os_des_day.setSkyClearness(@hash[:sky_condition][:clearness])
85
+ end
86
+
87
+ # ASHRAETau SkyCondition
88
+ if @hash[:sky_condition][:type] == "ASHRAETau"
89
+ os_des_day.setAshraeTaub(@hash[:sky_condition][:tau_b])
90
+ os_des_day.setAshraeTaud(@hash[:sky_condition][:tau_d])
91
+ end
92
+
93
+ os_des_day
94
+ end
95
+ end # DesignDay
96
+ end # Honeybee
@@ -0,0 +1,243 @@
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/simulation/parameter_model'
33
+
34
+ require 'openstudio'
35
+
36
+ module Honeybee
37
+ class SimulationParameter
38
+
39
+ # convert to openstudio model, clears errors and warnings
40
+ def to_openstudio_model(openstudio_model=nil, log_report=false)
41
+ @errors = []
42
+ @warnings = []
43
+
44
+ if log_report
45
+ puts 'Starting SimulationParameter translation from Honeybee to OpenStudio'
46
+ end
47
+ @openstudio_model = if openstudio_model
48
+ openstudio_model
49
+ else
50
+ OpenStudio::Model::Model.new
51
+ end
52
+
53
+ create_openstudio_objects
54
+
55
+ if log_report
56
+ puts 'Done with SimulationParameter translation!'
57
+ end
58
+
59
+ @openstudio_model
60
+ end
61
+
62
+ def create_openstudio_objects
63
+ # get the defaults for each sub-object
64
+ simct_defaults = defaults[:SimulationControl][:properties]
65
+ shdw_defaults = defaults[:ShadowCalculation][:properties]
66
+ siz_defaults = defaults[:SizingParameter][:properties]
67
+ out_defaults = defaults[:SimulationOutput][:properties]
68
+ runper_defaults = defaults[:RunPeriod][:properties]
69
+ simpar_defaults = defaults[:SimulationParameter][:properties]
70
+
71
+ # set defaults for the Model's SimulationControl object
72
+ os_sim_control = @openstudio_model.getSimulationControl
73
+ os_sim_control.setDoZoneSizingCalculation(simct_defaults[:do_zone_sizing][:default])
74
+ os_sim_control.setDoSystemSizingCalculation(simct_defaults[:do_system_sizing][:default])
75
+ os_sim_control.setDoPlantSizingCalculation(simct_defaults[:do_plant_sizing][:default])
76
+ os_sim_control.setRunSimulationforWeatherFileRunPeriods(simct_defaults[:run_for_run_periods][:default])
77
+ os_sim_control.setRunSimulationforSizingPeriods(simct_defaults[:run_for_sizing_periods][:default])
78
+ os_sim_control.setSolarDistribution(shdw_defaults[:solar_distribution][:default])
79
+
80
+ # override any SimulationControl defaults with lodaded JSON
81
+ if @hash[:simulation_control]
82
+ unless @hash[:simulation_control][:do_zone_sizing].nil?
83
+ os_sim_control.setDoZoneSizingCalculation(@hash[:simulation_control][:do_zone_sizing])
84
+ end
85
+ unless @hash[:simulation_control][:do_system_sizing].nil?
86
+ os_sim_control.setDoSystemSizingCalculation(@hash[:simulation_control][:do_system_sizing])
87
+ end
88
+ unless @hash[:simulation_control][:do_plant_sizing].nil?
89
+ os_sim_control.setDoPlantSizingCalculation(@hash[:simulation_control][:do_plant_sizing])
90
+ end
91
+ unless @hash[:simulation_control][:run_for_run_periods].nil?
92
+ os_sim_control.setRunSimulationforWeatherFileRunPeriods(@hash[:simulation_control][:run_for_run_periods])
93
+ end
94
+ unless @hash[:simulation_control][:run_for_sizing_periods].nil?
95
+ os_sim_control.setRunSimulationforSizingPeriods(@hash[:simulation_control][:run_for_sizing_periods])
96
+ end
97
+ end
98
+
99
+ # set defaults for the Model's ShadowCalculation object
100
+ os_shadow_calc = @openstudio_model.getShadowCalculation
101
+ os_shadow_calc.setShadingCalculationMethod(
102
+ shdw_defaults[:calculation_method][:default])
103
+ os_shadow_calc.setShadingCalculationUpdateFrequencyMethod(
104
+ shdw_defaults[:calculation_update_method][:default])
105
+ os_shadow_calc.setShadingCalculationUpdateFrequency(
106
+ shdw_defaults[:calculation_frequency][:default])
107
+ os_shadow_calc.setMaximumFiguresInShadowOverlapCalculations(
108
+ shdw_defaults[:maximum_figures][:default])
109
+
110
+ # override any ShadowCalculation defaults with lodaded JSON
111
+ if @hash[:shadow_calculation]
112
+ if @hash[:shadow_calculation][:calculation_method]
113
+ os_shadow_calc.setShadingCalculationMethod(
114
+ @hash[:shadow_calculation][:calculation_method])
115
+ end
116
+ if @hash[:shadow_calculation][:calculation_update_method]
117
+ os_shadow_calc.setShadingCalculationUpdateFrequencyMethod(
118
+ @hash[:shadow_calculation][:calculation_update_method])
119
+ end
120
+ if @hash[:shadow_calculation][:calculation_frequency]
121
+ os_shadow_calc.setShadingCalculationUpdateFrequency(
122
+ @hash[:shadow_calculation][:calculation_frequency])
123
+ end
124
+ if @hash[:shadow_calculation][:maximum_figures]
125
+ os_shadow_calc.setMaximumFiguresInShadowOverlapCalculations(
126
+ @hash[:shadow_calculation][:maximum_figures])
127
+ end
128
+ if @hash[:shadow_calculation][:solar_distribution]
129
+ os_sim_control.setSolarDistribution(
130
+ @hash[:shadow_calculation][:solar_distribution])
131
+ end
132
+ end
133
+
134
+ # set defaults for the Model's SizingParameter object
135
+ os_sizing_par = @openstudio_model.getSizingParameters
136
+ os_sizing_par.setHeatingSizingFactor(siz_defaults[:heating_factor][:default])
137
+ os_sizing_par.setCoolingSizingFactor(siz_defaults[:cooling_factor][:default])
138
+
139
+ # override any SizingParameter defaults with lodaded JSON
140
+ if @hash[:sizing_parameter]
141
+ if @hash[:sizing_parameter][:heating_factor]
142
+ os_sizing_par.setHeatingSizingFactor(@hash[:sizing_parameter][:heating_factor])
143
+ end
144
+ if @hash[:sizing_parameter][:cooling_factor]
145
+ os_sizing_par.setCoolingSizingFactor(@hash[:sizing_parameter][:cooling_factor])
146
+ end
147
+ # set any design days
148
+ if @hash[:sizing_parameter][:design_days]
149
+ @hash[:sizing_parameter][:design_days].each do |des_day|
150
+ des_day_object = DesignDay.new(des_day)
151
+ os_des_day = des_day_object.to_openstudio(@openstudio_model)
152
+ end
153
+ end
154
+ end
155
+
156
+ # set Outputs for the simulation
157
+ if @hash[:output]
158
+ if @hash[:output][:outputs]
159
+ @hash[:output][:outputs].each do |output|
160
+ os_output = OpenStudio::Model::OutputVariable.new(output, @openstudio_model)
161
+ if @hash[:output][:reporting_frequency]
162
+ os_output.setReportingFrequency(@hash[:output][:reporting_frequency])
163
+ else
164
+ os_output.setReportingFrequency(out_defaults[:reporting_frequency][:default])
165
+ end
166
+ end
167
+ end
168
+ if @hash[:output][:summary_reports]
169
+ os_report = @openstudio_model.getOutputTableSummaryReports
170
+ @hash[:output][:summary_reports].each do |report|
171
+ os_report.addSummaryReport(report)
172
+ end
173
+ end
174
+ end
175
+
176
+ # set defaults for the year description
177
+ year_description = @openstudio_model.getYearDescription
178
+ year_description.setDayofWeekforStartDay(runper_defaults[:start_day_of_week][:default])
179
+
180
+ # set up the simulation RunPeriod
181
+ if @hash[:run_period]
182
+ # set the leap year
183
+ if @hash[:run_period][:leap_year]
184
+ year_description.setIsLeapYear(@hash[:run_period][:leap_year])
185
+ end
186
+
187
+ # set the start day of the week
188
+ if @hash[:run_period][:start_day_of_week]
189
+ year_description.setDayofWeekforStartDay(@hash[:run_period][:start_day_of_week])
190
+ end
191
+
192
+ # set the run preiod start and end dates
193
+ openstudio_runperiod = @openstudio_model.getRunPeriod
194
+ openstudio_runperiod.setBeginMonth(@hash[:run_period][:start_date][0])
195
+ openstudio_runperiod.setBeginDayOfMonth(@hash[:run_period][:start_date][1])
196
+ openstudio_runperiod.setEndMonth(@hash[:run_period][:end_date][0])
197
+ openstudio_runperiod.setEndDayOfMonth(@hash[:run_period][:end_date][1])
198
+
199
+ # set the daylight savings time
200
+ if @hash[:run_period][:daylight_saving_time]
201
+ os_dl_saving = @openstudio_model.getRunPeriodControlDaylightSavingTime
202
+ os_dl_saving.setStartDate(
203
+ OpenStudio::MonthOfYear.new(@hash[:run_period][:daylight_saving_time][:start_date][0]),
204
+ @hash[:run_period][:daylight_saving_time][:start_date][1])
205
+ os_dl_saving.setEndDate(
206
+ OpenStudio::MonthOfYear.new(@hash[:run_period][:daylight_saving_time][:end_date][0]),
207
+ @hash[:run_period][:daylight_saving_time][:end_date][1])
208
+ end
209
+
210
+ # Set the holidays
211
+ if @hash[:run_period][:holidays]
212
+ @hash[:run_period][:holidays].each do |hol|
213
+ os_hol = OpenStudio::Model::RunPeriodControlSpecialDays.new(
214
+ OpenStudio::MonthOfYear.new(hol[0]), hol[1], @openstudio_model)
215
+ os_hol.setDuration(1)
216
+ os_hol.setSpecialDayType('Holiday')
217
+ end
218
+ end
219
+ end
220
+
221
+ # set the simulation timestep
222
+ os_timestep = @openstudio_model.getTimestep
223
+ if @hash[:timestep]
224
+ os_timestep.setNumberOfTimestepsPerHour(@hash[:timestep])
225
+ else
226
+ os_timestep.setNumberOfTimestepsPerHour(simpar_defaults[:timestep][:default])
227
+ end
228
+
229
+ # assign the north
230
+ if @hash[:north_angle]
231
+ @openstudio_model.getBuilding.setNorthAxis(-@hash[:north_angle])
232
+ end
233
+
234
+ # assign the terrain
235
+ os_site = @openstudio_model.getSite
236
+ os_site.setTerrain(simpar_defaults[:terrain_type][:default])
237
+ if @hash[:terrain_type]
238
+ os_site.setTerrain(@hash[:terrain_type])
239
+ end
240
+ end
241
+
242
+ end #SimulationParameter
243
+ end #Honeybee
@@ -0,0 +1,185 @@
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/ventcool/opening'
33
+
34
+ require 'to_openstudio/model_object'
35
+
36
+ module Honeybee
37
+ class VentilationControlAbridged
38
+ @@outdoor_node = nil
39
+ @@program_manager = nil
40
+ @@sensor_count = 1
41
+ @@actuator_count = 1
42
+ @@program_count = 1
43
+
44
+ def get_outdoor_node(openstudio_model)
45
+ # get the EMS sensor for the outdoor node if it exists or generate it if it doesn't
46
+ if @@outdoor_node.nil?
47
+ out_var = OpenStudio::Model::OutputVariable.new(
48
+ 'Site Outdoor Air Drybulb Temperature', openstudio_model)
49
+ out_var.setReportingFrequency('Timestep')
50
+ out_var.setKeyValue('Environment')
51
+ @@outdoor_node = OpenStudio::Model::EnergyManagementSystemSensor.new(
52
+ openstudio_model, out_var)
53
+ @@outdoor_node.setName('Outdoor_Sensor')
54
+ end
55
+ @@outdoor_node
56
+ end
57
+
58
+ def get_program_manager(openstudio_model)
59
+ # get the EMS Program Manager for all window opening if it exists or generate it if it doesn't
60
+ if @@program_manager.nil?
61
+ @@program_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(
62
+ openstudio_model)
63
+ @@program_manager.setName('Temperature_Controlled_Window_Opening')
64
+ @@program_manager.setCallingPoint('BeginTimestepBeforePredictor')
65
+ end
66
+ @@program_manager
67
+ end
68
+
69
+ def replace_ems_special_characters(ems_variable_name)
70
+ # remove special characters from an name to be used as an EMS variable
71
+ new_name = ems_variable_name.to_s
72
+ new_name.gsub!(/[^A-Za-z]/, '')
73
+ new_name
74
+ end
75
+
76
+ def to_openstudio(openstudio_model, parent_zone, vent_opening_surfaces, vent_opening_factors)
77
+ # Get the outdoor temperature sensor and the room air temperature sensor
78
+ out_air_temp = get_outdoor_node(openstudio_model)
79
+ in_var = OpenStudio::Model::OutputVariable.new('Zone Air Temperature', openstudio_model)
80
+ in_var.setReportingFrequency('Timestep')
81
+ zone_name = parent_zone.name
82
+ os_zone_name = 'Indoor'
83
+ unless zone_name.empty?
84
+ os_zone_name = zone_name.get
85
+ in_var.setKeyValue(os_zone_name)
86
+ end
87
+ in_air_temp = OpenStudio::Model::EnergyManagementSystemSensor.new(openstudio_model, in_var)
88
+ in_sensor_name = replace_ems_special_characters(os_zone_name) + '_Sensor' + @@sensor_count.to_s
89
+ @@sensor_count = @@sensor_count + 1
90
+ in_air_temp.setName(in_sensor_name)
91
+
92
+ # set up a schedule sensor if there's a schedule specified
93
+ if @hash[:schedule]
94
+ vent_sch = openstudio_model.getScheduleByName(@hash[:schedule])
95
+ unless vent_sch.empty? # schedule not specified
96
+ sch_var = OpenStudio::Model::OutputVariable.new('Schedule Value', openstudio_model)
97
+ sch_var.setReportingFrequency('Timestep')
98
+ sch_var.setKeyValue(@hash[:schedule])
99
+ sch_sens = OpenStudio::Model::EnergyManagementSystemSensor.new(openstudio_model, sch_var)
100
+ sch_sensor_name = replace_ems_special_characters(os_zone_name) + '_Sensor' + @@sensor_count.to_s
101
+ @@sensor_count = @@sensor_count + 1
102
+ sch_sens.setName(sch_sensor_name)
103
+ end
104
+ end
105
+
106
+ # create the actuators for each of the operaable windows
107
+ actuator_names = []
108
+ vent_opening_surfaces.each do |vent_srf|
109
+ window_act = OpenStudio::Model::EnergyManagementSystemActuator.new(
110
+ vent_srf, 'AirFlow Network Window/Door Opening', 'Venting Opening Factor')
111
+ vent_srf_name = vent_srf.name
112
+ unless vent_srf_name.empty?
113
+ act_name = replace_ems_special_characters(vent_srf_name.get) + \
114
+ '_OpenFactor' + @@actuator_count.to_s
115
+ @@actuator_count = @@actuator_count + 1
116
+ window_act.setName(act_name)
117
+ actuator_names << act_name
118
+ end
119
+ end
120
+
121
+ # create the first line of the EMS Program to open each window according to the control logic
122
+ logic_statements = []
123
+ # check the minimum indoor tempertaure for ventilation
124
+ min_in = @hash[:min_indoor_temperature]
125
+ if min_in && min_in != defaults[:min_indoor_temperature][:default]
126
+ logic_statements << '(' + in_sensor_name + ' > ' + min_in.to_s + ')'
127
+ end
128
+ # check the maximum indoor tempertaure for ventilation
129
+ max_in = @hash[:max_indoor_temperature]
130
+ if max_in && max_in != defaults[:max_indoor_temperature][:default]
131
+ logic_statements << '(' + in_sensor_name + ' < ' + max_in.to_s + ')'
132
+ end
133
+ # check the minimum outdoor tempertaure for ventilation
134
+ min_out = @hash[:min_outdoor_temperature]
135
+ if min_out && min_out != defaults[:min_outdoor_temperature][:default]
136
+ logic_statements << '(Outdoor_Sensor > ' + min_out.to_s + ')'
137
+ end
138
+ # check the maximum outdoor tempertaure for ventilation
139
+ max_out = @hash[:max_outdoor_temperature]
140
+ if max_out && max_out != defaults[:max_outdoor_temperature][:default]
141
+ logic_statements << '(Outdoor_Sensor < ' + max_out.to_s + ')'
142
+ end
143
+ # check the delta tempertaure for ventilation
144
+ delta_in_out = @hash[:delta_temperature]
145
+ if delta_in_out && delta_in_out != defaults[:delta_temperature][:default]
146
+ logic_statements << '((' + in_sensor_name + ' - Outdoor_Sensor) > ' + delta_in_out.to_s + ')'
147
+ end
148
+ # check the schedule for ventilation
149
+ if sch_sensor_name
150
+ logic_statements << '(' + sch_sensor_name + ' > 0)'
151
+ end
152
+ # create the complete logic statement for opening windows
153
+ if logic_statements.empty?
154
+ complete_logic = 'IF (Outdoor_Sensor < 100)' # no logic has been provided; always open windows
155
+ else
156
+ complete_logic = 'IF ' + logic_statements.join(' && ')
157
+ end
158
+
159
+ # initialize the program and add the complete logic
160
+ ems_program = OpenStudio::Model::EnergyManagementSystemProgram.new(openstudio_model)
161
+ prog_name = replace_ems_special_characters(os_zone_name) + '_WindowOpening' + @@program_count.to_s
162
+ @@program_count = @@program_count + 1
163
+ ems_program.setName(prog_name)
164
+ ems_program.addLine(complete_logic)
165
+
166
+ # loop through each of the actuators and open each window
167
+ actuator_names.zip(vent_opening_factors).each do |act_name, open_factor|
168
+ ems_program.addLine('SET ' + act_name + ' = ' + open_factor.to_s)
169
+ end
170
+ # loop through each of the actuators and close each window
171
+ ems_program.addLine('ELSE')
172
+ actuator_names.each do |act_name|
173
+ ems_program.addLine('SET ' + act_name + ' = 0')
174
+ end
175
+ ems_program.addLine('ENDIF')
176
+
177
+ # add the program object the the global program manager for all window opening
178
+ prog_manager = get_program_manager(openstudio_model)
179
+ prog_manager.addProgram(ems_program)
180
+
181
+ ems_program
182
+ end
183
+
184
+ end #VentilationControl
185
+ end #Honeybee