openstudio-standards 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/data/standards/OpenStudio_Standards.xlsx +0 -0
- data/data/standards/OpenStudio_Standards_boilers.json +62 -4
- data/data/standards/OpenStudio_Standards_chillers.json +778 -68
- data/data/standards/OpenStudio_Standards_construction_sets.json +52 -93
- data/data/standards/OpenStudio_Standards_curve_biquadratics.json +36 -36
- data/data/standards/OpenStudio_Standards_curve_quadratics.json +3 -3
- data/data/standards/OpenStudio_Standards_heat_pumps.json +840 -0
- data/data/standards/OpenStudio_Standards_heat_pumps_heating.json +352 -0
- data/data/standards/OpenStudio_Standards_heat_rejection.json +48 -0
- data/data/standards/OpenStudio_Standards_motors.json +270 -0
- data/data/standards/OpenStudio_Standards_space_types.json +10390 -2824
- data/data/standards/OpenStudio_Standards_unitary_acs.json +794 -18
- data/data/weather/USA_CO_Boulder-Broomfield-Jefferson.County.AP.724699_TMY3.ddy +538 -0
- data/data/weather/USA_CO_Boulder-Broomfield-Jefferson.County.AP.724699_TMY3.epw +8768 -0
- data/data/weather/USA_CO_Boulder-Broomfield-Jefferson.County.AP.724699_TMY3.stat +493 -0
- data/data/weather/USA_CO_Denver.Intl.AP.725650_TMY3.ddy +536 -0
- data/data/weather/USA_CO_Denver.Intl.AP.725650_TMY3.epw +8768 -0
- data/data/weather/USA_CO_Denver.Intl.AP.725650_TMY3.stat +554 -0
- data/data/weather/USA_CO_Fort.Collins.AWOS.724769_TMY3.ddy +536 -0
- data/data/weather/USA_CO_Fort.Collins.AWOS.724769_TMY3.epw +8768 -0
- data/data/weather/USA_CO_Fort.Collins.AWOS.724769_TMY3.stat +554 -0
- data/data/weather/envelope_info.csv +6 -0
- data/lib/openstudio-standards.rb +10 -11
- data/lib/openstudio-standards/btap/compliance.rb +251 -969
- data/lib/openstudio-standards/btap/envelope.rb +1 -1
- data/lib/openstudio-standards/btap/fileio.rb +37 -5
- data/lib/openstudio-standards/btap/geometry.rb +27 -17
- data/lib/openstudio-standards/btap/hvac.rb +80 -27
- data/lib/openstudio-standards/hvac_sizing/{HVACSizing.CoilHeatingDXMultiSpeed.rb → Siz.CoilHeatingDXMultiSpeed.rb} +0 -0
- data/lib/openstudio-standards/hvac_sizing/Siz.ControllerOutdoorAir.rb +30 -4
- data/lib/openstudio-standards/hvac_sizing/Siz.CoolingTowerTwoSpeed.rb +61 -5
- data/lib/openstudio-standards/hvac_sizing/Siz.CoolingTowerVariableSpeed.rb +37 -7
- data/lib/openstudio-standards/hvac_sizing/Siz.DistrictCooling.rb +27 -0
- data/lib/openstudio-standards/hvac_sizing/Siz.DistrictHeating.rb +27 -0
- data/lib/openstudio-standards/hvac_sizing/Siz.HeaderedPumpsConstantSpeed.rb +55 -0
- data/lib/openstudio-standards/hvac_sizing/Siz.HeaderedPumpsVariableSpeed.rb +55 -0
- data/lib/openstudio-standards/hvac_sizing/Siz.HeatingCoolingFuels.rb +51 -9
- data/lib/openstudio-standards/hvac_sizing/Siz.Model.rb +99 -17
- data/lib/openstudio-standards/hvac_sizing/Siz.PumpConstantSpeed.rb +1 -1
- data/lib/openstudio-standards/hvac_sizing/Siz.ThermalZone.rb +29 -6
- data/lib/openstudio-standards/hvac_sizing/Siz.WaterHeaterMixed.rb +16 -0
- data/lib/openstudio-standards/prototypes/Prototype.AirTerminalSingleDuctVAVReheat.rb +43 -48
- data/lib/openstudio-standards/prototypes/Prototype.ControllerWaterCoil.rb +5 -9
- data/lib/openstudio-standards/prototypes/Prototype.Fan.rb +68 -0
- data/lib/openstudio-standards/prototypes/Prototype.FanConstantVolume.rb +39 -43
- data/lib/openstudio-standards/prototypes/Prototype.FanOnOff.rb +49 -51
- data/lib/openstudio-standards/prototypes/Prototype.FanVariableVolume.rb +55 -61
- data/lib/openstudio-standards/prototypes/Prototype.FanZoneExhaust.rb +8 -10
- data/lib/openstudio-standards/prototypes/Prototype.HeatExchangerAirToAirSensibleAndLatent.rb +15 -20
- data/lib/openstudio-standards/prototypes/Prototype.Model.hvac.rb +330 -322
- data/lib/openstudio-standards/prototypes/Prototype.Model.rb +501 -446
- data/lib/openstudio-standards/prototypes/Prototype.Model.swh.rb +221 -230
- data/lib/openstudio-standards/prototypes/Prototype.add_objects.rb +0 -2
- data/lib/openstudio-standards/prototypes/Prototype.full_service_restaurant.rb +130 -137
- data/lib/openstudio-standards/prototypes/Prototype.high_rise_apartment.rb +374 -291
- data/lib/openstudio-standards/prototypes/Prototype.hospital.rb +146 -193
- data/lib/openstudio-standards/prototypes/Prototype.hvac_systems.rb +1315 -1113
- data/lib/openstudio-standards/prototypes/Prototype.large_hotel.rb +65 -88
- data/lib/openstudio-standards/prototypes/Prototype.large_office.rb +101 -156
- data/lib/openstudio-standards/prototypes/Prototype.medium_office.rb +46 -96
- data/lib/openstudio-standards/prototypes/Prototype.mid_rise_apartment.rb +113 -123
- data/lib/openstudio-standards/prototypes/Prototype.outpatient.rb +356 -345
- data/lib/openstudio-standards/prototypes/Prototype.primary_school.rb +48 -103
- data/lib/openstudio-standards/prototypes/Prototype.quick_service_restaurant.rb +115 -123
- data/lib/openstudio-standards/prototypes/Prototype.retail_standalone.rb +30 -39
- data/lib/openstudio-standards/prototypes/Prototype.retail_stripmall.rb +32 -45
- data/lib/openstudio-standards/prototypes/Prototype.secondary_school.rb +98 -258
- data/lib/openstudio-standards/prototypes/Prototype.small_hotel.rb +429 -474
- data/lib/openstudio-standards/prototypes/Prototype.small_office.rb +28 -36
- data/lib/openstudio-standards/prototypes/Prototype.strip_model.rb +7 -7
- data/lib/openstudio-standards/prototypes/Prototype.utilities.rb +172 -146
- data/lib/openstudio-standards/prototypes/Prototype.warehouse.rb +46 -53
- data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +885 -707
- data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctParallelPIUReheat.rb +48 -57
- data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctVAVReheat.rb +24 -31
- data/lib/openstudio-standards/standards/Standards.BoilerHotWater.rb +80 -93
- data/lib/openstudio-standards/standards/Standards.BuildingStory.rb +69 -0
- data/lib/openstudio-standards/standards/Standards.ChillerElectricEIR.rb +60 -72
- data/lib/openstudio-standards/standards/Standards.CoilCoolingDXMultiSpeed.rb +104 -108
- data/lib/openstudio-standards/standards/Standards.CoilCoolingDXSingleSpeed.rb +190 -198
- data/lib/openstudio-standards/standards/Standards.CoilCoolingDXTwoSpeed.rb +134 -146
- data/lib/openstudio-standards/standards/Standards.CoilHeatingDXMultiSpeed.rb +56 -60
- data/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb +151 -161
- data/lib/openstudio-standards/standards/Standards.CoilHeatingGasMultiStage.rb +30 -34
- data/lib/openstudio-standards/standards/Standards.Construction.rb +116 -132
- data/lib/openstudio-standards/standards/Standards.CoolingTower.rb +138 -0
- data/lib/openstudio-standards/standards/Standards.CoolingTowerSingleSpeed.rb +11 -0
- data/lib/openstudio-standards/standards/Standards.CoolingTowerTwoSpeed.rb +11 -0
- data/lib/openstudio-standards/standards/Standards.CoolingTowerVariableSpeed.rb +16 -0
- data/lib/openstudio-standards/standards/Standards.Fan.rb +190 -236
- data/lib/openstudio-standards/standards/Standards.FanConstantVolume.rb +0 -2
- data/lib/openstudio-standards/standards/Standards.FanOnOff.rb +0 -2
- data/lib/openstudio-standards/standards/Standards.FanVariableVolume.rb +168 -14
- data/lib/openstudio-standards/standards/Standards.FanZoneExhaust.rb +0 -2
- data/lib/openstudio-standards/standards/Standards.HeaderedPumpsConstantSpeed.rb +33 -0
- data/lib/openstudio-standards/standards/Standards.HeaderedPumpsVariableSpeed.rb +83 -0
- data/lib/openstudio-standards/standards/Standards.HeatExchangerSensLat.rb +22 -0
- data/lib/openstudio-standards/standards/Standards.Model.rb +2385 -1622
- data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +83 -35
- data/lib/openstudio-standards/standards/Standards.PlantLoop.rb +805 -395
- data/lib/openstudio-standards/standards/Standards.Pump.rb +139 -119
- data/lib/openstudio-standards/standards/Standards.PumpConstantSpeed.rb +0 -2
- data/lib/openstudio-standards/standards/Standards.PumpVariableSpeed.rb +16 -15
- data/lib/openstudio-standards/standards/Standards.ScheduleCompact.rb +35 -0
- data/lib/openstudio-standards/standards/Standards.ScheduleConstant.rb +7 -13
- data/lib/openstudio-standards/standards/Standards.ScheduleRuleset.rb +144 -59
- data/lib/openstudio-standards/standards/Standards.Space.rb +1509 -1326
- data/lib/openstudio-standards/standards/Standards.SpaceType.rb +254 -262
- data/lib/openstudio-standards/standards/Standards.SubSurface.rb +105 -105
- data/lib/openstudio-standards/standards/Standards.Surface.rb +27 -31
- data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +882 -157
- data/lib/openstudio-standards/standards/Standards.WaterHeaterMixed.rb +179 -69
- data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +75 -0
- data/lib/openstudio-standards/utilities/logging.rb +31 -38
- data/lib/openstudio-standards/utilities/simulation.rb +118 -82
- data/lib/openstudio-standards/version.rb +1 -1
- data/lib/openstudio-standards/weather/Weather.Model.rb +382 -390
- data/lib/openstudio-standards/weather/Weather.stat_file.rb +159 -78
- metadata +59 -6
@@ -1,90 +1,95 @@
|
|
1
1
|
|
2
2
|
# open the class to add methods to size all HVAC equipment
|
3
3
|
class OpenStudio::Model::Model
|
4
|
-
|
5
4
|
require_relative 'Prototype.AirTerminalSingleDuctVAVReheat'
|
6
5
|
|
7
|
-
# Creates a hot water loop with one boiler
|
6
|
+
# Creates a hot water loop with one boiler or district heating
|
8
7
|
# and add it to the model.
|
9
8
|
#
|
10
|
-
# @param boiler_fuel_type [String] valid choices are Electricity,
|
9
|
+
# @param boiler_fuel_type [String] valid choices are Electricity, NaturalGas, PropaneGas, FuelOil#1, FuelOil#2, DistrictHeating
|
11
10
|
# @return [OpenStudio::Model::PlantLoop] the resulting hot water loop
|
12
|
-
def add_hw_loop(boiler_fuel_type, building_type=nil)
|
13
|
-
|
14
|
-
OpenStudio::logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding hot water loop.")
|
11
|
+
def add_hw_loop(boiler_fuel_type, building_type = nil)
|
12
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', 'Adding hot water loop.')
|
15
13
|
|
16
|
-
#hot water loop
|
14
|
+
# hot water loop
|
17
15
|
hot_water_loop = OpenStudio::Model::PlantLoop.new(self)
|
18
16
|
hot_water_loop.setName('Hot Water Loop')
|
19
17
|
hot_water_loop.setMinimumLoopTemperature(10)
|
20
18
|
|
21
|
-
#hot water loop controls
|
19
|
+
# hot water loop controls
|
22
20
|
# TODO: Yixing check other building types and add the parameter to the prototype input if more values comes out.
|
23
|
-
if building_type ==
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
hw_delta_t_r = 20 #20F delta-T
|
30
|
-
hw_temp_c = OpenStudio.convert(hw_temp_f,'F','C').get
|
31
|
-
hw_delta_t_k = OpenStudio.convert(hw_delta_t_r,'R','K').get
|
21
|
+
hw_temp_f = if building_type == 'LargeHotel'
|
22
|
+
140 # HW setpoint 140F
|
23
|
+
else
|
24
|
+
180 # HW setpoint 180F
|
25
|
+
end
|
26
|
+
|
27
|
+
hw_delta_t_r = 20 # 20F delta-T
|
28
|
+
hw_temp_c = OpenStudio.convert(hw_temp_f, 'F', 'C').get
|
29
|
+
hw_delta_t_k = OpenStudio.convert(hw_delta_t_r, 'R', 'K').get
|
32
30
|
hw_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
33
31
|
hw_temp_sch.setName("Hot Water Loop Temp - #{hw_temp_f}F")
|
34
32
|
hw_temp_sch.defaultDaySchedule.setName("Hot Water Loop Temp - #{hw_temp_f}F Default")
|
35
|
-
hw_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),hw_temp_c)
|
36
|
-
hw_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self,hw_temp_sch)
|
37
|
-
hw_stpt_manager.setName(
|
33
|
+
hw_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), hw_temp_c)
|
34
|
+
hw_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self, hw_temp_sch)
|
35
|
+
hw_stpt_manager.setName('Hot water loop setpoint manager')
|
38
36
|
hw_stpt_manager.addToNode(hot_water_loop.supplyOutletNode)
|
39
37
|
sizing_plant = hot_water_loop.sizingPlant
|
40
38
|
sizing_plant.setLoopType('Heating')
|
41
39
|
sizing_plant.setDesignLoopExitTemperature(hw_temp_c)
|
42
40
|
sizing_plant.setLoopDesignTemperatureDifference(hw_delta_t_k)
|
43
41
|
|
44
|
-
#hot water pump
|
45
|
-
if building_type ==
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
# hot water pump
|
43
|
+
hw_pump = if building_type == 'Outpatient'
|
44
|
+
OpenStudio::Model::PumpConstantSpeed.new(self)
|
45
|
+
else
|
46
|
+
OpenStudio::Model::PumpVariableSpeed.new(self)
|
47
|
+
end
|
50
48
|
hw_pump.setName('Hot Water Loop Pump')
|
51
49
|
hw_pump_head_ft_h2o = 60.0
|
52
|
-
hw_pump_head_press_pa = OpenStudio.convert(hw_pump_head_ft_h2o, 'ftH_{2}O','Pa').get
|
50
|
+
hw_pump_head_press_pa = OpenStudio.convert(hw_pump_head_ft_h2o, 'ftH_{2}O', 'Pa').get
|
53
51
|
hw_pump.setRatedPumpHead(hw_pump_head_press_pa)
|
54
52
|
hw_pump.setMotorEfficiency(0.9)
|
55
53
|
hw_pump.setPumpControlType('Intermittent')
|
56
54
|
hw_pump.addToNode(hot_water_loop.supplyInletNode)
|
57
55
|
|
58
|
-
#
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
boiler.
|
74
|
-
boiler.setDesignWaterOutletTemperature(81)
|
56
|
+
# DistrictHeating
|
57
|
+
if boiler_fuel_type == 'DistrictHeating'
|
58
|
+
dist_ht = OpenStudio::Model::DistrictHeating.new(self)
|
59
|
+
dist_ht.setName('Purchased Heating')
|
60
|
+
dist_ht.autosizeNominalCapacity
|
61
|
+
hot_water_loop.addSupplyBranchForComponent(dist_ht)
|
62
|
+
# Boiler
|
63
|
+
else
|
64
|
+
boiler_max_t_f = 203
|
65
|
+
boiler_max_t_c = OpenStudio.convert(boiler_max_t_f, 'F', 'C').get
|
66
|
+
boiler = OpenStudio::Model::BoilerHotWater.new(self)
|
67
|
+
boiler.setName('Hot Water Loop Boiler')
|
68
|
+
boiler.setEfficiencyCurveTemperatureEvaluationVariable('LeavingBoiler')
|
69
|
+
boiler.setFuelType(boiler_fuel_type)
|
70
|
+
boiler.setDesignWaterOutletTemperature(hw_temp_c)
|
71
|
+
boiler.setNominalThermalEfficiency(0.78)
|
75
72
|
boiler.setMaximumPartLoadRatio(1.2)
|
76
|
-
boiler.
|
77
|
-
boiler.
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
73
|
+
boiler.setWaterOutletUpperTemperatureLimit(boiler_max_t_c)
|
74
|
+
boiler.setBoilerFlowMode('LeavingSetpointModulated')
|
75
|
+
hot_water_loop.addSupplyBranchForComponent(boiler)
|
76
|
+
|
77
|
+
if building_type == 'LargeHotel'
|
78
|
+
boiler.setEfficiencyCurveTemperatureEvaluationVariable('LeavingBoiler')
|
79
|
+
boiler.setDesignWaterOutletTemperature(81)
|
80
|
+
boiler.setMaximumPartLoadRatio(1.2)
|
81
|
+
boiler.setSizingFactor(1.2)
|
82
|
+
boiler.setWaterOutletUpperTemperatureLimit(95)
|
83
|
+
end
|
85
84
|
|
85
|
+
# TODO: Yixing. Add the temperature setpoint will cost the simulation with
|
86
|
+
# thousands of Severe Errors. Need to figure this out later.
|
87
|
+
# boiler_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self,hw_temp_sch)
|
88
|
+
# boiler_stpt_manager.setName("Boiler outlet setpoint manager")
|
89
|
+
# boiler_stpt_manager.addToNode(boiler.outletModelObject.get.to_Node.get)
|
90
|
+
end
|
86
91
|
|
87
|
-
#hot water loop pipes
|
92
|
+
# hot water loop pipes
|
88
93
|
boiler_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(self)
|
89
94
|
hot_water_loop.addSupplyBranchForComponent(boiler_bypass_pipe)
|
90
95
|
coil_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(self)
|
@@ -97,33 +102,32 @@ class OpenStudio::Model::Model
|
|
97
102
|
demand_outlet_pipe.addToNode(hot_water_loop.demandOutletNode)
|
98
103
|
|
99
104
|
return hot_water_loop
|
100
|
-
|
101
105
|
end
|
102
106
|
|
103
107
|
# Creates a chilled water loop and adds it to the model.
|
104
108
|
#
|
105
|
-
# @param
|
109
|
+
# @param template [String] Valid choices are 90.1-2004,
|
106
110
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
107
111
|
# @param chw_pumping_type [String] valid choices are const_pri, const_pri_var_sec
|
108
112
|
# @param chiller_cooling_type [String] valid choices are AirCooled, WaterCooled
|
109
113
|
# @param chiller_condenser_type [String] valid choices are WithCondenser, WithoutCondenser, nil
|
110
114
|
# @param chiller_compressor_type [String] valid choices are Centrifugal, Reciprocating, Rotary Screw, Scroll, nil
|
111
|
-
# @param
|
115
|
+
# @param cooling_fuel [String] cooling fuel. Valid choices are:
|
116
|
+
# Electricity, DistrictCooling
|
112
117
|
# @param condenser_water_loop [OpenStudio::Model::PlantLoop] optional condenser water loop
|
113
118
|
# for water-cooled chillers. If this is not passed in, the chillers will be air cooled.
|
114
119
|
# @return [OpenStudio::Model::PlantLoop] the resulting chilled water loop
|
115
|
-
def add_chw_loop(
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
OpenStudio
|
126
|
-
|
120
|
+
def add_chw_loop(template,
|
121
|
+
chw_pumping_type,
|
122
|
+
chiller_cooling_type,
|
123
|
+
chiller_condenser_type,
|
124
|
+
chiller_compressor_type,
|
125
|
+
cooling_fuel,
|
126
|
+
condenser_water_loop = nil,
|
127
|
+
building_type = nil,
|
128
|
+
num_chillers = 1)
|
129
|
+
|
130
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', 'Adding chilled water loop.')
|
127
131
|
|
128
132
|
# Chilled water loop
|
129
133
|
chilled_water_loop = OpenStudio::Model::PlantLoop.new(self)
|
@@ -132,22 +136,22 @@ class OpenStudio::Model::Model
|
|
132
136
|
chilled_water_loop.setMinimumLoopTemperature(1)
|
133
137
|
|
134
138
|
# Chilled water loop controls
|
135
|
-
chw_temp_f = 44 #CHW setpoint 44F
|
136
|
-
chw_delta_t_r = 10.1 #10.1F delta-T
|
139
|
+
chw_temp_f = 44 # CHW setpoint 44F
|
140
|
+
chw_delta_t_r = 10.1 # 10.1F delta-T
|
137
141
|
# TODO: Yixing check the CHW Setpoint from standards
|
138
|
-
# TODO: Should be a OutdoorAirReset, see the changes I've made in Standards.PlantLoop.
|
142
|
+
# TODO: Should be a OutdoorAirReset, see the changes I've made in Standards.PlantLoop.apply_prm_baseline_temperatures
|
139
143
|
if building_type == 'LargeHotel'
|
140
|
-
chw_temp_f = 45 #CHW setpoint 45F
|
141
|
-
chw_delta_t_r = 12 #12F delta-T
|
144
|
+
chw_temp_f = 45 # CHW setpoint 45F
|
145
|
+
chw_delta_t_r = 12 # 12F delta-T
|
142
146
|
end
|
143
|
-
chw_temp_c = OpenStudio.convert(chw_temp_f,'F','C').get
|
144
|
-
chw_delta_t_k = OpenStudio.convert(chw_delta_t_r,'R','K').get
|
147
|
+
chw_temp_c = OpenStudio.convert(chw_temp_f, 'F', 'C').get
|
148
|
+
chw_delta_t_k = OpenStudio.convert(chw_delta_t_r, 'R', 'K').get
|
145
149
|
chw_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
146
150
|
chw_temp_sch.setName("Chilled Water Loop Temp - #{chw_temp_f}F")
|
147
151
|
chw_temp_sch.defaultDaySchedule.setName("Chilled Water Loop Temp - #{chw_temp_f}F Default")
|
148
|
-
chw_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),chw_temp_c)
|
149
|
-
chw_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self,chw_temp_sch)
|
150
|
-
chw_stpt_manager.setName(
|
152
|
+
chw_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), chw_temp_c)
|
153
|
+
chw_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self, chw_temp_sch)
|
154
|
+
chw_stpt_manager.setName('Chilled water loop setpoint manager')
|
151
155
|
chw_stpt_manager.addToNode(chilled_water_loop.supplyOutletNode)
|
152
156
|
|
153
157
|
sizing_plant = chilled_water_loop.sizingPlant
|
@@ -161,7 +165,7 @@ class OpenStudio::Model::Model
|
|
161
165
|
pri_chw_pump = OpenStudio::Model::PumpVariableSpeed.new(self)
|
162
166
|
pri_chw_pump.setName('Chilled Water Loop Pump')
|
163
167
|
pri_chw_pump_head_ft_h2o = 60.0
|
164
|
-
pri_chw_pump_head_press_pa = OpenStudio.convert(pri_chw_pump_head_ft_h2o, 'ftH_{2}O','Pa').get
|
168
|
+
pri_chw_pump_head_press_pa = OpenStudio.convert(pri_chw_pump_head_ft_h2o, 'ftH_{2}O', 'Pa').get
|
165
169
|
pri_chw_pump.setRatedPumpHead(pri_chw_pump_head_press_pa)
|
166
170
|
pri_chw_pump.setMotorEfficiency(0.9)
|
167
171
|
# Flat pump curve makes it behave as a constant speed pump
|
@@ -177,7 +181,7 @@ class OpenStudio::Model::Model
|
|
177
181
|
pri_chw_pump = OpenStudio::Model::PumpConstantSpeed.new(self)
|
178
182
|
pri_chw_pump.setName('Chilled Water Loop Primary Pump')
|
179
183
|
pri_chw_pump_head_ft_h2o = 15
|
180
|
-
pri_chw_pump_head_press_pa = OpenStudio.convert(pri_chw_pump_head_ft_h2o, 'ftH_{2}O','Pa').get
|
184
|
+
pri_chw_pump_head_press_pa = OpenStudio.convert(pri_chw_pump_head_ft_h2o, 'ftH_{2}O', 'Pa').get
|
181
185
|
pri_chw_pump.setRatedPumpHead(pri_chw_pump_head_press_pa)
|
182
186
|
pri_chw_pump.setMotorEfficiency(0.9)
|
183
187
|
pri_chw_pump.setPumpControlType('Intermittent')
|
@@ -186,7 +190,7 @@ class OpenStudio::Model::Model
|
|
186
190
|
sec_chw_pump = OpenStudio::Model::PumpVariableSpeed.new(self)
|
187
191
|
sec_chw_pump.setName('Chilled Water Loop Secondary Pump')
|
188
192
|
sec_chw_pump_head_ft_h2o = 45
|
189
|
-
sec_chw_pump_head_press_pa = OpenStudio.convert(sec_chw_pump_head_ft_h2o, 'ftH_{2}O','Pa').get
|
193
|
+
sec_chw_pump_head_press_pa = OpenStudio.convert(sec_chw_pump_head_ft_h2o, 'ftH_{2}O', 'Pa').get
|
190
194
|
sec_chw_pump.setRatedPumpHead(sec_chw_pump_head_press_pa)
|
191
195
|
sec_chw_pump.setMotorEfficiency(0.9)
|
192
196
|
# Curve makes it perform like variable speed pump
|
@@ -201,47 +205,55 @@ class OpenStudio::Model::Model
|
|
201
205
|
chilled_water_loop.setCommonPipeSimulation('CommonPipe')
|
202
206
|
end
|
203
207
|
|
208
|
+
# DistrictCooling
|
209
|
+
if cooling_fuel == 'DistrictCooling'
|
210
|
+
dist_clg = OpenStudio::Model::DistrictCooling.new(self)
|
211
|
+
dist_clg.setName('Purchased Cooling')
|
212
|
+
dist_clg.autosizeNominalCapacity
|
213
|
+
chilled_water_loop.addSupplyBranchForComponent(dist_clg)
|
214
|
+
# Chiller
|
215
|
+
else
|
204
216
|
|
205
|
-
num_chillers.times do |i|
|
206
217
|
# Make the correct type of chiller based these properties
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
218
|
+
num_chillers.times do |i|
|
219
|
+
chiller = OpenStudio::Model::ChillerElectricEIR.new(self)
|
220
|
+
chiller.setName("#{template} #{chiller_cooling_type} #{chiller_condenser_type} #{chiller_compressor_type} Chiller #{i}")
|
221
|
+
chilled_water_loop.addSupplyBranchForComponent(chiller)
|
222
|
+
chiller.setReferenceLeavingChilledWaterTemperature(chw_temp_c)
|
223
|
+
ref_cond_wtr_temp_f = 95
|
224
|
+
ref_cond_wtr_temp_c = OpenStudio.convert(ref_cond_wtr_temp_f, 'F', 'C').get
|
225
|
+
chiller.setReferenceEnteringCondenserFluidTemperature(ref_cond_wtr_temp_c)
|
226
|
+
chiller.setMinimumPartLoadRatio(0.15)
|
227
|
+
chiller.setMaximumPartLoadRatio(1.0)
|
228
|
+
chiller.setOptimumPartLoadRatio(1.0)
|
229
|
+
chiller.setMinimumUnloadingRatio(0.25)
|
230
|
+
chiller.setCondenserType('AirCooled')
|
231
|
+
chiller.setLeavingChilledWaterLowerTemperatureLimit(OpenStudio.convert(36, 'F', 'C').get)
|
232
|
+
chiller.setChillerFlowMode('ConstantFlow')
|
233
|
+
|
234
|
+
if building_type == 'LargeHotel' || building_type == 'Hospital'
|
235
|
+
chiller.setSizingFactor(0.5)
|
236
|
+
end
|
226
237
|
|
227
|
-
|
238
|
+
# if building_type == "LargeHotel"
|
228
239
|
# TODO: Yixing. Add the temperature setpoint and change the flow mode will cost the simulation with
|
229
240
|
# thousands of Severe Errors. Need to figure this out later.
|
230
|
-
#chiller.setChillerFlowMode('LeavingSetpointModulated')
|
231
|
-
#chiller_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self,chw_temp_sch)
|
232
|
-
#chiller_stpt_manager.setName("chiller outlet setpoint manager")
|
233
|
-
#chiller_stpt_manager.addToNode(chiller.supplyOutletModelObject.get.to_Node.get)
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
+
# chiller.setChillerFlowMode('LeavingSetpointModulated')
|
242
|
+
# chiller_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self,chw_temp_sch)
|
243
|
+
# chiller_stpt_manager.setName("chiller outlet setpoint manager")
|
244
|
+
# chiller_stpt_manager.addToNode(chiller.supplyOutletModelObject.get.to_Node.get)
|
245
|
+
# end
|
246
|
+
|
247
|
+
# Connect the chiller to the condenser loop if
|
248
|
+
# one was supplied.
|
249
|
+
if condenser_water_loop
|
250
|
+
condenser_water_loop.addDemandBranchForComponent(chiller)
|
251
|
+
chiller.setCondenserType('WaterCooled')
|
252
|
+
end
|
241
253
|
end
|
242
254
|
end
|
243
255
|
|
244
|
-
|
256
|
+
# chilled water loop pipes
|
245
257
|
chiller_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(self)
|
246
258
|
chilled_water_loop.addSupplyBranchForComponent(chiller_bypass_pipe)
|
247
259
|
coil_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(self)
|
@@ -254,19 +266,26 @@ class OpenStudio::Model::Model
|
|
254
266
|
demand_outlet_pipe.addToNode(chilled_water_loop.demandOutletNode)
|
255
267
|
|
256
268
|
return chilled_water_loop
|
257
|
-
|
258
269
|
end
|
259
270
|
|
260
271
|
# Creates a condenser water loop and adds it to the model.
|
261
272
|
#
|
273
|
+
# @param cooling_tower_type [String] valid choices are Open Cooling Tower, Closed Cooling Tower
|
274
|
+
# @param cooling_tower_fan_type [String] valid choices are Centrifugal, Propeller or Axial
|
275
|
+
# @param cooling_tower_capacity_control [String] valid choices are Fluid Bypass, Fan Cycling, TwoSpeed Fan, Variable Speed Fan
|
276
|
+
# @param number_of_cells_per_tower [Integer] the number of discrete cells per tower
|
262
277
|
# @param number_cooling_towers [Integer] the number of cooling towers to be added (in parallel)
|
278
|
+
# @param building_type [String] the building type
|
263
279
|
# @return [OpenStudio::Model::PlantLoop] the resulting plant loop
|
280
|
+
def add_cw_loop(template,
|
281
|
+
cooling_tower_type,
|
282
|
+
cooling_tower_fan_type,
|
283
|
+
cooling_tower_capacity_control,
|
284
|
+
number_of_cells_per_tower,
|
285
|
+
number_cooling_towers = 1,
|
286
|
+
building_type = nil)
|
264
287
|
|
265
|
-
|
266
|
-
def add_cw_loop(building_type, building_vintage, number_cooling_towers = 1)
|
267
|
-
|
268
|
-
|
269
|
-
OpenStudio::logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding condenser water loop.")
|
288
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', 'Adding condenser water loop.')
|
270
289
|
|
271
290
|
# Condenser water loop
|
272
291
|
condenser_water_loop = OpenStudio::Model::PlantLoop.new(self)
|
@@ -275,75 +294,84 @@ class OpenStudio::Model::Model
|
|
275
294
|
condenser_water_loop.setMinimumLoopTemperature(5)
|
276
295
|
|
277
296
|
# Condenser water loop controls
|
278
|
-
cw_temp_f = 70 #CW setpoint 70F
|
279
|
-
cw_temp_sizing_f = 85 #CW sized to deliver 85F
|
280
|
-
cw_delta_t_r = 10 #10F delta-T
|
281
|
-
cw_approach_delta_t_r = 7 #7F approach
|
282
|
-
cw_temp_c = OpenStudio.convert(cw_temp_f,'F','C').get
|
283
|
-
cw_temp_sizing_c = OpenStudio.convert(cw_temp_sizing_f,'F','C').get
|
284
|
-
cw_delta_t_k = OpenStudio.convert(cw_delta_t_r,'R','K').get
|
285
|
-
cw_approach_delta_t_k = OpenStudio.convert(cw_approach_delta_t_r,'R','K').get
|
297
|
+
cw_temp_f = 70 # CW setpoint 70F
|
298
|
+
cw_temp_sizing_f = 85 # CW sized to deliver 85F
|
299
|
+
cw_delta_t_r = 10 # 10F delta-T
|
300
|
+
cw_approach_delta_t_r = 7 # 7F approach
|
301
|
+
cw_temp_c = OpenStudio.convert(cw_temp_f, 'F', 'C').get
|
302
|
+
cw_temp_sizing_c = OpenStudio.convert(cw_temp_sizing_f, 'F', 'C').get
|
303
|
+
cw_delta_t_k = OpenStudio.convert(cw_delta_t_r, 'R', 'K').get
|
304
|
+
cw_approach_delta_t_k = OpenStudio.convert(cw_approach_delta_t_r, 'R', 'K').get
|
286
305
|
cw_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
287
306
|
cw_temp_sch.setName("Condenser Water Loop Temp - #{cw_temp_f}F")
|
288
307
|
cw_temp_sch.defaultDaySchedule.setName("Condenser Water Loop Temp - #{cw_temp_f}F Default")
|
289
|
-
cw_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),cw_temp_c)
|
290
|
-
cw_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self,cw_temp_sch)
|
308
|
+
cw_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), cw_temp_c)
|
309
|
+
cw_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self, cw_temp_sch)
|
291
310
|
cw_stpt_manager.addToNode(condenser_water_loop.supplyOutletNode)
|
292
311
|
sizing_plant = condenser_water_loop.sizingPlant
|
293
312
|
sizing_plant.setLoopType('Condenser')
|
294
313
|
sizing_plant.setDesignLoopExitTemperature(cw_temp_sizing_c)
|
295
314
|
sizing_plant.setLoopDesignTemperatureDifference(cw_delta_t_k)
|
296
315
|
|
297
|
-
|
316
|
+
# Condenser water pump
|
317
|
+
if building_type == 'Hospital' && (template == 'DOE Ref 1980-2004' || template == 'DOE Ref Pre-1980')
|
298
318
|
cw_pump = OpenStudio::Model::PumpConstantSpeed.new(self)
|
299
319
|
cw_pump.setName('Condenser Water Loop Pump')
|
300
320
|
cw_pump_head_ft_h2o = 60.0
|
301
|
-
cw_pump_head_press_pa = OpenStudio.convert(cw_pump_head_ft_h2o, 'ftH_{2}O','Pa').get
|
321
|
+
cw_pump_head_press_pa = OpenStudio.convert(cw_pump_head_ft_h2o, 'ftH_{2}O', 'Pa').get
|
302
322
|
cw_pump.setRatedPumpHead(cw_pump_head_press_pa)
|
303
323
|
cw_pump.addToNode(condenser_water_loop.supplyInletNode)
|
304
324
|
else
|
305
325
|
# Condenser water pump #TODO make this into a HeaderedPump:VariableSpeed
|
306
|
-
cw_pump = OpenStudio::Model::
|
326
|
+
cw_pump = OpenStudio::Model::PumpConstantSpeed.new(self)
|
307
327
|
cw_pump.setName('Condenser Water Loop Pump')
|
308
328
|
cw_pump_head_ft_h2o = 49.7
|
309
|
-
cw_pump_head_press_pa = OpenStudio.convert(cw_pump_head_ft_h2o, 'ftH_{2}O','Pa').get
|
329
|
+
cw_pump_head_press_pa = OpenStudio.convert(cw_pump_head_ft_h2o, 'ftH_{2}O', 'Pa').get
|
310
330
|
cw_pump.setRatedPumpHead(cw_pump_head_press_pa)
|
311
|
-
# Curve makes it perform like variable speed pump
|
312
|
-
cw_pump.setFractionofMotorInefficienciestoFluidStream(0)
|
313
|
-
cw_pump.setCoefficient1ofthePartLoadPerformanceCurve(0)
|
314
|
-
cw_pump.setCoefficient2ofthePartLoadPerformanceCurve(0.0216)
|
315
|
-
cw_pump.setCoefficient3ofthePartLoadPerformanceCurve(-0.0325)
|
316
|
-
cw_pump.setCoefficient4ofthePartLoadPerformanceCurve(1.0095)
|
317
331
|
cw_pump.setPumpControlType('Intermittent')
|
318
332
|
cw_pump.addToNode(condenser_water_loop.supplyInletNode)
|
319
333
|
end
|
320
334
|
|
321
|
-
# TODO move cooling tower curve to lookup from spreadsheet
|
322
|
-
cooling_tower_fan_curve = OpenStudio::Model::CurveCubic.new(self)
|
323
|
-
cooling_tower_fan_curve.setName('Cooling Tower Fan Curve')
|
324
|
-
cooling_tower_fan_curve.setCoefficient1Constant(0)
|
325
|
-
cooling_tower_fan_curve.setCoefficient2x(0)
|
326
|
-
cooling_tower_fan_curve.setCoefficient3xPOW2(0)
|
327
|
-
cooling_tower_fan_curve.setCoefficient4xPOW3(1)
|
328
|
-
cooling_tower_fan_curve.setMinimumValueofx(0)
|
329
|
-
cooling_tower_fan_curve.setMaximumValueofx(1)
|
330
|
-
|
331
335
|
# Cooling towers
|
332
|
-
|
333
|
-
|
336
|
+
# Per PNNL PRM Reference Manual
|
337
|
+
number_cooling_towers.times do |_i|
|
338
|
+
sizing_factor = 1 / number_cooling_towers
|
339
|
+
twr_name = "#{cooling_tower_fan_type} #{cooling_tower_capacity_control} #{cooling_tower_type}"
|
340
|
+
|
341
|
+
# Tower object depends on the control type
|
342
|
+
cooling_tower = nil
|
343
|
+
case cooling_tower_capacity_control
|
344
|
+
when 'Fluid Bypass', 'Fan Cycling'
|
334
345
|
cooling_tower = OpenStudio::Model::CoolingTowerSingleSpeed.new(self)
|
335
|
-
|
336
|
-
|
337
|
-
|
346
|
+
if cooling_tower_capacity_control == 'Fluid Bypass'
|
347
|
+
cooling_tower.setCellControl('FluidBypass')
|
348
|
+
else
|
349
|
+
cooling_tower.setCellControl('FanCycling')
|
350
|
+
end
|
351
|
+
when 'TwoSpeed Fan'
|
352
|
+
cooling_tower = OpenStudio::Model::CoolingTowerTwoSpeed.new(self)
|
353
|
+
# TODO: expose newer cooling tower sizing fields in API
|
354
|
+
# cooling_tower.setLowFanSpeedAirFlowRateSizingFactor(0.5)
|
355
|
+
# cooling_tower.setLowFanSpeedFanPowerSizingFactor(0.3)
|
356
|
+
# cooling_tower.setLowFanSpeedUFactorTimesAreaSizingFactor
|
357
|
+
# cooling_tower.setLowSpeedNominalCapacitySizingFactor
|
358
|
+
when 'Variable Speed Fan'
|
338
359
|
cooling_tower = OpenStudio::Model::CoolingTowerVariableSpeed.new(self)
|
339
|
-
cooling_tower.setName("#{condenser_water_loop.name} Cooling Tower #{i}")
|
340
360
|
cooling_tower.setDesignApproachTemperature(cw_approach_delta_t_k)
|
341
361
|
cooling_tower.setDesignRangeTemperature(cw_delta_t_k)
|
342
|
-
cooling_tower.setFanPowerRatioFunctionofAirFlowRateRatioCurve(cooling_tower_fan_curve)
|
343
|
-
cooling_tower.setMinimumAirFlowRateRatio(0.2)
|
344
362
|
cooling_tower.setFractionofTowerCapacityinFreeConvectionRegime(0.125)
|
345
|
-
|
346
|
-
cooling_tower.
|
363
|
+
twr_fan_curve = add_curve('VSD-TWR-FAN-FPLR')
|
364
|
+
cooling_tower.setFanPowerRatioFunctionofAirFlowRateRatioCurve(twr_fan_curve)
|
365
|
+
else
|
366
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.Model.Model', "#{cooling_tower_capacity_control} is not a valid choice of cooling tower capacity control. Valid choices are Fluid Bypass, Fan Cycling, TwoSpeed Fan, Variable Speed Fan.")
|
367
|
+
end
|
368
|
+
|
369
|
+
# Set the properties that apply to all tower types
|
370
|
+
# and attach to the condenser loop.
|
371
|
+
unless cooling_tower.nil?
|
372
|
+
cooling_tower.setName(twr_name)
|
373
|
+
cooling_tower.setSizingFactor(sizing_factor)
|
374
|
+
cooling_tower.setNumberofCells(number_of_cells_per_tower)
|
347
375
|
condenser_water_loop.addSupplyBranchForComponent(cooling_tower)
|
348
376
|
end
|
349
377
|
end
|
@@ -361,7 +389,6 @@ class OpenStudio::Model::Model
|
|
361
389
|
demand_outlet_pipe.addToNode(condenser_water_loop.demandOutletNode)
|
362
390
|
|
363
391
|
return condenser_water_loop
|
364
|
-
|
365
392
|
end
|
366
393
|
|
367
394
|
# Creates a heat pump loop which has a boiler and fluid cooler
|
@@ -369,9 +396,8 @@ class OpenStudio::Model::Model
|
|
369
396
|
#
|
370
397
|
# @return [OpenStudio::Model::PlantLoop] the resulting plant loop
|
371
398
|
# @todo replace cooling tower with fluid cooler once added to OS 1.9.0
|
372
|
-
def add_hp_loop(building_type=nil)
|
373
|
-
|
374
|
-
OpenStudio::logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding heat pump loop.")
|
399
|
+
def add_hp_loop(building_type = nil)
|
400
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', 'Adding heat pump loop.')
|
375
401
|
|
376
402
|
# Heat Pump loop
|
377
403
|
heat_pump_water_loop = OpenStudio::Model::PlantLoop.new(self)
|
@@ -382,25 +408,25 @@ class OpenStudio::Model::Model
|
|
382
408
|
# Heat Pump loop controls
|
383
409
|
hp_high_temp_f = 65 # Supplemental heat below 65F
|
384
410
|
hp_low_temp_f = 41 # Supplemental cooling below 41F
|
385
|
-
hp_temp_sizing_f = 102.2 #CW sized to deliver 102.2F
|
386
|
-
hp_delta_t_r = 19.8 #19.8F delta-T
|
387
|
-
boiler_hw_temp_f = 86 #Boiler makes 86F water
|
411
|
+
hp_temp_sizing_f = 102.2 # CW sized to deliver 102.2F
|
412
|
+
hp_delta_t_r = 19.8 # 19.8F delta-T
|
413
|
+
boiler_hw_temp_f = 86 # Boiler makes 86F water
|
388
414
|
|
389
|
-
hp_high_temp_c = OpenStudio.convert(hp_high_temp_f,'F','C').get
|
390
|
-
hp_low_temp_c = OpenStudio.convert(hp_low_temp_f,'F','C').get
|
391
|
-
hp_temp_sizing_c = OpenStudio.convert(hp_temp_sizing_f,'F','C').get
|
392
|
-
hp_delta_t_k = OpenStudio.convert(hp_delta_t_r,'R','K').get
|
393
|
-
boiler_hw_temp_c = OpenStudio.convert(boiler_hw_temp_f,'F','C').get
|
415
|
+
hp_high_temp_c = OpenStudio.convert(hp_high_temp_f, 'F', 'C').get
|
416
|
+
hp_low_temp_c = OpenStudio.convert(hp_low_temp_f, 'F', 'C').get
|
417
|
+
hp_temp_sizing_c = OpenStudio.convert(hp_temp_sizing_f, 'F', 'C').get
|
418
|
+
hp_delta_t_k = OpenStudio.convert(hp_delta_t_r, 'R', 'K').get
|
419
|
+
boiler_hw_temp_c = OpenStudio.convert(boiler_hw_temp_f, 'F', 'C').get
|
394
420
|
|
395
421
|
hp_high_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
396
422
|
hp_high_temp_sch.setName("Heat Pump Loop High Temp - #{hp_high_temp_f}F")
|
397
423
|
hp_high_temp_sch.defaultDaySchedule.setName("Heat Pump Loop High Temp - #{hp_high_temp_f}F Default")
|
398
|
-
hp_high_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),hp_high_temp_c)
|
424
|
+
hp_high_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), hp_high_temp_c)
|
399
425
|
|
400
426
|
hp_low_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
401
427
|
hp_low_temp_sch.setName("Heat Pump Loop Low Temp - #{hp_low_temp_f}F")
|
402
428
|
hp_low_temp_sch.defaultDaySchedule.setName("Heat Pump Loop Low Temp - #{hp_low_temp_f}F Default")
|
403
|
-
hp_low_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),hp_low_temp_c)
|
429
|
+
hp_low_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), hp_low_temp_c)
|
404
430
|
|
405
431
|
hp_stpt_manager = OpenStudio::Model::SetpointManagerScheduledDualSetpoint.new(self)
|
406
432
|
hp_stpt_manager.setHighSetpointSchedule(hp_high_temp_sch)
|
@@ -416,7 +442,7 @@ class OpenStudio::Model::Model
|
|
416
442
|
hp_pump = OpenStudio::Model::PumpConstantSpeed.new(self)
|
417
443
|
hp_pump.setName('Heat Pump Loop Pump')
|
418
444
|
hp_pump_head_ft_h2o = 60
|
419
|
-
hp_pump_head_press_pa = OpenStudio.convert(hp_pump_head_ft_h2o, 'ftH_{2}O','Pa').get
|
445
|
+
hp_pump_head_press_pa = OpenStudio.convert(hp_pump_head_ft_h2o, 'ftH_{2}O', 'Pa').get
|
420
446
|
hp_pump.setRatedPumpHead(hp_pump_head_press_pa)
|
421
447
|
hp_pump.setPumpControlType('Intermittent')
|
422
448
|
hp_pump.addToNode(heat_pump_water_loop.supplyInletNode)
|
@@ -436,14 +462,14 @@ class OpenStudio::Model::Model
|
|
436
462
|
hp_stpt_manager_2.addToNode(cooling_tower.outletModelObject.get.to_Node.get)
|
437
463
|
|
438
464
|
else
|
439
|
-
# TODO replace with FluidCooler:TwoSpeed when available
|
465
|
+
# TODO: replace with FluidCooler:TwoSpeed when available
|
440
466
|
# cooling_tower = OpenStudio::Model::CoolingTowerTwoSpeed.new(self)
|
441
467
|
# cooling_tower.setName("#{heat_pump_water_loop.name} Sup Cooling Tower")
|
442
468
|
# heat_pump_water_loop.addSupplyBranchForComponent(cooling_tower)
|
443
469
|
fluid_cooler = OpenStudio::Model::EvaporativeFluidCoolerSingleSpeed.new(self)
|
444
470
|
fluid_cooler.setName("#{heat_pump_water_loop.name} Sup Cooling Tower")
|
445
|
-
fluid_cooler.setDesignSprayWaterFlowRate(0.002208)
|
446
|
-
fluid_cooler.setPerformanceInputMethod(
|
471
|
+
fluid_cooler.setDesignSprayWaterFlowRate(0.002208) # Based on HighRiseApartment
|
472
|
+
fluid_cooler.setPerformanceInputMethod('UFactorTimesAreaAndDesignWaterFlowRate')
|
447
473
|
heat_pump_water_loop.addSupplyBranchForComponent(fluid_cooler)
|
448
474
|
end
|
449
475
|
|
@@ -485,12 +511,11 @@ class OpenStudio::Model::Model
|
|
485
511
|
demand_outlet_pipe.addToNode(heat_pump_water_loop.demandOutletNode)
|
486
512
|
|
487
513
|
return heat_pump_water_loop
|
488
|
-
|
489
514
|
end
|
490
515
|
|
491
516
|
# Creates a VAV system and adds it to the model.
|
492
517
|
#
|
493
|
-
# @param
|
518
|
+
# @param template [String] Valid choices are 90.1-2004,
|
494
519
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
495
520
|
# @param sys_name [String] the name of the system, or nil in which case it will be defaulted
|
496
521
|
# @param hot_water_loop [String] hot water loop to connect heating and reheat coils to
|
@@ -505,32 +530,35 @@ class OpenStudio::Model::Model
|
|
505
530
|
# @param vav_fan_pressure_rise [Double] fan pressure rise, in Pa
|
506
531
|
# @param return_plenum [OpenStudio::Model::ThermalZone] the zone to attach as
|
507
532
|
# the supply plenum, or nil, in which case no return plenum will be used.
|
533
|
+
# @param electric_reheat [Bool] if true, this system will have electric reheat coils,
|
534
|
+
# but if false, the reheat coils will be served by the hot_water_loop.
|
508
535
|
# @param building_type [String] the building type
|
509
536
|
# @return [OpenStudio::Model::AirLoopHVAC] the resulting VAV air loop
|
510
|
-
def add_vav_reheat(
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
537
|
+
def add_vav_reheat(template,
|
538
|
+
sys_name,
|
539
|
+
hot_water_loop,
|
540
|
+
chilled_water_loop,
|
541
|
+
thermal_zones,
|
542
|
+
hvac_op_sch,
|
543
|
+
oa_damper_sch,
|
544
|
+
vav_fan_efficiency,
|
545
|
+
vav_fan_motor_efficiency,
|
546
|
+
vav_fan_pressure_rise,
|
547
|
+
return_plenum,
|
548
|
+
electric_reheat = false,
|
549
|
+
building_type = nil)
|
550
|
+
|
551
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding VAV system for #{thermal_zones.size} zones.")
|
524
552
|
thermal_zones.each do |zone|
|
525
|
-
OpenStudio
|
553
|
+
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.Model.Model', "---#{zone.name}")
|
526
554
|
end
|
527
555
|
|
528
|
-
hw_temp_f = 180 #HW setpoint 180F
|
529
|
-
hw_delta_t_r = 20 #20F delta-T
|
530
|
-
hw_temp_c = OpenStudio.convert(hw_temp_f,'F','C').get
|
531
|
-
hw_delta_t_k = OpenStudio.convert(hw_delta_t_r,'R','K').get
|
556
|
+
hw_temp_f = 180 # HW setpoint 180F
|
557
|
+
hw_delta_t_r = 20 # 20F delta-T
|
558
|
+
hw_temp_c = OpenStudio.convert(hw_temp_f, 'F', 'C').get
|
559
|
+
hw_delta_t_k = OpenStudio.convert(hw_delta_t_r, 'R', 'K').get
|
532
560
|
|
533
|
-
if building_type ==
|
561
|
+
if building_type == 'LargeHotel'
|
534
562
|
rht_sa_temp_f = 90 # VAV box reheat to 90F for large hotel
|
535
563
|
zone_htg_sa_temp_f = 104 # Zone heating design supply air temperature to 104 F
|
536
564
|
else
|
@@ -539,52 +567,52 @@ class OpenStudio::Model::Model
|
|
539
567
|
end
|
540
568
|
|
541
569
|
# hvac operation schedule
|
542
|
-
if hvac_op_sch.nil?
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
570
|
+
hvac_op_sch = if hvac_op_sch.nil?
|
571
|
+
alwaysOnDiscreteSchedule
|
572
|
+
else
|
573
|
+
add_schedule(hvac_op_sch)
|
574
|
+
end
|
547
575
|
|
548
576
|
# oa damper schedule
|
549
|
-
if oa_damper_sch.nil?
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
577
|
+
oa_damper_sch = if oa_damper_sch.nil?
|
578
|
+
alwaysOnDiscreteSchedule
|
579
|
+
else
|
580
|
+
add_schedule(oa_damper_sch)
|
581
|
+
end
|
554
582
|
|
555
583
|
# control temps used across all air handlers
|
556
584
|
clg_sa_temp_f = 55.04 # Central deck clg temp 55F
|
557
585
|
prehtg_sa_temp_f = 44.6 # Preheat to 44.6F
|
558
586
|
preclg_sa_temp_f = 55.04 # Precool to 55F
|
559
587
|
htg_sa_temp_f = 55.04 # Central deck htg temp 55F
|
560
|
-
if building_type ==
|
588
|
+
if building_type == 'LargeHotel'
|
561
589
|
htg_sa_temp_f = 62 # Central deck htg temp 55F
|
562
590
|
end
|
563
591
|
rht_sa_temp_f = 104 # VAV box reheat to 104F
|
564
|
-
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f,'F','C').get
|
565
|
-
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f,'F','C').get
|
566
|
-
preclg_sa_temp_c = OpenStudio.convert(preclg_sa_temp_f,'F','C').get
|
567
|
-
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f,'F','C').get
|
568
|
-
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f,'F','C').get
|
569
|
-
zone_htg_sa_temp_c = OpenStudio.convert(zone_htg_sa_temp_f,'F','C').get
|
592
|
+
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f, 'F', 'C').get
|
593
|
+
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f, 'F', 'C').get
|
594
|
+
preclg_sa_temp_c = OpenStudio.convert(preclg_sa_temp_f, 'F', 'C').get
|
595
|
+
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f, 'F', 'C').get
|
596
|
+
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f, 'F', 'C').get
|
597
|
+
zone_htg_sa_temp_c = OpenStudio.convert(zone_htg_sa_temp_f, 'F', 'C').get
|
570
598
|
sa_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
571
599
|
sa_temp_sch.setName("Supply Air Temp - #{clg_sa_temp_f}F")
|
572
600
|
sa_temp_sch.defaultDaySchedule.setName("Supply Air Temp - #{clg_sa_temp_f}F Default")
|
573
|
-
sa_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),clg_sa_temp_c)
|
574
|
-
|
575
|
-
if building_type == 'Hospital'
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
#air handler
|
601
|
+
sa_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), clg_sa_temp_c)
|
602
|
+
|
603
|
+
air_flow_ratio = if building_type == 'Hospital'
|
604
|
+
if sys_name == 'VAV_PATRMS'
|
605
|
+
0.5
|
606
|
+
elsif sys_name == 'VAV_1' || sys_name == 'VAV_2'
|
607
|
+
0.3
|
608
|
+
else
|
609
|
+
1
|
610
|
+
end
|
611
|
+
else
|
612
|
+
0.3
|
613
|
+
end
|
614
|
+
|
615
|
+
# air handler
|
588
616
|
air_loop = OpenStudio::Model::AirLoopHVAC.new(self)
|
589
617
|
if sys_name.nil?
|
590
618
|
air_loop.setName("#{thermal_zones.size} Zone VAV")
|
@@ -593,19 +621,19 @@ class OpenStudio::Model::Model
|
|
593
621
|
end
|
594
622
|
air_loop.setAvailabilitySchedule(hvac_op_sch)
|
595
623
|
|
596
|
-
sa_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self,sa_temp_sch)
|
624
|
+
sa_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self, sa_temp_sch)
|
597
625
|
sa_stpt_manager.setName("#{thermal_zones.size} Zone VAV supply air setpoint manager")
|
598
626
|
sa_stpt_manager.addToNode(air_loop.supplyOutletNode)
|
599
627
|
|
600
|
-
#air handler controls
|
628
|
+
# air handler controls
|
601
629
|
sizing_system = air_loop.sizingSystem
|
602
630
|
sizing_system.setMinimumSystemAirFlowRatio(air_flow_ratio)
|
603
631
|
sizing_system.setPreheatDesignTemperature(prehtg_sa_temp_c)
|
604
632
|
sizing_system.setPrecoolDesignTemperature(preclg_sa_temp_c)
|
605
633
|
sizing_system.setCentralCoolingDesignSupplyAirTemperature(clg_sa_temp_c)
|
606
634
|
sizing_system.setCentralHeatingDesignSupplyAirTemperature(htg_sa_temp_c)
|
607
|
-
if building_type ==
|
608
|
-
if sys_name == 'VAV_2'|| sys_name=='VAV_1'
|
635
|
+
if building_type == 'Hospital'
|
636
|
+
if sys_name == 'VAV_2' || sys_name == 'VAV_1'
|
609
637
|
sizing_system.setSizingOption('Coincident')
|
610
638
|
else
|
611
639
|
sizing_system.setSizingOption('NonCoincident')
|
@@ -617,8 +645,8 @@ class OpenStudio::Model::Model
|
|
617
645
|
sizing_system.setAllOutdoorAirinHeating(false)
|
618
646
|
sizing_system.setSystemOutdoorAirMethod('ZoneSum')
|
619
647
|
|
620
|
-
#fan
|
621
|
-
fan = OpenStudio::Model::FanVariableVolume.new(self,
|
648
|
+
# fan
|
649
|
+
fan = OpenStudio::Model::FanVariableVolume.new(self, alwaysOnDiscreteSchedule)
|
622
650
|
fan.setName("#{air_loop.name} Fan")
|
623
651
|
fan.setFanEfficiency(vav_fan_efficiency)
|
624
652
|
fan.setMotorEfficiency(vav_fan_motor_efficiency)
|
@@ -626,10 +654,10 @@ class OpenStudio::Model::Model
|
|
626
654
|
fan.setFanPowerMinimumFlowRateInputMethod('fraction')
|
627
655
|
fan.setFanPowerMinimumFlowFraction(0.25)
|
628
656
|
fan.addToNode(air_loop.supplyInletNode)
|
629
|
-
fan.setEndUseSubcategory(
|
657
|
+
fan.setEndUseSubcategory('VAV system Fans')
|
630
658
|
|
631
|
-
#heating coil
|
632
|
-
htg_coil = OpenStudio::Model::CoilHeatingWater.new(self,
|
659
|
+
# heating coil
|
660
|
+
htg_coil = OpenStudio::Model::CoilHeatingWater.new(self, alwaysOnDiscreteSchedule)
|
633
661
|
htg_coil.addToNode(air_loop.supplyInletNode)
|
634
662
|
hot_water_loop.addDemandBranchForComponent(htg_coil)
|
635
663
|
htg_coil.setName("#{air_loop.name} Main Htg Coil")
|
@@ -638,7 +666,7 @@ class OpenStudio::Model::Model
|
|
638
666
|
htg_coil.setRatedInletAirTemperature(prehtg_sa_temp_c)
|
639
667
|
htg_coil.setRatedOutletWaterTemperature(hw_temp_c - hw_delta_t_k)
|
640
668
|
htg_coil.setRatedOutletAirTemperature(htg_sa_temp_c)
|
641
|
-
if building_type ==
|
669
|
+
if building_type == 'LargeHotel'
|
642
670
|
htg_coil.setRatedInletAirTemperature(htg_sa_temp_c)
|
643
671
|
htg_coil.setRatedOutletAirTemperature(rht_sa_temp_c)
|
644
672
|
else
|
@@ -646,28 +674,28 @@ class OpenStudio::Model::Model
|
|
646
674
|
htg_coil.setRatedOutletAirTemperature(htg_sa_temp_c)
|
647
675
|
end
|
648
676
|
|
649
|
-
#cooling coil
|
650
|
-
clg_coil = OpenStudio::Model::CoilCoolingWater.new(self,
|
677
|
+
# cooling coil
|
678
|
+
clg_coil = OpenStudio::Model::CoilCoolingWater.new(self, alwaysOnDiscreteSchedule)
|
651
679
|
clg_coil.setName("#{air_loop.name} Clg Coil")
|
652
680
|
clg_coil.addToNode(air_loop.supplyInletNode)
|
653
|
-
clg_coil.setHeatExchangerConfiguration(
|
681
|
+
clg_coil.setHeatExchangerConfiguration('CrossFlow')
|
654
682
|
chilled_water_loop.addDemandBranchForComponent(clg_coil)
|
655
683
|
clg_coil.controllerWaterCoil.get.setName("#{air_loop.name} Clg Coil Controller")
|
656
684
|
|
657
|
-
#outdoor air intake system
|
685
|
+
# outdoor air intake system
|
658
686
|
oa_intake_controller = OpenStudio::Model::ControllerOutdoorAir.new(self)
|
659
687
|
oa_intake_controller.setName("#{air_loop.name} OA Controller")
|
660
688
|
oa_intake_controller.setMinimumLimitType('FixedMinimum')
|
661
|
-
#oa_intake_controller.setMinimumOutdoorAirSchedule(oa_damper_sch)
|
689
|
+
# oa_intake_controller.setMinimumOutdoorAirSchedule(oa_damper_sch)
|
662
690
|
oa_intake_controller.setHeatRecoveryBypassControlType('BypassWhenOAFlowGreaterThanMinimum')
|
663
691
|
|
664
692
|
controller_mv = oa_intake_controller.controllerMechanicalVentilation
|
665
693
|
controller_mv.setName("#{air_loop.name} Vent Controller")
|
666
694
|
controller_mv.setSystemOutdoorAirMethod('VentilationRateProcedure')
|
667
695
|
|
668
|
-
if building_type ==
|
669
|
-
oa_intake_controller.setEconomizerControlType(
|
670
|
-
oa_intake_controller.setHeatRecoveryBypassControlType(
|
696
|
+
if building_type == 'LargeHotel'
|
697
|
+
oa_intake_controller.setEconomizerControlType('DifferentialEnthalpy')
|
698
|
+
oa_intake_controller.setHeatRecoveryBypassControlType('BypassWhenOAFlowGreaterThanMinimum')
|
671
699
|
oa_intake_controller.resetMaximumFractionofOutdoorAirSchedule
|
672
700
|
oa_intake_controller.resetEconomizerMinimumLimitDryBulbTemperature
|
673
701
|
end
|
@@ -676,31 +704,35 @@ class OpenStudio::Model::Model
|
|
676
704
|
oa_intake.setName("#{air_loop.name} OA Sys")
|
677
705
|
oa_intake.addToNode(air_loop.supplyInletNode)
|
678
706
|
|
679
|
-
|
680
707
|
# The oa system need to be added before setting the night cycle control
|
681
708
|
air_loop.setNightCycleControlType('CycleOnAny')
|
682
709
|
|
683
|
-
#hook the VAV system to each zone
|
710
|
+
# hook the VAV system to each zone
|
684
711
|
thermal_zones.each do |zone|
|
712
|
+
# reheat coil
|
713
|
+
rht_coil = nil
|
714
|
+
if electric_reheat
|
715
|
+
rht_coil = OpenStudio::Model::CoilHeatingElectric.new(self, alwaysOnDiscreteSchedule)
|
716
|
+
rht_coil.setName("#{zone.name} Rht Coil")
|
717
|
+
else
|
718
|
+
rht_coil = OpenStudio::Model::CoilHeatingWater.new(self, alwaysOnDiscreteSchedule)
|
719
|
+
rht_coil.setName("#{zone.name} Rht Coil")
|
720
|
+
rht_coil.setRatedInletWaterTemperature(hw_temp_c)
|
721
|
+
rht_coil.setRatedInletAirTemperature(htg_sa_temp_c)
|
722
|
+
rht_coil.setRatedOutletWaterTemperature(hw_temp_c - hw_delta_t_k)
|
723
|
+
rht_coil.setRatedOutletAirTemperature(rht_sa_temp_c)
|
724
|
+
hot_water_loop.addDemandBranchForComponent(rht_coil)
|
725
|
+
end
|
685
726
|
|
686
|
-
#
|
687
|
-
|
688
|
-
rht_coil.setName("#{zone.name} Rht Coil")
|
689
|
-
rht_coil.setRatedInletWaterTemperature(hw_temp_c)
|
690
|
-
rht_coil.setRatedInletAirTemperature(htg_sa_temp_c)
|
691
|
-
rht_coil.setRatedOutletWaterTemperature(hw_temp_c - hw_delta_t_k)
|
692
|
-
rht_coil.setRatedOutletAirTemperature(rht_sa_temp_c)
|
693
|
-
hot_water_loop.addDemandBranchForComponent(rht_coil)
|
694
|
-
|
695
|
-
#vav terminal
|
696
|
-
terminal = OpenStudio::Model::AirTerminalSingleDuctVAVReheat.new(self,self.alwaysOnDiscreteSchedule,rht_coil)
|
727
|
+
# vav terminal
|
728
|
+
terminal = OpenStudio::Model::AirTerminalSingleDuctVAVReheat.new(self, alwaysOnDiscreteSchedule, rht_coil)
|
697
729
|
terminal.setName("#{zone.name} VAV Term")
|
698
730
|
terminal.setZoneMinimumAirFlowMethod('Constant')
|
699
|
-
terminal.
|
731
|
+
terminal.apply_initial_prototype_damper_position(building_type, template, zone.outdoor_airflow_rate_per_area)
|
700
732
|
terminal.setMaximumFlowPerZoneFloorAreaDuringReheat(0.0)
|
701
733
|
terminal.setMaximumFlowFractionDuringReheat(0.5)
|
702
734
|
terminal.setMaximumReheatAirTemperature(rht_sa_temp_c)
|
703
|
-
air_loop.addBranchForZone(zone,terminal.to_StraightComponent)
|
735
|
+
air_loop.addBranchForZone(zone, terminal.to_StraightComponent)
|
704
736
|
|
705
737
|
# Zone sizing
|
706
738
|
# TODO Create general logic for cooling airflow method.
|
@@ -709,29 +741,27 @@ class OpenStudio::Model::Model
|
|
709
741
|
if building_type == 'SecondarySchool'
|
710
742
|
sizing_zone.setCoolingDesignAirFlowMethod('DesignDay')
|
711
743
|
else
|
712
|
-
sizing_zone.setCoolingDesignAirFlowMethod(
|
744
|
+
sizing_zone.setCoolingDesignAirFlowMethod('DesignDayWithLimit')
|
713
745
|
end
|
714
|
-
sizing_zone.setHeatingDesignAirFlowMethod(
|
746
|
+
sizing_zone.setHeatingDesignAirFlowMethod('DesignDay')
|
715
747
|
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(clg_sa_temp_c)
|
716
|
-
#sizing_zone.setZoneHeatingDesignSupplyAirTemperature(rht_sa_temp_c)
|
748
|
+
# sizing_zone.setZoneHeatingDesignSupplyAirTemperature(rht_sa_temp_c)
|
717
749
|
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(zone_htg_sa_temp_c)
|
718
750
|
|
719
751
|
unless return_plenum.nil?
|
720
752
|
zone.setReturnPlenum(return_plenum)
|
721
753
|
end
|
722
|
-
|
723
754
|
end
|
724
755
|
|
725
756
|
# Set the damper action based on the template.
|
726
|
-
air_loop.
|
757
|
+
air_loop.apply_vav_damper_action(template)
|
727
758
|
|
728
759
|
return air_loop
|
729
|
-
|
730
760
|
end
|
731
761
|
|
732
762
|
# Creates a VAV system with parallel fan powered boxes and adds it to the model.
|
733
763
|
#
|
734
|
-
# @param
|
764
|
+
# @param template [String] Valid choices are 90.1-2004,
|
735
765
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
736
766
|
# @param sys_name [String] the name of the system, or nil in which case it will be defaulted
|
737
767
|
# @param chilled_water_loop [String] chilled water loop to connect cooling coil to
|
@@ -745,35 +775,35 @@ class OpenStudio::Model::Model
|
|
745
775
|
# @param vav_fan_pressure_rise [Double] fan pressure rise, in Pa
|
746
776
|
# @param building_type [String] the building type
|
747
777
|
# @return [OpenStudio::Model::AirLoopHVAC] the resulting VAV air loop
|
748
|
-
def add_vav_pfp_boxes(
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
OpenStudio
|
778
|
+
def add_vav_pfp_boxes(template,
|
779
|
+
sys_name,
|
780
|
+
chilled_water_loop,
|
781
|
+
thermal_zones,
|
782
|
+
hvac_op_sch,
|
783
|
+
oa_damper_sch,
|
784
|
+
vav_fan_efficiency,
|
785
|
+
vav_fan_motor_efficiency,
|
786
|
+
vav_fan_pressure_rise,
|
787
|
+
building_type = nil)
|
788
|
+
|
789
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding VAV with PFP Boxes and Reheat system for #{thermal_zones.size} zones.")
|
760
790
|
thermal_zones.each do |zone|
|
761
|
-
OpenStudio
|
791
|
+
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.Model.Model', "---#{zone.name}")
|
762
792
|
end
|
763
793
|
|
764
794
|
# hvac operation schedule
|
765
|
-
if hvac_op_sch.nil?
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
795
|
+
hvac_op_sch = if hvac_op_sch.nil?
|
796
|
+
alwaysOnDiscreteSchedule
|
797
|
+
else
|
798
|
+
add_schedule(hvac_op_sch)
|
799
|
+
end
|
770
800
|
|
771
801
|
# oa damper schedule
|
772
|
-
if oa_damper_sch.nil?
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
802
|
+
oa_damper_sch = if oa_damper_sch.nil?
|
803
|
+
alwaysOnDiscreteSchedule
|
804
|
+
else
|
805
|
+
add_schedule(oa_damper_sch)
|
806
|
+
end
|
777
807
|
|
778
808
|
# control temps used across all air handlers
|
779
809
|
clg_sa_temp_f = 55.04 # Central deck clg temp 55F
|
@@ -783,19 +813,19 @@ class OpenStudio::Model::Model
|
|
783
813
|
rht_sa_temp_f = 104 # VAV box reheat to 104F
|
784
814
|
zone_htg_sa_temp_f = 104 # Zone heating design supply air temperature to 104 F
|
785
815
|
|
786
|
-
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f,'F','C').get
|
787
|
-
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f,'F','C').get
|
788
|
-
preclg_sa_temp_c = OpenStudio.convert(preclg_sa_temp_f,'F','C').get
|
789
|
-
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f,'F','C').get
|
790
|
-
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f,'F','C').get
|
791
|
-
zone_htg_sa_temp_c = OpenStudio.convert(zone_htg_sa_temp_f,'F','C').get
|
816
|
+
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f, 'F', 'C').get
|
817
|
+
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f, 'F', 'C').get
|
818
|
+
preclg_sa_temp_c = OpenStudio.convert(preclg_sa_temp_f, 'F', 'C').get
|
819
|
+
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f, 'F', 'C').get
|
820
|
+
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f, 'F', 'C').get
|
821
|
+
zone_htg_sa_temp_c = OpenStudio.convert(zone_htg_sa_temp_f, 'F', 'C').get
|
792
822
|
|
793
823
|
sa_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
794
824
|
sa_temp_sch.setName("Supply Air Temp - #{clg_sa_temp_f}F")
|
795
825
|
sa_temp_sch.defaultDaySchedule.setName("Supply Air Temp - #{clg_sa_temp_f}F Default")
|
796
|
-
sa_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),clg_sa_temp_c)
|
826
|
+
sa_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), clg_sa_temp_c)
|
797
827
|
|
798
|
-
#air handler
|
828
|
+
# air handler
|
799
829
|
air_loop = OpenStudio::Model::AirLoopHVAC.new(self)
|
800
830
|
if sys_name.nil?
|
801
831
|
air_loop.setName("#{thermal_zones.size} Zone VAV with PFP Boxes and Reheat")
|
@@ -804,11 +834,11 @@ class OpenStudio::Model::Model
|
|
804
834
|
end
|
805
835
|
air_loop.setAvailabilitySchedule(hvac_op_sch)
|
806
836
|
|
807
|
-
sa_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self,sa_temp_sch)
|
837
|
+
sa_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self, sa_temp_sch)
|
808
838
|
sa_stpt_manager.setName("#{thermal_zones.size} Zone VAV supply air setpoint manager")
|
809
839
|
sa_stpt_manager.addToNode(air_loop.supplyOutletNode)
|
810
840
|
|
811
|
-
#air handler controls
|
841
|
+
# air handler controls
|
812
842
|
sizing_system = air_loop.sizingSystem
|
813
843
|
sizing_system.setPreheatDesignTemperature(prehtg_sa_temp_c)
|
814
844
|
sizing_system.setPrecoolDesignTemperature(preclg_sa_temp_c)
|
@@ -819,8 +849,8 @@ class OpenStudio::Model::Model
|
|
819
849
|
sizing_system.setAllOutdoorAirinHeating(false)
|
820
850
|
sizing_system.setSystemOutdoorAirMethod('ZoneSum')
|
821
851
|
|
822
|
-
#fan
|
823
|
-
fan = OpenStudio::Model::FanVariableVolume.new(self,
|
852
|
+
# fan
|
853
|
+
fan = OpenStudio::Model::FanVariableVolume.new(self, alwaysOnDiscreteSchedule)
|
824
854
|
fan.setName("#{air_loop.name} Fan")
|
825
855
|
fan.setFanEfficiency(vav_fan_efficiency)
|
826
856
|
fan.setMotorEfficiency(vav_fan_motor_efficiency)
|
@@ -828,26 +858,26 @@ class OpenStudio::Model::Model
|
|
828
858
|
fan.setFanPowerMinimumFlowRateInputMethod('fraction')
|
829
859
|
fan.setFanPowerMinimumFlowFraction(0.25)
|
830
860
|
fan.addToNode(air_loop.supplyInletNode)
|
831
|
-
fan.setEndUseSubcategory(
|
861
|
+
fan.setEndUseSubcategory('VAV system Fans')
|
832
862
|
|
833
|
-
#heating coil
|
834
|
-
htg_coil = OpenStudio::Model::CoilHeatingElectric.new(self,
|
863
|
+
# heating coil
|
864
|
+
htg_coil = OpenStudio::Model::CoilHeatingElectric.new(self, alwaysOnDiscreteSchedule)
|
835
865
|
htg_coil.setName("#{air_loop.name} Htg Coil")
|
836
866
|
htg_coil.addToNode(air_loop.supplyInletNode)
|
837
867
|
|
838
|
-
#cooling coil
|
839
|
-
clg_coil = OpenStudio::Model::CoilCoolingWater.new(self,
|
868
|
+
# cooling coil
|
869
|
+
clg_coil = OpenStudio::Model::CoilCoolingWater.new(self, alwaysOnDiscreteSchedule)
|
840
870
|
clg_coil.setName("#{air_loop.name} Clg Coil")
|
841
871
|
clg_coil.addToNode(air_loop.supplyInletNode)
|
842
|
-
clg_coil.setHeatExchangerConfiguration(
|
872
|
+
clg_coil.setHeatExchangerConfiguration('CrossFlow')
|
843
873
|
chilled_water_loop.addDemandBranchForComponent(clg_coil)
|
844
874
|
clg_coil.controllerWaterCoil.get.setName("#{air_loop.name} Clg Coil Controller")
|
845
875
|
|
846
|
-
#outdoor air intake system
|
876
|
+
# outdoor air intake system
|
847
877
|
oa_intake_controller = OpenStudio::Model::ControllerOutdoorAir.new(self)
|
848
878
|
oa_intake_controller.setName("#{air_loop.name} OA Controller")
|
849
879
|
oa_intake_controller.setMinimumLimitType('FixedMinimum')
|
850
|
-
#oa_intake_controller.setMinimumOutdoorAirSchedule(oa_damper_sch)
|
880
|
+
# oa_intake_controller.setMinimumOutdoorAirSchedule(oa_damper_sch)
|
851
881
|
oa_intake_controller.setHeatRecoveryBypassControlType('BypassWhenOAFlowGreaterThanMinimum')
|
852
882
|
|
853
883
|
controller_mv = oa_intake_controller.controllerMechanicalVentilation
|
@@ -861,25 +891,24 @@ class OpenStudio::Model::Model
|
|
861
891
|
# The oa system need to be added before setting the night cycle control
|
862
892
|
air_loop.setNightCycleControlType('CycleOnAny')
|
863
893
|
|
864
|
-
#hook the VAV system to each zone
|
894
|
+
# hook the VAV system to each zone
|
865
895
|
thermal_zones.each do |zone|
|
866
|
-
|
867
|
-
|
868
|
-
rht_coil = OpenStudio::Model::CoilHeatingElectric.new(self,self.alwaysOnDiscreteSchedule)
|
896
|
+
# reheat coil
|
897
|
+
rht_coil = OpenStudio::Model::CoilHeatingElectric.new(self, alwaysOnDiscreteSchedule)
|
869
898
|
rht_coil.setName("#{zone.name} Rht Coil")
|
870
899
|
|
871
900
|
# terminal fan
|
872
|
-
pfp_fan = OpenStudio::Model::FanConstantVolume.new(self,
|
901
|
+
pfp_fan = OpenStudio::Model::FanConstantVolume.new(self, alwaysOnDiscreteSchedule)
|
873
902
|
pfp_fan.setName("#{zone.name} PFP Term Fan")
|
874
903
|
pfp_fan.setPressureRise(300)
|
875
904
|
|
876
|
-
#parallel fan powered terminal
|
905
|
+
# parallel fan powered terminal
|
877
906
|
pfp_terminal = OpenStudio::Model::AirTerminalSingleDuctParallelPIUReheat.new(self,
|
878
|
-
|
879
|
-
|
880
|
-
|
907
|
+
alwaysOnDiscreteSchedule,
|
908
|
+
pfp_fan,
|
909
|
+
rht_coil)
|
881
910
|
pfp_terminal.setName("#{zone.name} PFP Term")
|
882
|
-
air_loop.addBranchForZone(zone,pfp_terminal.to_StraightComponent)
|
911
|
+
air_loop.addBranchForZone(zone, pfp_terminal.to_StraightComponent)
|
883
912
|
|
884
913
|
# Zone sizing
|
885
914
|
# TODO Create general logic for cooling airflow method.
|
@@ -888,64 +917,70 @@ class OpenStudio::Model::Model
|
|
888
917
|
sizing_zone.setCoolingDesignAirFlowMethod('DesignDay')
|
889
918
|
sizing_zone.setHeatingDesignAirFlowMethod('DesignDay')
|
890
919
|
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(clg_sa_temp_c)
|
891
|
-
#sizing_zone.setZoneHeatingDesignSupplyAirTemperature(rht_sa_temp_c)
|
920
|
+
# sizing_zone.setZoneHeatingDesignSupplyAirTemperature(rht_sa_temp_c)
|
892
921
|
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(zone_htg_sa_temp_c)
|
893
|
-
|
894
922
|
end
|
895
923
|
|
896
924
|
return air_loop
|
897
|
-
|
898
925
|
end
|
899
926
|
|
900
927
|
# Creates a packaged VAV system and adds it to the model.
|
901
928
|
#
|
902
|
-
# @param
|
929
|
+
# @param template [String] Valid choices are 90.1-2004,
|
903
930
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
904
931
|
# @param sys_name [String] the name of the system, or nil in which case it will be defaulted
|
905
|
-
# @param hot_water_loop [String] hot water loop to connect heating and reheat coils to.
|
906
|
-
# if nil, will be electric heat and electric reheat
|
907
932
|
# @param thermal_zones [String] zones to connect to this system
|
908
933
|
# @param hvac_op_sch [String] name of the HVAC operation schedule
|
909
934
|
# or nil in which case will be defaulted to always on
|
910
935
|
# @param oa_damper_sch [Double] name of the oa damper schedule,
|
911
936
|
# or nil in which case will be defaulted to always open
|
937
|
+
# @param electric_reheat [Bool] if true, this system will have electric reheat coils,
|
938
|
+
# but if false, the reheat coils will be served by the hot_water_loop.
|
939
|
+
# @param hot_water_loop [String] hot water loop to connect heating and reheat coils to.
|
940
|
+
# if nil, will be electric heat and electric reheat
|
941
|
+
# @param chilled_water_loop [String] chilled water loop to connect cooling coils to.
|
942
|
+
# if nil, will be DX cooling.
|
943
|
+
# @param return_plenum [OpenStudio::Model::ThermalZone] the zone to attach as
|
944
|
+
# the supply plenum, or nil, in which case no return plenum will be used.
|
912
945
|
# @param building_type [String] the building type
|
913
946
|
# @return [OpenStudio::Model::AirLoopHVAC] the resulting packaged VAV air loop
|
914
|
-
def add_pvav(
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
947
|
+
def add_pvav(template,
|
948
|
+
sys_name,
|
949
|
+
thermal_zones,
|
950
|
+
hvac_op_sch,
|
951
|
+
oa_damper_sch,
|
952
|
+
electric_reheat = false,
|
953
|
+
hot_water_loop = nil,
|
954
|
+
chilled_water_loop = nil,
|
955
|
+
return_plenum = nil,
|
956
|
+
building_type = nil)
|
957
|
+
|
958
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding Packaged VAV for #{thermal_zones.size} zones.")
|
924
959
|
thermal_zones.each do |zone|
|
925
|
-
OpenStudio
|
960
|
+
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.Model.Model', "---#{zone.name}")
|
926
961
|
end
|
927
962
|
|
928
963
|
# hvac operation schedule
|
929
|
-
if hvac_op_sch.nil?
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
964
|
+
hvac_op_sch = if hvac_op_sch.nil?
|
965
|
+
alwaysOnDiscreteSchedule
|
966
|
+
else
|
967
|
+
add_schedule(hvac_op_sch)
|
968
|
+
end
|
934
969
|
|
935
970
|
# oa damper schedule
|
936
|
-
if oa_damper_sch.nil?
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
971
|
+
oa_damper_sch = if oa_damper_sch.nil?
|
972
|
+
alwaysOnDiscreteSchedule
|
973
|
+
else
|
974
|
+
add_schedule(oa_damper_sch)
|
975
|
+
end
|
941
976
|
|
942
977
|
# Control temps for HW loop
|
943
978
|
# will only be used when hot_water_loop is provided.
|
944
|
-
hw_temp_f = 180 #HW setpoint 180F
|
945
|
-
hw_delta_t_r = 20 #20F delta-T
|
979
|
+
hw_temp_f = 180 # HW setpoint 180F
|
980
|
+
hw_delta_t_r = 20 # 20F delta-T
|
946
981
|
|
947
|
-
hw_temp_c = OpenStudio.convert(hw_temp_f,'F','C').get
|
948
|
-
hw_delta_t_k = OpenStudio.convert(hw_delta_t_r,'R','K').get
|
982
|
+
hw_temp_c = OpenStudio.convert(hw_temp_f, 'F', 'C').get
|
983
|
+
hw_delta_t_k = OpenStudio.convert(hw_delta_t_r, 'R', 'K').get
|
949
984
|
|
950
985
|
# Control temps used across all air handlers
|
951
986
|
# TODO why aren't design and operational temps coordinated?
|
@@ -958,19 +993,19 @@ class OpenStudio::Model::Model
|
|
958
993
|
rht_rated_air_out_temp_f = 90 # Reheat coils designed to supply 90F...but zone expects 122F...?
|
959
994
|
clg_sa_temp_f = 55 # Central deck clg temp operates at 55F
|
960
995
|
|
961
|
-
sys_dsn_prhtg_temp_c = OpenStudio.convert(sys_dsn_prhtg_temp_f,'F','C').get
|
962
|
-
sys_dsn_clg_sa_temp_c = OpenStudio.convert(sys_dsn_clg_sa_temp_f,'F','C').get
|
963
|
-
sys_dsn_htg_sa_temp_c = OpenStudio.convert(sys_dsn_htg_sa_temp_f,'F','C').get
|
964
|
-
zn_dsn_clg_sa_temp_c = OpenStudio.convert(zn_dsn_clg_sa_temp_f,'F','C').get
|
965
|
-
zn_dsn_htg_sa_temp_c = OpenStudio.convert(zn_dsn_htg_sa_temp_f,'F','C').get
|
966
|
-
rht_rated_air_in_temp_c = OpenStudio.convert(rht_rated_air_in_temp_f,'F','C').get
|
967
|
-
rht_rated_air_out_temp_c = OpenStudio.convert(rht_rated_air_out_temp_f,'F','C').get
|
968
|
-
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f,'F','C').get
|
996
|
+
sys_dsn_prhtg_temp_c = OpenStudio.convert(sys_dsn_prhtg_temp_f, 'F', 'C').get
|
997
|
+
sys_dsn_clg_sa_temp_c = OpenStudio.convert(sys_dsn_clg_sa_temp_f, 'F', 'C').get
|
998
|
+
sys_dsn_htg_sa_temp_c = OpenStudio.convert(sys_dsn_htg_sa_temp_f, 'F', 'C').get
|
999
|
+
zn_dsn_clg_sa_temp_c = OpenStudio.convert(zn_dsn_clg_sa_temp_f, 'F', 'C').get
|
1000
|
+
zn_dsn_htg_sa_temp_c = OpenStudio.convert(zn_dsn_htg_sa_temp_f, 'F', 'C').get
|
1001
|
+
rht_rated_air_in_temp_c = OpenStudio.convert(rht_rated_air_in_temp_f, 'F', 'C').get
|
1002
|
+
rht_rated_air_out_temp_c = OpenStudio.convert(rht_rated_air_out_temp_f, 'F', 'C').get
|
1003
|
+
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f, 'F', 'C').get
|
969
1004
|
|
970
1005
|
sa_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
971
1006
|
sa_temp_sch.setName("Supply Air Temp - #{clg_sa_temp_f}F")
|
972
1007
|
sa_temp_sch.defaultDaySchedule.setName("Supply Air Temp - #{clg_sa_temp_f}F Default")
|
973
|
-
sa_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),clg_sa_temp_c)
|
1008
|
+
sa_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), clg_sa_temp_c)
|
974
1009
|
|
975
1010
|
# Air handler
|
976
1011
|
air_loop = OpenStudio::Model::AirLoopHVAC.new(self)
|
@@ -983,20 +1018,20 @@ class OpenStudio::Model::Model
|
|
983
1018
|
air_loop.setAvailabilitySchedule(hvac_op_sch)
|
984
1019
|
|
985
1020
|
# Some exceptions for the Outpatient
|
986
|
-
if sys_name.include?
|
1021
|
+
if sys_name.include? 'PVAV Outpatient F1'
|
987
1022
|
# Outpatient two AHU1 and AHU2 have different HVAC schedule
|
988
|
-
hvac_op_sch =
|
1023
|
+
hvac_op_sch = add_schedule('OutPatientHealthCare AHU1-Fan_Pre2004')
|
989
1024
|
# Outpatient has different temperature settings for sizing
|
990
1025
|
clg_sa_temp_f = 52 # for AHU1 in Outpatient, SAT is 52F
|
991
|
-
if
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
1026
|
+
sys_dsn_clg_sa_temp_f = if template == 'DOE Ref 1980-2004' || template == 'DOE Ref Pre-1980'
|
1027
|
+
52
|
1028
|
+
else
|
1029
|
+
45
|
1030
|
+
end
|
996
1031
|
zn_dsn_clg_sa_temp_f = 52 # zone cooling design SAT
|
997
1032
|
zn_dsn_htg_sa_temp_f = 104 # zone heating design SAT
|
998
1033
|
elsif sys_name.include? 'PVAV Outpatient F2 F3'
|
999
|
-
hvac_op_sch =
|
1034
|
+
hvac_op_sch = add_schedule('OutPatientHealthCare AHU2-Fan_Pre2004')
|
1000
1035
|
clg_sa_temp_f = 55 # for AHU2 in Outpatient, SAT is 55F
|
1001
1036
|
sys_dsn_clg_sa_temp_f = 52
|
1002
1037
|
zn_dsn_clg_sa_temp_f = 55 # zone cooling design SAT
|
@@ -1004,7 +1039,7 @@ class OpenStudio::Model::Model
|
|
1004
1039
|
end
|
1005
1040
|
|
1006
1041
|
# Air handler controls
|
1007
|
-
stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self,sa_temp_sch)
|
1042
|
+
stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self, sa_temp_sch)
|
1008
1043
|
stpt_manager.addToNode(air_loop.supplyOutletNode)
|
1009
1044
|
sizing_system = air_loop.sizingSystem
|
1010
1045
|
# sizing_system.setPreheatDesignTemperature(sys_dsn_prhtg_temp_c)
|
@@ -1016,18 +1051,18 @@ class OpenStudio::Model::Model
|
|
1016
1051
|
air_loop.setNightCycleControlType('CycleOnAny')
|
1017
1052
|
|
1018
1053
|
# Fan
|
1019
|
-
fan = OpenStudio::Model::FanVariableVolume.new(self,
|
1054
|
+
fan = OpenStudio::Model::FanVariableVolume.new(self, alwaysOnDiscreteSchedule)
|
1020
1055
|
fan.setName("#{air_loop.name} Fan")
|
1021
1056
|
fan.addToNode(air_loop.supplyInletNode)
|
1022
1057
|
|
1023
1058
|
# Heating coil - depends on whether heating is hot water or electric,
|
1024
1059
|
# which is determined by whether or not a hot water loop is provided.
|
1025
1060
|
if hot_water_loop.nil?
|
1026
|
-
htg_coil = OpenStudio::Model::CoilHeatingGas.new(self,
|
1061
|
+
htg_coil = OpenStudio::Model::CoilHeatingGas.new(self, alwaysOnDiscreteSchedule)
|
1027
1062
|
htg_coil.setName("#{air_loop.name} Main Htg Coil")
|
1028
1063
|
htg_coil.addToNode(air_loop.supplyInletNode)
|
1029
1064
|
else
|
1030
|
-
htg_coil = OpenStudio::Model::CoilHeatingWater.new(self,
|
1065
|
+
htg_coil = OpenStudio::Model::CoilHeatingWater.new(self, alwaysOnDiscreteSchedule)
|
1031
1066
|
htg_coil.setName("#{air_loop.name} Main Htg Coil")
|
1032
1067
|
htg_coil.setRatedInletWaterTemperature(hw_temp_c)
|
1033
1068
|
htg_coil.setRatedInletAirTemperature(rht_rated_air_in_temp_c)
|
@@ -1038,9 +1073,18 @@ class OpenStudio::Model::Model
|
|
1038
1073
|
end
|
1039
1074
|
|
1040
1075
|
# Cooling coil
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1076
|
+
if chilled_water_loop.nil?
|
1077
|
+
clg_coil = OpenStudio::Model::CoilCoolingDXTwoSpeed.new(self)
|
1078
|
+
clg_coil.setName("#{air_loop.name} Clg Coil")
|
1079
|
+
clg_coil.addToNode(air_loop.supplyInletNode)
|
1080
|
+
else
|
1081
|
+
clg_coil = OpenStudio::Model::CoilCoolingWater.new(self, alwaysOnDiscreteSchedule)
|
1082
|
+
clg_coil.setName("#{air_loop.name} Clg Coil")
|
1083
|
+
clg_coil.addToNode(air_loop.supplyInletNode)
|
1084
|
+
clg_coil.setHeatExchangerConfiguration('CrossFlow')
|
1085
|
+
chilled_water_loop.addDemandBranchForComponent(clg_coil)
|
1086
|
+
clg_coil.controllerWaterCoil.get.setName("#{air_loop.name} Clg Coil Controller")
|
1087
|
+
end
|
1044
1088
|
|
1045
1089
|
# Outdoor air intake system
|
1046
1090
|
oa_intake_controller = OpenStudio::Model::ControllerOutdoorAir.new(self)
|
@@ -1055,15 +1099,14 @@ class OpenStudio::Model::Model
|
|
1055
1099
|
|
1056
1100
|
# Hook the VAV system to each zone
|
1057
1101
|
thermal_zones.each do |zone|
|
1058
|
-
|
1059
1102
|
# Reheat coil
|
1060
1103
|
rht_coil = nil
|
1061
1104
|
# sys_name.include? "Outpatient F2 F3" is only for reheat coil of Outpatient Floor2&3
|
1062
|
-
if hot_water_loop.nil?
|
1063
|
-
rht_coil = OpenStudio::Model::CoilHeatingElectric.new(self,
|
1105
|
+
if electric_reheat || hot_water_loop.nil? || sys_name.include?('Outpatient F2 F3')
|
1106
|
+
rht_coil = OpenStudio::Model::CoilHeatingElectric.new(self, alwaysOnDiscreteSchedule)
|
1064
1107
|
rht_coil.setName("#{zone.name} Rht Coil")
|
1065
1108
|
else
|
1066
|
-
rht_coil = OpenStudio::Model::CoilHeatingWater.new(self,
|
1109
|
+
rht_coil = OpenStudio::Model::CoilHeatingWater.new(self, alwaysOnDiscreteSchedule)
|
1067
1110
|
rht_coil.setName("#{zone.name} Rht Coil")
|
1068
1111
|
rht_coil.setRatedInletWaterTemperature(hw_temp_c)
|
1069
1112
|
rht_coil.setRatedInletAirTemperature(rht_rated_air_in_temp_c)
|
@@ -1073,11 +1116,11 @@ class OpenStudio::Model::Model
|
|
1073
1116
|
end
|
1074
1117
|
|
1075
1118
|
# VAV terminal
|
1076
|
-
terminal = OpenStudio::Model::AirTerminalSingleDuctVAVReheat.new(self,
|
1119
|
+
terminal = OpenStudio::Model::AirTerminalSingleDuctVAVReheat.new(self, alwaysOnDiscreteSchedule, rht_coil)
|
1077
1120
|
terminal.setName("#{zone.name} VAV Term")
|
1078
1121
|
terminal.setZoneMinimumAirFlowMethod('Constant')
|
1079
|
-
terminal.
|
1080
|
-
air_loop.addBranchForZone(zone,terminal.to_StraightComponent)
|
1122
|
+
terminal.apply_initial_prototype_damper_position(building_type, template, zone.outdoor_airflow_rate_per_area)
|
1123
|
+
air_loop.addBranchForZone(zone, terminal.to_StraightComponent)
|
1081
1124
|
|
1082
1125
|
unless return_plenum.nil?
|
1083
1126
|
zone.setReturnPlenum(return_plenum)
|
@@ -1087,19 +1130,187 @@ class OpenStudio::Model::Model
|
|
1087
1130
|
sizing_zone = zone.sizingZone
|
1088
1131
|
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(zn_dsn_clg_sa_temp_c)
|
1089
1132
|
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(zn_dsn_htg_sa_temp_c)
|
1090
|
-
|
1091
1133
|
end
|
1092
1134
|
|
1093
1135
|
# Set the damper action based on the template.
|
1094
|
-
air_loop.
|
1136
|
+
air_loop.apply_vav_damper_action(template)
|
1095
1137
|
|
1096
1138
|
return true
|
1139
|
+
end
|
1140
|
+
|
1141
|
+
# Creates a packaged VAV system with parallel fan powered boxes and adds it to the model.
|
1142
|
+
#
|
1143
|
+
# @param template [String] Valid choices are 90.1-2004,
|
1144
|
+
# 90.1-2007, 90.1-2010, 90.1-2013
|
1145
|
+
# @param sys_name [String] the name of the system, or nil in which case it will be defaulted
|
1146
|
+
# @param thermal_zones [String] zones to connect to this system
|
1147
|
+
# @param hvac_op_sch [String] name of the HVAC operation schedule
|
1148
|
+
# or nil in which case will be defaulted to always on
|
1149
|
+
# @param oa_damper_sch [Double] name of the oa damper schedule,
|
1150
|
+
# or nil in which case will be defaulted to always open
|
1151
|
+
# @param vav_fan_efficiency [Double] fan total efficiency, including motor and impeller
|
1152
|
+
# @param vav_fan_motor_efficiency [Double] fan motor efficiency
|
1153
|
+
# @param vav_fan_pressure_rise [Double] fan pressure rise, in Pa
|
1154
|
+
# @param chilled_water_loop [String] chilled water loop to connect cooling coils to.
|
1155
|
+
# if nil, will be DX cooling.
|
1156
|
+
# @param building_type [String] the building type
|
1157
|
+
# @return [OpenStudio::Model::AirLoopHVAC] the resulting VAV air loop
|
1158
|
+
def add_pvav_pfp_boxes(template,
|
1159
|
+
sys_name,
|
1160
|
+
thermal_zones,
|
1161
|
+
hvac_op_sch,
|
1162
|
+
oa_damper_sch,
|
1163
|
+
vav_fan_efficiency,
|
1164
|
+
vav_fan_motor_efficiency,
|
1165
|
+
vav_fan_pressure_rise,
|
1166
|
+
chilled_water_loop = nil,
|
1167
|
+
building_type = nil)
|
1168
|
+
|
1169
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding PVAV with PFP Boxes and Reheat system for #{thermal_zones.size} zones.")
|
1170
|
+
thermal_zones.each do |zone|
|
1171
|
+
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.Model.Model', "---#{zone.name}")
|
1172
|
+
end
|
1173
|
+
|
1174
|
+
# hvac operation schedule
|
1175
|
+
hvac_op_sch = if hvac_op_sch.nil?
|
1176
|
+
alwaysOnDiscreteSchedule
|
1177
|
+
else
|
1178
|
+
add_schedule(hvac_op_sch)
|
1179
|
+
end
|
1180
|
+
|
1181
|
+
# oa damper schedule
|
1182
|
+
oa_damper_sch = if oa_damper_sch.nil?
|
1183
|
+
alwaysOnDiscreteSchedule
|
1184
|
+
else
|
1185
|
+
add_schedule(oa_damper_sch)
|
1186
|
+
end
|
1187
|
+
|
1188
|
+
# control temps used across all air handlers
|
1189
|
+
clg_sa_temp_f = 55.04 # Central deck clg temp 55F
|
1190
|
+
prehtg_sa_temp_f = 44.6 # Preheat to 44.6F
|
1191
|
+
preclg_sa_temp_f = 55.04 # Precool to 55F
|
1192
|
+
htg_sa_temp_f = 55.04 # Central deck htg temp 55F
|
1193
|
+
rht_sa_temp_f = 104 # VAV box reheat to 104F
|
1194
|
+
zone_htg_sa_temp_f = 104 # Zone heating design supply air temperature to 104 F
|
1195
|
+
|
1196
|
+
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f, 'F', 'C').get
|
1197
|
+
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f, 'F', 'C').get
|
1198
|
+
preclg_sa_temp_c = OpenStudio.convert(preclg_sa_temp_f, 'F', 'C').get
|
1199
|
+
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f, 'F', 'C').get
|
1200
|
+
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f, 'F', 'C').get
|
1201
|
+
zone_htg_sa_temp_c = OpenStudio.convert(zone_htg_sa_temp_f, 'F', 'C').get
|
1202
|
+
|
1203
|
+
sa_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
1204
|
+
sa_temp_sch.setName("Supply Air Temp - #{clg_sa_temp_f}F")
|
1205
|
+
sa_temp_sch.defaultDaySchedule.setName("Supply Air Temp - #{clg_sa_temp_f}F Default")
|
1206
|
+
sa_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), clg_sa_temp_c)
|
1207
|
+
|
1208
|
+
# air handler
|
1209
|
+
air_loop = OpenStudio::Model::AirLoopHVAC.new(self)
|
1210
|
+
if sys_name.nil?
|
1211
|
+
air_loop.setName("#{thermal_zones.size} Zone VAV with PFP Boxes and Reheat")
|
1212
|
+
else
|
1213
|
+
air_loop.setName(sys_name)
|
1214
|
+
end
|
1215
|
+
air_loop.setAvailabilitySchedule(hvac_op_sch)
|
1216
|
+
|
1217
|
+
sa_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self, sa_temp_sch)
|
1218
|
+
sa_stpt_manager.setName("#{thermal_zones.size} Zone VAV supply air setpoint manager")
|
1219
|
+
sa_stpt_manager.addToNode(air_loop.supplyOutletNode)
|
1220
|
+
|
1221
|
+
# air handler controls
|
1222
|
+
sizing_system = air_loop.sizingSystem
|
1223
|
+
sizing_system.setPreheatDesignTemperature(prehtg_sa_temp_c)
|
1224
|
+
sizing_system.setPrecoolDesignTemperature(preclg_sa_temp_c)
|
1225
|
+
sizing_system.setCentralCoolingDesignSupplyAirTemperature(clg_sa_temp_c)
|
1226
|
+
sizing_system.setCentralHeatingDesignSupplyAirTemperature(htg_sa_temp_c)
|
1227
|
+
sizing_system.setSizingOption('Coincident')
|
1228
|
+
sizing_system.setAllOutdoorAirinCooling(false)
|
1229
|
+
sizing_system.setAllOutdoorAirinHeating(false)
|
1230
|
+
sizing_system.setSystemOutdoorAirMethod('ZoneSum')
|
1231
|
+
|
1232
|
+
# fan
|
1233
|
+
fan = OpenStudio::Model::FanVariableVolume.new(self, alwaysOnDiscreteSchedule)
|
1234
|
+
fan.setName("#{air_loop.name} Fan")
|
1235
|
+
fan.setFanEfficiency(vav_fan_efficiency)
|
1236
|
+
fan.setMotorEfficiency(vav_fan_motor_efficiency)
|
1237
|
+
fan.setPressureRise(vav_fan_pressure_rise)
|
1238
|
+
fan.setFanPowerMinimumFlowRateInputMethod('fraction')
|
1239
|
+
fan.setFanPowerMinimumFlowFraction(0.25)
|
1240
|
+
fan.addToNode(air_loop.supplyInletNode)
|
1241
|
+
fan.setEndUseSubcategory('VAV system Fans')
|
1242
|
+
|
1243
|
+
# heating coil
|
1244
|
+
htg_coil = OpenStudio::Model::CoilHeatingElectric.new(self, alwaysOnDiscreteSchedule)
|
1245
|
+
htg_coil.setName("#{air_loop.name} Main Htg Coil")
|
1246
|
+
htg_coil.addToNode(air_loop.supplyInletNode)
|
1247
|
+
|
1248
|
+
# Cooling coil
|
1249
|
+
if chilled_water_loop.nil?
|
1250
|
+
clg_coil = OpenStudio::Model::CoilCoolingDXTwoSpeed.new(self)
|
1251
|
+
clg_coil.setName("#{air_loop.name} Clg Coil")
|
1252
|
+
clg_coil.addToNode(air_loop.supplyInletNode)
|
1253
|
+
else
|
1254
|
+
clg_coil = OpenStudio::Model::CoilCoolingWater.new(self, alwaysOnDiscreteSchedule)
|
1255
|
+
clg_coil.setName("#{air_loop.name} Clg Coil")
|
1256
|
+
clg_coil.addToNode(air_loop.supplyInletNode)
|
1257
|
+
clg_coil.setHeatExchangerConfiguration('CrossFlow')
|
1258
|
+
chilled_water_loop.addDemandBranchForComponent(clg_coil)
|
1259
|
+
clg_coil.controllerWaterCoil.get.setName("#{air_loop.name} Clg Coil Controller")
|
1260
|
+
end
|
1261
|
+
|
1262
|
+
# outdoor air intake system
|
1263
|
+
oa_intake_controller = OpenStudio::Model::ControllerOutdoorAir.new(self)
|
1264
|
+
oa_intake_controller.setName("#{air_loop.name} OA Controller")
|
1265
|
+
oa_intake_controller.setMinimumLimitType('FixedMinimum')
|
1266
|
+
oa_intake_controller.setMinimumOutdoorAirSchedule(oa_damper_sch)
|
1267
|
+
oa_intake_controller.setHeatRecoveryBypassControlType('BypassWhenOAFlowGreaterThanMinimum')
|
1268
|
+
|
1269
|
+
controller_mv = oa_intake_controller.controllerMechanicalVentilation
|
1270
|
+
controller_mv.setName("#{air_loop.name} Vent Controller")
|
1271
|
+
controller_mv.setSystemOutdoorAirMethod('VentilationRateProcedure')
|
1272
|
+
|
1273
|
+
oa_intake = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(self, oa_intake_controller)
|
1274
|
+
oa_intake.setName("#{air_loop.name} OA Sys")
|
1275
|
+
oa_intake.addToNode(air_loop.supplyInletNode)
|
1276
|
+
|
1277
|
+
# The oa system need to be added before setting the night cycle control
|
1278
|
+
air_loop.setNightCycleControlType('CycleOnAny')
|
1279
|
+
|
1280
|
+
# hook the VAV system to each zone
|
1281
|
+
thermal_zones.each do |zone|
|
1282
|
+
# reheat coil
|
1283
|
+
rht_coil = OpenStudio::Model::CoilHeatingElectric.new(self, alwaysOnDiscreteSchedule)
|
1284
|
+
rht_coil.setName("#{zone.name} Rht Coil")
|
1285
|
+
|
1286
|
+
# terminal fan
|
1287
|
+
pfp_fan = OpenStudio::Model::FanConstantVolume.new(self, alwaysOnDiscreteSchedule)
|
1288
|
+
pfp_fan.setName("#{zone.name} PFP Term Fan")
|
1289
|
+
pfp_fan.setPressureRise(300)
|
1290
|
+
|
1291
|
+
# parallel fan powered terminal
|
1292
|
+
pfp_terminal = OpenStudio::Model::AirTerminalSingleDuctParallelPIUReheat.new(self,
|
1293
|
+
alwaysOnDiscreteSchedule,
|
1294
|
+
pfp_fan,
|
1295
|
+
rht_coil)
|
1296
|
+
pfp_terminal.setName("#{zone.name} PFP Term")
|
1297
|
+
air_loop.addBranchForZone(zone, pfp_terminal.to_StraightComponent)
|
1097
1298
|
|
1299
|
+
# Zone sizing
|
1300
|
+
sizing_zone = zone.sizingZone
|
1301
|
+
sizing_zone.setCoolingDesignAirFlowMethod('DesignDay')
|
1302
|
+
sizing_zone.setHeatingDesignAirFlowMethod('DesignDay')
|
1303
|
+
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(clg_sa_temp_c)
|
1304
|
+
# sizing_zone.setZoneHeatingDesignSupplyAirTemperature(rht_sa_temp_c)
|
1305
|
+
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(zone_htg_sa_temp_c)
|
1306
|
+
end
|
1307
|
+
|
1308
|
+
return air_loop
|
1098
1309
|
end
|
1099
1310
|
|
1100
1311
|
# Creates a packaged VAV system and adds it to the model.
|
1101
1312
|
#
|
1102
|
-
# @param
|
1313
|
+
# @param template [String] Valid choices are 90.1-2004,
|
1103
1314
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
1104
1315
|
# @param sys_name [String] the name of the system, or nil in which case it will be defaulted
|
1105
1316
|
# @param hot_water_loop [String] hot water loop to connect heating and reheat coils to.
|
@@ -1114,7 +1325,7 @@ class OpenStudio::Model::Model
|
|
1114
1325
|
# @param chilled_water_loop [String] chilled water loop to connect cooling coil to.
|
1115
1326
|
# @param building_type [String] the building type
|
1116
1327
|
# @return [OpenStudio::Model::AirLoopHVAC] the resulting packaged VAV air loop
|
1117
|
-
def add_cav(
|
1328
|
+
def add_cav(template,
|
1118
1329
|
sys_name,
|
1119
1330
|
hot_water_loop,
|
1120
1331
|
thermal_zones,
|
@@ -1123,37 +1334,36 @@ class OpenStudio::Model::Model
|
|
1123
1334
|
fan_efficiency,
|
1124
1335
|
fan_motor_efficiency,
|
1125
1336
|
fan_pressure_rise,
|
1126
|
-
chilled_water_loop=nil,
|
1127
|
-
building_type=nil)
|
1337
|
+
chilled_water_loop = nil,
|
1338
|
+
building_type = nil)
|
1128
1339
|
|
1129
|
-
OpenStudio
|
1340
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding CAV for #{thermal_zones.size} zones.")
|
1130
1341
|
thermal_zones.each do |zone|
|
1131
|
-
OpenStudio
|
1342
|
+
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.Model.Model', "---#{zone.name}")
|
1132
1343
|
end
|
1133
1344
|
|
1134
1345
|
# hvac operation schedule
|
1135
|
-
if hvac_op_sch.nil?
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1346
|
+
hvac_op_sch = if hvac_op_sch.nil?
|
1347
|
+
alwaysOnDiscreteSchedule
|
1348
|
+
else
|
1349
|
+
add_schedule(hvac_op_sch)
|
1350
|
+
end
|
1140
1351
|
|
1141
1352
|
# oa damper schedule
|
1142
|
-
if oa_damper_sch.nil?
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1353
|
+
oa_damper_sch = if oa_damper_sch.nil?
|
1354
|
+
alwaysOnDiscreteSchedule
|
1355
|
+
else
|
1356
|
+
add_schedule(oa_damper_sch)
|
1357
|
+
end
|
1148
1358
|
|
1149
1359
|
# Hot water loop control temperatures
|
1150
|
-
hw_temp_f = 152.6 #HW setpoint 152.6F
|
1360
|
+
hw_temp_f = 152.6 # HW setpoint 152.6F
|
1151
1361
|
if building_type == 'Hospital'
|
1152
1362
|
hw_temp_f = 180
|
1153
1363
|
end
|
1154
|
-
hw_delta_t_r = 20 #20F delta-T
|
1155
|
-
hw_temp_c = OpenStudio.convert(hw_temp_f,'F','C').get
|
1156
|
-
hw_delta_t_k = OpenStudio.convert(hw_delta_t_r,'R','K').get
|
1364
|
+
hw_delta_t_r = 20 # 20F delta-T
|
1365
|
+
hw_temp_c = OpenStudio.convert(hw_temp_f, 'F', 'C').get
|
1366
|
+
hw_delta_t_k = OpenStudio.convert(hw_delta_t_r, 'R', 'K').get
|
1157
1367
|
air_flow_ratio = 1
|
1158
1368
|
|
1159
1369
|
# Air handler control temperatures
|
@@ -1168,15 +1378,15 @@ class OpenStudio::Model::Model
|
|
1168
1378
|
zone_htg_sa_temp_f = 122 # Zone heating design supply air temperature to 122F
|
1169
1379
|
if building_type == 'Hospital'
|
1170
1380
|
htg_sa_temp_f = 104 # Central deck htg temp 104F
|
1171
|
-
#rht_sa_temp_f = 122 # VAV box reheat to 104F
|
1381
|
+
# rht_sa_temp_f = 122 # VAV box reheat to 104F
|
1172
1382
|
zone_htg_sa_temp_f = 104 # Zone heating design supply air temperature to 122F
|
1173
1383
|
end
|
1174
|
-
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f,'F','C').get
|
1175
|
-
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f,'F','C').get
|
1176
|
-
preclg_sa_temp_c = OpenStudio.convert(preclg_sa_temp_f,'F','C').get
|
1177
|
-
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f,'F','C').get
|
1178
|
-
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f,'F','C').get
|
1179
|
-
zone_htg_sa_temp_c = OpenStudio.convert(zone_htg_sa_temp_f,'F','C').get
|
1384
|
+
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f, 'F', 'C').get
|
1385
|
+
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f, 'F', 'C').get
|
1386
|
+
preclg_sa_temp_c = OpenStudio.convert(preclg_sa_temp_f, 'F', 'C').get
|
1387
|
+
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f, 'F', 'C').get
|
1388
|
+
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f, 'F', 'C').get
|
1389
|
+
zone_htg_sa_temp_c = OpenStudio.convert(zone_htg_sa_temp_f, 'F', 'C').get
|
1180
1390
|
|
1181
1391
|
# Air handler
|
1182
1392
|
air_loop = OpenStudio::Model::AirLoopHVAC.new(self)
|
@@ -1191,9 +1401,9 @@ class OpenStudio::Model::Model
|
|
1191
1401
|
sa_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
1192
1402
|
sa_temp_sch.setName("Supply Air Temp - #{clg_sa_temp_f}F")
|
1193
1403
|
sa_temp_sch.defaultDaySchedule.setName("Supply Air Temp - #{clg_sa_temp_f}F Default")
|
1194
|
-
sa_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),clg_sa_temp_c)
|
1404
|
+
sa_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), clg_sa_temp_c)
|
1195
1405
|
|
1196
|
-
sa_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self,sa_temp_sch)
|
1406
|
+
sa_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self, sa_temp_sch)
|
1197
1407
|
sa_stpt_manager.setName("#{air_loop.name} supply air setpoint manager")
|
1198
1408
|
sa_stpt_manager.addToNode(air_loop.supplyOutletNode)
|
1199
1409
|
|
@@ -1214,7 +1424,7 @@ class OpenStudio::Model::Model
|
|
1214
1424
|
sizing_system.setSystemOutdoorAirMethod('ZoneSum')
|
1215
1425
|
|
1216
1426
|
# Fan
|
1217
|
-
fan = OpenStudio::Model::FanConstantVolume.new(self,
|
1427
|
+
fan = OpenStudio::Model::FanConstantVolume.new(self, alwaysOnDiscreteSchedule)
|
1218
1428
|
fan.setName("#{air_loop.name} Fan")
|
1219
1429
|
if building_type == 'Hospital'
|
1220
1430
|
fan.setFanEfficiency(0.61425)
|
@@ -1226,10 +1436,10 @@ class OpenStudio::Model::Model
|
|
1226
1436
|
fan.setPressureRise(fan_pressure_rise)
|
1227
1437
|
end
|
1228
1438
|
fan.addToNode(air_loop.supplyInletNode)
|
1229
|
-
fan.setEndUseSubcategory(
|
1439
|
+
fan.setEndUseSubcategory('CAV system Fans')
|
1230
1440
|
|
1231
1441
|
# Air handler heating coil
|
1232
|
-
htg_coil = OpenStudio::Model::CoilHeatingWater.new(self,
|
1442
|
+
htg_coil = OpenStudio::Model::CoilHeatingWater.new(self, alwaysOnDiscreteSchedule)
|
1233
1443
|
htg_coil.addToNode(air_loop.supplyInletNode)
|
1234
1444
|
hot_water_loop.addDemandBranchForComponent(htg_coil)
|
1235
1445
|
htg_coil.setName("#{air_loop.name} Main Htg Coil")
|
@@ -1244,8 +1454,8 @@ class OpenStudio::Model::Model
|
|
1244
1454
|
if chilled_water_loop.nil?
|
1245
1455
|
clg_coil = OpenStudio::Model::CoilCoolingDXTwoSpeed.new(self)
|
1246
1456
|
else
|
1247
|
-
clg_coil = OpenStudio::Model::CoilCoolingWater.new(self,
|
1248
|
-
clg_coil.setHeatExchangerConfiguration(
|
1457
|
+
clg_coil = OpenStudio::Model::CoilCoolingWater.new(self, alwaysOnDiscreteSchedule)
|
1458
|
+
clg_coil.setHeatExchangerConfiguration('CrossFlow')
|
1249
1459
|
chilled_water_loop.addDemandBranchForComponent(clg_coil)
|
1250
1460
|
clg_coil.controllerWaterCoil.get.setName("#{air_loop.name} Clg Coil Controller")
|
1251
1461
|
end
|
@@ -1256,7 +1466,7 @@ class OpenStudio::Model::Model
|
|
1256
1466
|
oa_intake_controller = OpenStudio::Model::ControllerOutdoorAir.new(self)
|
1257
1467
|
oa_intake_controller.setName("#{air_loop.name} OA Controller")
|
1258
1468
|
oa_intake_controller.setMinimumLimitType('FixedMinimum')
|
1259
|
-
#oa_intake_controller.setMinimumOutdoorAirSchedule(motorized_oa_damper_sch)
|
1469
|
+
# oa_intake_controller.setMinimumOutdoorAirSchedule(motorized_oa_damper_sch)
|
1260
1470
|
oa_intake_controller.setMinimumFractionofOutdoorAirSchedule(oa_damper_sch)
|
1261
1471
|
oa_intake_controller.setHeatRecoveryBypassControlType('BypassWhenOAFlowGreaterThanMinimum')
|
1262
1472
|
|
@@ -1273,14 +1483,13 @@ class OpenStudio::Model::Model
|
|
1273
1483
|
|
1274
1484
|
# Connect the CAV system to each zone
|
1275
1485
|
thermal_zones.each do |zone|
|
1276
|
-
|
1277
1486
|
if building_type == 'Hospital'
|
1278
1487
|
# CAV terminal
|
1279
|
-
terminal = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(self,
|
1488
|
+
terminal = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(self, alwaysOnDiscreteSchedule)
|
1280
1489
|
terminal.setName("#{zone.name} CAV Term")
|
1281
1490
|
else
|
1282
1491
|
# Reheat coil
|
1283
|
-
rht_coil = OpenStudio::Model::CoilHeatingWater.new(self,
|
1492
|
+
rht_coil = OpenStudio::Model::CoilHeatingWater.new(self, alwaysOnDiscreteSchedule)
|
1284
1493
|
rht_coil.setName("#{zone.name} Rht Coil")
|
1285
1494
|
rht_coil.setRatedInletWaterTemperature(hw_temp_c)
|
1286
1495
|
rht_coil.setRatedInletAirTemperature(htg_sa_temp_c)
|
@@ -1289,15 +1498,15 @@ class OpenStudio::Model::Model
|
|
1289
1498
|
hot_water_loop.addDemandBranchForComponent(rht_coil)
|
1290
1499
|
|
1291
1500
|
# VAV terminal
|
1292
|
-
terminal = OpenStudio::Model::AirTerminalSingleDuctVAVReheat.new(self,
|
1501
|
+
terminal = OpenStudio::Model::AirTerminalSingleDuctVAVReheat.new(self, alwaysOnDiscreteSchedule, rht_coil)
|
1293
1502
|
terminal.setName("#{zone.name} VAV Term")
|
1294
1503
|
terminal.setZoneMinimumAirFlowMethod('Constant')
|
1295
|
-
terminal.
|
1504
|
+
terminal.apply_initial_prototype_damper_position(building_type, template, zone.outdoor_airflow_rate_per_area)
|
1296
1505
|
terminal.setMaximumFlowPerZoneFloorAreaDuringReheat(0.0)
|
1297
1506
|
terminal.setMaximumFlowFractionDuringReheat(0.5)
|
1298
1507
|
terminal.setMaximumReheatAirTemperature(rht_sa_temp_c)
|
1299
1508
|
end
|
1300
|
-
air_loop.addBranchForZone(zone,terminal.to_StraightComponent)
|
1509
|
+
air_loop.addBranchForZone(zone, terminal.to_StraightComponent)
|
1301
1510
|
|
1302
1511
|
# Zone sizing
|
1303
1512
|
# TODO Create general logic for cooling airflow method.
|
@@ -1306,25 +1515,23 @@ class OpenStudio::Model::Model
|
|
1306
1515
|
if building_type == 'SecondarySchool'
|
1307
1516
|
sizing_zone.setCoolingDesignAirFlowMethod('DesignDay')
|
1308
1517
|
else
|
1309
|
-
sizing_zone.setCoolingDesignAirFlowMethod(
|
1518
|
+
sizing_zone.setCoolingDesignAirFlowMethod('DesignDayWithLimit')
|
1310
1519
|
end
|
1311
|
-
sizing_zone.setHeatingDesignAirFlowMethod(
|
1520
|
+
sizing_zone.setHeatingDesignAirFlowMethod('DesignDay')
|
1312
1521
|
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(clg_sa_temp_c)
|
1313
|
-
#sizing_zone.setZoneHeatingDesignSupplyAirTemperature(rht_sa_temp_c)
|
1522
|
+
# sizing_zone.setZoneHeatingDesignSupplyAirTemperature(rht_sa_temp_c)
|
1314
1523
|
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(zone_htg_sa_temp_c)
|
1315
|
-
|
1316
1524
|
end
|
1317
1525
|
|
1318
1526
|
# Set the damper action based on the template.
|
1319
|
-
air_loop.
|
1527
|
+
air_loop.apply_vav_damper_action(template)
|
1320
1528
|
|
1321
1529
|
return true
|
1322
|
-
|
1323
1530
|
end
|
1324
1531
|
|
1325
1532
|
# Creates a PSZ-AC system for each zone and adds it to the model.
|
1326
1533
|
#
|
1327
|
-
# @param
|
1534
|
+
# @param template [String] Valid choices are 90.1-2004,
|
1328
1535
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
1329
1536
|
# @param sys_name [String] the name of the system, or nil in which case it will be defaulted
|
1330
1537
|
# @param hot_water_loop [String] hot water loop to connect heating coil to, or nil
|
@@ -1345,25 +1552,25 @@ class OpenStudio::Model::Model
|
|
1345
1552
|
# @return [Array<OpenStudio::Model::AirLoopHVAC>] an array of the resulting PSZ-AC air loops
|
1346
1553
|
# Todo: clarify where these default curves coefficients are coming from
|
1347
1554
|
# Todo: I (jmarrec) believe it is the DOE Ref curves ("DOE Ref DX Clg Coil Cool-Cap-fT")
|
1348
|
-
def add_psz_ac(
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
unless hot_water_loop.nil?
|
1363
|
-
hw_temp_f = 180 #HW setpoint 180F
|
1364
|
-
hw_delta_t_r = 20 #20F delta-T
|
1365
|
-
hw_temp_c = OpenStudio.convert(hw_temp_f,'F','C').get
|
1366
|
-
hw_delta_t_k = OpenStudio.convert(hw_delta_t_r,'R','K').get
|
1555
|
+
def add_psz_ac(template,
|
1556
|
+
sys_name,
|
1557
|
+
hot_water_loop,
|
1558
|
+
chilled_water_loop,
|
1559
|
+
thermal_zones,
|
1560
|
+
hvac_op_sch,
|
1561
|
+
oa_damper_sch,
|
1562
|
+
fan_location,
|
1563
|
+
fan_type,
|
1564
|
+
heating_type,
|
1565
|
+
supplemental_heating_type,
|
1566
|
+
cooling_type,
|
1567
|
+
building_type = nil)
|
1568
|
+
|
1569
|
+
unless hot_water_loop.nil? || chilled_water_loop.nil?
|
1570
|
+
hw_temp_f = 180 # HW setpoint 180F
|
1571
|
+
hw_delta_t_r = 20 # 20F delta-T
|
1572
|
+
hw_temp_c = OpenStudio.convert(hw_temp_f, 'F', 'C').get
|
1573
|
+
hw_delta_t_k = OpenStudio.convert(hw_delta_t_r, 'R', 'K').get
|
1367
1574
|
|
1368
1575
|
# control temps used across all air handlers
|
1369
1576
|
clg_sa_temp_f = 55 # Central deck clg temp 55F
|
@@ -1371,31 +1578,30 @@ class OpenStudio::Model::Model
|
|
1371
1578
|
htg_sa_temp_f = 55 # Central deck htg temp 55F
|
1372
1579
|
rht_sa_temp_f = 104 # VAV box reheat to 104F
|
1373
1580
|
|
1374
|
-
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f,'F','C').get
|
1375
|
-
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f,'F','C').get
|
1376
|
-
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f,'F','C').get
|
1377
|
-
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f,'F','C').get
|
1581
|
+
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f, 'F', 'C').get
|
1582
|
+
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f, 'F', 'C').get
|
1583
|
+
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f, 'F', 'C').get
|
1584
|
+
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f, 'F', 'C').get
|
1378
1585
|
end
|
1379
1586
|
|
1380
1587
|
# hvac operation schedule
|
1381
|
-
if hvac_op_sch.nil?
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1588
|
+
hvac_op_sch = if hvac_op_sch.nil?
|
1589
|
+
alwaysOnDiscreteSchedule
|
1590
|
+
else
|
1591
|
+
add_schedule(hvac_op_sch)
|
1592
|
+
end
|
1386
1593
|
|
1387
1594
|
# oa damper schedule
|
1388
|
-
if oa_damper_sch.nil?
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1595
|
+
oa_damper_sch = if oa_damper_sch.nil?
|
1596
|
+
alwaysOnDiscreteSchedule
|
1597
|
+
else
|
1598
|
+
add_schedule(oa_damper_sch)
|
1599
|
+
end
|
1393
1600
|
|
1394
1601
|
# Make a PSZ-AC for each zone
|
1395
1602
|
air_loops = []
|
1396
1603
|
thermal_zones.each do |zone|
|
1397
|
-
|
1398
|
-
OpenStudio::logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding PSZ-AC for #{zone.name}.")
|
1604
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding PSZ-AC for #{zone.name}.")
|
1399
1605
|
|
1400
1606
|
air_loop = OpenStudio::Model::AirLoopHVAC.new(self)
|
1401
1607
|
if sys_name.nil?
|
@@ -1434,7 +1640,7 @@ class OpenStudio::Model::Model
|
|
1434
1640
|
|
1435
1641
|
# Zone sizing
|
1436
1642
|
sizing_zone = zone.sizingZone
|
1437
|
-
if building_type == 'RetailStandalone' && (
|
1643
|
+
if building_type == 'RetailStandalone' && (template == 'DOE Ref 1980-2004' || template == 'DOE Ref Pre-1980')
|
1438
1644
|
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(14)
|
1439
1645
|
else
|
1440
1646
|
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(12.8)
|
@@ -1452,42 +1658,42 @@ class OpenStudio::Model::Model
|
|
1452
1658
|
# Cycling: Unitary System;
|
1453
1659
|
# CyclingHeatPump: Unitary Heat Pump system
|
1454
1660
|
if fan_type == 'ConstantVolume'
|
1455
|
-
fan = OpenStudio::Model::FanConstantVolume.new(self,hvac_op_sch)
|
1661
|
+
fan = OpenStudio::Model::FanConstantVolume.new(self, hvac_op_sch)
|
1456
1662
|
fan.setName("#{air_loop.name} Fan")
|
1457
1663
|
fan_static_pressure_in_h2o = 2.5
|
1458
|
-
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o, 'inH_{2}O','Pa').get
|
1664
|
+
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o, 'inH_{2}O', 'Pa').get
|
1459
1665
|
fan.setPressureRise(fan_static_pressure_pa)
|
1460
1666
|
fan.setFanEfficiency(0.54)
|
1461
1667
|
fan.setMotorEfficiency(0.90)
|
1462
1668
|
elsif fan_type == 'Cycling'
|
1463
1669
|
|
1464
|
-
fan = OpenStudio::Model::FanOnOff.new(self,hvac_op_sch) # Set fan op sch manually since fwd translator doesn't
|
1670
|
+
fan = OpenStudio::Model::FanOnOff.new(self, hvac_op_sch) # Set fan op sch manually since fwd translator doesn't
|
1465
1671
|
fan.setName("#{air_loop.name} Fan")
|
1466
1672
|
fan_static_pressure_in_h2o = 2.5
|
1467
|
-
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o, 'inH_{2}O','Pa').get
|
1673
|
+
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o, 'inH_{2}O', 'Pa').get
|
1468
1674
|
fan.setPressureRise(fan_static_pressure_pa)
|
1469
1675
|
fan.setFanEfficiency(0.54)
|
1470
1676
|
fan.setMotorEfficiency(0.90)
|
1471
1677
|
else
|
1472
|
-
OpenStudio
|
1678
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.Model.Model', "Fan type '#{fan_type}' not recognized, cannot add PSZ-AC.")
|
1473
1679
|
return []
|
1474
1680
|
end
|
1475
1681
|
|
1476
1682
|
htg_coil = nil
|
1477
1683
|
if heating_type == 'Gas'
|
1478
|
-
htg_coil = OpenStudio::Model::CoilHeatingGas.new(self,
|
1684
|
+
htg_coil = OpenStudio::Model::CoilHeatingGas.new(self, alwaysOnDiscreteSchedule)
|
1479
1685
|
htg_coil.setName("#{air_loop.name} Gas Htg Coil")
|
1480
1686
|
|
1481
|
-
if
|
1687
|
+
if template == 'DOE Ref Pre-1980'
|
1482
1688
|
htg_coil.setGasBurnerEfficiency(0.78)
|
1483
1689
|
end
|
1484
1690
|
|
1485
1691
|
elsif heating_type == 'Water'
|
1486
1692
|
if hot_water_loop.nil?
|
1487
|
-
OpenStudio
|
1693
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'No hot water plant loop supplied')
|
1488
1694
|
return false
|
1489
1695
|
end
|
1490
|
-
htg_coil = OpenStudio::Model::CoilHeatingWater.new(self,
|
1696
|
+
htg_coil = OpenStudio::Model::CoilHeatingWater.new(self, alwaysOnDiscreteSchedule)
|
1491
1697
|
htg_coil.setName("#{air_loop.name} Water Htg Coil")
|
1492
1698
|
htg_coil.setRatedInletWaterTemperature(hw_temp_c)
|
1493
1699
|
htg_coil.setRatedInletAirTemperature(prehtg_sa_temp_c)
|
@@ -1534,15 +1740,15 @@ class OpenStudio::Model::Model
|
|
1534
1740
|
htg_part_load_fraction.setMaximumValueofx(1.0)
|
1535
1741
|
|
1536
1742
|
htg_coil = OpenStudio::Model::CoilHeatingDXSingleSpeed.new(self,
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1743
|
+
alwaysOnDiscreteSchedule,
|
1744
|
+
htg_cap_f_of_temp,
|
1745
|
+
htg_cap_f_of_flow,
|
1746
|
+
htg_energy_input_ratio_f_of_temp,
|
1747
|
+
htg_energy_input_ratio_f_of_flow,
|
1748
|
+
htg_part_load_fraction)
|
1543
1749
|
|
1544
1750
|
htg_coil.setName("#{air_loop.name} HP Htg Coil")
|
1545
|
-
htg_coil.setRatedCOP(3.3) # TODO add this to standards
|
1751
|
+
htg_coil.setRatedCOP(3.3) # TODO: add this to standards
|
1546
1752
|
htg_coil.setMinimumOutdoorDryBulbTemperatureforCompressorOperation(-12.2)
|
1547
1753
|
htg_coil.setMaximumOutdoorDryBulbTemperatureforDefrostOperation(1.67)
|
1548
1754
|
htg_coil.setCrankcaseHeaterCapacity(50.0)
|
@@ -1566,12 +1772,12 @@ class OpenStudio::Model::Model
|
|
1566
1772
|
htg_coil.setDefrostEnergyInputRatioFunctionofTemperatureCurve(def_eir_f_of_temp)
|
1567
1773
|
elsif heating_type == 'Water To Air Heat Pump'
|
1568
1774
|
if hot_water_loop.nil?
|
1569
|
-
OpenStudio
|
1775
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'No hot water plant loop supplied')
|
1570
1776
|
return false
|
1571
1777
|
end
|
1572
1778
|
htg_coil = OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit.new(self)
|
1573
1779
|
htg_coil.setName("#{air_loop.name} Water-to-Air HP Htg Coil")
|
1574
|
-
htg_coil.setRatedHeatingCoefficientofPerformance(4.2) # TODO add this to standards
|
1780
|
+
htg_coil.setRatedHeatingCoefficientofPerformance(4.2) # TODO: add this to standards
|
1575
1781
|
htg_coil.setHeatingCapacityCoefficient1(0.237847462869254)
|
1576
1782
|
htg_coil.setHeatingCapacityCoefficient2(-3.35823796081626)
|
1577
1783
|
htg_coil.setHeatingCapacityCoefficient3(3.80640467406376)
|
@@ -1588,21 +1794,20 @@ class OpenStudio::Model::Model
|
|
1588
1794
|
|
1589
1795
|
supplemental_htg_coil = nil
|
1590
1796
|
if supplemental_heating_type == 'Electric'
|
1591
|
-
supplemental_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(self,
|
1797
|
+
supplemental_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(self, alwaysOnDiscreteSchedule)
|
1592
1798
|
supplemental_htg_coil.setName("#{air_loop.name} Electric Backup Htg Coil")
|
1593
1799
|
elsif supplemental_heating_type == 'Gas'
|
1594
|
-
supplemental_htg_coil = OpenStudio::Model::CoilHeatingGas.new(self,
|
1800
|
+
supplemental_htg_coil = OpenStudio::Model::CoilHeatingGas.new(self, alwaysOnDiscreteSchedule)
|
1595
1801
|
supplemental_htg_coil.setName("#{air_loop.name} Gas Backup Htg Coil")
|
1596
1802
|
end
|
1597
1803
|
|
1598
|
-
|
1599
1804
|
clg_coil = nil
|
1600
1805
|
if cooling_type == 'Water'
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
clg_coil = OpenStudio::Model::CoilCoolingWater.new(self,
|
1806
|
+
if chilled_water_loop.nil?
|
1807
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'No chilled water plant loop supplied')
|
1808
|
+
return false
|
1809
|
+
end
|
1810
|
+
clg_coil = OpenStudio::Model::CoilCoolingWater.new(self, alwaysOnDiscreteSchedule)
|
1606
1811
|
clg_coil.setName("#{air_loop.name} Water Clg Coil")
|
1607
1812
|
chilled_water_loop.addDemandBranchForComponent(clg_coil)
|
1608
1813
|
elsif cooling_type == 'Two Speed DX AC'
|
@@ -1677,14 +1882,14 @@ class OpenStudio::Model::Model
|
|
1677
1882
|
clg_energy_input_ratio_f_of_temp_low_spd.setMaximumValueofy(46.0)
|
1678
1883
|
|
1679
1884
|
clg_coil = OpenStudio::Model::CoilCoolingDXTwoSpeed.new(self,
|
1680
|
-
|
1681
|
-
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
1685
|
-
|
1686
|
-
|
1687
|
-
|
1885
|
+
alwaysOnDiscreteSchedule,
|
1886
|
+
clg_cap_f_of_temp,
|
1887
|
+
clg_cap_f_of_flow,
|
1888
|
+
clg_energy_input_ratio_f_of_temp,
|
1889
|
+
clg_energy_input_ratio_f_of_flow,
|
1890
|
+
clg_part_load_ratio,
|
1891
|
+
clg_cap_f_of_temp_low_spd,
|
1892
|
+
clg_energy_input_ratio_f_of_temp_low_spd)
|
1688
1893
|
|
1689
1894
|
clg_coil.setName("#{air_loop.name} 2spd DX AC Clg Coil")
|
1690
1895
|
clg_coil.setRatedLowSpeedSensibleHeatRatio(OpenStudio::OptionalDouble.new(0.69))
|
@@ -1743,12 +1948,12 @@ class OpenStudio::Model::Model
|
|
1743
1948
|
clg_part_load_ratio.setMaximumCurveOutput(1.0)
|
1744
1949
|
|
1745
1950
|
clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(self,
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1951
|
+
alwaysOnDiscreteSchedule,
|
1952
|
+
clg_cap_f_of_temp,
|
1953
|
+
clg_cap_f_of_flow,
|
1954
|
+
clg_energy_input_ratio_f_of_temp,
|
1955
|
+
clg_energy_input_ratio_f_of_flow,
|
1956
|
+
clg_part_load_ratio)
|
1752
1957
|
|
1753
1958
|
clg_coil.setName("#{air_loop.name} 1spd DX AC Clg Coil")
|
1754
1959
|
|
@@ -1800,27 +2005,27 @@ class OpenStudio::Model::Model
|
|
1800
2005
|
clg_part_load_ratio.setMaximumValueofx(1.0)
|
1801
2006
|
|
1802
2007
|
clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(self,
|
1803
|
-
|
1804
|
-
|
1805
|
-
|
1806
|
-
|
1807
|
-
|
1808
|
-
|
2008
|
+
alwaysOnDiscreteSchedule,
|
2009
|
+
clg_cap_f_of_temp,
|
2010
|
+
clg_cap_f_of_flow,
|
2011
|
+
clg_energy_input_ratio_f_of_temp,
|
2012
|
+
clg_energy_input_ratio_f_of_flow,
|
2013
|
+
clg_part_load_ratio)
|
1809
2014
|
|
1810
2015
|
clg_coil.setName("#{air_loop.name} 1spd DX HP Clg Coil")
|
1811
|
-
#clg_coil.setMaximumOutdoorDryBulbTemperatureForCrankcaseHeaterOperation(OpenStudio::OptionalDouble.new(10.0))
|
1812
|
-
#clg_coil.setRatedSensibleHeatRatio(0.69)
|
1813
|
-
#clg_coil.setBasinHeaterCapacity(10)
|
1814
|
-
#clg_coil.setBasinHeaterSetpointTemperature(2.0)
|
2016
|
+
# clg_coil.setMaximumOutdoorDryBulbTemperatureForCrankcaseHeaterOperation(OpenStudio::OptionalDouble.new(10.0))
|
2017
|
+
# clg_coil.setRatedSensibleHeatRatio(0.69)
|
2018
|
+
# clg_coil.setBasinHeaterCapacity(10)
|
2019
|
+
# clg_coil.setBasinHeaterSetpointTemperature(2.0)
|
1815
2020
|
|
1816
2021
|
elsif cooling_type == 'Water To Air Heat Pump'
|
1817
2022
|
if chilled_water_loop.nil?
|
1818
|
-
OpenStudio
|
2023
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'No chilled water plant loop supplied')
|
1819
2024
|
return false
|
1820
2025
|
end
|
1821
2026
|
clg_coil = OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit.new(self)
|
1822
2027
|
clg_coil.setName("#{air_loop.name} Water-to-Air HP Clg Coil")
|
1823
|
-
clg_coil.setRatedCoolingCoefficientofPerformance(3.4) # TODO add this to standards
|
2028
|
+
clg_coil.setRatedCoolingCoefficientofPerformance(3.4) # TODO: add this to standards
|
1824
2029
|
|
1825
2030
|
clg_coil.setTotalCoolingCapacityCoefficient1(-4.30266987344639)
|
1826
2031
|
clg_coil.setTotalCoolingCapacityCoefficient2(7.18536990534372)
|
@@ -1846,15 +2051,15 @@ class OpenStudio::Model::Model
|
|
1846
2051
|
oa_controller.setName("#{air_loop.name} OA Sys Controller")
|
1847
2052
|
oa_controller.setMinimumOutdoorAirSchedule(oa_damper_sch)
|
1848
2053
|
oa_controller.setHeatRecoveryBypassControlType('BypassWhenOAFlowGreaterThanMinimum')
|
1849
|
-
oa_system = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(self,oa_controller)
|
2054
|
+
oa_system = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(self, oa_controller)
|
1850
2055
|
oa_system.setName("#{air_loop.name} OA Sys")
|
1851
|
-
econ_eff_sch =
|
2056
|
+
econ_eff_sch = add_schedule('RetailStandalone PSZ_Econ_MaxOAFrac_Sch')
|
1852
2057
|
|
1853
|
-
case
|
1854
|
-
when '90.1-2004','90.1-2007','90.1-2010','90.1-2013'
|
1855
|
-
oa_controller.setMaximumFractionofOutdoorAirSchedule(econ_eff_sch) if building_type ==
|
1856
|
-
when 'DOE Ref Pre-1980','DOE Ref 1980-2004'
|
1857
|
-
OpenStudio
|
2058
|
+
case template
|
2059
|
+
when '90.1-2004', '90.1-2007', '90.1-2010', '90.1-2013'
|
2060
|
+
oa_controller.setMaximumFractionofOutdoorAirSchedule(econ_eff_sch) if building_type == 'RetailStandalone' || building_type == 'RetailStripmall'
|
2061
|
+
when 'DOE Ref Pre-1980', 'DOE Ref 1980-2004'
|
2062
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'No maximum fraction outdoor air schedule in PSZ for building types except RetailStandalone')
|
1858
2063
|
end
|
1859
2064
|
|
1860
2065
|
# Add the components to the air loop
|
@@ -1875,28 +2080,28 @@ class OpenStudio::Model::Model
|
|
1875
2080
|
unitary_system.setControllingZoneorThermostatLocation(zone)
|
1876
2081
|
unitary_system.setMaximumSupplyAirTemperature(50)
|
1877
2082
|
unitary_system.setFanPlacement('BlowThrough')
|
1878
|
-
unitary_system.setSupplyAirFlowRateMethodDuringCoolingOperation(
|
1879
|
-
unitary_system.setSupplyAirFlowRateMethodDuringHeatingOperation(
|
1880
|
-
unitary_system.setSupplyAirFlowRateMethodWhenNoCoolingorHeatingisRequired(
|
1881
|
-
unitary_system.setSupplyAirFanOperatingModeSchedule(
|
2083
|
+
unitary_system.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
|
2084
|
+
unitary_system.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
|
2085
|
+
unitary_system.setSupplyAirFlowRateMethodWhenNoCoolingorHeatingisRequired('SupplyAirFlowRate')
|
2086
|
+
unitary_system.setSupplyAirFanOperatingModeSchedule(alwaysOnDiscreteSchedule)
|
1882
2087
|
unitary_system.addToNode(supply_inlet_node)
|
1883
2088
|
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(50)
|
1884
2089
|
else
|
1885
2090
|
unitary_system = OpenStudio::Model::AirLoopHVACUnitaryHeatPumpAirToAir.new(self,
|
1886
|
-
|
1887
|
-
|
1888
|
-
|
1889
|
-
|
1890
|
-
|
2091
|
+
alwaysOnDiscreteSchedule,
|
2092
|
+
fan,
|
2093
|
+
htg_coil,
|
2094
|
+
clg_coil,
|
2095
|
+
supplemental_htg_coil)
|
1891
2096
|
unitary_system.setName("#{air_loop.name} Unitary HP")
|
1892
2097
|
unitary_system.setControllingZone(zone)
|
1893
|
-
unitary_system.setMaximumOutdoorDryBulbTemperatureforSupplementalHeaterOperation(OpenStudio.convert(40,'F','C').get)
|
2098
|
+
unitary_system.setMaximumOutdoorDryBulbTemperatureforSupplementalHeaterOperation(OpenStudio.convert(40, 'F', 'C').get)
|
1894
2099
|
unitary_system.setFanPlacement(fan_location)
|
1895
2100
|
unitary_system.setSupplyAirFanOperatingModeSchedule(hvac_op_sch)
|
1896
2101
|
unitary_system.addToNode(supply_inlet_node)
|
1897
2102
|
|
1898
|
-
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(OpenStudio.convert(55,'F','C').get)
|
1899
|
-
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(OpenStudio.convert(104,'F','C').get)
|
2103
|
+
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(OpenStudio.convert(55, 'F', 'C').get)
|
2104
|
+
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(OpenStudio.convert(104, 'F', 'C').get)
|
1900
2105
|
end
|
1901
2106
|
|
1902
2107
|
else
|
@@ -1941,12 +2146,12 @@ class OpenStudio::Model::Model
|
|
1941
2146
|
fan.addToNode(supply_inlet_node)
|
1942
2147
|
end
|
1943
2148
|
else
|
1944
|
-
OpenStudio
|
2149
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'Invalid fan location')
|
1945
2150
|
return false
|
1946
2151
|
end
|
1947
2152
|
|
1948
|
-
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(OpenStudio.convert(50,'F','C').get)
|
1949
|
-
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(OpenStudio.convert(122,'F','C').get)
|
2153
|
+
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(OpenStudio.convert(50, 'F', 'C').get)
|
2154
|
+
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(OpenStudio.convert(122, 'F', 'C').get)
|
1950
2155
|
|
1951
2156
|
end
|
1952
2157
|
|
@@ -1958,14 +2163,12 @@ class OpenStudio::Model::Model
|
|
1958
2163
|
air_loop.setNightCycleControlType('CycleOnAny')
|
1959
2164
|
|
1960
2165
|
# Create a diffuser and attach the zone/diffuser pair to the air loop
|
1961
|
-
diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(self,
|
2166
|
+
diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(self, alwaysOnDiscreteSchedule)
|
1962
2167
|
diffuser.setName("#{air_loop.name} Diffuser")
|
1963
|
-
air_loop.addBranchForZone(zone,diffuser.to_StraightComponent)
|
1964
|
-
|
2168
|
+
air_loop.addBranchForZone(zone, diffuser.to_StraightComponent)
|
1965
2169
|
end
|
1966
2170
|
|
1967
2171
|
return air_loops
|
1968
|
-
|
1969
2172
|
end
|
1970
2173
|
|
1971
2174
|
# Adds a data center load to a given space.
|
@@ -1974,7 +2177,6 @@ class OpenStudio::Model::Model
|
|
1974
2177
|
# @param dc_watts_per_area [Double] data center load, in W/m^2
|
1975
2178
|
# @return [Bool] returns true if successful, false if not
|
1976
2179
|
def add_data_center_load(space, dc_watts_per_area)
|
1977
|
-
|
1978
2180
|
# Data center load
|
1979
2181
|
data_center_definition = OpenStudio::Model::ElectricEquipmentDefinition.new(self)
|
1980
2182
|
data_center_definition.setName('Data Center Load')
|
@@ -1982,17 +2184,16 @@ class OpenStudio::Model::Model
|
|
1982
2184
|
|
1983
2185
|
data_center_equipment = OpenStudio::Model::ElectricEquipment.new(data_center_definition)
|
1984
2186
|
data_center_equipment.setName('Data Center Load')
|
1985
|
-
data_center_sch =
|
2187
|
+
data_center_sch = alwaysOnDiscreteSchedule
|
1986
2188
|
data_center_equipment.setSchedule(data_center_sch)
|
1987
2189
|
data_center_equipment.setSpace(space)
|
1988
2190
|
|
1989
2191
|
return true
|
1990
|
-
|
1991
2192
|
end
|
1992
2193
|
|
1993
2194
|
# Creates a data center PSZ-AC system for each zone.
|
1994
2195
|
#
|
1995
|
-
# @param
|
2196
|
+
# @param template [String] Valid choices are 90.1-2004,
|
1996
2197
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
1997
2198
|
# @param sys_name [String] the name of the system, or nil in which case it will be defaulted
|
1998
2199
|
# @param hot_water_loop [String] hot water loop to connect heatin coil to
|
@@ -2005,24 +2206,23 @@ class OpenStudio::Model::Model
|
|
2005
2206
|
# @param main_data_center [Bool] whether or not this is the main data
|
2006
2207
|
# center in the building.
|
2007
2208
|
# @return [Array<OpenStudio::Model::AirLoopHVAC>] an array of the resulting air loops
|
2008
|
-
def add_data_center_hvac(
|
2009
|
-
|
2010
|
-
|
2011
|
-
|
2012
|
-
|
2013
|
-
|
2014
|
-
|
2015
|
-
|
2016
|
-
|
2209
|
+
def add_data_center_hvac(template,
|
2210
|
+
sys_name,
|
2211
|
+
hot_water_loop,
|
2212
|
+
heat_pump_loop,
|
2213
|
+
thermal_zones,
|
2214
|
+
hvac_op_sch,
|
2215
|
+
oa_damper_sch,
|
2216
|
+
main_data_center = false)
|
2017
2217
|
|
2018
2218
|
thermal_zones.each do |zone|
|
2019
|
-
OpenStudio
|
2219
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding data center HVAC for #{zone.name}.")
|
2020
2220
|
end
|
2021
2221
|
|
2022
|
-
hw_temp_f = 180 #HW setpoint 180F
|
2023
|
-
hw_delta_t_r = 20 #20F delta-T
|
2024
|
-
hw_temp_c = OpenStudio.convert(hw_temp_f,'F','C').get
|
2025
|
-
hw_delta_t_k = OpenStudio.convert(hw_delta_t_r,'R','K').get
|
2222
|
+
hw_temp_f = 180 # HW setpoint 180F
|
2223
|
+
hw_delta_t_r = 20 # 20F delta-T
|
2224
|
+
hw_temp_c = OpenStudio.convert(hw_temp_f, 'F', 'C').get
|
2225
|
+
hw_delta_t_k = OpenStudio.convert(hw_delta_t_r, 'R', 'K').get
|
2026
2226
|
|
2027
2227
|
# control temps used across all air handlers
|
2028
2228
|
clg_sa_temp_f = 55 # Central deck clg temp 55F
|
@@ -2030,29 +2230,28 @@ class OpenStudio::Model::Model
|
|
2030
2230
|
htg_sa_temp_f = 55 # Central deck htg temp 55F
|
2031
2231
|
rht_sa_temp_f = 104 # VAV box reheat to 104F
|
2032
2232
|
|
2033
|
-
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f,'F','C').get
|
2034
|
-
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f,'F','C').get
|
2035
|
-
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f,'F','C').get
|
2036
|
-
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f,'F','C').get
|
2233
|
+
clg_sa_temp_c = OpenStudio.convert(clg_sa_temp_f, 'F', 'C').get
|
2234
|
+
prehtg_sa_temp_c = OpenStudio.convert(prehtg_sa_temp_f, 'F', 'C').get
|
2235
|
+
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f, 'F', 'C').get
|
2236
|
+
rht_sa_temp_c = OpenStudio.convert(rht_sa_temp_f, 'F', 'C').get
|
2037
2237
|
|
2038
2238
|
# hvac operation schedule
|
2039
|
-
if hvac_op_sch.nil?
|
2040
|
-
|
2041
|
-
|
2042
|
-
|
2043
|
-
|
2239
|
+
hvac_op_sch = if hvac_op_sch.nil?
|
2240
|
+
alwaysOnDiscreteSchedule
|
2241
|
+
else
|
2242
|
+
add_schedule(hvac_op_sch)
|
2243
|
+
end
|
2044
2244
|
|
2045
2245
|
# oa damper schedule
|
2046
|
-
if oa_damper_sch.nil?
|
2047
|
-
|
2048
|
-
|
2049
|
-
|
2050
|
-
|
2246
|
+
oa_damper_sch = if oa_damper_sch.nil?
|
2247
|
+
alwaysOnDiscreteSchedule
|
2248
|
+
else
|
2249
|
+
add_schedule(oa_damper_sch)
|
2250
|
+
end
|
2051
2251
|
|
2052
2252
|
# Make a PSZ-AC for each zone
|
2053
2253
|
air_loops = []
|
2054
2254
|
thermal_zones.each do |zone|
|
2055
|
-
|
2056
2255
|
air_loop = OpenStudio::Model::AirLoopHVAC.new(self)
|
2057
2256
|
if sys_name.nil?
|
2058
2257
|
air_loop.setName("#{zone.name} PSZ-AC Data Center")
|
@@ -2098,17 +2297,17 @@ class OpenStudio::Model::Model
|
|
2098
2297
|
setpoint_mgr_single_zone_reheat = OpenStudio::Model::SetpointManagerSingleZoneReheat.new(self)
|
2099
2298
|
setpoint_mgr_single_zone_reheat.setControlZone(zone)
|
2100
2299
|
|
2101
|
-
fan = OpenStudio::Model::FanOnOff.new(self,hvac_op_sch) # Set fan op sch manually since fwd translator doesn't
|
2300
|
+
fan = OpenStudio::Model::FanOnOff.new(self, hvac_op_sch) # Set fan op sch manually since fwd translator doesn't
|
2102
2301
|
fan.setName("#{air_loop.name} Fan")
|
2103
2302
|
fan_static_pressure_in_h2o = 2.5
|
2104
|
-
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o, 'inH_{2}O','Pa').get
|
2303
|
+
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o, 'inH_{2}O', 'Pa').get
|
2105
2304
|
fan.setPressureRise(fan_static_pressure_pa)
|
2106
2305
|
fan.setFanEfficiency(0.54)
|
2107
2306
|
fan.setMotorEfficiency(0.90)
|
2108
2307
|
|
2109
2308
|
htg_coil = OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit.new(self)
|
2110
2309
|
htg_coil.setName("#{air_loop.name} Water-to-Air HP Htg Coil")
|
2111
|
-
htg_coil.setRatedHeatingCoefficientofPerformance(4.2) # TODO add this to standards
|
2310
|
+
htg_coil.setRatedHeatingCoefficientofPerformance(4.2) # TODO: add this to standards
|
2112
2311
|
htg_coil.setHeatingCapacityCoefficient1(0.237847462869254)
|
2113
2312
|
htg_coil.setHeatingCapacityCoefficient2(-3.35823796081626)
|
2114
2313
|
htg_coil.setHeatingCapacityCoefficient3(3.80640467406376)
|
@@ -2124,7 +2323,7 @@ class OpenStudio::Model::Model
|
|
2124
2323
|
|
2125
2324
|
clg_coil = OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit.new(self)
|
2126
2325
|
clg_coil.setName("#{air_loop.name} Water-to-Air HP Clg Coil")
|
2127
|
-
clg_coil.setRatedCoolingCoefficientofPerformance(3.4) # TODO add this to standards
|
2326
|
+
clg_coil.setRatedCoolingCoefficientofPerformance(3.4) # TODO: add this to standards
|
2128
2327
|
|
2129
2328
|
clg_coil.setTotalCoolingCapacityCoefficient1(-4.30266987344639)
|
2130
2329
|
clg_coil.setTotalCoolingCapacityCoefficient2(7.18536990534372)
|
@@ -2145,13 +2344,13 @@ class OpenStudio::Model::Model
|
|
2145
2344
|
|
2146
2345
|
heat_pump_loop.addDemandBranchForComponent(clg_coil)
|
2147
2346
|
|
2148
|
-
supplemental_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(self,
|
2347
|
+
supplemental_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(self, alwaysOnDiscreteSchedule)
|
2149
2348
|
supplemental_htg_coil.setName("#{air_loop.name} Electric Backup Htg Coil")
|
2150
2349
|
|
2151
2350
|
oa_controller = OpenStudio::Model::ControllerOutdoorAir.new(self)
|
2152
2351
|
oa_controller.setName("#{air_loop.name} OA Sys Controller")
|
2153
2352
|
oa_controller.setMinimumOutdoorAirSchedule(oa_damper_sch)
|
2154
|
-
oa_system = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(self,oa_controller)
|
2353
|
+
oa_system = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(self, oa_controller)
|
2155
2354
|
oa_system.setName("#{air_loop.name} OA Sys")
|
2156
2355
|
|
2157
2356
|
# Add the components to the air loop
|
@@ -2161,13 +2360,13 @@ class OpenStudio::Model::Model
|
|
2161
2360
|
if main_data_center
|
2162
2361
|
humidifier = OpenStudio::Model::HumidifierSteamElectric.new(self)
|
2163
2362
|
humidifier.setRatedCapacity(3.72E-5)
|
2164
|
-
humidifier.setRatedPower(
|
2363
|
+
humidifier.setRatedPower(100_000)
|
2165
2364
|
humidifier.setName("#{air_loop.name} Electric Steam Humidifier")
|
2166
2365
|
|
2167
|
-
extra_elec_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(self,
|
2366
|
+
extra_elec_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(self, alwaysOnDiscreteSchedule)
|
2168
2367
|
extra_elec_htg_coil.setName("#{air_loop.name} Electric Htg Coil")
|
2169
2368
|
|
2170
|
-
extra_water_htg_coil = OpenStudio::Model::CoilHeatingWater.new(self,
|
2369
|
+
extra_water_htg_coil = OpenStudio::Model::CoilHeatingWater.new(self, alwaysOnDiscreteSchedule)
|
2171
2370
|
extra_water_htg_coil.setName("#{air_loop.name} Water Htg Coil")
|
2172
2371
|
extra_water_htg_coil.setRatedInletWaterTemperature(hw_temp_c)
|
2173
2372
|
extra_water_htg_coil.setRatedInletAirTemperature(prehtg_sa_temp_c)
|
@@ -2182,10 +2381,10 @@ class OpenStudio::Model::Model
|
|
2182
2381
|
humidity_spm = OpenStudio::Model::SetpointManagerSingleZoneHumidityMinimum.new(self)
|
2183
2382
|
humidity_spm.setControlZone(zone)
|
2184
2383
|
|
2185
|
-
humidity_spm.addToNode(humidifier.outletModelObject
|
2384
|
+
humidity_spm.addToNode(humidifier.outletModelObject.get.to_Node.get)
|
2186
2385
|
|
2187
2386
|
humidistat = OpenStudio::Model::ZoneControlHumidistat.new(self)
|
2188
|
-
humidistat.setHumidifyingRelativeHumiditySetpointSchedule(
|
2387
|
+
humidistat.setHumidifyingRelativeHumiditySetpointSchedule(add_schedule('OfficeLarge DC_MinRelHumSetSch'))
|
2189
2388
|
zone.setZoneControlHumidistat(humidistat)
|
2190
2389
|
end
|
2191
2390
|
|
@@ -2197,14 +2396,14 @@ class OpenStudio::Model::Model
|
|
2197
2396
|
|
2198
2397
|
unitary_system.setName("#{zone.name} Unitary HP")
|
2199
2398
|
unitary_system.setControllingZoneorThermostatLocation(zone)
|
2200
|
-
unitary_system.setMaximumOutdoorDryBulbTemperatureforSupplementalHeaterOperation(OpenStudio.convert(40,'F','C').get)
|
2399
|
+
unitary_system.setMaximumOutdoorDryBulbTemperatureforSupplementalHeaterOperation(OpenStudio.convert(40, 'F', 'C').get)
|
2201
2400
|
unitary_system.setFanPlacement('BlowThrough')
|
2202
2401
|
unitary_system.setSupplyAirFanOperatingModeSchedule(hvac_op_sch)
|
2203
|
-
unitary_system.setSupplyAirFanOperatingModeSchedule(
|
2402
|
+
unitary_system.setSupplyAirFanOperatingModeSchedule(alwaysOnDiscreteSchedule)
|
2204
2403
|
unitary_system.addToNode(supply_inlet_node)
|
2205
2404
|
|
2206
|
-
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(OpenStudio.convert(55,'F','C').get)
|
2207
|
-
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(OpenStudio.convert(104,'F','C').get)
|
2405
|
+
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(OpenStudio.convert(55, 'F', 'C').get)
|
2406
|
+
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(OpenStudio.convert(104, 'F', 'C').get)
|
2208
2407
|
|
2209
2408
|
# Add the OA system
|
2210
2409
|
oa_system.addToNode(supply_inlet_node)
|
@@ -2214,19 +2413,17 @@ class OpenStudio::Model::Model
|
|
2214
2413
|
air_loop.setNightCycleControlType('CycleOnAny')
|
2215
2414
|
|
2216
2415
|
# Create a diffuser and attach the zone/diffuser pair to the air loop
|
2217
|
-
diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(self,
|
2416
|
+
diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(self, alwaysOnDiscreteSchedule)
|
2218
2417
|
diffuser.setName("#{air_loop.name} Diffuser")
|
2219
|
-
air_loop.addBranchForZone(zone,diffuser.to_StraightComponent)
|
2220
|
-
|
2418
|
+
air_loop.addBranchForZone(zone, diffuser.to_StraightComponent)
|
2221
2419
|
end
|
2222
2420
|
|
2223
2421
|
return air_loops
|
2224
|
-
|
2225
2422
|
end
|
2226
2423
|
|
2227
2424
|
# Creates a split DX AC system for each zone and adds it to the model.
|
2228
2425
|
#
|
2229
|
-
# @param
|
2426
|
+
# @param template [String] Valid choices are 90.1-2004,
|
2230
2427
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
2231
2428
|
# @param sys_name [String] the name of the system, or nil in which case it will be defaulted
|
2232
2429
|
# @param thermal_zones [String] zones to connect to this system
|
@@ -2241,45 +2438,45 @@ class OpenStudio::Model::Model
|
|
2241
2438
|
# Single Speed DX AC, Single Speed Heat Pump
|
2242
2439
|
# @param building_type [String] the building type
|
2243
2440
|
# @return [OpenStudio::Model::AirLoopHVAC] the resulting split AC air loop.
|
2244
|
-
def
|
2245
|
-
|
2246
|
-
|
2247
|
-
|
2248
|
-
|
2249
|
-
|
2250
|
-
|
2251
|
-
|
2252
|
-
|
2253
|
-
|
2254
|
-
|
2441
|
+
def add_split_ac(template,
|
2442
|
+
sys_name,
|
2443
|
+
thermal_zones,
|
2444
|
+
hvac_op_sch,
|
2445
|
+
alt_hvac_op_sch,
|
2446
|
+
oa_damper_sch,
|
2447
|
+
fan_type,
|
2448
|
+
heating_type,
|
2449
|
+
supplemental_heating_type,
|
2450
|
+
cooling_type,
|
2451
|
+
building_type = nil)
|
2255
2452
|
|
2256
2453
|
thermal_zones.each do |zone|
|
2257
|
-
OpenStudio
|
2454
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding split DX AC for #{zone.name}.")
|
2258
2455
|
end
|
2259
2456
|
|
2260
2457
|
# hvac operation schedule
|
2261
|
-
if hvac_op_sch.nil?
|
2262
|
-
|
2263
|
-
|
2264
|
-
|
2265
|
-
|
2458
|
+
hvac_op_sch = if hvac_op_sch.nil?
|
2459
|
+
alwaysOnDiscreteSchedule
|
2460
|
+
else
|
2461
|
+
add_schedule(hvac_op_sch)
|
2462
|
+
end
|
2266
2463
|
|
2267
2464
|
# alternate hvac operation schedule
|
2268
|
-
if alt_hvac_op_sch.nil?
|
2269
|
-
|
2270
|
-
|
2271
|
-
|
2272
|
-
|
2465
|
+
alt_hvac_op_sch = if alt_hvac_op_sch.nil?
|
2466
|
+
alwaysOnDiscreteSchedule
|
2467
|
+
else
|
2468
|
+
add_schedule(alt_hvac_op_sch)
|
2469
|
+
end
|
2273
2470
|
|
2274
2471
|
# oa damper schedule
|
2275
|
-
if oa_damper_sch.nil?
|
2276
|
-
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
2472
|
+
oa_damper_sch = if oa_damper_sch.nil?
|
2473
|
+
alwaysOnDiscreteSchedule
|
2474
|
+
else
|
2475
|
+
add_schedule(oa_damper_sch)
|
2476
|
+
end
|
2280
2477
|
|
2281
2478
|
# OA_controller Maximum OA Fraction schedule
|
2282
|
-
|
2479
|
+
econ_max_oa_frac_sch = add_schedule('HotelSmall SAC_Econ_MaxOAFrac_Sch')
|
2283
2480
|
|
2284
2481
|
# Make a SAC for each group of thermal zones
|
2285
2482
|
parts = []
|
@@ -2287,7 +2484,7 @@ class OpenStudio::Model::Model
|
|
2287
2484
|
thermal_zones.each do |zone|
|
2288
2485
|
name = zone.name
|
2289
2486
|
parts << name.get
|
2290
|
-
#get space types
|
2487
|
+
# get space types
|
2291
2488
|
zone.spaces.each do |space|
|
2292
2489
|
space_type_name = space.spaceType.get.standardsSpaceType.get
|
2293
2490
|
space_type_names << space_type_name
|
@@ -2299,7 +2496,6 @@ class OpenStudio::Model::Model
|
|
2299
2496
|
sizing_zone.setZoneHeatingDesignSupplyAirTemperature(50.0)
|
2300
2497
|
sizing_zone.setZoneCoolingDesignSupplyAirHumidityRatio(0.008)
|
2301
2498
|
sizing_zone.setZoneHeatingDesignSupplyAirHumidityRatio(0.008)
|
2302
|
-
|
2303
2499
|
end
|
2304
2500
|
thermal_zone_name = parts.join(' - ')
|
2305
2501
|
|
@@ -2318,7 +2514,7 @@ class OpenStudio::Model::Model
|
|
2318
2514
|
# this systems is a constant volume system with no VAV terminals,
|
2319
2515
|
# and therfore needs different default settings
|
2320
2516
|
air_loop_sizing = air_loop.sizingSystem # TODO units
|
2321
|
-
air_loop_sizing.setTypeofLoadtoSizeOn(
|
2517
|
+
air_loop_sizing.setTypeofLoadtoSizeOn('Sensible')
|
2322
2518
|
air_loop_sizing.autosizeDesignOutdoorAirFlowRate
|
2323
2519
|
air_loop_sizing.setMinimumSystemAirFlowRatio(1.0)
|
2324
2520
|
air_loop_sizing.setPreheatDesignTemperature(7.0)
|
@@ -2327,16 +2523,16 @@ class OpenStudio::Model::Model
|
|
2327
2523
|
air_loop_sizing.setPrecoolDesignHumidityRatio(0.008)
|
2328
2524
|
air_loop_sizing.setCentralCoolingDesignSupplyAirTemperature(12)
|
2329
2525
|
air_loop_sizing.setCentralHeatingDesignSupplyAirTemperature(50)
|
2330
|
-
air_loop_sizing.setSizingOption(
|
2526
|
+
air_loop_sizing.setSizingOption('NonCoincident')
|
2331
2527
|
air_loop_sizing.setAllOutdoorAirinCooling(false)
|
2332
2528
|
air_loop_sizing.setAllOutdoorAirinHeating(false)
|
2333
2529
|
air_loop_sizing.setCentralCoolingDesignSupplyAirHumidityRatio(0.008)
|
2334
2530
|
air_loop_sizing.setCentralHeatingDesignSupplyAirHumidityRatio(0.0080)
|
2335
|
-
air_loop_sizing.setCoolingDesignAirFlowMethod(
|
2531
|
+
air_loop_sizing.setCoolingDesignAirFlowMethod('DesignDay')
|
2336
2532
|
air_loop_sizing.setCoolingDesignAirFlowRate(0.0)
|
2337
|
-
air_loop_sizing.setHeatingDesignAirFlowMethod(
|
2533
|
+
air_loop_sizing.setHeatingDesignAirFlowMethod('DesignDay')
|
2338
2534
|
air_loop_sizing.setHeatingDesignAirFlowRate(0.0)
|
2339
|
-
air_loop_sizing.setSystemOutdoorAirMethod(
|
2535
|
+
air_loop_sizing.setSystemOutdoorAirMethod('ZoneSum')
|
2340
2536
|
|
2341
2537
|
# Add a setpoint manager single zone reheat to control the
|
2342
2538
|
# supply air temperature based on the needs of this zone
|
@@ -2346,19 +2542,19 @@ class OpenStudio::Model::Model
|
|
2346
2542
|
|
2347
2543
|
# Fan
|
2348
2544
|
fan = nil
|
2349
|
-
if fan_type ==
|
2350
|
-
fan = OpenStudio::Model::FanConstantVolume.new(self,
|
2545
|
+
if fan_type == 'ConstantVolume'
|
2546
|
+
fan = OpenStudio::Model::FanConstantVolume.new(self, alwaysOnDiscreteSchedule)
|
2351
2547
|
fan.setName("#{thermal_zone_name} SAC Fan")
|
2352
2548
|
fan_static_pressure_in_h2o = 2.5
|
2353
|
-
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o,
|
2549
|
+
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o, 'inH_{2}O', 'Pa').get
|
2354
2550
|
fan.setPressureRise(fan_static_pressure_pa)
|
2355
|
-
fan.setFanEfficiency(0.56)
|
2356
|
-
fan.setMotorEfficiency(0.86)
|
2357
|
-
elsif fan_type ==
|
2358
|
-
fan = OpenStudio::Model::FanOnOff.new(self,
|
2551
|
+
fan.setFanEfficiency(0.56) # get the average of four fans
|
2552
|
+
fan.setMotorEfficiency(0.86) # get the average of four fans
|
2553
|
+
elsif fan_type == 'Cycling'
|
2554
|
+
fan = OpenStudio::Model::FanOnOff.new(self, alwaysOnDiscreteSchedule)
|
2359
2555
|
fan.setName("#{thermal_zone_name} SAC Fan")
|
2360
2556
|
fan_static_pressure_in_h2o = 2.5
|
2361
|
-
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o,
|
2557
|
+
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o, 'inH_{2}O', 'Pa').get
|
2362
2558
|
fan.setPressureRise(fan_static_pressure_pa)
|
2363
2559
|
fan.setFanEfficiency(0.53625)
|
2364
2560
|
fan.setMotorEfficiency(0.825)
|
@@ -2366,8 +2562,8 @@ class OpenStudio::Model::Model
|
|
2366
2562
|
|
2367
2563
|
# Heating Coil
|
2368
2564
|
htg_coil = nil
|
2369
|
-
if heating_type ==
|
2370
|
-
htg_coil = OpenStudio::Model::CoilHeatingGas.new(self,
|
2565
|
+
if heating_type == 'Gas'
|
2566
|
+
htg_coil = OpenStudio::Model::CoilHeatingGas.new(self, alwaysOnDiscreteSchedule)
|
2371
2567
|
htg_coil.setName("#{thermal_zone_name} SAC Gas Htg Coil")
|
2372
2568
|
htg_coil.setGasBurnerEfficiency(0.8)
|
2373
2569
|
htg_part_load_fraction_correlation = OpenStudio::Model::CurveCubic.new(self)
|
@@ -2378,7 +2574,7 @@ class OpenStudio::Model::Model
|
|
2378
2574
|
htg_part_load_fraction_correlation.setMinimumValueofx(0)
|
2379
2575
|
htg_part_load_fraction_correlation.setMaximumValueofx(1)
|
2380
2576
|
htg_coil.setPartLoadFractionCorrelationCurve(htg_part_load_fraction_correlation)
|
2381
|
-
elsif heating_type ==
|
2577
|
+
elsif heating_type == 'Single Speed Heat Pump'
|
2382
2578
|
htg_cap_f_of_temp = OpenStudio::Model::CurveCubic.new(self)
|
2383
2579
|
htg_cap_f_of_temp.setCoefficient1Constant(0.758746)
|
2384
2580
|
htg_cap_f_of_temp.setCoefficient2x(0.027626)
|
@@ -2418,29 +2614,29 @@ class OpenStudio::Model::Model
|
|
2418
2614
|
htg_part_load_fraction.setMaximumValueofx(1.0)
|
2419
2615
|
|
2420
2616
|
htg_coil = OpenStudio::Model::CoilHeatingDXSingleSpeed.new(self,
|
2421
|
-
|
2422
|
-
|
2423
|
-
|
2424
|
-
|
2425
|
-
|
2426
|
-
|
2617
|
+
alwaysOnDiscreteSchedule,
|
2618
|
+
htg_cap_f_of_temp,
|
2619
|
+
htg_cap_f_of_flow,
|
2620
|
+
htg_energy_input_ratio_f_of_temp,
|
2621
|
+
htg_energy_input_ratio_f_of_flow,
|
2622
|
+
htg_part_load_fraction)
|
2427
2623
|
|
2428
2624
|
htg_coil.setName("#{thermal_zone_name} SAC HP Htg Coil")
|
2429
2625
|
end
|
2430
2626
|
|
2431
2627
|
# Supplemental Heating Coil
|
2432
2628
|
supplemental_htg_coil = nil
|
2433
|
-
if supplemental_heating_type ==
|
2434
|
-
supplemental_htg_coil = OpenStudio::Model::CoilHeatingGas.new(self,
|
2629
|
+
if supplemental_heating_type == 'Electric'
|
2630
|
+
supplemental_htg_coil = OpenStudio::Model::CoilHeatingGas.new(self, alwaysOnDiscreteSchedule)
|
2435
2631
|
supplemental_htg_coil.setName("#{thermal_zone_name} PSZ-AC Electric Backup Htg Coil")
|
2436
|
-
elsif supplemental_heating_type ==
|
2437
|
-
supplemental_htg_coil = OpenStudio::Model::CoilHeatingGas.new(self,
|
2632
|
+
elsif supplemental_heating_type == 'Gas'
|
2633
|
+
supplemental_htg_coil = OpenStudio::Model::CoilHeatingGas.new(self, alwaysOnDiscreteSchedule)
|
2438
2634
|
supplemental_htg_coil.setName("#{thermal_zone_name} PSZ-AC Gas Backup Htg Coil")
|
2439
2635
|
end
|
2440
2636
|
|
2441
2637
|
# Cooling Coil
|
2442
2638
|
clg_coil = nil
|
2443
|
-
if cooling_type ==
|
2639
|
+
if cooling_type == 'Two Speed DX AC'
|
2444
2640
|
|
2445
2641
|
clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(self)
|
2446
2642
|
clg_cap_f_of_temp.setCoefficient1Constant(0.42415)
|
@@ -2512,21 +2708,21 @@ class OpenStudio::Model::Model
|
|
2512
2708
|
clg_energy_input_ratio_f_of_temp_low_spd.setMaximumValueofy(46.0)
|
2513
2709
|
|
2514
2710
|
clg_coil = OpenStudio::Model::CoilCoolingDXTwoSpeed.new(self,
|
2515
|
-
|
2516
|
-
|
2517
|
-
|
2518
|
-
|
2519
|
-
|
2520
|
-
|
2521
|
-
|
2522
|
-
|
2711
|
+
alwaysOnDiscreteSchedule,
|
2712
|
+
clg_cap_f_of_temp,
|
2713
|
+
clg_cap_f_of_flow,
|
2714
|
+
clg_energy_input_ratio_f_of_temp,
|
2715
|
+
clg_energy_input_ratio_f_of_flow,
|
2716
|
+
clg_part_load_ratio,
|
2717
|
+
clg_cap_f_of_temp_low_spd,
|
2718
|
+
clg_energy_input_ratio_f_of_temp_low_spd)
|
2523
2719
|
|
2524
2720
|
clg_coil.setName("#{thermal_zone_name} SAC 2spd DX AC Clg Coil")
|
2525
2721
|
clg_coil.setRatedLowSpeedSensibleHeatRatio(OpenStudio::OptionalDouble.new(0.69))
|
2526
2722
|
clg_coil.setBasinHeaterCapacity(10)
|
2527
2723
|
clg_coil.setBasinHeaterSetpointTemperature(2.0)
|
2528
2724
|
|
2529
|
-
elsif cooling_type ==
|
2725
|
+
elsif cooling_type == 'Single Speed DX AC'
|
2530
2726
|
|
2531
2727
|
clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(self)
|
2532
2728
|
clg_cap_f_of_temp.setCoefficient1Constant(0.942587793)
|
@@ -2576,16 +2772,16 @@ class OpenStudio::Model::Model
|
|
2576
2772
|
clg_part_load_ratio.setMaximumCurveOutput(1.0)
|
2577
2773
|
|
2578
2774
|
clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(self,
|
2579
|
-
|
2580
|
-
|
2581
|
-
|
2582
|
-
|
2583
|
-
|
2584
|
-
|
2775
|
+
alwaysOnDiscreteSchedule,
|
2776
|
+
clg_cap_f_of_temp,
|
2777
|
+
clg_cap_f_of_flow,
|
2778
|
+
clg_energy_input_ratio_f_of_temp,
|
2779
|
+
clg_energy_input_ratio_f_of_flow,
|
2780
|
+
clg_part_load_ratio)
|
2585
2781
|
|
2586
2782
|
clg_coil.setName("#{thermal_zone_name} SAC 1spd DX AC Clg Coil")
|
2587
2783
|
|
2588
|
-
elsif cooling_type ==
|
2784
|
+
elsif cooling_type == 'Single Speed Heat Pump'
|
2589
2785
|
|
2590
2786
|
clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(self)
|
2591
2787
|
clg_cap_f_of_temp.setCoefficient1Constant(0.766956)
|
@@ -2633,25 +2829,25 @@ class OpenStudio::Model::Model
|
|
2633
2829
|
clg_part_load_ratio.setMaximumValueofx(1.0)
|
2634
2830
|
|
2635
2831
|
clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(self,
|
2636
|
-
|
2637
|
-
|
2638
|
-
|
2639
|
-
|
2640
|
-
|
2641
|
-
|
2832
|
+
alwaysOnDiscreteSchedule,
|
2833
|
+
clg_cap_f_of_temp,
|
2834
|
+
clg_cap_f_of_flow,
|
2835
|
+
clg_energy_input_ratio_f_of_temp,
|
2836
|
+
clg_energy_input_ratio_f_of_flow,
|
2837
|
+
clg_part_load_ratio)
|
2642
2838
|
|
2643
2839
|
clg_coil.setName("#{thermal_zone_name} SAC 1spd DX HP Clg Coil")
|
2644
|
-
#clg_coil.setRatedSensibleHeatRatio(0.69)
|
2645
|
-
#clg_coil.setBasinHeaterCapacity(10)
|
2646
|
-
#clg_coil.setBasinHeaterSetpointTemperature(2.0)
|
2840
|
+
# clg_coil.setRatedSensibleHeatRatio(0.69)
|
2841
|
+
# clg_coil.setBasinHeaterCapacity(10)
|
2842
|
+
# clg_coil.setBasinHeaterSetpointTemperature(2.0)
|
2647
2843
|
|
2648
2844
|
end
|
2649
2845
|
|
2650
2846
|
oa_controller = OpenStudio::Model::ControllerOutdoorAir.new(self)
|
2651
2847
|
oa_controller.setName("#{thermal_zone_name} SAC OA Sys Controller")
|
2652
2848
|
oa_controller.setMinimumOutdoorAirSchedule(oa_damper_sch)
|
2653
|
-
oa_controller.setMaximumFractionofOutdoorAirSchedule(
|
2654
|
-
oa_system = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(self,oa_controller)
|
2849
|
+
oa_controller.setMaximumFractionofOutdoorAirSchedule(econ_max_oa_frac_sch)
|
2850
|
+
oa_system = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(self, oa_controller)
|
2655
2851
|
oa_system.setName("#{thermal_zone_name} SAC OA Sys")
|
2656
2852
|
|
2657
2853
|
# Add the components to the air loop
|
@@ -2678,8 +2874,8 @@ class OpenStudio::Model::Model
|
|
2678
2874
|
clg_coil.addToNode(supply_inlet_node)
|
2679
2875
|
end
|
2680
2876
|
|
2681
|
-
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(OpenStudio.convert(55.4,
|
2682
|
-
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(OpenStudio.convert(113,
|
2877
|
+
setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(OpenStudio.convert(55.4, 'F', 'C').get)
|
2878
|
+
setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(OpenStudio.convert(113, 'F', 'C').get)
|
2683
2879
|
|
2684
2880
|
setpoint_mgr_single_zone_reheat.addToNode(air_loop.supplyOutletNode)
|
2685
2881
|
|
@@ -2688,18 +2884,17 @@ class OpenStudio::Model::Model
|
|
2688
2884
|
|
2689
2885
|
# Create a diffuser and attach the zone/diffuser pair to the air loop
|
2690
2886
|
thermal_zones.each do |zone|
|
2691
|
-
diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(self,
|
2887
|
+
diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(self, alwaysOnDiscreteSchedule)
|
2692
2888
|
diffuser.setName("#{zone.name} SAC Diffuser")
|
2693
|
-
air_loop.addBranchForZone(zone,diffuser.to_StraightComponent)
|
2889
|
+
air_loop.addBranchForZone(zone, diffuser.to_StraightComponent)
|
2694
2890
|
end
|
2695
2891
|
|
2696
2892
|
return air_loop
|
2697
|
-
|
2698
2893
|
end
|
2699
2894
|
|
2700
2895
|
# Creates a PTAC system for each zone and adds it to the model.
|
2701
2896
|
#
|
2702
|
-
# @param
|
2897
|
+
# @param template [String] Valid choices are 90.1-2004,
|
2703
2898
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
2704
2899
|
# @param sys_name [String] the name of the system, or nil in which case it will be defaulted
|
2705
2900
|
# @param hot_water_loop [String] hot water loop to connect heating coil to.
|
@@ -2713,31 +2908,30 @@ class OpenStudio::Model::Model
|
|
2713
2908
|
# @param building_type [String] the building type
|
2714
2909
|
# @return [Array<OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner>] an
|
2715
2910
|
# array of the resulting PTACs.
|
2716
|
-
def add_ptac(
|
2717
|
-
|
2718
|
-
|
2719
|
-
|
2720
|
-
|
2721
|
-
|
2722
|
-
|
2723
|
-
|
2911
|
+
def add_ptac(template,
|
2912
|
+
sys_name,
|
2913
|
+
hot_water_loop,
|
2914
|
+
thermal_zones,
|
2915
|
+
fan_type,
|
2916
|
+
heating_type,
|
2917
|
+
cooling_type,
|
2918
|
+
building_type = nil)
|
2724
2919
|
|
2725
2920
|
thermal_zones.each do |zone|
|
2726
|
-
OpenStudio
|
2921
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding PTAC for #{zone.name}.")
|
2727
2922
|
end
|
2728
2923
|
|
2729
2924
|
# schedule: always off
|
2730
2925
|
always_off = OpenStudio::Model::ScheduleRuleset.new(self)
|
2731
|
-
always_off.setName(
|
2732
|
-
always_off.defaultDaySchedule.setName(
|
2733
|
-
always_off.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0), 0.0)
|
2926
|
+
always_off.setName('ALWAYS_OFF')
|
2927
|
+
always_off.defaultDaySchedule.setName('ALWAYS_OFF day')
|
2928
|
+
always_off.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0.0)
|
2734
2929
|
always_off.setSummerDesignDaySchedule(always_off.defaultDaySchedule)
|
2735
2930
|
always_off.setWinterDesignDaySchedule(always_off.defaultDaySchedule)
|
2736
2931
|
|
2737
2932
|
# Make a PTAC for each zone
|
2738
2933
|
ptacs = []
|
2739
2934
|
thermal_zones.each do |zone|
|
2740
|
-
|
2741
2935
|
# Zone sizing
|
2742
2936
|
sizing_zone = zone.sizingZone
|
2743
2937
|
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(14)
|
@@ -2747,37 +2941,37 @@ class OpenStudio::Model::Model
|
|
2747
2941
|
|
2748
2942
|
# add fan
|
2749
2943
|
fan = nil
|
2750
|
-
if fan_type ==
|
2751
|
-
fan = OpenStudio::Model::FanConstantVolume.new(self,
|
2944
|
+
if fan_type == 'ConstantVolume'
|
2945
|
+
fan = OpenStudio::Model::FanConstantVolume.new(self, alwaysOnDiscreteSchedule)
|
2752
2946
|
fan.setName("#{zone.name} PTAC Fan")
|
2753
2947
|
fan_static_pressure_in_h2o = 1.33
|
2754
|
-
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o,
|
2948
|
+
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o, 'inH_{2}O', 'Pa').get
|
2755
2949
|
fan.setPressureRise(fan_static_pressure_pa)
|
2756
2950
|
fan.setFanEfficiency(0.52)
|
2757
2951
|
fan.setMotorEfficiency(0.8)
|
2758
|
-
elsif fan_type ==
|
2759
|
-
fan = OpenStudio::Model::FanOnOff.new(self,
|
2952
|
+
elsif fan_type == 'Cycling'
|
2953
|
+
fan = OpenStudio::Model::FanOnOff.new(self, alwaysOnDiscreteSchedule)
|
2760
2954
|
fan.setName("#{zone.name} PTAC Fan")
|
2761
2955
|
fan_static_pressure_in_h2o = 1.33
|
2762
|
-
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o,
|
2956
|
+
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o, 'inH_{2}O', 'Pa').get
|
2763
2957
|
fan.setPressureRise(fan_static_pressure_pa)
|
2764
2958
|
fan.setFanEfficiency(0.52)
|
2765
2959
|
fan.setMotorEfficiency(0.8)
|
2766
2960
|
else
|
2767
|
-
OpenStudio
|
2961
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.model.Model', "ptac_fan_type of #{fan_type} is not recognized.")
|
2768
2962
|
end
|
2769
2963
|
|
2770
2964
|
# add heating coil
|
2771
2965
|
htg_coil = nil
|
2772
|
-
if heating_type ==
|
2773
|
-
htg_coil = OpenStudio::Model::CoilHeatingGas.new(self,
|
2966
|
+
if heating_type == 'Gas'
|
2967
|
+
htg_coil = OpenStudio::Model::CoilHeatingGas.new(self, alwaysOnDiscreteSchedule)
|
2774
2968
|
htg_coil.setName("#{zone.name} PTAC Gas Htg Coil")
|
2775
|
-
elsif heating_type ==
|
2776
|
-
htg_coil = OpenStudio::Model::CoilHeatingElectric.new(self,
|
2969
|
+
elsif heating_type == 'Electric'
|
2970
|
+
htg_coil = OpenStudio::Model::CoilHeatingElectric.new(self, alwaysOnDiscreteSchedule)
|
2777
2971
|
htg_coil.setName("#{zone.name} PTAC Electric Htg Coil")
|
2778
|
-
elsif heating_type ==
|
2972
|
+
elsif heating_type == 'Water'
|
2779
2973
|
if hot_water_loop.nil?
|
2780
|
-
OpenStudio
|
2974
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'No hot water plant loop supplied')
|
2781
2975
|
return false
|
2782
2976
|
end
|
2783
2977
|
|
@@ -2789,8 +2983,7 @@ class OpenStudio::Model::Model
|
|
2789
2983
|
prehtg_sa_temp_c = 16.6
|
2790
2984
|
htg_sa_temp_c = 32.2
|
2791
2985
|
|
2792
|
-
|
2793
|
-
htg_coil = OpenStudio::Model::CoilHeatingWater.new(self,self.alwaysOnDiscreteSchedule)
|
2986
|
+
htg_coil = OpenStudio::Model::CoilHeatingWater.new(self, alwaysOnDiscreteSchedule)
|
2794
2987
|
htg_coil.setName("#{hot_water_loop.name} Water Htg Coil")
|
2795
2988
|
# None of these temperatures are defined
|
2796
2989
|
htg_coil.setRatedInletWaterTemperature(hw_temp_c)
|
@@ -2799,12 +2992,12 @@ class OpenStudio::Model::Model
|
|
2799
2992
|
htg_coil.setRatedOutletAirTemperature(htg_sa_temp_c)
|
2800
2993
|
hot_water_loop.addDemandBranchForComponent(htg_coil)
|
2801
2994
|
else
|
2802
|
-
OpenStudio
|
2995
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.model.Model', "ptac_heating_type of #{heating_type} is not recognized.")
|
2803
2996
|
end
|
2804
2997
|
|
2805
2998
|
# add cooling coil
|
2806
2999
|
clg_coil = nil
|
2807
|
-
if cooling_type ==
|
3000
|
+
if cooling_type == 'Two Speed DX AC'
|
2808
3001
|
|
2809
3002
|
clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(self)
|
2810
3003
|
clg_cap_f_of_temp.setCoefficient1Constant(0.42415)
|
@@ -2876,21 +3069,21 @@ class OpenStudio::Model::Model
|
|
2876
3069
|
clg_energy_input_ratio_f_of_temp_low_spd.setMaximumValueofy(46.0)
|
2877
3070
|
|
2878
3071
|
clg_coil = OpenStudio::Model::CoilCoolingDXTwoSpeed.new(self,
|
2879
|
-
|
2880
|
-
|
2881
|
-
|
2882
|
-
|
2883
|
-
|
2884
|
-
|
2885
|
-
|
2886
|
-
|
3072
|
+
alwaysOnDiscreteSchedule,
|
3073
|
+
clg_cap_f_of_temp,
|
3074
|
+
clg_cap_f_of_flow,
|
3075
|
+
clg_energy_input_ratio_f_of_temp,
|
3076
|
+
clg_energy_input_ratio_f_of_flow,
|
3077
|
+
clg_part_load_ratio,
|
3078
|
+
clg_cap_f_of_temp_low_spd,
|
3079
|
+
clg_energy_input_ratio_f_of_temp_low_spd)
|
2887
3080
|
|
2888
3081
|
clg_coil.setName("#{zone.name} PTAC 2spd DX AC Clg Coil")
|
2889
3082
|
clg_coil.setRatedLowSpeedSensibleHeatRatio(OpenStudio::OptionalDouble.new(0.69))
|
2890
3083
|
clg_coil.setBasinHeaterCapacity(10)
|
2891
3084
|
clg_coil.setBasinHeaterSetpointTemperature(2.0)
|
2892
3085
|
|
2893
|
-
elsif cooling_type ==
|
3086
|
+
elsif cooling_type == 'Single Speed DX AC' # for small hotel
|
2894
3087
|
|
2895
3088
|
clg_cap_f_of_temp = OpenStudio::Model::CurveBiquadratic.new(self)
|
2896
3089
|
clg_cap_f_of_temp.setCoefficient1Constant(0.942587793)
|
@@ -2940,47 +3133,44 @@ class OpenStudio::Model::Model
|
|
2940
3133
|
clg_part_load_ratio.setMaximumCurveOutput(1.0)
|
2941
3134
|
|
2942
3135
|
clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(self,
|
2943
|
-
|
2944
|
-
|
2945
|
-
|
2946
|
-
|
2947
|
-
|
2948
|
-
|
3136
|
+
alwaysOnDiscreteSchedule,
|
3137
|
+
clg_cap_f_of_temp,
|
3138
|
+
clg_cap_f_of_flow,
|
3139
|
+
clg_energy_input_ratio_f_of_temp,
|
3140
|
+
clg_energy_input_ratio_f_of_flow,
|
3141
|
+
clg_part_load_ratio)
|
2949
3142
|
|
2950
3143
|
clg_coil.setName("#{zone.name} PTAC 1spd DX AC Clg Coil")
|
2951
3144
|
|
2952
3145
|
else
|
2953
|
-
OpenStudio
|
3146
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.model.Model', "ptac_cooling_type of #{heating_type} is not recognized.")
|
2954
3147
|
end
|
2955
3148
|
|
2956
3149
|
# Wrap coils in a PTAC system
|
2957
3150
|
ptac_system = OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner.new(self,
|
2958
|
-
|
3151
|
+
alwaysOnDiscreteSchedule,
|
2959
3152
|
fan,
|
2960
3153
|
htg_coil,
|
2961
3154
|
clg_coil)
|
2962
3155
|
|
2963
|
-
|
2964
3156
|
ptac_system.setName("#{zone.name} PTAC")
|
2965
|
-
ptac_system.setFanPlacement(
|
2966
|
-
if fan_type ==
|
2967
|
-
ptac_system.setSupplyAirFanOperatingModeSchedule(
|
2968
|
-
elsif fan_type ==
|
3157
|
+
ptac_system.setFanPlacement('DrawThrough')
|
3158
|
+
if fan_type == 'ConstantVolume'
|
3159
|
+
ptac_system.setSupplyAirFanOperatingModeSchedule(alwaysOnDiscreteSchedule)
|
3160
|
+
elsif fan_type == 'Cycling'
|
2969
3161
|
ptac_system.setSupplyAirFanOperatingModeSchedule(always_off)
|
2970
3162
|
end
|
2971
3163
|
ptac_system.addToThermalZone(zone)
|
2972
3164
|
|
2973
3165
|
ptacs << ptac_system
|
2974
|
-
|
2975
3166
|
end
|
2976
3167
|
|
2977
3168
|
return ptacs
|
2978
|
-
|
2979
3169
|
end
|
2980
3170
|
|
2981
3171
|
# Creates a PTHP system for each zone and adds it to the model.
|
2982
3172
|
#
|
2983
|
-
# @param
|
3173
|
+
# @param template [String] Valid choices are 90.1-2004,
|
2984
3174
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
2985
3175
|
# @param sys_name [String] the name of the system, or nil in which case it will be defaulted
|
2986
3176
|
# @param thermal_zones [String] zones to connect to this system
|
@@ -2988,28 +3178,27 @@ class OpenStudio::Model::Model
|
|
2988
3178
|
# @param building_type [String] the building type
|
2989
3179
|
# @return [Array<OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner>] an
|
2990
3180
|
# array of the resulting PTACs.
|
2991
|
-
def add_pthp(
|
2992
|
-
|
2993
|
-
|
2994
|
-
|
2995
|
-
|
3181
|
+
def add_pthp(template,
|
3182
|
+
sys_name,
|
3183
|
+
thermal_zones,
|
3184
|
+
fan_type,
|
3185
|
+
building_type = nil)
|
2996
3186
|
|
2997
3187
|
thermal_zones.each do |zone|
|
2998
|
-
OpenStudio
|
3188
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding PTHP for #{zone.name}.")
|
2999
3189
|
end
|
3000
3190
|
|
3001
3191
|
# schedule: always off
|
3002
3192
|
always_off = OpenStudio::Model::ScheduleRuleset.new(self)
|
3003
|
-
always_off.setName(
|
3004
|
-
always_off.defaultDaySchedule.setName(
|
3005
|
-
always_off.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0), 0.0)
|
3193
|
+
always_off.setName('ALWAYS_OFF')
|
3194
|
+
always_off.defaultDaySchedule.setName('ALWAYS_OFF day')
|
3195
|
+
always_off.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0.0)
|
3006
3196
|
always_off.setSummerDesignDaySchedule(always_off.defaultDaySchedule)
|
3007
3197
|
always_off.setWinterDesignDaySchedule(always_off.defaultDaySchedule)
|
3008
3198
|
|
3009
3199
|
# Make a PTHP for each zone
|
3010
3200
|
pthps = []
|
3011
3201
|
thermal_zones.each do |zone|
|
3012
|
-
|
3013
3202
|
# Zone sizing
|
3014
3203
|
sizing_zone = zone.sizingZone
|
3015
3204
|
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(14)
|
@@ -3019,24 +3208,24 @@ class OpenStudio::Model::Model
|
|
3019
3208
|
|
3020
3209
|
# add fan
|
3021
3210
|
fan = nil
|
3022
|
-
if fan_type ==
|
3023
|
-
fan = OpenStudio::Model::FanConstantVolume.new(self,
|
3211
|
+
if fan_type == 'ConstantVolume'
|
3212
|
+
fan = OpenStudio::Model::FanConstantVolume.new(self, alwaysOnDiscreteSchedule)
|
3024
3213
|
fan.setName("#{zone.name} PTAC Fan")
|
3025
3214
|
fan_static_pressure_in_h2o = 1.33
|
3026
|
-
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o,
|
3215
|
+
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o, 'inH_{2}O', 'Pa').get
|
3027
3216
|
fan.setPressureRise(fan_static_pressure_pa)
|
3028
3217
|
fan.setFanEfficiency(0.52)
|
3029
3218
|
fan.setMotorEfficiency(0.8)
|
3030
|
-
elsif fan_type ==
|
3031
|
-
fan = OpenStudio::Model::FanOnOff.new(self,
|
3219
|
+
elsif fan_type == 'Cycling'
|
3220
|
+
fan = OpenStudio::Model::FanOnOff.new(self, alwaysOnDiscreteSchedule)
|
3032
3221
|
fan.setName("#{zone.name} PTAC Fan")
|
3033
3222
|
fan_static_pressure_in_h2o = 1.33
|
3034
|
-
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o,
|
3223
|
+
fan_static_pressure_pa = OpenStudio.convert(fan_static_pressure_in_h2o, 'inH_{2}O', 'Pa').get
|
3035
3224
|
fan.setPressureRise(fan_static_pressure_pa)
|
3036
3225
|
fan.setFanEfficiency(0.52)
|
3037
3226
|
fan.setMotorEfficiency(0.8)
|
3038
3227
|
else
|
3039
|
-
OpenStudio
|
3228
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.model.Model', "ptac_fan_type of #{fan_type} is not recognized.")
|
3040
3229
|
end
|
3041
3230
|
|
3042
3231
|
# add heating coil
|
@@ -3079,12 +3268,12 @@ class OpenStudio::Model::Model
|
|
3079
3268
|
htg_part_load_fraction.setMaximumValueofx(1.0)
|
3080
3269
|
|
3081
3270
|
htg_coil = OpenStudio::Model::CoilHeatingDXSingleSpeed.new(self,
|
3082
|
-
|
3083
|
-
|
3084
|
-
|
3085
|
-
|
3086
|
-
|
3087
|
-
|
3271
|
+
alwaysOnDiscreteSchedule,
|
3272
|
+
htg_cap_f_of_temp,
|
3273
|
+
htg_cap_f_of_flow,
|
3274
|
+
htg_energy_input_ratio_f_of_temp,
|
3275
|
+
htg_energy_input_ratio_f_of_flow,
|
3276
|
+
htg_part_load_fraction)
|
3088
3277
|
|
3089
3278
|
htg_coil.setName("#{zone.name} PTHP Htg Coil")
|
3090
3279
|
|
@@ -3135,49 +3324,47 @@ class OpenStudio::Model::Model
|
|
3135
3324
|
clg_part_load_ratio.setMaximumValueofx(1.0)
|
3136
3325
|
|
3137
3326
|
clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(self,
|
3138
|
-
|
3139
|
-
|
3140
|
-
|
3141
|
-
|
3142
|
-
|
3143
|
-
|
3144
|
-
|
3145
|
-
clg_coil.setName("#{zone.name}
|
3146
|
-
#clg_coil.setRatedSensibleHeatRatio(0.69)
|
3147
|
-
#clg_coil.setBasinHeaterCapacity(10)
|
3148
|
-
#clg_coil.setBasinHeaterSetpointTemperature(2.0)
|
3327
|
+
alwaysOnDiscreteSchedule,
|
3328
|
+
clg_cap_f_of_temp,
|
3329
|
+
clg_cap_f_of_flow,
|
3330
|
+
clg_energy_input_ratio_f_of_temp,
|
3331
|
+
clg_energy_input_ratio_f_of_flow,
|
3332
|
+
clg_part_load_ratio)
|
3333
|
+
|
3334
|
+
clg_coil.setName("#{zone.name} PTHP Clg Coil")
|
3335
|
+
# clg_coil.setRatedSensibleHeatRatio(0.69)
|
3336
|
+
# clg_coil.setBasinHeaterCapacity(10)
|
3337
|
+
# clg_coil.setBasinHeaterSetpointTemperature(2.0)
|
3149
3338
|
|
3150
3339
|
# Supplemental heating coil
|
3151
|
-
supplemental_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(self,
|
3340
|
+
supplemental_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(self, alwaysOnDiscreteSchedule)
|
3152
3341
|
|
3153
3342
|
# Wrap coils in a PTHP system
|
3154
3343
|
pthp_system = OpenStudio::Model::ZoneHVACPackagedTerminalHeatPump.new(self,
|
3155
|
-
|
3344
|
+
alwaysOnDiscreteSchedule,
|
3156
3345
|
fan,
|
3157
3346
|
htg_coil,
|
3158
3347
|
clg_coil,
|
3159
3348
|
supplemental_htg_coil)
|
3160
3349
|
|
3161
3350
|
pthp_system.setName("#{zone.name} PTHP")
|
3162
|
-
pthp_system.setFanPlacement(
|
3163
|
-
if fan_type ==
|
3164
|
-
pthp_system.setSupplyAirFanOperatingModeSchedule(
|
3165
|
-
elsif fan_type ==
|
3351
|
+
pthp_system.setFanPlacement('DrawThrough')
|
3352
|
+
if fan_type == 'ConstantVolume'
|
3353
|
+
pthp_system.setSupplyAirFanOperatingModeSchedule(alwaysOnDiscreteSchedule)
|
3354
|
+
elsif fan_type == 'Cycling'
|
3166
3355
|
pthp_system.setSupplyAirFanOperatingModeSchedule(always_off)
|
3167
3356
|
end
|
3168
3357
|
pthp_system.addToThermalZone(zone)
|
3169
3358
|
|
3170
3359
|
pthps << pthp_system
|
3171
|
-
|
3172
3360
|
end
|
3173
3361
|
|
3174
3362
|
return pthps
|
3175
|
-
|
3176
3363
|
end
|
3177
3364
|
|
3178
3365
|
# Creates a unit heater for each zone and adds it to the model.
|
3179
3366
|
#
|
3180
|
-
# @param
|
3367
|
+
# @param template [String] Valid choices are 90.1-2004,
|
3181
3368
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
3182
3369
|
# @param sys_name [String] the name of the system, or nil in which case it will be defaulted
|
3183
3370
|
# @param thermal_zones [String] zones to connect to this system
|
@@ -3186,37 +3373,49 @@ class OpenStudio::Model::Model
|
|
3186
3373
|
# @param fan_control_type [Double] valid choices are Continuous, OnOff, Cycling
|
3187
3374
|
# @param fan_pressure_rise [Double] fan pressure rise, in Pa
|
3188
3375
|
# @param heating_type [Double] valid choices are
|
3189
|
-
#
|
3376
|
+
# NaturalGas, Electricity, DistrictHeating
|
3190
3377
|
# @param building_type [String] the building type
|
3191
3378
|
# @return [Array<OpenStudio::Model::ZoneHVACUnitHeater>] an
|
3192
3379
|
# array of the resulting unit heaters.
|
3193
|
-
|
3194
|
-
|
3195
|
-
|
3196
|
-
|
3197
|
-
|
3198
|
-
|
3199
|
-
|
3200
|
-
|
3201
|
-
|
3380
|
+
def add_unitheater(template,
|
3381
|
+
sys_name,
|
3382
|
+
thermal_zones,
|
3383
|
+
hvac_op_sch,
|
3384
|
+
fan_control_type,
|
3385
|
+
fan_pressure_rise,
|
3386
|
+
heating_type,
|
3387
|
+
hot_water_loop = nil,
|
3388
|
+
building_type = nil)
|
3389
|
+
|
3390
|
+
# Control temps for HW loop
|
3391
|
+
# will only be used when hot_water_loop is provided.
|
3392
|
+
hw_temp_f = 180 # HW setpoint 180F
|
3393
|
+
hw_delta_t_r = 20 # 20F delta-T
|
3394
|
+
htg_sa_temp_f = 100 # 100F air from unit heaters
|
3395
|
+
zn_temp_f = 60 # 60F entering unit heater from zone
|
3396
|
+
|
3397
|
+
hw_temp_c = OpenStudio.convert(hw_temp_f, 'F', 'C').get
|
3398
|
+
hw_delta_t_k = OpenStudio.convert(hw_delta_t_r, 'R', 'K').get
|
3399
|
+
htg_sa_temp_c = OpenStudio.convert(htg_sa_temp_f, 'F', 'C').get
|
3400
|
+
zn_temp_c = OpenStudio.convert(zn_temp_f, 'F', 'C').get
|
3202
3401
|
|
3203
3402
|
thermal_zones.each do |zone|
|
3204
|
-
OpenStudio
|
3403
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding split unit heater for #{zone.name}.")
|
3205
3404
|
end
|
3206
3405
|
|
3207
3406
|
# hvac operation schedule
|
3208
|
-
if hvac_op_sch.nil?
|
3209
|
-
|
3210
|
-
|
3211
|
-
|
3212
|
-
|
3407
|
+
hvac_op_sch = if hvac_op_sch.nil?
|
3408
|
+
alwaysOnDiscreteSchedule
|
3409
|
+
else
|
3410
|
+
add_schedule(hvac_op_sch)
|
3411
|
+
end
|
3213
3412
|
|
3214
3413
|
# Make a unit heater for each zone
|
3215
3414
|
unit_heaters = []
|
3216
3415
|
thermal_zones.each do |zone|
|
3217
3416
|
# Zone sizing
|
3218
3417
|
sizing_zone = zone.sizingZone
|
3219
|
-
if building_type == 'RetailStandalone' &&
|
3418
|
+
if building_type == 'RetailStandalone' && template != 'DOE Ref 1980-2004' && template != 'DOE Ref Pre-1980'
|
3220
3419
|
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(12.8)
|
3221
3420
|
else
|
3222
3421
|
sizing_zone.setZoneCoolingDesignSupplyAirTemperature(14)
|
@@ -3227,7 +3426,7 @@ class OpenStudio::Model::Model
|
|
3227
3426
|
sizing_zone.setZoneHeatingDesignSupplyAirHumidityRatio(0.008)
|
3228
3427
|
|
3229
3428
|
# add fan
|
3230
|
-
fan = OpenStudio::Model::FanConstantVolume.new(self,hvac_op_sch)
|
3429
|
+
fan = OpenStudio::Model::FanConstantVolume.new(self, hvac_op_sch)
|
3231
3430
|
fan.setName("#{zone.name} UnitHeater Fan")
|
3232
3431
|
fan.setPressureRise(fan_pressure_rise)
|
3233
3432
|
fan.setFanEfficiency(0.53625)
|
@@ -3235,14 +3434,22 @@ class OpenStudio::Model::Model
|
|
3235
3434
|
|
3236
3435
|
# add heating coil
|
3237
3436
|
htg_coil = nil
|
3238
|
-
if heating_type ==
|
3437
|
+
if heating_type == 'NaturalGas' || heating_type == 'Gas'
|
3239
3438
|
htg_coil = OpenStudio::Model::CoilHeatingGas.new(self, hvac_op_sch)
|
3240
3439
|
htg_coil.setName("#{zone.name} UnitHeater Gas Htg Coil")
|
3241
|
-
elsif heating_type ==
|
3440
|
+
elsif heating_type == 'Electricity' || heating_type == 'Electric'
|
3242
3441
|
htg_coil = OpenStudio::Model::CoilHeatingElectric.new(self, hvac_op_sch)
|
3243
3442
|
htg_coil.setName("#{zone.name} UnitHeater Electric Htg Coil")
|
3443
|
+
elsif heating_type == 'DistrictHeating' && !hot_water_loop.nil?
|
3444
|
+
htg_coil = OpenStudio::Model::CoilHeatingWater.new(self, alwaysOnDiscreteSchedule)
|
3445
|
+
htg_coil.setName("#{zone.name} UnitHeater Water Htg Coil")
|
3446
|
+
htg_coil.setRatedInletWaterTemperature(hw_temp_c)
|
3447
|
+
htg_coil.setRatedInletAirTemperature(zn_temp_c)
|
3448
|
+
htg_coil.setRatedOutletWaterTemperature(hw_temp_c - hw_delta_t_k)
|
3449
|
+
htg_coil.setRatedOutletAirTemperature(htg_sa_temp_c)
|
3450
|
+
hot_water_loop.addDemandBranchForComponent(htg_coil)
|
3244
3451
|
else
|
3245
|
-
OpenStudio
|
3452
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.Model.Model', 'No heating type was found when adding unit heater; no unit heater will be created.')
|
3246
3453
|
return false
|
3247
3454
|
end
|
3248
3455
|
|
@@ -3257,12 +3464,11 @@ class OpenStudio::Model::Model
|
|
3257
3464
|
end
|
3258
3465
|
|
3259
3466
|
return unit_heaters
|
3260
|
-
|
3261
3467
|
end
|
3262
3468
|
|
3263
3469
|
# Creates a high temp radiant heater for each zone and adds it to the model.
|
3264
3470
|
#
|
3265
|
-
# @param
|
3471
|
+
# @param template [String] Valid choices are 90.1-2004,
|
3266
3472
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
3267
3473
|
# @param sys_name [String] the name of the system, or nil in which case it will be defaulted
|
3268
3474
|
# @param thermal_zones [String] zones to connect to this system
|
@@ -3272,17 +3478,16 @@ class OpenStudio::Model::Model
|
|
3272
3478
|
# @param building_type [String] the building type
|
3273
3479
|
# @return [Array<OpenStudio::Model::ZoneHVACHighTemperatureRadiant>] an
|
3274
3480
|
# array of the resulting radiant heaters.
|
3275
|
-
def add_high_temp_radiant(
|
3481
|
+
def add_high_temp_radiant(template,
|
3276
3482
|
sys_name,
|
3277
3483
|
thermal_zones,
|
3278
3484
|
heating_type,
|
3279
3485
|
combustion_efficiency,
|
3280
|
-
building_type=nil)
|
3486
|
+
building_type = nil)
|
3281
3487
|
|
3282
3488
|
# Make a high temp radiant heater for each zone
|
3283
3489
|
rad_heaters = []
|
3284
3490
|
thermal_zones.each do |zone|
|
3285
|
-
|
3286
3491
|
high_temp_radiant = OpenStudio::Model::ZoneHVACHighTemperatureRadiant.new(self)
|
3287
3492
|
high_temp_radiant.setName("#{zone.name} High Temp Radiant")
|
3288
3493
|
high_temp_radiant.setFuelType(heating_type)
|
@@ -3292,16 +3497,14 @@ class OpenStudio::Model::Model
|
|
3292
3497
|
high_temp_radiant.setHeatingThrottlingRange(2)
|
3293
3498
|
high_temp_radiant.addToThermalZone(zone)
|
3294
3499
|
rad_heaters << high_temp_radiant
|
3295
|
-
|
3296
3500
|
end
|
3297
3501
|
|
3298
3502
|
return rad_heaters
|
3299
|
-
|
3300
3503
|
end
|
3301
3504
|
|
3302
3505
|
# Creates a service water heating loop.
|
3303
3506
|
#
|
3304
|
-
# @param
|
3507
|
+
# @param template [String] Valid choices are 90.1-2004,
|
3305
3508
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
3306
3509
|
# @param sys_name [String] the name of the system, or nil in which case it will be defaulted
|
3307
3510
|
# @param water_heater_thermal_zone [OpenStudio::Model::ThermalZone]
|
@@ -3319,19 +3522,19 @@ class OpenStudio::Model::Model
|
|
3319
3522
|
# @param building_type [String] the building type
|
3320
3523
|
# @return [OpenStudio::Model::PlantLoop]
|
3321
3524
|
# the resulting service water loop.
|
3322
|
-
def add_swh_loop(
|
3323
|
-
|
3324
|
-
|
3325
|
-
|
3326
|
-
|
3327
|
-
|
3328
|
-
|
3329
|
-
|
3330
|
-
|
3331
|
-
|
3332
|
-
|
3333
|
-
|
3334
|
-
OpenStudio
|
3525
|
+
def add_swh_loop(template,
|
3526
|
+
sys_name,
|
3527
|
+
water_heater_thermal_zone,
|
3528
|
+
service_water_temperature,
|
3529
|
+
service_water_pump_head,
|
3530
|
+
service_water_pump_motor_efficiency,
|
3531
|
+
water_heater_capacity,
|
3532
|
+
water_heater_volume,
|
3533
|
+
water_heater_fuel,
|
3534
|
+
parasitic_fuel_consumption_rate,
|
3535
|
+
building_type = nil)
|
3536
|
+
|
3537
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', 'Adding service water loop.')
|
3335
3538
|
|
3336
3539
|
# Service water heating loop
|
3337
3540
|
service_water_loop = OpenStudio::Model::PlantLoop.new(self)
|
@@ -3339,7 +3542,7 @@ class OpenStudio::Model::Model
|
|
3339
3542
|
service_water_loop.setMaximumLoopTemperature(60)
|
3340
3543
|
|
3341
3544
|
if sys_name.nil?
|
3342
|
-
service_water_loop.setName(
|
3545
|
+
service_water_loop.setName('Service Water Loop')
|
3343
3546
|
else
|
3344
3547
|
service_water_loop.setName(sys_name)
|
3345
3548
|
end
|
@@ -3354,16 +3557,16 @@ class OpenStudio::Model::Model
|
|
3354
3557
|
|
3355
3558
|
# Service water heating loop controls
|
3356
3559
|
swh_temp_c = service_water_temperature
|
3357
|
-
swh_temp_f = OpenStudio.convert(swh_temp_c,'C','F').get
|
3358
|
-
swh_delta_t_r = 9 #9F delta-T
|
3359
|
-
swh_delta_t_k = OpenStudio.convert(swh_delta_t_r,'R','K').get
|
3560
|
+
swh_temp_f = OpenStudio.convert(swh_temp_c, 'C', 'F').get
|
3561
|
+
swh_delta_t_r = 9 # 9F delta-T
|
3562
|
+
swh_delta_t_k = OpenStudio.convert(swh_delta_t_r, 'R', 'K').get
|
3360
3563
|
swh_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
3361
3564
|
swh_temp_sch.setName("Service Water Loop Temp - #{swh_temp_f.round}F")
|
3362
|
-
swh_temp_sch.defaultDaySchedule
|
3363
|
-
swh_temp_sch.defaultDaySchedule
|
3565
|
+
swh_temp_sch.defaultDaySchedule.setName("Service Water Loop Temp - #{swh_temp_f.round}F Default")
|
3566
|
+
swh_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), swh_temp_c)
|
3364
3567
|
swh_temp_sch.setScheduleTypeLimits(temp_sch_type_limits)
|
3365
|
-
swh_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self,swh_temp_sch)
|
3366
|
-
swh_stpt_manager.setName(
|
3568
|
+
swh_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self, swh_temp_sch)
|
3569
|
+
swh_stpt_manager.setName('Service hot water setpoint manager')
|
3367
3570
|
swh_stpt_manager.addToNode(service_water_loop.supplyOutletNode)
|
3368
3571
|
sizing_plant = service_water_loop.sizingPlant
|
3369
3572
|
sizing_plant.setLoopType('Heating')
|
@@ -3379,22 +3582,22 @@ class OpenStudio::Model::Model
|
|
3379
3582
|
swh_pump_motor_efficiency = 1
|
3380
3583
|
end
|
3381
3584
|
|
3382
|
-
if
|
3383
|
-
|
3384
|
-
|
3385
|
-
|
3386
|
-
|
3387
|
-
|
3388
|
-
|
3389
|
-
|
3390
|
-
|
3585
|
+
swh_pump = if template == 'DOE Ref 1980-2004' || template == 'DOE Ref Pre-1980'
|
3586
|
+
if building_type == 'Medium Office'
|
3587
|
+
OpenStudio::Model::PumpConstantSpeed.new(self)
|
3588
|
+
else
|
3589
|
+
OpenStudio::Model::PumpVariableSpeed.new(self)
|
3590
|
+
end
|
3591
|
+
else
|
3592
|
+
OpenStudio::Model::PumpConstantSpeed.new(self)
|
3593
|
+
end
|
3391
3594
|
swh_pump.setName('Service Water Loop Pump')
|
3392
3595
|
swh_pump.setRatedPumpHead(swh_pump_head_press_pa.to_f)
|
3393
3596
|
swh_pump.setMotorEfficiency(swh_pump_motor_efficiency)
|
3394
3597
|
swh_pump.setPumpControlType('Intermittent')
|
3395
3598
|
swh_pump.addToNode(service_water_loop.supplyInletNode)
|
3396
3599
|
|
3397
|
-
water_heater = add_water_heater(
|
3600
|
+
water_heater = add_water_heater(template,
|
3398
3601
|
water_heater_capacity,
|
3399
3602
|
water_heater_volume,
|
3400
3603
|
water_heater_fuel,
|
@@ -3427,7 +3630,7 @@ class OpenStudio::Model::Model
|
|
3427
3630
|
# Creates a water heater and attaches it to the supplied
|
3428
3631
|
# service water heating loop.
|
3429
3632
|
#
|
3430
|
-
# @param
|
3633
|
+
# @param template [String] Valid choices are 90.1-2004,
|
3431
3634
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
3432
3635
|
# @param water_heater_capacity [Double] water heater capacity, in W
|
3433
3636
|
# @param water_heater_volume [Double] water heater volume, in m^3
|
@@ -3447,27 +3650,27 @@ class OpenStudio::Model::Model
|
|
3447
3650
|
# @param building_type [String] the building type
|
3448
3651
|
# @return [OpenStudio::Model::WaterHeaterMixed]
|
3449
3652
|
# the resulting water heater.
|
3450
|
-
def add_water_heater(
|
3451
|
-
|
3452
|
-
|
3453
|
-
|
3454
|
-
|
3455
|
-
|
3456
|
-
|
3457
|
-
|
3458
|
-
|
3459
|
-
|
3460
|
-
|
3461
|
-
|
3462
|
-
|
3463
|
-
OpenStudio
|
3653
|
+
def add_water_heater(template,
|
3654
|
+
water_heater_capacity,
|
3655
|
+
water_heater_volume,
|
3656
|
+
water_heater_fuel,
|
3657
|
+
service_water_temperature,
|
3658
|
+
parasitic_fuel_consumption_rate,
|
3659
|
+
swh_temp_sch,
|
3660
|
+
set_peak_use_flowrate,
|
3661
|
+
peak_flowrate,
|
3662
|
+
flowrate_schedule,
|
3663
|
+
water_heater_thermal_zone,
|
3664
|
+
building_type = nil)
|
3665
|
+
|
3666
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', 'Adding water heater.')
|
3464
3667
|
|
3465
3668
|
# Water heater
|
3466
3669
|
# TODO Standards - Change water heater methodology to follow
|
3467
3670
|
# 'Model Enhancements Appendix A.'
|
3468
|
-
water_heater_capacity_btu_per_hr = OpenStudio.convert(water_heater_capacity,
|
3469
|
-
water_heater_capacity_kbtu_per_hr = OpenStudio.convert(water_heater_capacity_btu_per_hr,
|
3470
|
-
water_heater_vol_gal = OpenStudio.convert(water_heater_volume,
|
3671
|
+
water_heater_capacity_btu_per_hr = OpenStudio.convert(water_heater_capacity, 'W', 'Btu/hr').get
|
3672
|
+
water_heater_capacity_kbtu_per_hr = OpenStudio.convert(water_heater_capacity_btu_per_hr, 'Btu/hr', 'kBtu/hr').get
|
3673
|
+
water_heater_vol_gal = OpenStudio.convert(water_heater_volume, 'm^3', 'gal').get
|
3471
3674
|
|
3472
3675
|
# Temperature schedule type limits
|
3473
3676
|
temp_sch_type_limits = OpenStudio::Model::ScheduleTypeLimits.new(self)
|
@@ -3480,21 +3683,21 @@ class OpenStudio::Model::Model
|
|
3480
3683
|
if swh_temp_sch.nil?
|
3481
3684
|
# Service water heating loop controls
|
3482
3685
|
swh_temp_c = service_water_temperature
|
3483
|
-
swh_temp_f = OpenStudio.convert(swh_temp_c,'C','F').get
|
3484
|
-
swh_delta_t_r = 9 #9F delta-T
|
3485
|
-
swh_temp_c = OpenStudio.convert(swh_temp_f,'F','C').get
|
3486
|
-
swh_delta_t_k = OpenStudio.convert(swh_delta_t_r,'R','K').get
|
3686
|
+
swh_temp_f = OpenStudio.convert(swh_temp_c, 'C', 'F').get
|
3687
|
+
swh_delta_t_r = 9 # 9F delta-T
|
3688
|
+
swh_temp_c = OpenStudio.convert(swh_temp_f, 'F', 'C').get
|
3689
|
+
swh_delta_t_k = OpenStudio.convert(swh_delta_t_r, 'R', 'K').get
|
3487
3690
|
swh_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
3488
3691
|
swh_temp_sch.setName("Service Water Loop Temp - #{swh_temp_f.round}F")
|
3489
3692
|
swh_temp_sch.defaultDaySchedule.setName("Service Water Loop Temp - #{swh_temp_f.round}F Default")
|
3490
|
-
swh_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),swh_temp_c)
|
3693
|
+
swh_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), swh_temp_c)
|
3491
3694
|
swh_temp_sch.setScheduleTypeLimits(temp_sch_type_limits)
|
3492
3695
|
end
|
3493
3696
|
|
3494
3697
|
# Water heater depends on the fuel type
|
3495
3698
|
water_heater = OpenStudio::Model::WaterHeaterMixed.new(self)
|
3496
3699
|
water_heater.setName("#{water_heater_vol_gal}gal #{water_heater_fuel} Water Heater - #{water_heater_capacity_kbtu_per_hr.round}kBtu/hr")
|
3497
|
-
water_heater.setTankVolume(OpenStudio.convert(water_heater_vol_gal,'gal','m^3').get)
|
3700
|
+
water_heater.setTankVolume(OpenStudio.convert(water_heater_vol_gal, 'gal', 'm^3').get)
|
3498
3701
|
water_heater.setSetpointTemperatureSchedule(swh_temp_sch)
|
3499
3702
|
|
3500
3703
|
if water_heater_thermal_zone.nil?
|
@@ -3502,7 +3705,7 @@ class OpenStudio::Model::Model
|
|
3502
3705
|
default_water_heater_ambient_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
3503
3706
|
default_water_heater_ambient_temp_sch.setName('Water Heater Ambient Temp Schedule - 70F')
|
3504
3707
|
default_water_heater_ambient_temp_sch.defaultDaySchedule.setName('Water Heater Ambient Temp Schedule - 70F Default')
|
3505
|
-
default_water_heater_ambient_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),OpenStudio
|
3708
|
+
default_water_heater_ambient_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), OpenStudio.convert(70, 'F', 'C').get)
|
3506
3709
|
default_water_heater_ambient_temp_sch.setScheduleTypeLimits(temp_sch_type_limits)
|
3507
3710
|
water_heater.setAmbientTemperatureIndicator('Schedule')
|
3508
3711
|
water_heater.setAmbientTemperatureSchedule(default_water_heater_ambient_temp_sch)
|
@@ -3511,10 +3714,10 @@ class OpenStudio::Model::Model
|
|
3511
3714
|
water_heater.setAmbientTemperatureThermalZone water_heater_thermal_zone
|
3512
3715
|
end
|
3513
3716
|
|
3514
|
-
water_heater.setMaximumTemperatureLimit(OpenStudio
|
3515
|
-
water_heater.setDeadbandTemperatureDifference(OpenStudio.convert(3.6,'R','K').get)
|
3717
|
+
water_heater.setMaximumTemperatureLimit(OpenStudio.convert(180, 'F', 'C').get)
|
3718
|
+
water_heater.setDeadbandTemperatureDifference(OpenStudio.convert(3.6, 'R', 'K').get)
|
3516
3719
|
water_heater.setHeaterControlType('Cycle')
|
3517
|
-
water_heater.setHeaterMaximumCapacity(OpenStudio.convert(water_heater_capacity_btu_per_hr,'Btu/hr','W').get)
|
3720
|
+
water_heater.setHeaterMaximumCapacity(OpenStudio.convert(water_heater_capacity_btu_per_hr, 'Btu/hr', 'W').get)
|
3518
3721
|
water_heater.setOffCycleParasiticHeatFractiontoTank(0.8)
|
3519
3722
|
water_heater.setIndirectWaterHeatingRecoveryTime(1.5) # 1.5hrs
|
3520
3723
|
if water_heater_fuel == 'Electricity'
|
@@ -3539,21 +3742,20 @@ class OpenStudio::Model::Model
|
|
3539
3742
|
|
3540
3743
|
if set_peak_use_flowrate
|
3541
3744
|
rated_flow_rate_m3_per_s = peak_flowrate
|
3542
|
-
rated_flow_rate_gal_per_min = OpenStudio.convert(rated_flow_rate_m3_per_s,'m^3/s','gal/min').get
|
3745
|
+
rated_flow_rate_gal_per_min = OpenStudio.convert(rated_flow_rate_m3_per_s, 'm^3/s', 'gal/min').get
|
3543
3746
|
water_heater.setPeakUseFlowRate(rated_flow_rate_m3_per_s)
|
3544
3747
|
|
3545
|
-
schedule =
|
3748
|
+
schedule = add_schedule(flowrate_schedule)
|
3546
3749
|
water_heater.setUseFlowRateFractionSchedule(schedule)
|
3547
3750
|
end
|
3548
3751
|
|
3549
3752
|
return water_heater
|
3550
|
-
|
3551
3753
|
end
|
3552
3754
|
|
3553
3755
|
# Creates a booster water heater and attaches it
|
3554
3756
|
# to the supplied service water heating loop.
|
3555
3757
|
#
|
3556
|
-
# @param
|
3758
|
+
# @param template [String] Valid choices are 90.1-2004,
|
3557
3759
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
3558
3760
|
# @param main_service_water_loop [OpenStudio::Model::PlantLoop]
|
3559
3761
|
# the main service water loop that this booster assists.
|
@@ -3569,7 +3771,7 @@ class OpenStudio::Model::Model
|
|
3569
3771
|
# @param building_type [String] the building type
|
3570
3772
|
# @return [OpenStudio::Model::PlantLoop]
|
3571
3773
|
# the resulting booster water loop.
|
3572
|
-
def add_swh_booster(
|
3774
|
+
def add_swh_booster(template,
|
3573
3775
|
main_service_water_loop,
|
3574
3776
|
water_heater_capacity,
|
3575
3777
|
water_heater_volume,
|
@@ -3579,7 +3781,7 @@ class OpenStudio::Model::Model
|
|
3579
3781
|
booster_water_heater_thermal_zone,
|
3580
3782
|
building_type = nil)
|
3581
3783
|
|
3582
|
-
OpenStudio
|
3784
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding booster water heater to #{main_service_water_loop.name}.")
|
3583
3785
|
|
3584
3786
|
# Booster water heating loop
|
3585
3787
|
booster_service_water_loop = OpenStudio::Model::PlantLoop.new(self)
|
@@ -3595,16 +3797,16 @@ class OpenStudio::Model::Model
|
|
3595
3797
|
|
3596
3798
|
# Service water heating loop controls
|
3597
3799
|
swh_temp_c = booster_water_temperature
|
3598
|
-
swh_temp_f = OpenStudio.convert(swh_temp_c,'C','F').get
|
3599
|
-
swh_delta_t_r = 9 #9F delta-T
|
3600
|
-
swh_delta_t_k = OpenStudio.convert(swh_delta_t_r,'R','K').get
|
3800
|
+
swh_temp_f = OpenStudio.convert(swh_temp_c, 'C', 'F').get
|
3801
|
+
swh_delta_t_r = 9 # 9F delta-T
|
3802
|
+
swh_delta_t_k = OpenStudio.convert(swh_delta_t_r, 'R', 'K').get
|
3601
3803
|
swh_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
3602
3804
|
swh_temp_sch.setName("Service Water Booster Temp - #{swh_temp_f}F")
|
3603
|
-
swh_temp_sch.defaultDaySchedule
|
3604
|
-
swh_temp_sch.defaultDaySchedule
|
3805
|
+
swh_temp_sch.defaultDaySchedule.setName("Service Water Booster Temp - #{swh_temp_f}F Default")
|
3806
|
+
swh_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), swh_temp_c)
|
3605
3807
|
swh_temp_sch.setScheduleTypeLimits(temp_sch_type_limits)
|
3606
|
-
swh_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self,swh_temp_sch)
|
3607
|
-
swh_stpt_manager.setName(
|
3808
|
+
swh_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self, swh_temp_sch)
|
3809
|
+
swh_stpt_manager.setName('Hot water booster setpoint manager')
|
3608
3810
|
swh_stpt_manager.addToNode(booster_service_water_loop.supplyOutletNode)
|
3609
3811
|
sizing_plant = booster_service_water_loop.sizingPlant
|
3610
3812
|
sizing_plant.setLoopType('Heating')
|
@@ -3623,14 +3825,14 @@ class OpenStudio::Model::Model
|
|
3623
3825
|
# Water heater
|
3624
3826
|
# TODO Standards - Change water heater methodology to follow
|
3625
3827
|
# 'Model Enhancements Appendix A.'
|
3626
|
-
water_heater_capacity_btu_per_hr = OpenStudio.convert(water_heater_capacity,
|
3627
|
-
water_heater_capacity_kbtu_per_hr = OpenStudio.convert(water_heater_capacity_btu_per_hr,
|
3628
|
-
water_heater_vol_gal = OpenStudio.convert(water_heater_volume,'m^3','gal').get
|
3828
|
+
water_heater_capacity_btu_per_hr = OpenStudio.convert(water_heater_capacity, 'W', 'Btu/hr').get
|
3829
|
+
water_heater_capacity_kbtu_per_hr = OpenStudio.convert(water_heater_capacity_btu_per_hr, 'Btu/hr', 'kBtu/hr').get
|
3830
|
+
water_heater_vol_gal = OpenStudio.convert(water_heater_volume, 'm^3', 'gal').get
|
3629
3831
|
|
3630
3832
|
# Water heater depends on the fuel type
|
3631
3833
|
water_heater = OpenStudio::Model::WaterHeaterMixed.new(self)
|
3632
3834
|
water_heater.setName("#{water_heater_vol_gal}gal #{water_heater_fuel} Booster Water Heater - #{water_heater_capacity_kbtu_per_hr.round}kBtu/hr")
|
3633
|
-
water_heater.setTankVolume(OpenStudio.convert(water_heater_vol_gal,'gal','m^3').get)
|
3835
|
+
water_heater.setTankVolume(OpenStudio.convert(water_heater_vol_gal, 'gal', 'm^3').get)
|
3634
3836
|
water_heater.setSetpointTemperatureSchedule(swh_temp_sch)
|
3635
3837
|
|
3636
3838
|
if booster_water_heater_thermal_zone.nil?
|
@@ -3638,7 +3840,7 @@ class OpenStudio::Model::Model
|
|
3638
3840
|
default_water_heater_ambient_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
3639
3841
|
default_water_heater_ambient_temp_sch.setName('Water Heater Ambient Temp Schedule - 70F')
|
3640
3842
|
default_water_heater_ambient_temp_sch.defaultDaySchedule.setName('Water Heater Ambient Temp Schedule - 70F Default')
|
3641
|
-
default_water_heater_ambient_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),OpenStudio
|
3843
|
+
default_water_heater_ambient_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), OpenStudio.convert(70, 'F', 'C').get)
|
3642
3844
|
default_water_heater_ambient_temp_sch.setScheduleTypeLimits(temp_sch_type_limits)
|
3643
3845
|
water_heater.setAmbientTemperatureIndicator('Schedule')
|
3644
3846
|
water_heater.setAmbientTemperatureSchedule(default_water_heater_ambient_temp_sch)
|
@@ -3647,10 +3849,10 @@ class OpenStudio::Model::Model
|
|
3647
3849
|
water_heater.setAmbientTemperatureThermalZone booster_water_heater_thermal_zone
|
3648
3850
|
end
|
3649
3851
|
|
3650
|
-
water_heater.setMaximumTemperatureLimit(OpenStudio
|
3651
|
-
water_heater.setDeadbandTemperatureDifference(OpenStudio.convert(3.6,'R','K').get)
|
3852
|
+
water_heater.setMaximumTemperatureLimit(OpenStudio.convert(180, 'F', 'C').get)
|
3853
|
+
water_heater.setDeadbandTemperatureDifference(OpenStudio.convert(3.6, 'R', 'K').get)
|
3652
3854
|
water_heater.setHeaterControlType('Cycle')
|
3653
|
-
water_heater.setHeaterMaximumCapacity(OpenStudio.convert(water_heater_capacity_btu_per_hr,'Btu/hr','W').get)
|
3855
|
+
water_heater.setHeaterMaximumCapacity(OpenStudio.convert(water_heater_capacity_btu_per_hr, 'Btu/hr', 'W').get)
|
3654
3856
|
water_heater.setOffCycleParasiticHeatFractiontoTank(0.8)
|
3655
3857
|
water_heater.setIndirectWaterHeatingRecoveryTime(1.5) # 1.5hrs
|
3656
3858
|
if water_heater_fuel == 'Electricity'
|
@@ -3699,10 +3901,10 @@ class OpenStudio::Model::Model
|
|
3699
3901
|
# Heat exchanger to supply the booster water heater
|
3700
3902
|
# with normal hot water from the main service water loop.
|
3701
3903
|
hx = OpenStudio::Model::HeatExchangerFluidToFluid.new(self)
|
3702
|
-
hx.setName(
|
3703
|
-
hx.setHeatExchangeModelType(
|
3704
|
-
hx.setControlType(
|
3705
|
-
hx.setHeatTransferMeteringEndUseType(
|
3904
|
+
hx.setName('HX for Booster Water Heating')
|
3905
|
+
hx.setHeatExchangeModelType('Ideal')
|
3906
|
+
hx.setControlType('UncontrolledOn')
|
3907
|
+
hx.setHeatTransferMeteringEndUseType('LoopToLoop')
|
3706
3908
|
|
3707
3909
|
# Add the HX to the supply side of the booster loop
|
3708
3910
|
hx.addToNode(booster_service_water_loop.supplyInletNode)
|
@@ -3712,13 +3914,12 @@ class OpenStudio::Model::Model
|
|
3712
3914
|
main_service_water_loop.addDemandBranchForComponent(hx)
|
3713
3915
|
|
3714
3916
|
return booster_service_water_loop
|
3715
|
-
|
3716
3917
|
end
|
3717
3918
|
|
3718
3919
|
# Creates water fixtures and attaches them
|
3719
3920
|
# to the supplied service water loop.
|
3720
3921
|
#
|
3721
|
-
# @param
|
3922
|
+
# @param template [String] Valid choices are 90.1-2004,
|
3722
3923
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
3723
3924
|
# @param use_name [String] The name that will be assigned
|
3724
3925
|
# to the newly created fixture.
|
@@ -3732,16 +3933,16 @@ class OpenStudio::Model::Model
|
|
3732
3933
|
# @param building_type [String] the building type
|
3733
3934
|
# @return [OpenStudio::Model::WaterUseEquipment]
|
3734
3935
|
# the resulting water fixture.
|
3735
|
-
def add_swh_end_uses(
|
3736
|
-
|
3737
|
-
|
3738
|
-
|
3739
|
-
|
3740
|
-
|
3741
|
-
|
3742
|
-
|
3936
|
+
def add_swh_end_uses(template,
|
3937
|
+
use_name,
|
3938
|
+
swh_loop,
|
3939
|
+
peak_flowrate,
|
3940
|
+
flowrate_schedule,
|
3941
|
+
water_use_temperature,
|
3942
|
+
space_name,
|
3943
|
+
building_type = nil)
|
3743
3944
|
|
3744
|
-
OpenStudio
|
3945
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding water fixture to #{swh_loop.name}.")
|
3745
3946
|
|
3746
3947
|
# Water use connection
|
3747
3948
|
swh_connection = OpenStudio::Model::WaterUseConnections.new(self)
|
@@ -3749,7 +3950,7 @@ class OpenStudio::Model::Model
|
|
3749
3950
|
# Water fixture definition
|
3750
3951
|
water_fixture_def = OpenStudio::Model::WaterUseEquipmentDefinition.new(self)
|
3751
3952
|
rated_flow_rate_m3_per_s = peak_flowrate
|
3752
|
-
rated_flow_rate_gal_per_min = OpenStudio.convert(rated_flow_rate_m3_per_s,'m^3/s','gal/min').get
|
3953
|
+
rated_flow_rate_gal_per_min = OpenStudio.convert(rated_flow_rate_m3_per_s, 'm^3/s', 'gal/min').get
|
3753
3954
|
frac_sensible = 0.2
|
3754
3955
|
frac_latent = 0.05
|
3755
3956
|
# water_use_sensible_frac_sch = OpenStudio::Model::ScheduleConstant.new(self)
|
@@ -3758,24 +3959,24 @@ class OpenStudio::Model::Model
|
|
3758
3959
|
# water_use_latent_frac_sch.setValue(0.05)
|
3759
3960
|
water_use_sensible_frac_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
3760
3961
|
water_use_sensible_frac_sch.setName("Fraction Sensible - #{frac_sensible}")
|
3761
|
-
water_use_sensible_frac_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),frac_sensible)
|
3962
|
+
water_use_sensible_frac_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), frac_sensible)
|
3762
3963
|
water_use_latent_frac_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
3763
3964
|
water_use_latent_frac_sch.setName("Fraction Latent - #{frac_latent}")
|
3764
|
-
water_use_latent_frac_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),frac_latent)
|
3965
|
+
water_use_latent_frac_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), frac_latent)
|
3765
3966
|
water_fixture_def.setSensibleFractionSchedule(water_use_sensible_frac_sch)
|
3766
3967
|
water_fixture_def.setLatentFractionSchedule(water_use_latent_frac_sch)
|
3767
3968
|
water_fixture_def.setPeakFlowRate(rated_flow_rate_m3_per_s)
|
3768
3969
|
water_fixture_def.setName("#{use_name.capitalize} Service Water Use Def #{rated_flow_rate_gal_per_min.round(2)}gal/min")
|
3769
3970
|
# Target mixed water temperature
|
3770
|
-
mixed_water_temp_f = OpenStudio.convert(water_use_temperature,'C','F').get
|
3971
|
+
mixed_water_temp_f = OpenStudio.convert(water_use_temperature, 'C', 'F').get
|
3771
3972
|
mixed_water_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
3772
3973
|
mixed_water_temp_sch.setName("Mixed Water At Faucet Temp - #{mixed_water_temp_f.round}F")
|
3773
|
-
mixed_water_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),OpenStudio.convert(mixed_water_temp_f,'F','C').get)
|
3974
|
+
mixed_water_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), OpenStudio.convert(mixed_water_temp_f, 'F', 'C').get)
|
3774
3975
|
water_fixture_def.setTargetTemperatureSchedule(mixed_water_temp_sch)
|
3775
3976
|
|
3776
3977
|
# Water use equipment
|
3777
3978
|
water_fixture = OpenStudio::Model::WaterUseEquipment.new(water_fixture_def)
|
3778
|
-
schedule =
|
3979
|
+
schedule = add_schedule(flowrate_schedule)
|
3779
3980
|
water_fixture.setFlowRateFractionSchedule(schedule)
|
3780
3981
|
|
3781
3982
|
if space_name.nil?
|
@@ -3785,7 +3986,7 @@ class OpenStudio::Model::Model
|
|
3785
3986
|
end
|
3786
3987
|
|
3787
3988
|
unless space_name.nil?
|
3788
|
-
space =
|
3989
|
+
space = getSpaceByName(space_name)
|
3789
3990
|
space = space.get
|
3790
3991
|
water_fixture.setSpace(space)
|
3791
3992
|
end
|
@@ -3796,47 +3997,56 @@ class OpenStudio::Model::Model
|
|
3796
3997
|
swh_loop.addDemandBranchForComponent(swh_connection)
|
3797
3998
|
|
3798
3999
|
return water_fixture
|
3799
|
-
|
3800
4000
|
end
|
3801
4001
|
|
3802
|
-
|
3803
|
-
|
4002
|
+
# This method will add an swh water fixture to the model for the space.
|
4003
|
+
# if the it will return a water fixture object, or NIL if there is no water load at all.
|
4004
|
+
def add_swh_end_uses_by_space(building_type, template, climate_zone, swh_loop, space_type_name, space_name, space_multiplier = nil, is_flow_per_area = true)
|
3804
4005
|
# find the specific space_type properties from standard.json
|
3805
4006
|
search_criteria = {
|
3806
|
-
'template' =>
|
4007
|
+
'template' => template,
|
3807
4008
|
'building_type' => building_type,
|
3808
4009
|
'space_type' => space_type_name
|
3809
4010
|
}
|
3810
|
-
data = find_object($os_standards['space_types'],search_criteria)
|
3811
|
-
|
4011
|
+
data = find_object($os_standards['space_types'], search_criteria)
|
4012
|
+
if data.nil?
|
4013
|
+
puts "Error: #{search_criteria}"
|
4014
|
+
end
|
4015
|
+
space = getSpaceByName(space_name)
|
3812
4016
|
space = space.get
|
3813
|
-
space_area = OpenStudio.convert(space.floorArea,'m^2','ft^2').get
|
4017
|
+
space_area = OpenStudio.convert(space.floorArea, 'm^2', 'ft^2').get # ft2
|
3814
4018
|
if space_multiplier.nil?
|
3815
4019
|
space_multiplier = 1
|
3816
4020
|
end
|
3817
4021
|
|
4022
|
+
# If there is no service hot water load.. Don't bother adding anything.
|
4023
|
+
if data['service_water_heating_peak_flow_per_area'].to_f == 0.0 ||
|
4024
|
+
data['service_water_heating_peak_flow_rate'].to_f == 0.0
|
4025
|
+
return nil
|
4026
|
+
end
|
4027
|
+
|
3818
4028
|
# Water use connection
|
3819
4029
|
swh_connection = OpenStudio::Model::WaterUseConnections.new(self)
|
3820
4030
|
|
3821
4031
|
# Water fixture definition
|
3822
4032
|
water_fixture_def = OpenStudio::Model::WaterUseEquipmentDefinition.new(self)
|
3823
|
-
rated_flow_rate_per_area = data['service_water_heating_peak_flow_per_area'].to_f
|
3824
|
-
if is_flow_per_area
|
3825
|
-
|
3826
|
-
|
3827
|
-
|
3828
|
-
|
3829
|
-
rated_flow_rate_gal_per_min = rated_flow_rate_gal_per_hour/60
|
3830
|
-
rated_flow_rate_m3_per_s = OpenStudio.convert(rated_flow_rate_gal_per_min,'gal/min','m^3/s').get
|
4033
|
+
rated_flow_rate_per_area = data['service_water_heating_peak_flow_per_area'].to_f # gal/h.ft2
|
4034
|
+
rated_flow_rate_gal_per_hour = if is_flow_per_area
|
4035
|
+
rated_flow_rate_per_area * space_area * space_multiplier # gal/h
|
4036
|
+
else
|
4037
|
+
data['service_water_heating_peak_flow_rate'].to_f
|
4038
|
+
end
|
4039
|
+
rated_flow_rate_gal_per_min = rated_flow_rate_gal_per_hour / 60 # gal/h to gal/min
|
4040
|
+
rated_flow_rate_m3_per_s = OpenStudio.convert(rated_flow_rate_gal_per_min, 'gal/min', 'm^3/s').get
|
3831
4041
|
|
3832
4042
|
# water_use_sensible_frac_sch = OpenStudio::Model::ScheduleConstant.new(self)
|
3833
4043
|
# water_use_sensible_frac_sch.setValue(0.2)
|
3834
4044
|
# water_use_latent_frac_sch = OpenStudio::Model::ScheduleConstant.new(self)
|
3835
4045
|
# water_use_latent_frac_sch.setValue(0.05)
|
3836
4046
|
water_use_sensible_frac_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
3837
|
-
water_use_sensible_frac_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),0.2)
|
4047
|
+
water_use_sensible_frac_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0.2)
|
3838
4048
|
water_use_latent_frac_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
3839
|
-
water_use_latent_frac_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),0.05)
|
4049
|
+
water_use_latent_frac_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0.05)
|
3840
4050
|
water_fixture_def.setSensibleFractionSchedule(water_use_sensible_frac_sch)
|
3841
4051
|
water_fixture_def.setLatentFractionSchedule(water_use_latent_frac_sch)
|
3842
4052
|
water_fixture_def.setPeakFlowRate(rated_flow_rate_m3_per_s)
|
@@ -3844,25 +4054,25 @@ class OpenStudio::Model::Model
|
|
3844
4054
|
# Target mixed water temperature
|
3845
4055
|
mixed_water_temp_c = data['service_water_heating_target_temperature']
|
3846
4056
|
mixed_water_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
3847
|
-
mixed_water_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),mixed_water_temp_c)
|
4057
|
+
mixed_water_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), mixed_water_temp_c)
|
3848
4058
|
water_fixture_def.setTargetTemperatureSchedule(mixed_water_temp_sch)
|
3849
4059
|
|
3850
4060
|
# Water use equipment
|
3851
4061
|
water_fixture = OpenStudio::Model::WaterUseEquipment.new(water_fixture_def)
|
3852
|
-
schedule =
|
4062
|
+
schedule = add_schedule(data['service_water_heating_schedule'])
|
3853
4063
|
water_fixture.setFlowRateFractionSchedule(schedule)
|
3854
4064
|
water_fixture.setName("#{space_name.capitalize} Service Water Use #{rated_flow_rate_gal_per_min.round(2)}gal/min")
|
3855
4065
|
swh_connection.addWaterUseEquipment(water_fixture)
|
3856
4066
|
|
3857
4067
|
# Connect the water use connection to the SWH loop
|
3858
4068
|
swh_loop.addDemandBranchForComponent(swh_connection)
|
3859
|
-
|
4069
|
+
return water_fixture
|
3860
4070
|
end
|
3861
4071
|
|
3862
4072
|
# Creates water fixtures and attaches them
|
3863
4073
|
# to the supplied booster water loop.
|
3864
4074
|
#
|
3865
|
-
# @param
|
4075
|
+
# @param template [String] Valid choices are 90.1-2004,
|
3866
4076
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
3867
4077
|
# @param swh_booster_loop [OpenStudio::Model::PlantLoop]
|
3868
4078
|
# the booster water loop to add water fixtures to.
|
@@ -3872,14 +4082,14 @@ class OpenStudio::Model::Model
|
|
3872
4082
|
# @param building_type [String] the building type
|
3873
4083
|
# @return [OpenStudio::Model::WaterUseEquipment]
|
3874
4084
|
# the resulting water fixture.
|
3875
|
-
def add_booster_swh_end_uses(
|
3876
|
-
|
3877
|
-
|
3878
|
-
|
3879
|
-
|
3880
|
-
|
4085
|
+
def add_booster_swh_end_uses(template,
|
4086
|
+
swh_booster_loop,
|
4087
|
+
peak_flowrate,
|
4088
|
+
flowrate_schedule,
|
4089
|
+
water_use_temperature,
|
4090
|
+
building_type = nil)
|
3881
4091
|
|
3882
|
-
OpenStudio
|
4092
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding water fixture to #{swh_booster_loop.name}.")
|
3883
4093
|
|
3884
4094
|
# Water use connection
|
3885
4095
|
swh_connection = OpenStudio::Model::WaterUseConnections.new(self)
|
@@ -3887,19 +4097,20 @@ class OpenStudio::Model::Model
|
|
3887
4097
|
# Water fixture definition
|
3888
4098
|
water_fixture_def = OpenStudio::Model::WaterUseEquipmentDefinition.new(self)
|
3889
4099
|
rated_flow_rate_m3_per_s = peak_flowrate
|
3890
|
-
rated_flow_rate_gal_per_min = OpenStudio.convert(rated_flow_rate_m3_per_s,'m^3/s','gal/min').get
|
4100
|
+
rated_flow_rate_gal_per_min = OpenStudio.convert(rated_flow_rate_m3_per_s, 'm^3/s', 'gal/min').get
|
3891
4101
|
water_fixture_def.setName("Water Fixture Def - #{rated_flow_rate_gal_per_min} gal/min")
|
3892
4102
|
water_fixture_def.setPeakFlowRate(rated_flow_rate_m3_per_s)
|
3893
4103
|
# Target mixed water temperature
|
3894
|
-
mixed_water_temp_f = OpenStudio.convert(water_use_temperature,'F','C').get
|
4104
|
+
mixed_water_temp_f = OpenStudio.convert(water_use_temperature, 'F', 'C').get
|
3895
4105
|
mixed_water_temp_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
3896
|
-
mixed_water_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0),OpenStudio.convert(mixed_water_temp_f,'F','C').get)
|
4106
|
+
mixed_water_temp_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), OpenStudio.convert(mixed_water_temp_f, 'F', 'C').get)
|
4107
|
+
puts mixed_water_temp_sch
|
3897
4108
|
water_fixture_def.setTargetTemperatureSchedule(mixed_water_temp_sch)
|
3898
4109
|
|
3899
4110
|
# Water use equipment
|
3900
4111
|
water_fixture = OpenStudio::Model::WaterUseEquipment.new(water_fixture_def)
|
3901
4112
|
water_fixture.setName("Booster Water Fixture - #{rated_flow_rate_gal_per_min} gal/min at #{mixed_water_temp_f}F")
|
3902
|
-
schedule =
|
4113
|
+
schedule = add_schedule(flowrate_schedule)
|
3903
4114
|
water_fixture.setFlowRateFractionSchedule(schedule)
|
3904
4115
|
swh_connection.addWaterUseEquipment(water_fixture)
|
3905
4116
|
|
@@ -3907,15 +4118,12 @@ class OpenStudio::Model::Model
|
|
3907
4118
|
swh_booster_loop.addDemandBranchForComponent(swh_connection)
|
3908
4119
|
|
3909
4120
|
return water_fixture
|
3910
|
-
|
3911
4121
|
end
|
3912
4122
|
|
3913
|
-
|
3914
|
-
|
3915
4123
|
# Creates a DOAS system with fan coil units
|
3916
4124
|
# for each zone.
|
3917
4125
|
#
|
3918
|
-
# @param
|
4126
|
+
# @param template [String] Valid choices are 90.1-2004,
|
3919
4127
|
# 90.1-2007, 90.1-2010, 90.1-2013
|
3920
4128
|
# @param sys_name [String] the name of the system, or nil in which case it will be defaulted
|
3921
4129
|
# @param hot_water_loop [String] hot water loop to connect heating and zone fan coils to
|
@@ -3931,53 +4139,53 @@ class OpenStudio::Model::Model
|
|
3931
4139
|
# FixedDryBulb,
|
3932
4140
|
# @param building_type [String] the building type
|
3933
4141
|
# @return [OpenStudio::Model::AirLoopHVAC] the resulting DOAS air loop
|
3934
|
-
def add_doas(
|
3935
|
-
|
3936
|
-
|
3937
|
-
|
3938
|
-
|
3939
|
-
|
3940
|
-
|
3941
|
-
|
3942
|
-
|
3943
|
-
|
3944
|
-
|
3945
|
-
OpenStudio
|
4142
|
+
def add_doas(template,
|
4143
|
+
sys_name,
|
4144
|
+
hot_water_loop,
|
4145
|
+
chilled_water_loop,
|
4146
|
+
thermal_zones,
|
4147
|
+
hvac_op_sch,
|
4148
|
+
oa_damper_sch,
|
4149
|
+
fan_max_flow_rate,
|
4150
|
+
economizer_control_type,
|
4151
|
+
building_type = nil)
|
4152
|
+
|
4153
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding DOAS system for #{thermal_zones.size} zones.")
|
3946
4154
|
thermal_zones.each do |zone|
|
3947
|
-
OpenStudio
|
4155
|
+
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.Model.Model', "---#{zone.name}")
|
3948
4156
|
end
|
3949
4157
|
|
3950
4158
|
# hvac operation schedule
|
3951
|
-
if hvac_op_sch.nil?
|
3952
|
-
|
3953
|
-
|
3954
|
-
|
3955
|
-
|
4159
|
+
hvac_op_sch = if hvac_op_sch.nil?
|
4160
|
+
alwaysOnDiscreteSchedule
|
4161
|
+
else
|
4162
|
+
add_schedule(hvac_op_sch)
|
4163
|
+
end
|
3956
4164
|
|
3957
4165
|
# oa damper schedule
|
3958
|
-
if oa_damper_sch.nil?
|
3959
|
-
|
3960
|
-
|
3961
|
-
|
3962
|
-
|
4166
|
+
oa_damper_sch = if oa_damper_sch.nil?
|
4167
|
+
alwaysOnDiscreteSchedule
|
4168
|
+
else
|
4169
|
+
add_schedule(oa_damper_sch)
|
4170
|
+
end
|
3963
4171
|
|
3964
4172
|
# DOAS
|
3965
4173
|
air_loop = OpenStudio::Model::AirLoopHVAC.new(self)
|
3966
4174
|
if sys_name.nil?
|
3967
4175
|
air_loop.setName("#{thermal_zones.size} DOAS Air Loop HVAC")
|
3968
4176
|
else
|
3969
|
-
air_loop.setName(
|
4177
|
+
air_loop.setName('DOAS Air Loop HVAC')
|
3970
4178
|
end
|
3971
4179
|
air_loop.setNightCycleControlType('CycleOnAny')
|
3972
4180
|
# modify system sizing properties
|
3973
4181
|
sizing_system = air_loop.sizingSystem
|
3974
4182
|
# set central heating and cooling temperatures for sizing
|
3975
4183
|
sizing_system.setCentralCoolingDesignSupplyAirTemperature(12.8)
|
3976
|
-
sizing_system.setCentralHeatingDesignSupplyAirTemperature(16.7)
|
3977
|
-
sizing_system.setSizingOption(
|
4184
|
+
sizing_system.setCentralHeatingDesignSupplyAirTemperature(16.7) # ML OS default is 16.7
|
4185
|
+
sizing_system.setSizingOption('Coincident')
|
3978
4186
|
# load specification
|
3979
|
-
sizing_system.setSystemOutdoorAirMethod(
|
3980
|
-
sizing_system.setTypeofLoadtoSizeOn(
|
4187
|
+
sizing_system.setSystemOutdoorAirMethod('ZoneSum') # ML OS default is ZoneSum
|
4188
|
+
sizing_system.setTypeofLoadtoSizeOn('Sensible') # DOAS
|
3981
4189
|
sizing_system.setAllOutdoorAirinCooling(true) # DOAS
|
3982
4190
|
sizing_system.setAllOutdoorAirinHeating(true) # DOAS
|
3983
4191
|
sizing_system.setMinimumSystemAirFlowRatio(0.3) # No DCV
|
@@ -3988,23 +4196,23 @@ class OpenStudio::Model::Model
|
|
3988
4196
|
|
3989
4197
|
# create air loop fan
|
3990
4198
|
# constant speed fan
|
3991
|
-
fan = OpenStudio::Model::FanConstantVolume.new(self,
|
3992
|
-
fan.setName(
|
4199
|
+
fan = OpenStudio::Model::FanConstantVolume.new(self, alwaysOnDiscreteSchedule)
|
4200
|
+
fan.setName('DOAS fan')
|
3993
4201
|
fan.setFanEfficiency(0.58175)
|
3994
|
-
fan.setPressureRise(622.5) #Pa
|
3995
|
-
if fan_max_flow_rate
|
3996
|
-
fan.setMaximumFlowRate(OpenStudio.convert(fan_max_flow_rate, 'cfm', 'm^3/s').get)
|
4202
|
+
fan.setPressureRise(622.5) # Pa
|
4203
|
+
if !fan_max_flow_rate.nil?
|
4204
|
+
fan.setMaximumFlowRate(OpenStudio.convert(fan_max_flow_rate, 'cfm', 'm^3/s').get) # unit of fan_max_flow_rate is cfm
|
3997
4205
|
else
|
3998
4206
|
fan.autosizeMaximumFlowRate
|
3999
4207
|
end
|
4000
4208
|
fan.setMotorEfficiency(0.895)
|
4001
4209
|
fan.setMotorInAirstreamFraction(1.0)
|
4002
|
-
fan.setEndUseSubcategory(
|
4210
|
+
fan.setEndUseSubcategory('DOAS Fans')
|
4003
4211
|
fan.addToNode(airloop_supply_inlet)
|
4004
4212
|
|
4005
4213
|
# create heating coil
|
4006
4214
|
# water coil
|
4007
|
-
heating_coil = OpenStudio::Model::CoilHeatingWater.new(self,
|
4215
|
+
heating_coil = OpenStudio::Model::CoilHeatingWater.new(self, alwaysOnDiscreteSchedule)
|
4008
4216
|
hot_water_loop.addDemandBranchForComponent(heating_coil)
|
4009
4217
|
heating_coil.controllerWaterCoil.get.setMinimumActuatedFlow(0)
|
4010
4218
|
heating_coil.addToNode(airloop_supply_inlet)
|
@@ -4012,32 +4220,32 @@ class OpenStudio::Model::Model
|
|
4012
4220
|
|
4013
4221
|
# create cooling coil
|
4014
4222
|
# water coil
|
4015
|
-
cooling_coil = OpenStudio::Model::CoilCoolingWater.new(self,
|
4223
|
+
cooling_coil = OpenStudio::Model::CoilCoolingWater.new(self, alwaysOnDiscreteSchedule)
|
4016
4224
|
chilled_water_loop.addDemandBranchForComponent(cooling_coil)
|
4017
4225
|
cooling_coil.controllerWaterCoil.get.setMinimumActuatedFlow(0)
|
4018
4226
|
cooling_coil.addToNode(airloop_supply_inlet)
|
4019
4227
|
|
4020
4228
|
# create controller outdoor air
|
4021
|
-
|
4022
|
-
|
4023
|
-
|
4024
|
-
|
4025
|
-
|
4026
|
-
|
4229
|
+
controller_oa = OpenStudio::Model::ControllerOutdoorAir.new(self)
|
4230
|
+
controller_oa.setName('DOAS OA Controller')
|
4231
|
+
controller_oa.setEconomizerControlType(economizer_control_type)
|
4232
|
+
controller_oa.setMinimumLimitType('FixedMinimum')
|
4233
|
+
controller_oa.setMinimumOutdoorAirSchedule(oa_damper_sch)
|
4234
|
+
controller_oa.resetEconomizerMaximumLimitDryBulbTemperature
|
4027
4235
|
# TODO: Yixing read the schedule from the Prototype Input
|
4028
|
-
if building_type ==
|
4029
|
-
|
4236
|
+
if building_type == 'LargeHotel'
|
4237
|
+
controller_oa.setMinimumFractionofOutdoorAirSchedule(add_schedule('HotelLarge FLR_3_DOAS_OAminOAFracSchedule'))
|
4030
4238
|
end
|
4031
|
-
|
4032
|
-
|
4033
|
-
|
4239
|
+
controller_oa.resetEconomizerMaximumLimitEnthalpy
|
4240
|
+
controller_oa.resetMaximumFractionofOutdoorAirSchedule
|
4241
|
+
controller_oa.resetEconomizerMinimumLimitDryBulbTemperature
|
4034
4242
|
|
4035
4243
|
# create ventilation schedules and assign to OA controller
|
4036
|
-
|
4244
|
+
controller_oa.setHeatRecoveryBypassControlType('BypassWhenWithinEconomizerLimits')
|
4037
4245
|
|
4038
4246
|
# create outdoor air system
|
4039
|
-
|
4040
|
-
|
4247
|
+
system_oa = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(self, controller_oa)
|
4248
|
+
system_oa.addToNode(airloop_supply_inlet)
|
4041
4249
|
|
4042
4250
|
# create scheduled setpoint manager for airloop
|
4043
4251
|
# DOAS or VAV for cooling and not ventilation
|
@@ -4061,36 +4269,36 @@ class OpenStudio::Model::Model
|
|
4061
4269
|
zone_sizing = zone.sizingZone
|
4062
4270
|
zone_sizing.setZoneCoolingDesignSupplyAirTemperature(12.8)
|
4063
4271
|
zone_sizing.setZoneHeatingDesignSupplyAirTemperature(40)
|
4064
|
-
zone_sizing.setCoolingDesignAirFlowMethod(
|
4065
|
-
zone_sizing.setHeatingDesignAirFlowMethod(
|
4272
|
+
zone_sizing.setCoolingDesignAirFlowMethod('DesignDayWithLimit')
|
4273
|
+
zone_sizing.setHeatingDesignAirFlowMethod('DesignDay')
|
4066
4274
|
|
4067
4275
|
# make an air terminal for the zone
|
4068
|
-
air_terminal = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(self,
|
4069
|
-
air_terminal.setName(zone_name +
|
4276
|
+
air_terminal = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(self, alwaysOnDiscreteSchedule)
|
4277
|
+
air_terminal.setName(zone_name + 'Air Terminal')
|
4070
4278
|
|
4071
|
-
fan_coil_cooling_coil = OpenStudio::Model::CoilCoolingWater.new(self,
|
4072
|
-
fan_coil_cooling_coil.setName(zone_name +
|
4279
|
+
fan_coil_cooling_coil = OpenStudio::Model::CoilCoolingWater.new(self, alwaysOnDiscreteSchedule)
|
4280
|
+
fan_coil_cooling_coil.setName(zone_name + 'FCU Cooling Coil')
|
4073
4281
|
chilled_water_loop.addDemandBranchForComponent(fan_coil_cooling_coil)
|
4074
4282
|
fan_coil_cooling_coil.controllerWaterCoil.get.setMinimumActuatedFlow(0)
|
4075
4283
|
|
4076
|
-
fan_coil_heating_coil = OpenStudio::Model::CoilHeatingWater.new(self,
|
4077
|
-
fan_coil_heating_coil.setName(zone_name +
|
4284
|
+
fan_coil_heating_coil = OpenStudio::Model::CoilHeatingWater.new(self, alwaysOnDiscreteSchedule)
|
4285
|
+
fan_coil_heating_coil.setName(zone_name + 'FCU Heating Coil')
|
4078
4286
|
hot_water_loop.addDemandBranchForComponent(fan_coil_heating_coil)
|
4079
4287
|
fan_coil_heating_coil.controllerWaterCoil.get.setMinimumActuatedFlow(0)
|
4080
4288
|
|
4081
|
-
fan_coil_fan = OpenStudio::Model::FanOnOff.new(self,
|
4082
|
-
fan_coil_fan.setName(zone_name +
|
4289
|
+
fan_coil_fan = OpenStudio::Model::FanOnOff.new(self, alwaysOnDiscreteSchedule)
|
4290
|
+
fan_coil_fan.setName(zone_name + ' Fan Coil fan')
|
4083
4291
|
fan_coil_fan.setFanEfficiency(0.16)
|
4084
|
-
fan_coil_fan.setPressureRise(270.9) #Pa
|
4292
|
+
fan_coil_fan.setPressureRise(270.9) # Pa
|
4085
4293
|
fan_coil_fan.autosizeMaximumFlowRate
|
4086
4294
|
fan_coil_fan.setMotorEfficiency(0.29)
|
4087
4295
|
fan_coil_fan.setMotorInAirstreamFraction(1.0)
|
4088
|
-
fan_coil_fan.setEndUseSubcategory(
|
4296
|
+
fan_coil_fan.setEndUseSubcategory('FCU Fans')
|
4089
4297
|
|
4090
|
-
fan_coil = OpenStudio::Model::ZoneHVACFourPipeFanCoil.new(self,
|
4091
|
-
|
4092
|
-
fan_coil.setName(zone_name +
|
4093
|
-
fan_coil.setCapacityControlMethod(
|
4298
|
+
fan_coil = OpenStudio::Model::ZoneHVACFourPipeFanCoil.new(self, alwaysOnDiscreteSchedule,
|
4299
|
+
fan_coil_fan, fan_coil_cooling_coil, fan_coil_heating_coil)
|
4300
|
+
fan_coil.setName(zone_name + 'FCU')
|
4301
|
+
fan_coil.setCapacityControlMethod('CyclingFan')
|
4094
4302
|
fan_coil.autosizeMaximumSupplyAirFlowRate
|
4095
4303
|
fan_coil.setMaximumOutdoorAirFlowRate(0)
|
4096
4304
|
fan_coil.addToThermalZone(zone)
|
@@ -4100,12 +4308,11 @@ class OpenStudio::Model::Model
|
|
4100
4308
|
end
|
4101
4309
|
|
4102
4310
|
return air_loop
|
4103
|
-
|
4104
4311
|
end
|
4105
4312
|
|
4106
4313
|
# Add an elevator the the specified space
|
4107
4314
|
#
|
4108
|
-
# @param
|
4315
|
+
# @param template [String] Valid choices are
|
4109
4316
|
# DOE Ref Pre-1980, DOE Ref 1980-2004,
|
4110
4317
|
# 90.1-2004, 90.1-2007, 90.1-2010, 90.1-2013,
|
4111
4318
|
# @param space [OpenStudio::Model::Space] the space
|
@@ -4118,39 +4325,39 @@ class OpenStudio::Model::Model
|
|
4118
4325
|
# @param elevator_lights_schedule [String] the name of the elevator lights schedule
|
4119
4326
|
# @param building_type [String] the building type
|
4120
4327
|
# @return [OpenStudio::Model::ElectricEquipment] the resulting elevator
|
4121
|
-
def add_elevator(
|
4328
|
+
def add_elevator(template,
|
4122
4329
|
space,
|
4123
4330
|
number_of_elevators,
|
4124
4331
|
elevator_type,
|
4125
4332
|
elevator_schedule,
|
4126
4333
|
elevator_fan_schedule,
|
4127
4334
|
elevator_lights_schedule,
|
4128
|
-
building_type=nil)
|
4335
|
+
building_type = nil)
|
4129
4336
|
|
4130
4337
|
# Lift motor assumptions
|
4131
4338
|
lift_pwr_w = nil
|
4132
|
-
case
|
4133
|
-
when
|
4339
|
+
case template
|
4340
|
+
when 'DOE Ref Pre-1980', 'DOE Ref 1980-2004'
|
4134
4341
|
if elevator_type == 'Traction'
|
4135
|
-
lift_pwr_w =
|
4342
|
+
lift_pwr_w = 18_537.0
|
4136
4343
|
elsif elevator_type == 'Hydraulic'
|
4137
|
-
if building_type == 'MidriseApartment'
|
4138
|
-
|
4139
|
-
|
4140
|
-
|
4141
|
-
|
4344
|
+
lift_pwr_w = if building_type == 'MidriseApartment'
|
4345
|
+
16_055.0
|
4346
|
+
else
|
4347
|
+
14_610.0
|
4348
|
+
end
|
4142
4349
|
else
|
4143
|
-
lift_pwr_w =
|
4144
|
-
OpenStudio
|
4350
|
+
lift_pwr_w = 14_610.0
|
4351
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.model.Model', "Elevator type '#{elevator_type}', not recognized, will assume Hydraulic elevator, #{lift_pwr_w} W.")
|
4145
4352
|
end
|
4146
4353
|
when '90.1-2004', '90.1-2007', '90.1-2010', '90.1-2013'
|
4147
4354
|
if elevator_type == 'Traction'
|
4148
|
-
lift_pwr_w =
|
4355
|
+
lift_pwr_w = 20_370.0
|
4149
4356
|
elsif elevator_type == 'Hydraulic'
|
4150
|
-
lift_pwr_w =
|
4357
|
+
lift_pwr_w = 16_055.0
|
4151
4358
|
else
|
4152
|
-
lift_pwr_w =
|
4153
|
-
OpenStudio
|
4359
|
+
lift_pwr_w = 16_055.0
|
4360
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.model.Model', "Elevator type '#{elevator_type}', not recognized, will assume Hydraulic elevator, #{lift_pwr_w} W.")
|
4154
4361
|
end
|
4155
4362
|
end
|
4156
4363
|
|
@@ -4174,12 +4381,12 @@ class OpenStudio::Model::Model
|
|
4174
4381
|
pct_led = 0.3
|
4175
4382
|
incandescent_efficacy_lm_per_w = 10.0
|
4176
4383
|
led_efficacy_lm_per_w = 35.0
|
4177
|
-
target_ltg_lm_per_ft2 = design_ltg_lm_per_ft2 / light_loss_factor
|
4178
|
-
target_ltg_lm = target_ltg_lm_per_ft2 * area_ft2
|
4179
|
-
lm_incandescent = target_ltg_lm * pct_incandescent
|
4180
|
-
lm_led = target_ltg_lm * pct_led
|
4181
|
-
w_incandescent = lm_incandescent / incandescent_efficacy_lm_per_w
|
4182
|
-
w_led = lm_led / led_efficacy_lm_per_w
|
4384
|
+
target_ltg_lm_per_ft2 = design_ltg_lm_per_ft2 / light_loss_factor # 40
|
4385
|
+
target_ltg_lm = target_ltg_lm_per_ft2 * area_ft2 # 1132.2
|
4386
|
+
lm_incandescent = target_ltg_lm * pct_incandescent # 792.54
|
4387
|
+
lm_led = target_ltg_lm * pct_led # 339.66
|
4388
|
+
w_incandescent = lm_incandescent / incandescent_efficacy_lm_per_w # 79.254
|
4389
|
+
w_led = lm_led / led_efficacy_lm_per_w # 9.7
|
4183
4390
|
lighting_pwr_w = w_incandescent + w_led
|
4184
4391
|
|
4185
4392
|
# Elevator lift motor
|
@@ -4189,13 +4396,13 @@ class OpenStudio::Model::Model
|
|
4189
4396
|
|
4190
4397
|
elevator_equipment = OpenStudio::Model::ElectricEquipment.new(elevator_definition)
|
4191
4398
|
elevator_equipment.setName("#{number_of_elevators.round} Elevator Lift Motors")
|
4192
|
-
elevator_sch =
|
4399
|
+
elevator_sch = add_schedule(elevator_schedule)
|
4193
4400
|
elevator_equipment.setSchedule(elevator_sch)
|
4194
4401
|
elevator_equipment.setSpace(space)
|
4195
4402
|
elevator_equipment.setMultiplier(number_of_elevators)
|
4196
4403
|
|
4197
4404
|
# Pre-1980 and 1980-2004 don't have lights or fans
|
4198
|
-
return elevator_equipment if
|
4405
|
+
return elevator_equipment if template == 'DOE Ref Pre-1980' || template == 'DOE Ref 1980-2004'
|
4199
4406
|
|
4200
4407
|
# Elevator fan
|
4201
4408
|
elevator_fan_definition = OpenStudio::Model::ElectricEquipmentDefinition.new(self)
|
@@ -4204,7 +4411,7 @@ class OpenStudio::Model::Model
|
|
4204
4411
|
|
4205
4412
|
elevator_fan_equipment = OpenStudio::Model::ElectricEquipment.new(elevator_fan_definition)
|
4206
4413
|
elevator_fan_equipment.setName("#{number_of_elevators.round} Elevator Fans")
|
4207
|
-
elevator_fan_sch =
|
4414
|
+
elevator_fan_sch = add_schedule(elevator_fan_schedule)
|
4208
4415
|
elevator_fan_equipment.setSchedule(elevator_fan_sch)
|
4209
4416
|
elevator_fan_equipment.setSpace(space)
|
4210
4417
|
elevator_fan_equipment.setMultiplier(number_of_elevators)
|
@@ -4216,13 +4423,12 @@ class OpenStudio::Model::Model
|
|
4216
4423
|
|
4217
4424
|
elevator_lights_equipment = OpenStudio::Model::ElectricEquipment.new(elevator_lights_definition)
|
4218
4425
|
elevator_lights_equipment.setName("#{number_of_elevators.round} Elevator Lights")
|
4219
|
-
elevator_lights_sch =
|
4426
|
+
elevator_lights_sch = add_schedule(elevator_lights_schedule)
|
4220
4427
|
elevator_lights_equipment.setSchedule(elevator_lights_sch)
|
4221
4428
|
elevator_lights_equipment.setSpace(space)
|
4222
4429
|
elevator_lights_equipment.setMultiplier(number_of_elevators)
|
4223
4430
|
|
4224
4431
|
return elevator_equipment
|
4225
|
-
|
4226
4432
|
end
|
4227
4433
|
|
4228
4434
|
# Adds an exhaust fan to each zone.
|
@@ -4244,7 +4450,7 @@ class OpenStudio::Model::Model
|
|
4244
4450
|
thermal_zones.each do |zone|
|
4245
4451
|
fan = OpenStudio::Model::FanZoneExhaust.new(self)
|
4246
4452
|
fan.setName("#{zone.name} Exhaust Fan")
|
4247
|
-
fan.setAvailabilitySchedule(
|
4453
|
+
fan.setAvailabilitySchedule(add_schedule(availability_sch_name))
|
4248
4454
|
# two ways to input the flow rate: Number of Array.
|
4249
4455
|
# For number: assign directly. For Array: assign each flow rate to each according zone.
|
4250
4456
|
if flow_rate.is_a? Numeric
|
@@ -4254,21 +4460,20 @@ class OpenStudio::Model::Model
|
|
4254
4460
|
flow_rate_zone = flow_rate[index]
|
4255
4461
|
fan.setMaximumFlowRate(flow_rate_zone)
|
4256
4462
|
else
|
4257
|
-
OpenStudio
|
4463
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.model.Model', 'Wrong format of flow rate')
|
4258
4464
|
end
|
4259
4465
|
unless flow_fraction_schedule_name.nil?
|
4260
|
-
fan.setFlowFractionSchedule(
|
4466
|
+
fan.setFlowFractionSchedule(add_schedule(flow_fraction_schedule_name))
|
4261
4467
|
end
|
4262
4468
|
fan.setSystemAvailabilityManagerCouplingMode('Decoupled')
|
4263
4469
|
unless balanced_exhaust_fraction_schedule_name.nil?
|
4264
|
-
fan.setBalancedExhaustFractionSchedule(
|
4470
|
+
fan.setBalancedExhaustFractionSchedule(add_schedule(balanced_exhaust_fraction_schedule_name))
|
4265
4471
|
end
|
4266
4472
|
fan.addToThermalZone(zone)
|
4267
4473
|
fans << fan
|
4268
4474
|
end
|
4269
4475
|
|
4270
4476
|
return fans
|
4271
|
-
|
4272
4477
|
end
|
4273
4478
|
|
4274
4479
|
# Adds a zone ventilation design flow rate to each zone.
|
@@ -4289,14 +4494,14 @@ class OpenStudio::Model::Model
|
|
4289
4494
|
thermal_zones.each do |zone|
|
4290
4495
|
ventilation = OpenStudio::Model::ZoneVentilationDesignFlowRate.new(self)
|
4291
4496
|
ventilation.setName("#{zone.name} Ventilation")
|
4292
|
-
ventilation.setSchedule(
|
4497
|
+
ventilation.setSchedule(add_schedule(availability_sch_name))
|
4293
4498
|
ventilation.setVentilationType(ventilation_type)
|
4294
4499
|
|
4295
4500
|
ventilation.setAirChangesperHour(0)
|
4296
4501
|
ventilation.setTemperatureTermCoefficient(0)
|
4297
4502
|
|
4298
4503
|
if ventilation_type == 'Exhaust'
|
4299
|
-
ventilation.setDesignFlowRateCalculationMethod(
|
4504
|
+
ventilation.setDesignFlowRateCalculationMethod('Flow/Zone')
|
4300
4505
|
ventilation.setDesignFlowRate(flow_rate)
|
4301
4506
|
ventilation.setFanPressureRise(31.1361206455786)
|
4302
4507
|
ventilation.setFanTotalEfficiency(0.51)
|
@@ -4306,7 +4511,7 @@ class OpenStudio::Model::Model
|
|
4306
4511
|
ventilation.setMaximumIndoorTemperature(100)
|
4307
4512
|
ventilation.setDeltaTemperature(-100)
|
4308
4513
|
elsif ventilation_type == 'Natural'
|
4309
|
-
ventilation.setDesignFlowRateCalculationMethod(
|
4514
|
+
ventilation.setDesignFlowRateCalculationMethod('Flow/Zone')
|
4310
4515
|
ventilation.setDesignFlowRate(flow_rate)
|
4311
4516
|
ventilation.setFanPressureRise(0)
|
4312
4517
|
ventilation.setFanTotalEfficiency(1)
|
@@ -4316,7 +4521,7 @@ class OpenStudio::Model::Model
|
|
4316
4521
|
ventilation.setMaximumIndoorTemperature(29.4444452244559)
|
4317
4522
|
ventilation.setDeltaTemperature(-100)
|
4318
4523
|
elsif ventilation_type == 'Intake'
|
4319
|
-
ventilation.setDesignFlowRateCalculationMethod(
|
4524
|
+
ventilation.setDesignFlowRateCalculationMethod('Flow/Area')
|
4320
4525
|
ventilation.setFlowRateperZoneFloorArea(flow_rate)
|
4321
4526
|
ventilation.setFanPressureRise(49.8)
|
4322
4527
|
ventilation.setFanTotalEfficiency(0.53625)
|
@@ -4334,7 +4539,6 @@ class OpenStudio::Model::Model
|
|
4334
4539
|
end
|
4335
4540
|
|
4336
4541
|
return zone_ventilations
|
4337
|
-
|
4338
4542
|
end
|
4339
4543
|
|
4340
4544
|
# Adds a single refrigerated case connected to a rack composed
|
@@ -4347,20 +4551,20 @@ class OpenStudio::Model::Model
|
|
4347
4551
|
# @todo Set compressor properties since prototypes use simple
|
4348
4552
|
# refrigeration rack instead of detailed
|
4349
4553
|
# @todo fix latent case credit curve setter
|
4350
|
-
def add_refrigeration(
|
4351
|
-
|
4352
|
-
|
4353
|
-
|
4354
|
-
|
4355
|
-
|
4356
|
-
|
4357
|
-
|
4358
|
-
|
4359
|
-
|
4360
|
-
|
4361
|
-
|
4362
|
-
|
4363
|
-
|
4554
|
+
def add_refrigeration(template,
|
4555
|
+
case_type,
|
4556
|
+
cooling_capacity_per_length,
|
4557
|
+
length,
|
4558
|
+
evaporator_fan_pwr_per_length,
|
4559
|
+
lighting_per_length,
|
4560
|
+
lighting_sch_name,
|
4561
|
+
defrost_pwr_per_length,
|
4562
|
+
restocking_sch_name,
|
4563
|
+
cop,
|
4564
|
+
cop_f_of_t_curve_name,
|
4565
|
+
condenser_fan_pwr,
|
4566
|
+
condenser_fan_pwr_curve_name,
|
4567
|
+
thermal_zone)
|
4364
4568
|
|
4365
4569
|
# Default properties based on the case type
|
4366
4570
|
# case_type = 'Walkin Freezer', 'Display Case'
|
@@ -4372,12 +4576,12 @@ class OpenStudio::Model::Model
|
|
4372
4576
|
latent_case_credit_curve_name = nil
|
4373
4577
|
defrost_type = nil
|
4374
4578
|
if case_type == 'Walkin Freezer'
|
4375
|
-
case_temp = OpenStudio.convert(-9.4,'F','C').get
|
4579
|
+
case_temp = OpenStudio.convert(-9.4, 'F', 'C').get
|
4376
4580
|
latent_heat_ratio = 0.1
|
4377
4581
|
runtime_fraction = 0.4
|
4378
4582
|
fraction_antisweat_to_case = 0.0
|
4379
4583
|
under_case_return_air_fraction = 0.0
|
4380
|
-
case
|
4584
|
+
case template
|
4381
4585
|
when '90.1-2004', '90.1-2007', '90.1-2010', '90.1-2013'
|
4382
4586
|
latent_case_credit_curve_name = 'Single Shelf Horizontal Latent Energy Multiplier_After2004'
|
4383
4587
|
when 'DOE Ref Pre-1980', 'DOE Ref 1980-2004'
|
@@ -4385,7 +4589,7 @@ class OpenStudio::Model::Model
|
|
4385
4589
|
end
|
4386
4590
|
defrost_type = 'Electric'
|
4387
4591
|
elsif case_type == 'Display Case'
|
4388
|
-
case_temp = OpenStudio.convert(35.6,'F','C').get
|
4592
|
+
case_temp = OpenStudio.convert(35.6, 'F', 'C').get
|
4389
4593
|
latent_heat_ratio = 0.08
|
4390
4594
|
runtime_fraction = 0.85
|
4391
4595
|
fraction_antisweat_to_case = 0.2
|
@@ -4394,44 +4598,44 @@ class OpenStudio::Model::Model
|
|
4394
4598
|
defrost_type = 'None'
|
4395
4599
|
end
|
4396
4600
|
|
4397
|
-
OpenStudio
|
4601
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Started Adding Refrigeration System')
|
4398
4602
|
|
4399
4603
|
# Defrost schedule
|
4400
4604
|
defrost_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
4401
|
-
defrost_sch.setName(
|
4402
|
-
defrost_sch.defaultDaySchedule.setName(
|
4605
|
+
defrost_sch.setName('Refrigeration Defrost Schedule')
|
4606
|
+
defrost_sch.defaultDaySchedule.setName('Refrigeration Defrost Schedule Default')
|
4403
4607
|
if case_type == 'Walkin Freezer'
|
4404
|
-
defrost_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,11,0,0), 0)
|
4405
|
-
defrost_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,11,20,0), 1)
|
4406
|
-
defrost_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,23,0,0), 0)
|
4407
|
-
defrost_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,23,20,0), 1)
|
4408
|
-
defrost_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0), 0)
|
4608
|
+
defrost_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 11, 0, 0), 0)
|
4609
|
+
defrost_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 11, 20, 0), 1)
|
4610
|
+
defrost_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 23, 0, 0), 0)
|
4611
|
+
defrost_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 23, 20, 0), 1)
|
4612
|
+
defrost_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0)
|
4409
4613
|
elsif case_type == 'Display Case'
|
4410
|
-
defrost_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,23,20,0), 0)
|
4614
|
+
defrost_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 23, 20, 0), 0)
|
4411
4615
|
end
|
4412
4616
|
|
4413
4617
|
# Dripdown schedule
|
4414
4618
|
defrost_dripdown_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
4415
|
-
defrost_dripdown_sch.setName(
|
4416
|
-
defrost_dripdown_sch.defaultDaySchedule.setName(
|
4417
|
-
defrost_dripdown_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,11,0,0), 0)
|
4418
|
-
defrost_dripdown_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,11,30,0), 1)
|
4419
|
-
defrost_dripdown_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,23,0,0), 0)
|
4420
|
-
defrost_dripdown_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,23,30,0), 1)
|
4421
|
-
defrost_dripdown_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0), 0)
|
4619
|
+
defrost_dripdown_sch.setName('Refrigeration Defrost DripDown Schedule')
|
4620
|
+
defrost_dripdown_sch.defaultDaySchedule.setName('Refrigeration Defrost DripDown Schedule Default')
|
4621
|
+
defrost_dripdown_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 11, 0, 0), 0)
|
4622
|
+
defrost_dripdown_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 11, 30, 0), 1)
|
4623
|
+
defrost_dripdown_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 23, 0, 0), 0)
|
4624
|
+
defrost_dripdown_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 23, 30, 0), 1)
|
4625
|
+
defrost_dripdown_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0)
|
4422
4626
|
|
4423
4627
|
# Case Credit Schedule
|
4424
4628
|
case_credit_sch = OpenStudio::Model::ScheduleRuleset.new(self)
|
4425
|
-
case_credit_sch.setName(
|
4426
|
-
case_credit_sch.defaultDaySchedule.setName(
|
4427
|
-
case_credit_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,7,0,0), 0.2)
|
4428
|
-
case_credit_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,21,0,0), 0.4)
|
4429
|
-
case_credit_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0,24,0,0), 0.2)
|
4629
|
+
case_credit_sch.setName('Refrigeration Case Credit Schedule')
|
4630
|
+
case_credit_sch.defaultDaySchedule.setName('Refrigeration Case Credit Schedule Default')
|
4631
|
+
case_credit_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 7, 0, 0), 0.2)
|
4632
|
+
case_credit_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 21, 0, 0), 0.4)
|
4633
|
+
case_credit_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0.2)
|
4430
4634
|
|
4431
4635
|
# Case
|
4432
4636
|
ref_case = OpenStudio::Model::RefrigerationCase.new(self, defrost_sch)
|
4433
4637
|
ref_case.setName("#{thermal_zone.name} #{case_type}")
|
4434
|
-
ref_case.setAvailabilitySchedule(
|
4638
|
+
ref_case.setAvailabilitySchedule(alwaysOnDiscreteSchedule)
|
4435
4639
|
ref_case.setThermalZone(thermal_zone)
|
4436
4640
|
ref_case.setRatedTotalCoolingCapacityperUnitLength(cooling_capacity_per_length)
|
4437
4641
|
ref_case.setCaseLength(length)
|
@@ -4440,7 +4644,7 @@ class OpenStudio::Model::Model
|
|
4440
4644
|
ref_case.setOperatingCaseFanPowerperUnitLength(evaporator_fan_pwr_per_length)
|
4441
4645
|
ref_case.setStandardCaseLightingPowerperUnitLength(lighting_per_length)
|
4442
4646
|
ref_case.resetInstalledCaseLightingPowerperUnitLength
|
4443
|
-
ref_case.setCaseLightingSchedule(
|
4647
|
+
ref_case.setCaseLightingSchedule(add_schedule(lighting_sch_name))
|
4444
4648
|
ref_case.setHumidityatZeroAntiSweatHeaterEnergy(0)
|
4445
4649
|
unless defrost_type == 'None'
|
4446
4650
|
ref_case.setCaseDefrostType('Electric')
|
@@ -4450,14 +4654,14 @@ class OpenStudio::Model::Model
|
|
4450
4654
|
ref_case.setUnderCaseHVACReturnAirFraction(under_case_return_air_fraction)
|
4451
4655
|
ref_case.setFractionofAntiSweatHeaterEnergytoCase(fraction_antisweat_to_case)
|
4452
4656
|
ref_case.resetDesignEvaporatorTemperatureorBrineInletTemperature
|
4453
|
-
ref_case.setRatedAmbientTemperature(OpenStudio.convert(75,'F','C').get)
|
4657
|
+
ref_case.setRatedAmbientTemperature(OpenStudio.convert(75, 'F', 'C').get)
|
4454
4658
|
ref_case.setRatedLatentHeatRatio(latent_heat_ratio)
|
4455
4659
|
ref_case.setRatedRuntimeFraction(runtime_fraction)
|
4456
|
-
#TODO enable ref_case.setLatentCaseCreditCurve(self.add_curve(latent_case_credit_curve_name))
|
4457
|
-
ref_case.setLatentCaseCreditCurve(
|
4660
|
+
# TODO: enable ref_case.setLatentCaseCreditCurve(self.add_curve(latent_case_credit_curve_name))
|
4661
|
+
ref_case.setLatentCaseCreditCurve(add_curve(latent_case_credit_curve_name))
|
4458
4662
|
ref_case.setCaseHeight(0)
|
4459
4663
|
# TODO: setRefrigeratedCaseRestockingSchedule is not working
|
4460
|
-
ref_case.setRefrigeratedCaseRestockingSchedule(
|
4664
|
+
ref_case.setRefrigeratedCaseRestockingSchedule(add_schedule(restocking_sch_name))
|
4461
4665
|
if case_type == 'Walkin Freezer'
|
4462
4666
|
ref_case.setCaseCreditFractionSchedule(case_credit_sch)
|
4463
4667
|
end
|
@@ -4478,10 +4682,8 @@ class OpenStudio::Model::Model
|
|
4478
4682
|
ref_sys.setRefrigerationCondenser(condenser)
|
4479
4683
|
ref_sys.setSuctionPipingZone(thermal_zone)
|
4480
4684
|
|
4481
|
-
OpenStudio
|
4685
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Finished adding Refrigeration System')
|
4482
4686
|
|
4483
4687
|
return true
|
4484
|
-
|
4485
4688
|
end
|
4486
|
-
|
4487
4689
|
end
|