openstudio-extension 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +29 -26
  3. data/.rspec +3 -3
  4. data/.rubocop.yml +10 -9
  5. data/CHANGELOG.md +16 -0
  6. data/Gemfile +6 -6
  7. data/Jenkinsfile +10 -10
  8. data/README.md +251 -250
  9. data/Rakefile +119 -119
  10. data/bin/console +14 -14
  11. data/bin/setup +8 -8
  12. data/doc_templates/LICENSE.md +26 -26
  13. data/doc_templates/README.md.erb +41 -41
  14. data/doc_templates/copyright_erb.txt +35 -35
  15. data/doc_templates/copyright_js.txt +3 -3
  16. data/doc_templates/copyright_ruby.txt +33 -33
  17. data/init_templates/README.md +37 -37
  18. data/init_templates/gemspec.txt +32 -32
  19. data/init_templates/openstudio_module.rb +50 -50
  20. data/init_templates/spec.rb +47 -47
  21. data/init_templates/spec_helper.rb +49 -49
  22. data/init_templates/template_gemfile.txt +17 -17
  23. data/init_templates/template_rakefile.txt +15 -15
  24. data/init_templates/version.rb +40 -40
  25. data/lib/files/openstudio-extension-gem-test.ddy +536 -536
  26. data/lib/files/openstudio-extension-gem-test.epw +8768 -8768
  27. data/lib/files/openstudio-extension-gem-test.stat +554 -554
  28. data/lib/measures/openstudio_extension_test_measure/LICENSE.md +26 -26
  29. data/lib/measures/openstudio_extension_test_measure/README.md +26 -26
  30. data/lib/measures/openstudio_extension_test_measure/README.md.erb +41 -41
  31. data/lib/measures/openstudio_extension_test_measure/measure.rb +72 -72
  32. data/lib/measures/openstudio_extension_test_measure/measure.xml +83 -83
  33. data/lib/measures/openstudio_extension_test_measure/resources/os_lib_helper_methods.rb +399 -399
  34. data/lib/measures/openstudio_extension_test_measure/tests/{OpenStudioExtensionTestMeasure_Test.rb → openstudio_extension_test_measure_test.rb} +74 -75
  35. data/lib/openstudio-extension.rb +1 -1
  36. data/lib/openstudio/extension.rb +234 -229
  37. data/lib/openstudio/extension/core/CreateResults.rb +886 -886
  38. data/lib/openstudio/extension/core/check_air_sys_temps.rb +190 -190
  39. data/lib/openstudio/extension/core/check_calibration.rb +155 -155
  40. data/lib/openstudio/extension/core/check_cond_zns.rb +84 -84
  41. data/lib/openstudio/extension/core/check_domestic_hot_water.rb +334 -334
  42. data/lib/openstudio/extension/core/check_envelope_conductance.rb +453 -453
  43. data/lib/openstudio/extension/core/check_eui_by_end_use.rb +162 -162
  44. data/lib/openstudio/extension/core/check_eui_reasonableness.rb +135 -135
  45. data/lib/openstudio/extension/core/check_fan_pwr.rb +98 -98
  46. data/lib/openstudio/extension/core/check_internal_loads.rb +393 -393
  47. data/lib/openstudio/extension/core/check_mech_sys_capacity.rb +226 -226
  48. data/lib/openstudio/extension/core/check_mech_sys_efficiency.rb +326 -326
  49. data/lib/openstudio/extension/core/check_mech_sys_part_load_eff.rb +464 -464
  50. data/lib/openstudio/extension/core/check_mech_sys_type.rb +139 -139
  51. data/lib/openstudio/extension/core/check_part_loads.rb +451 -451
  52. data/lib/openstudio/extension/core/check_placeholder.rb +75 -75
  53. data/lib/openstudio/extension/core/check_plant_cap.rb +123 -123
  54. data/lib/openstudio/extension/core/check_plant_temps.rb +159 -159
  55. data/lib/openstudio/extension/core/check_plenum_loads.rb +87 -87
  56. data/lib/openstudio/extension/core/check_pump_pwr.rb +108 -108
  57. data/lib/openstudio/extension/core/check_sch_coord.rb +241 -241
  58. data/lib/openstudio/extension/core/check_schedules.rb +311 -311
  59. data/lib/openstudio/extension/core/check_simultaneous_heating_and_cooling.rb +158 -158
  60. data/lib/openstudio/extension/core/check_supply_air_and_thermostat_temp_difference.rb +148 -148
  61. data/lib/openstudio/extension/core/check_weather_files.rb +132 -132
  62. data/lib/openstudio/extension/core/deer_vintages.rb +311 -311
  63. data/lib/openstudio/extension/core/os_lib_aedg_measures.rb +491 -491
  64. data/lib/openstudio/extension/core/os_lib_cofee.rb +258 -258
  65. data/lib/openstudio/extension/core/os_lib_constructions.rb +378 -378
  66. data/lib/openstudio/extension/core/os_lib_geometry.rb +1022 -1022
  67. data/lib/openstudio/extension/core/os_lib_helper_methods.rb +399 -399
  68. data/lib/openstudio/extension/core/os_lib_hvac.rb +2171 -2171
  69. data/lib/openstudio/extension/core/os_lib_lighting_and_equipment.rb +214 -214
  70. data/lib/openstudio/extension/core/os_lib_model_generation.rb +817 -817
  71. data/lib/openstudio/extension/core/os_lib_model_simplification.rb +1049 -1049
  72. data/lib/openstudio/extension/core/os_lib_outdoorair_and_infiltration.rb +165 -165
  73. data/lib/openstudio/extension/core/os_lib_reporting.rb +4651 -4651
  74. data/lib/openstudio/extension/core/os_lib_reporting_qaqc.rb +200 -200
  75. data/lib/openstudio/extension/core/os_lib_schedules.rb +963 -963
  76. data/lib/openstudio/extension/rake_task.rb +159 -149
  77. data/lib/openstudio/extension/runner.rb +667 -644
  78. data/lib/openstudio/extension/runner_config.rb +114 -0
  79. data/lib/openstudio/extension/version.rb +40 -40
  80. data/openstudio-extension.gemspec +34 -33
  81. metadata +39 -37
