honeybee-openstudio 2.15.0 → 2.16.4

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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/honeybee-openstudio.gemspec +1 -1
  3. data/lib/from_openstudio/geometry/aperture.rb +1 -1
  4. data/lib/from_openstudio/geometry/door.rb +1 -1
  5. data/lib/from_openstudio/geometry/face.rb +1 -1
  6. data/lib/from_openstudio/geometry/room.rb +1 -1
  7. data/lib/from_openstudio/geometry/shade.rb +2 -2
  8. data/lib/honeybee/_defaults/model.json +189 -294
  9. data/lib/honeybee/hvac/template.rb +1 -1
  10. data/lib/honeybee/model_object.rb +1 -1
  11. data/lib/measures/from_gbxml_model/LICENSE.md +23 -0
  12. data/lib/measures/from_gbxml_model/README.md +32 -0
  13. data/lib/measures/from_gbxml_model/measure.rb +114 -0
  14. data/lib/measures/from_gbxml_model/measure.xml +131 -0
  15. data/lib/measures/from_gbxml_model/tests/from_gbxml_model_test.rb +107 -0
  16. data/lib/measures/from_honeybee_model/README.md +1 -1
  17. data/lib/measures/from_honeybee_model_to_gbxml/LICENSE.md +23 -0
  18. data/lib/measures/from_honeybee_model_to_gbxml/README.md +32 -0
  19. data/lib/measures/from_honeybee_model_to_gbxml/measure.rb +113 -0
  20. data/lib/measures/from_honeybee_model_to_gbxml/measure.xml +88 -0
  21. data/lib/measures/from_honeybee_model_to_gbxml/tests/from_honeybee_model_to_gbxml_test.rb +105 -0
  22. data/lib/measures/from_idf_model/LICENSE.md +23 -0
  23. data/lib/measures/from_idf_model/README.md +32 -0
  24. data/lib/measures/from_idf_model/measure.rb +114 -0
  25. data/lib/measures/from_idf_model/measure.xml +110 -0
  26. data/lib/measures/from_idf_model/tests/from_idf_model_test.rb +107 -0
  27. data/lib/measures/from_openstudio_model/LICENSE.md +23 -0
  28. data/lib/measures/from_openstudio_model/README.md +32 -0
  29. data/lib/measures/from_openstudio_model/measure.rb +114 -0
  30. data/lib/measures/from_openstudio_model/measure.xml +95 -0
  31. data/lib/measures/from_openstudio_model/tests/from_openstudio_model_test.rb +107 -0
  32. data/lib/to_openstudio/hvac/template.rb +103 -11
  33. metadata +22 -2
