openstudio-standards 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/data/geometry/ASHRAE90120042007LargeHotel.osm +55 -55
- data/data/geometry/ASHRAE9012010LargeHotel.osm +56 -56
- data/data/geometry/ASHRAE9012010SuperMarket.osm +153 -153
- data/data/geometry/ASHRAE9012013Hospital.osm +815 -874
- data/data/geometry/ASHRAE9012013LargeHotel.osm +56 -56
- data/data/geometry/ASHRAE9012013LargeOffice.osm +12 -3
- data/data/geometry/ASHRAE9012013MediumOffice.osm +8 -16
- data/data/geometry/ASHRAE9012013MidriseApartment.osm +792 -792
- data/data/geometry/ASHRAE9012013SuperMarket.osm +152 -152
- data/data/geometry/ASHRAEHospital.osm +815 -874
- data/data/geometry/ASHRAELargeOffice.osm +58 -49
- data/data/geometry/ASHRAEMediumOffice.osm +12 -3
- data/data/geometry/ASHRAEMidriseApartment.osm +792 -792
- data/data/geometry/ASHRAESmallOffice.osm +4 -4
- data/data/geometry/ASHRAESuperMarket.osm +152 -152
- data/data/geometry/DOERefLargeOffice.osm +38 -29
- data/data/geometry/DOERefMidriseApartment.osm +792 -792
- data/data/geometry/DOERefPre1980SmallOffice.osm +4 -4
- data/data/geometry/DOERefSmallHotel.osm +4 -4
- data/data/geometry/DOERefWarehouse.osm +80 -30
- data/data/standards/OpenStudio_Standards.xlsx +0 -0
- data/data/standards/OpenStudio_Standards_construction_sets.json +582 -238
- data/data/standards/OpenStudio_Standards_constructions.json +14 -14
- data/data/standards/OpenStudio_Standards_hvac_inference.json +741 -0
- data/data/standards/OpenStudio_Standards_prototype_inputs.json +12 -12
- data/data/standards/OpenStudio_Standards_schedules.json +1479 -622
- data/data/standards/OpenStudio_Standards_size_category.json +67 -0
- data/data/standards/OpenStudio_Standards_space_types.json +2640 -2032
- data/lib/openstudio-standards.rb +1 -0
- data/lib/openstudio-standards/btap/btap.rb +0 -1
- data/lib/openstudio-standards/btap/simmanager.rb +3 -10
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeOffice.rb +24 -0
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MediumOffice.rb +29 -4
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.elevators.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.hvac.rb +68 -3
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.SizingSystem.rb +36 -0
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +743 -730
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.utilities.rb +7 -2
- data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.Model.rb +95 -170
- data/lib/openstudio-standards/standards/Standards.Space.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirLoopHVAC.rb +34 -1
- data/lib/openstudio-standards/standards/standard.rb +2 -0
- data/lib/openstudio-standards/version.rb +1 -1
- metadata +5 -2
data/lib/openstudio-standards.rb
CHANGED
@@ -253,6 +253,7 @@ module OpenstudioStandards
|
|
253
253
|
require_relative "#{proto}/common/objects/Prototype.Model.swh"
|
254
254
|
require_relative "#{proto}/common/objects/Prototype.refrigeration"
|
255
255
|
require_relative "#{proto}/common/objects/Prototype.ServiceWaterHeating"
|
256
|
+
require_relative "#{proto}/common/objects/Prototype.SizingSystem"
|
256
257
|
require_relative "#{proto}/common/objects/Prototype.utilities"
|
257
258
|
# 90.1-2004
|
258
259
|
require_relative "#{proto}/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirTerminalSingleDuctVAVReheat"
|
@@ -101,12 +101,10 @@ module BTAP
|
|
101
101
|
|
102
102
|
|
103
103
|
def getPaths
|
104
|
-
# Find EnergyPlus on this computer.
|
105
|
-
@ep_hash = OpenStudio::EnergyPlus::find_energyplus(BTAP::ENERGY_PLUS_MAJOR_VERSION,BTAP::ENERGY_PLUS_MINOR_VERSION)
|
106
104
|
#set the Energyplus.exe path variable
|
107
|
-
@ep_path = OpenStudio
|
105
|
+
@ep_path = OpenStudio.getEnergyPlusExecutable
|
108
106
|
#set the root folder for E+
|
109
|
-
@ep_parent_path =
|
107
|
+
@ep_parent_path = OpenStudio.getEnergyPlusDirectory
|
110
108
|
|
111
109
|
#find IDD path
|
112
110
|
idd_path = @ep_parent_path.to_s + "/Energy+.idd"
|
@@ -146,12 +144,7 @@ module BTAP
|
|
146
144
|
#@author Phylroy A. Lopez
|
147
145
|
#@return [String] a simple string of the epw file path, remember to escape the slashes..(i.e. // not / )
|
148
146
|
def self.find_energyplus_folder()
|
149
|
-
|
150
|
-
ep_hash = OpenStudio::EnergyPlus::find_energyplus(BTAP::ENERGY_PLUS_MAJOR_VERSION,BTAP::ENERGY_PLUS_MINOR_VERSION)
|
151
|
-
#set the Energyplus.exe path variable
|
152
|
-
ep_path = OpenStudio::Path.new( ep_hash[:energyplus_exe].to_s)
|
153
|
-
#set the root folder for E+
|
154
|
-
return ep_path.parent_path();
|
147
|
+
return OpenStudio.getEnergyPlusDirectory.to_s
|
155
148
|
end
|
156
149
|
|
157
150
|
#This method finds the eReadVarsESO.exe and returns the path string.
|
@@ -75,6 +75,30 @@ module LargeOffice
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
# set infiltration schedule for plenums
|
79
|
+
# @todo remove once infil_sch in Standards.Space pulls from default building infiltration schedule
|
80
|
+
model.getSpaces.each do |space|
|
81
|
+
next unless space.name.get.to_s.include? 'Plenum'
|
82
|
+
# add infiltration if DOE Ref vintage
|
83
|
+
if template == 'DOE Ref 1980-2004' || template == 'DOE Ref Pre-1980'
|
84
|
+
# Create an infiltration rate object for this space
|
85
|
+
infiltration = OpenStudio::Model::SpaceInfiltrationDesignFlowRate.new(space.model)
|
86
|
+
infiltration.setName("#{space.name} Infiltration")
|
87
|
+
all_ext_infil_m3_per_s_per_m2 = OpenStudio.convert(0.2232, 'ft^3/min*ft^2', 'm^3/s*m^2').get
|
88
|
+
infiltration.setFlowperExteriorSurfaceArea(all_ext_infil_m3_per_s_per_m2)
|
89
|
+
infiltration.setSchedule(model_add_schedule(model, 'Large Office Infil Quarter On'))
|
90
|
+
infiltration.setConstantTermCoefficient(1.0)
|
91
|
+
infiltration.setTemperatureTermCoefficient(0.0)
|
92
|
+
infiltration.setVelocityTermCoefficient(0.0)
|
93
|
+
infiltration.setVelocitySquaredTermCoefficient(0.0)
|
94
|
+
infiltration.setSpace(space)
|
95
|
+
else
|
96
|
+
space.spaceInfiltrationDesignFlowRates.each do |infiltration_object|
|
97
|
+
infiltration_object.setSchedule(model_add_schedule(model, 'OfficeLarge INFIL_SCH_PNNL'))
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
78
102
|
return true
|
79
103
|
end
|
80
104
|
|
@@ -25,6 +25,30 @@ module MediumOffice
|
|
25
25
|
add_door_infiltration(climate_zone, model)
|
26
26
|
OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Added door infiltration')
|
27
27
|
|
28
|
+
# set infiltration schedule for plenums
|
29
|
+
# @todo remove once infil_sch in Standards.Space pulls from default building infiltration schedule
|
30
|
+
model.getSpaces.each do |space|
|
31
|
+
next unless space.name.get.to_s.include? 'Plenum'
|
32
|
+
# add infiltration if DOE Ref vintage
|
33
|
+
if template == 'DOE Ref 1980-2004' || template == 'DOE Ref Pre-1980'
|
34
|
+
# Create an infiltration rate object for this space
|
35
|
+
infiltration = OpenStudio::Model::SpaceInfiltrationDesignFlowRate.new(space.model)
|
36
|
+
infiltration.setName("#{space.name} Infiltration")
|
37
|
+
all_ext_infil_m3_per_s_per_m2 = OpenStudio.convert(0.2232, 'ft^3/min*ft^2', 'm^3/s*m^2').get
|
38
|
+
infiltration.setFlowperExteriorSurfaceArea(all_ext_infil_m3_per_s_per_m2)
|
39
|
+
infiltration.setSchedule(model_add_schedule(model, 'Medium Office Infil Quarter On'))
|
40
|
+
infiltration.setConstantTermCoefficient(1.0)
|
41
|
+
infiltration.setTemperatureTermCoefficient(0.0)
|
42
|
+
infiltration.setVelocityTermCoefficient(0.0)
|
43
|
+
infiltration.setVelocitySquaredTermCoefficient(0.0)
|
44
|
+
infiltration.setSpace(space)
|
45
|
+
else
|
46
|
+
space.spaceInfiltrationDesignFlowRates.each do |infiltration_object|
|
47
|
+
infiltration_object.setSchedule(model_add_schedule(model, 'OfficeMedium INFIL_SCH_PNNL'))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
28
52
|
return true
|
29
53
|
end
|
30
54
|
|
@@ -59,10 +83,11 @@ module MediumOffice
|
|
59
83
|
OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Adjusting daylight sensor positions and fractions')
|
60
84
|
|
61
85
|
adjustments = [
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
86
|
+
{
|
87
|
+
'stds_spc_type' => 'WholeBuilding - Md Office',
|
88
|
+
'sensor_1_frac' => 0.3835,
|
89
|
+
'sensor_2_frac' => 0.1395
|
90
|
+
}
|
66
91
|
]
|
67
92
|
|
68
93
|
# Adjust daylight sensors in each space
|
@@ -304,7 +304,7 @@ class Standard
|
|
304
304
|
'building_type' => building_type
|
305
305
|
}
|
306
306
|
|
307
|
-
prototype_input = model_find_object(standards_data['prototype_inputs'], search_criteria
|
307
|
+
prototype_input = model_find_object(standards_data['prototype_inputs'], search_criteria)
|
308
308
|
if prototype_input.nil?
|
309
309
|
OpenStudio.logFree(OpenStudio::Error, 'openstudio.prototype.elevators', "Could not find prototype inputs for #{search_criteria}, cannot add elevators.")
|
310
310
|
return nil
|
@@ -263,9 +263,9 @@ class Standard
|
|
263
263
|
fan_type: system['fan_type'])
|
264
264
|
|
265
265
|
when 'PTHP'
|
266
|
-
|
267
|
-
|
268
|
-
|
266
|
+
model_add_pthp(model,
|
267
|
+
thermal_zones,
|
268
|
+
fan_type: system['fan_type'])
|
269
269
|
|
270
270
|
when 'Exhaust Fan'
|
271
271
|
model_add_exhaust_fan(model,
|
@@ -365,6 +365,71 @@ class Standard
|
|
365
365
|
return true
|
366
366
|
end # add hvac
|
367
367
|
|
368
|
+
# Determine the typical system type given the inputs.
|
369
|
+
#
|
370
|
+
# @param area_type [String] Valid choices are residential and nonresidential
|
371
|
+
# @param delivery_type [String] Conditioning delivery type. Valid choices are air and hydronic
|
372
|
+
# @param heating_source [String] Valid choices are Electricity, NaturalGas, DistrictHeating, DistrictAmbient
|
373
|
+
# @param cooling_source [String] Valid choices are Electricity, DistrictCooling, DistrictAmbient
|
374
|
+
# @param area_m2 [Double] Area in m^2
|
375
|
+
# @param num_stories [Integer] Number of stories
|
376
|
+
# @return [Array] An array containing the system type, central heating fuel, zone heating fuel, and cooling fuel
|
377
|
+
def model_typical_hvac_system_type(model,
|
378
|
+
climate_zone,
|
379
|
+
area_type,
|
380
|
+
delivery_type,
|
381
|
+
heating_source,
|
382
|
+
cooling_source,
|
383
|
+
area_m2,
|
384
|
+
num_stories)
|
385
|
+
|
386
|
+
# Convert area to ft^2
|
387
|
+
area_ft2 = OpenStudio.convert(area_m2, 'm^2', 'ft^2').get
|
388
|
+
|
389
|
+
case area_type
|
390
|
+
when 'residential'
|
391
|
+
area_type = 'Residential'
|
392
|
+
when 'nonresidential', 'retail', 'publicassembly', 'heatedonly'
|
393
|
+
area_type = 'Nonresidential'
|
394
|
+
else
|
395
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.Model.Model', "area_type '#{area_type}' invalid or missing.")
|
396
|
+
return nil
|
397
|
+
end
|
398
|
+
|
399
|
+
# lookup size category
|
400
|
+
search_criteria = {}
|
401
|
+
search_criteria['template'] = template
|
402
|
+
search_criteria['building_category'] = area_type
|
403
|
+
size_data = model_find_object(standards_data['size_category'], search_criteria, nil, nil, area_ft2, num_stories)
|
404
|
+
if size_data.nil?
|
405
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.Model.Model', "Unable to find size category for #{search_criteria}.")
|
406
|
+
return nil
|
407
|
+
end
|
408
|
+
|
409
|
+
# lookup infered HVAC system type
|
410
|
+
search_criteria = {}
|
411
|
+
search_criteria['template'] = template
|
412
|
+
search_criteria['size_category'] = size_data['size_category']
|
413
|
+
search_criteria['heating_source'] = heating_source
|
414
|
+
search_criteria['cooling_source'] = cooling_source
|
415
|
+
search_criteria['delivery_type'] = delivery_type
|
416
|
+
hvac_data = model_find_object(standards_data['hvac_inference'], search_criteria)
|
417
|
+
|
418
|
+
# return system type inputs with format [type, central_heating_fuel, zone_heating_fuel, cooling_fuel]
|
419
|
+
if hvac_data.nil? || hvac_data.empty?
|
420
|
+
system_type_inputs = [nil, nil, nil, nil]
|
421
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Could not determine system type for #{area_type} building of size #{area_ft2.round} ft^2 and #{num_stories} stories, and lookups #{search_criteria}.")
|
422
|
+
else
|
423
|
+
system_type_inputs = [hvac_data['hvac_system_type'], hvac_data['central_heating_fuel'], hvac_data['zone_heating_fuel'], hvac_data['cooling_fuel']]
|
424
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "System type is #{system_type_inputs[0]} for #{area_type} building of size #{area_ft2.round} ft^2 and #{num_stories} stories, and lookups #{search_criteria}.")
|
425
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "--- #{system_type_inputs[1]} for main heating") unless system_type_inputs[1].nil?
|
426
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "--- #{system_type_inputs[2]} for zone heat/reheat") unless system_type_inputs[2].nil?
|
427
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "--- #{system_type_inputs[3]} for cooling") unless system_type_inputs[3].nil?
|
428
|
+
end
|
429
|
+
|
430
|
+
return system_type_inputs
|
431
|
+
end
|
432
|
+
|
368
433
|
private
|
369
434
|
|
370
435
|
def model_get_zones_from_spaces_on_system(model, system)
|
@@ -435,7 +435,7 @@ Standard.class_eval do
|
|
435
435
|
adj_space = adj_surface.space.get
|
436
436
|
if adj_space.spaceType.is_initialized && adj_space.spaceType.get.standardsSpaceType.is_initialized
|
437
437
|
adj_std_space_type = adj_space.spaceType.get.standardsSpaceType.get
|
438
|
-
if adj_std_space_type == '
|
438
|
+
if adj_std_space_type.downcase == 'plenum'
|
439
439
|
plenum_construction = adj_surface.construction
|
440
440
|
if plenum_construction.is_initialized
|
441
441
|
plenum_construction = plenum_construction.get
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Standard
|
2
|
+
# @!group Sizing System
|
3
|
+
|
4
|
+
# Prototype SizingSystem object
|
5
|
+
#
|
6
|
+
# @param air_loop_hvac [<OpenStudio::Model::AirLoopHVAC>] air loop to set sizing system properties
|
7
|
+
# @param dsgn_temps [Hash] a hash of design temperature lookups from standard_design_sizing_temperatures
|
8
|
+
def adjust_sizing_system(air_loop_hvac,
|
9
|
+
dsgn_temps,
|
10
|
+
type_of_load_sizing: 'Sensible',
|
11
|
+
min_sys_airflow_ratio: 0.3,
|
12
|
+
sizing_option: 'Coincident')
|
13
|
+
|
14
|
+
# adjust sizing system defaults
|
15
|
+
sizing_system = air_loop_hvac.sizingSystem
|
16
|
+
sizing_system.setTypeofLoadtoSizeOn(type_of_load_sizing)
|
17
|
+
sizing_system.autosizeDesignOutdoorAirFlowRate
|
18
|
+
sizing_system.setPreheatDesignTemperature(dsgn_temps['prehtg_dsgn_sup_air_temp_c'])
|
19
|
+
sizing_system.setPrecoolDesignTemperature(dsgn_temps['preclg_dsgn_sup_air_temp_c'])
|
20
|
+
sizing_system.setCentralCoolingDesignSupplyAirTemperature(dsgn_temps['clg_dsgn_sup_air_temp_c'])
|
21
|
+
sizing_system.setCentralHeatingDesignSupplyAirTemperature(dsgn_temps['htg_dsgn_sup_air_temp_c'])
|
22
|
+
sizing_system.setPreheatDesignHumidityRatio(0.008)
|
23
|
+
sizing_system.setPrecoolDesignHumidityRatio(0.008)
|
24
|
+
sizing_system.setCentralCoolingDesignSupplyAirHumidityRatio(0.0085)
|
25
|
+
sizing_system.setCentralHeatingDesignSupplyAirHumidityRatio(0.0080)
|
26
|
+
sizing_system.setMinimumSystemAirFlowRatio(min_sys_airflow_ratio)
|
27
|
+
sizing_system.setSizingOption(sizing_option)
|
28
|
+
sizing_system.setAllOutdoorAirinCooling(false)
|
29
|
+
sizing_system.setAllOutdoorAirinHeating(false)
|
30
|
+
sizing_system.setSystemOutdoorAirMethod('ZoneSum')
|
31
|
+
sizing_system.setCoolingDesignAirFlowMethod('DesignDay')
|
32
|
+
sizing_system.setHeatingDesignAirFlowMethod('DesignDay')
|
33
|
+
|
34
|
+
return sizing_system
|
35
|
+
end
|
36
|
+
end
|
@@ -1,6 +1,26 @@
|
|
1
1
|
class Standard
|
2
2
|
# @!group hvac_systems
|
3
3
|
|
4
|
+
# Returns standard design sizing temperatures
|
5
|
+
|
6
|
+
# @return [Hash] Hash of design sizing temperature lookups
|
7
|
+
def standard_design_sizing_temperatures
|
8
|
+
dsgn_temps = {}
|
9
|
+
dsgn_temps['prehtg_dsgn_sup_air_temp_f'] = 45.0
|
10
|
+
dsgn_temps['preclg_dsgn_sup_air_temp_f'] = 55.0
|
11
|
+
dsgn_temps['htg_dsgn_sup_air_temp_f'] = 55.0
|
12
|
+
dsgn_temps['clg_dsgn_sup_air_temp_f'] = 55.0
|
13
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_f'] = 104.0
|
14
|
+
dsgn_temps['zn_clg_dsgn_sup_air_temp_f'] = 55.0
|
15
|
+
dsgn_temps['prehtg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['prehtg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
16
|
+
dsgn_temps['preclg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['preclg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
17
|
+
dsgn_temps['htg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['htg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
18
|
+
dsgn_temps['clg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['clg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
19
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['zn_htg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
20
|
+
dsgn_temps['zn_clg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['zn_clg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
21
|
+
return dsgn_temps
|
22
|
+
end
|
23
|
+
|
4
24
|
# Creates a hot water loop with a boiler, district heating, or a
|
5
25
|
# water-to-water heat pump and adds it to the model.
|
6
26
|
#
|
@@ -113,7 +133,7 @@ class Standard
|
|
113
133
|
end
|
114
134
|
|
115
135
|
if boiler_out_temp_lmt.nil?
|
116
|
-
out_temp_lmt = OpenStudio.convert(203, 'F', 'C').get
|
136
|
+
out_temp_lmt = OpenStudio.convert(203.0, 'F', 'C').get
|
117
137
|
else
|
118
138
|
out_temp_lmt = boiler_out_temp_lmt
|
119
139
|
end
|
@@ -130,7 +150,7 @@ class Standard
|
|
130
150
|
sizing_factor: boiler_sizing_factor)
|
131
151
|
|
132
152
|
# TODO: Yixing. Adding temperature setpoint controller at boiler outlet causes simulation errors
|
133
|
-
# boiler_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self,hw_temp_sch)
|
153
|
+
# boiler_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self, hw_temp_sch)
|
134
154
|
# boiler_stpt_manager.setName("Boiler outlet setpoint manager")
|
135
155
|
# boiler_stpt_manager.addToNode(boiler.outletModelObject.get.to_Node.get)
|
136
156
|
else
|
@@ -688,12 +708,15 @@ class Standard
|
|
688
708
|
loop_stpt_manager.addToNode(ground_hx_loop.supplyOutletNode)
|
689
709
|
|
690
710
|
# sensor to read supply inlet temperature
|
691
|
-
inlet_temp_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model,
|
711
|
+
inlet_temp_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model,
|
712
|
+
'System Node Temperature')
|
692
713
|
inlet_temp_sensor.setName("#{ground_hx.name.to_s.gsub(/[ +-.]/,'_')} Inlet Temp Sensor")
|
693
714
|
inlet_temp_sensor.setKeyName(ground_hx_loop.supplyInletNode.handle.to_s)
|
694
715
|
|
695
716
|
# actuator to set supply outlet temperature
|
696
|
-
outlet_temp_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(hx_temp_sch,
|
717
|
+
outlet_temp_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(hx_temp_sch,
|
718
|
+
'Schedule:Constant',
|
719
|
+
'Schedule Value')
|
697
720
|
outlet_temp_actuator.setName("#{ground_hx.name} Outlet Temp Actuator")
|
698
721
|
|
699
722
|
# program to control outlet temperature
|
@@ -747,17 +770,16 @@ class Standard
|
|
747
770
|
amb_temp_sizing_c = OpenStudio.convert(amb_temp_sizing_f, 'F', 'C').get
|
748
771
|
amb_delta_t_k = OpenStudio.convert(amb_delta_t_r, 'R', 'K').get
|
749
772
|
|
750
|
-
amb_high_temp_sch =
|
751
|
-
|
752
|
-
|
753
|
-
amb_high_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), amb_high_temp_c)
|
773
|
+
amb_high_temp_sch = model_add_constant_schedule_ruleset(model,
|
774
|
+
amb_high_temp_c,
|
775
|
+
name = "Ambient Loop High Temp - #{amb_high_temp_f}F")
|
754
776
|
|
755
|
-
amb_low_temp_sch =
|
756
|
-
|
757
|
-
|
758
|
-
amb_low_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), amb_low_temp_c)
|
777
|
+
amb_low_temp_sch = model_add_constant_schedule_ruleset(model,
|
778
|
+
amb_low_temp_c,
|
779
|
+
name = "Ambient Loop Low Temp - #{amb_low_temp_f}F")
|
759
780
|
|
760
781
|
amb_stpt_manager = OpenStudio::Model::SetpointManagerScheduledDualSetpoint.new(model)
|
782
|
+
amb_stpt_manager.setName("#{ambient_loop.name} Supply Water Setpoint Manager")
|
761
783
|
amb_stpt_manager.setHighSetpointSchedule(amb_high_temp_sch)
|
762
784
|
amb_stpt_manager.setLowSetpointSchedule(amb_low_temp_sch)
|
763
785
|
amb_stpt_manager.addToNode(ambient_loop.supplyOutletNode)
|
@@ -894,7 +916,10 @@ class Standard
|
|
894
916
|
sizing_system.setCentralHeatingDesignSupplyAirTemperature(htg_dsgn_sup_air_temp_c)
|
895
917
|
|
896
918
|
# create supply fan
|
897
|
-
supply_fan = create_fan_by_name(model,
|
919
|
+
supply_fan = create_fan_by_name(model,
|
920
|
+
'Constant_DOAS_Fan',
|
921
|
+
fan_name: 'DOAS Supply Fan',
|
922
|
+
end_use_subcategory: 'DOAS Fans')
|
898
923
|
supply_fan.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
899
924
|
supply_fan.setMaximumFlowRate(OpenStudio.convert(fan_maximum_flow_rate, 'cfm', 'm^3/s').get) unless fan_maximum_flow_rate.nil?
|
900
925
|
supply_fan.addToNode(air_loop.supplyInletNode)
|
@@ -1019,11 +1044,11 @@ class Standard
|
|
1019
1044
|
air_loop.addBranchForZone(zone, air_terminal.to_StraightComponent)
|
1020
1045
|
|
1021
1046
|
# DOAS sizing
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1047
|
+
sizing_zone = zone.sizingZone
|
1048
|
+
sizing_zone.setAccountforDedicatedOutdoorAirSystem(true)
|
1049
|
+
sizing_zone.setDedicatedOutdoorAirSystemControlStrategy('ColdSupplyAir')
|
1050
|
+
sizing_zone.setDedicatedOutdoorAirLowSetpointTemperatureforDesign(clg_dsgn_sup_air_temp_c)
|
1051
|
+
sizing_zone.setDedicatedOutdoorAirHighSetpointTemperatureforDesign(htg_dsgn_sup_air_temp_c)
|
1027
1052
|
end
|
1028
1053
|
|
1029
1054
|
return air_loop
|
@@ -1120,9 +1145,15 @@ class Standard
|
|
1120
1145
|
sizing_system.setCentralHeatingDesignSupplyAirTemperature(htg_dsgn_sup_air_temp_c)
|
1121
1146
|
|
1122
1147
|
if doas_type == 'DOASCV'
|
1123
|
-
supply_fan = create_fan_by_name(model,
|
1148
|
+
supply_fan = create_fan_by_name(model,
|
1149
|
+
'Constant_DOAS_Fan',
|
1150
|
+
fan_name: 'DOAS Supply Fan',
|
1151
|
+
end_use_subcategory: 'DOAS Fans')
|
1124
1152
|
else # 'DOASVAV'
|
1125
|
-
supply_fan = create_fan_by_name(model,
|
1153
|
+
supply_fan = create_fan_by_name(model,
|
1154
|
+
'Variable_DOAS_Fan',
|
1155
|
+
fan_name: 'DOAS Supply Fan',
|
1156
|
+
end_use_subcategory: 'DOAS Fans')
|
1126
1157
|
end
|
1127
1158
|
supply_fan.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
1128
1159
|
supply_fan.setMaximumFlowRate(OpenStudio.convert(fan_maximum_flow_rate, 'cfm', 'm^3/s').get) unless fan_maximum_flow_rate.nil?
|
@@ -1209,9 +1240,15 @@ class Standard
|
|
1209
1240
|
# create an exhaust fan
|
1210
1241
|
if include_exhaust_fan
|
1211
1242
|
if doas_type == 'DOASCV'
|
1212
|
-
exhaust_fan = create_fan_by_name(model,
|
1243
|
+
exhaust_fan = create_fan_by_name(model,
|
1244
|
+
'Constant_DOAS_Fan',
|
1245
|
+
fan_name: 'DOAS Exhaust Fan',
|
1246
|
+
end_use_subcategory: 'DOAS Fans')
|
1213
1247
|
else # 'DOASVAV'
|
1214
|
-
exhaust_fan = create_fan_by_name(model,
|
1248
|
+
exhaust_fan = create_fan_by_name(model,
|
1249
|
+
'Variable_DOAS_Fan',
|
1250
|
+
fan_name: 'DOAS Exhaust Fan',
|
1251
|
+
end_use_subcategory: 'DOAS Fans')
|
1215
1252
|
end
|
1216
1253
|
# set pressure rise 0.5 inH2O lower than supply fan, 0.5 inH2O minimum
|
1217
1254
|
exhaust_fan_pressure_rise = supply_fan.pressureRise - OpenStudio.convert(0.5, 'inH_{2}O', 'Pa').get
|
@@ -1293,11 +1330,11 @@ class Standard
|
|
1293
1330
|
air_loop.addBranchForZone(zone, air_terminal.to_StraightComponent)
|
1294
1331
|
|
1295
1332
|
# DOAS sizing
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1333
|
+
sizing_zone = zone.sizingZone
|
1334
|
+
sizing_zone.setAccountforDedicatedOutdoorAirSystem(true)
|
1335
|
+
sizing_zone.setDedicatedOutdoorAirSystemControlStrategy(doas_control_strategy)
|
1336
|
+
sizing_zone.setDedicatedOutdoorAirLowSetpointTemperatureforDesign(clg_dsgn_sup_air_temp_c)
|
1337
|
+
sizing_zone.setDedicatedOutdoorAirHighSetpointTemperatureforDesign(htg_dsgn_sup_air_temp_c)
|
1301
1338
|
end
|
1302
1339
|
|
1303
1340
|
return air_loop
|
@@ -1337,12 +1374,20 @@ class Standard
|
|
1337
1374
|
econo_ctrl_mthd: nil)
|
1338
1375
|
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding VAV system for #{thermal_zones.size} zones.")
|
1339
1376
|
|
1377
|
+
# create air handler
|
1378
|
+
air_loop = OpenStudio::Model::AirLoopHVAC.new(model)
|
1379
|
+
if system_name.nil?
|
1380
|
+
air_loop.setName("#{thermal_zones.size} Zone VAV")
|
1381
|
+
else
|
1382
|
+
air_loop.setName(system_name)
|
1383
|
+
end
|
1384
|
+
|
1340
1385
|
# hvac operation schedule
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1386
|
+
if hvac_op_sch.nil?
|
1387
|
+
hvac_op_sch = model.alwaysOnDiscreteSchedule
|
1388
|
+
else
|
1389
|
+
hvac_op_sch = model_add_schedule(model, hvac_op_sch)
|
1390
|
+
end
|
1346
1391
|
|
1347
1392
|
# oa damper schedule
|
1348
1393
|
if oa_damper_sch.nil?
|
@@ -1351,63 +1396,28 @@ class Standard
|
|
1351
1396
|
oa_damper_sch = model_add_schedule(model, oa_damper_sch)
|
1352
1397
|
end
|
1353
1398
|
|
1354
|
-
#
|
1399
|
+
# default design temperatures and settings used across all air loops
|
1400
|
+
dsgn_temps = standard_design_sizing_temperatures
|
1401
|
+
sizing_system = adjust_sizing_system(air_loop, dsgn_temps)
|
1402
|
+
sizing_system.setMinimumSystemAirFlowRatio(min_sys_airflow_ratio) unless min_sys_airflow_ratio.nil?
|
1403
|
+
sizing_system.setSizingOption(vav_sizing_option) unless vav_sizing_option.nil?
|
1355
1404
|
unless hot_water_loop.nil?
|
1356
1405
|
hw_temp_c = hot_water_loop.sizingPlant.designLoopExitTemperature
|
1357
1406
|
hw_delta_t_k = hot_water_loop.sizingPlant.loopDesignTemperatureDifference
|
1358
1407
|
end
|
1359
|
-
clg_sa_temp_f = 55.04
|
1360
|
-
prehtg_sa_temp_f = 44.6
|
1361
|
-
preclg_sa_temp_f = 55.04
|
1362
|
-
htg_sa_temp_f = 55.04
|
1363
|
-
zone_htg_sa_temp_f = 104.0
|
1364
|
-
rht_sa_temp_f = 104.0
|
1365
|
-
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f, 'F', 'C').get
|
1366
|
-
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f, 'F', 'C').get
|
1367
|
-
preclg_sa_temp_c = OpenStudio.convert(preclg_sa_temp_f, 'F', 'C').get
|
1368
|
-
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f, 'F', 'C').get
|
1369
|
-
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f, 'F', 'C').get
|
1370
|
-
zone_htg_sa_temp_c = OpenStudio.convert(zone_htg_sa_temp_f, 'F', 'C').get
|
1371
|
-
sa_temp_sch = OpenStudio::Model::ScheduleRuleset.new(model)
|
1372
|
-
sa_temp_sch.setName("Supply Air Temp - #{clg_sa_temp_f}F")
|
1373
|
-
sa_temp_sch.defaultDaySchedule.setName("Supply Air Temp - #{clg_sa_temp_f}F Default")
|
1374
|
-
sa_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), clg_sa_temp_c)
|
1375
|
-
|
1376
|
-
# create air handler
|
1377
|
-
air_loop = OpenStudio::Model::AirLoopHVAC.new(model)
|
1378
|
-
if system_name.nil?
|
1379
|
-
air_loop.setName("#{thermal_zones.size} Zone VAV")
|
1380
|
-
else
|
1381
|
-
air_loop.setName(system_name)
|
1382
|
-
end
|
1383
1408
|
|
1409
|
+
# air handler controls
|
1410
|
+
sa_temp_sch = model_add_constant_schedule_ruleset(model,
|
1411
|
+
dsgn_temps['clg_dsgn_sup_air_temp_c'],
|
1412
|
+
name = "Supply Air Temp - #{dsgn_temps['clg_dsgn_sup_air_temp_f']}F")
|
1384
1413
|
sa_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, sa_temp_sch)
|
1385
|
-
sa_stpt_manager.setName("#{
|
1414
|
+
sa_stpt_manager.setName("#{air_loop.name} Supply Air Setpoint Manager")
|
1386
1415
|
sa_stpt_manager.addToNode(air_loop.supplyOutletNode)
|
1387
1416
|
|
1388
|
-
# air handler controls
|
1389
|
-
sizing_system = air_loop.sizingSystem
|
1390
|
-
if min_sys_airflow_ratio.nil?
|
1391
|
-
sizing_system.setMinimumSystemAirFlowRatio(0.3)
|
1392
|
-
else
|
1393
|
-
sizing_system.setMinimumSystemAirFlowRatio(min_sys_airflow_ratio)
|
1394
|
-
end
|
1395
|
-
# sizing_system.setPreheatDesignTemperature(htg_oa_tdb_c)
|
1396
|
-
sizing_system.setPrecoolDesignTemperature(preclg_sa_temp_c)
|
1397
|
-
sizing_system.setCentralCoolingDesignSupplyAirTemperature(clg_sa_temp_c)
|
1398
|
-
sizing_system.setCentralHeatingDesignSupplyAirTemperature(htg_sa_temp_c)
|
1399
|
-
if vav_sizing_option.nil?
|
1400
|
-
sizing_system.setSizingOption('Coincident')
|
1401
|
-
else
|
1402
|
-
sizing_system.setSizingOption(vav_sizing_option) unless vav_sizing_option.nil?
|
1403
|
-
end
|
1404
|
-
sizing_system.setAllOutdoorAirinCooling(false)
|
1405
|
-
sizing_system.setAllOutdoorAirinHeating(false)
|
1406
|
-
sizing_system.setSystemOutdoorAirMethod('ZoneSum')
|
1407
|
-
|
1408
1417
|
# create fan
|
1409
1418
|
# @type [OpenStudio::Model::FanVariableVolume] fan
|
1410
|
-
fan = create_fan_by_name(model,
|
1419
|
+
fan = create_fan_by_name(model,
|
1420
|
+
'VAV_System_Fan',
|
1411
1421
|
fan_name: "#{air_loop.name} Fan",
|
1412
1422
|
fan_efficiency: fan_efficiency,
|
1413
1423
|
pressure_rise: fan_pressure_rise,
|
@@ -1428,8 +1438,8 @@ class Standard
|
|
1428
1438
|
name: "#{air_loop.name} Main Htg Coil",
|
1429
1439
|
rated_inlet_water_temperature: hw_temp_c,
|
1430
1440
|
rated_outlet_water_temperature: (hw_temp_c - hw_delta_t_k),
|
1431
|
-
rated_inlet_air_temperature:
|
1432
|
-
rated_outlet_air_temperature:
|
1441
|
+
rated_inlet_air_temperature: dsgn_temps['prehtg_dsgn_sup_air_temp_c'],
|
1442
|
+
rated_outlet_air_temperature: dsgn_temps['htg_dsgn_sup_air_temp_c'])
|
1433
1443
|
end
|
1434
1444
|
|
1435
1445
|
# create cooling coil
|
@@ -1478,41 +1488,57 @@ class Standard
|
|
1478
1488
|
|
1479
1489
|
# create reheat coil
|
1480
1490
|
case reheat_type
|
1481
|
-
when 'NaturalGas'
|
1482
|
-
rht_coil = create_coil_heating_gas(model,
|
1491
|
+
when 'NaturalGas', 'Gas'
|
1492
|
+
rht_coil = create_coil_heating_gas(model,
|
1493
|
+
name: "#{zone.name} Gas Reheat Coil")
|
1483
1494
|
when 'Electricity'
|
1484
|
-
rht_coil = create_coil_heating_electric(model,
|
1495
|
+
rht_coil = create_coil_heating_electric(model,
|
1496
|
+
name: "#{zone.name} Electric Reheat Coil")
|
1485
1497
|
when 'Water'
|
1486
1498
|
rht_coil = create_coil_heating_water(model,
|
1487
1499
|
hot_water_loop,
|
1488
1500
|
name: "#{zone.name} Reheat Coil",
|
1489
1501
|
rated_inlet_water_temperature: hw_temp_c,
|
1490
1502
|
rated_outlet_water_temperature: (hw_temp_c - hw_delta_t_k),
|
1491
|
-
rated_inlet_air_temperature:
|
1492
|
-
rated_outlet_air_temperature:
|
1503
|
+
rated_inlet_air_temperature: dsgn_temps['htg_dsgn_sup_air_temp_c'],
|
1504
|
+
rated_outlet_air_temperature: dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
1493
1505
|
else
|
1494
|
-
#
|
1495
|
-
|
1496
|
-
name: "#{zone.name} No Reheat",
|
1497
|
-
schedule: model.alwaysOffDiscreteSchedule,
|
1498
|
-
nominal_capacity: 0.0)
|
1506
|
+
# no reheat
|
1507
|
+
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.Model.Model', "No reheat coil for terminal in #{zone.name}")
|
1499
1508
|
end
|
1500
1509
|
|
1501
|
-
#
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1510
|
+
# set zone reheat temperatures depending on reheat
|
1511
|
+
case reheat_type
|
1512
|
+
when 'NaturalGas', 'Gas', 'Electricity', 'Water'
|
1513
|
+
# create vav terminal
|
1514
|
+
terminal = OpenStudio::Model::AirTerminalSingleDuctVAVReheat.new(model, model.alwaysOnDiscreteSchedule, rht_coil)
|
1515
|
+
terminal.setName("#{zone.name} VAV Terminal")
|
1516
|
+
terminal.setZoneMinimumAirFlowMethod('Constant')
|
1517
|
+
air_terminal_single_duct_vav_reheat_apply_initial_prototype_damper_position(terminal, thermal_zone_outdoor_airflow_rate_per_area(zone))
|
1518
|
+
terminal.setMaximumFlowFractionDuringReheat(0.5)
|
1519
|
+
terminal.setMaximumReheatAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
1520
|
+
air_loop.addBranchForZone(zone, terminal.to_StraightComponent)
|
1521
|
+
|
1522
|
+
# zone sizing
|
1523
|
+
sizing_zone = zone.sizingZone
|
1524
|
+
sizing_zone.setCoolingDesignAirFlowMethod('DesignDayWithLimit')
|
1525
|
+
sizing_zone.setHeatingDesignAirFlowMethod('DesignDay')
|
1526
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
1527
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
1528
|
+
else
|
1529
|
+
# no reheat
|
1530
|
+
# create vav terminal
|
1531
|
+
terminal = OpenStudio::Model::AirTerminalSingleDuctVAVNoReheat.new(model, model.alwaysOnDiscreteSchedule)
|
1532
|
+
terminal.setName("#{zone.name} VAV Terminal")
|
1533
|
+
terminal.setZoneMinimumAirFlowInputMethod('Constant')
|
1534
|
+
air_terminal_single_duct_vav_reheat_apply_initial_prototype_damper_position(terminal, thermal_zone_outdoor_airflow_rate_per_area(zone))
|
1535
|
+
air_loop.addBranchForZone(zone, terminal.to_StraightComponent)
|
1536
|
+
|
1537
|
+
# zone sizing
|
1538
|
+
sizing_zone = zone.sizingZone
|
1539
|
+
sizing_zone.setCoolingDesignAirFlowMethod('DesignDayWithLimit')
|
1540
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
1541
|
+
end
|
1516
1542
|
|
1517
1543
|
unless return_plenum.nil?
|
1518
1544
|
zone.setReturnPlenum(return_plenum)
|
@@ -1547,6 +1573,14 @@ class Standard
|
|
1547
1573
|
fan_pressure_rise: 4.0)
|
1548
1574
|
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding VAV with PFP Boxes and Reheat system for #{thermal_zones.size} zones.")
|
1549
1575
|
|
1576
|
+
# create air handler
|
1577
|
+
air_loop = OpenStudio::Model::AirLoopHVAC.new(model)
|
1578
|
+
if system_name.nil?
|
1579
|
+
air_loop.setName("#{thermal_zones.size} Zone VAV with PFP Boxes and Reheat")
|
1580
|
+
else
|
1581
|
+
air_loop.setName(system_name)
|
1582
|
+
end
|
1583
|
+
|
1550
1584
|
# hvac operation schedule
|
1551
1585
|
if hvac_op_sch.nil?
|
1552
1586
|
hvac_op_sch = model.alwaysOnDiscreteSchedule
|
@@ -1561,50 +1595,22 @@ class Standard
|
|
1561
1595
|
oa_damper_sch = model_add_schedule(model, oa_damper_sch)
|
1562
1596
|
end
|
1563
1597
|
|
1564
|
-
#
|
1565
|
-
|
1566
|
-
|
1567
|
-
preclg_sa_temp_f = 55.04 # Precool to 55F
|
1568
|
-
htg_sa_temp_f = 55.04 # Central deck htg temp 55F
|
1569
|
-
rht_sa_temp_f = 104 # VAV box reheat to 104F
|
1570
|
-
zone_htg_sa_temp_f = 104 # Zone heating design supply air temperature to 104 F
|
1571
|
-
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f, 'F', 'C').get
|
1572
|
-
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f, 'F', 'C').get
|
1573
|
-
preclg_sa_temp_c = OpenStudio.convert(preclg_sa_temp_f, 'F', 'C').get
|
1574
|
-
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f, 'F', 'C').get
|
1575
|
-
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f, 'F', 'C').get
|
1576
|
-
zone_htg_sa_temp_c = OpenStudio.convert(zone_htg_sa_temp_f, 'F', 'C').get
|
1577
|
-
sa_temp_sch = OpenStudio::Model::ScheduleRuleset.new(model)
|
1578
|
-
sa_temp_sch.setName("Supply Air Temp - #{clg_sa_temp_f}F")
|
1579
|
-
sa_temp_sch.defaultDaySchedule.setName("Supply Air Temp - #{clg_sa_temp_f}F Default")
|
1580
|
-
sa_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), clg_sa_temp_c)
|
1581
|
-
|
1582
|
-
# create air handler
|
1583
|
-
air_loop = OpenStudio::Model::AirLoopHVAC.new(model)
|
1584
|
-
if system_name.nil?
|
1585
|
-
air_loop.setName("#{thermal_zones.size} Zone VAV with PFP Boxes and Reheat")
|
1586
|
-
else
|
1587
|
-
air_loop.setName(system_name)
|
1588
|
-
end
|
1598
|
+
# default design temperatures and settings used across all air loops
|
1599
|
+
dsgn_temps = standard_design_sizing_temperatures
|
1600
|
+
sizing_system = adjust_sizing_system(air_loop, dsgn_temps)
|
1589
1601
|
|
1602
|
+
# air handler controls
|
1603
|
+
sa_temp_sch = model_add_constant_schedule_ruleset(model,
|
1604
|
+
dsgn_temps['clg_dsgn_sup_air_temp_c'],
|
1605
|
+
name = "Supply Air Temp - #{dsgn_temps['clg_dsgn_sup_air_temp_f']}F")
|
1590
1606
|
sa_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, sa_temp_sch)
|
1591
|
-
sa_stpt_manager.setName("#{
|
1607
|
+
sa_stpt_manager.setName("#{air_loop.name} Supply Air Setpoint Manager")
|
1592
1608
|
sa_stpt_manager.addToNode(air_loop.supplyOutletNode)
|
1593
1609
|
|
1594
|
-
# air handler controls
|
1595
|
-
sizing_system = air_loop.sizingSystem
|
1596
|
-
sizing_system.setPreheatDesignTemperature(prehtg_sa_temp_c)
|
1597
|
-
sizing_system.setPrecoolDesignTemperature(preclg_sa_temp_c)
|
1598
|
-
sizing_system.setCentralCoolingDesignSupplyAirTemperature(clg_sa_temp_c)
|
1599
|
-
sizing_system.setCentralHeatingDesignSupplyAirTemperature(htg_sa_temp_c)
|
1600
|
-
sizing_system.setSizingOption('Coincident')
|
1601
|
-
sizing_system.setAllOutdoorAirinCooling(false)
|
1602
|
-
sizing_system.setAllOutdoorAirinHeating(false)
|
1603
|
-
sizing_system.setSystemOutdoorAirMethod('ZoneSum')
|
1604
|
-
|
1605
1610
|
# create fan
|
1606
1611
|
# @type [OpenStudio::Model::FanVariableVolume] fan
|
1607
|
-
fan = create_fan_by_name(model,
|
1612
|
+
fan = create_fan_by_name(model,
|
1613
|
+
'VAV_System_Fan',
|
1608
1614
|
fan_name: "#{air_loop.name} Fan",
|
1609
1615
|
fan_efficiency: fan_efficiency,
|
1610
1616
|
pressure_rise: fan_pressure_rise,
|
@@ -1647,11 +1653,14 @@ class Standard
|
|
1647
1653
|
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding VAV with PFP Boxes and Reheat system terminal for #{zone.name}.")
|
1648
1654
|
|
1649
1655
|
# create reheat coil
|
1650
|
-
rht_coil = create_coil_heating_electric(model,
|
1656
|
+
rht_coil = create_coil_heating_electric(model,
|
1657
|
+
name: "#{zone.name} Electric Reheat Coil")
|
1651
1658
|
|
1652
1659
|
# create terminal fan
|
1653
1660
|
# @type [OpenStudio::Model::FanConstantVolume] pfp_fan
|
1654
|
-
pfp_fan = create_fan_by_name(model,
|
1661
|
+
pfp_fan = create_fan_by_name(model,
|
1662
|
+
'PFP_Fan',
|
1663
|
+
fan_name: "#{zone.name} PFP Term Fan")
|
1655
1664
|
pfp_fan.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
1656
1665
|
|
1657
1666
|
# create parallel fan powered terminal
|
@@ -1666,9 +1675,8 @@ class Standard
|
|
1666
1675
|
sizing_zone = zone.sizingZone
|
1667
1676
|
sizing_zone.setCoolingDesignAirFlowMethod('DesignDay')
|
1668
1677
|
sizing_zone.setHeatingDesignAirFlowMethod('DesignDay')
|
1669
|
-
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(
|
1670
|
-
|
1671
|
-
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(zone_htg_sa_temp_c)
|
1678
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
1679
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
1672
1680
|
end
|
1673
1681
|
|
1674
1682
|
return air_loop
|
@@ -1696,6 +1704,14 @@ class Standard
|
|
1696
1704
|
oa_damper_sch: nil)
|
1697
1705
|
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding Packaged VAV for #{thermal_zones.size} zones.")
|
1698
1706
|
|
1707
|
+
# create air handler
|
1708
|
+
air_loop = OpenStudio::Model::AirLoopHVAC.new(model)
|
1709
|
+
if system_name.nil?
|
1710
|
+
air_loop.setName("#{thermal_zones.size} Zone PVAV")
|
1711
|
+
else
|
1712
|
+
air_loop.setName(system_name)
|
1713
|
+
end
|
1714
|
+
|
1699
1715
|
# hvac operation schedule
|
1700
1716
|
if hvac_op_sch.nil?
|
1701
1717
|
hvac_op_sch = model.alwaysOnDiscreteSchedule
|
@@ -1710,62 +1726,32 @@ class Standard
|
|
1710
1726
|
oa_damper_sch = model_add_schedule(model, oa_damper_sch)
|
1711
1727
|
end
|
1712
1728
|
|
1713
|
-
#
|
1729
|
+
# default design temperatures used across all air loops
|
1730
|
+
dsgn_temps = standard_design_sizing_temperatures
|
1714
1731
|
unless hot_water_loop.nil?
|
1715
1732
|
hw_temp_c = hot_water_loop.sizingPlant.designLoopExitTemperature
|
1716
1733
|
hw_delta_t_k = hot_water_loop.sizingPlant.loopDesignTemperatureDifference
|
1717
1734
|
end
|
1718
|
-
sys_dsn_prhtg_temp_f = 44.6 # Design central deck to preheat to 44.6F
|
1719
|
-
sys_dsn_clg_sa_temp_f = 55 # Design central deck to cool to 55F
|
1720
|
-
sys_dsn_htg_sa_temp_f = 55 # Central heat to 55F
|
1721
|
-
zn_dsn_clg_sa_temp_f = 55 # Design VAV box for 55F from central deck
|
1722
|
-
zn_dsn_htg_sa_temp_f = 122 # Design VAV box to reheat to 122F
|
1723
|
-
rht_rated_air_in_temp_f = 55 # Reheat coils designed to receive 55F
|
1724
|
-
rht_rated_air_out_temp_f = 122 # Reheat coils designed to supply 122F
|
1725
|
-
clg_sa_temp_f = 55 # Central deck clg temp operates at 55F
|
1726
|
-
sys_dsn_prhtg_temp_c = OpenStudio.convert(sys_dsn_prhtg_temp_f, 'F', 'C').get
|
1727
|
-
sys_dsn_clg_sa_temp_c = OpenStudio.convert(sys_dsn_clg_sa_temp_f, 'F', 'C').get
|
1728
|
-
sys_dsn_htg_sa_temp_c = OpenStudio.convert(sys_dsn_htg_sa_temp_f, 'F', 'C').get
|
1729
|
-
zn_dsn_clg_sa_temp_c = OpenStudio.convert(zn_dsn_clg_sa_temp_f, 'F', 'C').get
|
1730
|
-
zn_dsn_htg_sa_temp_c = OpenStudio.convert(zn_dsn_htg_sa_temp_f, 'F', 'C').get
|
1731
|
-
rht_rated_air_in_temp_c = OpenStudio.convert(rht_rated_air_in_temp_f, 'F', 'C').get
|
1732
|
-
rht_rated_air_out_temp_c = OpenStudio.convert(rht_rated_air_out_temp_f, 'F', 'C').get
|
1733
|
-
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f, 'F', 'C').get
|
1734
|
-
sa_temp_sch = OpenStudio::Model::ScheduleRuleset.new(model)
|
1735
|
-
sa_temp_sch.setName("Supply Air Temp - #{clg_sa_temp_f.round(0)}F")
|
1736
|
-
sa_temp_sch.defaultDaySchedule.setName("Supply Air Temp - #{clg_sa_temp_f.round(0)}F Default")
|
1737
|
-
sa_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), clg_sa_temp_c)
|
1738
1735
|
|
1739
|
-
#
|
1740
|
-
|
1741
|
-
|
1742
|
-
air_loop.setName("#{thermal_zones.size} Zone PVAV")
|
1743
|
-
else
|
1744
|
-
air_loop.setName(system_name)
|
1745
|
-
end
|
1736
|
+
# adjusted zone design heating temperature for pvav
|
1737
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_f'] = 122.0
|
1738
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['zn_htg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
1746
1739
|
|
1747
|
-
#
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1757
|
-
air_loop.setNightCycleControlType('CycleOnAny')
|
1758
|
-
avail_mgr = air_loop.availabilityManager
|
1759
|
-
if avail_mgr.is_initialized
|
1760
|
-
avail_mgr = avail_mgr.get
|
1761
|
-
if avail_mgr.to_AvailabilityManagerNightCycle.is_initialized
|
1762
|
-
avail_mgr = avail_mgr.to_AvailabilityManagerNightCycle.get
|
1763
|
-
avail_mgr.setCyclingRunTime(1800)
|
1764
|
-
end
|
1765
|
-
end
|
1740
|
+
# default design settings used across all air loops
|
1741
|
+
sizing_system = adjust_sizing_system(air_loop, dsgn_temps)
|
1742
|
+
|
1743
|
+
# air handler controls
|
1744
|
+
sa_temp_sch = model_add_constant_schedule_ruleset(model,
|
1745
|
+
dsgn_temps['clg_dsgn_sup_air_temp_c'],
|
1746
|
+
name = "Supply Air Temp - #{dsgn_temps['clg_dsgn_sup_air_temp_f']}F")
|
1747
|
+
sa_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, sa_temp_sch)
|
1748
|
+
sa_stpt_manager.setName("#{air_loop.name} Supply Air Setpoint Manager")
|
1749
|
+
sa_stpt_manager.addToNode(air_loop.supplyOutletNode)
|
1766
1750
|
|
1767
1751
|
# create fan
|
1768
|
-
fan = create_fan_by_name(model,
|
1752
|
+
fan = create_fan_by_name(model,
|
1753
|
+
'VAV_default',
|
1754
|
+
fan_name: "#{air_loop.name} Fan")
|
1769
1755
|
fan.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
1770
1756
|
fan.addToNode(air_loop.supplyInletNode)
|
1771
1757
|
|
@@ -1781,8 +1767,8 @@ class Standard
|
|
1781
1767
|
name: "#{air_loop.name} Main Htg Coil",
|
1782
1768
|
rated_inlet_water_temperature: hw_temp_c,
|
1783
1769
|
rated_outlet_water_temperature: (hw_temp_c - hw_delta_t_k),
|
1784
|
-
rated_inlet_air_temperature:
|
1785
|
-
rated_outlet_air_temperature:
|
1770
|
+
rated_inlet_air_temperature: dsgn_temps['prehtg_dsgn_sup_air_temp_c'],
|
1771
|
+
rated_outlet_air_temperature: dsgn_temps['htg_dsgn_sup_air_temp_c'])
|
1786
1772
|
end
|
1787
1773
|
|
1788
1774
|
# create cooling coil
|
@@ -1814,6 +1800,14 @@ class Standard
|
|
1814
1800
|
# set air loop availability controls and night cycle manager, after oa system added
|
1815
1801
|
air_loop.setAvailabilitySchedule(hvac_op_sch)
|
1816
1802
|
air_loop.setNightCycleControlType('CycleOnAny')
|
1803
|
+
avail_mgr = air_loop.availabilityManager
|
1804
|
+
if avail_mgr.is_initialized
|
1805
|
+
avail_mgr = avail_mgr.get
|
1806
|
+
if avail_mgr.to_AvailabilityManagerNightCycle.is_initialized
|
1807
|
+
avail_mgr = avail_mgr.to_AvailabilityManagerNightCycle.get
|
1808
|
+
avail_mgr.setCyclingRunTime(1800)
|
1809
|
+
end
|
1810
|
+
end
|
1817
1811
|
|
1818
1812
|
# attach the VAV system to each zone
|
1819
1813
|
thermal_zones.each do |zone|
|
@@ -1821,22 +1815,23 @@ class Standard
|
|
1821
1815
|
|
1822
1816
|
# create reheat coil
|
1823
1817
|
if electric_reheat || hot_water_loop.nil?
|
1824
|
-
rht_coil = create_coil_heating_electric(model,
|
1818
|
+
rht_coil = create_coil_heating_electric(model,
|
1819
|
+
name: "#{zone.name} Electric Reheat Coil")
|
1825
1820
|
else
|
1826
1821
|
rht_coil = create_coil_heating_water(model,
|
1827
1822
|
hot_water_loop,
|
1828
1823
|
name: "#{zone.name} Reheat Coil",
|
1829
1824
|
rated_inlet_water_temperature: hw_temp_c,
|
1830
1825
|
rated_outlet_water_temperature: (hw_temp_c - hw_delta_t_k),
|
1831
|
-
rated_inlet_air_temperature:
|
1832
|
-
rated_outlet_air_temperature:
|
1826
|
+
rated_inlet_air_temperature: dsgn_temps['htg_dsgn_sup_air_temp_c'],
|
1827
|
+
rated_outlet_air_temperature: dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
1833
1828
|
end
|
1834
1829
|
|
1835
1830
|
# create VAV terminal
|
1836
1831
|
terminal = OpenStudio::Model::AirTerminalSingleDuctVAVReheat.new(model, model.alwaysOnDiscreteSchedule, rht_coil)
|
1837
1832
|
terminal.setName("#{zone.name} VAV Terminal")
|
1838
1833
|
terminal.setZoneMinimumAirFlowMethod('Constant')
|
1839
|
-
terminal.setMaximumReheatAirTemperature(
|
1834
|
+
terminal.setMaximumReheatAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
1840
1835
|
air_terminal_single_duct_vav_reheat_apply_initial_prototype_damper_position(terminal, thermal_zone_outdoor_airflow_rate_per_area(zone))
|
1841
1836
|
air_loop.addBranchForZone(zone, terminal.to_StraightComponent)
|
1842
1837
|
|
@@ -1846,8 +1841,8 @@ class Standard
|
|
1846
1841
|
|
1847
1842
|
# zone sizing
|
1848
1843
|
sizing_zone = zone.sizingZone
|
1849
|
-
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(
|
1850
|
-
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(
|
1844
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
1845
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
1851
1846
|
end
|
1852
1847
|
|
1853
1848
|
# set the damper action based on the template
|
@@ -1878,6 +1873,14 @@ class Standard
|
|
1878
1873
|
fan_pressure_rise: 4.0)
|
1879
1874
|
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding PVAV with PFP Boxes and Reheat system for #{thermal_zones.size} zones.")
|
1880
1875
|
|
1876
|
+
# create air handler
|
1877
|
+
air_loop = OpenStudio::Model::AirLoopHVAC.new(model)
|
1878
|
+
if system_name.nil?
|
1879
|
+
air_loop.setName("#{thermal_zones.size} Zone VAV with PFP Boxes and Reheat")
|
1880
|
+
else
|
1881
|
+
air_loop.setName(system_name)
|
1882
|
+
end
|
1883
|
+
|
1881
1884
|
# hvac operation schedule
|
1882
1885
|
if hvac_op_sch.nil?
|
1883
1886
|
hvac_op_sch = model.alwaysOnDiscreteSchedule
|
@@ -1892,47 +1895,18 @@ class Standard
|
|
1892
1895
|
oa_damper_sch = model_add_schedule(model, oa_damper_sch)
|
1893
1896
|
end
|
1894
1897
|
|
1895
|
-
#
|
1896
|
-
|
1897
|
-
|
1898
|
-
preclg_sa_temp_f = 55.04 # Precool to 55F
|
1899
|
-
htg_sa_temp_f = 55.04 # Central deck htg temp 55F
|
1900
|
-
rht_sa_temp_f = 104 # VAV box reheat to 104F
|
1901
|
-
zone_htg_sa_temp_f = 104 # Zone heating design supply air temperature to 104 F
|
1902
|
-
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f, 'F', 'C').get
|
1903
|
-
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f, 'F', 'C').get
|
1904
|
-
preclg_sa_temp_c = OpenStudio.convert(preclg_sa_temp_f, 'F', 'C').get
|
1905
|
-
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f, 'F', 'C').get
|
1906
|
-
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f, 'F', 'C').get
|
1907
|
-
zone_htg_sa_temp_c = OpenStudio.convert(zone_htg_sa_temp_f, 'F', 'C').get
|
1908
|
-
sa_temp_sch = OpenStudio::Model::ScheduleRuleset.new(model)
|
1909
|
-
sa_temp_sch.setName("Supply Air Temp #{clg_sa_temp_f}F")
|
1910
|
-
sa_temp_sch.defaultDaySchedule.setName("Supply Air Temp #{clg_sa_temp_f}F Default")
|
1911
|
-
sa_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), clg_sa_temp_c)
|
1912
|
-
|
1913
|
-
# create air handler
|
1914
|
-
air_loop = OpenStudio::Model::AirLoopHVAC.new(model)
|
1915
|
-
if system_name.nil?
|
1916
|
-
air_loop.setName("#{thermal_zones.size} Zone VAV with PFP Boxes and Reheat")
|
1917
|
-
else
|
1918
|
-
air_loop.setName(system_name)
|
1919
|
-
end
|
1898
|
+
# default design temperatures and settings used across all air loops
|
1899
|
+
dsgn_temps = standard_design_sizing_temperatures
|
1900
|
+
sizing_system = adjust_sizing_system(air_loop, dsgn_temps)
|
1920
1901
|
|
1902
|
+
# air handler controls
|
1903
|
+
sa_temp_sch = model_add_constant_schedule_ruleset(model,
|
1904
|
+
dsgn_temps['clg_dsgn_sup_air_temp_c'],
|
1905
|
+
name = "Supply Air Temp - #{dsgn_temps['clg_dsgn_sup_air_temp_f']}F")
|
1921
1906
|
sa_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, sa_temp_sch)
|
1922
|
-
sa_stpt_manager.setName("#{
|
1907
|
+
sa_stpt_manager.setName("#{air_loop.name} Supply Air Setpoint Manager")
|
1923
1908
|
sa_stpt_manager.addToNode(air_loop.supplyOutletNode)
|
1924
1909
|
|
1925
|
-
# set air handler controls
|
1926
|
-
sizing_system = air_loop.sizingSystem
|
1927
|
-
sizing_system.setPreheatDesignTemperature(prehtg_sa_temp_c)
|
1928
|
-
sizing_system.setPrecoolDesignTemperature(preclg_sa_temp_c)
|
1929
|
-
sizing_system.setCentralCoolingDesignSupplyAirTemperature(clg_sa_temp_c)
|
1930
|
-
sizing_system.setCentralHeatingDesignSupplyAirTemperature(htg_sa_temp_c)
|
1931
|
-
sizing_system.setSizingOption('Coincident')
|
1932
|
-
sizing_system.setAllOutdoorAirinCooling(false)
|
1933
|
-
sizing_system.setAllOutdoorAirinHeating(false)
|
1934
|
-
sizing_system.setSystemOutdoorAirMethod('ZoneSum')
|
1935
|
-
|
1936
1910
|
# create fan
|
1937
1911
|
# @type [OpenStudio::Model::FanVariableVolume] fan
|
1938
1912
|
fan = create_fan_by_name(model,
|
@@ -1986,11 +1960,14 @@ class Standard
|
|
1986
1960
|
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.Model.Model', "Adding PVAV PFP Box to zone #{zone.name}")
|
1987
1961
|
|
1988
1962
|
# create electric reheat coil
|
1989
|
-
rht_coil = create_coil_heating_electric(model,
|
1963
|
+
rht_coil = create_coil_heating_electric(model,
|
1964
|
+
name: "#{zone.name} Electric Reheat Coil")
|
1990
1965
|
|
1991
1966
|
# create terminal fan
|
1992
1967
|
# @type [OpenStudio::Model::FanConstantVolume] pfp_fan
|
1993
|
-
pfp_fan = create_fan_by_name(model,
|
1968
|
+
pfp_fan = create_fan_by_name(model,
|
1969
|
+
'PFP_Fan',
|
1970
|
+
fan_name: "#{zone.name} PFP Term Fan")
|
1994
1971
|
pfp_fan.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
1995
1972
|
|
1996
1973
|
# parallel fan powered terminal
|
@@ -2005,8 +1982,8 @@ class Standard
|
|
2005
1982
|
sizing_zone = zone.sizingZone
|
2006
1983
|
sizing_zone.setCoolingDesignAirFlowMethod('DesignDay')
|
2007
1984
|
sizing_zone.setHeatingDesignAirFlowMethod('DesignDay')
|
2008
|
-
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(
|
2009
|
-
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(
|
1985
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
1986
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
2010
1987
|
end
|
2011
1988
|
|
2012
1989
|
return air_loop
|
@@ -2036,6 +2013,14 @@ class Standard
|
|
2036
2013
|
fan_pressure_rise: 4.0)
|
2037
2014
|
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding CAV for #{thermal_zones.size} zones.")
|
2038
2015
|
|
2016
|
+
# create air handler
|
2017
|
+
air_loop = OpenStudio::Model::AirLoopHVAC.new(model)
|
2018
|
+
if system_name.nil?
|
2019
|
+
air_loop.setName("#{thermal_zones.size} Zone CAV")
|
2020
|
+
else
|
2021
|
+
air_loop.setName(system_name)
|
2022
|
+
end
|
2023
|
+
|
2039
2024
|
# hvac operation schedule
|
2040
2025
|
if hvac_op_sch.nil?
|
2041
2026
|
hvac_op_sch = model.alwaysOnDiscreteSchedule
|
@@ -2050,54 +2035,30 @@ class Standard
|
|
2050
2035
|
oa_damper_sch = model_add_schedule(model, oa_damper_sch)
|
2051
2036
|
end
|
2052
2037
|
|
2053
|
-
#
|
2038
|
+
# default design temperatures used across all air loops
|
2039
|
+
dsgn_temps = standard_design_sizing_temperatures
|
2054
2040
|
unless hot_water_loop.nil?
|
2055
2041
|
hw_temp_c = hot_water_loop.sizingPlant.designLoopExitTemperature
|
2056
2042
|
hw_delta_t_k = hot_water_loop.sizingPlant.loopDesignTemperatureDifference
|
2057
2043
|
end
|
2058
|
-
clg_sa_temp_f = 55.04
|
2059
|
-
prehtg_sa_temp_f = 44.6
|
2060
|
-
preclg_sa_temp_f = 55.04
|
2061
|
-
htg_sa_temp_f = 62.06
|
2062
|
-
rht_sa_temp_f = 122.0
|
2063
|
-
zone_htg_sa_temp_f = 122.0
|
2064
|
-
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f, 'F', 'C').get
|
2065
|
-
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f, 'F', 'C').get
|
2066
|
-
preclg_sa_temp_c = OpenStudio.convert(preclg_sa_temp_f, 'F', 'C').get
|
2067
|
-
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f, 'F', 'C').get
|
2068
|
-
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f, 'F', 'C').get
|
2069
|
-
zone_htg_sa_temp_c = OpenStudio.convert(zone_htg_sa_temp_f, 'F', 'C').get
|
2070
2044
|
|
2071
|
-
#
|
2072
|
-
|
2073
|
-
|
2074
|
-
|
2075
|
-
|
2076
|
-
air_loop.setName(system_name)
|
2077
|
-
end
|
2045
|
+
# adjusted design heating temperature for cav
|
2046
|
+
dsgn_temps['htg_dsgn_sup_air_temp_f'] = 62.0
|
2047
|
+
dsgn_temps['htg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['htg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
2048
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_f'] = 122.0
|
2049
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['zn_htg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
2078
2050
|
|
2079
|
-
#
|
2080
|
-
|
2081
|
-
sa_temp_sch.setName("Supply Air Temp - #{clg_sa_temp_f}F")
|
2082
|
-
sa_temp_sch.defaultDaySchedule.setName("Supply Air Temp - #{clg_sa_temp_f}F Default")
|
2083
|
-
sa_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), clg_sa_temp_c)
|
2051
|
+
# default design settings used across all air loops
|
2052
|
+
sizing_system = adjust_sizing_system(air_loop, dsgn_temps, min_sys_airflow_ratio: 1.0)
|
2084
2053
|
|
2054
|
+
# air handler controls
|
2055
|
+
sa_temp_sch = model_add_constant_schedule_ruleset(model,
|
2056
|
+
dsgn_temps['clg_dsgn_sup_air_temp_c'],
|
2057
|
+
name = "Supply Air Temp - #{dsgn_temps['clg_dsgn_sup_air_temp_f']}F")
|
2085
2058
|
sa_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, sa_temp_sch)
|
2086
|
-
sa_stpt_manager.setName("#{air_loop.name}
|
2059
|
+
sa_stpt_manager.setName("#{air_loop.name} Supply Air Setpoint Manager")
|
2087
2060
|
sa_stpt_manager.addToNode(air_loop.supplyOutletNode)
|
2088
2061
|
|
2089
|
-
# set air handler sizing
|
2090
|
-
sizing_system = air_loop.sizingSystem
|
2091
|
-
sizing_system.setMinimumSystemAirFlowRatio(1.0)
|
2092
|
-
sizing_system.setPreheatDesignTemperature(prehtg_sa_temp_c)
|
2093
|
-
sizing_system.setPrecoolDesignTemperature(preclg_sa_temp_c)
|
2094
|
-
sizing_system.setCentralCoolingDesignSupplyAirTemperature(clg_sa_temp_c)
|
2095
|
-
sizing_system.setCentralHeatingDesignSupplyAirTemperature(htg_sa_temp_c)
|
2096
|
-
sizing_system.setSizingOption('Coincident')
|
2097
|
-
sizing_system.setAllOutdoorAirinCooling(false)
|
2098
|
-
sizing_system.setAllOutdoorAirinHeating(false)
|
2099
|
-
sizing_system.setSystemOutdoorAirMethod('ZoneSum')
|
2100
|
-
|
2101
2062
|
# create fan
|
2102
2063
|
fan = create_fan_by_name(model,
|
2103
2064
|
'Packaged_RTU_SZ_AC_CAV_Fan',
|
@@ -2116,8 +2077,8 @@ class Standard
|
|
2116
2077
|
name: "#{air_loop.name} Main Htg Coil",
|
2117
2078
|
rated_inlet_water_temperature: hw_temp_c,
|
2118
2079
|
rated_outlet_water_temperature: (hw_temp_c - hw_delta_t_k),
|
2119
|
-
rated_inlet_air_temperature:
|
2120
|
-
rated_outlet_air_temperature:
|
2080
|
+
rated_inlet_air_temperature: dsgn_temps['prehtg_dsgn_sup_air_temp_c'],
|
2081
|
+
rated_outlet_air_temperature: dsgn_temps['htg_dsgn_sup_air_temp_c'])
|
2121
2082
|
|
2122
2083
|
# create cooling coil
|
2123
2084
|
if chilled_water_loop.nil?
|
@@ -2160,8 +2121,8 @@ class Standard
|
|
2160
2121
|
name: "#{zone.name} Reheat Coil",
|
2161
2122
|
rated_inlet_water_temperature: hw_temp_c,
|
2162
2123
|
rated_outlet_water_temperature: (hw_temp_c - hw_delta_t_k),
|
2163
|
-
rated_inlet_air_temperature:
|
2164
|
-
rated_outlet_air_temperature:
|
2124
|
+
rated_inlet_air_temperature: dsgn_temps['htg_dsgn_sup_air_temp_c'],
|
2125
|
+
rated_outlet_air_temperature: dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
2165
2126
|
# VAV terminal
|
2166
2127
|
terminal = OpenStudio::Model::AirTerminalSingleDuctVAVReheat.new(model, model.alwaysOnDiscreteSchedule, rht_coil)
|
2167
2128
|
terminal.setName("#{zone.name} VAV Terminal")
|
@@ -2169,16 +2130,15 @@ class Standard
|
|
2169
2130
|
air_terminal_single_duct_vav_reheat_apply_initial_prototype_damper_position(terminal, thermal_zone_outdoor_airflow_rate_per_area(zone))
|
2170
2131
|
terminal.setMaximumFlowPerZoneFloorAreaDuringReheat(0.0)
|
2171
2132
|
terminal.setMaximumFlowFractionDuringReheat(0.5)
|
2172
|
-
terminal.setMaximumReheatAirTemperature(
|
2133
|
+
terminal.setMaximumReheatAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
2173
2134
|
air_loop.addBranchForZone(zone, terminal.to_StraightComponent)
|
2174
2135
|
|
2175
2136
|
# zone sizing
|
2176
2137
|
sizing_zone = zone.sizingZone
|
2177
2138
|
sizing_zone.setCoolingDesignAirFlowMethod('DesignDayWithLimit')
|
2178
2139
|
sizing_zone.setHeatingDesignAirFlowMethod('DesignDay')
|
2179
|
-
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(
|
2180
|
-
|
2181
|
-
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(zone_htg_sa_temp_c)
|
2140
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
2141
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
2182
2142
|
end
|
2183
2143
|
|
2184
2144
|
# Set the damper action based on the template.
|
@@ -2240,42 +2200,49 @@ class Standard
|
|
2240
2200
|
air_loop.setName("#{zone.name} #{system_name}")
|
2241
2201
|
end
|
2242
2202
|
|
2243
|
-
#
|
2244
|
-
|
2245
|
-
|
2246
|
-
|
2247
|
-
|
2248
|
-
|
2249
|
-
|
2250
|
-
|
2251
|
-
|
2252
|
-
|
2253
|
-
|
2254
|
-
|
2255
|
-
|
2256
|
-
|
2257
|
-
|
2258
|
-
|
2259
|
-
|
2260
|
-
|
2261
|
-
|
2262
|
-
|
2263
|
-
|
2203
|
+
# default design temperatures and settings used across all air loops
|
2204
|
+
dsgn_temps = standard_design_sizing_temperatures
|
2205
|
+
unless hot_water_loop.nil?
|
2206
|
+
hw_temp_c = hot_water_loop.sizingPlant.designLoopExitTemperature
|
2207
|
+
hw_delta_t_k = hot_water_loop.sizingPlant.loopDesignTemperatureDifference
|
2208
|
+
end
|
2209
|
+
|
2210
|
+
# adjusted design heating temperature for psz_ac
|
2211
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_f'] = 122.0
|
2212
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['zn_htg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
2213
|
+
dsgn_temps['htg_dsgn_sup_air_temp_f'] = dsgn_temps['zn_htg_dsgn_sup_air_temp_f']
|
2214
|
+
dsgn_temps['htg_dsgn_sup_air_temp_c'] = dsgn_temps['zn_htg_dsgn_sup_air_temp_c']
|
2215
|
+
|
2216
|
+
# default design settings used across all air loops
|
2217
|
+
sizing_system = adjust_sizing_system(air_loop, dsgn_temps, min_sys_airflow_ratio: 1.0)
|
2218
|
+
|
2219
|
+
# air handler controls
|
2220
|
+
# add a setpoint manager single zone reheat to control the supply air temperature
|
2221
|
+
setpoint_mgr_single_zone_reheat = OpenStudio::Model::SetpointManagerSingleZoneReheat.new(model)
|
2222
|
+
setpoint_mgr_single_zone_reheat.setName("#{zone.name} Setpoint Manager SZ Reheat")
|
2223
|
+
setpoint_mgr_single_zone_reheat.setControlZone(zone)
|
2224
|
+
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
2225
|
+
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
2226
|
+
setpoint_mgr_single_zone_reheat.addToNode(air_loop.supplyOutletNode)
|
2264
2227
|
|
2265
2228
|
# zone sizing
|
2266
2229
|
sizing_zone = zone.sizingZone
|
2267
|
-
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(
|
2268
|
-
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(
|
2230
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
2231
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
2269
2232
|
|
2270
2233
|
# create fan
|
2271
2234
|
# ConstantVolume: Packaged Rooftop Single Zone Air conditioner
|
2272
2235
|
# Cycling: Unitary System
|
2273
2236
|
# CyclingHeatPump: Unitary Heat Pump system
|
2274
2237
|
if fan_type == 'ConstantVolume'
|
2275
|
-
fan = create_fan_by_name(model,
|
2238
|
+
fan = create_fan_by_name(model,
|
2239
|
+
'Packaged_RTU_SZ_AC_CAV_Fan',
|
2240
|
+
fan_name: "#{air_loop.name} Fan")
|
2276
2241
|
fan.setAvailabilitySchedule(hvac_op_sch)
|
2277
2242
|
elsif fan_type == 'Cycling'
|
2278
|
-
fan = create_fan_by_name(model,
|
2243
|
+
fan = create_fan_by_name(model,
|
2244
|
+
'Packaged_RTU_SZ_AC_Cycling_Fan',
|
2245
|
+
fan_name: "#{air_loop.name} Fan")
|
2279
2246
|
fan.setAvailabilitySchedule(hvac_op_sch)
|
2280
2247
|
else
|
2281
2248
|
OpenStudio.logFree(OpenStudio::Error, 'openstudio.Model.Model', "Fan type '#{fan_type}' not recognized, cannot add PSZ-AC.")
|
@@ -2285,31 +2252,34 @@ class Standard
|
|
2285
2252
|
# create heating coil
|
2286
2253
|
case heating_type
|
2287
2254
|
when 'NaturalGas', 'Gas'
|
2288
|
-
htg_coil = create_coil_heating_gas(model,
|
2255
|
+
htg_coil = create_coil_heating_gas(model,
|
2256
|
+
name: "#{air_loop.name} Gas Htg Coil")
|
2289
2257
|
when 'Water'
|
2290
2258
|
if hot_water_loop.nil?
|
2291
2259
|
OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'No hot water plant loop supplied')
|
2292
2260
|
return false
|
2293
2261
|
end
|
2294
|
-
hw_temp_c = hot_water_loop.sizingPlant.designLoopExitTemperature
|
2295
|
-
hw_delta_t_k = hot_water_loop.sizingPlant.loopDesignTemperatureDifference
|
2296
|
-
prehtg_sa_temp_c = OpenStudio.convert(44.6, 'F', 'C').get
|
2297
|
-
htg_sa_temp_c = OpenStudio.convert(55.0, 'F', 'C').get
|
2298
2262
|
htg_coil = create_coil_heating_water(model,
|
2299
2263
|
hot_water_loop,
|
2300
2264
|
name: "#{air_loop.name} Water Htg Coil",
|
2301
2265
|
rated_inlet_water_temperature: hw_temp_c,
|
2302
2266
|
rated_outlet_water_temperature: (hw_temp_c - hw_delta_t_k),
|
2303
|
-
rated_inlet_air_temperature:
|
2304
|
-
rated_outlet_air_temperature:
|
2267
|
+
rated_inlet_air_temperature: dsgn_temps['prehtg_dsgn_sup_air_temp_c'],
|
2268
|
+
rated_outlet_air_temperature: dsgn_temps['htg_dsgn_sup_air_temp_c'])
|
2305
2269
|
when 'Single Speed Heat Pump'
|
2306
|
-
htg_coil = create_coil_heating_dx_single_speed(model,
|
2270
|
+
htg_coil = create_coil_heating_dx_single_speed(model,
|
2271
|
+
name: "#{zone.name} HP Htg Coil",
|
2272
|
+
type: 'PSZ-AC',
|
2273
|
+
cop: 3.3)
|
2307
2274
|
when 'Water To Air Heat Pump'
|
2308
|
-
htg_coil = create_coil_heating_water_to_air_heat_pump_equation_fit(model,
|
2275
|
+
htg_coil = create_coil_heating_water_to_air_heat_pump_equation_fit(model,
|
2276
|
+
hot_water_loop,
|
2277
|
+
name: "#{air_loop.name} Water-to-Air HP Htg Coil")
|
2309
2278
|
when 'Electricity', 'Electric'
|
2310
|
-
htg_coil = create_coil_heating_electric(model,
|
2279
|
+
htg_coil = create_coil_heating_electric(model,
|
2280
|
+
name: "#{air_loop.name} Electric Htg Coil")
|
2311
2281
|
else
|
2312
|
-
#
|
2282
|
+
# zero-capacity, always-off electric heating coil
|
2313
2283
|
htg_coil = create_coil_heating_electric(model,
|
2314
2284
|
name: "#{air_loop.name} No Heat",
|
2315
2285
|
schedule: model.alwaysOffDiscreteSchedule,
|
@@ -2319,9 +2289,11 @@ class Standard
|
|
2319
2289
|
# create supplemental heating coil
|
2320
2290
|
case supplemental_heating_type
|
2321
2291
|
when 'Electricity', 'Electric'
|
2322
|
-
supplemental_htg_coil = create_coil_heating_electric(model,
|
2292
|
+
supplemental_htg_coil = create_coil_heating_electric(model,
|
2293
|
+
name: "#{air_loop.name} Electric Backup Htg Coil")
|
2323
2294
|
when 'NaturalGas', 'Gas'
|
2324
|
-
supplemental_htg_coil = create_coil_heating_gas(model,
|
2295
|
+
supplemental_htg_coil = create_coil_heating_gas(model,
|
2296
|
+
name: "#{air_loop.name} Gas Backup Htg Coil")
|
2325
2297
|
else
|
2326
2298
|
# Zero-capacity, always-off electric heating coil
|
2327
2299
|
supplemental_htg_coil = create_coil_heating_electric(model,
|
@@ -2337,9 +2309,12 @@ class Standard
|
|
2337
2309
|
OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'No chilled water plant loop supplied')
|
2338
2310
|
return false
|
2339
2311
|
end
|
2340
|
-
clg_coil = create_coil_cooling_water(model,
|
2312
|
+
clg_coil = create_coil_cooling_water(model,
|
2313
|
+
chilled_water_loop,
|
2314
|
+
name: "#{air_loop.name} Water Clg Coil")
|
2341
2315
|
when 'Two Speed DX AC'
|
2342
|
-
clg_coil = create_coil_cooling_dx_two_speed(model,
|
2316
|
+
clg_coil = create_coil_cooling_dx_two_speed(model,
|
2317
|
+
name: "#{air_loop.name} 2spd DX AC Clg Coil")
|
2343
2318
|
when 'Single Speed DX AC'
|
2344
2319
|
clg_coil = create_coil_cooling_dx_single_speed(model,
|
2345
2320
|
name: "#{air_loop.name} 1spd DX AC Clg Coil",
|
@@ -2357,16 +2332,13 @@ class Standard
|
|
2357
2332
|
OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'No chilled water plant loop supplied')
|
2358
2333
|
return false
|
2359
2334
|
end
|
2360
|
-
clg_coil = create_coil_cooling_water_to_air_heat_pump_equation_fit(model,
|
2335
|
+
clg_coil = create_coil_cooling_water_to_air_heat_pump_equation_fit(model,
|
2336
|
+
chilled_water_loop,
|
2337
|
+
name: "#{air_loop.name} Water-to-Air HP Clg Coil")
|
2361
2338
|
else
|
2362
2339
|
clg_coil = nil
|
2363
2340
|
end
|
2364
2341
|
|
2365
|
-
# add a setpoint manager single zone reheat to control the supply air temperature
|
2366
|
-
setpoint_mgr_single_zone_reheat = OpenStudio::Model::SetpointManagerSingleZoneReheat.new(model)
|
2367
|
-
setpoint_mgr_single_zone_reheat.setControlZone(zone)
|
2368
|
-
setpoint_mgr_single_zone_reheat.addToNode(air_loop.supplyOutletNode)
|
2369
|
-
|
2370
2342
|
# wrap coils in a unitary system if cycling, or not if constant volume
|
2371
2343
|
if fan_type == 'Cycling'
|
2372
2344
|
if heating_type == 'Water To Air Heat Pump'
|
@@ -2378,14 +2350,13 @@ class Standard
|
|
2378
2350
|
unitary_system.setSupplementalHeatingCoil(supplemental_htg_coil) unless supplemental_htg_coil.nil?
|
2379
2351
|
unitary_system.setName("#{zone.name} Unitary HP")
|
2380
2352
|
unitary_system.setControllingZoneorThermostatLocation(zone)
|
2381
|
-
unitary_system.setMaximumSupplyAirTemperature(
|
2353
|
+
unitary_system.setMaximumSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
2382
2354
|
unitary_system.setFanPlacement('BlowThrough')
|
2383
2355
|
unitary_system.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
|
2384
2356
|
unitary_system.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
|
2385
2357
|
unitary_system.setSupplyAirFlowRateMethodWhenNoCoolingorHeatingisRequired('SupplyAirFlowRate')
|
2386
2358
|
unitary_system.setSupplyAirFanOperatingModeSchedule(model.alwaysOnDiscreteSchedule)
|
2387
2359
|
unitary_system.addToNode(air_loop.supplyInletNode)
|
2388
|
-
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(50.0)
|
2389
2360
|
else
|
2390
2361
|
# CyclingHeatPump: Unitary Heat Pump system
|
2391
2362
|
unitary_system = OpenStudio::Model::AirLoopHVACUnitaryHeatPumpAirToAir.new(model,
|
@@ -2400,8 +2371,6 @@ class Standard
|
|
2400
2371
|
unitary_system.setFanPlacement(fan_location)
|
2401
2372
|
unitary_system.setSupplyAirFanOperatingModeSchedule(hvac_op_sch)
|
2402
2373
|
unitary_system.addToNode(air_loop.supplyInletNode)
|
2403
|
-
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(OpenStudio.convert(55.0, 'F', 'C').get)
|
2404
|
-
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(OpenStudio.convert(104.0, 'F', 'C').get)
|
2405
2374
|
end
|
2406
2375
|
else
|
2407
2376
|
# ConstantVolume: Packaged Rooftop Single Zone Air conditioner
|
@@ -2427,8 +2396,6 @@ class Standard
|
|
2427
2396
|
OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'Invalid fan location')
|
2428
2397
|
return false
|
2429
2398
|
end
|
2430
|
-
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(OpenStudio.convert(50.0, 'F', 'C').get)
|
2431
|
-
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(OpenStudio.convert(122.0, 'F', 'C').get)
|
2432
2399
|
end
|
2433
2400
|
|
2434
2401
|
# add the OA system
|
@@ -2508,36 +2475,29 @@ class Standard
|
|
2508
2475
|
air_loop.setName("#{zone.name} #{system_name}")
|
2509
2476
|
end
|
2510
2477
|
|
2511
|
-
#
|
2512
|
-
|
2513
|
-
air_loop_sizing.setTypeofLoadtoSizeOn('Sensible')
|
2514
|
-
air_loop_sizing.autosizeDesignOutdoorAirFlowRate
|
2515
|
-
air_loop_sizing.setMinimumSystemAirFlowRatio(0.0)
|
2516
|
-
air_loop_sizing.setPreheatDesignTemperature(7.0)
|
2517
|
-
air_loop_sizing.setPreheatDesignHumidityRatio(0.008)
|
2518
|
-
air_loop_sizing.setPrecoolDesignTemperature(12.8)
|
2519
|
-
air_loop_sizing.setPrecoolDesignHumidityRatio(0.008)
|
2520
|
-
air_loop_sizing.setCentralCoolingDesignSupplyAirTemperature(12.8)
|
2521
|
-
air_loop_sizing.setCentralHeatingDesignSupplyAirTemperature(40.0)
|
2522
|
-
air_loop_sizing.setSizingOption('Coincident')
|
2523
|
-
air_loop_sizing.setAllOutdoorAirinCooling(false)
|
2524
|
-
air_loop_sizing.setAllOutdoorAirinHeating(false)
|
2525
|
-
air_loop_sizing.setCentralCoolingDesignSupplyAirHumidityRatio(0.0085)
|
2526
|
-
air_loop_sizing.setCentralHeatingDesignSupplyAirHumidityRatio(0.0080)
|
2527
|
-
air_loop_sizing.setCoolingDesignAirFlowMethod('DesignDay')
|
2528
|
-
air_loop_sizing.setCoolingDesignAirFlowRate(0.0)
|
2529
|
-
air_loop_sizing.setHeatingDesignAirFlowMethod('DesignDay')
|
2530
|
-
air_loop_sizing.setHeatingDesignAirFlowRate(0.0)
|
2531
|
-
air_loop_sizing.setSystemOutdoorAirMethod('ZoneSum')
|
2478
|
+
# default design temperatures used across all air loops
|
2479
|
+
dsgn_temps = standard_design_sizing_temperatures
|
2532
2480
|
|
2533
|
-
# zone
|
2534
|
-
|
2535
|
-
|
2536
|
-
|
2481
|
+
# adjusted zone design heating temperature for psz_vav
|
2482
|
+
dsgn_temps['htg_dsgn_sup_air_temp_f'] = dsgn_temps['zn_htg_dsgn_sup_air_temp_f']
|
2483
|
+
dsgn_temps['htg_dsgn_sup_air_temp_c'] = dsgn_temps['zn_htg_dsgn_sup_air_temp_c']
|
2484
|
+
|
2485
|
+
# default design settings used across all air loops
|
2486
|
+
sizing_system = adjust_sizing_system(air_loop, dsgn_temps)
|
2537
2487
|
|
2488
|
+
# air handler controls
|
2538
2489
|
# add a setpoint manager single zone reheat to control the supply air temperature
|
2539
2490
|
setpoint_mgr_single_zone_reheat = OpenStudio::Model::SetpointManagerSingleZoneReheat.new(model)
|
2491
|
+
setpoint_mgr_single_zone_reheat.setName("#{zone.name} Setpoint Manager SZ Reheat")
|
2540
2492
|
setpoint_mgr_single_zone_reheat.setControlZone(zone)
|
2493
|
+
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
2494
|
+
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
2495
|
+
setpoint_mgr_single_zone_reheat.addToNode(air_loop.supplyOutletNode)
|
2496
|
+
|
2497
|
+
# zone sizing
|
2498
|
+
sizing_zone = zone.sizingZone
|
2499
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
2500
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
2541
2501
|
|
2542
2502
|
# create fan
|
2543
2503
|
# @type [OpenStudio::Model::FanVariableVolume] fan
|
@@ -2550,9 +2510,11 @@ class Standard
|
|
2550
2510
|
# create heating coil
|
2551
2511
|
case heating_type
|
2552
2512
|
when 'NaturalGas', 'Gas'
|
2553
|
-
htg_coil = create_coil_heating_gas(model,
|
2513
|
+
htg_coil = create_coil_heating_gas(model,
|
2514
|
+
name: "#{air_loop.name} Gas Htg Coil")
|
2554
2515
|
when 'Electricity', 'Electric'
|
2555
|
-
htg_coil = create_coil_heating_electric(model,
|
2516
|
+
htg_coil = create_coil_heating_electric(model,
|
2517
|
+
name: "#{air_loop.name} Electric Htg Coil")
|
2556
2518
|
else
|
2557
2519
|
# Zero-capacity, always-off electric heating coil
|
2558
2520
|
htg_coil = create_coil_heating_electric(model,
|
@@ -2564,9 +2526,11 @@ class Standard
|
|
2564
2526
|
# create supplemental heating coil
|
2565
2527
|
case supplemental_heating_type
|
2566
2528
|
when 'Electricity', 'Electric'
|
2567
|
-
supplemental_htg_coil = create_coil_heating_electric(model,
|
2529
|
+
supplemental_htg_coil = create_coil_heating_electric(model,
|
2530
|
+
name: "#{air_loop.name} Electric Backup Htg Coil")
|
2568
2531
|
when 'NaturalGas', 'Gas'
|
2569
|
-
supplemental_htg_coil = create_coil_heating_gas(model,
|
2532
|
+
supplemental_htg_coil = create_coil_heating_gas(model,
|
2533
|
+
name: "#{air_loop.name} Gas Backup Htg Coil")
|
2570
2534
|
else
|
2571
2535
|
# zero-capacity, always-off electric heating coil
|
2572
2536
|
supplemental_htg_coil = create_coil_heating_electric(model,
|
@@ -2578,7 +2542,7 @@ class Standard
|
|
2578
2542
|
# create cooling coil
|
2579
2543
|
clg_coil = OpenStudio::Model::CoilCoolingDXVariableSpeed.new(model)
|
2580
2544
|
clg_coil.setName("#{air_loop.name} Var spd DX AC Clg Coil")
|
2581
|
-
clg_coil.setBasinHeaterCapacity(10)
|
2545
|
+
clg_coil.setBasinHeaterCapacity(10.0)
|
2582
2546
|
clg_coil.setBasinHeaterSetpointTemperature(2.0)
|
2583
2547
|
# first speed level
|
2584
2548
|
clg_spd_1 = OpenStudio::Model::CoilCoolingDXVariableSpeedSpeedData.new(model)
|
@@ -2597,7 +2561,7 @@ class Standard
|
|
2597
2561
|
unitary_system.setName("#{zone.name} Unitary PSZ-VAV")
|
2598
2562
|
unitary_system.setString(2, 'SingleZoneVAV') # TODO: add setControlType() method
|
2599
2563
|
unitary_system.setControllingZoneorThermostatLocation(zone)
|
2600
|
-
unitary_system.setMaximumSupplyAirTemperature(
|
2564
|
+
unitary_system.setMaximumSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
2601
2565
|
unitary_system.setFanPlacement('BlowThrough')
|
2602
2566
|
unitary_system.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
|
2603
2567
|
unitary_system.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
|
@@ -2694,46 +2658,36 @@ class Standard
|
|
2694
2658
|
air_loop.setName("#{zone.name} #{system_name}")
|
2695
2659
|
end
|
2696
2660
|
|
2697
|
-
#
|
2698
|
-
|
2699
|
-
|
2700
|
-
|
2701
|
-
|
2702
|
-
|
2703
|
-
|
2704
|
-
|
2705
|
-
|
2706
|
-
|
2707
|
-
|
2708
|
-
|
2709
|
-
|
2710
|
-
|
2711
|
-
|
2712
|
-
|
2713
|
-
|
2714
|
-
|
2715
|
-
|
2716
|
-
|
2717
|
-
|
2661
|
+
# default design temperatures across all air loops
|
2662
|
+
dsgn_temps = standard_design_sizing_temperatures
|
2663
|
+
unless hot_water_loop.nil?
|
2664
|
+
hw_temp_c = hot_water_loop.sizingPlant.designLoopExitTemperature
|
2665
|
+
hw_delta_t_k = hot_water_loop.sizingPlant.loopDesignTemperatureDifference
|
2666
|
+
end
|
2667
|
+
|
2668
|
+
# adjusted zone design heating temperature for data center psz_ac
|
2669
|
+
dsgn_temps['htg_dsgn_sup_air_temp_f'] = dsgn_temps['zn_htg_dsgn_sup_air_temp_f']
|
2670
|
+
dsgn_temps['htg_dsgn_sup_air_temp_c'] = dsgn_temps['zn_htg_dsgn_sup_air_temp_c']
|
2671
|
+
|
2672
|
+
# default design settings used across all air loops
|
2673
|
+
sizing_system = adjust_sizing_system(air_loop, dsgn_temps, min_sys_airflow_ratio: 1.0)
|
2674
|
+
|
2675
|
+
# air handler controls
|
2676
|
+
# add a setpoint manager single zone reheat to control the supply air temperature
|
2677
|
+
setpoint_mgr_single_zone_reheat = OpenStudio::Model::SetpointManagerSingleZoneReheat.new(model)
|
2678
|
+
setpoint_mgr_single_zone_reheat.setName("#{zone.name} Setpoint Manager SZ Reheat")
|
2679
|
+
setpoint_mgr_single_zone_reheat.setControlZone(zone)
|
2680
|
+
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
2681
|
+
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
2682
|
+
setpoint_mgr_single_zone_reheat.addToNode(air_loop.supplyOutletNode)
|
2718
2683
|
|
2719
2684
|
# zone sizing
|
2720
2685
|
sizing_zone = zone.sizingZone
|
2721
|
-
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(
|
2722
|
-
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(
|
2686
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
2687
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
2723
2688
|
|
2724
2689
|
# add the components to the air loop in order from closest to zone to furthest from zone
|
2725
2690
|
if main_data_center
|
2726
|
-
|
2727
|
-
# control temps used across all air handlers
|
2728
|
-
unless hot_water_loop.nil?
|
2729
|
-
hw_temp_c = hot_water_loop.sizingPlant.designLoopExitTemperature
|
2730
|
-
hw_delta_t_k = hot_water_loop.sizingPlant.loopDesignTemperatureDifference
|
2731
|
-
end
|
2732
|
-
prehtg_sa_temp_f = 44.6 # Preheat to 44.6F
|
2733
|
-
htg_sa_temp_f = 55.0 # Central deck htg temp 55F
|
2734
|
-
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f, 'F', 'C').get
|
2735
|
-
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f, 'F', 'C').get
|
2736
|
-
|
2737
2691
|
# extra water heating coil
|
2738
2692
|
create_coil_heating_water(model,
|
2739
2693
|
hot_water_loop,
|
@@ -2741,8 +2695,9 @@ class Standard
|
|
2741
2695
|
name: "#{air_loop.name} Water Htg Coil",
|
2742
2696
|
rated_inlet_water_temperature: hw_temp_c,
|
2743
2697
|
rated_outlet_water_temperature: (hw_temp_c - hw_delta_t_k),
|
2744
|
-
rated_inlet_air_temperature:
|
2745
|
-
rated_outlet_air_temperature:
|
2698
|
+
rated_inlet_air_temperature: dsgn_temps['prehtg_dsgn_sup_air_temp_c'],
|
2699
|
+
rated_outlet_air_temperature: dsgn_temps['htg_dsgn_sup_air_temp_c'])
|
2700
|
+
|
2746
2701
|
# extra electric heating coil
|
2747
2702
|
create_coil_heating_electric(model,
|
2748
2703
|
air_loop_node: air_loop.supplyInletNode,
|
@@ -2764,13 +2719,20 @@ class Standard
|
|
2764
2719
|
|
2765
2720
|
# create fan
|
2766
2721
|
# @type [OpenStudio::Model::FanConstantVolume]
|
2767
|
-
fan = create_fan_by_name(model,
|
2722
|
+
fan = create_fan_by_name(model,
|
2723
|
+
'Packaged_RTU_SZ_AC_Cycling_Fan',
|
2724
|
+
fan_name: "#{air_loop.name} Fan")
|
2768
2725
|
fan.setAvailabilitySchedule(hvac_op_sch)
|
2769
2726
|
|
2770
2727
|
# create heating and cooling coils
|
2771
|
-
htg_coil = create_coil_heating_water_to_air_heat_pump_equation_fit(model,
|
2772
|
-
|
2773
|
-
|
2728
|
+
htg_coil = create_coil_heating_water_to_air_heat_pump_equation_fit(model,
|
2729
|
+
heat_pump_loop,
|
2730
|
+
name: "#{air_loop.name} Water-to-Air HP Htg Coil")
|
2731
|
+
clg_coil = create_coil_cooling_water_to_air_heat_pump_equation_fit(model,
|
2732
|
+
heat_pump_loop,
|
2733
|
+
name: "#{air_loop.name} Water-to-Air HP Clg Coil")
|
2734
|
+
supplemental_htg_coil = create_coil_heating_electric(model,
|
2735
|
+
name: "#{air_loop.name} Electric Backup Htg Coil")
|
2774
2736
|
|
2775
2737
|
# wrap fan and coils in a unitary system object
|
2776
2738
|
unitary_system = OpenStudio::Model::AirLoopHVACUnitarySystem.new(model)
|
@@ -2796,13 +2758,6 @@ class Standard
|
|
2796
2758
|
oa_system.setName("#{air_loop.name} OA System")
|
2797
2759
|
oa_system.addToNode(air_loop.supplyInletNode)
|
2798
2760
|
|
2799
|
-
# add a setpoint manager single zone reheat to control the supply air temperature
|
2800
|
-
setpoint_mgr_single_zone_reheat = OpenStudio::Model::SetpointManagerSingleZoneReheat.new(model)
|
2801
|
-
setpoint_mgr_single_zone_reheat.setControlZone(zone)
|
2802
|
-
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(OpenStudio.convert(55.0, 'F', 'C').get)
|
2803
|
-
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(OpenStudio.convert(104.0, 'F', 'C').get)
|
2804
|
-
setpoint_mgr_single_zone_reheat.addToNode(air_loop.supplyOutletNode)
|
2805
|
-
|
2806
2761
|
# set air loop availability controls and night cycle manager, after oa system added
|
2807
2762
|
air_loop.setAvailabilitySchedule(hvac_op_sch)
|
2808
2763
|
air_loop.setNightCycleControlType('CycleOnAny')
|
@@ -2839,6 +2794,11 @@ class Standard
|
|
2839
2794
|
oa_damper_sch: nil,
|
2840
2795
|
econ_max_oa_frac_sch: nil)
|
2841
2796
|
|
2797
|
+
# create a split AC for each group of thermal zones
|
2798
|
+
air_loop = OpenStudio::Model::AirLoopHVAC.new(model)
|
2799
|
+
thermal_zones_name = (thermal_zones.map { |z| z.name }).join(' - ')
|
2800
|
+
air_loop.setName("#{thermal_zones_name} SAC")
|
2801
|
+
|
2842
2802
|
# hvac operation schedule
|
2843
2803
|
if hvac_op_sch.nil?
|
2844
2804
|
hvac_op_sch = model.alwaysOnDiscreteSchedule
|
@@ -2853,33 +2813,26 @@ class Standard
|
|
2853
2813
|
oa_damper_sch = model_add_schedule(model, oa_damper_sch)
|
2854
2814
|
end
|
2855
2815
|
|
2856
|
-
#
|
2857
|
-
|
2858
|
-
|
2859
|
-
|
2860
|
-
|
2816
|
+
# default design temperatures used across all air loops
|
2817
|
+
dsgn_temps = standard_design_sizing_temperatures
|
2818
|
+
|
2819
|
+
# adjusted zone design heating temperature for split_ac
|
2820
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_f'] = 122.0
|
2821
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['zn_htg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
2822
|
+
dsgn_temps['htg_dsgn_sup_air_temp_f'] = dsgn_temps['zn_htg_dsgn_sup_air_temp_f']
|
2823
|
+
dsgn_temps['htg_dsgn_sup_air_temp_c'] = dsgn_temps['zn_htg_dsgn_sup_air_temp_c']
|
2861
2824
|
|
2862
|
-
#
|
2863
|
-
|
2864
|
-
|
2865
|
-
|
2866
|
-
|
2867
|
-
|
2868
|
-
|
2869
|
-
|
2870
|
-
|
2871
|
-
|
2872
|
-
|
2873
|
-
air_loop_sizing.setSizingOption('NonCoincident')
|
2874
|
-
air_loop_sizing.setAllOutdoorAirinCooling(false)
|
2875
|
-
air_loop_sizing.setAllOutdoorAirinHeating(false)
|
2876
|
-
air_loop_sizing.setCentralCoolingDesignSupplyAirHumidityRatio(0.008)
|
2877
|
-
air_loop_sizing.setCentralHeatingDesignSupplyAirHumidityRatio(0.0080)
|
2878
|
-
air_loop_sizing.setCoolingDesignAirFlowMethod('DesignDay')
|
2879
|
-
air_loop_sizing.setCoolingDesignAirFlowRate(0.0)
|
2880
|
-
air_loop_sizing.setHeatingDesignAirFlowMethod('DesignDay')
|
2881
|
-
air_loop_sizing.setHeatingDesignAirFlowRate(0.0)
|
2882
|
-
air_loop_sizing.setSystemOutdoorAirMethod('ZoneSum')
|
2825
|
+
# default design settings used across all air loops
|
2826
|
+
sizing_system = adjust_sizing_system(air_loop, dsgn_temps, min_sys_airflow_ratio: 1.0, sizing_option: 'NonCoincident')
|
2827
|
+
|
2828
|
+
# air handler controls
|
2829
|
+
# add a setpoint manager single zone reheat to control the supply air temperature
|
2830
|
+
setpoint_mgr_single_zone_reheat = OpenStudio::Model::SetpointManagerSingleZoneReheat.new(model)
|
2831
|
+
setpoint_mgr_single_zone_reheat.setName("#{air_loop.name} Setpoint Manager SZ Reheat")
|
2832
|
+
setpoint_mgr_single_zone_reheat.setControlZone(thermal_zones[0])
|
2833
|
+
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
2834
|
+
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
2835
|
+
setpoint_mgr_single_zone_reheat.addToNode(air_loop.supplyOutletNode)
|
2883
2836
|
|
2884
2837
|
# add the components to the air loop in order from closest to zone to furthest from zone
|
2885
2838
|
# create fan
|
@@ -2957,14 +2910,8 @@ class Standard
|
|
2957
2910
|
oa_system.setName("#{air_loop.name} OA System")
|
2958
2911
|
oa_system.addToNode(air_loop.supplyInletNode)
|
2959
2912
|
|
2960
|
-
#
|
2961
|
-
|
2962
|
-
setpoint_mgr_single_zone_reheat.setName("#{air_loop.name} Setpoint Manager SZ Reheat")
|
2963
|
-
control_zone = thermal_zones[0]
|
2964
|
-
setpoint_mgr_single_zone_reheat.setControlZone(control_zone)
|
2965
|
-
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(OpenStudio.convert(55.4, 'F', 'C').get)
|
2966
|
-
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(OpenStudio.convert(113.0, 'F', 'C').get)
|
2967
|
-
setpoint_mgr_single_zone_reheat.addToNode(air_loop.supplyOutletNode)
|
2913
|
+
# set air loop availability controls after oa system added
|
2914
|
+
air_loop.setAvailabilitySchedule(hvac_op_sch)
|
2968
2915
|
|
2969
2916
|
# create a diffuser and attach the zone/diffuser pair to the air loop
|
2970
2917
|
thermal_zones.each do |zone|
|
@@ -2976,8 +2923,8 @@ class Standard
|
|
2976
2923
|
|
2977
2924
|
# zone sizing
|
2978
2925
|
sizing_zone = zone.sizingZone
|
2979
|
-
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(
|
2980
|
-
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(
|
2926
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
2927
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
2981
2928
|
sizing_zone.setZoneCoolingDesignSupplyAirHumidityRatio(0.008)
|
2982
2929
|
sizing_zone.setZoneHeatingDesignSupplyAirHumidityRatio(0.008)
|
2983
2930
|
end
|
@@ -3000,6 +2947,19 @@ class Standard
|
|
3000
2947
|
hot_water_loop: nil,
|
3001
2948
|
fan_type: 'ConstantVolume')
|
3002
2949
|
|
2950
|
+
# default design temperatures used across all air loops
|
2951
|
+
dsgn_temps = standard_design_sizing_temperatures
|
2952
|
+
unless hot_water_loop.nil?
|
2953
|
+
hw_temp_c = hot_water_loop.sizingPlant.designLoopExitTemperature
|
2954
|
+
hw_delta_t_k = hot_water_loop.sizingPlant.loopDesignTemperatureDifference
|
2955
|
+
end
|
2956
|
+
|
2957
|
+
# adjusted zone design temperatures for ptac
|
2958
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_f'] = 122.0
|
2959
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['zn_htg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
2960
|
+
dsgn_temps['zn_clg_dsgn_sup_air_temp_f'] = 57.0
|
2961
|
+
dsgn_temps['zn_clg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['zn_clg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
2962
|
+
|
3003
2963
|
# make a PTAC for each zone
|
3004
2964
|
ptacs = []
|
3005
2965
|
thermal_zones.each do |zone|
|
@@ -3007,17 +2967,21 @@ class Standard
|
|
3007
2967
|
|
3008
2968
|
# zone sizing
|
3009
2969
|
sizing_zone = zone.sizingZone
|
3010
|
-
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(
|
3011
|
-
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(
|
2970
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
2971
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
3012
2972
|
sizing_zone.setZoneCoolingDesignSupplyAirHumidityRatio(0.008)
|
3013
2973
|
sizing_zone.setZoneHeatingDesignSupplyAirHumidityRatio(0.008)
|
3014
2974
|
|
3015
2975
|
# add fan
|
3016
2976
|
if fan_type == 'ConstantVolume'
|
3017
|
-
fan = create_fan_by_name(model,
|
2977
|
+
fan = create_fan_by_name(model,
|
2978
|
+
'PTAC_CAV_Fan',
|
2979
|
+
fan_name: "#{zone.name} PTAC Fan")
|
3018
2980
|
fan.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
3019
2981
|
elsif fan_type == 'Cycling'
|
3020
|
-
fan = create_fan_by_name(model,
|
2982
|
+
fan = create_fan_by_name(model,
|
2983
|
+
'PTAC_Cycling_Fan',
|
2984
|
+
fan_name: "#{zone.name} PTAC Fan")
|
3021
2985
|
fan.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
3022
2986
|
else
|
3023
2987
|
OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', "ptac_fan_type of #{fan_type} is not recognized.")
|
@@ -3026,9 +2990,11 @@ class Standard
|
|
3026
2990
|
# add heating coil
|
3027
2991
|
case heating_type
|
3028
2992
|
when 'NaturalGas', 'Gas'
|
3029
|
-
htg_coil = create_coil_heating_gas(model,
|
2993
|
+
htg_coil = create_coil_heating_gas(model,
|
2994
|
+
name: "#{zone.name} PTAC Gas Htg Coil")
|
3030
2995
|
when 'Electricity', 'Electric'
|
3031
|
-
htg_coil = create_coil_heating_electric(model,
|
2996
|
+
htg_coil = create_coil_heating_electric(model,
|
2997
|
+
name: "#{zone.name} PTAC Electric Htg Coil")
|
3032
2998
|
when nil
|
3033
2999
|
htg_coil = create_coil_heating_electric(model,
|
3034
3000
|
name: "#{zone.name} PTAC No Heat",
|
@@ -3039,8 +3005,6 @@ class Standard
|
|
3039
3005
|
OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'No hot water plant loop supplied')
|
3040
3006
|
return false
|
3041
3007
|
end
|
3042
|
-
hw_temp_c = hot_water_loop.sizingPlant.designLoopExitTemperature
|
3043
|
-
hw_delta_t_k = hot_water_loop.sizingPlant.loopDesignTemperatureDifference
|
3044
3008
|
htg_coil = create_coil_heating_water(model,
|
3045
3009
|
hot_water_loop,
|
3046
3010
|
name: "#{hot_water_loop.name} Water Htg Coil",
|
@@ -3052,9 +3016,12 @@ class Standard
|
|
3052
3016
|
|
3053
3017
|
# add cooling coil
|
3054
3018
|
if cooling_type == 'Two Speed DX AC'
|
3055
|
-
clg_coil = create_coil_cooling_dx_two_speed(model,
|
3019
|
+
clg_coil = create_coil_cooling_dx_two_speed(model,
|
3020
|
+
name: "#{zone.name} PTAC 2spd DX AC Clg Coil")
|
3056
3021
|
elsif cooling_type == 'Single Speed DX AC'
|
3057
|
-
clg_coil = create_coil_cooling_dx_single_speed(model,
|
3022
|
+
clg_coil = create_coil_cooling_dx_single_speed(model,
|
3023
|
+
name: "#{zone.name} PTAC 1spd DX AC Clg Coil",
|
3024
|
+
type: 'PTAC')
|
3058
3025
|
else
|
3059
3026
|
OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', "ptac_cooling_type of #{cooling_type} is not recognized.")
|
3060
3027
|
end
|
@@ -3087,6 +3054,16 @@ class Standard
|
|
3087
3054
|
def model_add_pthp(model,
|
3088
3055
|
thermal_zones,
|
3089
3056
|
fan_type: 'Cycling')
|
3057
|
+
|
3058
|
+
# default design temperatures used across all air loops
|
3059
|
+
dsgn_temps = standard_design_sizing_temperatures
|
3060
|
+
|
3061
|
+
# adjusted zone design temperatures for pthp
|
3062
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_f'] = 122.0
|
3063
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['zn_htg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
3064
|
+
dsgn_temps['zn_clg_dsgn_sup_air_temp_f'] = 57.0
|
3065
|
+
dsgn_temps['zn_clg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['zn_clg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
3066
|
+
|
3090
3067
|
# make a PTHP for each zone
|
3091
3068
|
pthps = []
|
3092
3069
|
thermal_zones.each do |zone|
|
@@ -3094,17 +3071,21 @@ class Standard
|
|
3094
3071
|
|
3095
3072
|
# zone sizing
|
3096
3073
|
sizing_zone = zone.sizingZone
|
3097
|
-
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(
|
3098
|
-
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(
|
3074
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
3075
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
3099
3076
|
sizing_zone.setZoneCoolingDesignSupplyAirHumidityRatio(0.008)
|
3100
3077
|
sizing_zone.setZoneHeatingDesignSupplyAirHumidityRatio(0.008)
|
3101
3078
|
|
3102
3079
|
# add fan
|
3103
3080
|
if fan_type == 'ConstantVolume'
|
3104
|
-
fan = create_fan_by_name(model,
|
3081
|
+
fan = create_fan_by_name(model,
|
3082
|
+
'PTAC_CAV_Fan',
|
3083
|
+
fan_name: "#{zone.name} PTAC Fan")
|
3105
3084
|
fan.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
3106
3085
|
elsif fan_type == 'Cycling'
|
3107
|
-
fan = create_fan_by_name(model,
|
3086
|
+
fan = create_fan_by_name(model,
|
3087
|
+
'PTAC_Cycling_Fan',
|
3088
|
+
fan_name: "#{zone.name} PTAC Fan")
|
3108
3089
|
fan.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
3109
3090
|
else
|
3110
3091
|
OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', "PTHP fan_type of #{fan_type} is not recognized.")
|
@@ -3112,11 +3093,15 @@ class Standard
|
|
3112
3093
|
end
|
3113
3094
|
|
3114
3095
|
# add heating coil
|
3115
|
-
htg_coil = create_coil_heating_dx_single_speed(model,
|
3096
|
+
htg_coil = create_coil_heating_dx_single_speed(model,
|
3097
|
+
name: "#{zone.name} PTHP Htg Coil")
|
3116
3098
|
# add cooling coil
|
3117
|
-
clg_coil = create_coil_cooling_dx_single_speed(model,
|
3099
|
+
clg_coil = create_coil_cooling_dx_single_speed(model,
|
3100
|
+
name: "#{zone.name} PTHP Clg Coil",
|
3101
|
+
type: 'Heat Pump')
|
3118
3102
|
# supplemental heating coil
|
3119
|
-
supplemental_htg_coil = create_coil_heating_electric(model,
|
3103
|
+
supplemental_htg_coil = create_coil_heating_electric(model,
|
3104
|
+
name: "#{zone.name} PTHP Supplemental Htg Coil")
|
3120
3105
|
# wrap coils in a PTHP system
|
3121
3106
|
pthp_system = OpenStudio::Model::ZoneHVACPackagedTerminalHeatPump.new(model,
|
3122
3107
|
model.alwaysOnDiscreteSchedule,
|
@@ -3161,7 +3146,7 @@ class Standard
|
|
3161
3146
|
rated_inlet_water_temperature: 180.0,
|
3162
3147
|
rated_outlet_water_temperature: 160.0,
|
3163
3148
|
rated_inlet_air_temperature: 60.0,
|
3164
|
-
rated_outlet_air_temperature:
|
3149
|
+
rated_outlet_air_temperature: 104.0)
|
3165
3150
|
|
3166
3151
|
# hvac operation schedule
|
3167
3152
|
if hvac_op_sch.nil?
|
@@ -3174,6 +3159,13 @@ class Standard
|
|
3174
3159
|
fan_control_type = 'ConstantVolume' if fan_control_type.nil?
|
3175
3160
|
fan_pressure_rise = 0.2 if fan_pressure_rise.nil?
|
3176
3161
|
|
3162
|
+
# default design temperatures used across all air loops
|
3163
|
+
dsgn_temps = standard_design_sizing_temperatures
|
3164
|
+
|
3165
|
+
# adjusted zone design heating temperature for unit heater
|
3166
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_f'] = 122.0
|
3167
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['zn_htg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
3168
|
+
|
3177
3169
|
# make a unit heater for each zone
|
3178
3170
|
unit_heaters = []
|
3179
3171
|
thermal_zones.each do |zone|
|
@@ -3181,10 +3173,7 @@ class Standard
|
|
3181
3173
|
|
3182
3174
|
# zone sizing
|
3183
3175
|
sizing_zone = zone.sizingZone
|
3184
|
-
sizing_zone.
|
3185
|
-
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(50.0)
|
3186
|
-
sizing_zone.setZoneCoolingDesignSupplyAirHumidityRatio(0.008)
|
3187
|
-
sizing_zone.setZoneHeatingDesignSupplyAirHumidityRatio(0.008)
|
3176
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
3188
3177
|
|
3189
3178
|
# add fan
|
3190
3179
|
fan = create_fan_by_name(model,
|
@@ -3195,9 +3184,13 @@ class Standard
|
|
3195
3184
|
|
3196
3185
|
# add heating coil
|
3197
3186
|
if heating_type == 'NaturalGas' || heating_type == 'Gas'
|
3198
|
-
htg_coil = create_coil_heating_gas(model,
|
3187
|
+
htg_coil = create_coil_heating_gas(model,
|
3188
|
+
name: "#{zone.name} UnitHeater Gas Htg Coil",
|
3189
|
+
schedule: hvac_op_sch)
|
3199
3190
|
elsif heating_type == 'Electricity' || heating_type == 'Electric'
|
3200
|
-
htg_coil = create_coil_heating_electric(model,
|
3191
|
+
htg_coil = create_coil_heating_electric(model,
|
3192
|
+
name: "#{zone.name} UnitHeater Electric Htg Coil",
|
3193
|
+
schedule: hvac_op_sch)
|
3201
3194
|
elsif heating_type == 'DistrictHeating' && !hot_water_loop.nil?
|
3202
3195
|
# control temperature for hot water loop
|
3203
3196
|
if rated_inlet_water_temperature.nil?
|
@@ -3216,7 +3209,7 @@ class Standard
|
|
3216
3209
|
rated_inlet_air_temperature_c = OpenStudio.convert(rated_inlet_air_temperature, 'F', 'C').get
|
3217
3210
|
end
|
3218
3211
|
if rated_outlet_air_temperature.nil?
|
3219
|
-
rated_outlet_air_temperature_c = OpenStudio.convert(
|
3212
|
+
rated_outlet_air_temperature_c = OpenStudio.convert(104.0, 'F', 'C').get
|
3220
3213
|
else
|
3221
3214
|
rated_outlet_air_temperature_c = OpenStudio.convert(rated_outlet_air_temperature, 'F', 'C').get
|
3222
3215
|
end
|
@@ -3233,8 +3226,11 @@ class Standard
|
|
3233
3226
|
end
|
3234
3227
|
|
3235
3228
|
# create unit heater
|
3236
|
-
unit_heater = OpenStudio::Model::ZoneHVACUnitHeater.new(model,
|
3237
|
-
|
3229
|
+
unit_heater = OpenStudio::Model::ZoneHVACUnitHeater.new(model,
|
3230
|
+
hvac_op_sch,
|
3231
|
+
fan,
|
3232
|
+
htg_coil)
|
3233
|
+
unit_heater.setName("#{zone.name} Unit Heater")
|
3238
3234
|
unit_heater.setFanControlType(fan_control_type)
|
3239
3235
|
unit_heater.addToThermalZone(zone)
|
3240
3236
|
unit_heaters << unit_heater
|
@@ -3300,19 +3296,16 @@ class Standard
|
|
3300
3296
|
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.Model.Model', "---#{zone.name}")
|
3301
3297
|
end
|
3302
3298
|
|
3303
|
-
#
|
3304
|
-
|
3305
|
-
clg_sa_temp_f = 70
|
3306
|
-
max_sa_temp_f = 78
|
3307
|
-
htg_sa_temp_f = 122 # Not used
|
3308
|
-
|
3309
|
-
min_sa_temp_c = OpenStudio.convert(min_sa_temp_f, 'F', 'C').get
|
3310
|
-
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f, 'F', 'C').get
|
3311
|
-
max_sa_temp_c = OpenStudio.convert(max_sa_temp_f, 'F', 'C').get
|
3312
|
-
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f, 'F', 'C').get
|
3299
|
+
# default design temperatures used across all air loops
|
3300
|
+
dsgn_temps = standard_design_sizing_temperatures
|
3313
3301
|
|
3314
|
-
|
3315
|
-
|
3302
|
+
# adjusted design temperatures for evap cooler
|
3303
|
+
dsgn_temps['clg_dsgn_sup_air_temp_f'] = 70.0
|
3304
|
+
dsgn_temps['clg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['clg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
3305
|
+
dsgn_temps['max_clg_dsgn_sup_air_temp_f'] = 78.0
|
3306
|
+
dsgn_temps['max_clg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['max_clg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
3307
|
+
dsgn_temps['approach_r'] = 3.0 # wetbulb approach temperature
|
3308
|
+
dsgn_temps['approach_k'] = OpenStudio.convert(dsgn_temps['approach_r'], 'R', 'K').get
|
3316
3309
|
|
3317
3310
|
# EMS programs
|
3318
3311
|
programs = []
|
@@ -3326,6 +3319,19 @@ class Standard
|
|
3326
3319
|
air_loop = OpenStudio::Model::AirLoopHVAC.new(model)
|
3327
3320
|
air_loop.setName("#{zone_name_clean} Evaporative Cooler")
|
3328
3321
|
|
3322
|
+
# default design settings used across all air loops
|
3323
|
+
sizing_system = adjust_sizing_system(air_loop, dsgn_temps)
|
3324
|
+
|
3325
|
+
# air handler controls
|
3326
|
+
# setpoint follows OAT WetBulb
|
3327
|
+
evap_stpt_manager = OpenStudio::Model::SetpointManagerFollowOutdoorAirTemperature.new(model)
|
3328
|
+
evap_stpt_manager.setName("#{dsgn_temps['approach_r']} F above OATwb")
|
3329
|
+
evap_stpt_manager.setReferenceTemperatureType('OutdoorAirWetBulb')
|
3330
|
+
evap_stpt_manager.setMaximumSetpointTemperature(dsgn_temps['max_clg_dsgn_sup_air_temp_c'])
|
3331
|
+
evap_stpt_manager.setMinimumSetpointTemperature(dsgn_temps['clg_dsgn_sup_air_temp_c'])
|
3332
|
+
evap_stpt_manager.setOffsetTemperatureDifference(dsgn_temps['approach_k'])
|
3333
|
+
evap_stpt_manager.addToNode(air_loop.supplyOutletNode)
|
3334
|
+
|
3329
3335
|
# Schedule to control the airloop availability
|
3330
3336
|
air_loop_avail_sch = OpenStudio::Model::ScheduleConstant.new(model)
|
3331
3337
|
air_loop_avail_sch.setName("#{air_loop.name} Availability Sch")
|
@@ -3336,12 +3342,15 @@ class Standard
|
|
3336
3342
|
# Without this EMS, the airloop runs 24/7-365 even when there is no load in the zone.
|
3337
3343
|
|
3338
3344
|
# Create a sensor to read the zone load
|
3339
|
-
zn_load_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model,
|
3345
|
+
zn_load_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model,
|
3346
|
+
'Zone Predicted Sensible Load to Cooling Setpoint Heat Transfer Rate')
|
3340
3347
|
zn_load_sensor.setName("#{zone_name_clean.to_s.gsub(/[ +-.]/,'_')} Clg Load Sensor")
|
3341
3348
|
zn_load_sensor.setKeyName(zone.handle.to_s)
|
3342
3349
|
|
3343
3350
|
# Create an actuator to set the airloop availability
|
3344
|
-
air_loop_avail_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(air_loop_avail_sch,
|
3351
|
+
air_loop_avail_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(air_loop_avail_sch,
|
3352
|
+
'Schedule:Constant',
|
3353
|
+
'Schedule Value')
|
3345
3354
|
air_loop_avail_actuator.setName("#{air_loop.name.to_s.gsub(/[ +-.]/,'_')} Availability Actuator")
|
3346
3355
|
|
3347
3356
|
# Create a program to turn on Evap Cooler if
|
@@ -3360,23 +3369,6 @@ class Standard
|
|
3360
3369
|
|
3361
3370
|
programs << avail_program
|
3362
3371
|
|
3363
|
-
# Setpoint follows OAT WetBulb
|
3364
|
-
evap_stpt_manager = OpenStudio::Model::SetpointManagerFollowOutdoorAirTemperature.new(model)
|
3365
|
-
evap_stpt_manager.setName("#{approach_r} F above OATwb")
|
3366
|
-
evap_stpt_manager.setReferenceTemperatureType('OutdoorAirWetBulb')
|
3367
|
-
evap_stpt_manager.setMaximumSetpointTemperature(max_sa_temp_c)
|
3368
|
-
evap_stpt_manager.setMinimumSetpointTemperature(min_sa_temp_c)
|
3369
|
-
evap_stpt_manager.setOffsetTemperatureDifference(approach_k)
|
3370
|
-
evap_stpt_manager.addToNode(air_loop.supplyOutletNode)
|
3371
|
-
|
3372
|
-
# Air handler sizing
|
3373
|
-
sizing_system = air_loop.sizingSystem
|
3374
|
-
sizing_system.setCentralCoolingDesignSupplyAirTemperature(clg_sa_temp_c)
|
3375
|
-
sizing_system.setCentralHeatingDesignSupplyAirTemperature(htg_sa_temp_c)
|
3376
|
-
sizing_system.setAllOutdoorAirinCooling(true)
|
3377
|
-
sizing_system.setAllOutdoorAirinHeating(true)
|
3378
|
-
sizing_system.setSystemOutdoorAirMethod('ZoneSum')
|
3379
|
-
|
3380
3372
|
# Direct Evap Cooler
|
3381
3373
|
# TODO: better assumptions for evap cooler performance and fan pressure rise
|
3382
3374
|
evap = OpenStudio::Model::EvaporativeCoolerDirectResearchSpecial.new(model, model.alwaysOnDiscreteSchedule)
|
@@ -3385,7 +3377,9 @@ class Standard
|
|
3385
3377
|
evap.addToNode(air_loop.supplyInletNode)
|
3386
3378
|
|
3387
3379
|
# Fan (cycling), must be inside unitary system to cycle on airloop
|
3388
|
-
fan = create_fan_by_name(model,
|
3380
|
+
fan = create_fan_by_name(model,
|
3381
|
+
'Evap_Cooler_Supply_Fan',
|
3382
|
+
fan_name: "#{zone.name} Evap Cooler Supply Fan")
|
3389
3383
|
fan.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
3390
3384
|
|
3391
3385
|
# Dummy zero-capacity cooling coil
|
@@ -3397,7 +3391,7 @@ class Standard
|
|
3397
3391
|
unitary_system.setSupplyFan(fan)
|
3398
3392
|
unitary_system.setCoolingCoil(clg_coil)
|
3399
3393
|
unitary_system.setControllingZoneorThermostatLocation(zone)
|
3400
|
-
unitary_system.setMaximumSupplyAirTemperature(
|
3394
|
+
unitary_system.setMaximumSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
3401
3395
|
unitary_system.setFanPlacement('BlowThrough')
|
3402
3396
|
unitary_system.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
|
3403
3397
|
unitary_system.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
|
@@ -3429,9 +3423,7 @@ class Standard
|
|
3429
3423
|
|
3430
3424
|
sizing_zone = zone.sizingZone
|
3431
3425
|
sizing_zone.setCoolingDesignAirFlowMethod('DesignDay')
|
3432
|
-
sizing_zone.
|
3433
|
-
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(clg_sa_temp_c)
|
3434
|
-
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(htg_sa_temp_c)
|
3426
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
3435
3427
|
|
3436
3428
|
evap_coolers << air_loop
|
3437
3429
|
end
|
@@ -3493,9 +3485,9 @@ class Standard
|
|
3493
3485
|
vrf_outdoor_unit = create_air_conditioner_variable_refrigerant_flow(model,
|
3494
3486
|
name: "#{thermal_zones.size} Zone VRF System",
|
3495
3487
|
master_zone: master_zone)
|
3496
|
-
|
3497
|
-
|
3498
|
-
|
3488
|
+
|
3489
|
+
# default design temperatures used across all air loops
|
3490
|
+
dsgn_temps = standard_design_sizing_temperatures
|
3499
3491
|
|
3500
3492
|
vrfs = []
|
3501
3493
|
thermal_zones.each do |zone|
|
@@ -3503,8 +3495,8 @@ class Standard
|
|
3503
3495
|
|
3504
3496
|
# zone sizing
|
3505
3497
|
sizing_zone = zone.sizingZone
|
3506
|
-
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(
|
3507
|
-
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(
|
3498
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
3499
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
3508
3500
|
|
3509
3501
|
# add vrf terminal unit
|
3510
3502
|
vrf_terminal_unit = OpenStudio::Model::ZoneHVACTerminalUnitVariableRefrigerantFlow.new(model)
|
@@ -3513,15 +3505,15 @@ class Standard
|
|
3513
3505
|
vrf_terminal_unit.setTerminalUnitAvailabilityschedule(model.alwaysOnDiscreteSchedule)
|
3514
3506
|
|
3515
3507
|
# no outdoor air assumed
|
3516
|
-
vrf_terminal_unit.setOutdoorAirFlowRateDuringCoolingOperation(0)
|
3517
|
-
vrf_terminal_unit.setOutdoorAirFlowRateDuringHeatingOperation(0)
|
3518
|
-
vrf_terminal_unit.setOutdoorAirFlowRateWhenNoCoolingorHeatingisNeeded(0)
|
3508
|
+
vrf_terminal_unit.setOutdoorAirFlowRateDuringCoolingOperation(0.0)
|
3509
|
+
vrf_terminal_unit.setOutdoorAirFlowRateDuringHeatingOperation(0.0)
|
3510
|
+
vrf_terminal_unit.setOutdoorAirFlowRateWhenNoCoolingorHeatingisNeeded(0.0)
|
3519
3511
|
|
3520
3512
|
# set fan variables
|
3521
3513
|
# always off denotes cycling fan
|
3522
3514
|
vrf_terminal_unit.setSupplyAirFanOperatingModeSchedule(model.alwaysOffDiscreteSchedule)
|
3523
3515
|
vrf_fan = vrf_terminal_unit.supplyAirFan.to_FanOnOff.get
|
3524
|
-
vrf_fan.setPressureRise(300)
|
3516
|
+
vrf_fan.setPressureRise(300.0)
|
3525
3517
|
vrf_fan.setMotorEfficiency(0.8)
|
3526
3518
|
vrf_fan.setFanEfficiency(0.6)
|
3527
3519
|
vrf_fan.setName("#{zone.name} VRF Unit Cycling Fan")
|
@@ -3548,17 +3540,16 @@ class Standard
|
|
3548
3540
|
hot_water_loop: nil,
|
3549
3541
|
ventilation: false)
|
3550
3542
|
|
3551
|
-
#
|
3552
|
-
|
3553
|
-
zn_dsn_htg_sa_temp_c = OpenStudio.convert(104.0, 'F', 'C').get
|
3543
|
+
# default design temperatures used across all air loops
|
3544
|
+
dsgn_temps = standard_design_sizing_temperatures
|
3554
3545
|
|
3555
3546
|
# make a fan coil unit for each zone
|
3556
3547
|
fcus = []
|
3557
3548
|
thermal_zones.each do |zone|
|
3558
3549
|
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding fan coil for #{zone.name}.")
|
3559
|
-
|
3560
|
-
|
3561
|
-
|
3550
|
+
sizing_zone = zone.sizingZone
|
3551
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(dsgn_temps['zn_clg_dsgn_sup_air_temp_c'])
|
3552
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
3562
3553
|
|
3563
3554
|
if chilled_water_loop
|
3564
3555
|
fcu_clg_coil = create_coil_cooling_water(model,
|
@@ -3573,7 +3564,7 @@ class Standard
|
|
3573
3564
|
fcu_htg_coil = create_coil_heating_water(model,
|
3574
3565
|
hot_water_loop,
|
3575
3566
|
name: "#{zone.name} FCU Heating Coil",
|
3576
|
-
rated_outlet_air_temperature:
|
3567
|
+
rated_outlet_air_temperature: dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
3577
3568
|
else
|
3578
3569
|
# Zero-capacity, always-off electric heating coil
|
3579
3570
|
fcu_htg_coil = create_coil_heating_electric(model,
|
@@ -3645,7 +3636,11 @@ class Standard
|
|
3645
3636
|
name: "#{zone.name} Window AC Always Off Htg Coil",
|
3646
3637
|
schedule: model.alwaysOffDiscreteSchedule,
|
3647
3638
|
nominal_capacity: 0)
|
3648
|
-
ptac = OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner.new(model,
|
3639
|
+
ptac = OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner.new(model,
|
3640
|
+
model.alwaysOnDiscreteSchedule,
|
3641
|
+
fan,
|
3642
|
+
htg_coil,
|
3643
|
+
clg_coil)
|
3649
3644
|
ptac.setName("#{zone.name} Window AC")
|
3650
3645
|
ptac.setSupplyAirFanOperatingModeSchedule(model.alwaysOffDiscreteSchedule)
|
3651
3646
|
ptac.addToThermalZone(zone)
|
@@ -3697,6 +3692,21 @@ class Standard
|
|
3697
3692
|
air_loop.setName("#{zone.name} #{equip_name}")
|
3698
3693
|
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding furnace AC for #{zone.name}.")
|
3699
3694
|
|
3695
|
+
|
3696
|
+
# default design temperatures across all air loops
|
3697
|
+
dsgn_temps = standard_design_sizing_temperatures
|
3698
|
+
|
3699
|
+
# adjusted temperatures for furnace_central_ac
|
3700
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_f'] = 122.0
|
3701
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['zn_htg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
3702
|
+
dsgn_temps['htg_dsgn_sup_air_temp_f'] = dsgn_temps['zn_htg_dsgn_sup_air_temp_f']
|
3703
|
+
dsgn_temps['htg_dsgn_sup_air_temp_c'] = dsgn_temps['zn_htg_dsgn_sup_air_temp_c']
|
3704
|
+
|
3705
|
+
# default design settings used across all air loops
|
3706
|
+
sizing_system = adjust_sizing_system(air_loop, dsgn_temps, sizing_option: 'NonCoincident')
|
3707
|
+
sizing_system.setAllOutdoorAirinCooling(true)
|
3708
|
+
sizing_system.setAllOutdoorAirinHeating(true)
|
3709
|
+
|
3700
3710
|
# create heating coil
|
3701
3711
|
htg_coil = nil
|
3702
3712
|
if heating
|
@@ -3726,7 +3736,7 @@ class Standard
|
|
3726
3736
|
# create fan
|
3727
3737
|
fan = create_fan_by_name(model,
|
3728
3738
|
'Residential_HVAC_Fan',
|
3729
|
-
fan_name: "#{air_loop.name}
|
3739
|
+
fan_name: "#{air_loop.name} Supply Fan",
|
3730
3740
|
end_use_subcategory: 'Residential HVAC Fans')
|
3731
3741
|
fan.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
3732
3742
|
|
@@ -3743,9 +3753,9 @@ class Standard
|
|
3743
3753
|
|
3744
3754
|
# create unitary system (holds the coils and fan)
|
3745
3755
|
unitary = OpenStudio::Model::AirLoopHVACUnitarySystem.new(model)
|
3746
|
-
unitary.setName("#{air_loop.name}
|
3756
|
+
unitary.setName("#{air_loop.name} Unitary System")
|
3747
3757
|
unitary.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
3748
|
-
unitary.setMaximumSupplyAirTemperature(
|
3758
|
+
unitary.setMaximumSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
|
3749
3759
|
unitary.setControllingZoneorThermostatLocation(zone)
|
3750
3760
|
unitary.addToNode(air_loop.supplyInletNode)
|
3751
3761
|
|
@@ -3763,7 +3773,7 @@ class Standard
|
|
3763
3773
|
|
3764
3774
|
# create a diffuser
|
3765
3775
|
diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, model.alwaysOnDiscreteSchedule)
|
3766
|
-
diffuser.setName("#{zone.name}
|
3776
|
+
diffuser.setName("#{zone.name} Direct Air")
|
3767
3777
|
air_loop.addBranchForZone(zone, diffuser)
|
3768
3778
|
|
3769
3779
|
furnaces << air_loop
|
@@ -3804,6 +3814,20 @@ class Standard
|
|
3804
3814
|
air_loop = OpenStudio::Model::AirLoopHVAC.new(model)
|
3805
3815
|
air_loop.setName("#{zone.name} Central Air Source HP")
|
3806
3816
|
|
3817
|
+
# default design temperatures across all air loops
|
3818
|
+
dsgn_temps = standard_design_sizing_temperatures
|
3819
|
+
|
3820
|
+
# adjusted temperatures for furnace_central_ac
|
3821
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_f'] = 122.0
|
3822
|
+
dsgn_temps['zn_htg_dsgn_sup_air_temp_c'] = OpenStudio.convert(dsgn_temps['zn_htg_dsgn_sup_air_temp_f'], 'F', 'C').get
|
3823
|
+
dsgn_temps['htg_dsgn_sup_air_temp_f'] = dsgn_temps['zn_htg_dsgn_sup_air_temp_f']
|
3824
|
+
dsgn_temps['htg_dsgn_sup_air_temp_c'] = dsgn_temps['zn_htg_dsgn_sup_air_temp_c']
|
3825
|
+
|
3826
|
+
# default design settings used across all air loops
|
3827
|
+
sizing_system = adjust_sizing_system(air_loop, dsgn_temps, sizing_option: 'NonCoincident')
|
3828
|
+
sizing_system.setAllOutdoorAirinCooling(true)
|
3829
|
+
sizing_system.setAllOutdoorAirinHeating(true)
|
3830
|
+
|
3807
3831
|
# create heating coil
|
3808
3832
|
htg_coil = nil
|
3809
3833
|
supplemental_htg_coil = nil
|
@@ -3824,14 +3848,15 @@ class Standard
|
|
3824
3848
|
# Supplemental Heating Coil
|
3825
3849
|
|
3826
3850
|
# create supplemental heating coil
|
3827
|
-
supplemental_htg_coil = create_coil_heating_electric(model,
|
3851
|
+
supplemental_htg_coil = create_coil_heating_electric(model,
|
3852
|
+
name: "#{air_loop.name} Supplemental Htg Coil")
|
3828
3853
|
end
|
3829
3854
|
|
3830
3855
|
# create cooling coil
|
3831
3856
|
clg_coil = nil
|
3832
3857
|
if cooling
|
3833
3858
|
clg_coil = create_coil_cooling_dx_single_speed(model,
|
3834
|
-
name: "#{air_loop.name}
|
3859
|
+
name: "#{air_loop.name} Cooling Coil",
|
3835
3860
|
type: 'Residential Central ASHP',
|
3836
3861
|
cop: cop)
|
3837
3862
|
clg_coil.setRatedSensibleHeatRatio(shr)
|
@@ -3848,7 +3873,7 @@ class Standard
|
|
3848
3873
|
# create fan
|
3849
3874
|
fan = create_fan_by_name(model,
|
3850
3875
|
'Residential_HVAC_Fan',
|
3851
|
-
fan_name: "#{air_loop.name}
|
3876
|
+
fan_name: "#{air_loop.name} Supply Fan",
|
3852
3877
|
end_use_subcategory: 'Residential HVAC Fans')
|
3853
3878
|
fan.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
3854
3879
|
|
@@ -3865,7 +3890,7 @@ class Standard
|
|
3865
3890
|
|
3866
3891
|
# create unitary system (holds the coils and fan)
|
3867
3892
|
unitary = OpenStudio::Model::AirLoopHVACUnitarySystem.new(model)
|
3868
|
-
unitary.setName("#{air_loop.name}
|
3893
|
+
unitary.setName("#{air_loop.name} Unitary System")
|
3869
3894
|
unitary.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
3870
3895
|
unitary.setMaximumSupplyAirTemperature(OpenStudio.convert(170.0, 'F', 'C').get) # higher temp for supplemental heat as to not severely limit its use, resulting in unmet hours.
|
3871
3896
|
unitary.setMaximumOutdoorDryBulbTemperatureforSupplementalHeaterOperation(OpenStudio.convert(40.0, 'F', 'C').get)
|
@@ -3885,7 +3910,7 @@ class Standard
|
|
3885
3910
|
|
3886
3911
|
# create a diffuser
|
3887
3912
|
diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, model.alwaysOnDiscreteSchedule)
|
3888
|
-
diffuser.setName(" #{zone.name}
|
3913
|
+
diffuser.setName(" #{zone.name} Direct Air")
|
3889
3914
|
air_loop.addBranchForZone(zone, diffuser)
|
3890
3915
|
|
3891
3916
|
hps << air_loop
|
@@ -3910,15 +3935,27 @@ class Standard
|
|
3910
3935
|
|
3911
3936
|
water_to_air_hp_systems = []
|
3912
3937
|
thermal_zones.each do |zone|
|
3913
|
-
supplemental_htg_coil = create_coil_heating_electric(model,
|
3914
|
-
|
3915
|
-
|
3938
|
+
supplemental_htg_coil = create_coil_heating_electric(model,
|
3939
|
+
name: "#{zone.name} Supplemental Htg Coil")
|
3940
|
+
htg_coil = create_coil_heating_water_to_air_heat_pump_equation_fit(model,
|
3941
|
+
condenser_loop,
|
3942
|
+
name: "#{zone.name} Water-to-Air HP Htg Coil")
|
3943
|
+
clg_coil = create_coil_cooling_water_to_air_heat_pump_equation_fit(model,
|
3944
|
+
condenser_loop,
|
3945
|
+
name: "#{zone.name} Water-to-Air HP Clg Coil")
|
3916
3946
|
|
3917
3947
|
# add fan
|
3918
|
-
fan = create_fan_by_name(model,
|
3948
|
+
fan = create_fan_by_name(model,
|
3949
|
+
'WSHP_Fan',
|
3950
|
+
fan_name: "#{zone.name} WSHP Fan")
|
3919
3951
|
fan.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
3920
3952
|
|
3921
|
-
water_to_air_hp_system = OpenStudio::Model::ZoneHVACWaterToAirHeatPump.new(model,
|
3953
|
+
water_to_air_hp_system = OpenStudio::Model::ZoneHVACWaterToAirHeatPump.new(model,
|
3954
|
+
model.alwaysOnDiscreteSchedule,
|
3955
|
+
fan,
|
3956
|
+
htg_coil,
|
3957
|
+
clg_coil,
|
3958
|
+
supplemental_htg_coil)
|
3922
3959
|
water_to_air_hp_system.setName("#{zone.name} WSHP")
|
3923
3960
|
unless ventilation
|
3924
3961
|
water_to_air_hp_system.setOutdoorAirFlowRateDuringHeatingOperation(OpenStudio::OptionalDouble.new(0.0))
|
@@ -3946,10 +3983,14 @@ class Standard
|
|
3946
3983
|
|
3947
3984
|
# Determine the OA requirement for this zone
|
3948
3985
|
min_oa_flow_m3_per_s_per_m2 = thermal_zone_outdoor_airflow_rate_per_area(zone)
|
3949
|
-
supply_fan = create_fan_by_name(model,
|
3986
|
+
supply_fan = create_fan_by_name(model,
|
3987
|
+
'ERV_Supply_Fan',
|
3988
|
+
fan_name: "#{zone.name} ERV Supply Fan")
|
3950
3989
|
impeller_eff = fan_baseline_impeller_efficiency(supply_fan)
|
3951
3990
|
fan_change_impeller_efficiency(supply_fan, impeller_eff)
|
3952
|
-
exhaust_fan = create_fan_by_name(model,
|
3991
|
+
exhaust_fan = create_fan_by_name(model,
|
3992
|
+
'ERV_Supply_Fan',
|
3993
|
+
fan_name: "#{zone.name} ERV Exhaust Fan")
|
3953
3994
|
fan_change_impeller_efficiency(exhaust_fan, impeller_eff)
|
3954
3995
|
|
3955
3996
|
erv_controller = OpenStudio::Model::ZoneHVACEnergyRecoveryVentilatorController.new(model)
|
@@ -4006,11 +4047,11 @@ class Standard
|
|
4006
4047
|
hottest_erv_supply_c = OpenStudio.convert(hottest_erv_supply_f, 'F', 'C').get
|
4007
4048
|
|
4008
4049
|
# Ensure that zone sizing accounts for OA from ERV
|
4009
|
-
|
4010
|
-
|
4011
|
-
|
4012
|
-
|
4013
|
-
|
4050
|
+
sizing_zone = zone.sizingZone
|
4051
|
+
sizing_zone.setAccountforDedicatedOutdoorAirSystem(true)
|
4052
|
+
sizing_zone.setDedicatedOutdoorAirSystemControlStrategy('NeutralSupplyAir')
|
4053
|
+
sizing_zone.setDedicatedOutdoorAirLowSetpointTemperatureforDesign(coldest_erv_supply_c)
|
4054
|
+
sizing_zone.setDedicatedOutdoorAirHighSetpointTemperatureforDesign(hottest_erv_supply_c)
|
4014
4055
|
|
4015
4056
|
ervs << zone_hvac
|
4016
4057
|
end
|
@@ -4020,19 +4061,158 @@ class Standard
|
|
4020
4061
|
|
4021
4062
|
# Adds ideal air loads systems for each zone.
|
4022
4063
|
#
|
4023
|
-
# @param thermal_zones [Array<OpenStudio::Model::ThermalZone>] array of zones to
|
4064
|
+
# @param thermal_zones [Array<OpenStudio::Model::ThermalZone>] array of zones to enable ideal air loads
|
4065
|
+
# @param hvac_op_sch [String] name of the HVAC operation schedule, default is always on
|
4066
|
+
# @param heat_avail_sch [String] name of the heating availability schedule, default is always on
|
4067
|
+
# @param cool_avail_sch [String] name of the cooling availability schedule, default is always on
|
4068
|
+
# @param heat_limit_type [String] heating limit type
|
4069
|
+
# options are 'NoLimit', 'LimitFlowRate', 'LimitCapacity', and 'LimitFlowRateAndCapacity'
|
4070
|
+
# @param cool_limit_type [String] cooling limit type
|
4071
|
+
# options are 'NoLimit', 'LimitFlowRate', 'LimitCapacity', and 'LimitFlowRateAndCapacity'
|
4072
|
+
# @param dehumid_limit_type [String] dehumidification limit type
|
4073
|
+
# options are 'None', 'ConstantSensibleHeatRatio', 'Humidistat', 'ConstantSupplyHumidityRatio'
|
4074
|
+
# @param cool_sensible_heat_ratio [Double] cooling sensible heat ratio if dehumidification limit type is 'ConstantSensibleHeatRatio'
|
4075
|
+
# @param humid_ctrl_type [String] humidification control type
|
4076
|
+
# options are 'None', 'Humidistat', 'ConstantSupplyHumidityRatio'
|
4077
|
+
# @param include_outdoor_air [Boolean] include design specification outdoor air ventilation
|
4078
|
+
# @param enable_dcv [Boolean] include demand control ventilation, uses occupancy schedule if true
|
4079
|
+
# @param econo_ctrl_mthd [String] economizer control method (require a cool_limit_type and include_outdoor_air set to true)
|
4080
|
+
# options are 'NoEconomizer', 'DifferentialDryBulb', 'DifferentialEnthalpy'
|
4081
|
+
# @param heat_recovery_type [String] heat recovery type
|
4082
|
+
# options are 'None', 'Sensible', 'Enthalpy'
|
4083
|
+
# @param heat_recovery_sensible_eff [Double] heat recovery sensible effectivness if heat recovery specified
|
4084
|
+
# @param heat_recovery_latent_eff [Double] heat recovery latent effectivness if heat recovery specified
|
4085
|
+
# @param add_output_meters [Boolean] include and output custom meter objects to sum all ideal air loads values
|
4024
4086
|
# @return [Array<OpenStudio::Model::ZoneHVACIdealLoadsAirSystem>] an array of ideal air loads systems
|
4025
|
-
# TODO: enable default ventilation settings, see https://github.com/UnmetHours/openstudio-measures/tree/master/ideal_loads_options
|
4026
4087
|
def model_add_ideal_air_loads(model,
|
4027
|
-
thermal_zones
|
4088
|
+
thermal_zones,
|
4089
|
+
hvac_op_sch: nil,
|
4090
|
+
heat_avail_sch: nil,
|
4091
|
+
cool_avail_sch: nil,
|
4092
|
+
heat_limit_type: 'NoLimit',
|
4093
|
+
cool_limit_type: 'NoLimit',
|
4094
|
+
dehumid_limit_type: 'ConstantSensibleHeatRatio',
|
4095
|
+
cool_sensible_heat_ratio: 0.7,
|
4096
|
+
humid_ctrl_type: 'None',
|
4097
|
+
include_outdoor_air: true,
|
4098
|
+
enable_dcv: false,
|
4099
|
+
econo_ctrl_mthd: 'NoEconomizer',
|
4100
|
+
heat_recovery_type: 'None',
|
4101
|
+
heat_recovery_sensible_eff: 0.7,
|
4102
|
+
heat_recovery_latent_eff: 0.65,
|
4103
|
+
add_output_meters: false)
|
4104
|
+
|
4105
|
+
# set availability schedules
|
4106
|
+
if hvac_op_sch.nil?
|
4107
|
+
hvac_op_sch = model.alwaysOnDiscreteSchedule
|
4108
|
+
else
|
4109
|
+
hvac_op_sch = model_add_schedule(model, hvac_op_sch)
|
4110
|
+
end
|
4111
|
+
|
4112
|
+
# set heating availability schedules
|
4113
|
+
if heat_avail_sch.nil?
|
4114
|
+
heat_avail_sch = model.alwaysOnDiscreteSchedule
|
4115
|
+
else
|
4116
|
+
heat_avail_sch = model_add_schedule(model, heat_avail_sch)
|
4117
|
+
end
|
4118
|
+
|
4119
|
+
# set cooling availability schedules
|
4120
|
+
if cool_avail_sch.nil?
|
4121
|
+
cool_avail_sch = model.alwaysOnDiscreteSchedule
|
4122
|
+
else
|
4123
|
+
cool_avail_sch = model_add_schedule(model, cool_avail_sch)
|
4124
|
+
end
|
4125
|
+
|
4028
4126
|
ideal_systems = []
|
4029
4127
|
thermal_zones.each do |zone|
|
4030
4128
|
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding ideal air loads for for #{zone.name}.")
|
4031
4129
|
ideal_loads = OpenStudio::Model::ZoneHVACIdealLoadsAirSystem.new(model)
|
4130
|
+
ideal_loads.setName("#{zone.name} Ideal Loads Air System")
|
4131
|
+
ideal_loads.setAvailabilitySchedule(hvac_op_sch)
|
4132
|
+
ideal_loads.setHeatingAvailabilitySchedule(heat_avail_sch)
|
4133
|
+
ideal_loads.setCoolingAvailabilitySchedule(cool_avail_sch)
|
4134
|
+
ideal_loads.setHeatingLimit(heat_limit_type)
|
4135
|
+
ideal_loads.setCoolingLimit(cool_limit_type)
|
4136
|
+
ideal_loads.setDehumidificationControlType(dehumid_limit_type)
|
4137
|
+
ideal_loads.setCoolingSensibleHeatRatio(cool_sensible_heat_ratio)
|
4138
|
+
ideal_loads.setHumidificationControlType(humid_ctrl_type)
|
4139
|
+
if include_outdoor_air
|
4140
|
+
# get the design specification outdoor air of the largest space in the zone
|
4141
|
+
# TODO: create a new design specification outdoor air object that sums ventilation rates and schedules if multiple design specification outdoor air objects
|
4142
|
+
space_areas = zone.spaces.map { |s| s.floorArea }
|
4143
|
+
largest_space = zone.spaces.select { |s| s.floorArea == space_areas.max }
|
4144
|
+
largest_space = largest_space[0]
|
4145
|
+
design_spec_oa = largest_space.designSpecificationOutdoorAir
|
4146
|
+
if design_spec_oa.is_initialized
|
4147
|
+
design_spec_oa = design_spec_oa.get
|
4148
|
+
ideal_loads.setDesignSpecificationOutdoorAirObject(design_spec_oa)
|
4149
|
+
else
|
4150
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.Model.Model', "Outdoor air requested for ideal loads object, but space #{largest_space.name} in thermal zone #{zone.name} does not have a design specification outdoor air object.")
|
4151
|
+
end
|
4152
|
+
end
|
4153
|
+
if enable_dcv
|
4154
|
+
ideal_loads.setDemandControlledVentilationType('OccupancySchedule')
|
4155
|
+
else
|
4156
|
+
ideal_loads.setDemandControlledVentilationType('None')
|
4157
|
+
end
|
4158
|
+
ideal_loads.setOutdoorAirEconomizerType(econo_ctrl_mthd)
|
4159
|
+
ideal_loads.setHeatRecoveryType(heat_recovery_type)
|
4160
|
+
ideal_loads.setSensibleHeatRecoveryEffectiveness(heat_recovery_sensible_eff)
|
4161
|
+
ideal_loads.setLatentHeatRecoveryEffectiveness(heat_recovery_latent_eff)
|
4032
4162
|
ideal_loads.addToThermalZone(zone)
|
4033
4163
|
ideal_systems << ideal_loads
|
4034
4164
|
end
|
4035
4165
|
|
4166
|
+
if add_output_meters
|
4167
|
+
# ideal air loads system variables to include
|
4168
|
+
ideal_air_loads_system_variables = [
|
4169
|
+
'Zone Ideal Loads Supply Air Sensible Heating Energy',
|
4170
|
+
'Zone Ideal Loads Supply Air Latent Heating Energy',
|
4171
|
+
'Zone Ideal Loads Supply Air Total Heating Energy',
|
4172
|
+
'Zone Ideal Loads Supply Air Sensible Cooling Energy',
|
4173
|
+
'Zone Ideal Loads Supply Air Latent Cooling Energy',
|
4174
|
+
'Zone Ideal Loads Supply Air Total Cooling Energy',
|
4175
|
+
'Zone Ideal Loads Zone Sensible Heating Energy',
|
4176
|
+
'Zone Ideal Loads Zone Latent Heating Energy',
|
4177
|
+
'Zone Ideal Loads Zone Total Heating Energy',
|
4178
|
+
'Zone Ideal Loads Zone Sensible Cooling Energy',
|
4179
|
+
'Zone Ideal Loads Zone Latent Cooling Energy',
|
4180
|
+
'Zone Ideal Loads Zone Total Cooling Energy',
|
4181
|
+
'Zone Ideal Loads Outdoor Air Sensible Heating Energy',
|
4182
|
+
'Zone Ideal Loads Outdoor Air Latent Heating Energy',
|
4183
|
+
'Zone Ideal Loads Outdoor Air Total Heating Energy',
|
4184
|
+
'Zone Ideal Loads Outdoor Air Sensible Cooling Energy',
|
4185
|
+
'Zone Ideal Loads Outdoor Air Latent Cooling Energy',
|
4186
|
+
'Zone Ideal Loads Outdoor Air Total Cooling Energy',
|
4187
|
+
'Zone Ideal Loads Heat Recovery Sensible Heating Energy',
|
4188
|
+
'Zone Ideal Loads Heat Recovery Latent Heating Energy',
|
4189
|
+
'Zone Ideal Loads Heat Recovery Total Heating Energy',
|
4190
|
+
'Zone Ideal Loads Heat Recovery Sensible Cooling Energy',
|
4191
|
+
'Zone Ideal Loads Heat Recovery Latent Cooling Energy',
|
4192
|
+
'Zone Ideal Loads Heat Recovery Total Cooling Energy'
|
4193
|
+
]
|
4194
|
+
|
4195
|
+
meters_added = 0
|
4196
|
+
outputs_added = 0
|
4197
|
+
ideal_air_loads_system_variables.each do |variable|
|
4198
|
+
# create meter definition for variable
|
4199
|
+
meter_definition = OpenStudio::Model::MeterCustom.new(model)
|
4200
|
+
meter_definition.setName("Sum #{variable}")
|
4201
|
+
meter_definition.setFuelType('Generic')
|
4202
|
+
model.getZoneHVACIdealLoadsAirSystems.each { |sys| meter_definition.addKeyVarGroup(sys.name.to_s, variable) }
|
4203
|
+
meters_added += 1
|
4204
|
+
|
4205
|
+
# add output meter
|
4206
|
+
output_meter_definition = OpenStudio::Model::OutputMeter.new(model)
|
4207
|
+
output_meter_definition.setName("Sum #{variable}")
|
4208
|
+
output_meter_definition.setReportingFrequency('Hourly')
|
4209
|
+
output_meter_definition.setMeterFileOnly(true)
|
4210
|
+
output_meter_definition.setCumulative(false)
|
4211
|
+
outputs_added += 1
|
4212
|
+
end
|
4213
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Added #{meters_added} custom meter objects and #{outputs_added} meter outputs for ideal loads air systems.")
|
4214
|
+
end
|
4215
|
+
|
4036
4216
|
return ideal_systems
|
4037
4217
|
end
|
4038
4218
|
|
@@ -4044,6 +4224,7 @@ class Standard
|
|
4044
4224
|
# @param flow_fraction_schedule_name [String] the name of the flow fraction schedule
|
4045
4225
|
# @param balanced_exhaust_fraction_schedule_name [String] the name of the balanced exhaust fraction schedule
|
4046
4226
|
# @return [Array<OpenStudio::Model::FanZoneExhaust>] an array of exhaust fans created
|
4227
|
+
# @todo: use the create_fan_zone_exhaust method, default to 1.25 inH2O pressure rise and fan efficiency of 0.6
|
4047
4228
|
def model_add_exhaust_fan(model,
|
4048
4229
|
thermal_zones,
|
4049
4230
|
flow_rate: nil,
|
@@ -4935,172 +5116,4 @@ class Standard
|
|
4935
5116
|
rename_air_loop_nodes(model)
|
4936
5117
|
rename_plant_loop_nodes(model)
|
4937
5118
|
end
|
4938
|
-
|
4939
|
-
# Determine the typical system type given the inputs.
|
4940
|
-
#
|
4941
|
-
# @param area_type [String] Valid choices are residential and nonresidential
|
4942
|
-
# @param delivery_type [String] Conditioning delivery type. Valid choices are air and hydronic
|
4943
|
-
# @param heating_source [String] Valid choices are Electricity, NaturalGas, DistrictHeating, DistrictAmbient
|
4944
|
-
# @param cooling_source [String] Valid choices are Electricity, DistrictCooling, DistrictAmbient
|
4945
|
-
# @param area_m2 [Double] Area in m^2
|
4946
|
-
# @param num_stories [Integer] Number of stories
|
4947
|
-
# @return [String] The system type. Possibilities are
|
4948
|
-
# PTHP, PTAC, PSZ_AC, PSZ_HP, PVAV_Reheat, PVAV_PFP_Boxes,
|
4949
|
-
# VAV_Reheat, VAV_PFP_Boxes, Gas_Furnace, Electric_Furnace
|
4950
|
-
def model_typical_hvac_system_type(model,
|
4951
|
-
climate_zone,
|
4952
|
-
area_type,
|
4953
|
-
delivery_type,
|
4954
|
-
heating_source,
|
4955
|
-
cooling_source,
|
4956
|
-
area_m2,
|
4957
|
-
num_stories)
|
4958
|
-
|
4959
|
-
# Convert area to ft^2
|
4960
|
-
area_ft2 = OpenStudio.convert(area_m2, 'm^2', 'ft^2').get
|
4961
|
-
|
4962
|
-
# categorize building by type & size
|
4963
|
-
size_category = nil
|
4964
|
-
case area_type
|
4965
|
-
when 'residential'
|
4966
|
-
# residential and less than 4 stories
|
4967
|
-
size_category = if num_stories <= 3
|
4968
|
-
'res_small'
|
4969
|
-
# residential and more than 4 stories
|
4970
|
-
else
|
4971
|
-
'res_med'
|
4972
|
-
end
|
4973
|
-
when 'nonresidential', 'retail', 'publicassembly', 'heatedonly'
|
4974
|
-
# nonresidential and 3 floors or less and < 75,000 ft2
|
4975
|
-
if num_stories <= 3 && area_ft2 < 75_000
|
4976
|
-
size_category = 'nonres_small'
|
4977
|
-
# nonresidential and 4 or 5 floors OR 5 floors or less and 75,000 ft2 to 150,000 ft2
|
4978
|
-
elsif ((num_stories == 4 || num_stories == 5) && area_ft2 < 75_000) || (num_stories <= 5 && (area_ft2 >= 75_000 && area_ft2 <= 150_000))
|
4979
|
-
size_category = 'nonres_med'
|
4980
|
-
# nonresidential and more than 5 floors or >150,000 ft2
|
4981
|
-
elsif num_stories >= 5 || area_ft2 > 150_000
|
4982
|
-
size_category = 'nonres_lg'
|
4983
|
-
end
|
4984
|
-
else
|
4985
|
-
OpenStudio.logFree(OpenStudio::Error, 'openstudio.Model.Model', 'No area_type specified.')
|
4986
|
-
end
|
4987
|
-
|
4988
|
-
# Define the lookup by row and by fuel type
|
4989
|
-
systems= Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
|
4990
|
-
# [heating_source][cooling_source][delivery_type][size_category] = [type, central_heating_fuel, zone_heating_fuel, cooling_fuel]
|
4991
|
-
|
4992
|
-
## Forced Air ##
|
4993
|
-
|
4994
|
-
# Gas, Electric, forced air
|
4995
|
-
systems['NaturalGas']['Electricity']['air']['res_small'] = ['PTAC', 'NaturalGas', nil, 'Electricity']
|
4996
|
-
systems['NaturalGas']['Electricity']['air']['res_med'] = ['PTAC', 'NaturalGas', nil, 'Electricity']
|
4997
|
-
systems['NaturalGas']['Electricity']['air']['nonres_small'] = ['PSZ-AC', 'NaturalGas', nil, 'Electricity']
|
4998
|
-
systems['NaturalGas']['Electricity']['air']['nonres_med'] = ['PVAV Reheat', 'NaturalGas', 'NaturalGas', 'Electricity']
|
4999
|
-
systems['NaturalGas']['Electricity']['air']['nonres_lg'] = ['VAV Reheat', 'NaturalGas', 'NaturalGas', 'Electricity']
|
5000
|
-
|
5001
|
-
# Electric, Electric, forced air
|
5002
|
-
systems['Electricity']['Electricity']['air']['res_small'] = ['PTHP', 'Electricity', nil, 'Electricity']
|
5003
|
-
systems['Electricity']['Electricity']['air']['res_med'] = ['PTHP', 'Electricity', nil, 'Electricity']
|
5004
|
-
systems['Electricity']['Electricity']['air']['nonres_small'] = ['PSZ-HP', 'Electricity', nil, 'Electricity']
|
5005
|
-
systems['Electricity']['Electricity']['air']['nonres_med'] = ['PVAV PFP Boxes', 'Electricity', 'Electricity', 'Electricity']
|
5006
|
-
systems['Electricity']['Electricity']['air']['nonres_lg'] = ['VAV PFP Boxes', 'Electricity', 'Electricity', 'Electricity']
|
5007
|
-
|
5008
|
-
# District Hot Water, Electric, forced air
|
5009
|
-
systems['DistrictHeating']['Electricity']['air']['res_small'] = ['PTAC', 'DistrictHeating', nil, 'Electricity']
|
5010
|
-
systems['DistrictHeating']['Electricity']['air']['res_med'] = ['PTAC', 'DistrictHeating', nil, 'Electricity']
|
5011
|
-
systems['DistrictHeating']['Electricity']['air']['nonres_small'] = ['PVAV Reheat', 'DistrictHeating', 'DistrictHeating', 'Electricity']
|
5012
|
-
systems['DistrictHeating']['Electricity']['air']['nonres_med'] = ['PVAV Reheat', 'DistrictHeating', 'DistrictHeating', 'Electricity']
|
5013
|
-
systems['DistrictHeating']['Electricity']['air']['nonres_lg'] = ['VAV Reheat', 'DistrictHeating', 'DistrictHeating', 'Electricity']
|
5014
|
-
|
5015
|
-
# Ambient Loop, Ambient Loop, forced air
|
5016
|
-
systems['DistrictAmbient']['DistrictAmbient']['air']['res_small'] = ['Water Source Heat Pumps with ERVs', 'HeatPump', nil, 'HeatPump']
|
5017
|
-
systems['DistrictAmbient']['DistrictAmbient']['air']['res_med'] = ['Water Source Heat Pumps with DOAS', 'HeatPump', nil, 'HeatPump']
|
5018
|
-
systems['DistrictAmbient']['DistrictAmbient']['air']['nonres_small'] = ['PVAV Reheat', 'HeatPump', 'HeatPump', 'HeatPump']
|
5019
|
-
systems['DistrictAmbient']['DistrictAmbient']['air']['nonres_med'] = ['PVAV Reheat', 'HeatPump', 'HeatPump', 'HeatPump']
|
5020
|
-
systems['DistrictAmbient']['DistrictAmbient']['air']['nonres_lg'] = ['VAV Reheat', 'HeatPump', 'HeatPump', 'HeatPump']
|
5021
|
-
|
5022
|
-
# Gas, District Chilled Water, forced air
|
5023
|
-
systems['NaturalGas']['DistrictCooling']['air']['res_small'] = ['PSZ-AC', 'NaturalGas', nil, 'DistrictCooling']
|
5024
|
-
systems['NaturalGas']['DistrictCooling']['air']['res_med'] = ['PSZ-AC', 'NaturalGas', nil, 'DistrictCooling']
|
5025
|
-
systems['NaturalGas']['DistrictCooling']['air']['nonres_small'] = ['PSZ-AC', 'NaturalGas', nil, 'DistrictCooling']
|
5026
|
-
systems['NaturalGas']['DistrictCooling']['air']['nonres_med'] = ['PVAV Reheat', 'NaturalGas', 'NaturalGas', 'DistrictCooling']
|
5027
|
-
systems['NaturalGas']['DistrictCooling']['air']['nonres_lg'] = ['VAV Reheat', 'NaturalGas', 'NaturalGas', 'DistrictCooling']
|
5028
|
-
|
5029
|
-
# Electric, District Chilled Water, forced air
|
5030
|
-
systems['Electricity']['DistrictCooling']['air']['res_small'] = ['PSZ-AC', 'Electricity', nil, 'DistrictCooling']
|
5031
|
-
systems['Electricity']['DistrictCooling']['air']['res_med'] = ['PSZ-AC', 'Electricity', nil, 'DistrictCooling']
|
5032
|
-
systems['Electricity']['DistrictCooling']['air']['nonres_small'] = ['PSZ-AC', 'Electricity', nil, 'DistrictCooling']
|
5033
|
-
systems['Electricity']['DistrictCooling']['air']['nonres_med'] = ['PVAV Reheat', 'Electricity', 'Electricity', 'DistrictCooling']
|
5034
|
-
systems['Electricity']['DistrictCooling']['air']['nonres_lg'] = ['VAV Reheat', 'Electricity', 'Electricity', 'DistrictCooling']
|
5035
|
-
|
5036
|
-
# District Hot Water, District Chilled Water, forced air
|
5037
|
-
systems['DistrictHeating']['DistrictCooling']['air']['res_small'] = ['PSZ-AC', 'DistrictHeating', nil, 'DistrictCooling']
|
5038
|
-
systems['DistrictHeating']['DistrictCooling']['air']['res_med'] = ['PSZ-AC', 'DistrictHeating', nil, 'DistrictCooling']
|
5039
|
-
systems['DistrictHeating']['DistrictCooling']['air']['nonres_small'] = ['PVAV Reheat', 'DistrictHeating', 'DistrictHeating', 'DistrictCooling']
|
5040
|
-
systems['DistrictHeating']['DistrictCooling']['air']['nonres_med'] = ['PVAV Reheat', 'DistrictHeating', 'DistrictHeating', 'DistrictCooling']
|
5041
|
-
systems['DistrictHeating']['DistrictCooling']['air']['nonres_lg'] = ['VAV Reheat', 'DistrictHeating', 'DistrictHeating', 'DistrictCooling']
|
5042
|
-
|
5043
|
-
## Hydronic ##
|
5044
|
-
|
5045
|
-
# Gas, Electric, hydronic
|
5046
|
-
systems['NaturalGas']['Electricity']['hydronic']['res_med'] = ['Fan Coil with DOAS', 'NaturalGas', nil, 'Electricity']
|
5047
|
-
systems['NaturalGas']['Electricity']['hydronic']['nonres_small'] = ['Water Source Heat Pumps with DOAS', 'NaturalGas', nil, 'Electricity']
|
5048
|
-
systems['NaturalGas']['Electricity']['hydronic']['nonres_med'] = ['Fan Coil with DOAS', 'NaturalGas', 'NaturalGas', 'Electricity']
|
5049
|
-
systems['NaturalGas']['Electricity']['hydronic']['nonres_lg'] = ['Fan Coil with DOAS', 'NaturalGas', 'NaturalGas', 'Electricity']
|
5050
|
-
|
5051
|
-
# Electric, Electric, hydronic
|
5052
|
-
systems['Electricity']['Electricity']['hydronic']['res_small'] = ['Ground Source Heat Pumps with ERVs', 'Electricity', nil, 'Electricity']
|
5053
|
-
systems['Electricity']['Electricity']['hydronic']['res_med'] = ['Ground Source Heat Pumps with DOAS', 'Electricity', nil, 'Electricity']
|
5054
|
-
systems['Electricity']['Electricity']['hydronic']['nonres_small'] = ['Ground Source Heat Pumps with DOAS', 'Electricity', nil, 'Electricity']
|
5055
|
-
systems['Electricity']['Electricity']['hydronic']['nonres_med'] = ['Ground Source Heat Pumps with DOAS', 'Electricity', 'Electricity', 'Electricity']
|
5056
|
-
systems['Electricity']['Electricity']['hydronic']['nonres_lg'] = ['Ground Source Heat Pumps with DOAS', 'Electricity', 'Electricity', 'Electricity']
|
5057
|
-
|
5058
|
-
# District Hot Water, Electric, hydronic
|
5059
|
-
systems['DistrictHeating']['Electricity']['hydronic']['res_small'] = [] # TODO decide if there is anything reasonable for this
|
5060
|
-
systems['DistrictHeating']['Electricity']['hydronic']['res_med'] = ['Fan Coil with DOAS', 'DistrictHeating', nil, 'Electricity']
|
5061
|
-
systems['DistrictHeating']['Electricity']['hydronic']['nonres_small'] = ['Water Source Heat Pumps with DOAS', 'DistrictHeating', 'DistrictHeating', 'Electricity']
|
5062
|
-
systems['DistrictHeating']['Electricity']['hydronic']['nonres_med'] = ['Fan Coil with DOAS', 'DistrictHeating', 'DistrictHeating', 'Electricity']
|
5063
|
-
systems['DistrictHeating']['Electricity']['hydronic']['nonres_lg'] = ['Fan Coil with DOAS', 'DistrictHeating', 'DistrictHeating', 'Electricity']
|
5064
|
-
|
5065
|
-
# Ambient Loop, Ambient Loop, hydronic
|
5066
|
-
systems['DistrictAmbient']['DistrictAmbient']['hydronic']['res_small'] = ['Water Source Heat Pumps with ERVs', 'HeatPump', nil, 'HeatPump']
|
5067
|
-
systems['DistrictAmbient']['DistrictAmbient']['hydronic']['res_med'] = ['Water Source Heat Pumps with DOAS', 'HeatPump', nil, 'HeatPump']
|
5068
|
-
systems['DistrictAmbient']['DistrictAmbient']['hydronic']['nonres_small'] = ['Water Source Heat Pumps with DOAS', 'HeatPump', 'HeatPump', 'HeatPump']
|
5069
|
-
systems['DistrictAmbient']['DistrictAmbient']['hydronic']['nonres_med'] = ['Water Source Heat Pumps with DOAS', 'HeatPump', 'HeatPump', 'HeatPump']
|
5070
|
-
systems['DistrictAmbient']['DistrictAmbient']['hydronic']['nonres_lg'] = ['Fan Coil with DOAS', 'DistrictHeating', nil, 'Electricity'] # TODO: is this reasonable?
|
5071
|
-
|
5072
|
-
# Gas, District Chilled Water, hydronic
|
5073
|
-
systems['NaturalGas']['DistrictCooling']['hydronic']['res_med'] = ['Fan Coil with DOAS', 'NaturalGas', nil, 'DistrictCooling']
|
5074
|
-
systems['NaturalGas']['DistrictCooling']['hydronic']['nonres_small'] = ['Fan Coil with DOAS', 'NaturalGas', nil, 'DistrictCooling']
|
5075
|
-
systems['NaturalGas']['DistrictCooling']['hydronic']['nonres_med'] = ['Fan Coil with DOAS', 'NaturalGas', 'NaturalGas', 'DistrictCooling']
|
5076
|
-
systems['NaturalGas']['DistrictCooling']['hydronic']['nonres_lg'] = ['Fan Coil with DOAS', 'NaturalGas', 'NaturalGas', 'DistrictCooling']
|
5077
|
-
|
5078
|
-
# Electric, District Chilled Water, hydronic
|
5079
|
-
systems['Electricity']['DistrictCooling']['hydronic']['res_med'] = ['Fan Coil with ERVs', 'Electricity', nil, 'DistrictCooling']
|
5080
|
-
systems['Electricity']['DistrictCooling']['hydronic']['nonres_small'] = ['Fan Coil with DOAS', 'Electricity', nil, 'DistrictCooling']
|
5081
|
-
systems['Electricity']['DistrictCooling']['hydronic']['nonres_med'] = ['Fan Coil with DOAS', 'Electricity', 'Electricity', 'DistrictCooling']
|
5082
|
-
systems['Electricity']['DistrictCooling']['hydronic']['nonres_lg'] = ['Fan Coil with DOAS', 'Electricity', 'Electricity', 'DistrictCooling']
|
5083
|
-
|
5084
|
-
# District Hot Water, District Chilled Water, hydronic
|
5085
|
-
systems['DistrictHeating']['DistrictCooling']['hydronic']['res_small'] = ['Fan Coil with ERVs', 'DistrictHeating', nil, 'DistrictCooling']
|
5086
|
-
systems['DistrictHeating']['DistrictCooling']['hydronic']['res_med'] = ['Fan Coil with DOAS', 'DistrictHeating', nil, 'DistrictCooling']
|
5087
|
-
systems['DistrictHeating']['DistrictCooling']['hydronic']['nonres_small'] = ['Fan Coil with DOAS', 'DistrictHeating', 'DistrictHeating', 'DistrictCooling']
|
5088
|
-
systems['DistrictHeating']['DistrictCooling']['hydronic']['nonres_med'] = ['Fan Coil with DOAS', 'DistrictHeating', 'DistrictHeating', 'DistrictCooling']
|
5089
|
-
systems['DistrictHeating']['DistrictCooling']['hydronic']['nonres_lg'] = ['Fan Coil with DOAS', 'DistrictHeating', 'DistrictHeating', 'DistrictCooling']
|
5090
|
-
|
5091
|
-
# Get the system type
|
5092
|
-
system_type = systems[heating_source][cooling_source][delivery_type][size_category]
|
5093
|
-
|
5094
|
-
if system_type.nil? || system_type.empty?
|
5095
|
-
system_type = [nil, nil, nil, nil]
|
5096
|
-
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Could not determine system type for #{template}, #{area_type}, #{heating_source} heating, #{cooling_source} cooling, #{delivery_type} delivery, #{area_ft2.round} ft^2, #{num_stories} stories.")
|
5097
|
-
else
|
5098
|
-
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "System type is #{system_type[0]} for #{template}, #{area_type}, #{heating_source} heating, #{cooling_source} cooling, #{delivery_type} delivery, #{area_ft2.round} ft^2, #{num_stories} stories.")
|
5099
|
-
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "--- #{system_type[1]} for main heating") unless system_type[1].nil?
|
5100
|
-
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "--- #{system_type[2]} for zone heat/reheat") unless system_type[2].nil?
|
5101
|
-
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "--- #{system_type[3]} for cooling") unless system_type[3].nil?
|
5102
|
-
end
|
5103
|
-
|
5104
|
-
return system_type
|
5105
|
-
end
|
5106
5119
|
end
|