@@ -1,2171 +1,2171 @@
1
- # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) 2008-2019, Alliance for Sustainable Energy, LLC.
3
- # All rights reserved.
4
- # Redistribution and use in source and binary forms, with or without
5
- # modification, are permitted provided that the following conditions are met:
6
- #
7
- # (1) Redistributions of source code must retain the above copyright notice,
8
- # this list of conditions and the following disclaimer.
9
- #
10
- # (2) Redistributions in binary form must reproduce the above copyright notice,
11
- # this list of conditions and the following disclaimer in the documentation
12
- # and/or other materials provided with the distribution.
13
- #
14
- # (3) Neither the name of the copyright holder nor the names of any contributors
15
- # may be used to endorse or promote products derived from this software without
16
- # specific prior written permission from the respective party.
17
- #
18
- # (4) Other than as required in clauses (1) and (2), distributions in any form
19
- # of modifications or other derivative works may not use the "OpenStudio"
20
- # trademark, "OS", "os", or any other confusingly similar designation without
21
- # specific prior written permission from Alliance for Sustainable Energy, LLC.
22
- #
23
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
24
- # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25
- # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
- # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
27
- # UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
28
- # THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29
- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30
- # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32
- # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33
- # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
- # *******************************************************************************
35
-
36
- module OsLib_HVAC
37
- # do something
38
- def self.doSomething(input)
39
- # do something
40
- output = input
41
-
42
- result = output
43
- return result
44
- end
45
-
46
- # validate and make plenum zones
47
- def self.validateAndAddPlenumZonesToSystem(model, runner, options = {})
48
- # set defaults to use if user inputs not passed in
49
- defaults = {
50
- 'zonesPlenum' => nil,
51
- 'zonesPrimary' => nil,
52
- 'type' => 'ceilingReturn'
53
- }
54
-
55
- # merge user inputs with defaults
56
- options = defaults.merge(options)
57
-
58
- # array of valid ceiling plenums
59
- zoneSurfaceHash = {}
60
- zonePlenumHash = {}
61
-
62
- if options['zonesPlenum'].nil?
63
- runner.registerWarning('No plenum zones were passed in, validateAndAddPlenumZonesToSystem will not alter the model.')
64
- else
65
- options['zonesPlenum'].each do |zone|
66
- # get spaces in zone
67
- spaces = zone.spaces
68
- # get adjacent spaces
69
- spaces.each do |space|
70
- # get surfaces
71
- surfaces = space.surfaces
72
- # loop through surfaces looking for floors with surface boundary condition, grab zone that surface's parent space is in.
73
- surfaces.each do |surface|
74
- if (surface.outsideBoundaryCondition == 'Surface') && (surface.surfaceType == 'Floor')
75
- next if surface.adjacentSurface.empty?
76
- adjacentSurface = surface.adjacentSurface.get
77
- next if adjacentSurface.space.empty?
78
- adjacentSurfaceSpace = adjacentSurface.space.get
79
- next if adjacentSurfaceSpace.thermalZone.empty?
80
- adjacentSurfaceSpaceZone = adjacentSurfaceSpace.thermalZone.get
81
- if options['zonesPrimary'].include? adjacentSurfaceSpaceZone
82
- if zoneSurfaceHash[adjacentSurfaceSpaceZone].nil? || (surface.grossArea > zoneSurfaceHash[adjacentSurfaceSpaceZone])
83
- adjacentSurfaceSpaceZone.setReturnPlenum(zone)
84
- zoneSurfaceHash[adjacentSurfaceSpaceZone] = surface.grossArea
85
- zonePlenumHash[adjacentSurfaceSpaceZone] = zone
86
- end
87
- end
88
- end
89
- end
90
- end
91
- end
92
- end
93
-
94
- # report out results of zone-plenum hash
95
- zonePlenumHash.each do |zone, plenum|
96
- runner.registerInfo("#{plenum.name} has been set as a return air plenum for #{zone.name}.")
97
- end
98
-
99
- # pass back zone-plenum hash
100
- result = zonePlenumHash
101
- return result
102
- end
103
-
104
- def self.sortZones(model, runner, options = {})
105
- # set defaults to use if user inputs not passed in
106
- defaults = { 'standardBuildingTypeTest' => nil, # not used for now
107
- 'secondarySpaceTypeTest' => nil,
108
- 'ceilingReturnPlenumSpaceType' => nil }
109
-
110
- # merge user inputs with defaults
111
- options = defaults.merge(options)
112
-
113
- # set up zone type arrays
114
- zonesPrimary = []
115
- zonesSecondary = []
116
- zonesPlenum = []
117
- zonesUnconditioned = []
118
-
119
- # get thermal zones
120
- zones = model.getThermalZones
121
- zones.each do |zone|
122
- # assign appropriate zones to zonesPlenum or zonesUnconditioned (those that don't have thermostats or zone HVAC equipment)
123
- # if not conditioned then add to zonesPlenum or zonesUnconditioned
124
- if zone.thermostatSetpointDualSetpoint.is_initialized || !zone.equipment.empty?
125
- # zone is conditioned. check if its space type is secondary or primary
126
- spaces = zone.spaces
127
- spaces.each do |space|
128
- # if a zone has already been assigned as secondary, skip
129
- next if zonesSecondary.include? zone
130
- # get space type if it exists
131
- next if space.spaceType.empty?
132
- spaceType = space.spaceType.get
133
- # get standards information
134
- # for now skip standardsBuildingType and just rely on the standardsSpaceType. Seems like enough.
135
- next if spaceType.standardsSpaceType.empty?
136
- standardSpaceType = spaceType.standardsSpaceType.get
137
- # test space type against secondary space type array
138
- # if any space type in zone is secondary, assign zone as secondary
139
- if options['secondarySpaceTypeTest'].include? standardSpaceType
140
- zonesSecondary << zone
141
- end
142
- end
143
- # if zone not assigned as secondary, assign as primary
144
- unless zonesSecondary.include? zone
145
- zonesPrimary << zone
146
- end
147
- else
148
- # determine if zone is a plenum zone or general unconditioned zone
149
- # assume it is a plenum if it has at least one planum space
150
- zone.spaces.each do |space|
151
- # if a zone has already been assigned as a plenum, skip
152
- next if zonesPlenum.include? zone
153
- # if zone not assigned as a plenum, get space type if it exists
154
- # compare to plenum space type if it has been assigned
155
- if space.spaceType.is_initialized && (options['ceilingReturnPlenumSpaceType'].nil? == false)
156
- spaceType = space.spaceType.get
157
- if spaceType == options['ceilingReturnPlenumSpaceType']
158
- zonesPlenum << zone # zone has a plenum space; assign it as a plenum
159
- end
160
- end
161
- end
162
- # if zone not assigned as a plenum, assign it as unconditioned
163
- unless zonesPlenum.include? zone
164
- zonesUnconditioned << zone
165
- end
166
- end
167
- end
168
-
169
- zonesSorted = { 'zonesPrimary' => zonesPrimary,
170
- 'zonesSecondary' => zonesSecondary,
171
- 'zonesPlenum' => zonesPlenum,
172
- 'zonesUnconditioned' => zonesUnconditioned }
173
- # pass back zonesSorted hash
174
- result = zonesSorted
175
- return result
176
- end
177
-
178
- def self.reportConditions(model, runner, condition,extra_string = '')
179
-
180
- airloops = model.getAirLoopHVACs
181
- plantLoops = model.getPlantLoops
182
- zones = model.getThermalZones
183
-
184
- # count up zone equipment (not counting zone exhaust fans)
185
- zoneHasEquip = false
186
- zonesWithEquipCounter = 0
187
-
188
- zones.each do |zone|
189
- if zone.equipment.size > 0
190
- zone.equipment.each do |equip|
191
- unless equip.to_FanZoneExhaust.is_initialized
192
- zonesWithEquipCounter += 1
193
- break
194
- end
195
- end
196
- end
197
- end
198
-
199
- if condition == "initial"
200
- runner.registerInitialCondition("The building started with #{airloops.size} air loops and #{plantLoops.size} plant loops. #{zonesWithEquipCounter} zones were conditioned with zone equipment.")
201
- elsif condition == "final"
202
- runner.registerFinalCondition("The building finished with #{airloops.size} air loops and #{plantLoops.size} plant loops. #{zonesWithEquipCounter} zones are conditioned with zone equipment. #{extra_string}")
203
- end
204
-
205
- end
206
-
207
- def self.removeEquipment(model, runner)
208
- airloops = model.getAirLoopHVACs
209
- plantLoops = model.getPlantLoops
210
- zones = model.getThermalZones
211
-
212
- # remove all airloops
213
- airloops.each(&:remove)
214
-
215
- # remove all zone equipment except zone exhaust fans
216
- zones.each do |zone|
217
- zone.equipment.each do |equip|
218
- if equip.to_FanZoneExhaust.is_initialized
219
- else
220
- equip.remove
221
- end
222
- end
223
- end
224
-
225
- # remove plant loops
226
- plantLoops.each do |plantloop|
227
- # get the demand components and see if water use connection, then save it
228
- # notify user with info statement if supply side of plant loop had heat exchanger for refrigeration
229
- usedForSHWorRefrigeration = false
230
- plantloop.demandComponents.each do |comp| # AP code to check your comments above
231
- if comp.to_WaterUseConnections.is_initialized || comp.to_CoilWaterHeatingDesuperheater.is_initialized
232
- usedForSHWorRefrigeration = true
233
- end
234
- end
235
- if usedForSHWorRefrigeration == false
236
- plantloop.remove
237
- else
238
- runner.registerWarning("#{plantloop.name} is used for SHW or refrigeration heat reclaim. Loop will not be deleted")
239
- end
240
- end
241
- end
242
-
243
- def self.assignHVACSchedules(model, runner, options = {})
244
- require "#{File.dirname(__FILE__)}/os_lib_schedules"
245
-
246
- schedulesHVAC = {}
247
- airloops = model.getAirLoopHVACs
248
-
249
- # find airloop with most primary spaces
250
- max_primary_spaces = 0
251
- representative_airloop = false
252
- building_HVAC_schedule = false
253
- building_ventilation_schedule = false
254
- unless options['remake_schedules']
255
- # if remake schedules not selected, get relevant schedules from model if they exist
256
- airloops.each do |air_loop|
257
- primary_spaces = 0
258
- air_loop.thermalZones.each do |thermal_zone|
259
- thermal_zone.spaces.each do |space|
260
- if space.spaceType.is_initialized
261
- if space.spaceType.get.name.get.include? options['primarySpaceType']
262
- primary_spaces += 1
263
- end
264
- end
265
- end
266
- end
267
- if primary_spaces > max_primary_spaces
268
- max_primary_spaces = primary_spaces
269
- representative_airloop = air_loop
270
- end
271
- end
272
- end
273
- if representative_airloop
274
- building_HVAC_schedule = representative_airloop.availabilitySchedule
275
- building_ventilation_schedule_optional = representative_airloop.airLoopHVACOutdoorAirSystem.get.getControllerOutdoorAir.maximumFractionofOutdoorAirSchedule
276
- if building_ventilation_schedule_optional.is_initialized
277
- building_ventilation_schedule = building_ventilation_schedule.get
278
- end
279
- end
280
- # build new airloop schedules if existing model doesn't have them
281
- if options['primarySpaceType'] == 'Classroom'
282
- # ventilation schedule
283
- unless building_ventilation_schedule
284
- ruleset_name = 'AEDG K-12 Ventilation Schedule'
285
- winter_design_day = [[24, 1]]
286
- summer_design_day = [[24, 1]]
287
- default_day = ['Weekday', [6, 0], [18, 1], [24, 0]]
288
- rules = []
289
- rules << ['Weekend', '1/1-12/31', 'Sat/Sun', [24, 0]]
290
- rules << ['Summer Weekday', '7/1-8/31', 'Mon/Tue/Wed/Thu/Fri', [8, 0], [13, 1], [24, 0]]
291
- options_ventilation = { 'name' => ruleset_name,
292
- 'winter_design_day' => winter_design_day,
293
- 'summer_design_day' => summer_design_day,
294
- 'default_day' => default_day,
295
- 'rules' => rules }
296
- building_ventilation_schedule = OsLib_Schedules.createComplexSchedule(model, options_ventilation)
297
- end
298
- # HVAC availability schedule
299
- unless building_HVAC_schedule
300
- ruleset_name = 'AEDG K-12 HVAC Availability Schedule'
301
- winter_design_day = [[24, 1]]
302
- summer_design_day = [[24, 1]]
303
- default_day = ['Weekday', [6, 0], [18, 1], [24, 0]]
304
- rules = []
305
- rules << ['Weekend', '1/1-12/31', 'Sat/Sun', [24, 0]]
306
- rules << ['Summer Weekday', '7/1-8/31', 'Mon/Tue/Wed/Thu/Fri', [8, 0], [13, 1], [24, 0]]
307
- options_hvac = { 'name' => ruleset_name,
308
- 'winter_design_day' => winter_design_day,
309
- 'summer_design_day' => summer_design_day,
310
- 'default_day' => default_day,
311
- 'rules' => rules }
312
- building_HVAC_schedule = OsLib_Schedules.createComplexSchedule(model, options_hvac)
313
- end
314
- elsif options['primarySpaceType'] == 'Office'
315
- # ventilation schedule
316
- unless building_ventilation_schedule
317
- ruleset_name = 'AEDG Office Ventilation Schedule'
318
- winter_design_day = [[24, 1]] # ML These are not always on in PNNL model
319
- summer_design_day = [[24, 1]] # ML These are not always on in PNNL model
320
- default_day = ['Weekday', [7, 0], [22, 1], [24, 0]] # ML PNNL has a one hour ventilation offset
321
- rules = []
322
- rules << ['Saturday', '1/1-12/31', 'Sat', [7, 0], [18, 1], [24, 0]] # ML PNNL has a one hour ventilation offset
323
- rules << ['Sunday', '1/1-12/31', 'Sun', [24, 0]]
324
- options_ventilation = { 'name' => ruleset_name,
325
- 'winter_design_day' => winter_design_day,
326
- 'summer_design_day' => summer_design_day,
327
- 'default_day' => default_day,
328
- 'rules' => rules }
329
- building_ventilation_schedule = OsLib_Schedules.createComplexSchedule(model, options_ventilation)
330
- end
331
- # HVAC availability schedule
332
- unless building_HVAC_schedule
333
- ruleset_name = 'AEDG Office HVAC Availability Schedule'
334
- winter_design_day = [[24, 1]] # ML These are not always on in PNNL model
335
- summer_design_day = [[24, 1]] # ML These are not always on in PNNL model
336
- default_day = ['Weekday', [6, 0], [22, 1], [24, 0]] # ML PNNL has a one hour ventilation offset
337
- rules = []
338
- rules << ['Saturday', '1/1-12/31', 'Sat', [6, 0], [18, 1], [24, 0]] # ML PNNL has a one hour ventilation offset
339
- rules << ['Sunday', '1/1-12/31', 'Sun', [24, 0]]
340
- options_hvac = { 'name' => ruleset_name,
341
- 'winter_design_day' => winter_design_day,
342
- 'summer_design_day' => summer_design_day,
343
- 'default_day' => default_day,
344
- 'rules' => rules }
345
- building_HVAC_schedule = OsLib_Schedules.createComplexSchedule(model, options_hvac)
346
- end
347
- # special loops for radiant system (different temperature setpoints)
348
- if options['allHVAC']['zone'] == 'Radiant'
349
- # create hot water schedule for radiant heating loop
350
- schedulesHVAC['radiant_hot_water'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HW-Radiant-Loop-Temp-Schedule',
351
- 'default_day' => ['All Days', [24, 45.0]])
352
- # create hot water schedule for radiant cooling loop
353
- schedulesHVAC['radiant_chilled_water'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG CW-Radiant-Loop-Temp-Schedule',
354
- 'default_day' => ['All Days', [24, 15.0]])
355
- # create mean radiant heating and cooling setpoint schedules
356
- # ML ideally, should grab schedules tied to zone thermostat and make modified versions that follow the setback pattern
357
- # for now, create new ones that match the recommended HVAC schedule
358
- # mean radiant heating setpoint schedule (PNNL values)
359
- ruleset_name = 'AEDG Office Mean Radiant Heating Setpoint Schedule'
360
- winter_design_day = [[24, 18.8]]
361
- summer_design_day = [[6, 18.3], [22, 18.8], [24, 18.3]]
362
- default_day = ['Weekday', [6, 18.3], [22, 18.8], [24, 18.3]]
363
- rules = []
364
- rules << ['Saturday', '1/1-12/31', 'Sat', [6, 18.3], [18, 18.8], [24, 18.3]]
365
- rules << ['Sunday', '1/1-12/31', 'Sun', [24, 18.3]]
366
- options_radiant_heating = { 'name' => ruleset_name,
367
- 'winter_design_day' => winter_design_day,
368
- 'summer_design_day' => summer_design_day,
369
- 'default_day' => default_day,
370
- 'rules' => rules }
371
- mean_radiant_heating_schedule = OsLib_Schedules.createComplexSchedule(model, options_radiant_heating)
372
- schedulesHVAC['mean_radiant_heating'] = mean_radiant_heating_schedule
373
- # mean radiant cooling setpoint schedule (PNNL values)
374
- ruleset_name = 'AEDG Office Mean Radiant Cooling Setpoint Schedule'
375
- winter_design_day = [[6, 26.7], [22, 24.0], [24, 26.7]]
376
- summer_design_day = [[24, 24.0]]
377
- default_day = ['Weekday', [6, 26.7], [22, 24.0], [24, 26.7]]
378
- rules = []
379
- rules << ['Saturday', '1/1-12/31', 'Sat', [6, 26.7], [18, 24.0], [24, 26.7]]
380
- rules << ['Sunday', '1/1-12/31', 'Sun', [24, 26.7]]
381
- options_radiant_cooling = { 'name' => ruleset_name,
382
- 'winter_design_day' => winter_design_day,
383
- 'summer_design_day' => summer_design_day,
384
- 'default_day' => default_day,
385
- 'rules' => rules }
386
- mean_radiant_cooling_schedule = OsLib_Schedules.createComplexSchedule(model, options_radiant_cooling)
387
- schedulesHVAC['mean_radiant_cooling'] = mean_radiant_cooling_schedule
388
- end
389
- end
390
- # SAT schedule
391
- if options['allHVAC']['primary']['doas']
392
- # primary airloop is DOAS
393
- schedulesHVAC['primary_sat'] = sch_ruleset_DOAS_setpoint = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG DOAS Temperature Setpoint Schedule',
394
- 'default_day' => ['All Days', [24, 20.0]])
395
- else
396
- # primary airloop is multizone VAV that cools
397
- schedulesHVAC['primary_sat'] = sch_ruleset_DOAS_setpoint = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG Cold Deck Temperature Setpoint Schedule',
398
- 'default_day' => ['All Days', [24, 12.8]])
399
- end
400
- schedulesHVAC['ventilation'] = building_ventilation_schedule
401
- schedulesHVAC['hvac'] = building_HVAC_schedule
402
- # build new plant schedules as needed
403
- zoneHVACHotWaterPlant = ['FanCoil', 'DualDuct', 'Baseboard'] # dual duct has fan coil and baseboard
404
- zoneHVACChilledWaterPlant = ['FanCoil', 'DualDuct'] # dual duct has fan coil
405
- # hot water
406
- if (options['allHVAC']['primary']['heat'] == 'Water') || (options['allHVAC']['secondary']['heat'] == 'Water') || zoneHVACHotWaterPlant.include?(options['allHVAC']['zone'])
407
- schedulesHVAC['hot_water'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HW-Loop-Temp-Schedule',
408
- 'default_day' => ['All Days', [24, 67.0]])
409
- end
410
- # chilled water
411
- if (options['allHVAC']['primary']['cool'] == 'Water') || (options['allHVAC']['secondary']['cool'] == 'Water') || zoneHVACChilledWaterPlant.include?(options['allHVAC']['zone'])
412
- schedulesHVAC['chilled_water'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG CW-Loop-Temp-Schedule',
413
- 'default_day' => ['All Days', [24, 6.7]])
414
- end
415
- # heat pump condenser loop schedules
416
- if options['allHVAC']['zone'] == 'GSHP'
417
- # there will be a heat pump condenser loop
418
- # loop setpoint schedule
419
- schedulesHVAC['hp_loop'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HP-Loop-Temp-Schedule',
420
- 'default_day' => ['All Days', [24, 21]])
421
- # cooling component schedule (#ML won't need this if a ground loop is actually modeled)
422
- schedulesHVAC['hp_loop_cooling'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HP-Loop-Clg-Temp-Schedule',
423
- 'default_day' => ['All Days', [24, 21]])
424
- # heating component schedule
425
- schedulesHVAC['hp_loop_heating'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HP-Loop-Htg-Temp-Schedule',
426
- 'default_day' => ['All Days', [24, 5]])
427
- end
428
- if options['allHVAC']['zone'] == 'WSHP'
429
- # there will be a heat pump condenser loop
430
- # loop setpoint schedule
431
- schedulesHVAC['hp_loop'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HP-Loop-Temp-Schedule',
432
- 'default_day' => ['All Days', [24, 30]]) # PNNL
433
- # cooling component schedule (#ML won't need this if a ground loop is actually modeled)
434
- schedulesHVAC['hp_loop_cooling'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HP-Loop-Clg-Temp-Schedule',
435
- 'default_day' => ['All Days', [24, 30]]) # PNNL
436
- # heating component schedule
437
- schedulesHVAC['hp_loop_heating'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HP-Loop-Htg-Temp-Schedule',
438
- 'default_day' => ['All Days', [24, 20]]) # PNNL
439
- end
440
-
441
- # pass back schedulesHVAC hash
442
- result = schedulesHVAC
443
- return result
444
- end
445
-
446
- def self.createHotWaterPlant(model, runner, hot_water_setpoint_schedule, loop_type)
447
- hot_water_plant = OpenStudio::Model::PlantLoop.new(model)
448
- hot_water_plant.setName("AEDG #{loop_type} Loop")
449
- hot_water_plant.setMaximumLoopTemperature(100)
450
- hot_water_plant.setMinimumLoopTemperature(10)
451
- loop_sizing = hot_water_plant.sizingPlant
452
- loop_sizing.setLoopType('Heating')
453
- if loop_type == 'Hot Water'
454
- loop_sizing.setDesignLoopExitTemperature(82)
455
- elsif loop_type == 'Radiant Hot Water'
456
- loop_sizing.setDesignLoopExitTemperature(60) # ML follows convention of sizing temp being larger than supplu temp
457
- end
458
- loop_sizing.setLoopDesignTemperatureDifference(11)
459
- # create a pump
460
- pump = OpenStudio::Model::PumpVariableSpeed.new(model)
461
- pump.setRatedPumpHead(119563) # Pa
462
- pump.setMotorEfficiency(0.9)
463
- pump.setCoefficient1ofthePartLoadPerformanceCurve(0)
464
- pump.setCoefficient2ofthePartLoadPerformanceCurve(0.0216)
465
- pump.setCoefficient3ofthePartLoadPerformanceCurve(-0.0325)
466
- pump.setCoefficient4ofthePartLoadPerformanceCurve(1.0095)
467
- # create a boiler
468
- boiler = OpenStudio::Model::BoilerHotWater.new(model)
469
- boiler.setNominalThermalEfficiency(0.9)
470
- # create a scheduled setpoint manager
471
- setpoint_manager_scheduled = OpenStudio::Model::SetpointManagerScheduled.new(model, hot_water_setpoint_schedule)
472
- # create a supply bypass pipe
473
- pipe_supply_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
474
- # create a supply outlet pipe
475
- pipe_supply_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
476
- # create a demand bypass pipe
477
- pipe_demand_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
478
- # create a demand inlet pipe
479
- pipe_demand_inlet = OpenStudio::Model::PipeAdiabatic.new(model)
480
- # create a demand outlet pipe
481
- pipe_demand_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
482
- # connect components to plant loop
483
- # supply side components
484
- hot_water_plant.addSupplyBranchForComponent(boiler)
485
- hot_water_plant.addSupplyBranchForComponent(pipe_supply_bypass)
486
- pump.addToNode(hot_water_plant.supplyInletNode)
487
- pipe_supply_outlet.addToNode(hot_water_plant.supplyOutletNode)
488
- setpoint_manager_scheduled.addToNode(hot_water_plant.supplyOutletNode)
489
- # demand side components (water coils are added as they are added to airloops and zoneHVAC)
490
- hot_water_plant.addDemandBranchForComponent(pipe_demand_bypass)
491
- pipe_demand_inlet.addToNode(hot_water_plant.demandInletNode)
492
- pipe_demand_outlet.addToNode(hot_water_plant.demandOutletNode)
493
-
494
- # pass back hot water plant
495
- result = hot_water_plant
496
- return result
497
- end
498
-
499
- def self.createChilledWaterPlant(model, runner, chilled_water_setpoint_schedule, loop_type, chillerType)
500
- # chilled water plant
501
- chilled_water_plant = OpenStudio::Model::PlantLoop.new(model)
502
- chilled_water_plant.setName("AEDG #{loop_type} Loop")
503
- chilled_water_plant.setMaximumLoopTemperature(98)
504
- chilled_water_plant.setMinimumLoopTemperature(1)
505
- loop_sizing = chilled_water_plant.sizingPlant
506
- loop_sizing.setLoopType('Cooling')
507
- if loop_type == 'Chilled Water'
508
- loop_sizing.setDesignLoopExitTemperature(6.7)
509
- elsif loop_type == 'Radiant Chilled Water'
510
- loop_sizing.setDesignLoopExitTemperature(15)
511
- end
512
- loop_sizing.setLoopDesignTemperatureDifference(6.7)
513
- # create a pump
514
- pump = OpenStudio::Model::PumpVariableSpeed.new(model)
515
- pump.setRatedPumpHead(149453) # Pa
516
- pump.setMotorEfficiency(0.9)
517
- pump.setCoefficient1ofthePartLoadPerformanceCurve(0)
518
- pump.setCoefficient2ofthePartLoadPerformanceCurve(0.0216)
519
- pump.setCoefficient3ofthePartLoadPerformanceCurve(-0.0325)
520
- pump.setCoefficient4ofthePartLoadPerformanceCurve(1.0095)
521
- # create a chiller
522
- if chillerType == 'WaterCooled'
523
- # create clgCapFuncTempCurve
524
- clgCapFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
525
- clgCapFuncTempCurve.setCoefficient1Constant(1.07E+00)
526
- clgCapFuncTempCurve.setCoefficient2x(4.29E-02)
527
- clgCapFuncTempCurve.setCoefficient3xPOW2(4.17E-04)
528
- clgCapFuncTempCurve.setCoefficient4y(-8.10E-03)
529
- clgCapFuncTempCurve.setCoefficient5yPOW2(-4.02E-05)
530
- clgCapFuncTempCurve.setCoefficient6xTIMESY(-3.86E-04)
531
- clgCapFuncTempCurve.setMinimumValueofx(0)
532
- clgCapFuncTempCurve.setMaximumValueofx(20)
533
- clgCapFuncTempCurve.setMinimumValueofy(0)
534
- clgCapFuncTempCurve.setMaximumValueofy(50)
535
- # create eirFuncTempCurve
536
- eirFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
537
- eirFuncTempCurve.setCoefficient1Constant(4.68E-01)
538
- eirFuncTempCurve.setCoefficient2x(-1.38E-02)
539
- eirFuncTempCurve.setCoefficient3xPOW2(6.98E-04)
540
- eirFuncTempCurve.setCoefficient4y(1.09E-02)
541
- eirFuncTempCurve.setCoefficient5yPOW2(4.62E-04)
542
- eirFuncTempCurve.setCoefficient6xTIMESY(-6.82E-04)
543
- eirFuncTempCurve.setMinimumValueofx(0)
544
- eirFuncTempCurve.setMaximumValueofx(20)
545
- eirFuncTempCurve.setMinimumValueofy(0)
546
- eirFuncTempCurve.setMaximumValueofy(50)
547
- # create eirFuncPlrCurve
548
- eirFuncPlrCurve = OpenStudio::Model::CurveQuadratic.new(model)
549
- eirFuncPlrCurve.setCoefficient1Constant(1.41E-01)
550
- eirFuncPlrCurve.setCoefficient2x(6.55E-01)
551
- eirFuncPlrCurve.setCoefficient3xPOW2(2.03E-01)
552
- eirFuncPlrCurve.setMinimumValueofx(0)
553
- eirFuncPlrCurve.setMaximumValueofx(1.2)
554
- # construct chiller
555
- chiller = OpenStudio::Model::ChillerElectricEIR.new(model, clgCapFuncTempCurve, eirFuncTempCurve, eirFuncPlrCurve)
556
- chiller.setReferenceCOP(6.1)
557
- chiller.setCondenserType('WaterCooled')
558
- chiller.setChillerFlowMode('ConstantFlow')
559
- elsif chillerType == 'AirCooled'
560
- # create clgCapFuncTempCurve
561
- clgCapFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
562
- clgCapFuncTempCurve.setCoefficient1Constant(1.05E+00)
563
- clgCapFuncTempCurve.setCoefficient2x(3.36E-02)
564
- clgCapFuncTempCurve.setCoefficient3xPOW2(2.15E-04)
565
- clgCapFuncTempCurve.setCoefficient4y(-5.18E-03)
566
- clgCapFuncTempCurve.setCoefficient5yPOW2(-4.42E-05)
567
- clgCapFuncTempCurve.setCoefficient6xTIMESY(-2.15E-04)
568
- clgCapFuncTempCurve.setMinimumValueofx(0)
569
- clgCapFuncTempCurve.setMaximumValueofx(20)
570
- clgCapFuncTempCurve.setMinimumValueofy(0)
571
- clgCapFuncTempCurve.setMaximumValueofy(50)
572
- # create eirFuncTempCurve
573
- eirFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
574
- eirFuncTempCurve.setCoefficient1Constant(5.83E-01)
575
- eirFuncTempCurve.setCoefficient2x(-4.04E-03)
576
- eirFuncTempCurve.setCoefficient3xPOW2(4.68E-04)
577
- eirFuncTempCurve.setCoefficient4y(-2.24E-04)
578
- eirFuncTempCurve.setCoefficient5yPOW2(4.81E-04)
579
- eirFuncTempCurve.setCoefficient6xTIMESY(-6.82E-04)
580
- eirFuncTempCurve.setMinimumValueofx(0)
581
- eirFuncTempCurve.setMaximumValueofx(20)
582
- eirFuncTempCurve.setMinimumValueofy(0)
583
- eirFuncTempCurve.setMaximumValueofy(50)
584
- # create eirFuncPlrCurve
585
- eirFuncPlrCurve = OpenStudio::Model::CurveQuadratic.new(model)
586
- eirFuncPlrCurve.setCoefficient1Constant(4.19E-02)
587
- eirFuncPlrCurve.setCoefficient2x(6.25E-01)
588
- eirFuncPlrCurve.setCoefficient3xPOW2(3.23E-01)
589
- eirFuncPlrCurve.setMinimumValueofx(0)
590
- eirFuncPlrCurve.setMaximumValueofx(1.2)
591
- # construct chiller
592
- chiller = OpenStudio::Model::ChillerElectricEIR.new(model, clgCapFuncTempCurve, eirFuncTempCurve, eirFuncPlrCurve)
593
- chiller.setReferenceCOP(2.93)
594
- chiller.setCondenserType('AirCooled')
595
- chiller.setChillerFlowMode('ConstantFlow')
596
- end
597
- # create a scheduled setpoint manager
598
- setpoint_manager_scheduled = OpenStudio::Model::SetpointManagerScheduled.new(model, chilled_water_setpoint_schedule)
599
- # create a supply bypass pipe
600
- pipe_supply_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
601
- # create a supply outlet pipe
602
- pipe_supply_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
603
- # create a demand bypass pipe
604
- pipe_demand_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
605
- # create a demand inlet pipe
606
- pipe_demand_inlet = OpenStudio::Model::PipeAdiabatic.new(model)
607
- # create a demand outlet pipe
608
- pipe_demand_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
609
- # connect components to plant loop
610
- # supply side components
611
- chilled_water_plant.addSupplyBranchForComponent(chiller)
612
- chilled_water_plant.addSupplyBranchForComponent(pipe_supply_bypass)
613
- pump.addToNode(chilled_water_plant.supplyInletNode)
614
- pipe_supply_outlet.addToNode(chilled_water_plant.supplyOutletNode)
615
- setpoint_manager_scheduled.addToNode(chilled_water_plant.supplyOutletNode)
616
- # demand side components (water coils are added as they are added to airloops and ZoneHVAC)
617
- chilled_water_plant.addDemandBranchForComponent(pipe_demand_bypass)
618
- pipe_demand_inlet.addToNode(chilled_water_plant.demandInletNode)
619
- pipe_demand_outlet.addToNode(chilled_water_plant.demandOutletNode)
620
-
621
- # pass back chilled water plant
622
- result = chilled_water_plant
623
- return result
624
- end
625
-
626
- def self.createCondenserLoop(model, runner, options)
627
- condenserLoops = {}
628
-
629
- # check for water-cooled chillers
630
- waterCooledChiller = false
631
- model.getChillerElectricEIRs.each do |chiller|
632
- next if waterCooledChiller == true
633
- if chiller.condenserType == 'WaterCooled'
634
- waterCooledChiller = true
635
- end
636
- end
637
- # create condenser loop for water-cooled chillers
638
- if waterCooledChiller
639
- # create condenser loop for water-cooled chiller(s)
640
- condenser_loop = OpenStudio::Model::PlantLoop.new(model)
641
- condenser_loop.setName('AEDG Condenser Loop')
642
- condenser_loop.setMaximumLoopTemperature(80)
643
- condenser_loop.setMinimumLoopTemperature(5)
644
- loop_sizing = condenser_loop.sizingPlant
645
- loop_sizing.setLoopType('Condenser')
646
- loop_sizing.setDesignLoopExitTemperature(29.4)
647
- loop_sizing.setLoopDesignTemperatureDifference(5.6)
648
- # create a pump
649
- pump = OpenStudio::Model::PumpVariableSpeed.new(model)
650
- pump.setRatedPumpHead(134508) # Pa
651
- pump.setMotorEfficiency(0.9)
652
- pump.setCoefficient1ofthePartLoadPerformanceCurve(0)
653
- pump.setCoefficient2ofthePartLoadPerformanceCurve(0.0216)
654
- pump.setCoefficient3ofthePartLoadPerformanceCurve(-0.0325)
655
- pump.setCoefficient4ofthePartLoadPerformanceCurve(1.0095)
656
- # create a cooling tower
657
- tower = OpenStudio::Model::CoolingTowerVariableSpeed.new(model)
658
- # create a supply bypass pipe
659
- pipe_supply_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
660
- # create a supply outlet pipe
661
- pipe_supply_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
662
- # create a demand bypass pipe
663
- pipe_demand_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
664
- # create a demand inlet pipe
665
- pipe_demand_inlet = OpenStudio::Model::PipeAdiabatic.new(model)
666
- # create a demand outlet pipe
667
- pipe_demand_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
668
- # create a setpoint manager
669
- setpoint_manager_follow_oa = OpenStudio::Model::SetpointManagerFollowOutdoorAirTemperature.new(model)
670
- setpoint_manager_follow_oa.setOffsetTemperatureDifference(0)
671
- setpoint_manager_follow_oa.setMaximumSetpointTemperature(80)
672
- setpoint_manager_follow_oa.setMinimumSetpointTemperature(5)
673
- # connect components to plant loop
674
- # supply side components
675
- condenser_loop.addSupplyBranchForComponent(tower)
676
- condenser_loop.addSupplyBranchForComponent(pipe_supply_bypass)
677
- pump.addToNode(condenser_loop.supplyInletNode)
678
- pipe_supply_outlet.addToNode(condenser_loop.supplyOutletNode)
679
- setpoint_manager_follow_oa.addToNode(condenser_loop.supplyOutletNode)
680
- # demand side components
681
- model.getChillerElectricEIRs.each do |chiller|
682
- if chiller.condenserType == 'WaterCooled' # works only if chillers not already connected to condenser loop(s)
683
- condenser_loop.addDemandBranchForComponent(chiller)
684
- end
685
- end
686
- condenser_loop.addDemandBranchForComponent(pipe_demand_bypass)
687
- pipe_demand_inlet.addToNode(condenser_loop.demandInletNode)
688
- pipe_demand_outlet.addToNode(condenser_loop.demandOutletNode)
689
- condenserLoops['condenser_loop'] = condenser_loop
690
- end
691
- if options['zoneHVAC'].include? 'GSHP'
692
- # create condenser loop for heat pumps
693
- condenser_loop = OpenStudio::Model::PlantLoop.new(model)
694
- condenser_loop.setName('AEDG Heat Pump Loop')
695
- condenser_loop.setMaximumLoopTemperature(80)
696
- condenser_loop.setMinimumLoopTemperature(1)
697
- loop_sizing = condenser_loop.sizingPlant
698
- loop_sizing.setLoopType('Condenser')
699
- if options['zoneHVAC'] == 'GSHP'
700
- loop_sizing.setDesignLoopExitTemperature(21)
701
- loop_sizing.setLoopDesignTemperatureDifference(5)
702
- elsif options['zoneHVAC'] == 'WSHP'
703
- loop_sizing.setDesignLoopExitTemperature(30) # PNNL
704
- loop_sizing.setLoopDesignTemperatureDifference(20) # PNNL
705
- end
706
- # create a pump
707
- pump = OpenStudio::Model::PumpVariableSpeed.new(model)
708
- pump.setRatedPumpHead(134508) # Pa
709
- pump.setMotorEfficiency(0.9)
710
- pump.setCoefficient1ofthePartLoadPerformanceCurve(0)
711
- pump.setCoefficient2ofthePartLoadPerformanceCurve(0.0216)
712
- pump.setCoefficient3ofthePartLoadPerformanceCurve(-0.0325)
713
- pump.setCoefficient4ofthePartLoadPerformanceCurve(1.0095)
714
- # create a supply bypass pipe
715
- pipe_supply_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
716
- # create a supply outlet pipe
717
- pipe_supply_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
718
- # create a demand bypass pipe
719
- pipe_demand_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
720
- # create a demand inlet pipe
721
- pipe_demand_inlet = OpenStudio::Model::PipeAdiabatic.new(model)
722
- # create a demand outlet pipe
723
- pipe_demand_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
724
- # create setpoint managers
725
- setpoint_manager_scheduled_loop = OpenStudio::Model::SetpointManagerScheduled.new(model, options['loop_setpoint_schedule'])
726
- setpoint_manager_scheduled_cooling = OpenStudio::Model::SetpointManagerScheduled.new(model, options['cooling_setpoint_schedule'])
727
- setpoint_manager_scheduled_heating = OpenStudio::Model::SetpointManagerScheduled.new(model, options['heating_setpoint_schedule'])
728
- # connect components to plant loop
729
- # supply side components
730
- condenser_loop.addSupplyBranchForComponent(pipe_supply_bypass)
731
- pump.addToNode(condenser_loop.supplyInletNode)
732
- pipe_supply_outlet.addToNode(condenser_loop.supplyOutletNode)
733
- setpoint_manager_scheduled_loop.addToNode(condenser_loop.supplyOutletNode)
734
- # demand side components
735
- condenser_loop.addDemandBranchForComponent(pipe_demand_bypass)
736
- pipe_demand_inlet.addToNode(condenser_loop.demandInletNode)
737
- pipe_demand_outlet.addToNode(condenser_loop.demandOutletNode)
738
- # add additional components according to specific system type
739
- if options['zoneHVAC'] == 'GSHP'
740
- # add district cooling and heating to supply side
741
- district_cooling = OpenStudio::Model::DistrictCooling.new(model)
742
- district_cooling.setNominalCapacity(1000000000000) # large number; no autosizing
743
- condenser_loop.addSupplyBranchForComponent(district_cooling)
744
- setpoint_manager_scheduled_cooling.addToNode(district_cooling.outletModelObject.get.to_Node.get)
745
- district_heating = OpenStudio::Model::DistrictHeating.new(model)
746
- district_heating.setNominalCapacity(1000000000000) # large number; no autosizing
747
- district_heating.addToNode(district_cooling.outletModelObject.get.to_Node.get)
748
- setpoint_manager_scheduled_heating.addToNode(district_heating.outletModelObject.get.to_Node.get)
749
- # add heat pumps to demand side after they get created
750
- elsif options['zoneHVAC'] == 'WSHP'
751
- # add a boiler and cooling tower to supply side
752
- # create a boiler
753
- boiler = OpenStudio::Model::BoilerHotWater.new(model)
754
- boiler.setNominalThermalEfficiency(0.9)
755
- condenser_loop.addSupplyBranchForComponent(boiler)
756
- setpoint_manager_scheduled_heating.addToNode(boiler.outletModelObject.get.to_Node.get)
757
- # create a cooling tower
758
- tower = OpenStudio::Model::CoolingTowerSingleSpeed.new(model)
759
- tower.addToNode(boiler.outletModelObject.get.to_Node.get)
760
- setpoint_manager_scheduled_cooling.addToNode(tower.outletModelObject.get.to_Node.get)
761
- end
762
- condenserLoops['heat_pump_loop'] = condenser_loop
763
- end
764
-
765
- # pass back condenser loop(s)
766
- result = condenserLoops
767
- return result
768
- end
769
-
770
- def self.createPrimaryAirLoops(model, runner, options)
771
- primary_airloops = []
772
- # create primary airloop for each story
773
- assignedThermalZones = []
774
- model.getBuildingStorys.each do |building_story|
775
- # ML stories need to be reordered from the ground up
776
- thermalZonesToAdd = []
777
- building_story.spaces.each do |space|
778
- # make sure spaces are assigned to thermal zones
779
- # otherwise might want to send a warning
780
- if space.thermalZone
781
- thermal_zone = space.thermalZone.get
782
- # grab primary zones
783
- if options['zonesPrimary'].include? thermal_zone
784
- # make sure zone was not already assigned to another air loop
785
- unless assignedThermalZones.include? thermal_zone
786
- # make sure thermal zones are not duplicated (spaces can share thermal zones)
787
- unless thermalZonesToAdd.include? thermal_zone
788
- thermalZonesToAdd << thermal_zone
789
- end
790
- end
791
- end
792
- end
793
- end
794
- # make sure thermal zones don't get added to more than one air loop
795
- assignedThermalZones << thermalZonesToAdd
796
-
797
- # create new air loop if story contains primary zones
798
- unless thermalZonesToAdd.empty?
799
- airloop_primary = OpenStudio::Model::AirLoopHVAC.new(model)
800
- airloop_primary.setName("AEDG Air Loop HVAC #{building_story.name}")
801
- # modify system sizing properties
802
- sizing_system = airloop_primary.sizingSystem
803
- # set central heating and cooling temperatures for sizing
804
- sizing_system.setCentralCoolingDesignSupplyAirTemperature(12.8)
805
- sizing_system.setCentralHeatingDesignSupplyAirTemperature(40) # ML OS default is 16.7
806
- # load specification
807
- sizing_system.setSystemOutdoorAirMethod('VentilationRateProcedure') # ML OS default is ZoneSum
808
- if options['primaryHVAC']['doas']
809
- sizing_system.setTypeofLoadtoSizeOn('VentilationRequirement') # DOAS
810
- sizing_system.setAllOutdoorAirinCooling(true) # DOAS
811
- sizing_system.setAllOutdoorAirinHeating(true) # DOAS
812
- else
813
- sizing_system.setTypeofLoadtoSizeOn('Sensible') # VAV
814
- sizing_system.setAllOutdoorAirinCooling(false) # VAV
815
- sizing_system.setAllOutdoorAirinHeating(false) # VAV
816
- end
817
-
818
- air_loop_comps = []
819
- # set availability schedule
820
- airloop_primary.setAvailabilitySchedule(options['hvac_schedule'])
821
- # create air loop fan
822
- if options['primaryHVAC']['fan'] == 'Variable'
823
- # create variable speed fan and set system sizing accordingly
824
- sizing_system.setMinimumSystemAirFlowRatio(0.3) # DCV
825
- # variable speed fan
826
- fan = OpenStudio::Model::FanVariableVolume.new(model, model.alwaysOnDiscreteSchedule)
827
- fan.setFanEfficiency(0.69)
828
- fan.setPressureRise(1125) # Pa
829
- fan.autosizeMaximumFlowRate
830
- fan.setFanPowerMinimumFlowFraction(0.6)
831
- fan.setMotorEfficiency(0.9)
832
- fan.setMotorInAirstreamFraction(1.0)
833
- air_loop_comps << fan
834
- else
835
- sizing_system.setMinimumSystemAirFlowRatio(1.0) # No DCV
836
- # constant speed fan
837
- fan = OpenStudio::Model::FanConstantVolume.new(model, model.alwaysOnDiscreteSchedule)
838
- fan.setFanEfficiency(0.6)
839
- fan.setPressureRise(500) # Pa
840
- fan.autosizeMaximumFlowRate
841
- fan.setMotorEfficiency(0.9)
842
- fan.setMotorInAirstreamFraction(1.0)
843
- air_loop_comps << fan
844
- end
845
- # create heating coil
846
- if options['primaryHVAC']['heat'] == 'Water'
847
- # water coil
848
- heating_coil = OpenStudio::Model::CoilHeatingWater.new(model, model.alwaysOnDiscreteSchedule)
849
- air_loop_comps << heating_coil
850
- else
851
- # gas coil
852
- heating_coil = OpenStudio::Model::CoilHeatingGas.new(model, model.alwaysOnDiscreteSchedule)
853
- air_loop_comps << heating_coil
854
- end
855
- # create cooling coil
856
- if options['primaryHVAC']['cool'] == 'Water'
857
- # water coil
858
- cooling_coil = OpenStudio::Model::CoilCoolingWater.new(model, model.alwaysOnDiscreteSchedule)
859
- air_loop_comps << cooling_coil
860
- elsif options['primaryHVAC']['cool'] == 'SingleDX'
861
- # single speed DX coil
862
- # create cooling coil
863
- # create clgCapFuncTempCurve
864
- clgCapFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
865
- clgCapFuncTempCurve.setCoefficient1Constant(0.42415)
866
- clgCapFuncTempCurve.setCoefficient2x(0.04426)
867
- clgCapFuncTempCurve.setCoefficient3xPOW2(-0.00042)
868
- clgCapFuncTempCurve.setCoefficient4y(0.00333)
869
- clgCapFuncTempCurve.setCoefficient5yPOW2(-0.00008)
870
- clgCapFuncTempCurve.setCoefficient6xTIMESY(-0.00021)
871
- clgCapFuncTempCurve.setMinimumValueofx(17)
872
- clgCapFuncTempCurve.setMaximumValueofx(22)
873
- clgCapFuncTempCurve.setMinimumValueofy(13)
874
- clgCapFuncTempCurve.setMaximumValueofy(46)
875
- # create clgCapFuncFlowFracCurve
876
- clgCapFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
877
- clgCapFuncFlowFracCurve.setCoefficient1Constant(0.77136)
878
- clgCapFuncFlowFracCurve.setCoefficient2x(0.34053)
879
- clgCapFuncFlowFracCurve.setCoefficient3xPOW2(-0.11088)
880
- clgCapFuncFlowFracCurve.setMinimumValueofx(0.75918)
881
- clgCapFuncFlowFracCurve.setMaximumValueofx(1.13877)
882
- # create clgEirFuncTempCurve
883
- clgEirFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
884
- clgEirFuncTempCurve.setCoefficient1Constant(1.23649)
885
- clgEirFuncTempCurve.setCoefficient2x(-0.02431)
886
- clgEirFuncTempCurve.setCoefficient3xPOW2(0.00057)
887
- clgEirFuncTempCurve.setCoefficient4y(-0.01434)
888
- clgEirFuncTempCurve.setCoefficient5yPOW2(0.00063)
889
- clgEirFuncTempCurve.setCoefficient6xTIMESY(-0.00038)
890
- clgEirFuncTempCurve.setMinimumValueofx(17)
891
- clgEirFuncTempCurve.setMaximumValueofx(22)
892
- clgEirFuncTempCurve.setMinimumValueofy(13)
893
- clgEirFuncTempCurve.setMaximumValueofy(46)
894
- # create clgEirFuncFlowFracCurve
895
- clgEirFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
896
- clgEirFuncFlowFracCurve.setCoefficient1Constant(1.20550)
897
- clgEirFuncFlowFracCurve.setCoefficient2x(-0.32953)
898
- clgEirFuncFlowFracCurve.setCoefficient3xPOW2(0.12308)
899
- clgEirFuncFlowFracCurve.setMinimumValueofx(0.75918)
900
- clgEirFuncFlowFracCurve.setMaximumValueofx(1.13877)
901
- # create clgPlrCurve
902
- clgPlrCurve = OpenStudio::Model::CurveQuadratic.new(model)
903
- clgPlrCurve.setCoefficient1Constant(0.77100)
904
- clgPlrCurve.setCoefficient2x(0.22900)
905
- clgPlrCurve.setCoefficient3xPOW2(0.0)
906
- clgPlrCurve.setMinimumValueofx(0.0)
907
- clgPlrCurve.setMaximumValueofx(1.0)
908
- # cooling coil
909
- cooling_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model,
910
- model.alwaysOnDiscreteSchedule,
911
- clgCapFuncTempCurve,
912
- clgCapFuncFlowFracCurve,
913
- clgEirFuncTempCurve,
914
- clgEirFuncFlowFracCurve,
915
- clgPlrCurve)
916
- cooling_coil.setRatedCOP(OpenStudio::OptionalDouble.new(4))
917
- air_loop_comps << cooling_coil
918
- else
919
- # two speed DX coil (PNNL curves)
920
- # create cooling coil
921
- # create clgCapFuncTempCurve
922
- clgCapFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
923
- clgCapFuncTempCurve.setCoefficient1Constant(1.39072)
924
- clgCapFuncTempCurve.setCoefficient2x(-0.0529058)
925
- clgCapFuncTempCurve.setCoefficient3xPOW2(0.0018423)
926
- clgCapFuncTempCurve.setCoefficient4y(0.00058267)
927
- clgCapFuncTempCurve.setCoefficient5yPOW2(-0.000186814)
928
- clgCapFuncTempCurve.setCoefficient6xTIMESY(0.000265159)
929
- clgCapFuncTempCurve.setMinimumValueofx(16.5556)
930
- clgCapFuncTempCurve.setMaximumValueofx(22.1111)
931
- clgCapFuncTempCurve.setMinimumValueofy(23.7778)
932
- clgCapFuncTempCurve.setMaximumValueofy(47.66)
933
- # create clgCapFuncFlowFracCurve
934
- clgCapFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
935
- clgCapFuncFlowFracCurve.setCoefficient1Constant(0.718954)
936
- clgCapFuncFlowFracCurve.setCoefficient2x(0.435436)
937
- clgCapFuncFlowFracCurve.setCoefficient3xPOW2(-0.154193)
938
- clgCapFuncFlowFracCurve.setMinimumValueofx(0.75)
939
- clgCapFuncFlowFracCurve.setMaximumValueofx(1.25)
940
- # create clgEirFuncTempCurve
941
- clgEirFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
942
- clgEirFuncTempCurve.setCoefficient1Constant(-0.536161)
943
- clgEirFuncTempCurve.setCoefficient2x(0.105138)
944
- clgEirFuncTempCurve.setCoefficient3xPOW2(-0.00172659)
945
- clgEirFuncTempCurve.setCoefficient4y(0.0149848)
946
- clgEirFuncTempCurve.setCoefficient5yPOW2(0.000659948)
947
- clgEirFuncTempCurve.setCoefficient6xTIMESY(-0.0017385)
948
- clgEirFuncTempCurve.setMinimumValueofx(16.5556)
949
- clgEirFuncTempCurve.setMaximumValueofx(22.1111)
950
- clgEirFuncTempCurve.setMinimumValueofy(23.7778)
951
- clgEirFuncTempCurve.setMaximumValueofy(47.66)
952
- # create clgEirFuncFlowFracCurve
953
- clgEirFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
954
- clgEirFuncFlowFracCurve.setCoefficient1Constant(1.19525)
955
- clgEirFuncFlowFracCurve.setCoefficient2x(-0.306138)
956
- clgEirFuncFlowFracCurve.setCoefficient3xPOW2(0.110973)
957
- clgEirFuncFlowFracCurve.setMinimumValueofx(0.75)
958
- clgEirFuncFlowFracCurve.setMaximumValueofx(1.25)
959
- # create clgPlrCurve
960
- clgPlrCurve = OpenStudio::Model::CurveQuadratic.new(model)
961
- clgPlrCurve.setCoefficient1Constant(0.77100)
962
- clgPlrCurve.setCoefficient2x(0.22900)
963
- clgPlrCurve.setCoefficient3xPOW2(0.0)
964
- clgPlrCurve.setMinimumValueofx(0.0)
965
- clgPlrCurve.setMaximumValueofx(1.0)
966
- # cooling coil
967
- cooling_coil = OpenStudio::Model::CoilCoolingDXTwoSpeed.new(model,
968
- model.alwaysOnDiscreteSchedule,
969
- clgCapFuncTempCurve,
970
- clgCapFuncFlowFracCurve,
971
- clgEirFuncTempCurve,
972
- clgEirFuncFlowFracCurve,
973
- clgPlrCurve,
974
- clgCapFuncTempCurve,
975
- clgEirFuncTempCurve)
976
- cooling_coil.setRatedHighSpeedCOP(4)
977
- cooling_coil.setRatedLowSpeedCOP(4)
978
- air_loop_comps << cooling_coil
979
- end
980
- unless options['zoneHVAC'] == 'DualDuct'
981
- # create controller outdoor air
982
- controller_OA = OpenStudio::Model::ControllerOutdoorAir.new(model)
983
- controller_OA.autosizeMinimumOutdoorAirFlowRate
984
- controller_OA.autosizeMaximumOutdoorAirFlowRate
985
- # create ventilation schedules and assign to OA controller
986
- if options['primaryHVAC']['doas']
987
- controller_OA.setMinimumFractionofOutdoorAirSchedule(model.alwaysOnDiscreteSchedule)
988
- controller_OA.setMaximumFractionofOutdoorAirSchedule(model.alwaysOnDiscreteSchedule)
989
- else
990
- # multizone VAV that ventilates
991
- controller_OA.setMaximumFractionofOutdoorAirSchedule(options['ventilation_schedule'])
992
- controller_OA.setEconomizerControlType('DifferentialEnthalpy')
993
- # add night cycling (ML would people actually do this for a VAV system?))
994
- airloop_primary.setNightCycleControlType('CycleOnAny') # ML Does this work with variable speed fans?
995
- end
996
- controller_OA.setHeatRecoveryBypassControlType('BypassWhenOAFlowGreaterThanMinimum')
997
- # create outdoor air system
998
- system_OA = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model, controller_OA)
999
- air_loop_comps << system_OA
1000
- # create ERV
1001
- heat_exchanger = OpenStudio::Model::HeatExchangerAirToAirSensibleAndLatent.new(model)
1002
- heat_exchanger.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
1003
- sensible_eff = 0.75
1004
- latent_eff = 0.69
1005
- heat_exchanger.setSensibleEffectivenessat100CoolingAirFlow(sensible_eff)
1006
- heat_exchanger.setSensibleEffectivenessat100HeatingAirFlow(sensible_eff)
1007
- heat_exchanger.setSensibleEffectivenessat75CoolingAirFlow(sensible_eff)
1008
- heat_exchanger.setSensibleEffectivenessat75HeatingAirFlow(sensible_eff)
1009
- heat_exchanger.setLatentEffectivenessat100CoolingAirFlow(latent_eff)
1010
- heat_exchanger.setLatentEffectivenessat100HeatingAirFlow(latent_eff)
1011
- heat_exchanger.setLatentEffectivenessat75CoolingAirFlow(latent_eff)
1012
- heat_exchanger.setLatentEffectivenessat75HeatingAirFlow(latent_eff)
1013
- heat_exchanger.setFrostControlType('ExhaustOnly')
1014
- heat_exchanger.setThresholdTemperature(-12.2)
1015
- heat_exchanger.setInitialDefrostTimeFraction(0.1670)
1016
- heat_exchanger.setRateofDefrostTimeFractionIncrease(0.0240)
1017
- heat_exchanger.setEconomizerLockout(false)
1018
- end
1019
- # create scheduled setpoint manager for airloop
1020
- if options['primaryHVAC']['doas'] || (options['zoneHVAC'] == 'DualDuct')
1021
- # DOAS or VAV for cooling and not ventilation
1022
- setpoint_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, options['primary_sat_schedule'])
1023
- else
1024
- # VAV for cooling and ventilation
1025
- setpoint_manager = OpenStudio::Model::SetpointManagerOutdoorAirReset.new(model)
1026
- setpoint_manager.setSetpointatOutdoorLowTemperature(15.6)
1027
- setpoint_manager.setOutdoorLowTemperature(14.4)
1028
- setpoint_manager.setSetpointatOutdoorHighTemperature(12.8)
1029
- setpoint_manager.setOutdoorHighTemperature(21.1)
1030
- end
1031
- # connect components to airloop
1032
- # find the supply inlet node of the airloop
1033
- airloop_supply_inlet = airloop_primary.supplyInletNode
1034
- # add the components to the airloop
1035
- air_loop_comps.each do |comp|
1036
- comp.addToNode(airloop_supply_inlet)
1037
- if comp.to_CoilHeatingWater.is_initialized
1038
- options['hot_water_plant'].addDemandBranchForComponent(comp)
1039
- elsif comp.to_CoilCoolingWater.is_initialized
1040
- options['chilled_water_plant'].addDemandBranchForComponent(comp)
1041
- end
1042
- end
1043
- # add erv to outdoor air system
1044
- unless options['zoneHVAC'] == 'DualDuct'
1045
- heat_exchanger.addToNode(system_OA.outboardOANode.get)
1046
- end
1047
- # add setpoint manager to supply equipment outlet node
1048
- setpoint_manager.addToNode(airloop_primary.supplyOutletNode)
1049
- # add thermal zones to airloop
1050
- thermalZonesToAdd.each do |zone|
1051
- # make an air terminal for the zone
1052
- if options['primaryHVAC']['fan'] == 'Variable'
1053
- air_terminal = OpenStudio::Model::AirTerminalSingleDuctVAVNoReheat.new(model, model.alwaysOnDiscreteSchedule)
1054
- else
1055
- air_terminal = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, model.alwaysOnDiscreteSchedule)
1056
- end
1057
- # attach new terminal to the zone and to the airloop
1058
- airloop_primary.addBranchForZone(zone, air_terminal.to_StraightComponent)
1059
- end
1060
- primary_airloops << airloop_primary
1061
- end
1062
- end
1063
-
1064
- # pass back primary airloops
1065
- result = primary_airloops
1066
- return result
1067
- end
1068
-
1069
- def self.createSecondaryAirLoops(model, runner, options)
1070
- secondary_airloops = []
1071
- # create secondary airloop for each secondary zone
1072
- model.getThermalZones.each do |zone|
1073
- if options['zonesSecondary'].include? zone
1074
- # create secondary airloop
1075
- airloop_secondary = OpenStudio::Model::AirLoopHVAC.new(model)
1076
- airloop_secondary.setName("AEDG Air Loop HVAC #{zone.name}")
1077
- # modify system sizing properties
1078
- sizing_system = airloop_secondary.sizingSystem
1079
- # set central heating and cooling temperatures for sizing
1080
- sizing_system.setCentralCoolingDesignSupplyAirTemperature(12.8)
1081
- sizing_system.setCentralHeatingDesignSupplyAirTemperature(40) # ML OS default is 16.7
1082
- # load specification
1083
- sizing_system.setSystemOutdoorAirMethod('VentilationRateProcedure') # ML OS default is ZoneSum
1084
- sizing_system.setTypeofLoadtoSizeOn('Sensible') # PSZ
1085
- sizing_system.setAllOutdoorAirinCooling(false) # PSZ
1086
- sizing_system.setAllOutdoorAirinHeating(false) # PSZ
1087
- sizing_system.setMinimumSystemAirFlowRatio(1.0) # Constant volume fan
1088
- air_loop_comps = []
1089
- # set availability schedule (HVAC operation schedule)
1090
- airloop_secondary.setAvailabilitySchedule(options['hvac_schedule'])
1091
- if options['secondaryHVAC']['fan'] == 'Variable'
1092
- # create variable speed fan and set system sizing accordingly
1093
- sizing_system.setMinimumSystemAirFlowRatio(0.3) # DCV
1094
- # variable speed fan
1095
- fan = OpenStudio::Model::FanVariableVolume.new(model, model.alwaysOnDiscreteSchedule)
1096
- fan.setFanEfficiency(0.69)
1097
- fan.setPressureRise(1125) # Pa
1098
- fan.autosizeMaximumFlowRate
1099
- fan.setFanPowerMinimumFlowFraction(0.6)
1100
- fan.setMotorEfficiency(0.9)
1101
- fan.setMotorInAirstreamFraction(1.0)
1102
- air_loop_comps << fan
1103
- else
1104
- sizing_system.setMinimumSystemAirFlowRatio(1.0) # No DCV
1105
- # constant speed fan
1106
- fan = OpenStudio::Model::FanConstantVolume.new(model, model.alwaysOnDiscreteSchedule)
1107
- fan.setFanEfficiency(0.6)
1108
- fan.setPressureRise(500) # Pa
1109
- fan.autosizeMaximumFlowRate
1110
- fan.setMotorEfficiency(0.9)
1111
- fan.setMotorInAirstreamFraction(1.0)
1112
- air_loop_comps << fan
1113
- end
1114
- # create cooling coil
1115
- if options['secondaryHVAC']['cool'] == 'Water'
1116
- # water coil
1117
- cooling_coil = OpenStudio::Model::CoilCoolingWater.new(model, model.alwaysOnDiscreteSchedule)
1118
- air_loop_comps << cooling_coil
1119
- elsif options['secondaryHVAC']['cool'] == 'SingleDX'
1120
- # single speed DX coil
1121
- # create cooling coil
1122
- # create clgCapFuncTempCurve
1123
- clgCapFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
1124
- clgCapFuncTempCurve.setCoefficient1Constant(0.42415)
1125
- clgCapFuncTempCurve.setCoefficient2x(0.04426)
1126
- clgCapFuncTempCurve.setCoefficient3xPOW2(-0.00042)
1127
- clgCapFuncTempCurve.setCoefficient4y(0.00333)
1128
- clgCapFuncTempCurve.setCoefficient5yPOW2(-0.00008)
1129
- clgCapFuncTempCurve.setCoefficient6xTIMESY(-0.00021)
1130
- clgCapFuncTempCurve.setMinimumValueofx(17)
1131
- clgCapFuncTempCurve.setMaximumValueofx(22)
1132
- clgCapFuncTempCurve.setMinimumValueofy(13)
1133
- clgCapFuncTempCurve.setMaximumValueofy(46)
1134
- # create clgCapFuncFlowFracCurve
1135
- clgCapFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
1136
- clgCapFuncFlowFracCurve.setCoefficient1Constant(0.77136)
1137
- clgCapFuncFlowFracCurve.setCoefficient2x(0.34053)
1138
- clgCapFuncFlowFracCurve.setCoefficient3xPOW2(-0.11088)
1139
- clgCapFuncFlowFracCurve.setMinimumValueofx(0.75918)
1140
- clgCapFuncFlowFracCurve.setMaximumValueofx(1.13877)
1141
- # create clgEirFuncTempCurve
1142
- clgEirFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
1143
- clgEirFuncTempCurve.setCoefficient1Constant(1.23649)
1144
- clgEirFuncTempCurve.setCoefficient2x(-0.02431)
1145
- clgEirFuncTempCurve.setCoefficient3xPOW2(0.00057)
1146
- clgEirFuncTempCurve.setCoefficient4y(-0.01434)
1147
- clgEirFuncTempCurve.setCoefficient5yPOW2(0.00063)
1148
- clgEirFuncTempCurve.setCoefficient6xTIMESY(-0.00038)
1149
- clgEirFuncTempCurve.setMinimumValueofx(17)
1150
- clgEirFuncTempCurve.setMaximumValueofx(22)
1151
- clgEirFuncTempCurve.setMinimumValueofy(13)
1152
- clgEirFuncTempCurve.setMaximumValueofy(46)
1153
- # create clgEirFuncFlowFracCurve
1154
- clgEirFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
1155
- clgEirFuncFlowFracCurve.setCoefficient1Constant(1.20550)
1156
- clgEirFuncFlowFracCurve.setCoefficient2x(-0.32953)
1157
- clgEirFuncFlowFracCurve.setCoefficient3xPOW2(0.12308)
1158
- clgEirFuncFlowFracCurve.setMinimumValueofx(0.75918)
1159
- clgEirFuncFlowFracCurve.setMaximumValueofx(1.13877)
1160
- # create clgPlrCurve
1161
- clgPlrCurve = OpenStudio::Model::CurveQuadratic.new(model)
1162
- clgPlrCurve.setCoefficient1Constant(0.77100)
1163
- clgPlrCurve.setCoefficient2x(0.22900)
1164
- clgPlrCurve.setCoefficient3xPOW2(0.0)
1165
- clgPlrCurve.setMinimumValueofx(0.0)
1166
- clgPlrCurve.setMaximumValueofx(1.0)
1167
- # cooling coil
1168
- cooling_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model,
1169
- model.alwaysOnDiscreteSchedule,
1170
- clgCapFuncTempCurve,
1171
- clgCapFuncFlowFracCurve,
1172
- clgEirFuncTempCurve,
1173
- clgEirFuncFlowFracCurve,
1174
- clgPlrCurve)
1175
- cooling_coil.setRatedCOP(OpenStudio::OptionalDouble.new(4))
1176
- air_loop_comps << cooling_coil
1177
- else
1178
- # two speed DX coil (PNNL curves)
1179
- # create cooling coil
1180
- # create clgCapFuncTempCurve
1181
- clgCapFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
1182
- clgCapFuncTempCurve.setCoefficient1Constant(1.39072)
1183
- clgCapFuncTempCurve.setCoefficient2x(-0.0529058)
1184
- clgCapFuncTempCurve.setCoefficient3xPOW2(0.0018423)
1185
- clgCapFuncTempCurve.setCoefficient4y(0.00058267)
1186
- clgCapFuncTempCurve.setCoefficient5yPOW2(-0.000186814)
1187
- clgCapFuncTempCurve.setCoefficient6xTIMESY(0.000265159)
1188
- clgCapFuncTempCurve.setMinimumValueofx(16.5556)
1189
- clgCapFuncTempCurve.setMaximumValueofx(22.1111)
1190
- clgCapFuncTempCurve.setMinimumValueofy(23.7778)
1191
- clgCapFuncTempCurve.setMaximumValueofy(47.66)
1192
- # create clgCapFuncFlowFracCurve
1193
- clgCapFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
1194
- clgCapFuncFlowFracCurve.setCoefficient1Constant(0.718954)
1195
- clgCapFuncFlowFracCurve.setCoefficient2x(0.435436)
1196
- clgCapFuncFlowFracCurve.setCoefficient3xPOW2(-0.154193)
1197
- clgCapFuncFlowFracCurve.setMinimumValueofx(0.75)
1198
- clgCapFuncFlowFracCurve.setMaximumValueofx(1.25)
1199
- # create clgEirFuncTempCurve
1200
- clgEirFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
1201
- clgEirFuncTempCurve.setCoefficient1Constant(-0.536161)
1202
- clgEirFuncTempCurve.setCoefficient2x(0.105138)
1203
- clgEirFuncTempCurve.setCoefficient3xPOW2(-0.00172659)
1204
- clgEirFuncTempCurve.setCoefficient4y(0.0149848)
1205
- clgEirFuncTempCurve.setCoefficient5yPOW2(0.000659948)
1206
- clgEirFuncTempCurve.setCoefficient6xTIMESY(-0.0017385)
1207
- clgEirFuncTempCurve.setMinimumValueofx(16.5556)
1208
- clgEirFuncTempCurve.setMaximumValueofx(22.1111)
1209
- clgEirFuncTempCurve.setMinimumValueofy(23.7778)
1210
- clgEirFuncTempCurve.setMaximumValueofy(47.66)
1211
- # create clgEirFuncFlowFracCurve
1212
- clgEirFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
1213
- clgEirFuncFlowFracCurve.setCoefficient1Constant(1.19525)
1214
- clgEirFuncFlowFracCurve.setCoefficient2x(-0.306138)
1215
- clgEirFuncFlowFracCurve.setCoefficient3xPOW2(0.110973)
1216
- clgEirFuncFlowFracCurve.setMinimumValueofx(0.75)
1217
- clgEirFuncFlowFracCurve.setMaximumValueofx(1.25)
1218
- # create clgPlrCurve
1219
- clgPlrCurve = OpenStudio::Model::CurveQuadratic.new(model)
1220
- clgPlrCurve.setCoefficient1Constant(0.77100)
1221
- clgPlrCurve.setCoefficient2x(0.22900)
1222
- clgPlrCurve.setCoefficient3xPOW2(0.0)
1223
- clgPlrCurve.setMinimumValueofx(0.0)
1224
- clgPlrCurve.setMaximumValueofx(1.0)
1225
- # cooling coil
1226
- cooling_coil = OpenStudio::Model::CoilCoolingDXTwoSpeed.new(model,
1227
- model.alwaysOnDiscreteSchedule,
1228
- clgCapFuncTempCurve,
1229
- clgCapFuncFlowFracCurve,
1230
- clgEirFuncTempCurve,
1231
- clgEirFuncFlowFracCurve,
1232
- clgPlrCurve,
1233
- clgCapFuncTempCurve,
1234
- clgEirFuncTempCurve)
1235
- cooling_coil.setRatedHighSpeedCOP(4)
1236
- cooling_coil.setRatedLowSpeedCOP(4)
1237
- air_loop_comps << cooling_coil
1238
- end
1239
- if options['secondaryHVAC']['heat'] == 'Water'
1240
- # water coil
1241
- heating_coil = OpenStudio::Model::CoilHeatingWater.new(model, model.alwaysOnDiscreteSchedule)
1242
- air_loop_comps << heating_coil
1243
- else
1244
- # gas coil
1245
- heating_coil = OpenStudio::Model::CoilHeatingGas.new(model, model.alwaysOnDiscreteSchedule)
1246
- air_loop_comps << heating_coil
1247
- end
1248
- # create controller outdoor air
1249
- controller_OA = OpenStudio::Model::ControllerOutdoorAir.new(model)
1250
- controller_OA.autosizeMinimumOutdoorAirFlowRate
1251
- controller_OA.autosizeMaximumOutdoorAirFlowRate
1252
- controller_OA.setEconomizerControlType('DifferentialEnthalpy')
1253
- controller_OA.setMaximumFractionofOutdoorAirSchedule(options['ventilation_schedule'])
1254
- controller_OA.setHeatRecoveryBypassControlType('BypassWhenOAFlowGreaterThanMinimum')
1255
- # create outdoor air system
1256
- system_OA = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model, controller_OA)
1257
- air_loop_comps << system_OA
1258
- # create ERV
1259
- heat_exchanger = OpenStudio::Model::HeatExchangerAirToAirSensibleAndLatent.new(model)
1260
- heat_exchanger.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
1261
- sensible_eff = 0.75
1262
- latent_eff = 0.69
1263
- heat_exchanger.setSensibleEffectivenessat100CoolingAirFlow(sensible_eff)
1264
- heat_exchanger.setSensibleEffectivenessat100HeatingAirFlow(sensible_eff)
1265
- heat_exchanger.setSensibleEffectivenessat75CoolingAirFlow(sensible_eff)
1266
- heat_exchanger.setSensibleEffectivenessat75HeatingAirFlow(sensible_eff)
1267
- heat_exchanger.setLatentEffectivenessat100CoolingAirFlow(latent_eff)
1268
- heat_exchanger.setLatentEffectivenessat100HeatingAirFlow(latent_eff)
1269
- heat_exchanger.setLatentEffectivenessat75CoolingAirFlow(latent_eff)
1270
- heat_exchanger.setLatentEffectivenessat75HeatingAirFlow(latent_eff)
1271
- heat_exchanger.setFrostControlType('ExhaustOnly')
1272
- heat_exchanger.setThresholdTemperature(-12.2)
1273
- heat_exchanger.setInitialDefrostTimeFraction(0.1670)
1274
- heat_exchanger.setRateofDefrostTimeFractionIncrease(0.0240)
1275
- heat_exchanger.setEconomizerLockout(false)
1276
- # create setpoint manager for airloop
1277
- setpoint_manager = OpenStudio::Model::SetpointManagerSingleZoneReheat.new(model)
1278
- setpoint_manager.setMinimumSupplyAirTemperature(10)
1279
- setpoint_manager.setMaximumSupplyAirTemperature(50)
1280
- setpoint_manager.setControlZone(zone)
1281
- # connect components to airloop
1282
- # find the supply inlet node of the airloop
1283
- airloop_supply_inlet = airloop_secondary.supplyInletNode
1284
- # add the components to the airloop
1285
- air_loop_comps.each do |comp|
1286
- comp.addToNode(airloop_supply_inlet)
1287
- if comp.to_CoilHeatingWater.is_initialized
1288
- options['hot_water_plant'].addDemandBranchForComponent(comp)
1289
- elsif comp.to_CoilCoolingWater.is_initialized
1290
- options['chilled_water_plant'].addDemandBranchForComponent(comp)
1291
- end
1292
- end
1293
- # add erv to outdoor air system
1294
- heat_exchanger.addToNode(system_OA.outboardOANode.get)
1295
- # add setpoint manager to supply equipment outlet node
1296
- setpoint_manager.addToNode(airloop_secondary.supplyOutletNode)
1297
- # add thermal zone to airloop
1298
- if options['secondaryHVAC']['fan'] == 'Variable'
1299
- air_terminal = OpenStudio::Model::AirTerminalSingleDuctVAVNoReheat.new(model, model.alwaysOnDiscreteSchedule)
1300
- else
1301
- air_terminal = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, model.alwaysOnDiscreteSchedule)
1302
- end
1303
- # attach new terminal to the zone and to the airloop
1304
- airloop_secondary.addBranchForZone(zone, air_terminal.to_StraightComponent)
1305
- # add night cycling
1306
- airloop_secondary.setNightCycleControlType('CycleOnAny') # ML Does this work with variable speed fans?
1307
- secondary_airloops << airloop_secondary
1308
- end
1309
- end
1310
-
1311
- # pass back secondary airloops
1312
- result = secondary_airloops
1313
- return result
1314
- end
1315
-
1316
- def self.createPrimaryZoneEquipment(model, runner, options)
1317
- model.getThermalZones.each do |zone|
1318
- if options['zonesPrimary'].include? zone
1319
- if options['zoneHVAC'] == 'FanCoil'
1320
- # create fan coil
1321
- # create fan
1322
- fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule)
1323
- fan.setFanEfficiency(0.5)
1324
- fan.setPressureRise(75) # Pa
1325
- fan.autosizeMaximumFlowRate
1326
- fan.setMotorEfficiency(0.9)
1327
- fan.setMotorInAirstreamFraction(1.0)
1328
- # create cooling coil and connect to chilled water plant
1329
- cooling_coil = OpenStudio::Model::CoilCoolingWater.new(model, model.alwaysOnDiscreteSchedule)
1330
- options['chilled_water_plant'].addDemandBranchForComponent(cooling_coil)
1331
- # create heating coil and connect to hot water plant
1332
- heating_coil = OpenStudio::Model::CoilHeatingWater.new(model, model.alwaysOnDiscreteSchedule)
1333
- options['hot_water_plant'].addDemandBranchForComponent(heating_coil)
1334
- # construct fan coil
1335
- fan_coil = OpenStudio::Model::ZoneHVACFourPipeFanCoil.new(model,
1336
- model.alwaysOnDiscreteSchedule,
1337
- fan,
1338
- cooling_coil,
1339
- heating_coil)
1340
- fan_coil.setMaximumOutdoorAirFlowRate(0)
1341
- # add fan coil to thermal zone
1342
- fan_coil.addToThermalZone(zone)
1343
- elsif options['zoneHVAC'].include? 'GSHP'
1344
- # create water source heat pump and attach to heat pump loop
1345
- # create fan
1346
- fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule)
1347
- fan.setFanEfficiency(0.5)
1348
- fan.setPressureRise(75) # Pa
1349
- fan.autosizeMaximumFlowRate
1350
- fan.setMotorEfficiency(0.9)
1351
- fan.setMotorInAirstreamFraction(1.0)
1352
- # create cooling coil and connect to heat pump loop
1353
- cooling_coil = OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit.new(model)
1354
- cooling_coil.setRatedCoolingCoefficientofPerformance(6.45)
1355
- cooling_coil.setTotalCoolingCapacityCoefficient1(-9.149069561)
1356
- cooling_coil.setTotalCoolingCapacityCoefficient2(10.87814026)
1357
- cooling_coil.setTotalCoolingCapacityCoefficient3(-1.718780157)
1358
- cooling_coil.setTotalCoolingCapacityCoefficient4(0.746414818)
1359
- cooling_coil.setTotalCoolingCapacityCoefficient5(0.0)
1360
- cooling_coil.setSensibleCoolingCapacityCoefficient1(-5.462690012)
1361
- cooling_coil.setSensibleCoolingCapacityCoefficient2(17.95968138)
1362
- cooling_coil.setSensibleCoolingCapacityCoefficient3(-11.87818402)
1363
- cooling_coil.setSensibleCoolingCapacityCoefficient4(-0.980163419)
1364
- cooling_coil.setSensibleCoolingCapacityCoefficient5(0.767285761)
1365
- cooling_coil.setSensibleCoolingCapacityCoefficient6(0.0)
1366
- cooling_coil.setCoolingPowerConsumptionCoefficient1(-3.205409884)
1367
- cooling_coil.setCoolingPowerConsumptionCoefficient2(-0.976409399)
1368
- cooling_coil.setCoolingPowerConsumptionCoefficient3(3.97892546)
1369
- cooling_coil.setCoolingPowerConsumptionCoefficient4(0.938181818)
1370
- cooling_coil.setCoolingPowerConsumptionCoefficient5(0.0)
1371
- options['heat_pump_loop'].addDemandBranchForComponent(cooling_coil)
1372
- # create heating coil and connect to heat pump loop
1373
- heating_coil = OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit.new(model)
1374
- heating_coil.setRatedHeatingCoefficientofPerformance(4.0)
1375
- heating_coil.setHeatingCapacityCoefficient1(-1.361311959)
1376
- heating_coil.setHeatingCapacityCoefficient2(-2.471798046)
1377
- heating_coil.setHeatingCapacityCoefficient3(4.173164514)
1378
- heating_coil.setHeatingCapacityCoefficient4(0.640757401)
1379
- heating_coil.setHeatingCapacityCoefficient5(0.0)
1380
- heating_coil.setHeatingPowerConsumptionCoefficient1(-2.176941116)
1381
- heating_coil.setHeatingPowerConsumptionCoefficient2(0.832114286)
1382
- heating_coil.setHeatingPowerConsumptionCoefficient3(1.570743399)
1383
- heating_coil.setHeatingPowerConsumptionCoefficient4(0.690793651)
1384
- heating_coil.setHeatingPowerConsumptionCoefficient5(0.0)
1385
- options['heat_pump_loop'].addDemandBranchForComponent(heating_coil)
1386
- # create supplemental heating coil
1387
- supplemental_heating_coil = OpenStudio::Model::CoilHeatingElectric.new(model, model.alwaysOnDiscreteSchedule)
1388
- # construct heat pump
1389
- heat_pump = OpenStudio::Model::ZoneHVACWaterToAirHeatPump.new(model,
1390
- model.alwaysOnDiscreteSchedule,
1391
- fan,
1392
- heating_coil,
1393
- cooling_coil,
1394
- supplemental_heating_coil)
1395
- heat_pump.setSupplyAirFlowRateWhenNoCoolingorHeatingisNeeded(OpenStudio::OptionalDouble.new(0))
1396
- heat_pump.setOutdoorAirFlowRateDuringCoolingOperation(OpenStudio::OptionalDouble.new(0))
1397
- heat_pump.setOutdoorAirFlowRateDuringHeatingOperation(OpenStudio::OptionalDouble.new(0))
1398
- heat_pump.setOutdoorAirFlowRateWhenNoCoolingorHeatingisNeeded(OpenStudio::OptionalDouble.new(0))
1399
- # add heat pump to thermal zone
1400
- heat_pump.addToThermalZone(zone)
1401
- elsif options['zoneHVAC'] == 'Baseboard'
1402
- # create baseboard heater add add to thermal zone and hot water loop
1403
- baseboard_coil = OpenStudio::Model::CoilHeatingWaterBaseboard.new(model)
1404
- baseboard_heater = OpenStudio::Model::ZoneHVACBaseboardConvectiveWater.new(model, model.alwaysOnDiscreteSchedule, baseboard_coil)
1405
- baseboard_heater.addToThermalZone(zone)
1406
- options['hot_water_plant'].addDemandBranchForComponent(baseboard_coil)
1407
- elsif options['zoneHVAC'] == 'Radiant'
1408
- # create low temperature radiant object and add to thermal zone and radiant plant loops
1409
- # create hot water coil and attach to radiant hot water loop
1410
- heating_coil = OpenStudio::Model::CoilHeatingLowTempRadiantVarFlow.new(model, options['mean_radiant_heating_setpoint_schedule'])
1411
- options['radiant_hot_water_plant'].addDemandBranchForComponent(heating_coil)
1412
- # create chilled water coil and attach to radiant chilled water loop
1413
- cooling_coil = OpenStudio::Model::CoilCoolingLowTempRadiantVarFlow.new(model, options['mean_radiant_cooling_setpoint_schedule'])
1414
- options['radiant_chilled_water_plant'].addDemandBranchForComponent(cooling_coil)
1415
- low_temp_radiant = OpenStudio::Model::ZoneHVACLowTempRadiantVarFlow.new(model,
1416
- model.alwaysOnDiscreteSchedule,
1417
- heating_coil,
1418
- cooling_coil)
1419
- low_temp_radiant.setRadiantSurfaceType('Floors')
1420
- low_temp_radiant.setHydronicTubingInsideDiameter(0.012)
1421
- low_temp_radiant.setTemperatureControlType('MeanRadiantTemperature')
1422
- low_temp_radiant.addToThermalZone(zone)
1423
- # create radiant floor construction and substitute for existing floor (interior or exterior) constructions
1424
- # create materials for radiant floor construction
1425
- layers = []
1426
- # ignore layer below insulation, which will depend on boundary condition
1427
- layers << rigid_insulation_1in = OpenStudio::Model::StandardOpaqueMaterial.new(model, 'Rough', 0.0254, 0.02, 56.06, 1210)
1428
- layers << concrete_2in = OpenStudio::Model::StandardOpaqueMaterial.new(model, 'MediumRough', 0.0508, 2.31, 2322, 832)
1429
- layers << concrete_2in
1430
- # create radiant floor construction from materials
1431
- radiant_floor = OpenStudio::Model::ConstructionWithInternalSource.new(layers)
1432
- radiant_floor.setSourcePresentAfterLayerNumber(2)
1433
- radiant_floor.setSourcePresentAfterLayerNumber(2)
1434
- # assign radiant construction to zone floor
1435
- zone.spaces.each do |space|
1436
- space.surfaces.each do |surface|
1437
- if surface.surfaceType == 'Floor'
1438
- surface.setConstruction(radiant_floor)
1439
- end
1440
- end
1441
- end
1442
- elsif options['zoneHVAC'] == 'DualDuct'
1443
- # create baseboard heater add add to thermal zone and hot water loop
1444
- baseboard_coil = OpenStudio::Model::CoilHeatingWaterBaseboard.new(model)
1445
- baseboard_heater = OpenStudio::Model::ZoneHVACBaseboardConvectiveWater.new(model, model.alwaysOnDiscreteSchedule, baseboard_coil)
1446
- baseboard_heater.addToThermalZone(zone)
1447
- options['hot_water_plant'].addDemandBranchForComponent(baseboard_coil)
1448
- # create fan coil (to mimic functionality of DOAS)
1449
- # variable speed fan
1450
- fan = OpenStudio::Model::FanVariableVolume.new(model, model.alwaysOnDiscreteSchedule)
1451
- fan.setFanEfficiency(0.69)
1452
- fan.setPressureRise(75) # Pa #ML This number is a guess; zone equipment pretending to be a DOAS
1453
- fan.autosizeMaximumFlowRate
1454
- fan.setFanPowerMinimumFlowFraction(0.6)
1455
- fan.setMotorEfficiency(0.9)
1456
- fan.setMotorInAirstreamFraction(1.0)
1457
- # create chilled water coil and attach to chilled water loop
1458
- cooling_coil = OpenStudio::Model::CoilCoolingWater.new(model, model.alwaysOnDiscreteSchedule)
1459
- options['chilled_water_plant'].addDemandBranchForComponent(cooling_coil)
1460
- # create hot water coil and attach to hot water loop
1461
- heating_coil = OpenStudio::Model::CoilHeatingWater.new(model, model.alwaysOnDiscreteSchedule)
1462
- options['hot_water_plant'].addDemandBranchForComponent(heating_coil)
1463
- # construct fan coil (DOAS) and attach to thermal zone
1464
- fan_coil_doas = OpenStudio::Model::ZoneHVACFourPipeFanCoil.new(model,
1465
- options['ventilation_schedule'],
1466
- fan,
1467
- cooling_coil,
1468
- heating_coil)
1469
- fan_coil_doas.setCapacityControlMethod('VariableFanVariableFlow')
1470
- fan_coil_doas.addToThermalZone(zone)
1471
- end
1472
- end
1473
- end
1474
- end
1475
-
1476
- def self.addDCV(model, runner, options)
1477
- unless options['primary_airloops'].nil?
1478
- options['primary_airloops'].each do |airloop|
1479
- if options['allHVAC']['primary']['fan'] == 'Variable'
1480
- controller_mv = airloop.airLoopHVACOutdoorAirSystem.get.getControllerOutdoorAir.controllerMechanicalVentilation
1481
- controller_mv.setDemandControlledVentilation(true)
1482
- runner.registerInfo("Enabling demand control ventilation for #{airloop.name}")
1483
- end
1484
- end
1485
- end
1486
-
1487
- unless options['secondary_airloops'].nil?
1488
- options['secondary_airloops'].each do |airloop|
1489
- if options['allHVAC']['secondary']['fan'] == 'Variable'
1490
- controller_mv = airloop.airLoopHVACOutdoorAirSystem.get.getControllerOutdoorAir.controllerMechanicalVentilation
1491
- controller_mv.setDemandControlledVentilation(true)
1492
- runner.registerInfo("Enabling demand control ventilation for #{airloop.name}")
1493
- end
1494
- end
1495
- end
1496
- end
1497
-
1498
- def self.getSpacesAndSpaceTypesFromThermalZone(zone, runner)
1499
- # set flag
1500
- space_type_hash = {}
1501
-
1502
- # check if zone has spaces
1503
- if zone.spaces.empty?
1504
- runner.registerWarning("#{zone.name} doesn't have any spaces.")
1505
- else
1506
- # check if all spaces have the same space type
1507
- zone.spaces.each do |space|
1508
- if !space.spaceType.is_initialized
1509
- runner.registerWarning("One or more spaces in #{zone.name} doesn't have a space type assigned.")
1510
- space_type_hash[space] = false
1511
- return space_type
1512
- else
1513
- space_type_hash[space] = space.spaceType.get
1514
- end
1515
- end
1516
- end
1517
-
1518
- return space_type_hash
1519
- end
1520
-
1521
- def self.get_or_add_hot_water_loop(model)
1522
- # How water loop
1523
- hw_loop = nil
1524
- model.getLoops.each do |loop|
1525
- if loop.name.to_s == 'Hot Water Loop' # sizingPlant has loopType method to do this better
1526
- hw_loop = loop.to_PlantLoop.get
1527
- end
1528
- end
1529
-
1530
- if hw_loop.nil?
1531
- hw_loop = OpenStudio::Model::PlantLoop.new(model)
1532
- hw_loop.setName('Hot Water Loop')
1533
- hw_sizing_plant = hw_loop.sizingPlant
1534
- hw_sizing_plant.setLoopType('Heating')
1535
- hw_sizing_plant.setDesignLoopExitTemperature(82.0) # TODO: units
1536
- hw_sizing_plant.setLoopDesignTemperatureDifference(11.0)
1537
-
1538
- hw_pump = OpenStudio::Model::PumpVariableSpeed.new(model)
1539
-
1540
- boiler = OpenStudio::Model::BoilerHotWater.new(model)
1541
-
1542
- boiler_eff_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1543
- boiler_eff_f_of_temp.setName('Boiler Efficiency')
1544
- boiler_eff_f_of_temp.setCoefficient1Constant(1.0)
1545
- boiler_eff_f_of_temp.setInputUnitTypeforX('Dimensionless')
1546
- boiler_eff_f_of_temp.setInputUnitTypeforY('Dimensionless')
1547
- boiler_eff_f_of_temp.setOutputUnitType('Dimensionless')
1548
-
1549
- boiler.setNormalizedBoilerEfficiencyCurve(boiler_eff_f_of_temp)
1550
- boiler.setEfficiencyCurveTemperatureEvaluationVariable('LeavingBoiler')
1551
-
1552
- boiler_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1553
-
1554
- hw_supply_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1555
-
1556
- # Add the components to the hot water loop
1557
- hw_supply_inlet_node = hw_loop.supplyInletNode
1558
- hw_supply_outlet_node = hw_loop.supplyOutletNode
1559
- hw_pump.addToNode(hw_supply_inlet_node)
1560
- hw_loop.addSupplyBranchForComponent(boiler)
1561
- hw_loop.addSupplyBranchForComponent(boiler_bypass_pipe)
1562
- hw_supply_outlet_pipe.addToNode(hw_supply_outlet_node)
1563
-
1564
- # Add a setpoint manager to control the
1565
- # hot water to a constant temperature
1566
- hw_t_c = OpenStudio.convert(153, 'F', 'C').get
1567
- hw_t_sch = OpenStudio::Model::ScheduleRuleset.new(model)
1568
- hw_t_sch.setName('HW Temp')
1569
- hw_t_sch.defaultDaySchedule.setName('HW Temp Default')
1570
- hw_t_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), hw_t_c)
1571
- hw_t_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, hw_t_sch)
1572
- hw_t_stpt_manager.addToNode(hw_supply_outlet_node)
1573
-
1574
- end
1575
-
1576
- return hw_loop
1577
- end
1578
-
1579
- def self.get_or_add_water_cooled_chiller_loops(model)
1580
- # Chilled Water Plant
1581
- # todo - add in logic here that if existing chw_loop is air cooled, replace it with this one.
1582
- chw_loop = nil
1583
- model.getLoops.each do |loop|
1584
- if loop.name.to_s == 'Chilled Water Loop'
1585
- chw_loop = loop.to_PlantLoop.get
1586
- end
1587
- end
1588
-
1589
- if chw_loop.nil?
1590
- chw_loop = OpenStudio::Model::PlantLoop.new(model)
1591
- chw_loop.setName('Chilled Water Loop')
1592
- chw_sizing_plant = chw_loop.sizingPlant
1593
- chw_sizing_plant.setLoopType('Cooling')
1594
- chw_sizing_plant.setDesignLoopExitTemperature(7.22) # TODO: units
1595
- chw_sizing_plant.setLoopDesignTemperatureDifference(6.67)
1596
-
1597
- chw_pump = OpenStudio::Model::PumpVariableSpeed.new(model)
1598
-
1599
- clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1600
- clg_cap_f_of_temp.setCoefficient1Constant(1.0215158)
1601
- clg_cap_f_of_temp.setCoefficient2x(0.037035864)
1602
- clg_cap_f_of_temp.setCoefficient3xPOW2(0.0002332476)
1603
- clg_cap_f_of_temp.setCoefficient4y(-0.003894048)
1604
- clg_cap_f_of_temp.setCoefficient5yPOW2(-6.52536e-005)
1605
- clg_cap_f_of_temp.setCoefficient6xTIMESY(-0.0002680452)
1606
- clg_cap_f_of_temp.setMinimumValueofx(5.0)
1607
- clg_cap_f_of_temp.setMaximumValueofx(10.0)
1608
- clg_cap_f_of_temp.setMinimumValueofy(24.0)
1609
- clg_cap_f_of_temp.setMaximumValueofy(35.0)
1610
-
1611
- eir_f_of_avail_to_nom_cap = OpenStudio::Model::CurveBiquadratic.new(model)
1612
- eir_f_of_avail_to_nom_cap.setCoefficient1Constant(0.70176857)
1613
- eir_f_of_avail_to_nom_cap.setCoefficient2x(-0.00452016)
1614
- eir_f_of_avail_to_nom_cap.setCoefficient3xPOW2(0.0005331096)
1615
- eir_f_of_avail_to_nom_cap.setCoefficient4y(-0.005498208)
1616
- eir_f_of_avail_to_nom_cap.setCoefficient5yPOW2(0.0005445792)
1617
- eir_f_of_avail_to_nom_cap.setCoefficient6xTIMESY(-0.0007290324)
1618
- eir_f_of_avail_to_nom_cap.setMinimumValueofx(5.0)
1619
- eir_f_of_avail_to_nom_cap.setMaximumValueofx(10.0)
1620
- eir_f_of_avail_to_nom_cap.setMinimumValueofy(24.0)
1621
- eir_f_of_avail_to_nom_cap.setMaximumValueofy(35.0)
1622
-
1623
- eir_f_of_plr = OpenStudio::Model::CurveQuadratic.new(model)
1624
- eir_f_of_plr.setCoefficient1Constant(0.06369119)
1625
- eir_f_of_plr.setCoefficient2x(0.58488832)
1626
- eir_f_of_plr.setCoefficient3xPOW2(0.35280274)
1627
- eir_f_of_plr.setMinimumValueofx(0.0)
1628
- eir_f_of_plr.setMaximumValueofx(1.0)
1629
-
1630
- chiller = OpenStudio::Model::ChillerElectricEIR.new(model,
1631
- clg_cap_f_of_temp,
1632
- eir_f_of_avail_to_nom_cap,
1633
- eir_f_of_plr)
1634
-
1635
- chiller_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1636
-
1637
- chw_supply_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1638
-
1639
- # Add the components to the chilled water loop
1640
- chw_supply_inlet_node = chw_loop.supplyInletNode
1641
- chw_supply_outlet_node = chw_loop.supplyOutletNode
1642
- chw_pump.addToNode(chw_supply_inlet_node)
1643
- chw_loop.addSupplyBranchForComponent(chiller)
1644
- chw_loop.addSupplyBranchForComponent(chiller_bypass_pipe)
1645
- chw_supply_outlet_pipe.addToNode(chw_supply_outlet_node)
1646
-
1647
- # Add a setpoint manager to control the
1648
- # chilled water to a constant temperature
1649
- chw_t_c = OpenStudio.convert(44, 'F', 'C').get
1650
- chw_t_sch = OpenStudio::Model::ScheduleRuleset.new(model)
1651
- chw_t_sch.setName('CHW Temp')
1652
- chw_t_sch.defaultDaySchedule.setName('HW Temp Default')
1653
- chw_t_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), chw_t_c)
1654
- chw_t_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, chw_t_sch)
1655
- chw_t_stpt_manager.addToNode(chw_supply_outlet_node)
1656
-
1657
- end
1658
-
1659
- # Condenser System
1660
- cw_loop = nil
1661
- model.getLoops.each do |loop|
1662
- if loop.name.to_s == 'Condenser Water Loop'
1663
- cw_loop = loop.to_PlantLoop.get
1664
- end
1665
- end
1666
-
1667
- if cw_loop.nil?
1668
- cw_loop = OpenStudio::Model::PlantLoop.new(model)
1669
- cw_loop.setName('Condenser Water Loop')
1670
- cw_sizing_plant = cw_loop.sizingPlant
1671
- cw_sizing_plant.setLoopType('Condenser')
1672
- cw_sizing_plant.setDesignLoopExitTemperature(29.4) # TODO: units
1673
- cw_sizing_plant.setLoopDesignTemperatureDifference(5.6)
1674
-
1675
- cw_pump = OpenStudio::Model::PumpVariableSpeed.new(model)
1676
-
1677
- clg_tower = OpenStudio::Model::CoolingTowerSingleSpeed.new(model)
1678
-
1679
- clg_tower_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1680
-
1681
- cw_supply_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1682
-
1683
- # Add the components to the condenser water loop
1684
- cw_supply_inlet_node = cw_loop.supplyInletNode
1685
- cw_supply_outlet_node = cw_loop.supplyOutletNode
1686
- cw_pump.addToNode(cw_supply_inlet_node)
1687
- cw_loop.addSupplyBranchForComponent(clg_tower)
1688
- cw_loop.addSupplyBranchForComponent(clg_tower_bypass_pipe)
1689
- cw_supply_outlet_pipe.addToNode(cw_supply_outlet_node)
1690
- cw_loop.addDemandBranchForComponent(chiller)
1691
-
1692
- # Add a setpoint manager to control the
1693
- # condenser water to follow the OA temp
1694
- cw_t_stpt_manager = OpenStudio::Model::SetpointManagerFollowOutdoorAirTemperature.new(model)
1695
- cw_t_stpt_manager.addToNode(cw_supply_outlet_node)
1696
-
1697
- end
1698
-
1699
- return chw_loop
1700
- end
1701
-
1702
- def self.get_or_add_air_cooled_chiller_loop(model)
1703
- # Chilled Water Plant
1704
- chw_loop = nil
1705
- model.getLoops.each do |loop|
1706
- if loop.name.to_s == 'Chilled Water Loop'
1707
- chw_loop = loop.to_PlantLoop.get
1708
- end
1709
- end
1710
-
1711
- if chw_loop.nil?
1712
- chw_loop = OpenStudio::Model::PlantLoop.new(model)
1713
- chw_loop.setName('Chilled Water Loop')
1714
- chw_sizing_plant = chw_loop.sizingPlant
1715
- chw_sizing_plant.setLoopType('Cooling')
1716
- chw_sizing_plant.setDesignLoopExitTemperature(7.22) # TODO: units
1717
- chw_sizing_plant.setLoopDesignTemperatureDifference(6.67)
1718
-
1719
- chw_pump = OpenStudio::Model::PumpVariableSpeed.new(model)
1720
-
1721
- clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1722
- clg_cap_f_of_temp.setCoefficient1Constant(1.0215158)
1723
- clg_cap_f_of_temp.setCoefficient2x(0.037035864)
1724
- clg_cap_f_of_temp.setCoefficient3xPOW2(0.0002332476)
1725
- clg_cap_f_of_temp.setCoefficient4y(-0.003894048)
1726
- clg_cap_f_of_temp.setCoefficient5yPOW2(-6.52536e-005)
1727
- clg_cap_f_of_temp.setCoefficient6xTIMESY(-0.0002680452)
1728
- clg_cap_f_of_temp.setMinimumValueofx(5.0)
1729
- clg_cap_f_of_temp.setMaximumValueofx(10.0)
1730
- clg_cap_f_of_temp.setMinimumValueofy(24.0)
1731
- clg_cap_f_of_temp.setMaximumValueofy(35.0)
1732
-
1733
- eir_f_of_avail_to_nom_cap = OpenStudio::Model::CurveBiquadratic.new(model)
1734
- eir_f_of_avail_to_nom_cap.setCoefficient1Constant(0.70176857)
1735
- eir_f_of_avail_to_nom_cap.setCoefficient2x(-0.00452016)
1736
- eir_f_of_avail_to_nom_cap.setCoefficient3xPOW2(0.0005331096)
1737
- eir_f_of_avail_to_nom_cap.setCoefficient4y(-0.005498208)
1738
- eir_f_of_avail_to_nom_cap.setCoefficient5yPOW2(0.0005445792)
1739
- eir_f_of_avail_to_nom_cap.setCoefficient6xTIMESY(-0.0007290324)
1740
- eir_f_of_avail_to_nom_cap.setMinimumValueofx(5.0)
1741
- eir_f_of_avail_to_nom_cap.setMaximumValueofx(10.0)
1742
- eir_f_of_avail_to_nom_cap.setMinimumValueofy(24.0)
1743
- eir_f_of_avail_to_nom_cap.setMaximumValueofy(35.0)
1744
-
1745
- eir_f_of_plr = OpenStudio::Model::CurveQuadratic.new(model)
1746
- eir_f_of_plr.setCoefficient1Constant(0.06369119)
1747
- eir_f_of_plr.setCoefficient2x(0.58488832)
1748
- eir_f_of_plr.setCoefficient3xPOW2(0.35280274)
1749
- eir_f_of_plr.setMinimumValueofx(0.0)
1750
- eir_f_of_plr.setMaximumValueofx(1.0)
1751
-
1752
- chiller = OpenStudio::Model::ChillerElectricEIR.new(model,
1753
- clg_cap_f_of_temp,
1754
- eir_f_of_avail_to_nom_cap,
1755
- eir_f_of_plr)
1756
-
1757
- chiller_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1758
-
1759
- chw_supply_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1760
-
1761
- # Add the components to the chilled water loop
1762
- chw_supply_inlet_node = chw_loop.supplyInletNode
1763
- chw_supply_outlet_node = chw_loop.supplyOutletNode
1764
- chw_pump.addToNode(chw_supply_inlet_node)
1765
- chw_loop.addSupplyBranchForComponent(chiller)
1766
- chw_loop.addSupplyBranchForComponent(chiller_bypass_pipe)
1767
- chw_supply_outlet_pipe.addToNode(chw_supply_outlet_node)
1768
-
1769
- # Add a setpoint manager to control the
1770
- # chilled water to a constant temperature
1771
- chw_t_c = OpenStudio.convert(44, 'F', 'C').get
1772
- chw_t_sch = OpenStudio::Model::ScheduleRuleset.new(model)
1773
- chw_t_sch.setName('CHW Temp')
1774
- chw_t_sch.defaultDaySchedule.setName('HW Temp Default')
1775
- chw_t_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), chw_t_c)
1776
- chw_t_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, chw_t_sch)
1777
- chw_t_stpt_manager.addToNode(chw_supply_outlet_node)
1778
-
1779
- end
1780
-
1781
- return chw_loop
1782
- end
1783
-
1784
- def self._add_coil_cooling_dx_two_speed(model)
1785
- clg_coil = nil
1786
-
1787
- always_on = model.alwaysOnDiscreteSchedule
1788
-
1789
- clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1790
- clg_cap_f_of_temp.setCoefficient1Constant(0.42415)
1791
- clg_cap_f_of_temp.setCoefficient2x(0.04426)
1792
- clg_cap_f_of_temp.setCoefficient3xPOW2(-0.00042)
1793
- clg_cap_f_of_temp.setCoefficient4y(0.00333)
1794
- clg_cap_f_of_temp.setCoefficient5yPOW2(-0.00008)
1795
- clg_cap_f_of_temp.setCoefficient6xTIMESY(-0.00021)
1796
- clg_cap_f_of_temp.setMinimumValueofx(17.0)
1797
- clg_cap_f_of_temp.setMaximumValueofx(22.0)
1798
- clg_cap_f_of_temp.setMinimumValueofy(13.0)
1799
- clg_cap_f_of_temp.setMaximumValueofy(46.0)
1800
-
1801
- clg_cap_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
1802
- clg_cap_f_of_flow.setCoefficient1Constant(0.77136)
1803
- clg_cap_f_of_flow.setCoefficient2x(0.34053)
1804
- clg_cap_f_of_flow.setCoefficient3xPOW2(-0.11088)
1805
- clg_cap_f_of_flow.setMinimumValueofx(0.75918)
1806
- clg_cap_f_of_flow.setMaximumValueofx(1.13877)
1807
-
1808
- clg_energy_input_ratio_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1809
- clg_energy_input_ratio_f_of_temp.setCoefficient1Constant(1.23649)
1810
- clg_energy_input_ratio_f_of_temp.setCoefficient2x(-0.02431)
1811
- clg_energy_input_ratio_f_of_temp.setCoefficient3xPOW2(0.00057)
1812
- clg_energy_input_ratio_f_of_temp.setCoefficient4y(-0.01434)
1813
- clg_energy_input_ratio_f_of_temp.setCoefficient5yPOW2(0.00063)
1814
- clg_energy_input_ratio_f_of_temp.setCoefficient6xTIMESY(-0.00038)
1815
- clg_energy_input_ratio_f_of_temp.setMinimumValueofx(17.0)
1816
- clg_energy_input_ratio_f_of_temp.setMaximumValueofx(22.0)
1817
- clg_energy_input_ratio_f_of_temp.setMinimumValueofy(13.0)
1818
- clg_energy_input_ratio_f_of_temp.setMaximumValueofy(46.0)
1819
-
1820
- clg_energy_input_ratio_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
1821
- clg_energy_input_ratio_f_of_flow.setCoefficient1Constant(1.20550)
1822
- clg_energy_input_ratio_f_of_flow.setCoefficient2x(-0.32953)
1823
- clg_energy_input_ratio_f_of_flow.setCoefficient3xPOW2(0.12308)
1824
- clg_energy_input_ratio_f_of_flow.setMinimumValueofx(0.75918)
1825
- clg_energy_input_ratio_f_of_flow.setMaximumValueofx(1.13877)
1826
-
1827
- clg_part_load_ratio = OpenStudio::Model::CurveQuadratic.new(model)
1828
- clg_part_load_ratio.setCoefficient1Constant(0.77100)
1829
- clg_part_load_ratio.setCoefficient2x(0.22900)
1830
- clg_part_load_ratio.setCoefficient3xPOW2(0.0)
1831
- clg_part_load_ratio.setMinimumValueofx(0.0)
1832
- clg_part_load_ratio.setMaximumValueofx(1.0)
1833
-
1834
- clg_cap_f_of_temp_low_spd = OpenStudio::Model::CurveBiquadratic.new(model)
1835
- clg_cap_f_of_temp_low_spd.setCoefficient1Constant(0.42415)
1836
- clg_cap_f_of_temp_low_spd.setCoefficient2x(0.04426)
1837
- clg_cap_f_of_temp_low_spd.setCoefficient3xPOW2(-0.00042)
1838
- clg_cap_f_of_temp_low_spd.setCoefficient4y(0.00333)
1839
- clg_cap_f_of_temp_low_spd.setCoefficient5yPOW2(-0.00008)
1840
- clg_cap_f_of_temp_low_spd.setCoefficient6xTIMESY(-0.00021)
1841
- clg_cap_f_of_temp_low_spd.setMinimumValueofx(17.0)
1842
- clg_cap_f_of_temp_low_spd.setMaximumValueofx(22.0)
1843
- clg_cap_f_of_temp_low_spd.setMinimumValueofy(13.0)
1844
- clg_cap_f_of_temp_low_spd.setMaximumValueofy(46.0)
1845
-
1846
- clg_energy_input_ratio_f_of_temp_low_spd = OpenStudio::Model::CurveBiquadratic.new(model)
1847
- clg_energy_input_ratio_f_of_temp_low_spd.setCoefficient1Constant(1.23649)
1848
- clg_energy_input_ratio_f_of_temp_low_spd.setCoefficient2x(-0.02431)
1849
- clg_energy_input_ratio_f_of_temp_low_spd.setCoefficient3xPOW2(0.00057)
1850
- clg_energy_input_ratio_f_of_temp_low_spd.setCoefficient4y(-0.01434)
1851
- clg_energy_input_ratio_f_of_temp_low_spd.setCoefficient5yPOW2(0.00063)
1852
- clg_energy_input_ratio_f_of_temp_low_spd.setCoefficient6xTIMESY(-0.00038)
1853
- clg_energy_input_ratio_f_of_temp_low_spd.setMinimumValueofx(17.0)
1854
- clg_energy_input_ratio_f_of_temp_low_spd.setMaximumValueofx(22.0)
1855
- clg_energy_input_ratio_f_of_temp_low_spd.setMinimumValueofy(13.0)
1856
- clg_energy_input_ratio_f_of_temp_low_spd.setMaximumValueofy(46.0)
1857
-
1858
- clg_coil = OpenStudio::Model::CoilCoolingDXTwoSpeed.new(model,
1859
- always_on,
1860
- clg_cap_f_of_temp,
1861
- clg_cap_f_of_flow,
1862
- clg_energy_input_ratio_f_of_temp,
1863
- clg_energy_input_ratio_f_of_flow,
1864
- clg_part_load_ratio,
1865
- clg_cap_f_of_temp_low_spd,
1866
- clg_energy_input_ratio_f_of_temp_low_spd)
1867
-
1868
- clg_coil.setRatedLowSpeedSensibleHeatRatio(OpenStudio::OptionalDouble.new(0.69))
1869
- clg_coil.setBasinHeaterCapacity(10)
1870
- clg_coil.setBasinHeaterSetpointTemperature(2.0)
1871
-
1872
- return clg_coil
1873
- end
1874
-
1875
- def self._add_coil_cooling_dx_single_speed_sys_type_1(model)
1876
- clg_coil = nil
1877
-
1878
- always_on = model.alwaysOnDiscreteSchedule
1879
-
1880
- clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1881
- clg_cap_f_of_temp.setCoefficient1Constant(0.942587793)
1882
- clg_cap_f_of_temp.setCoefficient2x(0.009543347)
1883
- clg_cap_f_of_temp.setCoefficient3xPOW2(0.000683770)
1884
- clg_cap_f_of_temp.setCoefficient4y(-0.011042676)
1885
- clg_cap_f_of_temp.setCoefficient5yPOW2(0.000005249)
1886
- clg_cap_f_of_temp.setCoefficient6xTIMESY(-0.000009720)
1887
- clg_cap_f_of_temp.setMinimumValueofx(17.0)
1888
- clg_cap_f_of_temp.setMaximumValueofx(22.0)
1889
- clg_cap_f_of_temp.setMinimumValueofy(13.0)
1890
- clg_cap_f_of_temp.setMaximumValueofy(46.0)
1891
-
1892
- clg_cap_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
1893
- clg_cap_f_of_flow.setCoefficient1Constant(0.8)
1894
- clg_cap_f_of_flow.setCoefficient2x(0.2)
1895
- clg_cap_f_of_flow.setCoefficient3xPOW2(0.0)
1896
- clg_cap_f_of_flow.setMinimumValueofx(0.5)
1897
- clg_cap_f_of_flow.setMaximumValueofx(1.5)
1898
-
1899
- energy_input_ratio_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1900
- energy_input_ratio_f_of_temp.setCoefficient1Constant(0.342414409)
1901
- energy_input_ratio_f_of_temp.setCoefficient2x(0.034885008)
1902
- energy_input_ratio_f_of_temp.setCoefficient3xPOW2(-0.000623700)
1903
- energy_input_ratio_f_of_temp.setCoefficient4y(0.004977216)
1904
- energy_input_ratio_f_of_temp.setCoefficient5yPOW2(0.000437951)
1905
- energy_input_ratio_f_of_temp.setCoefficient6xTIMESY(-0.000728028)
1906
- energy_input_ratio_f_of_temp.setMinimumValueofx(17.0)
1907
- energy_input_ratio_f_of_temp.setMaximumValueofx(22.0)
1908
- energy_input_ratio_f_of_temp.setMinimumValueofy(13.0)
1909
- energy_input_ratio_f_of_temp.setMaximumValueofy(46.0)
1910
-
1911
- energy_input_ratio_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
1912
- energy_input_ratio_f_of_flow.setCoefficient1Constant(1.1552)
1913
- energy_input_ratio_f_of_flow.setCoefficient2x(-0.1808)
1914
- energy_input_ratio_f_of_flow.setCoefficient3xPOW2(0.0256)
1915
- energy_input_ratio_f_of_flow.setMinimumValueofx(0.5)
1916
- energy_input_ratio_f_of_flow.setMaximumValueofx(1.5)
1917
-
1918
- part_load_fraction = OpenStudio::Model::CurveQuadratic.new(model)
1919
- part_load_fraction.setCoefficient1Constant(0.85)
1920
- part_load_fraction.setCoefficient2x(0.15)
1921
- part_load_fraction.setCoefficient3xPOW2(0.0)
1922
- part_load_fraction.setMinimumValueofx(0.0)
1923
- part_load_fraction.setMaximumValueofx(1.0)
1924
-
1925
- clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model,
1926
- always_on,
1927
- clg_cap_f_of_temp,
1928
- clg_cap_f_of_flow,
1929
- energy_input_ratio_f_of_temp,
1930
- energy_input_ratio_f_of_flow,
1931
- part_load_fraction)
1932
-
1933
- return clg_coil
1934
- end
1935
-
1936
- def self._add_coil_cooling_dx_single_speed_sys_type_2(model)
1937
- clg_coil = nil
1938
-
1939
- always_on = model.alwaysOnDiscreteSchedule
1940
-
1941
- clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1942
- clg_cap_f_of_temp.setCoefficient1Constant(0.942587793)
1943
- clg_cap_f_of_temp.setCoefficient2x(0.009543347)
1944
- clg_cap_f_of_temp.setCoefficient3xPOW2(0.0018423)
1945
- clg_cap_f_of_temp.setCoefficient4y(-0.011042676)
1946
- clg_cap_f_of_temp.setCoefficient5yPOW2(0.000005249)
1947
- clg_cap_f_of_temp.setCoefficient6xTIMESY(-0.000009720)
1948
- clg_cap_f_of_temp.setMinimumValueofx(17.0)
1949
- clg_cap_f_of_temp.setMaximumValueofx(22.0)
1950
- clg_cap_f_of_temp.setMinimumValueofy(13.0)
1951
- clg_cap_f_of_temp.setMaximumValueofy(46.0)
1952
-
1953
- clg_cap_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
1954
- clg_cap_f_of_flow.setCoefficient1Constant(0.718954)
1955
- clg_cap_f_of_flow.setCoefficient2x(0.435436)
1956
- clg_cap_f_of_flow.setCoefficient3xPOW2(-0.154193)
1957
- clg_cap_f_of_flow.setMinimumValueofx(0.75)
1958
- clg_cap_f_of_flow.setMaximumValueofx(1.25)
1959
-
1960
- clg_energy_input_ratio_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1961
- clg_energy_input_ratio_f_of_temp.setCoefficient1Constant(0.342414409)
1962
- clg_energy_input_ratio_f_of_temp.setCoefficient2x(0.034885008)
1963
- clg_energy_input_ratio_f_of_temp.setCoefficient3xPOW2(-0.000623700)
1964
- clg_energy_input_ratio_f_of_temp.setCoefficient4y(0.004977216)
1965
- clg_energy_input_ratio_f_of_temp.setCoefficient5yPOW2(0.000437951)
1966
- clg_energy_input_ratio_f_of_temp.setCoefficient6xTIMESY(-0.000728028)
1967
- clg_energy_input_ratio_f_of_temp.setMinimumValueofx(17.0)
1968
- clg_energy_input_ratio_f_of_temp.setMaximumValueofx(22.0)
1969
- clg_energy_input_ratio_f_of_temp.setMinimumValueofy(13.0)
1970
- clg_energy_input_ratio_f_of_temp.setMaximumValueofy(46.0)
1971
-
1972
- clg_energy_input_ratio_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
1973
- clg_energy_input_ratio_f_of_flow.setCoefficient1Constant(1.1552)
1974
- clg_energy_input_ratio_f_of_flow.setCoefficient2x(-0.1808)
1975
- clg_energy_input_ratio_f_of_flow.setCoefficient3xPOW2(0.0256)
1976
- clg_energy_input_ratio_f_of_flow.setMinimumValueofx(0.5)
1977
- clg_energy_input_ratio_f_of_flow.setMaximumValueofx(1.5)
1978
-
1979
- clg_part_load_fraction = OpenStudio::Model::CurveQuadratic.new(model)
1980
- clg_part_load_fraction.setCoefficient1Constant(0.75)
1981
- clg_part_load_fraction.setCoefficient2x(0.25)
1982
- clg_part_load_fraction.setCoefficient3xPOW2(0.0)
1983
- clg_part_load_fraction.setMinimumValueofx(0.0)
1984
- clg_part_load_fraction.setMaximumValueofx(1.0)
1985
-
1986
- clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model,
1987
- always_on,
1988
- clg_cap_f_of_temp,
1989
- clg_cap_f_of_flow,
1990
- clg_energy_input_ratio_f_of_temp,
1991
- clg_energy_input_ratio_f_of_flow,
1992
- clg_part_load_fraction)
1993
-
1994
- return clg_coil
1995
- end
1996
-
1997
- def self._add_coil_cooling_dx_single_speed_sys_type_3(model)
1998
- clg_coil = nil
1999
-
2000
- always_on = model.alwaysOnDiscreteSchedule
2001
-
2002
- clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
2003
- clg_cap_f_of_temp.setCoefficient1Constant(0.42415)
2004
- clg_cap_f_of_temp.setCoefficient2x(0.04426)
2005
- clg_cap_f_of_temp.setCoefficient3xPOW2(-0.00042)
2006
- clg_cap_f_of_temp.setCoefficient4y(0.00333)
2007
- clg_cap_f_of_temp.setCoefficient5yPOW2(-0.00008)
2008
- clg_cap_f_of_temp.setCoefficient6xTIMESY(-0.00021)
2009
- clg_cap_f_of_temp.setMinimumValueofx(17.0)
2010
- clg_cap_f_of_temp.setMaximumValueofx(22.0)
2011
- clg_cap_f_of_temp.setMinimumValueofy(13.0)
2012
- clg_cap_f_of_temp.setMaximumValueofy(46.0)
2013
-
2014
- clg_cap_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
2015
- clg_cap_f_of_flow.setCoefficient1Constant(0.77136)
2016
- clg_cap_f_of_flow.setCoefficient2x(0.34053)
2017
- clg_cap_f_of_flow.setCoefficient3xPOW2(-0.11088)
2018
- clg_cap_f_of_flow.setMinimumValueofx(0.75918)
2019
- clg_cap_f_of_flow.setMaximumValueofx(1.13877)
2020
-
2021
- clg_energy_input_ratio_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
2022
- clg_energy_input_ratio_f_of_temp.setCoefficient1Constant(1.23649)
2023
- clg_energy_input_ratio_f_of_temp.setCoefficient2x(-0.02431)
2024
- clg_energy_input_ratio_f_of_temp.setCoefficient3xPOW2(0.00057)
2025
- clg_energy_input_ratio_f_of_temp.setCoefficient4y(-0.01434)
2026
- clg_energy_input_ratio_f_of_temp.setCoefficient5yPOW2(0.00063)
2027
- clg_energy_input_ratio_f_of_temp.setCoefficient6xTIMESY(-0.00038)
2028
- clg_energy_input_ratio_f_of_temp.setMinimumValueofx(17.0)
2029
- clg_energy_input_ratio_f_of_temp.setMaximumValueofx(22.0)
2030
- clg_energy_input_ratio_f_of_temp.setMinimumValueofy(13.0)
2031
- clg_energy_input_ratio_f_of_temp.setMaximumValueofy(46.0)
2032
-
2033
- clg_energy_input_ratio_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
2034
- clg_energy_input_ratio_f_of_flow.setCoefficient1Constant(1.20550)
2035
- clg_energy_input_ratio_f_of_flow.setCoefficient2x(-0.32953)
2036
- clg_energy_input_ratio_f_of_flow.setCoefficient3xPOW2(0.12308)
2037
- clg_energy_input_ratio_f_of_flow.setMinimumValueofx(0.75918)
2038
- clg_energy_input_ratio_f_of_flow.setMaximumValueofx(1.13877)
2039
-
2040
- clg_part_load_ratio = OpenStudio::Model::CurveQuadratic.new(model)
2041
- clg_part_load_ratio.setCoefficient1Constant(0.77100)
2042
- clg_part_load_ratio.setCoefficient2x(0.22900)
2043
- clg_part_load_ratio.setCoefficient3xPOW2(0.0)
2044
- clg_part_load_ratio.setMinimumValueofx(0.0)
2045
- clg_part_load_ratio.setMaximumValueofx(1.0)
2046
-
2047
- clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model,
2048
- always_on,
2049
- clg_cap_f_of_temp,
2050
- clg_cap_f_of_flow,
2051
- clg_energy_input_ratio_f_of_temp,
2052
- clg_energy_input_ratio_f_of_flow,
2053
- clg_part_load_ratio)
2054
-
2055
- return clg_coil
2056
- end
2057
-
2058
- def self._add_coil_cooling_dx_single_speed_sys_type_4(model)
2059
- clg_coil = nil
2060
-
2061
- always_on = model.alwaysOnDiscreteSchedule
2062
-
2063
- clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
2064
- clg_cap_f_of_temp.setCoefficient1Constant(0.766956)
2065
- clg_cap_f_of_temp.setCoefficient2x(0.0107756)
2066
- clg_cap_f_of_temp.setCoefficient3xPOW2(-0.0000414703)
2067
- clg_cap_f_of_temp.setCoefficient4y(0.00134961)
2068
- clg_cap_f_of_temp.setCoefficient5yPOW2(-0.000261144)
2069
- clg_cap_f_of_temp.setCoefficient6xTIMESY(0.000457488)
2070
- clg_cap_f_of_temp.setMinimumValueofx(17.0)
2071
- clg_cap_f_of_temp.setMaximumValueofx(22.0)
2072
- clg_cap_f_of_temp.setMinimumValueofy(13.0)
2073
- clg_cap_f_of_temp.setMaximumValueofy(46.0)
2074
-
2075
- clg_cap_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
2076
- clg_cap_f_of_flow.setCoefficient1Constant(0.8)
2077
- clg_cap_f_of_flow.setCoefficient2x(0.2)
2078
- clg_cap_f_of_flow.setCoefficient3xPOW2(0.0)
2079
- clg_cap_f_of_flow.setMinimumValueofx(0.5)
2080
- clg_cap_f_of_flow.setMaximumValueofx(1.5)
2081
-
2082
- clg_energy_input_ratio_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
2083
- clg_energy_input_ratio_f_of_temp.setCoefficient1Constant(0.297145)
2084
- clg_energy_input_ratio_f_of_temp.setCoefficient2x(0.0430933)
2085
- clg_energy_input_ratio_f_of_temp.setCoefficient3xPOW2(-0.000748766)
2086
- clg_energy_input_ratio_f_of_temp.setCoefficient4y(0.00597727)
2087
- clg_energy_input_ratio_f_of_temp.setCoefficient5yPOW2(0.000482112)
2088
- clg_energy_input_ratio_f_of_temp.setCoefficient6xTIMESY(-0.000956448)
2089
- clg_energy_input_ratio_f_of_temp.setMinimumValueofx(17.0)
2090
- clg_energy_input_ratio_f_of_temp.setMaximumValueofx(22.0)
2091
- clg_energy_input_ratio_f_of_temp.setMinimumValueofy(13.0)
2092
- clg_energy_input_ratio_f_of_temp.setMaximumValueofy(46.0)
2093
-
2094
- clg_energy_input_ratio_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
2095
- clg_energy_input_ratio_f_of_flow.setCoefficient1Constant(1.156)
2096
- clg_energy_input_ratio_f_of_flow.setCoefficient2x(-0.1816)
2097
- clg_energy_input_ratio_f_of_flow.setCoefficient3xPOW2(0.0256)
2098
- clg_energy_input_ratio_f_of_flow.setMinimumValueofx(0.5)
2099
- clg_energy_input_ratio_f_of_flow.setMaximumValueofx(1.5)
2100
-
2101
- clg_part_load_ratio = OpenStudio::Model::CurveQuadratic.new(model)
2102
- clg_part_load_ratio.setCoefficient1Constant(0.75)
2103
- clg_part_load_ratio.setCoefficient2x(0.25)
2104
- clg_part_load_ratio.setCoefficient3xPOW2(0.0)
2105
- clg_part_load_ratio.setMinimumValueofx(0.0)
2106
- clg_part_load_ratio.setMaximumValueofx(1.0)
2107
-
2108
- clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model,
2109
- always_on,
2110
- clg_cap_f_of_temp,
2111
- clg_cap_f_of_flow,
2112
- clg_energy_input_ratio_f_of_temp,
2113
- clg_energy_input_ratio_f_of_flow,
2114
- clg_part_load_ratio)
2115
- return clg_coil
2116
- end
2117
-
2118
- def self._add_coil_heating_dx_single_speed(model)
2119
- htg_coil = nil
2120
-
2121
- always_on = model.alwaysOnDiscreteSchedule
2122
-
2123
- htg_cap_f_of_temp = OpenStudio::Model::CurveCubic.new(model)
2124
- htg_cap_f_of_temp.setCoefficient1Constant(0.758746)
2125
- htg_cap_f_of_temp.setCoefficient2x(0.027626)
2126
- htg_cap_f_of_temp.setCoefficient3xPOW2(0.000148716)
2127
- htg_cap_f_of_temp.setCoefficient4xPOW3(0.0000034992)
2128
- htg_cap_f_of_temp.setMinimumValueofx(-20.0)
2129
- htg_cap_f_of_temp.setMaximumValueofx(20.0)
2130
-
2131
- htg_cap_f_of_flow = OpenStudio::Model::CurveCubic.new(model)
2132
- htg_cap_f_of_flow.setCoefficient1Constant(0.84)
2133
- htg_cap_f_of_flow.setCoefficient2x(0.16)
2134
- htg_cap_f_of_flow.setCoefficient3xPOW2(0.0)
2135
- htg_cap_f_of_flow.setCoefficient4xPOW3(0.0)
2136
- htg_cap_f_of_flow.setMinimumValueofx(0.5)
2137
- htg_cap_f_of_flow.setMaximumValueofx(1.5)
2138
-
2139
- htg_energy_input_ratio_f_of_temp = OpenStudio::Model::CurveCubic.new(model)
2140
- htg_energy_input_ratio_f_of_temp.setCoefficient1Constant(1.19248)
2141
- htg_energy_input_ratio_f_of_temp.setCoefficient2x(-0.0300438)
2142
- htg_energy_input_ratio_f_of_temp.setCoefficient3xPOW2(0.00103745)
2143
- htg_energy_input_ratio_f_of_temp.setCoefficient4xPOW3(-0.000023328)
2144
- htg_energy_input_ratio_f_of_temp.setMinimumValueofx(-20.0)
2145
- htg_energy_input_ratio_f_of_temp.setMaximumValueofx(20.0)
2146
-
2147
- htg_energy_input_ratio_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
2148
- htg_energy_input_ratio_f_of_flow.setCoefficient1Constant(1.3824)
2149
- htg_energy_input_ratio_f_of_flow.setCoefficient2x(-0.4336)
2150
- htg_energy_input_ratio_f_of_flow.setCoefficient3xPOW2(0.0512)
2151
- htg_energy_input_ratio_f_of_flow.setMinimumValueofx(0.0)
2152
- htg_energy_input_ratio_f_of_flow.setMaximumValueofx(1.0)
2153
-
2154
- htg_part_load_fraction = OpenStudio::Model::CurveQuadratic.new(model)
2155
- htg_part_load_fraction.setCoefficient1Constant(0.75)
2156
- htg_part_load_fraction.setCoefficient2x(0.25)
2157
- htg_part_load_fraction.setCoefficient3xPOW2(0.0)
2158
- htg_part_load_fraction.setMinimumValueofx(0.0)
2159
- htg_part_load_fraction.setMaximumValueofx(1.0)
2160
-
2161
- htg_coil = OpenStudio::Model::CoilHeatingDXSingleSpeed.new(model,
2162
- always_on,
2163
- htg_cap_f_of_temp,
2164
- htg_cap_f_of_flow,
2165
- htg_energy_input_ratio_f_of_temp,
2166
- htg_energy_input_ratio_f_of_flow,
2167
- htg_part_load_fraction)
2168
-
2169
- return htg_coil
2170
- end
2171
- end
1
+ # *******************************************************************************
2
+ # OpenStudio(R), Copyright (c) 2008-2019, Alliance for Sustainable Energy, LLC.
3
+ # All rights reserved.
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # (1) Redistributions of source code must retain the above copyright notice,
8
+ # this list of conditions and the following disclaimer.
9
+ #
10
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # (3) Neither the name of the copyright holder nor the names of any contributors
15
+ # may be used to endorse or promote products derived from this software without
16
+ # specific prior written permission from the respective party.
17
+ #
18
+ # (4) Other than as required in clauses (1) and (2), distributions in any form
19
+ # of modifications or other derivative works may not use the "OpenStudio"
20
+ # trademark, "OS", "os", or any other confusingly similar designation without
21
+ # specific prior written permission from Alliance for Sustainable Energy, LLC.
22
+ #
23
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
24
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
27
+ # UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
28
+ # THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30
+ # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
+ # *******************************************************************************
35
+
36
+ module OsLib_HVAC
37
+ # do something
38
+ def self.doSomething(input)
39
+ # do something
40
+ output = input
41
+
42
+ result = output
43
+ return result
44
+ end
45
+
46
+ # validate and make plenum zones
47
+ def self.validateAndAddPlenumZonesToSystem(model, runner, options = {})
48
+ # set defaults to use if user inputs not passed in
49
+ defaults = {
50
+ 'zonesPlenum' => nil,
51
+ 'zonesPrimary' => nil,
52
+ 'type' => 'ceilingReturn'
53
+ }
54
+
55
+ # merge user inputs with defaults
56
+ options = defaults.merge(options)
57
+
58
+ # array of valid ceiling plenums
59
+ zoneSurfaceHash = {}
60
+ zonePlenumHash = {}
61
+
62
+ if options['zonesPlenum'].nil?
63
+ runner.registerWarning('No plenum zones were passed in, validateAndAddPlenumZonesToSystem will not alter the model.')
64
+ else
65
+ options['zonesPlenum'].each do |zone|
66
+ # get spaces in zone
67
+ spaces = zone.spaces
68
+ # get adjacent spaces
69
+ spaces.each do |space|
70
+ # get surfaces
71
+ surfaces = space.surfaces
72
+ # loop through surfaces looking for floors with surface boundary condition, grab zone that surface's parent space is in.
73
+ surfaces.each do |surface|
74
+ if (surface.outsideBoundaryCondition == 'Surface') && (surface.surfaceType == 'Floor')
75
+ next if surface.adjacentSurface.empty?
76
+ adjacentSurface = surface.adjacentSurface.get
77
+ next if adjacentSurface.space.empty?
78
+ adjacentSurfaceSpace = adjacentSurface.space.get
79
+ next if adjacentSurfaceSpace.thermalZone.empty?
80
+ adjacentSurfaceSpaceZone = adjacentSurfaceSpace.thermalZone.get
81
+ if options['zonesPrimary'].include? adjacentSurfaceSpaceZone
82
+ if zoneSurfaceHash[adjacentSurfaceSpaceZone].nil? || (surface.grossArea > zoneSurfaceHash[adjacentSurfaceSpaceZone])
83
+ adjacentSurfaceSpaceZone.setReturnPlenum(zone)
84
+ zoneSurfaceHash[adjacentSurfaceSpaceZone] = surface.grossArea
85
+ zonePlenumHash[adjacentSurfaceSpaceZone] = zone
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ # report out results of zone-plenum hash
95
+ zonePlenumHash.each do |zone, plenum|
96
+ runner.registerInfo("#{plenum.name} has been set as a return air plenum for #{zone.name}.")
97
+ end
98
+
99
+ # pass back zone-plenum hash
100
+ result = zonePlenumHash
101
+ return result
102
+ end
103
+
104
+ def self.sortZones(model, runner, options = {})
105
+ # set defaults to use if user inputs not passed in
106
+ defaults = { 'standardBuildingTypeTest' => nil, # not used for now
107
+ 'secondarySpaceTypeTest' => nil,
108
+ 'ceilingReturnPlenumSpaceType' => nil }
109
+
110
+ # merge user inputs with defaults
111
+ options = defaults.merge(options)
112
+
113
+ # set up zone type arrays
114
+ zonesPrimary = []
115
+ zonesSecondary = []
116
+ zonesPlenum = []
117
+ zonesUnconditioned = []
118
+
119
+ # get thermal zones
120
+ zones = model.getThermalZones
121
+ zones.each do |zone|
122
+ # assign appropriate zones to zonesPlenum or zonesUnconditioned (those that don't have thermostats or zone HVAC equipment)
123
+ # if not conditioned then add to zonesPlenum or zonesUnconditioned
124
+ if zone.thermostatSetpointDualSetpoint.is_initialized || !zone.equipment.empty?
125
+ # zone is conditioned. check if its space type is secondary or primary
126
+ spaces = zone.spaces
127
+ spaces.each do |space|
128
+ # if a zone has already been assigned as secondary, skip
129
+ next if zonesSecondary.include? zone
130
+ # get space type if it exists
131
+ next if space.spaceType.empty?
132
+ spaceType = space.spaceType.get
133
+ # get standards information
134
+ # for now skip standardsBuildingType and just rely on the standardsSpaceType. Seems like enough.
135
+ next if spaceType.standardsSpaceType.empty?
136
+ standardSpaceType = spaceType.standardsSpaceType.get
137
+ # test space type against secondary space type array
138
+ # if any space type in zone is secondary, assign zone as secondary
139
+ if options['secondarySpaceTypeTest'].include? standardSpaceType
140
+ zonesSecondary << zone
141
+ end
142
+ end
143
+ # if zone not assigned as secondary, assign as primary
144
+ unless zonesSecondary.include? zone
145
+ zonesPrimary << zone
146
+ end
147
+ else
148
+ # determine if zone is a plenum zone or general unconditioned zone
149
+ # assume it is a plenum if it has at least one planum space
150
+ zone.spaces.each do |space|
151
+ # if a zone has already been assigned as a plenum, skip
152
+ next if zonesPlenum.include? zone
153
+ # if zone not assigned as a plenum, get space type if it exists
154
+ # compare to plenum space type if it has been assigned
155
+ if space.spaceType.is_initialized && (options['ceilingReturnPlenumSpaceType'].nil? == false)
156
+ spaceType = space.spaceType.get
157
+ if spaceType == options['ceilingReturnPlenumSpaceType']
158
+ zonesPlenum << zone # zone has a plenum space; assign it as a plenum
159
+ end
160
+ end
161
+ end
162
+ # if zone not assigned as a plenum, assign it as unconditioned
163
+ unless zonesPlenum.include? zone
164
+ zonesUnconditioned << zone
165
+ end
166
+ end
167
+ end
168
+
169
+ zonesSorted = { 'zonesPrimary' => zonesPrimary,
170
+ 'zonesSecondary' => zonesSecondary,
171
+ 'zonesPlenum' => zonesPlenum,
172
+ 'zonesUnconditioned' => zonesUnconditioned }
173
+ # pass back zonesSorted hash
174
+ result = zonesSorted
175
+ return result
176
+ end
177
+
178
+ def self.reportConditions(model, runner, condition,extra_string = '')
179
+
180
+ airloops = model.getAirLoopHVACs
181
+ plantLoops = model.getPlantLoops
182
+ zones = model.getThermalZones
183
+
184
+ # count up zone equipment (not counting zone exhaust fans)
185
+ zoneHasEquip = false
186
+ zonesWithEquipCounter = 0
187
+
188
+ zones.each do |zone|
189
+ if zone.equipment.size > 0
190
+ zone.equipment.each do |equip|
191
+ unless equip.to_FanZoneExhaust.is_initialized
192
+ zonesWithEquipCounter += 1
193
+ break
194
+ end
195
+ end
196
+ end
197
+ end
198
+
199
+ if condition == "initial"
200
+ runner.registerInitialCondition("The building started with #{airloops.size} air loops and #{plantLoops.size} plant loops. #{zonesWithEquipCounter} zones were conditioned with zone equipment.")
201
+ elsif condition == "final"
202
+ runner.registerFinalCondition("The building finished with #{airloops.size} air loops and #{plantLoops.size} plant loops. #{zonesWithEquipCounter} zones are conditioned with zone equipment. #{extra_string}")
203
+ end
204
+
205
+ end
206
+
207
+ def self.removeEquipment(model, runner)
208
+ airloops = model.getAirLoopHVACs
209
+ plantLoops = model.getPlantLoops
210
+ zones = model.getThermalZones
211
+
212
+ # remove all airloops
213
+ airloops.each(&:remove)
214
+
215
+ # remove all zone equipment except zone exhaust fans
216
+ zones.each do |zone|
217
+ zone.equipment.each do |equip|
218
+ if equip.to_FanZoneExhaust.is_initialized
219
+ else
220
+ equip.remove
221
+ end
222
+ end
223
+ end
224
+
225
+ # remove plant loops
226
+ plantLoops.each do |plantloop|
227
+ # get the demand components and see if water use connection, then save it
228
+ # notify user with info statement if supply side of plant loop had heat exchanger for refrigeration
229
+ usedForSHWorRefrigeration = false
230
+ plantloop.demandComponents.each do |comp| # AP code to check your comments above
231
+ if comp.to_WaterUseConnections.is_initialized || comp.to_CoilWaterHeatingDesuperheater.is_initialized
232
+ usedForSHWorRefrigeration = true
233
+ end
234
+ end
235
+ if usedForSHWorRefrigeration == false
236
+ plantloop.remove
237
+ else
238
+ runner.registerWarning("#{plantloop.name} is used for SHW or refrigeration heat reclaim. Loop will not be deleted")
239
+ end
240
+ end
241
+ end
242
+
243
+ def self.assignHVACSchedules(model, runner, options = {})
244
+ require "#{File.dirname(__FILE__)}/os_lib_schedules"
245
+
246
+ schedulesHVAC = {}
247
+ airloops = model.getAirLoopHVACs
248
+
249
+ # find airloop with most primary spaces
250
+ max_primary_spaces = 0
251
+ representative_airloop = false
252
+ building_HVAC_schedule = false
253
+ building_ventilation_schedule = false
254
+ unless options['remake_schedules']
255
+ # if remake schedules not selected, get relevant schedules from model if they exist
256
+ airloops.each do |air_loop|
257
+ primary_spaces = 0
258
+ air_loop.thermalZones.each do |thermal_zone|
259
+ thermal_zone.spaces.each do |space|
260
+ if space.spaceType.is_initialized
261
+ if space.spaceType.get.name.get.include? options['primarySpaceType']
262
+ primary_spaces += 1
263
+ end
264
+ end
265
+ end
266
+ end
267
+ if primary_spaces > max_primary_spaces
268
+ max_primary_spaces = primary_spaces
269
+ representative_airloop = air_loop
270
+ end
271
+ end
272
+ end
273
+ if representative_airloop
274
+ building_HVAC_schedule = representative_airloop.availabilitySchedule
275
+ building_ventilation_schedule_optional = representative_airloop.airLoopHVACOutdoorAirSystem.get.getControllerOutdoorAir.maximumFractionofOutdoorAirSchedule
276
+ if building_ventilation_schedule_optional.is_initialized
277
+ building_ventilation_schedule = building_ventilation_schedule.get
278
+ end
279
+ end
280
+ # build new airloop schedules if existing model doesn't have them
281
+ if options['primarySpaceType'] == 'Classroom'
282
+ # ventilation schedule
283
+ unless building_ventilation_schedule
284
+ ruleset_name = 'AEDG K-12 Ventilation Schedule'
285
+ winter_design_day = [[24, 1]]
286
+ summer_design_day = [[24, 1]]
287
+ default_day = ['Weekday', [6, 0], [18, 1], [24, 0]]
288
+ rules = []
289
+ rules << ['Weekend', '1/1-12/31', 'Sat/Sun', [24, 0]]
290
+ rules << ['Summer Weekday', '7/1-8/31', 'Mon/Tue/Wed/Thu/Fri', [8, 0], [13, 1], [24, 0]]
291
+ options_ventilation = { 'name' => ruleset_name,
292
+ 'winter_design_day' => winter_design_day,
293
+ 'summer_design_day' => summer_design_day,
294
+ 'default_day' => default_day,
295
+ 'rules' => rules }
296
+ building_ventilation_schedule = OsLib_Schedules.createComplexSchedule(model, options_ventilation)
297
+ end
298
+ # HVAC availability schedule
299
+ unless building_HVAC_schedule
300
+ ruleset_name = 'AEDG K-12 HVAC Availability Schedule'
301
+ winter_design_day = [[24, 1]]
302
+ summer_design_day = [[24, 1]]
303
+ default_day = ['Weekday', [6, 0], [18, 1], [24, 0]]
304
+ rules = []
305
+ rules << ['Weekend', '1/1-12/31', 'Sat/Sun', [24, 0]]
306
+ rules << ['Summer Weekday', '7/1-8/31', 'Mon/Tue/Wed/Thu/Fri', [8, 0], [13, 1], [24, 0]]
307
+ options_hvac = { 'name' => ruleset_name,
308
+ 'winter_design_day' => winter_design_day,
309
+ 'summer_design_day' => summer_design_day,
310
+ 'default_day' => default_day,
311
+ 'rules' => rules }
312
+ building_HVAC_schedule = OsLib_Schedules.createComplexSchedule(model, options_hvac)
313
+ end
314
+ elsif options['primarySpaceType'] == 'Office'
315
+ # ventilation schedule
316
+ unless building_ventilation_schedule
317
+ ruleset_name = 'AEDG Office Ventilation Schedule'
318
+ winter_design_day = [[24, 1]] # ML These are not always on in PNNL model
319
+ summer_design_day = [[24, 1]] # ML These are not always on in PNNL model
320
+ default_day = ['Weekday', [7, 0], [22, 1], [24, 0]] # ML PNNL has a one hour ventilation offset
321
+ rules = []
322
+ rules << ['Saturday', '1/1-12/31', 'Sat', [7, 0], [18, 1], [24, 0]] # ML PNNL has a one hour ventilation offset
323
+ rules << ['Sunday', '1/1-12/31', 'Sun', [24, 0]]
324
+ options_ventilation = { 'name' => ruleset_name,
325
+ 'winter_design_day' => winter_design_day,
326
+ 'summer_design_day' => summer_design_day,
327
+ 'default_day' => default_day,
328
+ 'rules' => rules }
329
+ building_ventilation_schedule = OsLib_Schedules.createComplexSchedule(model, options_ventilation)
330
+ end
331
+ # HVAC availability schedule
332
+ unless building_HVAC_schedule
333
+ ruleset_name = 'AEDG Office HVAC Availability Schedule'
334
+ winter_design_day = [[24, 1]] # ML These are not always on in PNNL model
335
+ summer_design_day = [[24, 1]] # ML These are not always on in PNNL model
336
+ default_day = ['Weekday', [6, 0], [22, 1], [24, 0]] # ML PNNL has a one hour ventilation offset
337
+ rules = []
338
+ rules << ['Saturday', '1/1-12/31', 'Sat', [6, 0], [18, 1], [24, 0]] # ML PNNL has a one hour ventilation offset
339
+ rules << ['Sunday', '1/1-12/31', 'Sun', [24, 0]]
340
+ options_hvac = { 'name' => ruleset_name,
341
+ 'winter_design_day' => winter_design_day,
342
+ 'summer_design_day' => summer_design_day,
343
+ 'default_day' => default_day,
344
+ 'rules' => rules }
345
+ building_HVAC_schedule = OsLib_Schedules.createComplexSchedule(model, options_hvac)
346
+ end
347
+ # special loops for radiant system (different temperature setpoints)
348
+ if options['allHVAC']['zone'] == 'Radiant'
349
+ # create hot water schedule for radiant heating loop
350
+ schedulesHVAC['radiant_hot_water'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HW-Radiant-Loop-Temp-Schedule',
351
+ 'default_day' => ['All Days', [24, 45.0]])
352
+ # create hot water schedule for radiant cooling loop
353
+ schedulesHVAC['radiant_chilled_water'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG CW-Radiant-Loop-Temp-Schedule',
354
+ 'default_day' => ['All Days', [24, 15.0]])
355
+ # create mean radiant heating and cooling setpoint schedules
356
+ # ML ideally, should grab schedules tied to zone thermostat and make modified versions that follow the setback pattern
357
+ # for now, create new ones that match the recommended HVAC schedule
358
+ # mean radiant heating setpoint schedule (PNNL values)
359
+ ruleset_name = 'AEDG Office Mean Radiant Heating Setpoint Schedule'
360
+ winter_design_day = [[24, 18.8]]
361
+ summer_design_day = [[6, 18.3], [22, 18.8], [24, 18.3]]
362
+ default_day = ['Weekday', [6, 18.3], [22, 18.8], [24, 18.3]]
363
+ rules = []
364
+ rules << ['Saturday', '1/1-12/31', 'Sat', [6, 18.3], [18, 18.8], [24, 18.3]]
365
+ rules << ['Sunday', '1/1-12/31', 'Sun', [24, 18.3]]
366
+ options_radiant_heating = { 'name' => ruleset_name,
367
+ 'winter_design_day' => winter_design_day,
368
+ 'summer_design_day' => summer_design_day,
369
+ 'default_day' => default_day,
370
+ 'rules' => rules }
371
+ mean_radiant_heating_schedule = OsLib_Schedules.createComplexSchedule(model, options_radiant_heating)
372
+ schedulesHVAC['mean_radiant_heating'] = mean_radiant_heating_schedule
373
+ # mean radiant cooling setpoint schedule (PNNL values)
374
+ ruleset_name = 'AEDG Office Mean Radiant Cooling Setpoint Schedule'
375
+ winter_design_day = [[6, 26.7], [22, 24.0], [24, 26.7]]
376
+ summer_design_day = [[24, 24.0]]
377
+ default_day = ['Weekday', [6, 26.7], [22, 24.0], [24, 26.7]]
378
+ rules = []
379
+ rules << ['Saturday', '1/1-12/31', 'Sat', [6, 26.7], [18, 24.0], [24, 26.7]]
380
+ rules << ['Sunday', '1/1-12/31', 'Sun', [24, 26.7]]
381
+ options_radiant_cooling = { 'name' => ruleset_name,
382
+ 'winter_design_day' => winter_design_day,
383
+ 'summer_design_day' => summer_design_day,
384
+ 'default_day' => default_day,
385
+ 'rules' => rules }
386
+ mean_radiant_cooling_schedule = OsLib_Schedules.createComplexSchedule(model, options_radiant_cooling)
387
+ schedulesHVAC['mean_radiant_cooling'] = mean_radiant_cooling_schedule
388
+ end
389
+ end
390
+ # SAT schedule
391
+ if options['allHVAC']['primary']['doas']
392
+ # primary airloop is DOAS
393
+ schedulesHVAC['primary_sat'] = sch_ruleset_DOAS_setpoint = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG DOAS Temperature Setpoint Schedule',
394
+ 'default_day' => ['All Days', [24, 20.0]])
395
+ else
396
+ # primary airloop is multizone VAV that cools
397
+ schedulesHVAC['primary_sat'] = sch_ruleset_DOAS_setpoint = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG Cold Deck Temperature Setpoint Schedule',
398
+ 'default_day' => ['All Days', [24, 12.8]])
399
+ end
400
+ schedulesHVAC['ventilation'] = building_ventilation_schedule
401
+ schedulesHVAC['hvac'] = building_HVAC_schedule
402
+ # build new plant schedules as needed
403
+ zoneHVACHotWaterPlant = ['FanCoil', 'DualDuct', 'Baseboard'] # dual duct has fan coil and baseboard
404
+ zoneHVACChilledWaterPlant = ['FanCoil', 'DualDuct'] # dual duct has fan coil
405
+ # hot water
406
+ if (options['allHVAC']['primary']['heat'] == 'Water') || (options['allHVAC']['secondary']['heat'] == 'Water') || zoneHVACHotWaterPlant.include?(options['allHVAC']['zone'])
407
+ schedulesHVAC['hot_water'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HW-Loop-Temp-Schedule',
408
+ 'default_day' => ['All Days', [24, 67.0]])
409
+ end
410
+ # chilled water
411
+ if (options['allHVAC']['primary']['cool'] == 'Water') || (options['allHVAC']['secondary']['cool'] == 'Water') || zoneHVACChilledWaterPlant.include?(options['allHVAC']['zone'])
412
+ schedulesHVAC['chilled_water'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG CW-Loop-Temp-Schedule',
413
+ 'default_day' => ['All Days', [24, 6.7]])
414
+ end
415
+ # heat pump condenser loop schedules
416
+ if options['allHVAC']['zone'] == 'GSHP'
417
+ # there will be a heat pump condenser loop
418
+ # loop setpoint schedule
419
+ schedulesHVAC['hp_loop'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HP-Loop-Temp-Schedule',
420
+ 'default_day' => ['All Days', [24, 21]])
421
+ # cooling component schedule (#ML won't need this if a ground loop is actually modeled)
422
+ schedulesHVAC['hp_loop_cooling'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HP-Loop-Clg-Temp-Schedule',
423
+ 'default_day' => ['All Days', [24, 21]])
424
+ # heating component schedule
425
+ schedulesHVAC['hp_loop_heating'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HP-Loop-Htg-Temp-Schedule',
426
+ 'default_day' => ['All Days', [24, 5]])
427
+ end
428
+ if options['allHVAC']['zone'] == 'WSHP'
429
+ # there will be a heat pump condenser loop
430
+ # loop setpoint schedule
431
+ schedulesHVAC['hp_loop'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HP-Loop-Temp-Schedule',
432
+ 'default_day' => ['All Days', [24, 30]]) # PNNL
433
+ # cooling component schedule (#ML won't need this if a ground loop is actually modeled)
434
+ schedulesHVAC['hp_loop_cooling'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HP-Loop-Clg-Temp-Schedule',
435
+ 'default_day' => ['All Days', [24, 30]]) # PNNL
436
+ # heating component schedule
437
+ schedulesHVAC['hp_loop_heating'] = OsLib_Schedules.createComplexSchedule(model, 'name' => 'AEDG HP-Loop-Htg-Temp-Schedule',
438
+ 'default_day' => ['All Days', [24, 20]]) # PNNL
439
+ end
440
+
441
+ # pass back schedulesHVAC hash
442
+ result = schedulesHVAC
443
+ return result
444
+ end
445
+
446
+ def self.createHotWaterPlant(model, runner, hot_water_setpoint_schedule, loop_type)
447
+ hot_water_plant = OpenStudio::Model::PlantLoop.new(model)
448
+ hot_water_plant.setName("AEDG #{loop_type} Loop")
449
+ hot_water_plant.setMaximumLoopTemperature(100)
450
+ hot_water_plant.setMinimumLoopTemperature(10)
451
+ loop_sizing = hot_water_plant.sizingPlant
452
+ loop_sizing.setLoopType('Heating')
453
+ if loop_type == 'Hot Water'
454
+ loop_sizing.setDesignLoopExitTemperature(82)
455
+ elsif loop_type == 'Radiant Hot Water'
456
+ loop_sizing.setDesignLoopExitTemperature(60) # ML follows convention of sizing temp being larger than supplu temp
457
+ end
458
+ loop_sizing.setLoopDesignTemperatureDifference(11)
459
+ # create a pump
460
+ pump = OpenStudio::Model::PumpVariableSpeed.new(model)
461
+ pump.setRatedPumpHead(119563) # Pa
462
+ pump.setMotorEfficiency(0.9)
463
+ pump.setCoefficient1ofthePartLoadPerformanceCurve(0)
464
+ pump.setCoefficient2ofthePartLoadPerformanceCurve(0.0216)
465
+ pump.setCoefficient3ofthePartLoadPerformanceCurve(-0.0325)
466
+ pump.setCoefficient4ofthePartLoadPerformanceCurve(1.0095)
467
+ # create a boiler
468
+ boiler = OpenStudio::Model::BoilerHotWater.new(model)
469
+ boiler.setNominalThermalEfficiency(0.9)
470
+ # create a scheduled setpoint manager
471
+ setpoint_manager_scheduled = OpenStudio::Model::SetpointManagerScheduled.new(model, hot_water_setpoint_schedule)
472
+ # create a supply bypass pipe
473
+ pipe_supply_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
474
+ # create a supply outlet pipe
475
+ pipe_supply_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
476
+ # create a demand bypass pipe
477
+ pipe_demand_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
478
+ # create a demand inlet pipe
479
+ pipe_demand_inlet = OpenStudio::Model::PipeAdiabatic.new(model)
480
+ # create a demand outlet pipe
481
+ pipe_demand_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
482
+ # connect components to plant loop
483
+ # supply side components
484
+ hot_water_plant.addSupplyBranchForComponent(boiler)
485
+ hot_water_plant.addSupplyBranchForComponent(pipe_supply_bypass)
486
+ pump.addToNode(hot_water_plant.supplyInletNode)
487
+ pipe_supply_outlet.addToNode(hot_water_plant.supplyOutletNode)
488
+ setpoint_manager_scheduled.addToNode(hot_water_plant.supplyOutletNode)
489
+ # demand side components (water coils are added as they are added to airloops and zoneHVAC)
490
+ hot_water_plant.addDemandBranchForComponent(pipe_demand_bypass)
491
+ pipe_demand_inlet.addToNode(hot_water_plant.demandInletNode)
492
+ pipe_demand_outlet.addToNode(hot_water_plant.demandOutletNode)
493
+
494
+ # pass back hot water plant
495
+ result = hot_water_plant
496
+ return result
497
+ end
498
+
499
+ def self.createChilledWaterPlant(model, runner, chilled_water_setpoint_schedule, loop_type, chillerType)
500
+ # chilled water plant
501
+ chilled_water_plant = OpenStudio::Model::PlantLoop.new(model)
502
+ chilled_water_plant.setName("AEDG #{loop_type} Loop")
503
+ chilled_water_plant.setMaximumLoopTemperature(98)
504
+ chilled_water_plant.setMinimumLoopTemperature(1)
505
+ loop_sizing = chilled_water_plant.sizingPlant
506
+ loop_sizing.setLoopType('Cooling')
507
+ if loop_type == 'Chilled Water'
508
+ loop_sizing.setDesignLoopExitTemperature(6.7)
509
+ elsif loop_type == 'Radiant Chilled Water'
510
+ loop_sizing.setDesignLoopExitTemperature(15)
511
+ end
512
+ loop_sizing.setLoopDesignTemperatureDifference(6.7)
513
+ # create a pump
514
+ pump = OpenStudio::Model::PumpVariableSpeed.new(model)
515
+ pump.setRatedPumpHead(149453) # Pa
516
+ pump.setMotorEfficiency(0.9)
517
+ pump.setCoefficient1ofthePartLoadPerformanceCurve(0)
518
+ pump.setCoefficient2ofthePartLoadPerformanceCurve(0.0216)
519
+ pump.setCoefficient3ofthePartLoadPerformanceCurve(-0.0325)
520
+ pump.setCoefficient4ofthePartLoadPerformanceCurve(1.0095)
521
+ # create a chiller
522
+ if chillerType == 'WaterCooled'
523
+ # create clgCapFuncTempCurve
524
+ clgCapFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
525
+ clgCapFuncTempCurve.setCoefficient1Constant(1.07E+00)
526
+ clgCapFuncTempCurve.setCoefficient2x(4.29E-02)
527
+ clgCapFuncTempCurve.setCoefficient3xPOW2(4.17E-04)
528
+ clgCapFuncTempCurve.setCoefficient4y(-8.10E-03)
529
+ clgCapFuncTempCurve.setCoefficient5yPOW2(-4.02E-05)
530
+ clgCapFuncTempCurve.setCoefficient6xTIMESY(-3.86E-04)
531
+ clgCapFuncTempCurve.setMinimumValueofx(0)
532
+ clgCapFuncTempCurve.setMaximumValueofx(20)
533
+ clgCapFuncTempCurve.setMinimumValueofy(0)
534
+ clgCapFuncTempCurve.setMaximumValueofy(50)
535
+ # create eirFuncTempCurve
536
+ eirFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
537
+ eirFuncTempCurve.setCoefficient1Constant(4.68E-01)
538
+ eirFuncTempCurve.setCoefficient2x(-1.38E-02)
539
+ eirFuncTempCurve.setCoefficient3xPOW2(6.98E-04)
540
+ eirFuncTempCurve.setCoefficient4y(1.09E-02)
541
+ eirFuncTempCurve.setCoefficient5yPOW2(4.62E-04)
542
+ eirFuncTempCurve.setCoefficient6xTIMESY(-6.82E-04)
543
+ eirFuncTempCurve.setMinimumValueofx(0)
544
+ eirFuncTempCurve.setMaximumValueofx(20)
545
+ eirFuncTempCurve.setMinimumValueofy(0)
546
+ eirFuncTempCurve.setMaximumValueofy(50)
547
+ # create eirFuncPlrCurve
548
+ eirFuncPlrCurve = OpenStudio::Model::CurveQuadratic.new(model)
549
+ eirFuncPlrCurve.setCoefficient1Constant(1.41E-01)
550
+ eirFuncPlrCurve.setCoefficient2x(6.55E-01)
551
+ eirFuncPlrCurve.setCoefficient3xPOW2(2.03E-01)
552
+ eirFuncPlrCurve.setMinimumValueofx(0)
553
+ eirFuncPlrCurve.setMaximumValueofx(1.2)
554
+ # construct chiller
555
+ chiller = OpenStudio::Model::ChillerElectricEIR.new(model, clgCapFuncTempCurve, eirFuncTempCurve, eirFuncPlrCurve)
556
+ chiller.setReferenceCOP(6.1)
557
+ chiller.setCondenserType('WaterCooled')
558
+ chiller.setChillerFlowMode('ConstantFlow')
559
+ elsif chillerType == 'AirCooled'
560
+ # create clgCapFuncTempCurve
561
+ clgCapFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
562
+ clgCapFuncTempCurve.setCoefficient1Constant(1.05E+00)
563
+ clgCapFuncTempCurve.setCoefficient2x(3.36E-02)
564
+ clgCapFuncTempCurve.setCoefficient3xPOW2(2.15E-04)
565
+ clgCapFuncTempCurve.setCoefficient4y(-5.18E-03)
566
+ clgCapFuncTempCurve.setCoefficient5yPOW2(-4.42E-05)
567
+ clgCapFuncTempCurve.setCoefficient6xTIMESY(-2.15E-04)
568
+ clgCapFuncTempCurve.setMinimumValueofx(0)
569
+ clgCapFuncTempCurve.setMaximumValueofx(20)
570
+ clgCapFuncTempCurve.setMinimumValueofy(0)
571
+ clgCapFuncTempCurve.setMaximumValueofy(50)
572
+ # create eirFuncTempCurve
573
+ eirFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
574
+ eirFuncTempCurve.setCoefficient1Constant(5.83E-01)
575
+ eirFuncTempCurve.setCoefficient2x(-4.04E-03)
576
+ eirFuncTempCurve.setCoefficient3xPOW2(4.68E-04)
577
+ eirFuncTempCurve.setCoefficient4y(-2.24E-04)
578
+ eirFuncTempCurve.setCoefficient5yPOW2(4.81E-04)
579
+ eirFuncTempCurve.setCoefficient6xTIMESY(-6.82E-04)
580
+ eirFuncTempCurve.setMinimumValueofx(0)
581
+ eirFuncTempCurve.setMaximumValueofx(20)
582
+ eirFuncTempCurve.setMinimumValueofy(0)
583
+ eirFuncTempCurve.setMaximumValueofy(50)
584
+ # create eirFuncPlrCurve
585
+ eirFuncPlrCurve = OpenStudio::Model::CurveQuadratic.new(model)
586
+ eirFuncPlrCurve.setCoefficient1Constant(4.19E-02)
587
+ eirFuncPlrCurve.setCoefficient2x(6.25E-01)
588
+ eirFuncPlrCurve.setCoefficient3xPOW2(3.23E-01)
589
+ eirFuncPlrCurve.setMinimumValueofx(0)
590
+ eirFuncPlrCurve.setMaximumValueofx(1.2)
591
+ # construct chiller
592
+ chiller = OpenStudio::Model::ChillerElectricEIR.new(model, clgCapFuncTempCurve, eirFuncTempCurve, eirFuncPlrCurve)
593
+ chiller.setReferenceCOP(2.93)
594
+ chiller.setCondenserType('AirCooled')
595
+ chiller.setChillerFlowMode('ConstantFlow')
596
+ end
597
+ # create a scheduled setpoint manager
598
+ setpoint_manager_scheduled = OpenStudio::Model::SetpointManagerScheduled.new(model, chilled_water_setpoint_schedule)
599
+ # create a supply bypass pipe
600
+ pipe_supply_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
601
+ # create a supply outlet pipe
602
+ pipe_supply_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
603
+ # create a demand bypass pipe
604
+ pipe_demand_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
605
+ # create a demand inlet pipe
606
+ pipe_demand_inlet = OpenStudio::Model::PipeAdiabatic.new(model)
607
+ # create a demand outlet pipe
608
+ pipe_demand_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
609
+ # connect components to plant loop
610
+ # supply side components
611
+ chilled_water_plant.addSupplyBranchForComponent(chiller)
612
+ chilled_water_plant.addSupplyBranchForComponent(pipe_supply_bypass)
613
+ pump.addToNode(chilled_water_plant.supplyInletNode)
614
+ pipe_supply_outlet.addToNode(chilled_water_plant.supplyOutletNode)
615
+ setpoint_manager_scheduled.addToNode(chilled_water_plant.supplyOutletNode)
616
+ # demand side components (water coils are added as they are added to airloops and ZoneHVAC)
617
+ chilled_water_plant.addDemandBranchForComponent(pipe_demand_bypass)
618
+ pipe_demand_inlet.addToNode(chilled_water_plant.demandInletNode)
619
+ pipe_demand_outlet.addToNode(chilled_water_plant.demandOutletNode)
620
+
621
+ # pass back chilled water plant
622
+ result = chilled_water_plant
623
+ return result
624
+ end
625
+
626
+ def self.createCondenserLoop(model, runner, options)
627
+ condenserLoops = {}
628
+
629
+ # check for water-cooled chillers
630
+ waterCooledChiller = false
631
+ model.getChillerElectricEIRs.each do |chiller|
632
+ next if waterCooledChiller == true
633
+ if chiller.condenserType == 'WaterCooled'
634
+ waterCooledChiller = true
635
+ end
636
+ end
637
+ # create condenser loop for water-cooled chillers
638
+ if waterCooledChiller
639
+ # create condenser loop for water-cooled chiller(s)
640
+ condenser_loop = OpenStudio::Model::PlantLoop.new(model)
641
+ condenser_loop.setName('AEDG Condenser Loop')
642
+ condenser_loop.setMaximumLoopTemperature(80)
643
+ condenser_loop.setMinimumLoopTemperature(5)
644
+ loop_sizing = condenser_loop.sizingPlant
645
+ loop_sizing.setLoopType('Condenser')
646
+ loop_sizing.setDesignLoopExitTemperature(29.4)
647
+ loop_sizing.setLoopDesignTemperatureDifference(5.6)
648
+ # create a pump
649
+ pump = OpenStudio::Model::PumpVariableSpeed.new(model)
650
+ pump.setRatedPumpHead(134508) # Pa
651
+ pump.setMotorEfficiency(0.9)
652
+ pump.setCoefficient1ofthePartLoadPerformanceCurve(0)
653
+ pump.setCoefficient2ofthePartLoadPerformanceCurve(0.0216)
654
+ pump.setCoefficient3ofthePartLoadPerformanceCurve(-0.0325)
655
+ pump.setCoefficient4ofthePartLoadPerformanceCurve(1.0095)
656
+ # create a cooling tower
657
+ tower = OpenStudio::Model::CoolingTowerVariableSpeed.new(model)
658
+ # create a supply bypass pipe
659
+ pipe_supply_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
660
+ # create a supply outlet pipe
661
+ pipe_supply_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
662
+ # create a demand bypass pipe
663
+ pipe_demand_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
664
+ # create a demand inlet pipe
665
+ pipe_demand_inlet = OpenStudio::Model::PipeAdiabatic.new(model)
666
+ # create a demand outlet pipe
667
+ pipe_demand_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
668
+ # create a setpoint manager
669
+ setpoint_manager_follow_oa = OpenStudio::Model::SetpointManagerFollowOutdoorAirTemperature.new(model)
670
+ setpoint_manager_follow_oa.setOffsetTemperatureDifference(0)
671
+ setpoint_manager_follow_oa.setMaximumSetpointTemperature(80)
672
+ setpoint_manager_follow_oa.setMinimumSetpointTemperature(5)
673
+ # connect components to plant loop
674
+ # supply side components
675
+ condenser_loop.addSupplyBranchForComponent(tower)
676
+ condenser_loop.addSupplyBranchForComponent(pipe_supply_bypass)
677
+ pump.addToNode(condenser_loop.supplyInletNode)
678
+ pipe_supply_outlet.addToNode(condenser_loop.supplyOutletNode)
679
+ setpoint_manager_follow_oa.addToNode(condenser_loop.supplyOutletNode)
680
+ # demand side components
681
+ model.getChillerElectricEIRs.each do |chiller|
682
+ if chiller.condenserType == 'WaterCooled' # works only if chillers not already connected to condenser loop(s)
683
+ condenser_loop.addDemandBranchForComponent(chiller)
684
+ end
685
+ end
686
+ condenser_loop.addDemandBranchForComponent(pipe_demand_bypass)
687
+ pipe_demand_inlet.addToNode(condenser_loop.demandInletNode)
688
+ pipe_demand_outlet.addToNode(condenser_loop.demandOutletNode)
689
+ condenserLoops['condenser_loop'] = condenser_loop
690
+ end
691
+ if options['zoneHVAC'].include? 'GSHP'
692
+ # create condenser loop for heat pumps
693
+ condenser_loop = OpenStudio::Model::PlantLoop.new(model)
694
+ condenser_loop.setName('AEDG Heat Pump Loop')
695
+ condenser_loop.setMaximumLoopTemperature(80)
696
+ condenser_loop.setMinimumLoopTemperature(1)
697
+ loop_sizing = condenser_loop.sizingPlant
698
+ loop_sizing.setLoopType('Condenser')
699
+ if options['zoneHVAC'] == 'GSHP'
700
+ loop_sizing.setDesignLoopExitTemperature(21)
701
+ loop_sizing.setLoopDesignTemperatureDifference(5)
702
+ elsif options['zoneHVAC'] == 'WSHP'
703
+ loop_sizing.setDesignLoopExitTemperature(30) # PNNL
704
+ loop_sizing.setLoopDesignTemperatureDifference(20) # PNNL
705
+ end
706
+ # create a pump
707
+ pump = OpenStudio::Model::PumpVariableSpeed.new(model)
708
+ pump.setRatedPumpHead(134508) # Pa
709
+ pump.setMotorEfficiency(0.9)
710
+ pump.setCoefficient1ofthePartLoadPerformanceCurve(0)
711
+ pump.setCoefficient2ofthePartLoadPerformanceCurve(0.0216)
712
+ pump.setCoefficient3ofthePartLoadPerformanceCurve(-0.0325)
713
+ pump.setCoefficient4ofthePartLoadPerformanceCurve(1.0095)
714
+ # create a supply bypass pipe
715
+ pipe_supply_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
716
+ # create a supply outlet pipe
717
+ pipe_supply_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
718
+ # create a demand bypass pipe
719
+ pipe_demand_bypass = OpenStudio::Model::PipeAdiabatic.new(model)
720
+ # create a demand inlet pipe
721
+ pipe_demand_inlet = OpenStudio::Model::PipeAdiabatic.new(model)
722
+ # create a demand outlet pipe
723
+ pipe_demand_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
724
+ # create setpoint managers
725
+ setpoint_manager_scheduled_loop = OpenStudio::Model::SetpointManagerScheduled.new(model, options['loop_setpoint_schedule'])
726
+ setpoint_manager_scheduled_cooling = OpenStudio::Model::SetpointManagerScheduled.new(model, options['cooling_setpoint_schedule'])
727
+ setpoint_manager_scheduled_heating = OpenStudio::Model::SetpointManagerScheduled.new(model, options['heating_setpoint_schedule'])
728
+ # connect components to plant loop
729
+ # supply side components
730
+ condenser_loop.addSupplyBranchForComponent(pipe_supply_bypass)
731
+ pump.addToNode(condenser_loop.supplyInletNode)
732
+ pipe_supply_outlet.addToNode(condenser_loop.supplyOutletNode)
733
+ setpoint_manager_scheduled_loop.addToNode(condenser_loop.supplyOutletNode)
734
+ # demand side components
735
+ condenser_loop.addDemandBranchForComponent(pipe_demand_bypass)
736
+ pipe_demand_inlet.addToNode(condenser_loop.demandInletNode)
737
+ pipe_demand_outlet.addToNode(condenser_loop.demandOutletNode)
738
+ # add additional components according to specific system type
739
+ if options['zoneHVAC'] == 'GSHP'
740
+ # add district cooling and heating to supply side
741
+ district_cooling = OpenStudio::Model::DistrictCooling.new(model)
742
+ district_cooling.setNominalCapacity(1000000000000) # large number; no autosizing
743
+ condenser_loop.addSupplyBranchForComponent(district_cooling)
744
+ setpoint_manager_scheduled_cooling.addToNode(district_cooling.outletModelObject.get.to_Node.get)
745
+ district_heating = OpenStudio::Model::DistrictHeating.new(model)
746
+ district_heating.setNominalCapacity(1000000000000) # large number; no autosizing
747
+ district_heating.addToNode(district_cooling.outletModelObject.get.to_Node.get)
748
+ setpoint_manager_scheduled_heating.addToNode(district_heating.outletModelObject.get.to_Node.get)
749
+ # add heat pumps to demand side after they get created
750
+ elsif options['zoneHVAC'] == 'WSHP'
751
+ # add a boiler and cooling tower to supply side
752
+ # create a boiler
753
+ boiler = OpenStudio::Model::BoilerHotWater.new(model)
754
+ boiler.setNominalThermalEfficiency(0.9)
755
+ condenser_loop.addSupplyBranchForComponent(boiler)
756
+ setpoint_manager_scheduled_heating.addToNode(boiler.outletModelObject.get.to_Node.get)
757
+ # create a cooling tower
758
+ tower = OpenStudio::Model::CoolingTowerSingleSpeed.new(model)
759
+ tower.addToNode(boiler.outletModelObject.get.to_Node.get)
760
+ setpoint_manager_scheduled_cooling.addToNode(tower.outletModelObject.get.to_Node.get)
761
+ end
762
+ condenserLoops['heat_pump_loop'] = condenser_loop
763
+ end
764
+
765
+ # pass back condenser loop(s)
766
+ result = condenserLoops
767
+ return result
768
+ end
769
+
770
+ def self.createPrimaryAirLoops(model, runner, options)
771
+ primary_airloops = []
772
+ # create primary airloop for each story
773
+ assignedThermalZones = []
774
+ model.getBuildingStorys.each do |building_story|
775
+ # ML stories need to be reordered from the ground up
776
+ thermalZonesToAdd = []
777
+ building_story.spaces.each do |space|
778
+ # make sure spaces are assigned to thermal zones
779
+ # otherwise might want to send a warning
780
+ if space.thermalZone
781
+ thermal_zone = space.thermalZone.get
782
+ # grab primary zones
783
+ if options['zonesPrimary'].include? thermal_zone
784
+ # make sure zone was not already assigned to another air loop
785
+ unless assignedThermalZones.include? thermal_zone
786
+ # make sure thermal zones are not duplicated (spaces can share thermal zones)
787
+ unless thermalZonesToAdd.include? thermal_zone
788
+ thermalZonesToAdd << thermal_zone
789
+ end
790
+ end
791
+ end
792
+ end
793
+ end
794
+ # make sure thermal zones don't get added to more than one air loop
795
+ assignedThermalZones << thermalZonesToAdd
796
+
797
+ # create new air loop if story contains primary zones
798
+ unless thermalZonesToAdd.empty?
799
+ airloop_primary = OpenStudio::Model::AirLoopHVAC.new(model)
800
+ airloop_primary.setName("AEDG Air Loop HVAC #{building_story.name}")
801
+ # modify system sizing properties
802
+ sizing_system = airloop_primary.sizingSystem
803
+ # set central heating and cooling temperatures for sizing
804
+ sizing_system.setCentralCoolingDesignSupplyAirTemperature(12.8)
805
+ sizing_system.setCentralHeatingDesignSupplyAirTemperature(40) # ML OS default is 16.7
806
+ # load specification
807
+ sizing_system.setSystemOutdoorAirMethod('VentilationRateProcedure') # ML OS default is ZoneSum
808
+ if options['primaryHVAC']['doas']
809
+ sizing_system.setTypeofLoadtoSizeOn('VentilationRequirement') # DOAS
810
+ sizing_system.setAllOutdoorAirinCooling(true) # DOAS
811
+ sizing_system.setAllOutdoorAirinHeating(true) # DOAS
812
+ else
813
+ sizing_system.setTypeofLoadtoSizeOn('Sensible') # VAV
814
+ sizing_system.setAllOutdoorAirinCooling(false) # VAV
815
+ sizing_system.setAllOutdoorAirinHeating(false) # VAV
816
+ end
817
+
818
+ air_loop_comps = []
819
+ # set availability schedule
820
+ airloop_primary.setAvailabilitySchedule(options['hvac_schedule'])
821
+ # create air loop fan
822
+ if options['primaryHVAC']['fan'] == 'Variable'
823
+ # create variable speed fan and set system sizing accordingly
824
+ sizing_system.setMinimumSystemAirFlowRatio(0.3) # DCV
825
+ # variable speed fan
826
+ fan = OpenStudio::Model::FanVariableVolume.new(model, model.alwaysOnDiscreteSchedule)
827
+ fan.setFanEfficiency(0.69)
828
+ fan.setPressureRise(1125) # Pa
829
+ fan.autosizeMaximumFlowRate
830
+ fan.setFanPowerMinimumFlowFraction(0.6)
831
+ fan.setMotorEfficiency(0.9)
832
+ fan.setMotorInAirstreamFraction(1.0)
833
+ air_loop_comps << fan
834
+ else
835
+ sizing_system.setMinimumSystemAirFlowRatio(1.0) # No DCV
836
+ # constant speed fan
837
+ fan = OpenStudio::Model::FanConstantVolume.new(model, model.alwaysOnDiscreteSchedule)
838
+ fan.setFanEfficiency(0.6)
839
+ fan.setPressureRise(500) # Pa
840
+ fan.autosizeMaximumFlowRate
841
+ fan.setMotorEfficiency(0.9)
842
+ fan.setMotorInAirstreamFraction(1.0)
843
+ air_loop_comps << fan
844
+ end
845
+ # create heating coil
846
+ if options['primaryHVAC']['heat'] == 'Water'
847
+ # water coil
848
+ heating_coil = OpenStudio::Model::CoilHeatingWater.new(model, model.alwaysOnDiscreteSchedule)
849
+ air_loop_comps << heating_coil
850
+ else
851
+ # gas coil
852
+ heating_coil = OpenStudio::Model::CoilHeatingGas.new(model, model.alwaysOnDiscreteSchedule)
853
+ air_loop_comps << heating_coil
854
+ end
855
+ # create cooling coil
856
+ if options['primaryHVAC']['cool'] == 'Water'
857
+ # water coil
858
+ cooling_coil = OpenStudio::Model::CoilCoolingWater.new(model, model.alwaysOnDiscreteSchedule)
859
+ air_loop_comps << cooling_coil
860
+ elsif options['primaryHVAC']['cool'] == 'SingleDX'
861
+ # single speed DX coil
862
+ # create cooling coil
863
+ # create clgCapFuncTempCurve
864
+ clgCapFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
865
+ clgCapFuncTempCurve.setCoefficient1Constant(0.42415)
866
+ clgCapFuncTempCurve.setCoefficient2x(0.04426)
867
+ clgCapFuncTempCurve.setCoefficient3xPOW2(-0.00042)
868
+ clgCapFuncTempCurve.setCoefficient4y(0.00333)
869
+ clgCapFuncTempCurve.setCoefficient5yPOW2(-0.00008)
870
+ clgCapFuncTempCurve.setCoefficient6xTIMESY(-0.00021)
871
+ clgCapFuncTempCurve.setMinimumValueofx(17)
872
+ clgCapFuncTempCurve.setMaximumValueofx(22)
873
+ clgCapFuncTempCurve.setMinimumValueofy(13)
874
+ clgCapFuncTempCurve.setMaximumValueofy(46)
875
+ # create clgCapFuncFlowFracCurve
876
+ clgCapFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
877
+ clgCapFuncFlowFracCurve.setCoefficient1Constant(0.77136)
878
+ clgCapFuncFlowFracCurve.setCoefficient2x(0.34053)
879
+ clgCapFuncFlowFracCurve.setCoefficient3xPOW2(-0.11088)
880
+ clgCapFuncFlowFracCurve.setMinimumValueofx(0.75918)
881
+ clgCapFuncFlowFracCurve.setMaximumValueofx(1.13877)
882
+ # create clgEirFuncTempCurve
883
+ clgEirFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
884
+ clgEirFuncTempCurve.setCoefficient1Constant(1.23649)
885
+ clgEirFuncTempCurve.setCoefficient2x(-0.02431)
886
+ clgEirFuncTempCurve.setCoefficient3xPOW2(0.00057)
887
+ clgEirFuncTempCurve.setCoefficient4y(-0.01434)
888
+ clgEirFuncTempCurve.setCoefficient5yPOW2(0.00063)
889
+ clgEirFuncTempCurve.setCoefficient6xTIMESY(-0.00038)
890
+ clgEirFuncTempCurve.setMinimumValueofx(17)
891
+ clgEirFuncTempCurve.setMaximumValueofx(22)
892
+ clgEirFuncTempCurve.setMinimumValueofy(13)
893
+ clgEirFuncTempCurve.setMaximumValueofy(46)
894
+ # create clgEirFuncFlowFracCurve
895
+ clgEirFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
896
+ clgEirFuncFlowFracCurve.setCoefficient1Constant(1.20550)
897
+ clgEirFuncFlowFracCurve.setCoefficient2x(-0.32953)
898
+ clgEirFuncFlowFracCurve.setCoefficient3xPOW2(0.12308)
899
+ clgEirFuncFlowFracCurve.setMinimumValueofx(0.75918)
900
+ clgEirFuncFlowFracCurve.setMaximumValueofx(1.13877)
901
+ # create clgPlrCurve
902
+ clgPlrCurve = OpenStudio::Model::CurveQuadratic.new(model)
903
+ clgPlrCurve.setCoefficient1Constant(0.77100)
904
+ clgPlrCurve.setCoefficient2x(0.22900)
905
+ clgPlrCurve.setCoefficient3xPOW2(0.0)
906
+ clgPlrCurve.setMinimumValueofx(0.0)
907
+ clgPlrCurve.setMaximumValueofx(1.0)
908
+ # cooling coil
909
+ cooling_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model,
910
+ model.alwaysOnDiscreteSchedule,
911
+ clgCapFuncTempCurve,
912
+ clgCapFuncFlowFracCurve,
913
+ clgEirFuncTempCurve,
914
+ clgEirFuncFlowFracCurve,
915
+ clgPlrCurve)
916
+ cooling_coil.setRatedCOP(OpenStudio::OptionalDouble.new(4))
917
+ air_loop_comps << cooling_coil
918
+ else
919
+ # two speed DX coil (PNNL curves)
920
+ # create cooling coil
921
+ # create clgCapFuncTempCurve
922
+ clgCapFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
923
+ clgCapFuncTempCurve.setCoefficient1Constant(1.39072)
924
+ clgCapFuncTempCurve.setCoefficient2x(-0.0529058)
925
+ clgCapFuncTempCurve.setCoefficient3xPOW2(0.0018423)
926
+ clgCapFuncTempCurve.setCoefficient4y(0.00058267)
927
+ clgCapFuncTempCurve.setCoefficient5yPOW2(-0.000186814)
928
+ clgCapFuncTempCurve.setCoefficient6xTIMESY(0.000265159)
929
+ clgCapFuncTempCurve.setMinimumValueofx(16.5556)
930
+ clgCapFuncTempCurve.setMaximumValueofx(22.1111)
931
+ clgCapFuncTempCurve.setMinimumValueofy(23.7778)
932
+ clgCapFuncTempCurve.setMaximumValueofy(47.66)
933
+ # create clgCapFuncFlowFracCurve
934
+ clgCapFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
935
+ clgCapFuncFlowFracCurve.setCoefficient1Constant(0.718954)
936
+ clgCapFuncFlowFracCurve.setCoefficient2x(0.435436)
937
+ clgCapFuncFlowFracCurve.setCoefficient3xPOW2(-0.154193)
938
+ clgCapFuncFlowFracCurve.setMinimumValueofx(0.75)
939
+ clgCapFuncFlowFracCurve.setMaximumValueofx(1.25)
940
+ # create clgEirFuncTempCurve
941
+ clgEirFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
942
+ clgEirFuncTempCurve.setCoefficient1Constant(-0.536161)
943
+ clgEirFuncTempCurve.setCoefficient2x(0.105138)
944
+ clgEirFuncTempCurve.setCoefficient3xPOW2(-0.00172659)
945
+ clgEirFuncTempCurve.setCoefficient4y(0.0149848)
946
+ clgEirFuncTempCurve.setCoefficient5yPOW2(0.000659948)
947
+ clgEirFuncTempCurve.setCoefficient6xTIMESY(-0.0017385)
948
+ clgEirFuncTempCurve.setMinimumValueofx(16.5556)
949
+ clgEirFuncTempCurve.setMaximumValueofx(22.1111)
950
+ clgEirFuncTempCurve.setMinimumValueofy(23.7778)
951
+ clgEirFuncTempCurve.setMaximumValueofy(47.66)
952
+ # create clgEirFuncFlowFracCurve
953
+ clgEirFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
954
+ clgEirFuncFlowFracCurve.setCoefficient1Constant(1.19525)
955
+ clgEirFuncFlowFracCurve.setCoefficient2x(-0.306138)
956
+ clgEirFuncFlowFracCurve.setCoefficient3xPOW2(0.110973)
957
+ clgEirFuncFlowFracCurve.setMinimumValueofx(0.75)
958
+ clgEirFuncFlowFracCurve.setMaximumValueofx(1.25)
959
+ # create clgPlrCurve
960
+ clgPlrCurve = OpenStudio::Model::CurveQuadratic.new(model)
961
+ clgPlrCurve.setCoefficient1Constant(0.77100)
962
+ clgPlrCurve.setCoefficient2x(0.22900)
963
+ clgPlrCurve.setCoefficient3xPOW2(0.0)
964
+ clgPlrCurve.setMinimumValueofx(0.0)
965
+ clgPlrCurve.setMaximumValueofx(1.0)
966
+ # cooling coil
967
+ cooling_coil = OpenStudio::Model::CoilCoolingDXTwoSpeed.new(model,
968
+ model.alwaysOnDiscreteSchedule,
969
+ clgCapFuncTempCurve,
970
+ clgCapFuncFlowFracCurve,
971
+ clgEirFuncTempCurve,
972
+ clgEirFuncFlowFracCurve,
973
+ clgPlrCurve,
974
+ clgCapFuncTempCurve,
975
+ clgEirFuncTempCurve)
976
+ cooling_coil.setRatedHighSpeedCOP(4)
977
+ cooling_coil.setRatedLowSpeedCOP(4)
978
+ air_loop_comps << cooling_coil
979
+ end
980
+ unless options['zoneHVAC'] == 'DualDuct'
981
+ # create controller outdoor air
982
+ controller_OA = OpenStudio::Model::ControllerOutdoorAir.new(model)
983
+ controller_OA.autosizeMinimumOutdoorAirFlowRate
984
+ controller_OA.autosizeMaximumOutdoorAirFlowRate
985
+ # create ventilation schedules and assign to OA controller
986
+ if options['primaryHVAC']['doas']
987
+ controller_OA.setMinimumFractionofOutdoorAirSchedule(model.alwaysOnDiscreteSchedule)
988
+ controller_OA.setMaximumFractionofOutdoorAirSchedule(model.alwaysOnDiscreteSchedule)
989
+ else
990
+ # multizone VAV that ventilates
991
+ controller_OA.setMaximumFractionofOutdoorAirSchedule(options['ventilation_schedule'])
992
+ controller_OA.setEconomizerControlType('DifferentialEnthalpy')
993
+ # add night cycling (ML would people actually do this for a VAV system?))
994
+ airloop_primary.setNightCycleControlType('CycleOnAny') # ML Does this work with variable speed fans?
995
+ end
996
+ controller_OA.setHeatRecoveryBypassControlType('BypassWhenOAFlowGreaterThanMinimum')
997
+ # create outdoor air system
998
+ system_OA = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model, controller_OA)
999
+ air_loop_comps << system_OA
1000
+ # create ERV
1001
+ heat_exchanger = OpenStudio::Model::HeatExchangerAirToAirSensibleAndLatent.new(model)
1002
+ heat_exchanger.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
1003
+ sensible_eff = 0.75
1004
+ latent_eff = 0.69
1005
+ heat_exchanger.setSensibleEffectivenessat100CoolingAirFlow(sensible_eff)
1006
+ heat_exchanger.setSensibleEffectivenessat100HeatingAirFlow(sensible_eff)
1007
+ heat_exchanger.setSensibleEffectivenessat75CoolingAirFlow(sensible_eff)
1008
+ heat_exchanger.setSensibleEffectivenessat75HeatingAirFlow(sensible_eff)
1009
+ heat_exchanger.setLatentEffectivenessat100CoolingAirFlow(latent_eff)
1010
+ heat_exchanger.setLatentEffectivenessat100HeatingAirFlow(latent_eff)
1011
+ heat_exchanger.setLatentEffectivenessat75CoolingAirFlow(latent_eff)
1012
+ heat_exchanger.setLatentEffectivenessat75HeatingAirFlow(latent_eff)
1013
+ heat_exchanger.setFrostControlType('ExhaustOnly')
1014
+ heat_exchanger.setThresholdTemperature(-12.2)
1015
+ heat_exchanger.setInitialDefrostTimeFraction(0.1670)
1016
+ heat_exchanger.setRateofDefrostTimeFractionIncrease(0.0240)
1017
+ heat_exchanger.setEconomizerLockout(false)
1018
+ end
1019
+ # create scheduled setpoint manager for airloop
1020
+ if options['primaryHVAC']['doas'] || (options['zoneHVAC'] == 'DualDuct')
1021
+ # DOAS or VAV for cooling and not ventilation
1022
+ setpoint_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, options['primary_sat_schedule'])
1023
+ else
1024
+ # VAV for cooling and ventilation
1025
+ setpoint_manager = OpenStudio::Model::SetpointManagerOutdoorAirReset.new(model)
1026
+ setpoint_manager.setSetpointatOutdoorLowTemperature(15.6)
1027
+ setpoint_manager.setOutdoorLowTemperature(14.4)
1028
+ setpoint_manager.setSetpointatOutdoorHighTemperature(12.8)
1029
+ setpoint_manager.setOutdoorHighTemperature(21.1)
1030
+ end
1031
+ # connect components to airloop
1032
+ # find the supply inlet node of the airloop
1033
+ airloop_supply_inlet = airloop_primary.supplyInletNode
1034
+ # add the components to the airloop
1035
+ air_loop_comps.each do |comp|
1036
+ comp.addToNode(airloop_supply_inlet)
1037
+ if comp.to_CoilHeatingWater.is_initialized
1038
+ options['hot_water_plant'].addDemandBranchForComponent(comp)
1039
+ elsif comp.to_CoilCoolingWater.is_initialized
1040
+ options['chilled_water_plant'].addDemandBranchForComponent(comp)
1041
+ end
1042
+ end
1043
+ # add erv to outdoor air system
1044
+ unless options['zoneHVAC'] == 'DualDuct'
1045
+ heat_exchanger.addToNode(system_OA.outboardOANode.get)
1046
+ end
1047
+ # add setpoint manager to supply equipment outlet node
1048
+ setpoint_manager.addToNode(airloop_primary.supplyOutletNode)
1049
+ # add thermal zones to airloop
1050
+ thermalZonesToAdd.each do |zone|
1051
+ # make an air terminal for the zone
1052
+ if options['primaryHVAC']['fan'] == 'Variable'
1053
+ air_terminal = OpenStudio::Model::AirTerminalSingleDuctVAVNoReheat.new(model, model.alwaysOnDiscreteSchedule)
1054
+ else
1055
+ air_terminal = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, model.alwaysOnDiscreteSchedule)
1056
+ end
1057
+ # attach new terminal to the zone and to the airloop
1058
+ airloop_primary.addBranchForZone(zone, air_terminal.to_StraightComponent)
1059
+ end
1060
+ primary_airloops << airloop_primary
1061
+ end
1062
+ end
1063
+
1064
+ # pass back primary airloops
1065
+ result = primary_airloops
1066
+ return result
1067
+ end
1068
+
1069
+ def self.createSecondaryAirLoops(model, runner, options)
1070
+ secondary_airloops = []
1071
+ # create secondary airloop for each secondary zone
1072
+ model.getThermalZones.each do |zone|
1073
+ if options['zonesSecondary'].include? zone
1074
+ # create secondary airloop
1075
+ airloop_secondary = OpenStudio::Model::AirLoopHVAC.new(model)
1076
+ airloop_secondary.setName("AEDG Air Loop HVAC #{zone.name}")
1077
+ # modify system sizing properties
1078
+ sizing_system = airloop_secondary.sizingSystem
1079
+ # set central heating and cooling temperatures for sizing
1080
+ sizing_system.setCentralCoolingDesignSupplyAirTemperature(12.8)
1081
+ sizing_system.setCentralHeatingDesignSupplyAirTemperature(40) # ML OS default is 16.7
1082
+ # load specification
1083
+ sizing_system.setSystemOutdoorAirMethod('VentilationRateProcedure') # ML OS default is ZoneSum
1084
+ sizing_system.setTypeofLoadtoSizeOn('Sensible') # PSZ
1085
+ sizing_system.setAllOutdoorAirinCooling(false) # PSZ
1086
+ sizing_system.setAllOutdoorAirinHeating(false) # PSZ
1087
+ sizing_system.setMinimumSystemAirFlowRatio(1.0) # Constant volume fan
1088
+ air_loop_comps = []
1089
+ # set availability schedule (HVAC operation schedule)
1090
+ airloop_secondary.setAvailabilitySchedule(options['hvac_schedule'])
1091
+ if options['secondaryHVAC']['fan'] == 'Variable'
1092
+ # create variable speed fan and set system sizing accordingly
1093
+ sizing_system.setMinimumSystemAirFlowRatio(0.3) # DCV
1094
+ # variable speed fan
1095
+ fan = OpenStudio::Model::FanVariableVolume.new(model, model.alwaysOnDiscreteSchedule)
1096
+ fan.setFanEfficiency(0.69)
1097
+ fan.setPressureRise(1125) # Pa
1098
+ fan.autosizeMaximumFlowRate
1099
+ fan.setFanPowerMinimumFlowFraction(0.6)
1100
+ fan.setMotorEfficiency(0.9)
1101
+ fan.setMotorInAirstreamFraction(1.0)
1102
+ air_loop_comps << fan
1103
+ else
1104
+ sizing_system.setMinimumSystemAirFlowRatio(1.0) # No DCV
1105
+ # constant speed fan
1106
+ fan = OpenStudio::Model::FanConstantVolume.new(model, model.alwaysOnDiscreteSchedule)
1107
+ fan.setFanEfficiency(0.6)
1108
+ fan.setPressureRise(500) # Pa
1109
+ fan.autosizeMaximumFlowRate
1110
+ fan.setMotorEfficiency(0.9)
1111
+ fan.setMotorInAirstreamFraction(1.0)
1112
+ air_loop_comps << fan
1113
+ end
1114
+ # create cooling coil
1115
+ if options['secondaryHVAC']['cool'] == 'Water'
1116
+ # water coil
1117
+ cooling_coil = OpenStudio::Model::CoilCoolingWater.new(model, model.alwaysOnDiscreteSchedule)
1118
+ air_loop_comps << cooling_coil
1119
+ elsif options['secondaryHVAC']['cool'] == 'SingleDX'
1120
+ # single speed DX coil
1121
+ # create cooling coil
1122
+ # create clgCapFuncTempCurve
1123
+ clgCapFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
1124
+ clgCapFuncTempCurve.setCoefficient1Constant(0.42415)
1125
+ clgCapFuncTempCurve.setCoefficient2x(0.04426)
1126
+ clgCapFuncTempCurve.setCoefficient3xPOW2(-0.00042)
1127
+ clgCapFuncTempCurve.setCoefficient4y(0.00333)
1128
+ clgCapFuncTempCurve.setCoefficient5yPOW2(-0.00008)
1129
+ clgCapFuncTempCurve.setCoefficient6xTIMESY(-0.00021)
1130
+ clgCapFuncTempCurve.setMinimumValueofx(17)
1131
+ clgCapFuncTempCurve.setMaximumValueofx(22)
1132
+ clgCapFuncTempCurve.setMinimumValueofy(13)
1133
+ clgCapFuncTempCurve.setMaximumValueofy(46)
1134
+ # create clgCapFuncFlowFracCurve
1135
+ clgCapFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
1136
+ clgCapFuncFlowFracCurve.setCoefficient1Constant(0.77136)
1137
+ clgCapFuncFlowFracCurve.setCoefficient2x(0.34053)
1138
+ clgCapFuncFlowFracCurve.setCoefficient3xPOW2(-0.11088)
1139
+ clgCapFuncFlowFracCurve.setMinimumValueofx(0.75918)
1140
+ clgCapFuncFlowFracCurve.setMaximumValueofx(1.13877)
1141
+ # create clgEirFuncTempCurve
1142
+ clgEirFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
1143
+ clgEirFuncTempCurve.setCoefficient1Constant(1.23649)
1144
+ clgEirFuncTempCurve.setCoefficient2x(-0.02431)
1145
+ clgEirFuncTempCurve.setCoefficient3xPOW2(0.00057)
1146
+ clgEirFuncTempCurve.setCoefficient4y(-0.01434)
1147
+ clgEirFuncTempCurve.setCoefficient5yPOW2(0.00063)
1148
+ clgEirFuncTempCurve.setCoefficient6xTIMESY(-0.00038)
1149
+ clgEirFuncTempCurve.setMinimumValueofx(17)
1150
+ clgEirFuncTempCurve.setMaximumValueofx(22)
1151
+ clgEirFuncTempCurve.setMinimumValueofy(13)
1152
+ clgEirFuncTempCurve.setMaximumValueofy(46)
1153
+ # create clgEirFuncFlowFracCurve
1154
+ clgEirFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
1155
+ clgEirFuncFlowFracCurve.setCoefficient1Constant(1.20550)
1156
+ clgEirFuncFlowFracCurve.setCoefficient2x(-0.32953)
1157
+ clgEirFuncFlowFracCurve.setCoefficient3xPOW2(0.12308)
1158
+ clgEirFuncFlowFracCurve.setMinimumValueofx(0.75918)
1159
+ clgEirFuncFlowFracCurve.setMaximumValueofx(1.13877)
1160
+ # create clgPlrCurve
1161
+ clgPlrCurve = OpenStudio::Model::CurveQuadratic.new(model)
1162
+ clgPlrCurve.setCoefficient1Constant(0.77100)
1163
+ clgPlrCurve.setCoefficient2x(0.22900)
1164
+ clgPlrCurve.setCoefficient3xPOW2(0.0)
1165
+ clgPlrCurve.setMinimumValueofx(0.0)
1166
+ clgPlrCurve.setMaximumValueofx(1.0)
1167
+ # cooling coil
1168
+ cooling_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model,
1169
+ model.alwaysOnDiscreteSchedule,
1170
+ clgCapFuncTempCurve,
1171
+ clgCapFuncFlowFracCurve,
1172
+ clgEirFuncTempCurve,
1173
+ clgEirFuncFlowFracCurve,
1174
+ clgPlrCurve)
1175
+ cooling_coil.setRatedCOP(OpenStudio::OptionalDouble.new(4))
1176
+ air_loop_comps << cooling_coil
1177
+ else
1178
+ # two speed DX coil (PNNL curves)
1179
+ # create cooling coil
1180
+ # create clgCapFuncTempCurve
1181
+ clgCapFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
1182
+ clgCapFuncTempCurve.setCoefficient1Constant(1.39072)
1183
+ clgCapFuncTempCurve.setCoefficient2x(-0.0529058)
1184
+ clgCapFuncTempCurve.setCoefficient3xPOW2(0.0018423)
1185
+ clgCapFuncTempCurve.setCoefficient4y(0.00058267)
1186
+ clgCapFuncTempCurve.setCoefficient5yPOW2(-0.000186814)
1187
+ clgCapFuncTempCurve.setCoefficient6xTIMESY(0.000265159)
1188
+ clgCapFuncTempCurve.setMinimumValueofx(16.5556)
1189
+ clgCapFuncTempCurve.setMaximumValueofx(22.1111)
1190
+ clgCapFuncTempCurve.setMinimumValueofy(23.7778)
1191
+ clgCapFuncTempCurve.setMaximumValueofy(47.66)
1192
+ # create clgCapFuncFlowFracCurve
1193
+ clgCapFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
1194
+ clgCapFuncFlowFracCurve.setCoefficient1Constant(0.718954)
1195
+ clgCapFuncFlowFracCurve.setCoefficient2x(0.435436)
1196
+ clgCapFuncFlowFracCurve.setCoefficient3xPOW2(-0.154193)
1197
+ clgCapFuncFlowFracCurve.setMinimumValueofx(0.75)
1198
+ clgCapFuncFlowFracCurve.setMaximumValueofx(1.25)
1199
+ # create clgEirFuncTempCurve
1200
+ clgEirFuncTempCurve = OpenStudio::Model::CurveBiquadratic.new(model)
1201
+ clgEirFuncTempCurve.setCoefficient1Constant(-0.536161)
1202
+ clgEirFuncTempCurve.setCoefficient2x(0.105138)
1203
+ clgEirFuncTempCurve.setCoefficient3xPOW2(-0.00172659)
1204
+ clgEirFuncTempCurve.setCoefficient4y(0.0149848)
1205
+ clgEirFuncTempCurve.setCoefficient5yPOW2(0.000659948)
1206
+ clgEirFuncTempCurve.setCoefficient6xTIMESY(-0.0017385)
1207
+ clgEirFuncTempCurve.setMinimumValueofx(16.5556)
1208
+ clgEirFuncTempCurve.setMaximumValueofx(22.1111)
1209
+ clgEirFuncTempCurve.setMinimumValueofy(23.7778)
1210
+ clgEirFuncTempCurve.setMaximumValueofy(47.66)
1211
+ # create clgEirFuncFlowFracCurve
1212
+ clgEirFuncFlowFracCurve = OpenStudio::Model::CurveQuadratic.new(model)
1213
+ clgEirFuncFlowFracCurve.setCoefficient1Constant(1.19525)
1214
+ clgEirFuncFlowFracCurve.setCoefficient2x(-0.306138)
1215
+ clgEirFuncFlowFracCurve.setCoefficient3xPOW2(0.110973)
1216
+ clgEirFuncFlowFracCurve.setMinimumValueofx(0.75)
1217
+ clgEirFuncFlowFracCurve.setMaximumValueofx(1.25)
1218
+ # create clgPlrCurve
1219
+ clgPlrCurve = OpenStudio::Model::CurveQuadratic.new(model)
1220
+ clgPlrCurve.setCoefficient1Constant(0.77100)
1221
+ clgPlrCurve.setCoefficient2x(0.22900)
1222
+ clgPlrCurve.setCoefficient3xPOW2(0.0)
1223
+ clgPlrCurve.setMinimumValueofx(0.0)
1224
+ clgPlrCurve.setMaximumValueofx(1.0)
1225
+ # cooling coil
1226
+ cooling_coil = OpenStudio::Model::CoilCoolingDXTwoSpeed.new(model,
1227
+ model.alwaysOnDiscreteSchedule,
1228
+ clgCapFuncTempCurve,
1229
+ clgCapFuncFlowFracCurve,
1230
+ clgEirFuncTempCurve,
1231
+ clgEirFuncFlowFracCurve,
1232
+ clgPlrCurve,
1233
+ clgCapFuncTempCurve,
1234
+ clgEirFuncTempCurve)
1235
+ cooling_coil.setRatedHighSpeedCOP(4)
1236
+ cooling_coil.setRatedLowSpeedCOP(4)
1237
+ air_loop_comps << cooling_coil
1238
+ end
1239
+ if options['secondaryHVAC']['heat'] == 'Water'
1240
+ # water coil
1241
+ heating_coil = OpenStudio::Model::CoilHeatingWater.new(model, model.alwaysOnDiscreteSchedule)
1242
+ air_loop_comps << heating_coil
1243
+ else
1244
+ # gas coil
1245
+ heating_coil = OpenStudio::Model::CoilHeatingGas.new(model, model.alwaysOnDiscreteSchedule)
1246
+ air_loop_comps << heating_coil
1247
+ end
1248
+ # create controller outdoor air
1249
+ controller_OA = OpenStudio::Model::ControllerOutdoorAir.new(model)
1250
+ controller_OA.autosizeMinimumOutdoorAirFlowRate
1251
+ controller_OA.autosizeMaximumOutdoorAirFlowRate
1252
+ controller_OA.setEconomizerControlType('DifferentialEnthalpy')
1253
+ controller_OA.setMaximumFractionofOutdoorAirSchedule(options['ventilation_schedule'])
1254
+ controller_OA.setHeatRecoveryBypassControlType('BypassWhenOAFlowGreaterThanMinimum')
1255
+ # create outdoor air system
1256
+ system_OA = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model, controller_OA)
1257
+ air_loop_comps << system_OA
1258
+ # create ERV
1259
+ heat_exchanger = OpenStudio::Model::HeatExchangerAirToAirSensibleAndLatent.new(model)
1260
+ heat_exchanger.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
1261
+ sensible_eff = 0.75
1262
+ latent_eff = 0.69
1263
+ heat_exchanger.setSensibleEffectivenessat100CoolingAirFlow(sensible_eff)
1264
+ heat_exchanger.setSensibleEffectivenessat100HeatingAirFlow(sensible_eff)
1265
+ heat_exchanger.setSensibleEffectivenessat75CoolingAirFlow(sensible_eff)
1266
+ heat_exchanger.setSensibleEffectivenessat75HeatingAirFlow(sensible_eff)
1267
+ heat_exchanger.setLatentEffectivenessat100CoolingAirFlow(latent_eff)
1268
+ heat_exchanger.setLatentEffectivenessat100HeatingAirFlow(latent_eff)
1269
+ heat_exchanger.setLatentEffectivenessat75CoolingAirFlow(latent_eff)
1270
+ heat_exchanger.setLatentEffectivenessat75HeatingAirFlow(latent_eff)
1271
+ heat_exchanger.setFrostControlType('ExhaustOnly')
1272
+ heat_exchanger.setThresholdTemperature(-12.2)
1273
+ heat_exchanger.setInitialDefrostTimeFraction(0.1670)
1274
+ heat_exchanger.setRateofDefrostTimeFractionIncrease(0.0240)
1275
+ heat_exchanger.setEconomizerLockout(false)
1276
+ # create setpoint manager for airloop
1277
+ setpoint_manager = OpenStudio::Model::SetpointManagerSingleZoneReheat.new(model)
1278
+ setpoint_manager.setMinimumSupplyAirTemperature(10)
1279
+ setpoint_manager.setMaximumSupplyAirTemperature(50)
1280
+ setpoint_manager.setControlZone(zone)
1281
+ # connect components to airloop
1282
+ # find the supply inlet node of the airloop
1283
+ airloop_supply_inlet = airloop_secondary.supplyInletNode
1284
+ # add the components to the airloop
1285
+ air_loop_comps.each do |comp|
1286
+ comp.addToNode(airloop_supply_inlet)
1287
+ if comp.to_CoilHeatingWater.is_initialized
1288
+ options['hot_water_plant'].addDemandBranchForComponent(comp)
1289
+ elsif comp.to_CoilCoolingWater.is_initialized
1290
+ options['chilled_water_plant'].addDemandBranchForComponent(comp)
1291
+ end
1292
+ end
1293
+ # add erv to outdoor air system
1294
+ heat_exchanger.addToNode(system_OA.outboardOANode.get)
1295
+ # add setpoint manager to supply equipment outlet node
1296
+ setpoint_manager.addToNode(airloop_secondary.supplyOutletNode)
1297
+ # add thermal zone to airloop
1298
+ if options['secondaryHVAC']['fan'] == 'Variable'
1299
+ air_terminal = OpenStudio::Model::AirTerminalSingleDuctVAVNoReheat.new(model, model.alwaysOnDiscreteSchedule)
1300
+ else
1301
+ air_terminal = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, model.alwaysOnDiscreteSchedule)
1302
+ end
1303
+ # attach new terminal to the zone and to the airloop
1304
+ airloop_secondary.addBranchForZone(zone, air_terminal.to_StraightComponent)
1305
+ # add night cycling
1306
+ airloop_secondary.setNightCycleControlType('CycleOnAny') # ML Does this work with variable speed fans?
1307
+ secondary_airloops << airloop_secondary
1308
+ end
1309
+ end
1310
+
1311
+ # pass back secondary airloops
1312
+ result = secondary_airloops
1313
+ return result
1314
+ end
1315
+
1316
+ def self.createPrimaryZoneEquipment(model, runner, options)
1317
+ model.getThermalZones.each do |zone|
1318
+ if options['zonesPrimary'].include? zone
1319
+ if options['zoneHVAC'] == 'FanCoil'
1320
+ # create fan coil
1321
+ # create fan
1322
+ fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule)
1323
+ fan.setFanEfficiency(0.5)
1324
+ fan.setPressureRise(75) # Pa
1325
+ fan.autosizeMaximumFlowRate
1326
+ fan.setMotorEfficiency(0.9)
1327
+ fan.setMotorInAirstreamFraction(1.0)
1328
+ # create cooling coil and connect to chilled water plant
1329
+ cooling_coil = OpenStudio::Model::CoilCoolingWater.new(model, model.alwaysOnDiscreteSchedule)
1330
+ options['chilled_water_plant'].addDemandBranchForComponent(cooling_coil)
1331
+ # create heating coil and connect to hot water plant
1332
+ heating_coil = OpenStudio::Model::CoilHeatingWater.new(model, model.alwaysOnDiscreteSchedule)
1333
+ options['hot_water_plant'].addDemandBranchForComponent(heating_coil)
1334
+ # construct fan coil
1335
+ fan_coil = OpenStudio::Model::ZoneHVACFourPipeFanCoil.new(model,
1336
+ model.alwaysOnDiscreteSchedule,
1337
+ fan,
1338
+ cooling_coil,
1339
+ heating_coil)
1340
+ fan_coil.setMaximumOutdoorAirFlowRate(0)
1341
+ # add fan coil to thermal zone
1342
+ fan_coil.addToThermalZone(zone)
1343
+ elsif options['zoneHVAC'].include? 'GSHP'
1344
+ # create water source heat pump and attach to heat pump loop
1345
+ # create fan
1346
+ fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule)
1347
+ fan.setFanEfficiency(0.5)
1348
+ fan.setPressureRise(75) # Pa
1349
+ fan.autosizeMaximumFlowRate
1350
+ fan.setMotorEfficiency(0.9)
1351
+ fan.setMotorInAirstreamFraction(1.0)
1352
+ # create cooling coil and connect to heat pump loop
1353
+ cooling_coil = OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit.new(model)
1354
+ cooling_coil.setRatedCoolingCoefficientofPerformance(6.45)
1355
+ cooling_coil.setTotalCoolingCapacityCoefficient1(-9.149069561)
1356
+ cooling_coil.setTotalCoolingCapacityCoefficient2(10.87814026)
1357
+ cooling_coil.setTotalCoolingCapacityCoefficient3(-1.718780157)
1358
+ cooling_coil.setTotalCoolingCapacityCoefficient4(0.746414818)
1359
+ cooling_coil.setTotalCoolingCapacityCoefficient5(0.0)
1360
+ cooling_coil.setSensibleCoolingCapacityCoefficient1(-5.462690012)
1361
+ cooling_coil.setSensibleCoolingCapacityCoefficient2(17.95968138)
1362
+ cooling_coil.setSensibleCoolingCapacityCoefficient3(-11.87818402)
1363
+ cooling_coil.setSensibleCoolingCapacityCoefficient4(-0.980163419)
1364
+ cooling_coil.setSensibleCoolingCapacityCoefficient5(0.767285761)
1365
+ cooling_coil.setSensibleCoolingCapacityCoefficient6(0.0)
1366
+ cooling_coil.setCoolingPowerConsumptionCoefficient1(-3.205409884)
1367
+ cooling_coil.setCoolingPowerConsumptionCoefficient2(-0.976409399)
1368
+ cooling_coil.setCoolingPowerConsumptionCoefficient3(3.97892546)
1369
+ cooling_coil.setCoolingPowerConsumptionCoefficient4(0.938181818)
1370
+ cooling_coil.setCoolingPowerConsumptionCoefficient5(0.0)
1371
+ options['heat_pump_loop'].addDemandBranchForComponent(cooling_coil)
1372
+ # create heating coil and connect to heat pump loop
1373
+ heating_coil = OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit.new(model)
1374
+ heating_coil.setRatedHeatingCoefficientofPerformance(4.0)
1375
+ heating_coil.setHeatingCapacityCoefficient1(-1.361311959)
1376
+ heating_coil.setHeatingCapacityCoefficient2(-2.471798046)
1377
+ heating_coil.setHeatingCapacityCoefficient3(4.173164514)
1378
+ heating_coil.setHeatingCapacityCoefficient4(0.640757401)
1379
+ heating_coil.setHeatingCapacityCoefficient5(0.0)
1380
+ heating_coil.setHeatingPowerConsumptionCoefficient1(-2.176941116)
1381
+ heating_coil.setHeatingPowerConsumptionCoefficient2(0.832114286)
1382
+ heating_coil.setHeatingPowerConsumptionCoefficient3(1.570743399)
1383
+ heating_coil.setHeatingPowerConsumptionCoefficient4(0.690793651)
1384
+ heating_coil.setHeatingPowerConsumptionCoefficient5(0.0)
1385
+ options['heat_pump_loop'].addDemandBranchForComponent(heating_coil)
1386
+ # create supplemental heating coil
1387
+ supplemental_heating_coil = OpenStudio::Model::CoilHeatingElectric.new(model, model.alwaysOnDiscreteSchedule)
1388
+ # construct heat pump
1389
+ heat_pump = OpenStudio::Model::ZoneHVACWaterToAirHeatPump.new(model,
1390
+ model.alwaysOnDiscreteSchedule,
1391
+ fan,
1392
+ heating_coil,
1393
+ cooling_coil,
1394
+ supplemental_heating_coil)
1395
+ heat_pump.setSupplyAirFlowRateWhenNoCoolingorHeatingisNeeded(OpenStudio::OptionalDouble.new(0))
1396
+ heat_pump.setOutdoorAirFlowRateDuringCoolingOperation(OpenStudio::OptionalDouble.new(0))
1397
+ heat_pump.setOutdoorAirFlowRateDuringHeatingOperation(OpenStudio::OptionalDouble.new(0))
1398
+ heat_pump.setOutdoorAirFlowRateWhenNoCoolingorHeatingisNeeded(OpenStudio::OptionalDouble.new(0))
1399
+ # add heat pump to thermal zone
1400
+ heat_pump.addToThermalZone(zone)
1401
+ elsif options['zoneHVAC'] == 'Baseboard'
1402
+ # create baseboard heater add add to thermal zone and hot water loop
1403
+ baseboard_coil = OpenStudio::Model::CoilHeatingWaterBaseboard.new(model)
1404
+ baseboard_heater = OpenStudio::Model::ZoneHVACBaseboardConvectiveWater.new(model, model.alwaysOnDiscreteSchedule, baseboard_coil)
1405
+ baseboard_heater.addToThermalZone(zone)
1406
+ options['hot_water_plant'].addDemandBranchForComponent(baseboard_coil)
1407
+ elsif options['zoneHVAC'] == 'Radiant'
1408
+ # create low temperature radiant object and add to thermal zone and radiant plant loops
1409
+ # create hot water coil and attach to radiant hot water loop
1410
+ heating_coil = OpenStudio::Model::CoilHeatingLowTempRadiantVarFlow.new(model, options['mean_radiant_heating_setpoint_schedule'])
1411
+ options['radiant_hot_water_plant'].addDemandBranchForComponent(heating_coil)
1412
+ # create chilled water coil and attach to radiant chilled water loop
1413
+ cooling_coil = OpenStudio::Model::CoilCoolingLowTempRadiantVarFlow.new(model, options['mean_radiant_cooling_setpoint_schedule'])
1414
+ options['radiant_chilled_water_plant'].addDemandBranchForComponent(cooling_coil)
1415
+ low_temp_radiant = OpenStudio::Model::ZoneHVACLowTempRadiantVarFlow.new(model,
1416
+ model.alwaysOnDiscreteSchedule,
1417
+ heating_coil,
1418
+ cooling_coil)
1419
+ low_temp_radiant.setRadiantSurfaceType('Floors')
1420
+ low_temp_radiant.setHydronicTubingInsideDiameter(0.012)
1421
+ low_temp_radiant.setTemperatureControlType('MeanRadiantTemperature')
1422
+ low_temp_radiant.addToThermalZone(zone)
1423
+ # create radiant floor construction and substitute for existing floor (interior or exterior) constructions
1424
+ # create materials for radiant floor construction
1425
+ layers = []
1426
+ # ignore layer below insulation, which will depend on boundary condition
1427
+ layers << rigid_insulation_1in = OpenStudio::Model::StandardOpaqueMaterial.new(model, 'Rough', 0.0254, 0.02, 56.06, 1210)
1428
+ layers << concrete_2in = OpenStudio::Model::StandardOpaqueMaterial.new(model, 'MediumRough', 0.0508, 2.31, 2322, 832)
1429
+ layers << concrete_2in
1430
+ # create radiant floor construction from materials
1431
+ radiant_floor = OpenStudio::Model::ConstructionWithInternalSource.new(layers)
1432
+ radiant_floor.setSourcePresentAfterLayerNumber(2)
1433
+ radiant_floor.setSourcePresentAfterLayerNumber(2)
1434
+ # assign radiant construction to zone floor
1435
+ zone.spaces.each do |space|
1436
+ space.surfaces.each do |surface|
1437
+ if surface.surfaceType == 'Floor'
1438
+ surface.setConstruction(radiant_floor)
1439
+ end
1440
+ end
1441
+ end
1442
+ elsif options['zoneHVAC'] == 'DualDuct'
1443
+ # create baseboard heater add add to thermal zone and hot water loop
1444
+ baseboard_coil = OpenStudio::Model::CoilHeatingWaterBaseboard.new(model)
1445
+ baseboard_heater = OpenStudio::Model::ZoneHVACBaseboardConvectiveWater.new(model, model.alwaysOnDiscreteSchedule, baseboard_coil)
1446
+ baseboard_heater.addToThermalZone(zone)
1447
+ options['hot_water_plant'].addDemandBranchForComponent(baseboard_coil)
1448
+ # create fan coil (to mimic functionality of DOAS)
1449
+ # variable speed fan
1450
+ fan = OpenStudio::Model::FanVariableVolume.new(model, model.alwaysOnDiscreteSchedule)
1451
+ fan.setFanEfficiency(0.69)
1452
+ fan.setPressureRise(75) # Pa #ML This number is a guess; zone equipment pretending to be a DOAS
1453
+ fan.autosizeMaximumFlowRate
1454
+ fan.setFanPowerMinimumFlowFraction(0.6)
1455
+ fan.setMotorEfficiency(0.9)
1456
+ fan.setMotorInAirstreamFraction(1.0)
1457
+ # create chilled water coil and attach to chilled water loop
1458
+ cooling_coil = OpenStudio::Model::CoilCoolingWater.new(model, model.alwaysOnDiscreteSchedule)
1459
+ options['chilled_water_plant'].addDemandBranchForComponent(cooling_coil)
1460
+ # create hot water coil and attach to hot water loop
1461
+ heating_coil = OpenStudio::Model::CoilHeatingWater.new(model, model.alwaysOnDiscreteSchedule)
1462
+ options['hot_water_plant'].addDemandBranchForComponent(heating_coil)
1463
+ # construct fan coil (DOAS) and attach to thermal zone
1464
+ fan_coil_doas = OpenStudio::Model::ZoneHVACFourPipeFanCoil.new(model,
1465
+ options['ventilation_schedule'],
1466
+ fan,
1467
+ cooling_coil,
1468
+ heating_coil)
1469
+ fan_coil_doas.setCapacityControlMethod('VariableFanVariableFlow')
1470
+ fan_coil_doas.addToThermalZone(zone)
1471
+ end
1472
+ end
1473
+ end
1474
+ end
1475
+
1476
+ def self.addDCV(model, runner, options)
1477
+ unless options['primary_airloops'].nil?
1478
+ options['primary_airloops'].each do |airloop|
1479
+ if options['allHVAC']['primary']['fan'] == 'Variable'
1480
+ controller_mv = airloop.airLoopHVACOutdoorAirSystem.get.getControllerOutdoorAir.controllerMechanicalVentilation
1481
+ controller_mv.setDemandControlledVentilation(true)
1482
+ runner.registerInfo("Enabling demand control ventilation for #{airloop.name}")
1483
+ end
1484
+ end
1485
+ end
1486
+
1487
+ unless options['secondary_airloops'].nil?
1488
+ options['secondary_airloops'].each do |airloop|
1489
+ if options['allHVAC']['secondary']['fan'] == 'Variable'
1490
+ controller_mv = airloop.airLoopHVACOutdoorAirSystem.get.getControllerOutdoorAir.controllerMechanicalVentilation
1491
+ controller_mv.setDemandControlledVentilation(true)
1492
+ runner.registerInfo("Enabling demand control ventilation for #{airloop.name}")
1493
+ end
1494
+ end
1495
+ end
1496
+ end
1497
+
1498
+ def self.getSpacesAndSpaceTypesFromThermalZone(zone, runner)
1499
+ # set flag
1500
+ space_type_hash = {}
1501
+
1502
+ # check if zone has spaces
1503
+ if zone.spaces.empty?
1504
+ runner.registerWarning("#{zone.name} doesn't have any spaces.")
1505
+ else
1506
+ # check if all spaces have the same space type
1507
+ zone.spaces.each do |space|
1508
+ if !space.spaceType.is_initialized
1509
+ runner.registerWarning("One or more spaces in #{zone.name} doesn't have a space type assigned.")
1510
+ space_type_hash[space] = false
1511
+ return space_type
1512
+ else
1513
+ space_type_hash[space] = space.spaceType.get
1514
+ end
1515
+ end
1516
+ end
1517
+
1518
+ return space_type_hash
1519
+ end
1520
+
1521
+ def self.get_or_add_hot_water_loop(model)
1522
+ # How water loop
1523
+ hw_loop = nil
1524
+ model.getLoops.each do |loop|
1525
+ if loop.name.to_s == 'Hot Water Loop' # sizingPlant has loopType method to do this better
1526
+ hw_loop = loop.to_PlantLoop.get
1527
+ end
1528
+ end
1529
+
1530
+ if hw_loop.nil?
1531
+ hw_loop = OpenStudio::Model::PlantLoop.new(model)
1532
+ hw_loop.setName('Hot Water Loop')
1533
+ hw_sizing_plant = hw_loop.sizingPlant
1534
+ hw_sizing_plant.setLoopType('Heating')
1535
+ hw_sizing_plant.setDesignLoopExitTemperature(82.0) # TODO: units
1536
+ hw_sizing_plant.setLoopDesignTemperatureDifference(11.0)
1537
+
1538
+ hw_pump = OpenStudio::Model::PumpVariableSpeed.new(model)
1539
+
1540
+ boiler = OpenStudio::Model::BoilerHotWater.new(model)
1541
+
1542
+ boiler_eff_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1543
+ boiler_eff_f_of_temp.setName('Boiler Efficiency')
1544
+ boiler_eff_f_of_temp.setCoefficient1Constant(1.0)
1545
+ boiler_eff_f_of_temp.setInputUnitTypeforX('Dimensionless')
1546
+ boiler_eff_f_of_temp.setInputUnitTypeforY('Dimensionless')
1547
+ boiler_eff_f_of_temp.setOutputUnitType('Dimensionless')
1548
+
1549
+ boiler.setNormalizedBoilerEfficiencyCurve(boiler_eff_f_of_temp)
1550
+ boiler.setEfficiencyCurveTemperatureEvaluationVariable('LeavingBoiler')
1551
+
1552
+ boiler_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1553
+
1554
+ hw_supply_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1555
+
1556
+ # Add the components to the hot water loop
1557
+ hw_supply_inlet_node = hw_loop.supplyInletNode
1558
+ hw_supply_outlet_node = hw_loop.supplyOutletNode
1559
+ hw_pump.addToNode(hw_supply_inlet_node)
1560
+ hw_loop.addSupplyBranchForComponent(boiler)
1561
+ hw_loop.addSupplyBranchForComponent(boiler_bypass_pipe)
1562
+ hw_supply_outlet_pipe.addToNode(hw_supply_outlet_node)
1563
+
1564
+ # Add a setpoint manager to control the
1565
+ # hot water to a constant temperature
1566
+ hw_t_c = OpenStudio.convert(153, 'F', 'C').get
1567
+ hw_t_sch = OpenStudio::Model::ScheduleRuleset.new(model)
1568
+ hw_t_sch.setName('HW Temp')
1569
+ hw_t_sch.defaultDaySchedule.setName('HW Temp Default')
1570
+ hw_t_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), hw_t_c)
1571
+ hw_t_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, hw_t_sch)
1572
+ hw_t_stpt_manager.addToNode(hw_supply_outlet_node)
1573
+
1574
+ end
1575
+
1576
+ return hw_loop
1577
+ end
1578
+
1579
+ def self.get_or_add_water_cooled_chiller_loops(model)
1580
+ # Chilled Water Plant
1581
+ # todo - add in logic here that if existing chw_loop is air cooled, replace it with this one.
1582
+ chw_loop = nil
1583
+ model.getLoops.each do |loop|
1584
+ if loop.name.to_s == 'Chilled Water Loop'
1585
+ chw_loop = loop.to_PlantLoop.get
1586
+ end
1587
+ end
1588
+
1589
+ if chw_loop.nil?
1590
+ chw_loop = OpenStudio::Model::PlantLoop.new(model)
1591
+ chw_loop.setName('Chilled Water Loop')
1592
+ chw_sizing_plant = chw_loop.sizingPlant
1593
+ chw_sizing_plant.setLoopType('Cooling')
1594
+ chw_sizing_plant.setDesignLoopExitTemperature(7.22) # TODO: units
1595
+ chw_sizing_plant.setLoopDesignTemperatureDifference(6.67)
1596
+
1597
+ chw_pump = OpenStudio::Model::PumpVariableSpeed.new(model)
1598
+
1599
+ clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1600
+ clg_cap_f_of_temp.setCoefficient1Constant(1.0215158)
1601
+ clg_cap_f_of_temp.setCoefficient2x(0.037035864)
1602
+ clg_cap_f_of_temp.setCoefficient3xPOW2(0.0002332476)
1603
+ clg_cap_f_of_temp.setCoefficient4y(-0.003894048)
1604
+ clg_cap_f_of_temp.setCoefficient5yPOW2(-6.52536e-005)
1605
+ clg_cap_f_of_temp.setCoefficient6xTIMESY(-0.0002680452)
1606
+ clg_cap_f_of_temp.setMinimumValueofx(5.0)
1607
+ clg_cap_f_of_temp.setMaximumValueofx(10.0)
1608
+ clg_cap_f_of_temp.setMinimumValueofy(24.0)
1609
+ clg_cap_f_of_temp.setMaximumValueofy(35.0)
1610
+
1611
+ eir_f_of_avail_to_nom_cap = OpenStudio::Model::CurveBiquadratic.new(model)
1612
+ eir_f_of_avail_to_nom_cap.setCoefficient1Constant(0.70176857)
1613
+ eir_f_of_avail_to_nom_cap.setCoefficient2x(-0.00452016)
1614
+ eir_f_of_avail_to_nom_cap.setCoefficient3xPOW2(0.0005331096)
1615
+ eir_f_of_avail_to_nom_cap.setCoefficient4y(-0.005498208)
1616
+ eir_f_of_avail_to_nom_cap.setCoefficient5yPOW2(0.0005445792)
1617
+ eir_f_of_avail_to_nom_cap.setCoefficient6xTIMESY(-0.0007290324)
1618
+ eir_f_of_avail_to_nom_cap.setMinimumValueofx(5.0)
1619
+ eir_f_of_avail_to_nom_cap.setMaximumValueofx(10.0)
1620
+ eir_f_of_avail_to_nom_cap.setMinimumValueofy(24.0)
1621
+ eir_f_of_avail_to_nom_cap.setMaximumValueofy(35.0)
1622
+
1623
+ eir_f_of_plr = OpenStudio::Model::CurveQuadratic.new(model)
1624
+ eir_f_of_plr.setCoefficient1Constant(0.06369119)
1625
+ eir_f_of_plr.setCoefficient2x(0.58488832)
1626
+ eir_f_of_plr.setCoefficient3xPOW2(0.35280274)
1627
+ eir_f_of_plr.setMinimumValueofx(0.0)
1628
+ eir_f_of_plr.setMaximumValueofx(1.0)
1629
+
1630
+ chiller = OpenStudio::Model::ChillerElectricEIR.new(model,
1631
+ clg_cap_f_of_temp,
1632
+ eir_f_of_avail_to_nom_cap,
1633
+ eir_f_of_plr)
1634
+
1635
+ chiller_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1636
+
1637
+ chw_supply_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1638
+
1639
+ # Add the components to the chilled water loop
1640
+ chw_supply_inlet_node = chw_loop.supplyInletNode
1641
+ chw_supply_outlet_node = chw_loop.supplyOutletNode
1642
+ chw_pump.addToNode(chw_supply_inlet_node)
1643
+ chw_loop.addSupplyBranchForComponent(chiller)
1644
+ chw_loop.addSupplyBranchForComponent(chiller_bypass_pipe)
1645
+ chw_supply_outlet_pipe.addToNode(chw_supply_outlet_node)
1646
+
1647
+ # Add a setpoint manager to control the
1648
+ # chilled water to a constant temperature
1649
+ chw_t_c = OpenStudio.convert(44, 'F', 'C').get
1650
+ chw_t_sch = OpenStudio::Model::ScheduleRuleset.new(model)
1651
+ chw_t_sch.setName('CHW Temp')
1652
+ chw_t_sch.defaultDaySchedule.setName('HW Temp Default')
1653
+ chw_t_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), chw_t_c)
1654
+ chw_t_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, chw_t_sch)
1655
+ chw_t_stpt_manager.addToNode(chw_supply_outlet_node)
1656
+
1657
+ end
1658
+
1659
+ # Condenser System
1660
+ cw_loop = nil
1661
+ model.getLoops.each do |loop|
1662
+ if loop.name.to_s == 'Condenser Water Loop'
1663
+ cw_loop = loop.to_PlantLoop.get
1664
+ end
1665
+ end
1666
+
1667
+ if cw_loop.nil?
1668
+ cw_loop = OpenStudio::Model::PlantLoop.new(model)
1669
+ cw_loop.setName('Condenser Water Loop')
1670
+ cw_sizing_plant = cw_loop.sizingPlant
1671
+ cw_sizing_plant.setLoopType('Condenser')
1672
+ cw_sizing_plant.setDesignLoopExitTemperature(29.4) # TODO: units
1673
+ cw_sizing_plant.setLoopDesignTemperatureDifference(5.6)
1674
+
1675
+ cw_pump = OpenStudio::Model::PumpVariableSpeed.new(model)
1676
+
1677
+ clg_tower = OpenStudio::Model::CoolingTowerSingleSpeed.new(model)
1678
+
1679
+ clg_tower_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1680
+
1681
+ cw_supply_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1682
+
1683
+ # Add the components to the condenser water loop
1684
+ cw_supply_inlet_node = cw_loop.supplyInletNode
1685
+ cw_supply_outlet_node = cw_loop.supplyOutletNode
1686
+ cw_pump.addToNode(cw_supply_inlet_node)
1687
+ cw_loop.addSupplyBranchForComponent(clg_tower)
1688
+ cw_loop.addSupplyBranchForComponent(clg_tower_bypass_pipe)
1689
+ cw_supply_outlet_pipe.addToNode(cw_supply_outlet_node)
1690
+ cw_loop.addDemandBranchForComponent(chiller)
1691
+
1692
+ # Add a setpoint manager to control the
1693
+ # condenser water to follow the OA temp
1694
+ cw_t_stpt_manager = OpenStudio::Model::SetpointManagerFollowOutdoorAirTemperature.new(model)
1695
+ cw_t_stpt_manager.addToNode(cw_supply_outlet_node)
1696
+
1697
+ end
1698
+
1699
+ return chw_loop
1700
+ end
1701
+
1702
+ def self.get_or_add_air_cooled_chiller_loop(model)
1703
+ # Chilled Water Plant
1704
+ chw_loop = nil
1705
+ model.getLoops.each do |loop|
1706
+ if loop.name.to_s == 'Chilled Water Loop'
1707
+ chw_loop = loop.to_PlantLoop.get
1708
+ end
1709
+ end
1710
+
1711
+ if chw_loop.nil?
1712
+ chw_loop = OpenStudio::Model::PlantLoop.new(model)
1713
+ chw_loop.setName('Chilled Water Loop')
1714
+ chw_sizing_plant = chw_loop.sizingPlant
1715
+ chw_sizing_plant.setLoopType('Cooling')
1716
+ chw_sizing_plant.setDesignLoopExitTemperature(7.22) # TODO: units
1717
+ chw_sizing_plant.setLoopDesignTemperatureDifference(6.67)
1718
+
1719
+ chw_pump = OpenStudio::Model::PumpVariableSpeed.new(model)
1720
+
1721
+ clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1722
+ clg_cap_f_of_temp.setCoefficient1Constant(1.0215158)
1723
+ clg_cap_f_of_temp.setCoefficient2x(0.037035864)
1724
+ clg_cap_f_of_temp.setCoefficient3xPOW2(0.0002332476)
1725
+ clg_cap_f_of_temp.setCoefficient4y(-0.003894048)
1726
+ clg_cap_f_of_temp.setCoefficient5yPOW2(-6.52536e-005)
1727
+ clg_cap_f_of_temp.setCoefficient6xTIMESY(-0.0002680452)
1728
+ clg_cap_f_of_temp.setMinimumValueofx(5.0)
1729
+ clg_cap_f_of_temp.setMaximumValueofx(10.0)
1730
+ clg_cap_f_of_temp.setMinimumValueofy(24.0)
1731
+ clg_cap_f_of_temp.setMaximumValueofy(35.0)
1732
+
1733
+ eir_f_of_avail_to_nom_cap = OpenStudio::Model::CurveBiquadratic.new(model)
1734
+ eir_f_of_avail_to_nom_cap.setCoefficient1Constant(0.70176857)
1735
+ eir_f_of_avail_to_nom_cap.setCoefficient2x(-0.00452016)
1736
+ eir_f_of_avail_to_nom_cap.setCoefficient3xPOW2(0.0005331096)
1737
+ eir_f_of_avail_to_nom_cap.setCoefficient4y(-0.005498208)
1738
+ eir_f_of_avail_to_nom_cap.setCoefficient5yPOW2(0.0005445792)
1739
+ eir_f_of_avail_to_nom_cap.setCoefficient6xTIMESY(-0.0007290324)
1740
+ eir_f_of_avail_to_nom_cap.setMinimumValueofx(5.0)
1741
+ eir_f_of_avail_to_nom_cap.setMaximumValueofx(10.0)
1742
+ eir_f_of_avail_to_nom_cap.setMinimumValueofy(24.0)
1743
+ eir_f_of_avail_to_nom_cap.setMaximumValueofy(35.0)
1744
+
1745
+ eir_f_of_plr = OpenStudio::Model::CurveQuadratic.new(model)
1746
+ eir_f_of_plr.setCoefficient1Constant(0.06369119)
1747
+ eir_f_of_plr.setCoefficient2x(0.58488832)
1748
+ eir_f_of_plr.setCoefficient3xPOW2(0.35280274)
1749
+ eir_f_of_plr.setMinimumValueofx(0.0)
1750
+ eir_f_of_plr.setMaximumValueofx(1.0)
1751
+
1752
+ chiller = OpenStudio::Model::ChillerElectricEIR.new(model,
1753
+ clg_cap_f_of_temp,
1754
+ eir_f_of_avail_to_nom_cap,
1755
+ eir_f_of_plr)
1756
+
1757
+ chiller_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1758
+
1759
+ chw_supply_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1760
+
1761
+ # Add the components to the chilled water loop
1762
+ chw_supply_inlet_node = chw_loop.supplyInletNode
1763
+ chw_supply_outlet_node = chw_loop.supplyOutletNode
1764
+ chw_pump.addToNode(chw_supply_inlet_node)
1765
+ chw_loop.addSupplyBranchForComponent(chiller)
1766
+ chw_loop.addSupplyBranchForComponent(chiller_bypass_pipe)
1767
+ chw_supply_outlet_pipe.addToNode(chw_supply_outlet_node)
1768
+
1769
+ # Add a setpoint manager to control the
1770
+ # chilled water to a constant temperature
1771
+ chw_t_c = OpenStudio.convert(44, 'F', 'C').get
1772
+ chw_t_sch = OpenStudio::Model::ScheduleRuleset.new(model)
1773
+ chw_t_sch.setName('CHW Temp')
1774
+ chw_t_sch.defaultDaySchedule.setName('HW Temp Default')
1775
+ chw_t_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), chw_t_c)
1776
+ chw_t_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, chw_t_sch)
1777
+ chw_t_stpt_manager.addToNode(chw_supply_outlet_node)
1778
+
1779
+ end
1780
+
1781
+ return chw_loop
1782
+ end
1783
+
1784
+ def self._add_coil_cooling_dx_two_speed(model)
1785
+ clg_coil = nil
1786
+
1787
+ always_on = model.alwaysOnDiscreteSchedule
1788
+
1789
+ clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1790
+ clg_cap_f_of_temp.setCoefficient1Constant(0.42415)
1791
+ clg_cap_f_of_temp.setCoefficient2x(0.04426)
1792
+ clg_cap_f_of_temp.setCoefficient3xPOW2(-0.00042)
1793
+ clg_cap_f_of_temp.setCoefficient4y(0.00333)
1794
+ clg_cap_f_of_temp.setCoefficient5yPOW2(-0.00008)
1795
+ clg_cap_f_of_temp.setCoefficient6xTIMESY(-0.00021)
1796
+ clg_cap_f_of_temp.setMinimumValueofx(17.0)
1797
+ clg_cap_f_of_temp.setMaximumValueofx(22.0)
1798
+ clg_cap_f_of_temp.setMinimumValueofy(13.0)
1799
+ clg_cap_f_of_temp.setMaximumValueofy(46.0)
1800
+
1801
+ clg_cap_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
1802
+ clg_cap_f_of_flow.setCoefficient1Constant(0.77136)
1803
+ clg_cap_f_of_flow.setCoefficient2x(0.34053)
1804
+ clg_cap_f_of_flow.setCoefficient3xPOW2(-0.11088)
1805
+ clg_cap_f_of_flow.setMinimumValueofx(0.75918)
1806
+ clg_cap_f_of_flow.setMaximumValueofx(1.13877)
1807
+
1808
+ clg_energy_input_ratio_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1809
+ clg_energy_input_ratio_f_of_temp.setCoefficient1Constant(1.23649)
1810
+ clg_energy_input_ratio_f_of_temp.setCoefficient2x(-0.02431)
1811
+ clg_energy_input_ratio_f_of_temp.setCoefficient3xPOW2(0.00057)
1812
+ clg_energy_input_ratio_f_of_temp.setCoefficient4y(-0.01434)
1813
+ clg_energy_input_ratio_f_of_temp.setCoefficient5yPOW2(0.00063)
1814
+ clg_energy_input_ratio_f_of_temp.setCoefficient6xTIMESY(-0.00038)
1815
+ clg_energy_input_ratio_f_of_temp.setMinimumValueofx(17.0)
1816
+ clg_energy_input_ratio_f_of_temp.setMaximumValueofx(22.0)
1817
+ clg_energy_input_ratio_f_of_temp.setMinimumValueofy(13.0)
1818
+ clg_energy_input_ratio_f_of_temp.setMaximumValueofy(46.0)
1819
+
1820
+ clg_energy_input_ratio_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
1821
+ clg_energy_input_ratio_f_of_flow.setCoefficient1Constant(1.20550)
1822
+ clg_energy_input_ratio_f_of_flow.setCoefficient2x(-0.32953)
1823
+ clg_energy_input_ratio_f_of_flow.setCoefficient3xPOW2(0.12308)
1824
+ clg_energy_input_ratio_f_of_flow.setMinimumValueofx(0.75918)
1825
+ clg_energy_input_ratio_f_of_flow.setMaximumValueofx(1.13877)
1826
+
1827
+ clg_part_load_ratio = OpenStudio::Model::CurveQuadratic.new(model)
1828
+ clg_part_load_ratio.setCoefficient1Constant(0.77100)
1829
+ clg_part_load_ratio.setCoefficient2x(0.22900)
1830
+ clg_part_load_ratio.setCoefficient3xPOW2(0.0)
1831
+ clg_part_load_ratio.setMinimumValueofx(0.0)
1832
+ clg_part_load_ratio.setMaximumValueofx(1.0)
1833
+
1834
+ clg_cap_f_of_temp_low_spd = OpenStudio::Model::CurveBiquadratic.new(model)
1835
+ clg_cap_f_of_temp_low_spd.setCoefficient1Constant(0.42415)
1836
+ clg_cap_f_of_temp_low_spd.setCoefficient2x(0.04426)
1837
+ clg_cap_f_of_temp_low_spd.setCoefficient3xPOW2(-0.00042)
1838
+ clg_cap_f_of_temp_low_spd.setCoefficient4y(0.00333)
1839
+ clg_cap_f_of_temp_low_spd.setCoefficient5yPOW2(-0.00008)
1840
+ clg_cap_f_of_temp_low_spd.setCoefficient6xTIMESY(-0.00021)
1841
+ clg_cap_f_of_temp_low_spd.setMinimumValueofx(17.0)
1842
+ clg_cap_f_of_temp_low_spd.setMaximumValueofx(22.0)
1843
+ clg_cap_f_of_temp_low_spd.setMinimumValueofy(13.0)
1844
+ clg_cap_f_of_temp_low_spd.setMaximumValueofy(46.0)
1845
+
1846
+ clg_energy_input_ratio_f_of_temp_low_spd = OpenStudio::Model::CurveBiquadratic.new(model)
1847
+ clg_energy_input_ratio_f_of_temp_low_spd.setCoefficient1Constant(1.23649)
1848
+ clg_energy_input_ratio_f_of_temp_low_spd.setCoefficient2x(-0.02431)
1849
+ clg_energy_input_ratio_f_of_temp_low_spd.setCoefficient3xPOW2(0.00057)
1850
+ clg_energy_input_ratio_f_of_temp_low_spd.setCoefficient4y(-0.01434)
1851
+ clg_energy_input_ratio_f_of_temp_low_spd.setCoefficient5yPOW2(0.00063)
1852
+ clg_energy_input_ratio_f_of_temp_low_spd.setCoefficient6xTIMESY(-0.00038)
1853
+ clg_energy_input_ratio_f_of_temp_low_spd.setMinimumValueofx(17.0)
1854
+ clg_energy_input_ratio_f_of_temp_low_spd.setMaximumValueofx(22.0)
1855
+ clg_energy_input_ratio_f_of_temp_low_spd.setMinimumValueofy(13.0)
1856
+ clg_energy_input_ratio_f_of_temp_low_spd.setMaximumValueofy(46.0)
1857
+
1858
+ clg_coil = OpenStudio::Model::CoilCoolingDXTwoSpeed.new(model,
1859
+ always_on,
1860
+ clg_cap_f_of_temp,
1861
+ clg_cap_f_of_flow,
1862
+ clg_energy_input_ratio_f_of_temp,
1863
+ clg_energy_input_ratio_f_of_flow,
1864
+ clg_part_load_ratio,
1865
+ clg_cap_f_of_temp_low_spd,
1866
+ clg_energy_input_ratio_f_of_temp_low_spd)
1867
+
1868
+ clg_coil.setRatedLowSpeedSensibleHeatRatio(OpenStudio::OptionalDouble.new(0.69))
1869
+ clg_coil.setBasinHeaterCapacity(10)
1870
+ clg_coil.setBasinHeaterSetpointTemperature(2.0)
1871
+
1872
+ return clg_coil
1873
+ end
1874
+
1875
+ def self._add_coil_cooling_dx_single_speed_sys_type_1(model)
1876
+ clg_coil = nil
1877
+
1878
+ always_on = model.alwaysOnDiscreteSchedule
1879
+
1880
+ clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1881
+ clg_cap_f_of_temp.setCoefficient1Constant(0.942587793)
1882
+ clg_cap_f_of_temp.setCoefficient2x(0.009543347)
1883
+ clg_cap_f_of_temp.setCoefficient3xPOW2(0.000683770)
1884
+ clg_cap_f_of_temp.setCoefficient4y(-0.011042676)
1885
+ clg_cap_f_of_temp.setCoefficient5yPOW2(0.000005249)
1886
+ clg_cap_f_of_temp.setCoefficient6xTIMESY(-0.000009720)
1887
+ clg_cap_f_of_temp.setMinimumValueofx(17.0)
1888
+ clg_cap_f_of_temp.setMaximumValueofx(22.0)
1889
+ clg_cap_f_of_temp.setMinimumValueofy(13.0)
1890
+ clg_cap_f_of_temp.setMaximumValueofy(46.0)
1891
+
1892
+ clg_cap_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
1893
+ clg_cap_f_of_flow.setCoefficient1Constant(0.8)
1894
+ clg_cap_f_of_flow.setCoefficient2x(0.2)
1895
+ clg_cap_f_of_flow.setCoefficient3xPOW2(0.0)
1896
+ clg_cap_f_of_flow.setMinimumValueofx(0.5)
1897
+ clg_cap_f_of_flow.setMaximumValueofx(1.5)
1898
+
1899
+ energy_input_ratio_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1900
+ energy_input_ratio_f_of_temp.setCoefficient1Constant(0.342414409)
1901
+ energy_input_ratio_f_of_temp.setCoefficient2x(0.034885008)
1902
+ energy_input_ratio_f_of_temp.setCoefficient3xPOW2(-0.000623700)
1903
+ energy_input_ratio_f_of_temp.setCoefficient4y(0.004977216)
1904
+ energy_input_ratio_f_of_temp.setCoefficient5yPOW2(0.000437951)
1905
+ energy_input_ratio_f_of_temp.setCoefficient6xTIMESY(-0.000728028)
1906
+ energy_input_ratio_f_of_temp.setMinimumValueofx(17.0)
1907
+ energy_input_ratio_f_of_temp.setMaximumValueofx(22.0)
1908
+ energy_input_ratio_f_of_temp.setMinimumValueofy(13.0)
1909
+ energy_input_ratio_f_of_temp.setMaximumValueofy(46.0)
1910
+
1911
+ energy_input_ratio_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
1912
+ energy_input_ratio_f_of_flow.setCoefficient1Constant(1.1552)
1913
+ energy_input_ratio_f_of_flow.setCoefficient2x(-0.1808)
1914
+ energy_input_ratio_f_of_flow.setCoefficient3xPOW2(0.0256)
1915
+ energy_input_ratio_f_of_flow.setMinimumValueofx(0.5)
1916
+ energy_input_ratio_f_of_flow.setMaximumValueofx(1.5)
1917
+
1918
+ part_load_fraction = OpenStudio::Model::CurveQuadratic.new(model)
1919
+ part_load_fraction.setCoefficient1Constant(0.85)
1920
+ part_load_fraction.setCoefficient2x(0.15)
1921
+ part_load_fraction.setCoefficient3xPOW2(0.0)
1922
+ part_load_fraction.setMinimumValueofx(0.0)
1923
+ part_load_fraction.setMaximumValueofx(1.0)
1924
+
1925
+ clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model,
1926
+ always_on,
1927
+ clg_cap_f_of_temp,
1928
+ clg_cap_f_of_flow,
1929
+ energy_input_ratio_f_of_temp,
1930
+ energy_input_ratio_f_of_flow,
1931
+ part_load_fraction)
1932
+
1933
+ return clg_coil
1934
+ end
1935
+
1936
+ def self._add_coil_cooling_dx_single_speed_sys_type_2(model)
1937
+ clg_coil = nil
1938
+
1939
+ always_on = model.alwaysOnDiscreteSchedule
1940
+
1941
+ clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1942
+ clg_cap_f_of_temp.setCoefficient1Constant(0.942587793)
1943
+ clg_cap_f_of_temp.setCoefficient2x(0.009543347)
1944
+ clg_cap_f_of_temp.setCoefficient3xPOW2(0.0018423)
1945
+ clg_cap_f_of_temp.setCoefficient4y(-0.011042676)
1946
+ clg_cap_f_of_temp.setCoefficient5yPOW2(0.000005249)
1947
+ clg_cap_f_of_temp.setCoefficient6xTIMESY(-0.000009720)
1948
+ clg_cap_f_of_temp.setMinimumValueofx(17.0)
1949
+ clg_cap_f_of_temp.setMaximumValueofx(22.0)
1950
+ clg_cap_f_of_temp.setMinimumValueofy(13.0)
1951
+ clg_cap_f_of_temp.setMaximumValueofy(46.0)
1952
+
1953
+ clg_cap_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
1954
+ clg_cap_f_of_flow.setCoefficient1Constant(0.718954)
1955
+ clg_cap_f_of_flow.setCoefficient2x(0.435436)
1956
+ clg_cap_f_of_flow.setCoefficient3xPOW2(-0.154193)
1957
+ clg_cap_f_of_flow.setMinimumValueofx(0.75)
1958
+ clg_cap_f_of_flow.setMaximumValueofx(1.25)
1959
+
1960
+ clg_energy_input_ratio_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
1961
+ clg_energy_input_ratio_f_of_temp.setCoefficient1Constant(0.342414409)
1962
+ clg_energy_input_ratio_f_of_temp.setCoefficient2x(0.034885008)
1963
+ clg_energy_input_ratio_f_of_temp.setCoefficient3xPOW2(-0.000623700)
1964
+ clg_energy_input_ratio_f_of_temp.setCoefficient4y(0.004977216)
1965
+ clg_energy_input_ratio_f_of_temp.setCoefficient5yPOW2(0.000437951)
1966
+ clg_energy_input_ratio_f_of_temp.setCoefficient6xTIMESY(-0.000728028)
1967
+ clg_energy_input_ratio_f_of_temp.setMinimumValueofx(17.0)
1968
+ clg_energy_input_ratio_f_of_temp.setMaximumValueofx(22.0)
1969
+ clg_energy_input_ratio_f_of_temp.setMinimumValueofy(13.0)
1970
+ clg_energy_input_ratio_f_of_temp.setMaximumValueofy(46.0)
1971
+
1972
+ clg_energy_input_ratio_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
1973
+ clg_energy_input_ratio_f_of_flow.setCoefficient1Constant(1.1552)
1974
+ clg_energy_input_ratio_f_of_flow.setCoefficient2x(-0.1808)
1975
+ clg_energy_input_ratio_f_of_flow.setCoefficient3xPOW2(0.0256)
1976
+ clg_energy_input_ratio_f_of_flow.setMinimumValueofx(0.5)
1977
+ clg_energy_input_ratio_f_of_flow.setMaximumValueofx(1.5)
1978
+
1979
+ clg_part_load_fraction = OpenStudio::Model::CurveQuadratic.new(model)
1980
+ clg_part_load_fraction.setCoefficient1Constant(0.75)
1981
+ clg_part_load_fraction.setCoefficient2x(0.25)
1982
+ clg_part_load_fraction.setCoefficient3xPOW2(0.0)
1983
+ clg_part_load_fraction.setMinimumValueofx(0.0)
1984
+ clg_part_load_fraction.setMaximumValueofx(1.0)
1985
+
1986
+ clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model,
1987
+ always_on,
1988
+ clg_cap_f_of_temp,
1989
+ clg_cap_f_of_flow,
1990
+ clg_energy_input_ratio_f_of_temp,
1991
+ clg_energy_input_ratio_f_of_flow,
1992
+ clg_part_load_fraction)
1993
+
1994
+ return clg_coil
1995
+ end
1996
+
1997
+ def self._add_coil_cooling_dx_single_speed_sys_type_3(model)
1998
+ clg_coil = nil
1999
+
2000
+ always_on = model.alwaysOnDiscreteSchedule
2001
+
2002
+ clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
2003
+ clg_cap_f_of_temp.setCoefficient1Constant(0.42415)
2004
+ clg_cap_f_of_temp.setCoefficient2x(0.04426)
2005
+ clg_cap_f_of_temp.setCoefficient3xPOW2(-0.00042)
2006
+ clg_cap_f_of_temp.setCoefficient4y(0.00333)
2007
+ clg_cap_f_of_temp.setCoefficient5yPOW2(-0.00008)
2008
+ clg_cap_f_of_temp.setCoefficient6xTIMESY(-0.00021)
2009
+ clg_cap_f_of_temp.setMinimumValueofx(17.0)
2010
+ clg_cap_f_of_temp.setMaximumValueofx(22.0)
2011
+ clg_cap_f_of_temp.setMinimumValueofy(13.0)
2012
+ clg_cap_f_of_temp.setMaximumValueofy(46.0)
2013
+
2014
+ clg_cap_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
2015
+ clg_cap_f_of_flow.setCoefficient1Constant(0.77136)
2016
+ clg_cap_f_of_flow.setCoefficient2x(0.34053)
2017
+ clg_cap_f_of_flow.setCoefficient3xPOW2(-0.11088)
2018
+ clg_cap_f_of_flow.setMinimumValueofx(0.75918)
2019
+ clg_cap_f_of_flow.setMaximumValueofx(1.13877)
2020
+
2021
+ clg_energy_input_ratio_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
2022
+ clg_energy_input_ratio_f_of_temp.setCoefficient1Constant(1.23649)
2023
+ clg_energy_input_ratio_f_of_temp.setCoefficient2x(-0.02431)
2024
+ clg_energy_input_ratio_f_of_temp.setCoefficient3xPOW2(0.00057)
2025
+ clg_energy_input_ratio_f_of_temp.setCoefficient4y(-0.01434)
2026
+ clg_energy_input_ratio_f_of_temp.setCoefficient5yPOW2(0.00063)
2027
+ clg_energy_input_ratio_f_of_temp.setCoefficient6xTIMESY(-0.00038)
2028
+ clg_energy_input_ratio_f_of_temp.setMinimumValueofx(17.0)
2029
+ clg_energy_input_ratio_f_of_temp.setMaximumValueofx(22.0)
2030
+ clg_energy_input_ratio_f_of_temp.setMinimumValueofy(13.0)
2031
+ clg_energy_input_ratio_f_of_temp.setMaximumValueofy(46.0)
2032
+
2033
+ clg_energy_input_ratio_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
2034
+ clg_energy_input_ratio_f_of_flow.setCoefficient1Constant(1.20550)
2035
+ clg_energy_input_ratio_f_of_flow.setCoefficient2x(-0.32953)
2036
+ clg_energy_input_ratio_f_of_flow.setCoefficient3xPOW2(0.12308)
2037
+ clg_energy_input_ratio_f_of_flow.setMinimumValueofx(0.75918)
2038
+ clg_energy_input_ratio_f_of_flow.setMaximumValueofx(1.13877)
2039
+
2040
+ clg_part_load_ratio = OpenStudio::Model::CurveQuadratic.new(model)
2041
+ clg_part_load_ratio.setCoefficient1Constant(0.77100)
2042
+ clg_part_load_ratio.setCoefficient2x(0.22900)
2043
+ clg_part_load_ratio.setCoefficient3xPOW2(0.0)
2044
+ clg_part_load_ratio.setMinimumValueofx(0.0)
2045
+ clg_part_load_ratio.setMaximumValueofx(1.0)
2046
+
2047
+ clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model,
2048
+ always_on,
2049
+ clg_cap_f_of_temp,
2050
+ clg_cap_f_of_flow,
2051
+ clg_energy_input_ratio_f_of_temp,
2052
+ clg_energy_input_ratio_f_of_flow,
2053
+ clg_part_load_ratio)
2054
+
2055
+ return clg_coil
2056
+ end
2057
+
2058
+ def self._add_coil_cooling_dx_single_speed_sys_type_4(model)
2059
+ clg_coil = nil
2060
+
2061
+ always_on = model.alwaysOnDiscreteSchedule
2062
+
2063
+ clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
2064
+ clg_cap_f_of_temp.setCoefficient1Constant(0.766956)
2065
+ clg_cap_f_of_temp.setCoefficient2x(0.0107756)
2066
+ clg_cap_f_of_temp.setCoefficient3xPOW2(-0.0000414703)
2067
+ clg_cap_f_of_temp.setCoefficient4y(0.00134961)
2068
+ clg_cap_f_of_temp.setCoefficient5yPOW2(-0.000261144)
2069
+ clg_cap_f_of_temp.setCoefficient6xTIMESY(0.000457488)
2070
+ clg_cap_f_of_temp.setMinimumValueofx(17.0)
2071
+ clg_cap_f_of_temp.setMaximumValueofx(22.0)
2072
+ clg_cap_f_of_temp.setMinimumValueofy(13.0)
2073
+ clg_cap_f_of_temp.setMaximumValueofy(46.0)
2074
+
2075
+ clg_cap_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
2076
+ clg_cap_f_of_flow.setCoefficient1Constant(0.8)
2077
+ clg_cap_f_of_flow.setCoefficient2x(0.2)
2078
+ clg_cap_f_of_flow.setCoefficient3xPOW2(0.0)
2079
+ clg_cap_f_of_flow.setMinimumValueofx(0.5)
2080
+ clg_cap_f_of_flow.setMaximumValueofx(1.5)
2081
+
2082
+ clg_energy_input_ratio_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(model)
2083
+ clg_energy_input_ratio_f_of_temp.setCoefficient1Constant(0.297145)
2084
+ clg_energy_input_ratio_f_of_temp.setCoefficient2x(0.0430933)
2085
+ clg_energy_input_ratio_f_of_temp.setCoefficient3xPOW2(-0.000748766)
2086
+ clg_energy_input_ratio_f_of_temp.setCoefficient4y(0.00597727)
2087
+ clg_energy_input_ratio_f_of_temp.setCoefficient5yPOW2(0.000482112)
2088
+ clg_energy_input_ratio_f_of_temp.setCoefficient6xTIMESY(-0.000956448)
2089
+ clg_energy_input_ratio_f_of_temp.setMinimumValueofx(17.0)
2090
+ clg_energy_input_ratio_f_of_temp.setMaximumValueofx(22.0)
2091
+ clg_energy_input_ratio_f_of_temp.setMinimumValueofy(13.0)
2092
+ clg_energy_input_ratio_f_of_temp.setMaximumValueofy(46.0)
2093
+
2094
+ clg_energy_input_ratio_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
2095
+ clg_energy_input_ratio_f_of_flow.setCoefficient1Constant(1.156)
2096
+ clg_energy_input_ratio_f_of_flow.setCoefficient2x(-0.1816)
2097
+ clg_energy_input_ratio_f_of_flow.setCoefficient3xPOW2(0.0256)
2098
+ clg_energy_input_ratio_f_of_flow.setMinimumValueofx(0.5)
2099
+ clg_energy_input_ratio_f_of_flow.setMaximumValueofx(1.5)
2100
+
2101
+ clg_part_load_ratio = OpenStudio::Model::CurveQuadratic.new(model)
2102
+ clg_part_load_ratio.setCoefficient1Constant(0.75)
2103
+ clg_part_load_ratio.setCoefficient2x(0.25)
2104
+ clg_part_load_ratio.setCoefficient3xPOW2(0.0)
2105
+ clg_part_load_ratio.setMinimumValueofx(0.0)
2106
+ clg_part_load_ratio.setMaximumValueofx(1.0)
2107
+
2108
+ clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model,
2109
+ always_on,
2110
+ clg_cap_f_of_temp,
2111
+ clg_cap_f_of_flow,
2112
+ clg_energy_input_ratio_f_of_temp,
2113
+ clg_energy_input_ratio_f_of_flow,
2114
+ clg_part_load_ratio)
2115
+ return clg_coil
2116
+ end
2117
+
2118
+ def self._add_coil_heating_dx_single_speed(model)
2119
+ htg_coil = nil
2120
+
2121
+ always_on = model.alwaysOnDiscreteSchedule
2122
+
2123
+ htg_cap_f_of_temp = OpenStudio::Model::CurveCubic.new(model)
2124
+ htg_cap_f_of_temp.setCoefficient1Constant(0.758746)
2125
+ htg_cap_f_of_temp.setCoefficient2x(0.027626)
2126
+ htg_cap_f_of_temp.setCoefficient3xPOW2(0.000148716)
2127
+ htg_cap_f_of_temp.setCoefficient4xPOW3(0.0000034992)
2128
+ htg_cap_f_of_temp.setMinimumValueofx(-20.0)
2129
+ htg_cap_f_of_temp.setMaximumValueofx(20.0)
2130
+
2131
+ htg_cap_f_of_flow = OpenStudio::Model::CurveCubic.new(model)
2132
+ htg_cap_f_of_flow.setCoefficient1Constant(0.84)
2133
+ htg_cap_f_of_flow.setCoefficient2x(0.16)
2134
+ htg_cap_f_of_flow.setCoefficient3xPOW2(0.0)
2135
+ htg_cap_f_of_flow.setCoefficient4xPOW3(0.0)
2136
+ htg_cap_f_of_flow.setMinimumValueofx(0.5)
2137
+ htg_cap_f_of_flow.setMaximumValueofx(1.5)
2138
+
2139
+ htg_energy_input_ratio_f_of_temp = OpenStudio::Model::CurveCubic.new(model)
2140
+ htg_energy_input_ratio_f_of_temp.setCoefficient1Constant(1.19248)
2141
+ htg_energy_input_ratio_f_of_temp.setCoefficient2x(-0.0300438)
2142
+ htg_energy_input_ratio_f_of_temp.setCoefficient3xPOW2(0.00103745)
2143
+ htg_energy_input_ratio_f_of_temp.setCoefficient4xPOW3(-0.000023328)
2144
+ htg_energy_input_ratio_f_of_temp.setMinimumValueofx(-20.0)
2145
+ htg_energy_input_ratio_f_of_temp.setMaximumValueofx(20.0)
2146
+
2147
+ htg_energy_input_ratio_f_of_flow = OpenStudio::Model::CurveQuadratic.new(model)
2148
+ htg_energy_input_ratio_f_of_flow.setCoefficient1Constant(1.3824)
2149
+ htg_energy_input_ratio_f_of_flow.setCoefficient2x(-0.4336)
2150
+ htg_energy_input_ratio_f_of_flow.setCoefficient3xPOW2(0.0512)
2151
+ htg_energy_input_ratio_f_of_flow.setMinimumValueofx(0.0)
2152
+ htg_energy_input_ratio_f_of_flow.setMaximumValueofx(1.0)
2153
+
2154
+ htg_part_load_fraction = OpenStudio::Model::CurveQuadratic.new(model)
2155
+ htg_part_load_fraction.setCoefficient1Constant(0.75)
2156
+ htg_part_load_fraction.setCoefficient2x(0.25)
2157
+ htg_part_load_fraction.setCoefficient3xPOW2(0.0)
2158
+ htg_part_load_fraction.setMinimumValueofx(0.0)
2159
+ htg_part_load_fraction.setMaximumValueofx(1.0)
2160
+
2161
+ htg_coil = OpenStudio::Model::CoilHeatingDXSingleSpeed.new(model,
2162
+ always_on,
2163
+ htg_cap_f_of_temp,
2164
+ htg_cap_f_of_flow,
2165
+ htg_energy_input_ratio_f_of_temp,
2166
+ htg_energy_input_ratio_f_of_flow,
2167
+ htg_part_load_fraction)
2168
+
2169
+ return htg_coil
2170
+ end
2171
+ end