Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // EnergyPlus Headers
49 : #include <EnergyPlus/Data/EnergyPlusData.hh>
50 : #include <EnergyPlus/DataContaminantBalance.hh>
51 : #include <EnergyPlus/DataEnvironment.hh>
52 : #include <EnergyPlus/DataHeatBalance.hh>
53 : #include <EnergyPlus/DataSizing.hh>
54 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
55 : #include <EnergyPlus/DataZoneEquipment.hh>
56 : #include <EnergyPlus/Psychrometrics.hh>
57 : #include <EnergyPlus/ScheduleManager.hh>
58 :
59 : namespace EnergyPlus::DataSizing {
60 :
61 : // MODULE INFORMATION:
62 : // AUTHOR Fred Buhl
63 : // DATE WRITTEN December 2000
64 :
65 : // PURPOSE OF THIS MODULE:
66 : // This data-only module contains type definitions and variables
67 : // associated with HVAC system design flow rates, temperatures and
68 : // capacities. This data is available to the HVAC component modules
69 : // for their self sizing calculations.
70 :
71 : // days; includes effects of user multiplier
72 : // and user set flows)
73 : // of user input multiplier and flows
74 : // all design days, calculated only)
75 : // using user input system flow rates.
76 : // before applying user input sys flow rates.
77 :
78 785533 : Real64 TermUnitSizingData::applyTermUnitSizingCoolFlow(Real64 const coolFlowWithOA, // Cooling flow rate with MinOA limit applied
79 : Real64 const coolFlowNoOA // Cooling flow rate without MinOA limit applied
80 : )
81 : {
82 : // Apply DesignSpecification:AirTerminal:Sizing to cooling flow (could be vol flow or mass flow)
83 785533 : Real64 coolFlowRatio = 1.0;
84 785533 : if (this->SpecDesCoolSATRatio > 0.0) {
85 785533 : coolFlowRatio = this->SpecDesSensCoolingFrac / this->SpecDesCoolSATRatio;
86 : } else {
87 0 : coolFlowRatio = this->SpecDesSensCoolingFrac;
88 : }
89 785533 : Real64 adjustedFlow = coolFlowNoOA * coolFlowRatio + (coolFlowWithOA - coolFlowNoOA) * this->SpecMinOAFrac;
90 785533 : return adjustedFlow;
91 : }
92 :
93 785533 : Real64 TermUnitSizingData::applyTermUnitSizingHeatFlow(Real64 const heatFlowWithOA, // Heating flow rate with MinOA limit applied
94 : Real64 const heatFlowNoOA // Heating flow rate without MinOA limit applied
95 : )
96 : {
97 : // Apply DesignSpecification:AirTerminal:Sizing to heating flow (could be vol flow or mass flow)
98 785533 : Real64 heatFlowRatio = 1.0;
99 785533 : if (this->SpecDesHeatSATRatio > 0.0) {
100 785533 : heatFlowRatio = this->SpecDesSensHeatingFrac / this->SpecDesHeatSATRatio;
101 : } else {
102 0 : heatFlowRatio = this->SpecDesSensHeatingFrac;
103 : }
104 785533 : Real64 adjustedFlow = heatFlowNoOA * heatFlowRatio + (heatFlowWithOA - heatFlowNoOA) * this->SpecMinOAFrac;
105 785533 : return adjustedFlow;
106 : }
107 :
108 110 : void ZoneSizingData::scaleZoneCooling(Real64 const ratio // Scaling ratio
109 : )
110 : {
111 : // Apply scaling ratio to TermUnitFinalZoneSizing cooling flow and load
112 110 : this->DesCoolVolFlow = this->DesCoolVolFlow * ratio;
113 110 : this->DesCoolMassFlow = this->DesCoolMassFlow * ratio;
114 110 : this->DesCoolLoad = this->DesCoolLoad * ratio;
115 110 : this->CoolFlowSeq = this->CoolFlowSeq * ratio;
116 110 : this->CoolLoadSeq = this->CoolLoadSeq * ratio;
117 110 : }
118 :
119 64 : void ZoneSizingData::scaleZoneHeating(Real64 const ratio // Scaling ratio
120 : )
121 : {
122 : // Apply scaling ratio to TermUnitFinalZoneSizing heating flow and load
123 64 : this->DesHeatVolFlow = this->DesHeatVolFlow * ratio;
124 64 : this->DesHeatMassFlow = this->DesHeatMassFlow * ratio;
125 64 : this->DesHeatLoad = this->DesHeatLoad * ratio;
126 64 : this->HeatFlowSeq = this->HeatFlowSeq * ratio;
127 64 : this->HeatLoadSeq = this->HeatLoadSeq * ratio;
128 64 : }
129 :
130 828 : void ZoneSizingData::zeroMemberData()
131 : {
132 828 : if (!allocated(this->DOASSupMassFlowSeq)) return;
133 690 : std::fill(this->DOASSupMassFlowSeq.begin(), this->DOASSupMassFlowSeq.end(), 0.0);
134 690 : std::fill(this->DOASHeatLoadSeq.begin(), this->DOASHeatLoadSeq.end(), 0.0);
135 690 : std::fill(this->DOASCoolLoadSeq.begin(), this->DOASCoolLoadSeq.end(), 0.0);
136 690 : std::fill(this->DOASHeatAddSeq.begin(), this->DOASHeatAddSeq.end(), 0.0);
137 690 : std::fill(this->DOASLatAddSeq.begin(), this->DOASLatAddSeq.end(), 0.0);
138 690 : std::fill(this->DOASSupTempSeq.begin(), this->DOASSupTempSeq.end(), 0.0);
139 690 : std::fill(this->DOASSupHumRatSeq.begin(), this->DOASSupHumRatSeq.end(), 0.0);
140 690 : std::fill(this->DOASTotCoolLoadSeq.begin(), this->DOASTotCoolLoadSeq.end(), 0.0);
141 690 : std::fill(this->HeatFlowSeq.begin(), this->HeatFlowSeq.end(), 0.0);
142 690 : std::fill(this->HeatFlowSeqNoOA.begin(), this->HeatFlowSeqNoOA.end(), 0.0);
143 690 : std::fill(this->HeatLoadSeq.begin(), this->HeatLoadSeq.end(), 0.0);
144 690 : std::fill(this->HeatZoneTempSeq.begin(), this->HeatZoneTempSeq.end(), 0.0);
145 690 : std::fill(this->DesHeatSetPtSeq.begin(), this->DesHeatSetPtSeq.end(), 0.0);
146 690 : std::fill(this->HeatOutTempSeq.begin(), this->HeatOutTempSeq.end(), 0.0);
147 690 : std::fill(this->HeatZoneRetTempSeq.begin(), this->HeatZoneRetTempSeq.end(), 0.0);
148 690 : std::fill(this->HeatTstatTempSeq.begin(), this->HeatTstatTempSeq.end(), 0.0);
149 690 : std::fill(this->HeatZoneHumRatSeq.begin(), this->HeatZoneHumRatSeq.end(), 0.0);
150 690 : std::fill(this->HeatOutHumRatSeq.begin(), this->HeatOutHumRatSeq.end(), 0.0);
151 690 : std::fill(this->CoolFlowSeq.begin(), this->CoolFlowSeq.end(), 0.0);
152 690 : std::fill(this->CoolFlowSeqNoOA.begin(), this->CoolFlowSeqNoOA.end(), 0.0);
153 690 : std::fill(this->CoolLoadSeq.begin(), this->CoolLoadSeq.end(), 0.0);
154 690 : std::fill(this->CoolZoneTempSeq.begin(), this->CoolZoneTempSeq.end(), 0.0);
155 690 : std::fill(this->DesCoolSetPtSeq.begin(), this->DesCoolSetPtSeq.end(), 0.0);
156 690 : std::fill(this->CoolOutTempSeq.begin(), this->CoolOutTempSeq.end(), 0.0);
157 690 : std::fill(this->CoolZoneRetTempSeq.begin(), this->CoolZoneRetTempSeq.end(), 0.0);
158 690 : std::fill(this->CoolTstatTempSeq.begin(), this->CoolTstatTempSeq.end(), 0.0);
159 690 : std::fill(this->CoolZoneHumRatSeq.begin(), this->CoolZoneHumRatSeq.end(), 0.0);
160 690 : std::fill(this->CoolOutHumRatSeq.begin(), this->CoolOutHumRatSeq.end(), 0.0);
161 690 : std::fill(this->HeatLoadNoDOASSeq.begin(), this->HeatLoadNoDOASSeq.end(), 0.0);
162 690 : std::fill(this->CoolLoadNoDOASSeq.begin(), this->CoolLoadNoDOASSeq.end(), 0.0);
163 690 : std::fill(this->LatentHeatLoadSeq.begin(), this->LatentHeatLoadSeq.end(), 0.0);
164 690 : std::fill(this->LatentCoolLoadSeq.begin(), this->LatentCoolLoadSeq.end(), 0.0);
165 690 : std::fill(this->HeatLatentLoadNoDOASSeq.begin(), this->HeatLatentLoadNoDOASSeq.end(), 0.0);
166 690 : std::fill(this->CoolLatentLoadNoDOASSeq.begin(), this->CoolLatentLoadNoDOASSeq.end(), 0.0);
167 690 : std::fill(this->LatentCoolFlowSeq.begin(), this->LatentCoolFlowSeq.end(), 0.0);
168 690 : std::fill(this->LatentHeatFlowSeq.begin(), this->LatentHeatFlowSeq.end(), 0.0);
169 :
170 690 : this->CoolDesDay = ""; // name of a sensible cooling design day
171 690 : this->HeatDesDay = ""; // name of a sensible heating design day
172 690 : this->CoolNoDOASDesDay = ""; // name of a sensible cooling design day without DOAS
173 690 : this->HeatNoDOASDesDay = ""; // name of a sensible heating design day without DOAS
174 690 : this->LatCoolDesDay = ""; // name of a latent cooling design day
175 690 : this->LatHeatDesDay = ""; // name of a latent heating design day
176 690 : this->LatCoolNoDOASDesDay = ""; // name of a latent cooling design day without DOAS
177 690 : this->LatHeatNoDOASDesDay = ""; // name of a latent heating design day without DOAS
178 :
179 690 : this->DesHeatMassFlow = 0.0; // zone design heating air mass flow rate [kg/s]
180 690 : this->DesCoolMassFlow = 0.0; // zone design cooling air mass flow rate [kg/s]
181 690 : this->DesHeatLoad = 0.0; // zone design heating load [W]
182 690 : this->DesCoolLoad = 0.0; // zone design cooling load [W]
183 690 : this->DesHeatDens = 0.0; // zone design heating air density [kg/m3]
184 690 : this->DesCoolDens = 0.0; // zone design cooling air density [kg/m3]
185 690 : this->DesHeatVolFlow = 0.0; // zone design heating air volume flow rate [m3/s]
186 690 : this->DesCoolVolFlow = 0.0; // zone design cooling air volume flow rate [m3/s]
187 690 : this->DesHeatVolFlowMax = 0.0; // zone design heating maximum air volume flow rate [m3/s]
188 690 : this->DesCoolVolFlowMin = 0.0; // zone design cooling minimum air volume flow rate [m3/s]
189 690 : this->DesHeatCoilInTemp = 0.0; // zone heating coil design air inlet temperature [C]
190 690 : this->DesCoolCoilInTemp = 0.0; // zone cooling coil design air inlet temperature [C]
191 690 : this->DesHeatCoilInHumRat = 0.0; // zone heating coil design air inlet humidity ratio [kg/kg]
192 690 : this->DesCoolCoilInHumRat = 0.0; // zone cooling coil design air inlet humidity ratio [kg/kg]
193 690 : this->DesHeatCoilInTempTU = 0.0; // zone heating coil design air inlet temperature (supply air)([C]
194 690 : this->DesCoolCoilInTempTU = 0.0; // zone cooling coil design air inlet temperature (supply air)[C]
195 690 : this->DesHeatCoilInHumRatTU = 0.0; // zone heating coil design air inlet humidity ratio
196 690 : this->DesCoolCoilInHumRatTU = 0.0; // zone cooling coil design air inlet humidity ratio
197 690 : this->HeatMassFlow = 0.0; // current zone heating air mass flow rate (HVAC time step)
198 690 : this->CoolMassFlow = 0.0; // current zone cooling air mass flow rate (HVAC time step)
199 690 : this->HeatLoad = 0.0; // current zone heating load (HVAC time step)
200 690 : this->CoolLoad = 0.0; // current zone heating load (HVAC time step)
201 690 : this->HeatZoneTemp = 0.0; // current zone temperature (heating, time step)
202 690 : this->HeatOutTemp = 0.0; // current outdoor temperature (heating, time step)
203 690 : this->HeatZoneRetTemp = 0.0; // current zone return temperature (heating, time step)
204 690 : this->HeatTstatTemp = 0.0; // current zone thermostat temperature (heating, time step)
205 690 : this->CoolZoneTemp = 0.0; // current zone temperature (cooling, time step)
206 690 : this->CoolOutTemp = 0.0; // current Outdoor temperature (cooling, time step)
207 690 : this->CoolZoneRetTemp = 0.0; // current zone return temperature (cooling, time step)
208 690 : this->CoolTstatTemp = 0.0; // current zone thermostat temperature (cooling, time step)
209 690 : this->HeatZoneHumRat = 0.0; // current zone humidity ratio (heating, time step)
210 690 : this->CoolZoneHumRat = 0.0; // current zone humidity ratio (cooling, time step)
211 690 : this->HeatOutHumRat = 0.0; // current outdoor humidity ratio (heating, time step)
212 690 : this->CoolOutHumRat = 0.0; // current outdoor humidity ratio (cooling, time step)
213 690 : this->ZoneTempAtHeatPeak = 0.0; // zone temp at max heating [C]
214 690 : this->ZoneRetTempAtHeatPeak = 0.0; // zone return temp at max heating [C]
215 690 : this->OutTempAtHeatPeak = 0.0; // outdoor temperature at max heating [C]
216 690 : this->ZoneTempAtCoolPeak = 0.0; // zone temp at max cooling [C]
217 690 : this->ZoneRetTempAtCoolPeak = 0.0; // zone return temp at max cooling [C]
218 690 : this->OutTempAtCoolPeak = 0.0; // outdoor temperature at max cooling [C]
219 690 : this->ZoneHumRatAtHeatPeak = 0.0; // zone humidity ratio at max heating [kg/kg]
220 690 : this->ZoneHumRatAtCoolPeak = 0.0; // zone humidity ratio at max cooling [kg/kg]
221 690 : this->OutHumRatAtHeatPeak = 0.0; // outdoor humidity at max heating [kg/kg]
222 690 : this->OutHumRatAtCoolPeak = 0.0; // outdoor humidity at max cooling [kg/kg]
223 690 : this->TimeStepNumAtHeatMax = 0; // time step number (in day) at Heating peak
224 690 : this->TimeStepNumAtCoolMax = 0; // time step number (in day) at cooling peak
225 690 : this->HeatDDNum = 0; // design day index of design day causing heating peak
226 690 : this->CoolDDNum = 0; // design day index of design day causing heating peak
227 690 : this->LatentHeatDDNum = 0; // design day index of design day causing heating peak
228 690 : this->LatentCoolDDNum = 0; // design day index of design day causing cooling peak
229 690 : this->LatentHeatNoDOASDDNum = 0; // design day index of design day causing latent heating peak without DOAS
230 690 : this->LatentCoolNoDOASDDNum = 0; // design day index of design day causing latent cooling peak without DOAS
231 690 : this->cHeatDDDate = ""; // date of design day causing heating peak
232 690 : this->cCoolDDDate = ""; // date of design day causing cooling peak
233 690 : this->cLatentHeatDDDate = ""; // date of design day causing heating peak
234 690 : this->cLatentCoolDDDate = ""; // date of design day causing cooling peak
235 690 : this->DOASHeatLoad = 0.0; // current heating load from DOAS supply air [W]
236 690 : this->DOASCoolLoad = 0.0; // current cooling load from DOAS supply air [W]
237 690 : this->DOASSupMassFlow = 0.0; // current mass flow rate of DOAS supply air [kg/s]
238 690 : this->DOASSupTemp = 0.0; // current DOAS supply air temperature [C]
239 690 : this->DOASSupHumRat = 0.0; // current DOAS supply air humidity ratio [kgWater/kgDryAir]
240 690 : this->DOASTotCoolLoad = 0.0; // current total cooling load imposed by DOAS supply air [W]
241 690 : this->HeatLoadNoDOAS = 0.0; // current zone heating load no DOAS (HVAC time step)
242 690 : this->CoolLoadNoDOAS = 0.0; // current zone heating load no DOAS (HVAC time step)
243 690 : this->HeatLatentLoad = 0.0; // current zone humidification load (HVAC time step)
244 690 : this->CoolLatentLoad = 0.0; // current zone dehumidification load (HVAC time step)
245 690 : this->HeatLatentLoadNoDOAS = 0.0; // current zone humidification load without DOAS (HVAC time step)
246 690 : this->CoolLatentLoadNoDOAS = 0.0; // current zone dehumidification load without DOAS (HVAC time step)
247 690 : this->ZoneHeatLatentMassFlow = 0.0; // current mass flow rate required to meet humidification load [kg/s]
248 690 : this->ZoneCoolLatentMassFlow = 0.0; // current mass flow rate required to meet dehumidification load [kg/s]
249 690 : this->ZoneHeatLatentVolFlow = 0.0; // current volume flow rate required to meet humidification load [m3/s]
250 690 : this->ZoneCoolLatentVolFlow = 0.0; // current volume flow rate required to meet dehumidification load [m3/s]
251 690 : this->DesHeatLoadNoDOAS = 0.0; // zone design heating load without DOAS [W]
252 690 : this->DesCoolLoadNoDOAS = 0.0; // zone design cooling load without DOAS [W]
253 690 : this->DesLatentHeatLoad = 0.0; // current zone humidification load (HVAC time step)
254 690 : this->DesLatentCoolLoad = 0.0; // current zone dehumidification load (HVAC time step)
255 690 : this->DesLatentHeatLoadNoDOAS = 0.0; // current zone humidification load no DOAS (HVAC time step)
256 690 : this->DesLatentCoolLoadNoDOAS = 0.0; // current zone dehumidification load no DOAS (HVAC time step)
257 690 : this->DesLatentHeatMassFlow = 0.0; // current mass flow rate required to meet humidification load [kg/s]
258 690 : this->DesLatentCoolMassFlow = 0.0; // current mass flow rate required to meet dehumidification load [kg/s]
259 690 : this->DesLatentHeatVolFlow = 0.0; // current volume flow rate required to meet humidification load [m3/s]
260 690 : this->DesLatentCoolVolFlow = 0.0; // current volume flow rate required to meet dehumidification load [m3/s]
261 690 : this->DesLatentHeatCoilInTemp = 0.0; // zone heating coil design air inlet temperature [C]
262 690 : this->DesLatentCoolCoilInTemp = 0.0; // zone cooling coil design air inlet temperature [C]
263 690 : this->DesLatentHeatCoilInHumRat = 0.0; // zone heating coil design air inlet humidity ratio [kg/kg]
264 690 : this->DesLatentCoolCoilInHumRat = 0.0; // zone cooling coil design air inlet humidity ratio [kg/kg]
265 690 : this->TimeStepNumAtLatentHeatMax = 0; // time step number (in day) at latent heating peak
266 690 : this->TimeStepNumAtLatentCoolMax = 0; // time step number (in day) at latent cooling peak
267 690 : this->TimeStepNumAtLatentHeatNoDOASMax = 0; // time step number (in day) at latent heating peak without DOAS
268 690 : this->TimeStepNumAtLatentCoolNoDOASMax = 0; // time step number (in day) at latent cooling peak without DOAS
269 690 : this->OutTempAtLatentCoolPeak = 0.0; // outdoor temperature at max latent cooling [C]
270 690 : this->OutHumRatAtLatentCoolPeak = 0.0; // outdoor humrat at max latent cooling [C]
271 690 : this->OutTempAtLatentHeatPeak = 0.0; // outdoor temperature at max latent heating [C]
272 690 : this->OutHumRatAtLatentHeatPeak = 0.0; // outdoor humrat at max latent heating [C]
273 690 : this->ZoneRetTempAtLatentCoolPeak = 0.0; // zone return temp at max cooling [C]
274 690 : this->ZoneRetTempAtLatentHeatPeak = 0.0; // zone return temp at max heating [C]
275 : }
276 :
277 20954 : void ZoneSizingData::allocateMemberArrays(int const numOfTimeStepInDay)
278 : {
279 20954 : this->HeatFlowSeq.dimension(numOfTimeStepInDay, 0.0);
280 20954 : this->CoolFlowSeq.dimension(numOfTimeStepInDay, 0.0);
281 20954 : this->HeatFlowSeqNoOA.dimension(numOfTimeStepInDay, 0.0);
282 20954 : this->CoolFlowSeqNoOA.dimension(numOfTimeStepInDay, 0.0);
283 20954 : this->HeatLoadSeq.dimension(numOfTimeStepInDay, 0.0);
284 20954 : this->CoolLoadSeq.dimension(numOfTimeStepInDay, 0.0);
285 20954 : this->HeatZoneTempSeq.dimension(numOfTimeStepInDay, 0.0);
286 20954 : this->DesHeatSetPtSeq.dimension(numOfTimeStepInDay, 0.0);
287 20954 : this->CoolZoneTempSeq.dimension(numOfTimeStepInDay, 0.0);
288 20954 : this->DesCoolSetPtSeq.dimension(numOfTimeStepInDay, 0.0);
289 20954 : this->HeatOutTempSeq.dimension(numOfTimeStepInDay, 0.0);
290 20954 : this->CoolOutTempSeq.dimension(numOfTimeStepInDay, 0.0);
291 20954 : this->HeatZoneRetTempSeq.dimension(numOfTimeStepInDay, 0.0);
292 20954 : this->HeatTstatTempSeq.dimension(numOfTimeStepInDay, 0.0);
293 20954 : this->CoolZoneRetTempSeq.dimension(numOfTimeStepInDay, 0.0);
294 20954 : this->CoolTstatTempSeq.dimension(numOfTimeStepInDay, 0.0);
295 20954 : this->HeatZoneHumRatSeq.dimension(numOfTimeStepInDay, 0.0);
296 20954 : this->CoolZoneHumRatSeq.dimension(numOfTimeStepInDay, 0.0);
297 20954 : this->HeatOutHumRatSeq.dimension(numOfTimeStepInDay, 0.0);
298 20954 : this->CoolOutHumRatSeq.dimension(numOfTimeStepInDay, 0.0);
299 20954 : this->DOASHeatLoadSeq.dimension(numOfTimeStepInDay, 0.0);
300 20954 : this->DOASCoolLoadSeq.dimension(numOfTimeStepInDay, 0.0);
301 20954 : this->DOASHeatAddSeq.dimension(numOfTimeStepInDay, 0.0);
302 20954 : this->DOASLatAddSeq.dimension(numOfTimeStepInDay, 0.0);
303 20954 : this->DOASSupMassFlowSeq.dimension(numOfTimeStepInDay, 0.0);
304 20954 : this->DOASSupTempSeq.dimension(numOfTimeStepInDay, 0.0);
305 20954 : this->DOASSupHumRatSeq.dimension(numOfTimeStepInDay, 0.0);
306 20954 : this->DOASTotCoolLoadSeq.dimension(numOfTimeStepInDay, 0.0);
307 20954 : this->HeatLoadNoDOASSeq.dimension(numOfTimeStepInDay, 0.0);
308 20954 : this->CoolLoadNoDOASSeq.dimension(numOfTimeStepInDay, 0.0);
309 20954 : this->LatentHeatLoadSeq.dimension(numOfTimeStepInDay, 0.0);
310 20954 : this->LatentCoolLoadSeq.dimension(numOfTimeStepInDay, 0.0);
311 20954 : this->HeatLatentLoadNoDOASSeq.dimension(numOfTimeStepInDay, 0.0);
312 20954 : this->CoolLatentLoadNoDOASSeq.dimension(numOfTimeStepInDay, 0.0);
313 20954 : this->LatentCoolFlowSeq.dimension(numOfTimeStepInDay, 0.0);
314 20954 : this->LatentHeatFlowSeq.dimension(numOfTimeStepInDay, 0.0);
315 20954 : }
316 :
317 1325 : void resetHVACSizingGlobals(EnergyPlusData &state,
318 : int const curZoneEqNum,
319 : int const curSysNum,
320 : bool &firstPassFlag) // called in zone equipment Report function
321 : {
322 : // reset Data globals so that previously set variables are not used in other equipment models
323 1325 : state.dataSize->DataTotCapCurveIndex = 0;
324 1325 : state.dataSize->DataPltSizCoolNum = 0;
325 1325 : state.dataSize->DataPltSizHeatNum = 0;
326 1325 : state.dataSize->DataWaterLoopNum = 0;
327 1325 : state.dataSize->DataCoilNum = 0;
328 1325 : state.dataSize->DataFanOpMode = 0;
329 1325 : state.dataSize->DataCoilIsSuppHeater = false;
330 1325 : state.dataSize->DataIsDXCoil = false;
331 1325 : state.dataSize->DataAutosizable = true;
332 1325 : state.dataSize->DataEMSOverrideON = false;
333 1325 : state.dataSize->DataScalableSizingON = false;
334 1325 : state.dataSize->DataScalableCapSizingON = false;
335 1325 : state.dataSize->DataSysScalableFlowSizingON = false;
336 1325 : state.dataSize->DataSysScalableCapSizingON = false;
337 1325 : state.dataSize->DataDesAccountForFanHeat = true;
338 1325 : state.dataSize->DataDXCoolsLowSpeedsAutozize = false;
339 :
340 1325 : state.dataSize->DataDesInletWaterTemp = 0.0;
341 1325 : state.dataSize->DataDesInletAirHumRat = 0.0;
342 1325 : state.dataSize->DataDesInletAirTemp = 0.0;
343 1325 : state.dataSize->DataDesOutletAirTemp = 0.0;
344 1325 : state.dataSize->DataDesOutletAirHumRat = 0.0;
345 1325 : state.dataSize->DataCoolCoilCap = 0.0;
346 1325 : state.dataSize->DataFlowUsedForSizing = 0.0;
347 1325 : state.dataSize->DataAirFlowUsedForSizing = 0.0;
348 1325 : state.dataSize->DataWaterFlowUsedForSizing = 0.0;
349 1325 : state.dataSize->DataCapacityUsedForSizing = 0.0;
350 1325 : state.dataSize->DataDesignCoilCapacity = 0.0;
351 1325 : state.dataSize->DataHeatSizeRatio = 1.0;
352 1325 : state.dataSize->DataEMSOverride = 0.0;
353 1325 : state.dataSize->DataBypassFrac = 0.0;
354 1325 : state.dataSize->DataFracOfAutosizedCoolingAirflow = 1.0;
355 1325 : state.dataSize->DataFracOfAutosizedHeatingAirflow = 1.0;
356 1325 : state.dataSize->DataFlowPerCoolingCapacity = 0.0;
357 1325 : state.dataSize->DataFlowPerHeatingCapacity = 0.0;
358 1325 : state.dataSize->DataFracOfAutosizedCoolingCapacity = 1.0;
359 1325 : state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
360 1325 : state.dataSize->DataAutosizedCoolingCapacity = 0.0;
361 1325 : state.dataSize->DataAutosizedHeatingCapacity = 0.0;
362 1325 : state.dataSize->DataConstantUsedForSizing = 0.0;
363 1325 : state.dataSize->DataFractionUsedForSizing = 0.0;
364 1325 : state.dataSize->DataNonZoneNonAirloopValue = 0.0;
365 1325 : state.dataSize->DataZoneNumber = 0;
366 1325 : state.dataSize->DataFanEnumType = -1;
367 1325 : state.dataSize->DataFanIndex = -1;
368 1325 : state.dataSize->DataWaterCoilSizCoolDeltaT = 0.0;
369 1325 : state.dataSize->DataWaterCoilSizHeatDeltaT = 0.0;
370 1325 : state.dataSize->DataNomCapInpMeth = false;
371 1325 : state.dataSize->DataFanPlacement = ZoneFanPlacement::NotSet;
372 1325 : state.dataSize->DataDXSpeedNum = 0;
373 1325 : state.dataSize->DataCoilSizingAirInTemp = 0.0;
374 1325 : state.dataSize->DataCoilSizingAirInHumRat = 0.0;
375 1325 : state.dataSize->DataCoilSizingAirOutTemp = 0.0;
376 1325 : state.dataSize->DataCoilSizingAirOutHumRat = 0.0;
377 1325 : state.dataSize->DataCoolCoilType = -1;
378 1325 : state.dataSize->DataCoolCoilIndex = -1;
379 :
380 : // These zone specific sizing variables are set in zone equipment to use for sizing.
381 : // Reset to avoid chance that second zone equipment will size using these variables set by first zone equipment to be sized
382 1325 : if (curZoneEqNum > 0) {
383 :
384 568 : if (state.dataSize->ZoneEqSizing.size() == 0) {
385 0 : firstPassFlag = false;
386 0 : return;
387 : }
388 :
389 568 : auto &ZoneEqSizing = state.dataSize->ZoneEqSizing(curZoneEqNum);
390 568 : ZoneEqSizing.AirFlow = false;
391 568 : ZoneEqSizing.CoolingAirFlow = false;
392 568 : ZoneEqSizing.HeatingAirFlow = false;
393 568 : ZoneEqSizing.SystemAirFlow = false;
394 568 : ZoneEqSizing.Capacity = false;
395 568 : ZoneEqSizing.CoolingCapacity = false;
396 568 : ZoneEqSizing.HeatingCapacity = false;
397 568 : ZoneEqSizing.AirVolFlow = 0.0;
398 568 : ZoneEqSizing.MaxHWVolFlow = 0.0;
399 568 : ZoneEqSizing.MaxCWVolFlow = 0.0;
400 568 : ZoneEqSizing.OAVolFlow = 0.0;
401 568 : ZoneEqSizing.DesCoolingLoad = 0.0;
402 568 : ZoneEqSizing.DesHeatingLoad = 0.0;
403 568 : ZoneEqSizing.CoolingAirVolFlow = 0.0;
404 568 : ZoneEqSizing.HeatingAirVolFlow = 0.0;
405 568 : ZoneEqSizing.SystemAirVolFlow = 0.0;
406 568 : ZoneEqSizing.DesignSizeFromParent = false;
407 : }
408 :
409 1325 : if (curSysNum > 0) {
410 :
411 755 : if (state.dataSize->UnitarySysEqSizing.size() == 0) {
412 0 : firstPassFlag = false;
413 0 : return;
414 : }
415 :
416 755 : auto &UnitarySysEqSizing = state.dataSize->UnitarySysEqSizing(curSysNum);
417 755 : UnitarySysEqSizing.AirFlow = false;
418 755 : UnitarySysEqSizing.CoolingAirFlow = false;
419 755 : UnitarySysEqSizing.HeatingAirFlow = false;
420 755 : UnitarySysEqSizing.Capacity = false;
421 755 : UnitarySysEqSizing.CoolingCapacity = false;
422 755 : UnitarySysEqSizing.HeatingCapacity = false;
423 : }
424 :
425 1325 : firstPassFlag = false;
426 : }
427 :
428 323 : void GetCoilDesFlowT(EnergyPlusData &state,
429 : int SysNum, // central air system index
430 : Real64 CpAir, // specific heat to be used in calculations [J/kgC]
431 : Real64 &DesFlow, // returned design mass flow [kg/s]
432 : Real64 &DesExitTemp, // returned design coil exit temperature [kg/s]
433 : Real64 &DesExitHumRat // returned design coil exit humidity ratio [kg/kg]
434 : )
435 : {
436 : // FUNCTION INFORMATION:
437 : // AUTHOR Fred Buhl
438 : // DATE WRITTEN September 2014
439 :
440 : // PURPOSE OF THIS FUNCTION:
441 : // This function calculates the coil design air flow rate and exit temperature depending on the
442 : // cooling capacity control method
443 :
444 : // METHODOLOGY EMPLOYED:
445 : // energy and mass flow balance
446 :
447 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
448 323 : int TimeStepAtPeak = 0;
449 323 : Real64 ZoneCoolLoadSum = 0; // sum of zone cooling loads at the peak [W]
450 323 : Real64 AvgZoneTemp = 0; // average zone temperature [C]
451 :
452 323 : auto &finalSysSizing = state.dataSize->FinalSysSizing(SysNum);
453 323 : auto &sysSizPeakDDNum = state.dataSize->SysSizPeakDDNum(SysNum);
454 323 : auto &calcSysSizing = state.dataSize->CalcSysSizing(SysNum);
455 :
456 : int sysSizIndex =
457 323 : UtilityRoutines::FindItemInList(finalSysSizing.AirPriLoopName, state.dataSize->SysSizInput, &SystemSizingInputData::AirPriLoopName);
458 323 : if (sysSizIndex == 0) sysSizIndex = 1;
459 323 : auto &sysSizInput = state.dataSize->SysSizInput(sysSizIndex);
460 :
461 323 : if (sysSizPeakDDNum.SensCoolPeakDD > 0) {
462 323 : if (sysSizInput.coolingPeakLoad == PeakLoad::TotalCooling) {
463 5 : TimeStepAtPeak = sysSizPeakDDNum.TimeStepAtTotCoolPk(sysSizPeakDDNum.TotCoolPeakDD);
464 : } else {
465 318 : TimeStepAtPeak = sysSizPeakDDNum.TimeStepAtSensCoolPk(sysSizPeakDDNum.SensCoolPeakDD);
466 : }
467 : } else {
468 0 : if ((sysSizInput.CoolCapControl == CapacityControl::VT) || (sysSizInput.CoolCapControl == CapacityControl::Bypass)) {
469 0 : ShowWarningError(state,
470 0 : format("GetCoilDesFlow: AirLoopHVAC = {} has no time of peak cooling load for sizing.", sysSizInput.AirPriLoopName));
471 0 : ShowContinueError(state, "Using Central Cooling Capacity Control Method=VAV instead of Bypass or VT.");
472 0 : sysSizInput.CoolCapControl = CapacityControl::VAV;
473 : }
474 : }
475 :
476 323 : if (sysSizInput.CoolCapControl == CapacityControl::VAV) {
477 256 : DesExitTemp = finalSysSizing.CoolSupTemp;
478 256 : DesFlow = finalSysSizing.MassFlowAtCoolPeak / state.dataEnvrn->StdRhoAir;
479 256 : DesExitHumRat = finalSysSizing.CoolSupHumRat;
480 67 : } else if (sysSizInput.CoolCapControl == CapacityControl::OnOff) {
481 65 : DesExitTemp = finalSysSizing.CoolSupTemp;
482 65 : DesFlow = state.dataSize->DataAirFlowUsedForSizing;
483 65 : DesExitHumRat = finalSysSizing.CoolSupHumRat;
484 2 : } else if (sysSizInput.CoolCapControl == CapacityControl::VT) {
485 1 : ZoneCoolLoadSum = calcSysSizing.SumZoneCoolLoadSeq(TimeStepAtPeak);
486 1 : AvgZoneTemp = calcSysSizing.CoolZoneAvgTempSeq(TimeStepAtPeak);
487 1 : DesExitTemp =
488 1 : max(finalSysSizing.CoolSupTemp, AvgZoneTemp - ZoneCoolLoadSum / (state.dataEnvrn->StdRhoAir * CpAir * finalSysSizing.DesCoolVolFlow));
489 1 : DesFlow = finalSysSizing.DesCoolVolFlow;
490 1 : DesExitHumRat = Psychrometrics::PsyWFnTdbRhPb(state, DesExitTemp, 0.9, state.dataEnvrn->StdBaroPress, "GetCoilDesFlowT");
491 1 : } else if (sysSizInput.CoolCapControl == CapacityControl::Bypass) {
492 1 : ZoneCoolLoadSum = calcSysSizing.SumZoneCoolLoadSeq(TimeStepAtPeak);
493 1 : AvgZoneTemp = calcSysSizing.CoolZoneAvgTempSeq(TimeStepAtPeak);
494 1 : DesExitTemp = finalSysSizing.CoolSupTemp;
495 1 : if (calcSysSizing.MixTempAtCoolPeak > DesExitTemp) {
496 1 : Real64 AvgSupTemp = AvgZoneTemp - ZoneCoolLoadSum / (state.dataEnvrn->StdRhoAir * CpAir * finalSysSizing.DesCoolVolFlow);
497 2 : DesFlow = finalSysSizing.DesCoolVolFlow *
498 1 : max(0.0, min(1.0, ((calcSysSizing.MixTempAtCoolPeak - AvgSupTemp) / (calcSysSizing.MixTempAtCoolPeak - DesExitTemp))));
499 : } else {
500 0 : DesFlow = finalSysSizing.DesCoolVolFlow;
501 : }
502 1 : DesExitHumRat = Psychrometrics::PsyWFnTdbRhPb(state, DesExitTemp, 0.9, state.dataEnvrn->StdBaroPress, "GetCoilDesFlowT");
503 : }
504 323 : }
505 :
506 121056 : Real64 ZoneAirDistributionData::calculateEz(EnergyPlusData &state, int const ZoneNum) // Zone index
507 : {
508 121056 : Real64 zoneEz = 1.0;
509 : // Calc the zone supplied OA flow rate counting the zone air distribution effectiveness
510 : // First check whether the zone air distribution effectiveness schedule exists, if yes uses it;
511 : // otherwise uses the inputs of zone distribution effectiveness in cooling mode or heating mode
512 121056 : if (this->ZoneADEffSchPtr > 0) {
513 : // Get schedule value for the zone air distribution effectiveness
514 0 : zoneEz = ScheduleManager::GetCurrentScheduleValue(state, this->ZoneADEffSchPtr);
515 : } else {
516 121056 : Real64 zoneLoad = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).TotalOutputRequired;
517 :
518 : // Zone in cooling mode
519 121056 : if (zoneLoad < 0.0) zoneEz = this->ZoneADEffCooling;
520 :
521 : // Zone in heating mode
522 121056 : if (zoneLoad > 0.0) zoneEz = this->ZoneADEffHeating;
523 : }
524 121056 : if (zoneEz <= 0.0) {
525 : // Enforce defaults
526 0 : zoneEz = 1.0;
527 : }
528 121056 : return zoneEz;
529 : }
530 :
531 6023104 : Real64 calcDesignSpecificationOutdoorAir(EnergyPlusData &state,
532 : int const DSOAPtr, // Pointer to DesignSpecification:OutdoorAir object
533 : int const ActualZoneNum, // Zone index
534 : bool const UseOccSchFlag, // Zone occupancy schedule will be used instead of using total zone occupancy
535 : bool const UseMinOASchFlag, // Use min OA schedule in DesignSpecification:OutdoorAir object
536 : bool const PerPersonNotSet, // when calculation should not include occupants (e.g., dual duct)
537 : bool const MaxOAVolFlowFlag // TRUE when calculation uses occupancy schedule (e.g., dual duct)
538 : )
539 : {
540 6023104 : Real64 totOAFlowRate = 0.0;
541 6023104 : if (DSOAPtr == 0) return totOAFlowRate;
542 :
543 5690853 : auto &thisDSOA = state.dataSize->OARequirements(DSOAPtr);
544 :
545 5690853 : if (thisDSOA.numDSOA == 0) {
546 : // This is a simple DesignSpecification:OutdoorAir
547 5690617 : return thisDSOA.calcOAFlowRate(state, ActualZoneNum, UseOccSchFlag, UseMinOASchFlag, PerPersonNotSet, MaxOAVolFlowFlag);
548 : } else {
549 : // This is a DesignSpecification:OutdoorAir:SpaceList
550 708 : for (int dsoaCount = 1; dsoaCount <= thisDSOA.numDSOA; ++dsoaCount) {
551 944 : totOAFlowRate += state.dataSize->OARequirements(thisDSOA.dsoaIndexes(dsoaCount))
552 472 : .calcOAFlowRate(state,
553 : ActualZoneNum,
554 : UseOccSchFlag,
555 : UseMinOASchFlag,
556 : PerPersonNotSet,
557 : MaxOAVolFlowFlag,
558 472 : thisDSOA.dsoaSpaceIndexes(dsoaCount));
559 : }
560 236 : return totOAFlowRate;
561 : }
562 : }
563 :
564 3302 : Real64 OARequirementsData::desFlowPerZoneArea(EnergyPlusData &state,
565 : int const actualZoneNum // Zone index
566 : )
567 : {
568 3302 : Real64 desFlowPA = 0.0;
569 3302 : if (this->numDSOA == 0) {
570 : // This is a simple DesignSpecification:OutdoorAir
571 4293 : if (this->OAFlowMethod != OAFlowCalcMethod::PerPerson && this->OAFlowMethod != OAFlowCalcMethod::PerZone &&
572 992 : this->OAFlowMethod != OAFlowCalcMethod::ACH) {
573 992 : desFlowPA = this->OAFlowPerArea;
574 : }
575 : } else {
576 : // This is a DesignSpecification:OutdoorAir:SpaceList
577 1 : Real64 sumAreaOA = 0.0;
578 3 : for (int dsoaCount = 1; dsoaCount <= this->numDSOA; ++dsoaCount) {
579 2 : auto const &thisDSOA = state.dataSize->OARequirements(this->dsoaIndexes(dsoaCount));
580 4 : if (thisDSOA.OAFlowMethod != OAFlowCalcMethod::PerPerson && thisDSOA.OAFlowMethod != OAFlowCalcMethod::PerZone &&
581 2 : thisDSOA.OAFlowMethod != OAFlowCalcMethod::ACH) {
582 2 : Real64 spaceArea = state.dataHeatBal->space(this->dsoaSpaceIndexes(dsoaCount)).floorArea;
583 2 : sumAreaOA += thisDSOA.OAFlowPerArea * spaceArea;
584 : }
585 : }
586 1 : if (state.dataHeatBal->Zone(actualZoneNum).FloorArea) {
587 1 : desFlowPA = sumAreaOA / state.dataHeatBal->Zone(actualZoneNum).FloorArea;
588 : }
589 : }
590 3302 : return desFlowPA;
591 : }
592 :
593 3302 : Real64 OARequirementsData::desFlowPerZonePerson(EnergyPlusData &state,
594 : int const actualZoneNum // Zone index
595 : )
596 : {
597 3302 : Real64 desFlowPP = 0.0;
598 3302 : if (this->numDSOA == 0) {
599 : // This is a simple DesignSpecification:OutdoorAir
600 5131 : if (this->OAFlowMethod != OAFlowCalcMethod::PerArea && this->OAFlowMethod != OAFlowCalcMethod::PerZone &&
601 1830 : this->OAFlowMethod != OAFlowCalcMethod::ACH) {
602 1830 : desFlowPP = this->OAFlowPerPerson;
603 : }
604 : } else {
605 : // This is a DesignSpecification:OutdoorAir:SpaceList
606 1 : Real64 sumPeopleOA = 0.0;
607 3 : for (int dsoaCount = 1; dsoaCount <= this->numDSOA; ++dsoaCount) {
608 2 : auto const &thisDSOA = state.dataSize->OARequirements(this->dsoaIndexes(dsoaCount));
609 4 : if (thisDSOA.OAFlowMethod != OAFlowCalcMethod::PerArea && thisDSOA.OAFlowMethod != OAFlowCalcMethod::PerZone &&
610 2 : thisDSOA.OAFlowMethod != OAFlowCalcMethod::ACH) {
611 2 : Real64 spacePeople = state.dataHeatBal->space(this->dsoaSpaceIndexes(dsoaCount)).totOccupants;
612 2 : sumPeopleOA += thisDSOA.OAFlowPerPerson * spacePeople;
613 : }
614 : }
615 1 : if (state.dataHeatBal->Zone(actualZoneNum).TotOccupants > 0.0) {
616 1 : desFlowPP = sumPeopleOA / state.dataHeatBal->Zone(actualZoneNum).TotOccupants;
617 : }
618 : }
619 3302 : return desFlowPP;
620 : }
621 :
622 5691089 : Real64 OARequirementsData::calcOAFlowRate(EnergyPlusData &state,
623 : int const ActualZoneNum, // Zone index
624 : bool const UseOccSchFlag, // Zone occupancy schedule will be used instead of using total zone occupancy
625 : bool const UseMinOASchFlag, // Use min OA schedule in DesignSpecification:OutdoorAir object
626 : bool const PerPersonNotSet, // when calculation should not include occupants (e.g., dual duct)
627 : bool const MaxOAVolFlowFlag, // TRUE when calculation uses occupancy schedule (e.g., dual duct)
628 : int const spaceNum // Space index (if applicable)
629 : )
630 : {
631 :
632 : // FUNCTION INFORMATION:
633 : // AUTHOR Richard Raustad, FSEC
634 : // DATE WRITTEN October 2012
635 :
636 : // PURPOSE OF THIS FUNCTION:
637 : // This function returns the air volume flow rate based on DesignSpecification:OutdoorAir object.
638 :
639 : // METHODOLOGY EMPLOYED:
640 : // User inputs and zone index allows calculation of outdoor air quantity.
641 : // Sizing does not use occupancy or min OA schedule and will call with flags set to FALSE
642 : // Ventilation Rate Procedure uses occupancy schedule based on user input.
643 :
644 : // Return value
645 : Real64 OAVolumeFlowRate; // Return value for calculated outdoor air volume flow rate [m3/s]
646 :
647 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
648 : Real64 DSOAFlowPeople; // Outdoor air volume flow rate based on occupancy (m3/s)
649 : Real64 DSOAFlowPerZone; // Outdoor air volume flow rate (m3/s)
650 : Real64 DSOAFlowPerArea; // Outdoor air volume flow rate based on zone floor area (m3/s)
651 : Real64 DSOAFlowACH; // Outdoor air volume flow rate based on air changes per hour (m3/s)
652 : Real64 ZoneOAPeople; // Zone OA flow rate based on number of occupants [m3/s]
653 : Real64 ZoneOAArea; // Zone OA flow rate based on space floor area [m3/s]
654 : Real64 ZoneOAMin; // Minimum Zone OA flow rate when the zone is unoccupied (i.e. ZoneOAPeople = 0)
655 : // used for "ProportionalControl" System outdoor air method
656 : Real64 ZoneOAMax; // Maximum Zone OA flow rate (ZoneOAPeople + ZoneOAArea)
657 : // used for "ProportionalControl" System outdoor air method
658 : Real64 ZoneMaxCO2; // Breathing-zone CO2 concentration
659 : Real64 ZoneMinCO2; // Minimum CO2 concentration in zone
660 : Real64 ZoneContamControllerSched; // Schedule value for ZoneControl:ContaminantController
661 : Real64 CO2PeopleGeneration; // CO2 generation from people at design level
662 :
663 5691089 : OAVolumeFlowRate = 0.0;
664 :
665 5691089 : auto &thisZone = state.dataHeatBal->Zone(ActualZoneNum);
666 5691089 : Real64 floorArea = 0.0;
667 5691089 : Real64 volume = 0.0;
668 5691089 : Real64 nomTotOccupants = 0.0;
669 5691089 : Real64 curNumOccupants = 0.0;
670 5691089 : Real64 maxOccupants = 0.0;
671 5691089 : if (spaceNum > 0) {
672 472 : floorArea = state.dataHeatBal->space(spaceNum).floorArea;
673 : // TODO MJW: For now just proportion space volume by floor area
674 472 : if (thisZone.FloorArea > 0.0) {
675 472 : volume = thisZone.Volume * state.dataHeatBal->space(spaceNum).floorArea / thisZone.FloorArea;
676 : } else {
677 0 : volume = 0.0;
678 : }
679 472 : nomTotOccupants = state.dataHeatBal->space(spaceNum).totOccupants;
680 472 : curNumOccupants = state.dataHeatBal->spaceIntGain(spaceNum).NOFOCC;
681 472 : maxOccupants = state.dataHeatBal->space(spaceNum).maxOccupants;
682 : } else {
683 5690617 : floorArea = thisZone.FloorArea;
684 5690617 : volume = thisZone.Volume;
685 5690617 : nomTotOccupants = thisZone.TotOccupants;
686 5690617 : curNumOccupants = state.dataHeatBal->ZoneIntGain(ActualZoneNum).NOFOCC;
687 5690617 : maxOccupants = thisZone.maxOccupants;
688 : }
689 :
690 5691089 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::IAQProcedure && this->myEnvrnFlag) {
691 5 : if (!state.dataContaminantBalance->Contaminant.CO2Simulation) {
692 0 : ShowSevereError(state,
693 0 : "DesignSpecification:OutdoorAir=\"" + this->Name +
694 : R"(" valid Outdoor Air Method =" IndoorAirQualityProcedure" requires CO2 simulation.)");
695 0 : ShowContinueError(state, "The choice must be Yes for the field Carbon Dioxide Concentration in ZoneAirContaminantBalance");
696 0 : ShowFatalError(state, "CalcDesignSpecificationOutdoorAir: Errors found in input. Preceding condition(s) cause termination.");
697 : }
698 5 : this->myEnvrnFlag = false;
699 : }
700 5691089 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCOccSch && this->myEnvrnFlag) {
701 2 : if (!state.dataContaminantBalance->Contaminant.CO2Simulation) {
702 0 : ShowSevereError(state,
703 0 : "DesignSpecification:OutdoorAir=\"" + this->Name +
704 : R"(" valid Outdoor Air Method =" ProportionalControlBasedOnDesignOccupancy" requires CO2 simulation.)");
705 0 : ShowContinueError(state, "The choice must be Yes for the field Carbon Dioxide Concentration in ZoneAirContaminantBalance");
706 0 : ShowFatalError(state, "CalcDesignSpecificationOutdoorAir: Errors found in input. Preceding condition(s) cause termination.");
707 : }
708 2 : this->myEnvrnFlag = false;
709 : }
710 5691089 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCDesOcc && this->myEnvrnFlag) {
711 3 : if (!state.dataContaminantBalance->Contaminant.CO2Simulation) {
712 0 : ShowSevereError(state,
713 0 : "DesignSpecification:OutdoorAir=\"" + this->Name +
714 : R"(" valid Outdoor Air Method =" ProportionalControlBasedOnOccupancySchedule" requires CO2 simulation.)");
715 0 : ShowContinueError(state, "The choice must be Yes for the field Carbon Dioxide Concentration in ZoneAirContaminantBalance");
716 0 : ShowFatalError(state, "CalcDesignSpecificationOutdoorAir: Errors found in input. Preceding condition(s) cause termination.");
717 : }
718 3 : this->myEnvrnFlag = false;
719 : }
720 :
721 : // Calculate people outdoor air flow rate as needed
722 5691089 : switch (this->OAFlowMethod) {
723 2730414 : case OAFlowCalcMethod::PerPerson:
724 : case OAFlowCalcMethod::Sum:
725 : case OAFlowCalcMethod::Max: {
726 2730414 : if (UseOccSchFlag) {
727 2717450 : if (MaxOAVolFlowFlag) {
728 : // OAPerPersonMode == PerPersonDCVByCurrentLevel (UseOccSchFlag = TRUE)
729 : // for dual duct, get max people according to max schedule value when requesting MaxOAFlow
730 6 : DSOAFlowPeople = maxOccupants * this->OAFlowPerPerson;
731 : } else {
732 2717444 : DSOAFlowPeople = curNumOccupants * this->OAFlowPerPerson;
733 : }
734 : } else {
735 12964 : if (MaxOAVolFlowFlag) {
736 : // OAPerPersonMode == PerPersonByDesignLevel (UseOccSchFlag = FALSE)
737 : // use total people when requesting MaxOAFlow
738 0 : DSOAFlowPeople = nomTotOccupants * this->OAFlowPerPerson;
739 : } else {
740 12964 : DSOAFlowPeople = nomTotOccupants * this->OAFlowPerPerson;
741 : }
742 : }
743 2730414 : if (PerPersonNotSet) DSOAFlowPeople = 0.0; // for Dual Duct if Per Person Ventilation Rate Mode is not entered
744 2730414 : } break;
745 2960675 : default: {
746 2960675 : DSOAFlowPeople = 0.0;
747 2960675 : } break;
748 : }
749 :
750 : // Calculate minimum outdoor air flow rate
751 5691089 : switch (this->OAFlowMethod) {
752 1426492 : case OAFlowCalcMethod::PerPerson: {
753 : // Multiplied by occupancy
754 1426492 : OAVolumeFlowRate = DSOAFlowPeople;
755 1426492 : } break;
756 2490756 : case OAFlowCalcMethod::PerZone: {
757 : // User input
758 2490756 : OAVolumeFlowRate = this->OAFlowPerZone;
759 2490756 : } break;
760 189191 : case OAFlowCalcMethod::PerArea: {
761 : // Multiplied by zone floor area
762 189191 : OAVolumeFlowRate = this->OAFlowPerArea * floorArea;
763 189191 : } break;
764 0 : case OAFlowCalcMethod::ACH: {
765 : // Multiplied by zone volume
766 0 : OAVolumeFlowRate = this->OAFlowACH * volume / 3600.0;
767 0 : } break;
768 1303922 : case OAFlowCalcMethod::Sum:
769 : case OAFlowCalcMethod::Max: {
770 : // Use sum or max of per person and the following
771 1303922 : DSOAFlowPerZone = this->OAFlowPerZone;
772 1303922 : DSOAFlowPerArea = this->OAFlowPerArea * floorArea;
773 1303922 : DSOAFlowACH = this->OAFlowACH * volume / 3600.0;
774 1303922 : if (this->OAFlowMethod == OAFlowCalcMethod::Max) {
775 821 : OAVolumeFlowRate = max(DSOAFlowPeople, DSOAFlowPerZone, DSOAFlowPerArea, DSOAFlowACH);
776 : } else {
777 1303101 : OAVolumeFlowRate = DSOAFlowPeople + DSOAFlowPerZone + DSOAFlowPerArea + DSOAFlowACH;
778 : }
779 1303922 : } break;
780 113054 : case DataSizing::OAFlowCalcMethod::IAQProcedure: {
781 113054 : if (state.dataGlobal->DoingSizing) {
782 10 : DSOAFlowPeople = nomTotOccupants * this->OAFlowPerPerson;
783 10 : DSOAFlowPerZone = this->OAFlowPerZone;
784 10 : DSOAFlowPerArea = this->OAFlowPerArea * floorArea;
785 10 : DSOAFlowACH = this->OAFlowACH * volume / 3600.0;
786 10 : OAVolumeFlowRate = DSOAFlowPeople + DSOAFlowPerZone + DSOAFlowPerArea + DSOAFlowACH;
787 : } else {
788 113044 : OAVolumeFlowRate = state.dataContaminantBalance->ZoneSysContDemand(ActualZoneNum).OutputRequiredToCO2SP / state.dataEnvrn->StdRhoAir;
789 : }
790 113054 : } break;
791 167674 : case DataSizing::OAFlowCalcMethod::PCOccSch:
792 : case DataSizing::OAFlowCalcMethod::PCDesOcc: {
793 167674 : ZoneOAPeople = 0.0;
794 167674 : if (this->OAFlowMethod != DataSizing::OAFlowCalcMethod::PCDesOcc) {
795 59087 : ZoneOAPeople = curNumOccupants * thisZone.Multiplier * thisZone.ListMultiplier * this->OAFlowPerPerson;
796 : } else {
797 108587 : ZoneOAPeople = nomTotOccupants * thisZone.Multiplier * thisZone.ListMultiplier * this->OAFlowPerPerson;
798 108587 : CO2PeopleGeneration = 0.0;
799 108587 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCDesOcc) {
800 : // Accumulate CO2 generation from people at design occupancy and current activity level
801 651522 : for (int PeopleNum = 1; PeopleNum <= state.dataHeatBal->TotPeople; ++PeopleNum) {
802 542935 : if (spaceNum > 0) {
803 0 : if (state.dataHeatBal->People(PeopleNum).spaceIndex != spaceNum) continue;
804 : } else {
805 542935 : if (state.dataHeatBal->People(PeopleNum).ZonePtr != ActualZoneNum) continue;
806 : }
807 217174 : CO2PeopleGeneration += state.dataHeatBal->People(PeopleNum).NumberOfPeople * state.dataHeatBal->People(PeopleNum).CO2RateFactor *
808 108587 : ScheduleManager::GetCurrentScheduleValue(state, state.dataHeatBal->People(PeopleNum).ActivityLevelPtr);
809 : }
810 : }
811 : }
812 167674 : ZoneOAArea = floorArea * thisZone.Multiplier * thisZone.ListMultiplier * this->OAFlowPerArea;
813 167674 : ZoneOAMin = ZoneOAArea;
814 167674 : ZoneOAMax = (ZoneOAArea + ZoneOAPeople);
815 167674 : if (thisZone.ZoneContamControllerSchedIndex > 0.0) {
816 : // Check the availability schedule value for ZoneControl:ContaminantController
817 167674 : ZoneContamControllerSched = ScheduleManager::GetCurrentScheduleValue(state, thisZone.ZoneContamControllerSchedIndex);
818 167674 : if (ZoneContamControllerSched > 0.0) {
819 167674 : if (ZoneOAPeople > 0.0) {
820 140461 : if (state.dataContaminantBalance->ZoneCO2GainFromPeople(ActualZoneNum) > 0.0) {
821 84665 : if (thisZone.ZoneMinCO2SchedIndex > 0.0) {
822 : // Take the schedule value of "Minimum Carbon Dioxide Concentration Schedule Name"
823 : // in the ZoneControl:ContaminantController
824 0 : ZoneMinCO2 = ScheduleManager::GetCurrentScheduleValue(state, thisZone.ZoneMinCO2SchedIndex);
825 : } else {
826 84665 : ZoneMinCO2 = state.dataContaminantBalance->OutdoorCO2;
827 : }
828 :
829 : // Calculate zone maximum target CO2 concentration in PPM
830 84665 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCDesOcc) {
831 105582 : ZoneMaxCO2 = state.dataContaminantBalance->OutdoorCO2 +
832 52791 : (CO2PeopleGeneration * thisZone.Multiplier * thisZone.ListMultiplier * 1.0e6) / ZoneOAMax;
833 : } else {
834 31874 : ZoneMaxCO2 =
835 95622 : state.dataContaminantBalance->OutdoorCO2 + (state.dataContaminantBalance->ZoneCO2GainFromPeople(ActualZoneNum) *
836 63748 : thisZone.Multiplier * thisZone.ListMultiplier * 1.0e6) /
837 : ZoneOAMax;
838 : }
839 :
840 84665 : if (ZoneMaxCO2 <= ZoneMinCO2) {
841 0 : ++this->CO2MaxMinLimitErrorCount;
842 0 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCOccSch) {
843 0 : if (this->CO2MaxMinLimitErrorCount < 2) {
844 0 : ShowSevereError(state,
845 0 : format("CalcDesignSpecificationOutdoorAir DesignSpecification:OutdoorAir = \"{}\".", this->Name));
846 0 : ShowContinueError(
847 : state,
848 0 : format("For System Outdoor Air Method = ProportionalControlBasedOnOccupancySchedule, maximum target "
849 : "CO2 concentration ({:.2R}), is not greater than minimum target CO2 concentration ({:.2R}).",
850 : ZoneMaxCO2,
851 0 : ZoneMinCO2));
852 0 : ShowContinueError(state,
853 : "\"ProportionalControlBasedOnOccupancySchedule\" will not be modeled. Default "
854 : "\"Flow/Person+Flow/Area\" will be modeled. Simulation continues...");
855 0 : ShowContinueErrorTimeStamp(state, "");
856 : } else {
857 0 : ShowRecurringWarningErrorAtEnd(
858 : state,
859 0 : format("DesignSpecification:OutdoorAir = \"{}\", For System Outdoor Air Method = "
860 : "ProportionalControlBasedOnOccupancySchedule, maximum target CO2 concentration is not greater than "
861 : "minimum target CO2 concentration. Error continues...",
862 0 : this->Name),
863 : this->CO2MaxMinLimitErrorIndex);
864 : }
865 : }
866 0 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCDesOcc) {
867 0 : if (this->CO2MaxMinLimitErrorCount < 2) {
868 0 : ShowSevereError(state,
869 0 : format("CalcDesignSpecificationOutdoorAir DesignSpecification:OutdoorAir = \"{}\".", this->Name));
870 0 : ShowContinueError(
871 : state,
872 0 : format("For System Outdoor Air Method = ProportionalControlBasedOnDesignOccupancy, maximum target "
873 : "CO2 concentration ({:.2R}), is not greater than minimum target CO2 concentration ({:.2R}).",
874 : ZoneMaxCO2,
875 0 : ZoneMinCO2));
876 0 : ShowContinueError(state,
877 : "\"ProportionalControlBasedOnDesignOccupancy\" will not be modeled. Default "
878 : "\"Flow/Person+Flow/Area\" will be modeled. Simulation continues...");
879 0 : ShowContinueErrorTimeStamp(state, "");
880 : } else {
881 0 : ShowRecurringWarningErrorAtEnd(
882 : state,
883 0 : format("DesignSpecification:OutdoorAir = \"{}\", For System Outdoor Air Method = "
884 : "ProportionalControlBasedOnDesignOccupancy, maximum target CO2 concentration is not greater than "
885 : "minimum target CO2 concentration. Error continues...",
886 0 : this->Name),
887 : this->CO2MaxMinLimitErrorIndex);
888 : }
889 : }
890 :
891 0 : OAVolumeFlowRate = ZoneOAMax;
892 : } else {
893 :
894 84665 : if (state.dataContaminantBalance->ZoneAirCO2(ActualZoneNum) <= ZoneMinCO2) {
895 : // Zone air CO2 concentration is less than minimum zone CO2 concentration, set the Zone OA flow rate to
896 : // minimum Zone OA flow rate when the zone is unoccupied
897 18 : OAVolumeFlowRate = ZoneOAMin;
898 84647 : } else if (state.dataContaminantBalance->ZoneAirCO2(ActualZoneNum) >= ZoneMaxCO2) {
899 : // Zone air CO2 concentration is greater than maximum zone CO2 concentration, set the Zone OA flow rate to
900 : // maximum Zone OA flow rate (i.e. ZoneOAArea + ZoneOAPeople)
901 22782 : OAVolumeFlowRate = ZoneOAMax;
902 : } else {
903 : // Zone air CO2 concentration is between maximum and minimum limits of zone CO2 concentration,
904 : // set Zone OA flow rate by proportionally adjusting between ZoneOAMin and ZoneOAMax
905 61865 : OAVolumeFlowRate =
906 123730 : ZoneOAMin + (ZoneOAMax - ZoneOAMin) * ((state.dataContaminantBalance->ZoneAirCO2(ActualZoneNum) - ZoneMinCO2) /
907 61865 : (ZoneMaxCO2 - ZoneMinCO2));
908 : }
909 : }
910 : } else {
911 55796 : if (state.dataGlobal->DisplayExtraWarnings) {
912 0 : ++this->CO2GainErrorCount;
913 0 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCOccSch) {
914 0 : if (this->CO2GainErrorCount < 2) {
915 0 : ShowSevereError(state,
916 0 : format("CalcDesignSpecificationOutdoorAir DesignSpecification:OutdoorAir = \"{}\".", this->Name));
917 0 : ShowContinueError(state,
918 0 : format("For System Outdoor Air Method = ProportionalControlBasedOnOccupancySchedule, CO2 "
919 : "generation from people is not greater than zero. Occurs in Zone =\"{}\". ",
920 0 : thisZone.Name));
921 0 : ShowContinueError(state,
922 : "\"ProportionalControlBasedOnOccupancySchedule\" will not be modeled. Default "
923 : "\"Flow/Person+Flow/Area\" will be modeled. Simulation continues...");
924 0 : ShowContinueErrorTimeStamp(state, "");
925 : } else {
926 0 : ShowRecurringWarningErrorAtEnd(state,
927 0 : format("DesignSpecification:OutdoorAir = \"{}\", For System Outdoor Air Method = "
928 : "ProportionalControlBasedOnOccupancySchedule, CO2 generation from people "
929 : "is not greater than zero. Error continues...",
930 0 : this->Name),
931 : this->CO2GainErrorIndex);
932 : }
933 : }
934 0 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCDesOcc) {
935 0 : if (this->CO2GainErrorCount < 2) {
936 0 : ShowSevereError(state,
937 0 : format("CalcDesignSpecificationOutdoorAir DesignSpecification:OutdoorAir = \"{}\".", this->Name));
938 0 : ShowContinueError(state,
939 0 : format("For System Outdoor Air Method = ProportionalControlBasedOnDesignOccupancy, CO2 "
940 : "generation from people is not greater than zero. Occurs in Zone =\"{}\". ",
941 0 : thisZone.Name));
942 0 : ShowContinueError(state,
943 : "\"ProportionalControlBasedOnDesignOccupancy\" will not be modeled. Default "
944 : "\"Flow/Person+Flow/Area\" will be modeled. Simulation continues...");
945 0 : ShowContinueErrorTimeStamp(state, "");
946 : } else {
947 0 : ShowRecurringWarningErrorAtEnd(state,
948 0 : format("DesignSpecification:OutdoorAir = \"{}\", For System Outdoor Air Method = "
949 : "ProportionalControlBasedOnDesignOccupancy, CO2 generation from people is "
950 : "not greater than zero. Error continues...",
951 0 : this->Name),
952 : this->CO2GainErrorIndex);
953 : }
954 : }
955 : }
956 55796 : OAVolumeFlowRate = ZoneOAMax;
957 : }
958 : } else {
959 : // ZoneOAPeople is less than or equal to zero
960 27213 : OAVolumeFlowRate = ZoneOAMax;
961 : }
962 : } else {
963 : // ZoneControl:ContaminantController is scheduled off (not available)
964 0 : OAVolumeFlowRate = ZoneOAMax;
965 : }
966 : } else {
967 : // "Carbon Dioxide Control Availability Schedule" for ZoneControl:ContaminantController not found
968 0 : OAVolumeFlowRate = ZoneOAMax;
969 : }
970 167674 : } break;
971 0 : default: {
972 : // Will never get here
973 0 : OAVolumeFlowRate = 0.0;
974 0 : } break;
975 : }
976 :
977 : // Apply zone multipliers and zone list multipliers
978 : // TODO MJW: this looks like it's double-counting the multipliers
979 5691089 : OAVolumeFlowRate *= thisZone.Multiplier * thisZone.ListMultiplier;
980 :
981 : // Apply schedule as needed. Sizing does not use schedule.
982 5691089 : if (this->OAFlowFracSchPtr > 0 && UseMinOASchFlag) {
983 400351 : if (MaxOAVolFlowFlag) {
984 11 : OAVolumeFlowRate *= ScheduleManager::GetScheduleMaxValue(state, this->OAFlowFracSchPtr);
985 : } else {
986 400340 : OAVolumeFlowRate *= ScheduleManager::GetCurrentScheduleValue(state, this->OAFlowFracSchPtr);
987 : }
988 : }
989 :
990 5691089 : return OAVolumeFlowRate;
991 : }
992 :
993 2313 : } // namespace EnergyPlus::DataSizing
|