@@ -0,0 +1,107 @@
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 'openstudio'
33
+ require 'openstudio/ruleset/ShowRunnerOutput'
34
+ require 'minitest/autorun'
35
+ require_relative '../measure.rb'
36
+ require 'fileutils'
37
+
38
+ class FromOpenstudioModel_Test < Minitest::Test
39
+ # method to apply arguments, run measure, and assert results (only populate args hash with non-default argument values)
40
+ def apply_measure_to_model(test_name, args, model_name = nil, result_value = 'Success', warnings_count = 0, info_count = nil)
41
+ # create an instance of the measure
42
+ measure = FromOpenstudioModel.new
43
+
44
+ # create an instance of a runner
45
+ runner = OpenStudio::Measure::OSRunner.new(OpenStudio::WorkflowJSON.new)
46
+
47
+ if model_name.nil?
48
+ # make an empty model
49
+ model = OpenStudio::Model::Model.new
50
+ else
51
+ # load the test model
52
+ translator = OpenStudio::OSVersion::VersionTranslator.new
53
+ path = OpenStudio::Path.new(File.dirname(__FILE__) + '/' + model_name)
54
+ model = translator.loadModel(path)
55
+ assert(!model.empty?)
56
+ model = model.get
57
+ end
58
+
59
+ # get arguments
60
+ arguments = measure.arguments(model)
61
+ argument_map = OpenStudio::Measure.convertOSArgumentVectorToMap(arguments)
62
+
63
+ # populate argument with specified hash value if specified
64
+ arguments.each do |arg|
65
+ temp_arg_var = arg.clone
66
+ if args.key?(arg.name)
67
+ assert(temp_arg_var.setValue(args[arg.name]), "could not set #{arg.name} to #{args[arg.name]}.")
68
+ end
69
+ argument_map[arg.name] = temp_arg_var
70
+ end
71
+
72
+ # run the measure
73
+ measure.run(model, runner, argument_map)
74
+ result = runner.result
75
+
76
+ puts "this is measure #{measure.run(model, runner, argument_map)}"
77
+ # show the output
78
+ puts "measure results for #{test_name}"
79
+ show_output(result)
80
+
81
+ # assert that it ran correctly
82
+ if result_value.nil? then result_value = 'Success' end
83
+ assert_equal(result_value, result.value.valueName)
84
+
85
+ # check count of warning and info messages
86
+ unless info_count.nil? then assert(result.info.size == info_count) end
87
+ unless warnings_count.nil? then assert(result.warnings.size == warnings_count, "warning count (#{result.warnings.size}) did not match expectation (#{warnings_count})") end
88
+
89
+ # if 'Fail' passed in make sure at least one error message (while not typical there may be more than one message)
90
+ if result_value == 'Fail' then assert(result.errors.size >= 1) end
91
+
92
+ end
93
+
94
+ def test_example_model_with_output_path
95
+ args = {}
96
+ args['openstudio_model'] = File.join(File.dirname(__FILE__) + '/../../../../spec/samples/osm/exampleModel.osm')
97
+ args['output_file_path'] = File.join(File.dirname(__FILE__) + '/output/exampleModel.hbjson')
98
+ apply_measure_to_model(__method__.to_s.gsub('test_',''),args, nil)
99
+ end
100
+
101
+ def test_example_model_without_output_path
102
+ args = {}
103
+ args['openstudio_model'] = File.join(File.dirname(__FILE__) + '/../../../../spec/samples/osm/exampleModel.osm')
104
+ apply_measure_to_model(__method__.to_s.gsub('test_',''),args, nil)
105
+ end
106
+
107
+ end
@@ -83,27 +83,36 @@ module Honeybee
83
83
  air_loops = openstudio_model.getAirLoopHVACs
84
84
  unless air_loops.length == $air_loop_count # check if any new loops were added
85
85
  $air_loop_count = air_loops.length
86
- os_air_loop = air_loops[-1]
87
- loop_name = os_air_loop.name
88
- unless loop_name.empty?
89
- if @hash[:display_name]
90
- os_air_loop.setName(@hash[:display_name] + ' - ' + loop_name.get)
86
+ os_air_terminal = zones[0].airLoopHVACTerminal
87
+ unless os_air_terminal.empty?
88
+ os_air_terminal = os_air_terminal.get
89
+ os_air_loop_opt = os_air_terminal.airLoopHVAC
90
+ unless os_air_loop_opt.empty?
91
+ os_air_loop = os_air_loop_opt.get
92
+ loop_name = os_air_loop.name
93
+ unless loop_name.empty?
94
+ # set the name of the air loop to align with the HVAC name
95
+ if @hash[:display_name]
96
+ clean_name = @hash[:display_name].to_s.gsub(/[^.A-Za-z0-9_-] /, " ")
97
+ os_air_loop.setName(clean_name + ' - ' + loop_name.get)
98
+ end
99
+ end
91
100
  end
92
101
  end
93
102
  end
94
103
 
95
104
  # assign the economizer type if there's an air loop and the economizer is specified
96
- if @hash[:economizer_type] && @hash[:economizer_type] != 'Inferred' && os_air_loop
105
+ if @hash[:economizer_type] && os_air_loop
97
106
  oasys = os_air_loop.airLoopHVACOutdoorAirSystem
98
107
  unless oasys.empty?
99
- os_oasys = oasys.get
100
- oactrl = os_oasys.getControllerOutdoorAir
101
- oactrl.setEconomizerControlType(@hash[:economizer_type])
108
+ os_oasys = oasys.get
109
+ oactrl = os_oasys.getControllerOutdoorAir
110
+ oactrl.setEconomizerControlType(@hash[:economizer_type])
102
111
  end
103
112
  end
104
113
 
105
114
  # set the sensible heat recovery if there's an air loop and the heat recovery is specified
106
- if @hash[:sensible_heat_recovery] && @hash[:sensible_heat_recovery] != {:type => 'Autosize'} && os_air_loop
115
+ if @hash[:sensible_heat_recovery] && @hash[:sensible_heat_recovery] != 0 && os_air_loop
107
116
  erv = get_existing_erv(os_air_loop)
108
117
  unless erv
109
118
  erv = create_erv(openstudio_model, os_air_loop)
@@ -116,7 +125,7 @@ module Honeybee
116
125
  end
117
126
 
118
127
  # set the latent heat recovery if there's an air loop and the heat recovery is specified
119
- if @hash[:latent_heat_recovery] && @hash[:latent_heat_recovery] != {:type => 'Autosize'} && os_air_loop
128
+ if @hash[:latent_heat_recovery] && @hash[:latent_heat_recovery] != 0 && os_air_loop
120
129
  erv = get_existing_erv(os_air_loop)
121
130
  unless erv
122
131
  erv = create_erv(openstudio_model, os_air_loop)
@@ -128,6 +137,60 @@ module Honeybee
128
137
  erv.setLatentEffectivenessat75HeatingAirFlow(@hash[:latent_heat_recovery])
129
138
  end
130
139
 
140
+ # assign demand controlled ventilation if there's an air loop
141
+ if @hash[:demand_controlled_ventilation] && os_air_loop
142
+ oasys = os_air_loop.airLoopHVACOutdoorAirSystem
143
+ unless oasys.empty?
144
+ os_oasys = oasys.get
145
+ oactrl = os_oasys.getControllerOutdoorAir
146
+ vent_ctrl = oactrl.controllerMechanicalVentilation
147
+ vent_ctrl.setDemandControlledVentilationNoFail(true)
148
+ oactrl.resetMinimumFractionofOutdoorAirSchedule
149
+ end
150
+ end
151
+
152
+ # assign the DOAS availability schedule if there's an air loop and it is specified
153
+ if @hash[:doas_availability_schedule] && os_air_loop
154
+ schedule = openstudio_model.getScheduleByName(@hash[:doas_availability_schedule])
155
+ unless schedule.empty?
156
+ avail_sch = schedule.get
157
+ os_air_loop.setAvailabilitySchedule(avail_sch)
158
+ end
159
+ end
160
+
161
+ # set the outdoor air controller to respect room-level ventilation schedules if they exist
162
+ if os_air_loop
163
+ oasys = os_air_loop.airLoopHVACOutdoorAirSystem
164
+ unless oasys.empty?
165
+ os_oasys = oasys.get
166
+ oactrl = os_oasys.getControllerOutdoorAir
167
+ oa_sch, oa_sch_name = nil, nil
168
+ zones.each do |zone|
169
+ oa_spec = zone.spaces[0].designSpecificationOutdoorAir
170
+ unless oa_spec.empty?
171
+ oa_spec = oa_spec.get
172
+ space_oa_sch = oa_spec.outdoorAirFlowRateFractionSchedule
173
+ unless space_oa_sch.empty?
174
+ space_oa_sch = space_oa_sch.get
175
+ space_oa_sch_name = space_oa_sch.name
176
+ unless space_oa_sch_name.empty?
177
+ space_oa_sch_name = space_oa_sch_name.get
178
+ if oa_sch_name.nil? || space_oa_sch_name == oa_sch_name
179
+ oa_sch, oa_sch_name = space_oa_sch, space_oa_sch_name
180
+ else
181
+ oa_sch = nil
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
187
+ if oa_sch
188
+ oactrl.resetMinimumFractionofOutdoorAirSchedule
189
+ oactrl.setMinimumOutdoorAirSchedule(oa_sch)
190
+ end
191
+ end
192
+ end
193
+
131
194
  # if the systems are PTAC and there is ventilation, ensure the system includes it
132
195
  if equipment_type.include?('PTAC') || equipment_type.include?('PTHP')
133
196
  always_on = openstudio_model.getScheduleByName('Always On').get
@@ -164,6 +227,20 @@ module Honeybee
164
227
  end
165
228
  end
166
229
 
230
+ # assign an electric humidifier if there's an air loop and the zones have a humidistat
231
+ if os_air_loop
232
+ humidistat_exists = false
233
+ zones.each do |zone|
234
+ h_stat = zone.zoneControlHumidistat
235
+ unless h_stat.empty?
236
+ humidistat_exists = true
237
+ end
238
+ end
239
+ if humidistat_exists
240
+ humidifier = create_humidifier(openstudio_model, os_air_loop)
241
+ end
242
+ end
243
+
167
244
  # set all plants to non-coincident sizing to avoid simualtion control issues on design days
168
245
  openstudio_model.getPlantLoops.each do |loop|
169
246
  sizing = loop.sizingPlant
@@ -209,5 +286,20 @@ module Honeybee
209
286
  heat_ex
210
287
  end
211
288
 
289
+ def create_humidifier(model, os_air_loop)
290
+ # create an electric humidifier
291
+ humidifier = OpenStudio::Model::HumidifierSteamElectric.new(model)
292
+ humidifier.setName(@hash[:identifier] + '_Humidifier Unit')
293
+ humid_controller = OpenStudio::Model::SetpointManagerMultiZoneHumidityMinimum.new(model)
294
+ humid_controller.setName(@hash[:identifier] + '_Humidifier Controller')
295
+
296
+ # add the humidifier to the air loop
297
+ supply_node = os_air_loop.supplyOutletNode
298
+ humidifier.addToNode(supply_node)
299
+ humid_controller.addToNode(supply_node)
300
+
301
+ humidifier
302
+ end
303
+
212
304
  end #TemplateHVAC
213
305
  end #Honeybee
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.15.0
4
+ version: 2.16.4
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-04-27 00:00:00.000000000 Z
14
+ date: 2021-05-05 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: json_pure
@@ -152,16 +152,36 @@ files:
152
152
  - lib/honeybee/ventcool/opening.rb
153
153
  - lib/honeybee/ventcool/simulation.rb
154
154
  - lib/measures/.gitkeep
155
+ - lib/measures/from_gbxml_model/LICENSE.md
156
+ - lib/measures/from_gbxml_model/README.md
157
+ - lib/measures/from_gbxml_model/measure.rb
158
+ - lib/measures/from_gbxml_model/measure.xml
159
+ - lib/measures/from_gbxml_model/tests/from_gbxml_model_test.rb
155
160
  - lib/measures/from_honeybee_model/LICENSE.md
156
161
  - lib/measures/from_honeybee_model/README.md
157
162
  - lib/measures/from_honeybee_model/measure.rb
158
163
  - lib/measures/from_honeybee_model/measure.xml
159
164
  - lib/measures/from_honeybee_model/tests/from_honeybee_model_test.rb
165
+ - lib/measures/from_honeybee_model_to_gbxml/LICENSE.md
166
+ - lib/measures/from_honeybee_model_to_gbxml/README.md
167
+ - lib/measures/from_honeybee_model_to_gbxml/measure.rb
168
+ - lib/measures/from_honeybee_model_to_gbxml/measure.xml
169
+ - lib/measures/from_honeybee_model_to_gbxml/tests/from_honeybee_model_to_gbxml_test.rb
160
170
  - lib/measures/from_honeybee_simulation_parameter/LICENSE.md
161
171
  - lib/measures/from_honeybee_simulation_parameter/README.md
162
172
  - lib/measures/from_honeybee_simulation_parameter/measure.rb
163
173
  - lib/measures/from_honeybee_simulation_parameter/measure.xml
164
174
  - lib/measures/from_honeybee_simulation_parameter/tests/from_honeybee_simulation_parameter_test.rb
175
+ - lib/measures/from_idf_model/LICENSE.md
176
+ - lib/measures/from_idf_model/README.md
177
+ - lib/measures/from_idf_model/measure.rb
178
+ - lib/measures/from_idf_model/measure.xml
179
+ - lib/measures/from_idf_model/tests/from_idf_model_test.rb
180
+ - lib/measures/from_openstudio_model/LICENSE.md
181
+ - lib/measures/from_openstudio_model/README.md
182
+ - lib/measures/from_openstudio_model/measure.rb
183
+ - lib/measures/from_openstudio_model/measure.xml
184
+ - lib/measures/from_openstudio_model/tests/from_openstudio_model_test.rb
165
185
  - lib/to_openstudio.rb
166
186
  - lib/to_openstudio/construction/air.rb
167
187
  - lib/to_openstudio/construction/opaque.rb