Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, 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 : #include <EnergyPlus/SizingManager.hh>
59 :
60 : namespace EnergyPlus::DataSizing {
61 :
62 : // MODULE INFORMATION:
63 : // AUTHOR Fred Buhl
64 : // DATE WRITTEN December 2000
65 :
66 : // PURPOSE OF THIS MODULE:
67 : // This data-only module contains type definitions and variables
68 : // associated with HVAC system design flow rates, temperatures and
69 : // capacities. This data is available to the HVAC component modules
70 : // for their self sizing calculations.
71 :
72 : // days; includes effects of user multiplier
73 : // and user set flows)
74 : // of user input multiplier and flows
75 : // all design days, calculated only)
76 : // using user input system flow rates.
77 : // before applying user input sys flow rates.
78 :
79 10220 : Real64 TermUnitSizingData::applyTermUnitSizingCoolFlow(Real64 const coolFlowWithOA, // Cooling flow rate with MinOA limit applied
80 : Real64 const coolFlowNoOA // Cooling flow rate without MinOA limit applied
81 : )
82 : {
83 : // Apply DesignSpecification:AirTerminal:Sizing to cooling flow (could be vol flow or mass flow)
84 10220 : Real64 coolFlowRatio = 1.0;
85 10220 : if (this->SpecDesCoolSATRatio > 0.0) {
86 10220 : coolFlowRatio = this->SpecDesSensCoolingFrac / this->SpecDesCoolSATRatio;
87 : } else {
88 0 : coolFlowRatio = this->SpecDesSensCoolingFrac;
89 : }
90 10220 : Real64 adjustedFlow = coolFlowNoOA * coolFlowRatio + (coolFlowWithOA - coolFlowNoOA) * this->SpecMinOAFrac;
91 10220 : return adjustedFlow;
92 : }
93 :
94 10220 : Real64 TermUnitSizingData::applyTermUnitSizingHeatFlow(Real64 const heatFlowWithOA, // Heating flow rate with MinOA limit applied
95 : Real64 const heatFlowNoOA // Heating flow rate without MinOA limit applied
96 : )
97 : {
98 : // Apply DesignSpecification:AirTerminal:Sizing to heating flow (could be vol flow or mass flow)
99 10220 : Real64 heatFlowRatio = 1.0;
100 10220 : if (this->SpecDesHeatSATRatio > 0.0) {
101 10220 : heatFlowRatio = this->SpecDesSensHeatingFrac / this->SpecDesHeatSATRatio;
102 : } else {
103 0 : heatFlowRatio = this->SpecDesSensHeatingFrac;
104 : }
105 10220 : Real64 adjustedFlow = heatFlowNoOA * heatFlowRatio + (heatFlowWithOA - heatFlowNoOA) * this->SpecMinOAFrac;
106 10220 : return adjustedFlow;
107 : }
108 :
109 25 : void TermUnitZoneSizingData::scaleZoneCooling(Real64 const ratio)
110 : {
111 : // Apply scaling ratio to TermUnitFinalZoneSizing cooling flow and load
112 25 : this->DesCoolVolFlow *= ratio;
113 25 : this->DesCoolMassFlow *= ratio;
114 25 : this->DesCoolLoad *= ratio;
115 2425 : for (auto &cfs : this->CoolFlowSeq) {
116 2400 : cfs *= ratio;
117 : }
118 25 : }
119 :
120 17 : void TermUnitZoneSizingData::scaleZoneHeating(Real64 const ratio)
121 : {
122 : // Apply scaling ratio to TermUnitFinalZoneSizing heating flow and load
123 17 : this->DesHeatVolFlow *= ratio;
124 17 : this->DesHeatMassFlow *= ratio;
125 17 : this->DesHeatLoad *= ratio;
126 1649 : for (auto &cfs : this->HeatFlowSeq) {
127 1632 : cfs *= ratio;
128 : }
129 17 : }
130 :
131 214 : void ZoneSizingData::zeroMemberData()
132 : {
133 214 : if (!allocated(this->DOASSupMassFlowSeq)) return;
134 204 : std::fill(this->DOASSupMassFlowSeq.begin(), this->DOASSupMassFlowSeq.end(), 0.0);
135 204 : std::fill(this->DOASHeatLoadSeq.begin(), this->DOASHeatLoadSeq.end(), 0.0);
136 204 : std::fill(this->DOASCoolLoadSeq.begin(), this->DOASCoolLoadSeq.end(), 0.0);
137 204 : std::fill(this->DOASHeatAddSeq.begin(), this->DOASHeatAddSeq.end(), 0.0);
138 204 : std::fill(this->DOASLatAddSeq.begin(), this->DOASLatAddSeq.end(), 0.0);
139 204 : std::fill(this->DOASSupTempSeq.begin(), this->DOASSupTempSeq.end(), 0.0);
140 204 : std::fill(this->DOASSupHumRatSeq.begin(), this->DOASSupHumRatSeq.end(), 0.0);
141 204 : std::fill(this->DOASTotCoolLoadSeq.begin(), this->DOASTotCoolLoadSeq.end(), 0.0);
142 204 : std::fill(this->HeatFlowSeq.begin(), this->HeatFlowSeq.end(), 0.0);
143 204 : std::fill(this->HeatFlowSeqNoOA.begin(), this->HeatFlowSeqNoOA.end(), 0.0);
144 204 : std::fill(this->HeatLoadSeq.begin(), this->HeatLoadSeq.end(), 0.0);
145 204 : std::fill(this->HeatZoneTempSeq.begin(), this->HeatZoneTempSeq.end(), 0.0);
146 204 : std::fill(this->DesHeatSetPtSeq.begin(), this->DesHeatSetPtSeq.end(), 0.0);
147 204 : std::fill(this->HeatOutTempSeq.begin(), this->HeatOutTempSeq.end(), 0.0);
148 204 : std::fill(this->HeatZoneRetTempSeq.begin(), this->HeatZoneRetTempSeq.end(), 0.0);
149 204 : std::fill(this->HeatTstatTempSeq.begin(), this->HeatTstatTempSeq.end(), 0.0);
150 204 : std::fill(this->HeatZoneHumRatSeq.begin(), this->HeatZoneHumRatSeq.end(), 0.0);
151 204 : std::fill(this->HeatOutHumRatSeq.begin(), this->HeatOutHumRatSeq.end(), 0.0);
152 204 : std::fill(this->CoolFlowSeq.begin(), this->CoolFlowSeq.end(), 0.0);
153 204 : std::fill(this->CoolFlowSeqNoOA.begin(), this->CoolFlowSeqNoOA.end(), 0.0);
154 204 : std::fill(this->CoolLoadSeq.begin(), this->CoolLoadSeq.end(), 0.0);
155 204 : std::fill(this->CoolZoneTempSeq.begin(), this->CoolZoneTempSeq.end(), 0.0);
156 204 : std::fill(this->DesCoolSetPtSeq.begin(), this->DesCoolSetPtSeq.end(), 0.0);
157 204 : std::fill(this->CoolOutTempSeq.begin(), this->CoolOutTempSeq.end(), 0.0);
158 204 : std::fill(this->CoolZoneRetTempSeq.begin(), this->CoolZoneRetTempSeq.end(), 0.0);
159 204 : std::fill(this->CoolTstatTempSeq.begin(), this->CoolTstatTempSeq.end(), 0.0);
160 204 : std::fill(this->CoolZoneHumRatSeq.begin(), this->CoolZoneHumRatSeq.end(), 0.0);
161 204 : std::fill(this->CoolOutHumRatSeq.begin(), this->CoolOutHumRatSeq.end(), 0.0);
162 204 : std::fill(this->HeatLoadNoDOASSeq.begin(), this->HeatLoadNoDOASSeq.end(), 0.0);
163 204 : std::fill(this->CoolLoadNoDOASSeq.begin(), this->CoolLoadNoDOASSeq.end(), 0.0);
164 204 : std::fill(this->LatentHeatLoadSeq.begin(), this->LatentHeatLoadSeq.end(), 0.0);
165 204 : std::fill(this->LatentCoolLoadSeq.begin(), this->LatentCoolLoadSeq.end(), 0.0);
166 204 : std::fill(this->HeatLatentLoadNoDOASSeq.begin(), this->HeatLatentLoadNoDOASSeq.end(), 0.0);
167 204 : std::fill(this->CoolLatentLoadNoDOASSeq.begin(), this->CoolLatentLoadNoDOASSeq.end(), 0.0);
168 204 : std::fill(this->LatentCoolFlowSeq.begin(), this->LatentCoolFlowSeq.end(), 0.0);
169 204 : std::fill(this->LatentHeatFlowSeq.begin(), this->LatentHeatFlowSeq.end(), 0.0);
170 :
171 204 : this->CoolDesDay = ""; // name of a sensible cooling design day
172 204 : this->HeatDesDay = ""; // name of a sensible heating design day
173 204 : this->CoolNoDOASDesDay = ""; // name of a sensible cooling design day without DOAS
174 204 : this->HeatNoDOASDesDay = ""; // name of a sensible heating design day without DOAS
175 204 : this->LatCoolDesDay = ""; // name of a latent cooling design day
176 204 : this->LatHeatDesDay = ""; // name of a latent heating design day
177 204 : this->LatCoolNoDOASDesDay = ""; // name of a latent cooling design day without DOAS
178 204 : this->LatHeatNoDOASDesDay = ""; // name of a latent heating design day without DOAS
179 :
180 204 : this->DesHeatMassFlow = 0.0; // zone design heating air mass flow rate [kg/s]
181 204 : this->DesCoolMassFlow = 0.0; // zone design cooling air mass flow rate [kg/s]
182 204 : this->DesHeatLoad = 0.0; // zone design heating load [W]
183 204 : this->DesCoolLoad = 0.0; // zone design cooling load [W]
184 204 : this->DesHeatDens = 0.0; // zone design heating air density [kg/m3]
185 204 : this->DesCoolDens = 0.0; // zone design cooling air density [kg/m3]
186 204 : this->DesHeatVolFlow = 0.0; // zone design heating air volume flow rate [m3/s]
187 204 : this->DesCoolVolFlow = 0.0; // zone design cooling air volume flow rate [m3/s]
188 204 : this->DesHeatVolFlowMax = 0.0; // zone design heating maximum air volume flow rate [m3/s]
189 204 : this->DesCoolVolFlowMin = 0.0; // zone design cooling minimum air volume flow rate [m3/s]
190 204 : this->DesHeatCoilInTemp = 0.0; // zone heating coil design air inlet temperature [C]
191 204 : this->DesCoolCoilInTemp = 0.0; // zone cooling coil design air inlet temperature [C]
192 204 : this->DesHeatCoilInHumRat = 0.0; // zone heating coil design air inlet humidity ratio [kg/kg]
193 204 : this->DesCoolCoilInHumRat = 0.0; // zone cooling coil design air inlet humidity ratio [kg/kg]
194 204 : this->DesHeatCoilInTempTU = 0.0; // zone heating coil design air inlet temperature (supply air)([C]
195 204 : this->DesCoolCoilInTempTU = 0.0; // zone cooling coil design air inlet temperature (supply air)[C]
196 204 : this->DesHeatCoilInHumRatTU = 0.0; // zone heating coil design air inlet humidity ratio
197 204 : this->DesCoolCoilInHumRatTU = 0.0; // zone cooling coil design air inlet humidity ratio
198 204 : this->HeatMassFlow = 0.0; // current zone heating air mass flow rate (HVAC time step)
199 204 : this->CoolMassFlow = 0.0; // current zone cooling air mass flow rate (HVAC time step)
200 204 : this->HeatLoad = 0.0; // current zone heating load (HVAC time step)
201 204 : this->CoolLoad = 0.0; // current zone heating load (HVAC time step)
202 204 : this->HeatZoneTemp = 0.0; // current zone temperature (heating, time step)
203 204 : this->HeatOutTemp = 0.0; // current outdoor temperature (heating, time step)
204 204 : this->HeatZoneRetTemp = 0.0; // current zone return temperature (heating, time step)
205 204 : this->HeatTstatTemp = 0.0; // current zone thermostat temperature (heating, time step)
206 204 : this->CoolZoneTemp = 0.0; // current zone temperature (cooling, time step)
207 204 : this->CoolOutTemp = 0.0; // current Outdoor temperature (cooling, time step)
208 204 : this->CoolZoneRetTemp = 0.0; // current zone return temperature (cooling, time step)
209 204 : this->CoolTstatTemp = 0.0; // current zone thermostat temperature (cooling, time step)
210 204 : this->HeatZoneHumRat = 0.0; // current zone humidity ratio (heating, time step)
211 204 : this->CoolZoneHumRat = 0.0; // current zone humidity ratio (cooling, time step)
212 204 : this->HeatOutHumRat = 0.0; // current outdoor humidity ratio (heating, time step)
213 204 : this->CoolOutHumRat = 0.0; // current outdoor humidity ratio (cooling, time step)
214 204 : this->ZoneTempAtHeatPeak = 0.0; // zone temp at max heating [C]
215 204 : this->ZoneRetTempAtHeatPeak = 0.0; // zone return temp at max heating [C]
216 204 : this->OutTempAtHeatPeak = 0.0; // outdoor temperature at max heating [C]
217 204 : this->ZoneTempAtCoolPeak = 0.0; // zone temp at max cooling [C]
218 204 : this->ZoneRetTempAtCoolPeak = 0.0; // zone return temp at max cooling [C]
219 204 : this->OutTempAtCoolPeak = 0.0; // outdoor temperature at max cooling [C]
220 204 : this->ZoneHumRatAtHeatPeak = 0.0; // zone humidity ratio at max heating [kg/kg]
221 204 : this->ZoneHumRatAtCoolPeak = 0.0; // zone humidity ratio at max cooling [kg/kg]
222 204 : this->OutHumRatAtHeatPeak = 0.0; // outdoor humidity at max heating [kg/kg]
223 204 : this->OutHumRatAtCoolPeak = 0.0; // outdoor humidity at max cooling [kg/kg]
224 204 : this->TimeStepNumAtHeatMax = 0; // time step number (in day) at Heating peak
225 204 : this->TimeStepNumAtCoolMax = 0; // time step number (in day) at cooling peak
226 204 : this->HeatDDNum = 0; // design day index of design day causing heating peak
227 204 : this->CoolDDNum = 0; // design day index of design day causing heating peak
228 204 : this->LatentHeatDDNum = 0; // design day index of design day causing heating peak
229 204 : this->LatentCoolDDNum = 0; // design day index of design day causing cooling peak
230 204 : this->LatentHeatNoDOASDDNum = 0; // design day index of design day causing latent heating peak without DOAS
231 204 : this->LatentCoolNoDOASDDNum = 0; // design day index of design day causing latent cooling peak without DOAS
232 204 : this->cHeatDDDate = ""; // date of design day causing heating peak
233 204 : this->cCoolDDDate = ""; // date of design day causing cooling peak
234 204 : this->cLatentHeatDDDate = ""; // date of design day causing heating peak
235 204 : this->cLatentCoolDDDate = ""; // date of design day causing cooling peak
236 204 : this->DOASHeatLoad = 0.0; // current heating load from DOAS supply air [W]
237 204 : this->DOASCoolLoad = 0.0; // current cooling load from DOAS supply air [W]
238 204 : this->DOASSupMassFlow = 0.0; // current mass flow rate of DOAS supply air [kg/s]
239 204 : this->DOASSupTemp = 0.0; // current DOAS supply air temperature [C]
240 204 : this->DOASSupHumRat = 0.0; // current DOAS supply air humidity ratio [kgWater/kgDryAir]
241 204 : this->DOASTotCoolLoad = 0.0; // current total cooling load imposed by DOAS supply air [W]
242 204 : this->HeatLoadNoDOAS = 0.0; // current zone heating load no DOAS (HVAC time step)
243 204 : this->CoolLoadNoDOAS = 0.0; // current zone heating load no DOAS (HVAC time step)
244 204 : this->HeatLatentLoad = 0.0; // current zone humidification load (HVAC time step)
245 204 : this->CoolLatentLoad = 0.0; // current zone dehumidification load (HVAC time step)
246 204 : this->HeatLatentLoadNoDOAS = 0.0; // current zone humidification load without DOAS (HVAC time step)
247 204 : this->CoolLatentLoadNoDOAS = 0.0; // current zone dehumidification load without DOAS (HVAC time step)
248 204 : this->ZoneHeatLatentMassFlow = 0.0; // current mass flow rate required to meet humidification load [kg/s]
249 204 : this->ZoneCoolLatentMassFlow = 0.0; // current mass flow rate required to meet dehumidification load [kg/s]
250 204 : this->ZoneHeatLatentVolFlow = 0.0; // current volume flow rate required to meet humidification load [m3/s]
251 204 : this->ZoneCoolLatentVolFlow = 0.0; // current volume flow rate required to meet dehumidification load [m3/s]
252 204 : this->DesHeatLoadNoDOAS = 0.0; // zone design heating load without DOAS [W]
253 204 : this->DesCoolLoadNoDOAS = 0.0; // zone design cooling load without DOAS [W]
254 204 : this->DesLatentHeatLoad = 0.0; // current zone humidification load (HVAC time step)
255 204 : this->DesLatentCoolLoad = 0.0; // current zone dehumidification load (HVAC time step)
256 204 : this->DesLatentHeatLoadNoDOAS = 0.0; // current zone humidification load no DOAS (HVAC time step)
257 204 : this->DesLatentCoolLoadNoDOAS = 0.0; // current zone dehumidification load no DOAS (HVAC time step)
258 204 : this->DesLatentHeatMassFlow = 0.0; // current mass flow rate required to meet humidification load [kg/s]
259 204 : this->DesLatentCoolMassFlow = 0.0; // current mass flow rate required to meet dehumidification load [kg/s]
260 204 : this->DesLatentHeatVolFlow = 0.0; // current volume flow rate required to meet humidification load [m3/s]
261 204 : this->DesLatentCoolVolFlow = 0.0; // current volume flow rate required to meet dehumidification load [m3/s]
262 204 : this->DesLatentHeatCoilInTemp = 0.0; // zone heating coil design air inlet temperature [C]
263 204 : this->DesLatentCoolCoilInTemp = 0.0; // zone cooling coil design air inlet temperature [C]
264 204 : this->DesLatentHeatCoilInHumRat = 0.0; // zone heating coil design air inlet humidity ratio [kg/kg]
265 204 : this->DesLatentCoolCoilInHumRat = 0.0; // zone cooling coil design air inlet humidity ratio [kg/kg]
266 204 : this->TimeStepNumAtLatentHeatMax = 0; // time step number (in day) at latent heating peak
267 204 : this->TimeStepNumAtLatentCoolMax = 0; // time step number (in day) at latent cooling peak
268 204 : this->TimeStepNumAtLatentHeatNoDOASMax = 0; // time step number (in day) at latent heating peak without DOAS
269 204 : this->TimeStepNumAtLatentCoolNoDOASMax = 0; // time step number (in day) at latent cooling peak without DOAS
270 204 : this->OutTempAtLatentCoolPeak = 0.0; // outdoor temperature at max latent cooling [C]
271 204 : this->OutHumRatAtLatentCoolPeak = 0.0; // outdoor humrat at max latent cooling [C]
272 204 : this->OutTempAtLatentHeatPeak = 0.0; // outdoor temperature at max latent heating [C]
273 204 : this->OutHumRatAtLatentHeatPeak = 0.0; // outdoor humrat at max latent heating [C]
274 204 : this->ZoneRetTempAtLatentCoolPeak = 0.0; // zone return temp at max cooling [C]
275 204 : this->ZoneRetTempAtLatentHeatPeak = 0.0; // zone return temp at max heating [C]
276 : }
277 :
278 547 : void ZoneSizingData::allocateMemberArrays(int const numOfTimeStepInDay)
279 : {
280 547 : this->HeatFlowSeq.dimension(numOfTimeStepInDay, 0.0);
281 547 : this->CoolFlowSeq.dimension(numOfTimeStepInDay, 0.0);
282 547 : this->HeatFlowSeqNoOA.dimension(numOfTimeStepInDay, 0.0);
283 547 : this->CoolFlowSeqNoOA.dimension(numOfTimeStepInDay, 0.0);
284 547 : this->HeatLoadSeq.dimension(numOfTimeStepInDay, 0.0);
285 547 : this->CoolLoadSeq.dimension(numOfTimeStepInDay, 0.0);
286 547 : this->HeatZoneTempSeq.dimension(numOfTimeStepInDay, 0.0);
287 547 : this->DesHeatSetPtSeq.dimension(numOfTimeStepInDay, 0.0);
288 547 : this->CoolZoneTempSeq.dimension(numOfTimeStepInDay, 0.0);
289 547 : this->DesCoolSetPtSeq.dimension(numOfTimeStepInDay, 0.0);
290 547 : this->HeatOutTempSeq.dimension(numOfTimeStepInDay, 0.0);
291 547 : this->CoolOutTempSeq.dimension(numOfTimeStepInDay, 0.0);
292 547 : this->HeatZoneRetTempSeq.dimension(numOfTimeStepInDay, 0.0);
293 547 : this->HeatTstatTempSeq.dimension(numOfTimeStepInDay, 0.0);
294 547 : this->CoolZoneRetTempSeq.dimension(numOfTimeStepInDay, 0.0);
295 547 : this->CoolTstatTempSeq.dimension(numOfTimeStepInDay, 0.0);
296 547 : this->HeatZoneHumRatSeq.dimension(numOfTimeStepInDay, 0.0);
297 547 : this->CoolZoneHumRatSeq.dimension(numOfTimeStepInDay, 0.0);
298 547 : this->HeatOutHumRatSeq.dimension(numOfTimeStepInDay, 0.0);
299 547 : this->CoolOutHumRatSeq.dimension(numOfTimeStepInDay, 0.0);
300 547 : this->DOASHeatLoadSeq.dimension(numOfTimeStepInDay, 0.0);
301 547 : this->DOASCoolLoadSeq.dimension(numOfTimeStepInDay, 0.0);
302 547 : this->DOASHeatAddSeq.dimension(numOfTimeStepInDay, 0.0);
303 547 : this->DOASLatAddSeq.dimension(numOfTimeStepInDay, 0.0);
304 547 : this->DOASSupMassFlowSeq.dimension(numOfTimeStepInDay, 0.0);
305 547 : this->DOASSupTempSeq.dimension(numOfTimeStepInDay, 0.0);
306 547 : this->DOASSupHumRatSeq.dimension(numOfTimeStepInDay, 0.0);
307 547 : this->DOASTotCoolLoadSeq.dimension(numOfTimeStepInDay, 0.0);
308 547 : this->HeatLoadNoDOASSeq.dimension(numOfTimeStepInDay, 0.0);
309 547 : this->CoolLoadNoDOASSeq.dimension(numOfTimeStepInDay, 0.0);
310 547 : this->LatentHeatLoadSeq.dimension(numOfTimeStepInDay, 0.0);
311 547 : this->LatentCoolLoadSeq.dimension(numOfTimeStepInDay, 0.0);
312 547 : this->HeatLatentLoadNoDOASSeq.dimension(numOfTimeStepInDay, 0.0);
313 547 : this->CoolLatentLoadNoDOASSeq.dimension(numOfTimeStepInDay, 0.0);
314 547 : this->LatentCoolFlowSeq.dimension(numOfTimeStepInDay, 0.0);
315 547 : this->LatentHeatFlowSeq.dimension(numOfTimeStepInDay, 0.0);
316 547 : }
317 :
318 78 : void TermUnitZoneSizingData::allocateMemberArrays(int const numOfTimeStepInDay)
319 : {
320 78 : this->HeatFlowSeq.dimension(numOfTimeStepInDay, 0.0);
321 78 : this->CoolFlowSeq.dimension(numOfTimeStepInDay, 0.0);
322 78 : this->HeatFlowSeqNoOA.dimension(numOfTimeStepInDay, 0.0);
323 78 : this->CoolFlowSeqNoOA.dimension(numOfTimeStepInDay, 0.0);
324 78 : this->HeatZoneTempSeq.dimension(numOfTimeStepInDay, 0.0);
325 78 : this->HeatZoneRetTempSeq.dimension(numOfTimeStepInDay, 0.0);
326 78 : this->CoolZoneTempSeq.dimension(numOfTimeStepInDay, 0.0);
327 78 : this->CoolZoneRetTempSeq.dimension(numOfTimeStepInDay, 0.0);
328 78 : }
329 :
330 82 : void TermUnitZoneSizingData::copyFromZoneSizing(ZoneSizingData const &sourceData)
331 : {
332 82 : this->ZoneName = sourceData.ZoneName;
333 82 : this->ADUName = sourceData.ADUName;
334 82 : this->CoolDesTemp = sourceData.CoolDesTemp;
335 82 : this->HeatDesTemp = sourceData.HeatDesTemp;
336 82 : this->CoolDesHumRat = sourceData.CoolDesHumRat;
337 82 : this->HeatDesHumRat = sourceData.HeatDesHumRat;
338 82 : this->DesOAFlowPPer = sourceData.DesOAFlowPPer;
339 82 : this->DesOAFlowPerArea = sourceData.DesOAFlowPerArea;
340 82 : this->DesCoolMinAirFlow = sourceData.DesCoolMinAirFlow;
341 82 : this->DesCoolMinAirFlowFrac = sourceData.DesCoolMinAirFlowFrac;
342 82 : this->DesHeatMaxAirFlow = sourceData.DesHeatMaxAirFlow;
343 82 : this->DesHeatMaxAirFlowFrac = sourceData.DesHeatMaxAirFlowFrac;
344 82 : this->ZoneNum = sourceData.ZoneNum;
345 82 : this->DesHeatMassFlow = sourceData.DesHeatMassFlow;
346 82 : this->DesHeatMassFlowNoOA = sourceData.DesHeatMassFlowNoOA;
347 82 : this->DesHeatOAFlowFrac = sourceData.DesHeatOAFlowFrac;
348 82 : this->DesCoolMassFlow = sourceData.DesCoolMassFlow;
349 82 : this->DesCoolMassFlowNoOA = sourceData.DesCoolMassFlowNoOA;
350 82 : this->DesCoolOAFlowFrac = sourceData.DesCoolOAFlowFrac;
351 82 : this->DesHeatLoad = sourceData.DesHeatLoad;
352 82 : this->NonAirSysDesHeatLoad = sourceData.NonAirSysDesHeatLoad;
353 82 : this->DesCoolLoad = sourceData.DesCoolLoad;
354 82 : this->NonAirSysDesCoolLoad = sourceData.NonAirSysDesCoolLoad;
355 82 : this->DesHeatVolFlow = sourceData.DesHeatVolFlow;
356 82 : this->DesHeatVolFlowNoOA = sourceData.DesHeatVolFlowNoOA;
357 82 : this->NonAirSysDesHeatVolFlow = sourceData.NonAirSysDesHeatVolFlow;
358 82 : this->DesCoolVolFlow = sourceData.DesCoolVolFlow;
359 82 : this->DesCoolVolFlowNoOA = sourceData.DesCoolVolFlowNoOA;
360 82 : this->NonAirSysDesCoolVolFlow = sourceData.NonAirSysDesCoolVolFlow;
361 82 : this->DesHeatVolFlowMax = sourceData.DesHeatVolFlowMax;
362 82 : this->DesCoolVolFlowMin = sourceData.DesCoolVolFlowMin;
363 82 : this->DesHeatCoilInTempTU = sourceData.DesHeatCoilInTempTU;
364 82 : this->DesCoolCoilInTempTU = sourceData.DesCoolCoilInTempTU;
365 82 : this->DesHeatCoilInHumRatTU = sourceData.DesHeatCoilInHumRatTU;
366 82 : this->DesCoolCoilInHumRatTU = sourceData.DesCoolCoilInHumRatTU;
367 82 : this->ZoneTempAtHeatPeak = sourceData.ZoneTempAtHeatPeak;
368 82 : this->ZoneRetTempAtHeatPeak = sourceData.ZoneRetTempAtHeatPeak;
369 82 : this->ZoneTempAtCoolPeak = sourceData.ZoneTempAtCoolPeak;
370 82 : this->ZoneRetTempAtCoolPeak = sourceData.ZoneRetTempAtCoolPeak;
371 82 : this->ZoneHumRatAtHeatPeak = sourceData.ZoneHumRatAtHeatPeak;
372 82 : this->ZoneHumRatAtCoolPeak = sourceData.ZoneHumRatAtCoolPeak;
373 82 : this->TimeStepNumAtHeatMax = sourceData.TimeStepNumAtHeatMax;
374 82 : this->TimeStepNumAtCoolMax = sourceData.TimeStepNumAtCoolMax;
375 82 : this->HeatDDNum = sourceData.HeatDDNum;
376 82 : this->CoolDDNum = sourceData.CoolDDNum;
377 82 : this->MinOA = sourceData.MinOA;
378 82 : this->DesCoolMinAirFlow2 = sourceData.DesCoolMinAirFlow2;
379 82 : this->DesHeatMaxAirFlow2 = sourceData.DesHeatMaxAirFlow2;
380 8698 : for (size_t t = 1; t <= this->HeatFlowSeq.size(); ++t) {
381 8616 : this->HeatFlowSeq(t) = sourceData.HeatFlowSeq(t);
382 8616 : this->HeatFlowSeqNoOA(t) = sourceData.HeatFlowSeqNoOA(t);
383 8616 : this->CoolFlowSeq(t) = sourceData.CoolFlowSeq(t);
384 8616 : this->CoolFlowSeqNoOA(t) = sourceData.CoolFlowSeqNoOA(t);
385 8616 : this->HeatZoneTempSeq(t) = sourceData.HeatZoneTempSeq(t);
386 8616 : this->HeatZoneRetTempSeq(t) = sourceData.HeatZoneRetTempSeq(t);
387 8616 : this->CoolZoneTempSeq(t) = sourceData.CoolZoneTempSeq(t);
388 8616 : this->CoolZoneRetTempSeq(t) = sourceData.CoolZoneRetTempSeq(t);
389 : }
390 82 : this->ZoneADEffCooling = sourceData.ZoneADEffCooling;
391 82 : this->ZoneADEffHeating = sourceData.ZoneADEffHeating;
392 82 : this->ZoneSecondaryRecirculation = sourceData.ZoneSecondaryRecirculation;
393 82 : this->ZoneVentilationEff = sourceData.ZoneVentilationEff;
394 82 : this->ZonePrimaryAirFraction = sourceData.ZonePrimaryAirFraction;
395 82 : this->ZonePrimaryAirFractionHtg = sourceData.ZonePrimaryAirFractionHtg;
396 82 : this->ZoneOAFracCooling = sourceData.ZoneOAFracCooling;
397 82 : this->ZoneOAFracHeating = sourceData.ZoneOAFracHeating;
398 82 : this->TotalOAFromPeople = sourceData.TotalOAFromPeople;
399 82 : this->TotalOAFromArea = sourceData.TotalOAFromArea;
400 82 : this->TotPeopleInZone = sourceData.TotPeopleInZone;
401 82 : this->TotalZoneFloorArea = sourceData.TotalZoneFloorArea;
402 82 : this->SupplyAirAdjustFactor = sourceData.SupplyAirAdjustFactor;
403 82 : this->ZpzClgByZone = sourceData.ZpzClgByZone;
404 82 : this->ZpzHtgByZone = sourceData.ZpzHtgByZone;
405 82 : this->VozClgByZone = sourceData.VozClgByZone;
406 82 : this->VozHtgByZone = sourceData.VozHtgByZone;
407 82 : this->VpzMinByZoneSPSized = sourceData.VpzMinByZoneSPSized;
408 82 : this->ZoneSizThermSetPtHi = sourceData.ZoneSizThermSetPtHi;
409 82 : this->ZoneSizThermSetPtLo = sourceData.ZoneSizThermSetPtLo;
410 82 : }
411 :
412 76 : void resetHVACSizingGlobals(EnergyPlusData &state,
413 : int const curZoneEqNum,
414 : int const curSysNum,
415 : bool &firstPassFlag) // called in zone equipment Report function
416 : {
417 : // reset Data globals so that previously set variables are not used in other equipment models
418 76 : state.dataSize->DataTotCapCurveIndex = 0;
419 76 : state.dataSize->DataPltSizCoolNum = 0;
420 76 : state.dataSize->DataPltSizHeatNum = 0;
421 76 : state.dataSize->DataWaterLoopNum = 0;
422 76 : state.dataSize->DataCoilNum = 0;
423 76 : state.dataSize->DataFanOp = HVAC::FanOp::Invalid;
424 76 : state.dataSize->DataCoilIsSuppHeater = false;
425 76 : state.dataSize->DataIsDXCoil = false;
426 76 : state.dataSize->DataAutosizable = true;
427 76 : state.dataSize->DataEMSOverrideON = false;
428 76 : state.dataSize->DataScalableSizingON = false;
429 76 : state.dataSize->DataScalableCapSizingON = false;
430 76 : state.dataSize->DataSysScalableFlowSizingON = false;
431 76 : state.dataSize->DataSysScalableCapSizingON = false;
432 76 : state.dataSize->DataDesAccountForFanHeat = true;
433 76 : state.dataSize->DataDXCoolsLowSpeedsAutozize = false;
434 :
435 76 : state.dataSize->DataDesInletWaterTemp = 0.0;
436 76 : state.dataSize->DataDesInletAirHumRat = 0.0;
437 76 : state.dataSize->DataDesInletAirTemp = 0.0;
438 76 : state.dataSize->DataDesOutletAirTemp = 0.0;
439 76 : state.dataSize->DataDesOutletAirHumRat = 0.0;
440 76 : state.dataSize->DataCoolCoilCap = 0.0;
441 76 : state.dataSize->DataFlowUsedForSizing = 0.0;
442 76 : state.dataSize->DataAirFlowUsedForSizing = 0.0;
443 76 : state.dataSize->DataWaterFlowUsedForSizing = 0.0;
444 76 : state.dataSize->DataCapacityUsedForSizing = 0.0;
445 76 : state.dataSize->DataDesignCoilCapacity = 0.0;
446 76 : state.dataSize->DataHeatSizeRatio = 1.0;
447 76 : state.dataSize->DataEMSOverride = 0.0;
448 76 : state.dataSize->DataBypassFrac = 0.0;
449 76 : state.dataSize->DataFracOfAutosizedCoolingAirflow = 1.0;
450 76 : state.dataSize->DataFracOfAutosizedHeatingAirflow = 1.0;
451 76 : state.dataSize->DataFlowPerCoolingCapacity = 0.0;
452 76 : state.dataSize->DataFlowPerHeatingCapacity = 0.0;
453 76 : state.dataSize->DataFracOfAutosizedCoolingCapacity = 1.0;
454 76 : state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
455 76 : state.dataSize->DataAutosizedCoolingCapacity = 0.0;
456 76 : state.dataSize->DataAutosizedHeatingCapacity = 0.0;
457 76 : state.dataSize->DataConstantUsedForSizing = 0.0;
458 76 : state.dataSize->DataFractionUsedForSizing = 0.0;
459 76 : state.dataSize->DataNonZoneNonAirloopValue = 0.0;
460 76 : state.dataSize->DataZoneNumber = 0;
461 76 : state.dataSize->DataFanType = HVAC::FanType::Invalid;
462 76 : state.dataSize->DataFanIndex = 0;
463 76 : state.dataSize->DataWaterCoilSizCoolDeltaT = 0.0;
464 76 : state.dataSize->DataWaterCoilSizHeatDeltaT = 0.0;
465 76 : state.dataSize->DataNomCapInpMeth = false;
466 76 : state.dataSize->DataFanPlacement = HVAC::FanPlace::Invalid;
467 76 : state.dataSize->DataDXSpeedNum = 0;
468 76 : state.dataSize->DataCoilSizingAirInTemp = 0.0;
469 76 : state.dataSize->DataCoilSizingAirInHumRat = 0.0;
470 76 : state.dataSize->DataCoilSizingAirOutTemp = 0.0;
471 76 : state.dataSize->DataCoilSizingAirOutHumRat = 0.0;
472 76 : state.dataSize->DataCoolCoilType = -1;
473 76 : state.dataSize->DataCoolCoilIndex = -1;
474 :
475 : // These zone specific sizing variables are set in zone equipment to use for sizing.
476 : // Reset to avoid chance that second zone equipment will size using these variables set by first zone equipment to be sized
477 76 : if (curZoneEqNum > 0) {
478 :
479 58 : if (state.dataSize->ZoneEqSizing.size() == 0) {
480 1 : firstPassFlag = false;
481 1 : return;
482 : }
483 :
484 57 : auto &ZoneEqSizing = state.dataSize->ZoneEqSizing(curZoneEqNum);
485 57 : ZoneEqSizing.AirFlow = false;
486 57 : ZoneEqSizing.CoolingAirFlow = false;
487 57 : ZoneEqSizing.HeatingAirFlow = false;
488 57 : ZoneEqSizing.SystemAirFlow = false;
489 57 : ZoneEqSizing.Capacity = false;
490 57 : ZoneEqSizing.CoolingCapacity = false;
491 57 : ZoneEqSizing.HeatingCapacity = false;
492 57 : ZoneEqSizing.AirVolFlow = 0.0;
493 57 : ZoneEqSizing.MaxHWVolFlow = 0.0;
494 57 : ZoneEqSizing.MaxCWVolFlow = 0.0;
495 57 : ZoneEqSizing.OAVolFlow = 0.0;
496 57 : ZoneEqSizing.DesCoolingLoad = 0.0;
497 57 : ZoneEqSizing.DesHeatingLoad = 0.0;
498 57 : ZoneEqSizing.CoolingAirVolFlow = 0.0;
499 57 : ZoneEqSizing.HeatingAirVolFlow = 0.0;
500 57 : ZoneEqSizing.SystemAirVolFlow = 0.0;
501 57 : ZoneEqSizing.DesignSizeFromParent = false;
502 : }
503 :
504 75 : if (curSysNum > 0) {
505 :
506 16 : if (state.dataSize->UnitarySysEqSizing.size() == 0) {
507 0 : firstPassFlag = false;
508 0 : return;
509 : }
510 :
511 16 : auto &UnitarySysEqSizing = state.dataSize->UnitarySysEqSizing(curSysNum);
512 16 : UnitarySysEqSizing.AirFlow = false;
513 16 : UnitarySysEqSizing.CoolingAirFlow = false;
514 16 : UnitarySysEqSizing.HeatingAirFlow = false;
515 16 : UnitarySysEqSizing.Capacity = false;
516 16 : UnitarySysEqSizing.CoolingCapacity = false;
517 16 : UnitarySysEqSizing.HeatingCapacity = false;
518 : }
519 :
520 75 : firstPassFlag = false;
521 : }
522 :
523 33 : void GetCoilDesFlowT(EnergyPlusData &state,
524 : int SysNum, // central air system index
525 : Real64 CpAir, // specific heat to be used in calculations [J/kgC]
526 : Real64 &DesFlow, // returned design mass flow [kg/s]
527 : Real64 &DesExitTemp, // returned design coil exit temperature [kg/s]
528 : Real64 &DesExitHumRat // returned design coil exit humidity ratio [kg/kg]
529 : )
530 : {
531 : // FUNCTION INFORMATION:
532 : // AUTHOR Fred Buhl
533 : // DATE WRITTEN September 2014
534 :
535 : // PURPOSE OF THIS FUNCTION:
536 : // This function calculates the coil design air flow rate and exit temperature depending on the
537 : // cooling capacity control method
538 :
539 : // METHODOLOGY EMPLOYED:
540 : // energy and mass flow balance
541 :
542 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
543 33 : int TimeStepAtPeak = 0;
544 33 : Real64 ZoneCoolLoadSum = 0; // sum of zone cooling loads at the peak [W]
545 33 : Real64 AvgZoneTemp = 0; // average zone temperature [C]
546 :
547 33 : auto &finalSysSizing = state.dataSize->FinalSysSizing(SysNum);
548 33 : auto &sysSizPeakDDNum = state.dataSize->SysSizPeakDDNum(SysNum);
549 33 : auto &calcSysSizing = state.dataSize->CalcSysSizing(SysNum);
550 :
551 33 : int sysSizIndex = Util::FindItemInList(finalSysSizing.AirPriLoopName, state.dataSize->SysSizInput, &SystemSizingInputData::AirPriLoopName);
552 33 : if (sysSizIndex == 0) sysSizIndex = 1;
553 33 : auto &sysSizInput = state.dataSize->SysSizInput(sysSizIndex);
554 :
555 33 : if (sysSizPeakDDNum.SensCoolPeakDD > 0) {
556 29 : if (sysSizInput.coolingPeakLoad == PeakLoad::TotalCooling) {
557 11 : TimeStepAtPeak = sysSizPeakDDNum.TimeStepAtTotCoolPk(sysSizPeakDDNum.TotCoolPeakDD);
558 : } else {
559 18 : TimeStepAtPeak = sysSizPeakDDNum.TimeStepAtSensCoolPk(sysSizPeakDDNum.SensCoolPeakDD);
560 : }
561 : } else {
562 4 : if ((sysSizInput.CoolCapControl == CapacityControl::VT) || (sysSizInput.CoolCapControl == CapacityControl::Bypass)) {
563 4 : ShowWarningError(state,
564 4 : format("GetCoilDesFlow: AirLoopHVAC = {} has no time of peak cooling load for sizing.", sysSizInput.AirPriLoopName));
565 4 : ShowContinueError(state, "Using Central Cooling Capacity Control Method=VAV instead of Bypass or VT.");
566 2 : sysSizInput.CoolCapControl = CapacityControl::VAV;
567 : }
568 : }
569 :
570 33 : if (sysSizInput.CoolCapControl == CapacityControl::VAV) {
571 15 : DesExitTemp = finalSysSizing.CoolSupTemp;
572 15 : DesFlow = finalSysSizing.MassFlowAtCoolPeak / state.dataEnvrn->StdRhoAir;
573 15 : DesExitHumRat = finalSysSizing.CoolSupHumRat;
574 18 : } else if (sysSizInput.CoolCapControl == CapacityControl::OnOff) {
575 6 : DesExitTemp = finalSysSizing.CoolSupTemp;
576 6 : DesFlow = state.dataSize->DataAirFlowUsedForSizing;
577 6 : DesExitHumRat = finalSysSizing.CoolSupHumRat;
578 12 : } else if (sysSizInput.CoolCapControl == CapacityControl::VT) {
579 6 : ZoneCoolLoadSum = calcSysSizing.SumZoneCoolLoadSeq(TimeStepAtPeak);
580 6 : AvgZoneTemp = calcSysSizing.CoolZoneAvgTempSeq(TimeStepAtPeak);
581 6 : DesExitTemp =
582 6 : max(finalSysSizing.CoolSupTemp, AvgZoneTemp - ZoneCoolLoadSum / (state.dataEnvrn->StdRhoAir * CpAir * finalSysSizing.DesCoolVolFlow));
583 6 : DesFlow = finalSysSizing.DesCoolVolFlow;
584 6 : DesExitHumRat = Psychrometrics::PsyWFnTdbRhPb(state, DesExitTemp, 0.9, state.dataEnvrn->StdBaroPress, "GetCoilDesFlowT");
585 6 : } else if (sysSizInput.CoolCapControl == CapacityControl::Bypass) {
586 6 : ZoneCoolLoadSum = calcSysSizing.SumZoneCoolLoadSeq(TimeStepAtPeak);
587 6 : AvgZoneTemp = calcSysSizing.CoolZoneAvgTempSeq(TimeStepAtPeak);
588 6 : DesExitTemp = finalSysSizing.CoolSupTemp;
589 6 : if (calcSysSizing.MixTempAtCoolPeak > DesExitTemp) {
590 5 : Real64 AvgSupTemp = AvgZoneTemp - ZoneCoolLoadSum / (state.dataEnvrn->StdRhoAir * CpAir * finalSysSizing.DesCoolVolFlow);
591 5 : DesFlow = finalSysSizing.DesCoolVolFlow *
592 5 : max(0.0, min(1.0, ((calcSysSizing.MixTempAtCoolPeak - AvgSupTemp) / (calcSysSizing.MixTempAtCoolPeak - DesExitTemp))));
593 : } else {
594 1 : DesFlow = finalSysSizing.DesCoolVolFlow;
595 : }
596 6 : DesExitHumRat = Psychrometrics::PsyWFnTdbRhPb(state, DesExitTemp, 0.9, state.dataEnvrn->StdBaroPress, "GetCoilDesFlowT");
597 : }
598 33 : }
599 :
600 746 : Real64 ZoneAirDistributionData::calculateEz(EnergyPlusData &state, int const ZoneNum) // Zone index
601 : {
602 746 : Real64 zoneEz = 1.0;
603 : // Calc the zone supplied OA flow rate counting the zone air distribution effectiveness
604 : // First check whether the zone air distribution effectiveness schedule exists, if yes uses it;
605 : // otherwise uses the inputs of zone distribution effectiveness in cooling mode or heating mode
606 746 : if (this->zoneADEffSched != nullptr) {
607 : // Get schedule value for the zone air distribution effectiveness
608 0 : zoneEz = this->zoneADEffSched->getCurrentVal();
609 : } else {
610 746 : Real64 zoneLoad = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).TotalOutputRequired;
611 :
612 : // Zone in cooling mode
613 746 : if (zoneLoad < 0.0) zoneEz = this->ZoneADEffCooling;
614 :
615 : // Zone in heating mode
616 746 : if (zoneLoad > 0.0) zoneEz = this->ZoneADEffHeating;
617 : }
618 746 : if (zoneEz <= 0.0) {
619 : // Enforce defaults
620 0 : zoneEz = 1.0;
621 : }
622 746 : return zoneEz;
623 : }
624 :
625 : Real64
626 86190 : calcDesignSpecificationOutdoorAir(EnergyPlusData &state,
627 : int const DSOAPtr, // Pointer to DesignSpecification:OutdoorAir object
628 : int const ActualZoneNum, // Zone index
629 : bool const UseOccSchFlag, // Zone occupancy schedule will be used instead of using total zone occupancy
630 : bool const UseMinOASchFlag, // Use min OA schedule in DesignSpecification:OutdoorAir object
631 : bool const PerPersonNotSet, // when calculation should not include occupants (e.g., dual duct)
632 : bool const MaxOAVolFlowFlag, // TRUE when calculation uses occupancy schedule (e.g., dual duct)
633 : int const spaceNum, // Space index (if applicable)
634 : bool const calcIAQMethods) // For IAQProcedure, PCOccSch, and PCDesOcc, calculate if true, return zero if false
635 : {
636 86190 : Real64 totOAFlowRate = 0.0;
637 86190 : if (DSOAPtr == 0) return totOAFlowRate;
638 :
639 85848 : auto &thisDSOA = state.dataSize->OARequirements(DSOAPtr);
640 :
641 85848 : if (thisDSOA.numDSOA == 0) {
642 : // This is a simple DesignSpecification:OutdoorAir
643 82893 : return thisDSOA.calcOAFlowRate(
644 82893 : state, ActualZoneNum, UseOccSchFlag, UseMinOASchFlag, PerPersonNotSet, MaxOAVolFlowFlag, spaceNum, calcIAQMethods);
645 : } else {
646 : // This is a DesignSpecification:OutdoorAir:SpaceList
647 8879 : for (int dsoaCount = 1; dsoaCount <= thisDSOA.numDSOA; ++dsoaCount) {
648 5924 : if ((spaceNum == 0) || ((spaceNum > 0) && (spaceNum == thisDSOA.dsoaSpaceIndexes(dsoaCount)))) {
649 5924 : totOAFlowRate += state.dataSize->OARequirements(thisDSOA.dsoaIndexes(dsoaCount))
650 5924 : .calcOAFlowRate(state,
651 : ActualZoneNum,
652 : UseOccSchFlag,
653 : UseMinOASchFlag,
654 : PerPersonNotSet,
655 : MaxOAVolFlowFlag,
656 5924 : thisDSOA.dsoaSpaceIndexes(dsoaCount),
657 : calcIAQMethods);
658 : }
659 : }
660 2955 : return totOAFlowRate;
661 : }
662 : }
663 :
664 3 : int getDefaultOAReq(EnergyPlusData &state)
665 : {
666 3 : if (state.dataSize->OARequirements_Default == 0) {
667 2 : SizingManager::GetOARequirements(state); // get the OA requirements object and set up the default
668 : }
669 3 : return state.dataSize->OARequirements_Default;
670 : }
671 :
672 15 : Real64 OARequirementsData::oaFlowArea(EnergyPlusData &state,
673 : int const zoneNum,
674 : bool const useMinOASchFlag, // Use min OA schedule in DesignSpecification:OutdoorAir object
675 : int const spaceNum) // Space index (if applicable)
676 : {
677 15 : Real64 sumAreaOA = 0.0; // OA Flow Rate based on area [m3/s]
678 15 : if (this->numDSOA == 0) {
679 : // This is a simple DesignSpecification:OutdoorAir
680 12 : if (this->OAFlowMethod != OAFlowCalcMethod::PerPerson && this->OAFlowMethod != OAFlowCalcMethod::PerZone &&
681 12 : this->OAFlowMethod != OAFlowCalcMethod::ACH) {
682 12 : if (spaceNum == 0) {
683 12 : sumAreaOA = state.dataHeatBal->Zone(zoneNum).FloorArea * this->OAFlowPerArea;
684 : } else {
685 0 : sumAreaOA = state.dataHeatBal->space(spaceNum).FloorArea * this->OAFlowPerArea;
686 : }
687 12 : if (useMinOASchFlag && (this->oaFlowFracSched != nullptr)) {
688 12 : sumAreaOA *= this->oaFlowFracSched->getCurrentVal();
689 : }
690 : }
691 : } else {
692 : // This is a DesignSpecification:OutdoorAir:SpaceList
693 13 : for (int dsoaCount = 1; dsoaCount <= this->numDSOA; ++dsoaCount) {
694 10 : auto const &thisDSOA = state.dataSize->OARequirements(this->dsoaIndexes(dsoaCount));
695 10 : int const dsoaSpaceNum = this->dsoaSpaceIndexes(dsoaCount);
696 10 : if (thisDSOA.OAFlowMethod != OAFlowCalcMethod::PerPerson && thisDSOA.OAFlowMethod != OAFlowCalcMethod::PerZone &&
697 8 : thisDSOA.OAFlowMethod != OAFlowCalcMethod::ACH) {
698 7 : if ((spaceNum == 0) || (spaceNum == dsoaSpaceNum)) {
699 7 : Real64 spaceArea = state.dataHeatBal->space(this->dsoaSpaceIndexes(dsoaCount)).FloorArea;
700 7 : Real64 spaceOAArea = thisDSOA.OAFlowPerArea * spaceArea;
701 7 : if (useMinOASchFlag && (thisDSOA.oaFlowFracSched != nullptr)) {
702 0 : spaceOAArea *= thisDSOA.oaFlowFracSched->getCurrentVal();
703 : }
704 7 : sumAreaOA += spaceOAArea;
705 : }
706 : }
707 : }
708 : }
709 15 : auto &thisZone = state.dataHeatBal->Zone(zoneNum);
710 15 : sumAreaOA = sumAreaOA * thisZone.Multiplier * thisZone.ListMultiplier;
711 15 : return sumAreaOA;
712 : }
713 :
714 3 : Real64 OARequirementsData::floorArea(EnergyPlusData &state, int const zoneNum,
715 : int const spaceNum) // Space index (if applicable)
716 : {
717 3 : Real64 sumArea = 0.0; // Zone or space floor area [m2]
718 3 : if (this->numDSOA == 0) {
719 : // This is a simple DesignSpecification:OutdoorAir
720 0 : if (spaceNum == 0) {
721 0 : sumArea = state.dataHeatBal->Zone(zoneNum).FloorArea;
722 : } else {
723 0 : sumArea = state.dataHeatBal->space(spaceNum).FloorArea;
724 : }
725 : } else {
726 : // This is a DesignSpecification:OutdoorAir:SpaceList
727 13 : for (int dsoaCount = 1; dsoaCount <= this->numDSOA; ++dsoaCount) {
728 10 : auto const &thisDSOA = state.dataSize->OARequirements(this->dsoaIndexes(dsoaCount));
729 10 : int const dsoaSpaceNum = this->dsoaSpaceIndexes(dsoaCount);
730 10 : if ((spaceNum == 0) || (spaceNum == dsoaSpaceNum)) {
731 10 : Real64 spaceArea = state.dataHeatBal->space(this->dsoaSpaceIndexes(dsoaCount)).FloorArea;
732 10 : sumArea += spaceArea;
733 : }
734 : }
735 : }
736 3 : auto &thisZone = state.dataHeatBal->Zone(zoneNum);
737 3 : sumArea = sumArea * thisZone.Multiplier * thisZone.ListMultiplier;
738 3 : return sumArea;
739 : }
740 :
741 131 : Real64 OARequirementsData::desFlowPerZoneArea(EnergyPlusData &state, int const zoneNum, int const spaceNum)
742 : {
743 131 : Real64 desFlowPA = 0.0;
744 131 : if (this->numDSOA == 0) {
745 : // This is a simple DesignSpecification:OutdoorAir
746 128 : if (this->OAFlowMethod != OAFlowCalcMethod::PerPerson && this->OAFlowMethod != OAFlowCalcMethod::PerZone &&
747 64 : this->OAFlowMethod != OAFlowCalcMethod::ACH) {
748 62 : desFlowPA = this->OAFlowPerArea;
749 : }
750 : } else {
751 : // This is a DesignSpecification:OutdoorAir:SpaceList
752 3 : bool useMinOASch = false;
753 3 : Real64 sumAreaOA = this->oaFlowArea(state, zoneNum, useMinOASch, spaceNum);
754 3 : Real64 sumArea = this->floorArea(state, zoneNum, spaceNum);
755 3 : if (sumArea > 0.0) {
756 3 : desFlowPA = sumAreaOA / sumArea;
757 : }
758 : }
759 131 : return desFlowPA;
760 : }
761 :
762 18 : Real64 OARequirementsData::oaFlowPeople(EnergyPlusData &state,
763 : int const zoneNum, // Zone index
764 : bool const useOccSchFlag, // Use occupancy schedule
765 : bool const useMinOASchFlag, // Use min OA schedule in DesignSpecification:OutdoorAir object
766 : int const spaceNum) // Space index (if applicable)
767 : {
768 18 : Real64 sumPeopleOA = 0.0; // OA Flow Rate based on people [m3/s]
769 18 : if (this->numDSOA == 0) {
770 : // This is a simple DesignSpecification:OutdoorAir
771 14 : if (this->OAFlowMethod != OAFlowCalcMethod::PerArea && this->OAFlowMethod != OAFlowCalcMethod::PerZone &&
772 14 : this->OAFlowMethod != OAFlowCalcMethod::ACH) {
773 14 : Real64 sumPeople = 0.0; // Zone or space number of people
774 14 : if (spaceNum == 0) {
775 14 : if (useOccSchFlag) {
776 2 : sumPeople = state.dataHeatBal->ZoneIntGain(zoneNum).NOFOCC;
777 : } else {
778 12 : sumPeople = state.dataHeatBal->Zone(zoneNum).TotOccupants;
779 : }
780 : } else {
781 0 : if (useOccSchFlag) {
782 0 : sumPeople = state.dataHeatBal->space(spaceNum).TotOccupants;
783 : } else {
784 0 : sumPeople = state.dataHeatBal->spaceIntGain(spaceNum).NOFOCC;
785 : }
786 : }
787 14 : sumPeopleOA = sumPeople * this->OAFlowPerPerson;
788 : // Apply schedule as needed. Sizing does not use schedule.
789 14 : if (useMinOASchFlag && (this->oaFlowFracSched != nullptr)) {
790 14 : sumPeopleOA *= this->oaFlowFracSched->getCurrentVal();
791 : }
792 : }
793 : } else {
794 : // This is a DesignSpecification:OutdoorAir:SpaceList
795 16 : for (int dsoaCount = 1; dsoaCount <= this->numDSOA; ++dsoaCount) {
796 12 : auto const &thisDSOA = state.dataSize->OARequirements(this->dsoaIndexes(dsoaCount));
797 12 : int const dsoaSpaceNum = this->dsoaSpaceIndexes(dsoaCount);
798 12 : if (thisDSOA.OAFlowMethod != OAFlowCalcMethod::PerArea && thisDSOA.OAFlowMethod != OAFlowCalcMethod::PerZone &&
799 10 : thisDSOA.OAFlowMethod != OAFlowCalcMethod::ACH) {
800 9 : if ((spaceNum == 0) || (spaceNum == dsoaSpaceNum)) {
801 9 : Real64 spacePeople = 0.0;
802 9 : if (useOccSchFlag) {
803 0 : spacePeople = state.dataHeatBal->spaceIntGain(spaceNum).NOFOCC;
804 : } else {
805 9 : spacePeople = state.dataHeatBal->space(dsoaSpaceNum).TotOccupants;
806 : }
807 9 : sumPeopleOA += thisDSOA.OAFlowPerPerson * spacePeople;
808 9 : if (useMinOASchFlag && (thisDSOA.oaFlowFracSched != nullptr)) {
809 0 : sumPeopleOA *= thisDSOA.oaFlowFracSched->getCurrentVal();
810 : }
811 : }
812 : }
813 : }
814 : }
815 18 : auto &thisZone = state.dataHeatBal->Zone(zoneNum);
816 18 : sumPeopleOA = sumPeopleOA * thisZone.Multiplier * thisZone.ListMultiplier;
817 18 : return sumPeopleOA;
818 : }
819 :
820 4 : Real64 OARequirementsData::people(EnergyPlusData &state,
821 : int const zoneNum, // Zone index
822 : bool const useOccSchFlag, // Use zone occupancy schedule
823 : int const spaceNum) // Space index (if applicable)
824 : {
825 4 : Real64 sumPeople = 0.0; // Zone or space number of people
826 4 : if (this->numDSOA == 0) {
827 : // This is a simple DesignSpecification:OutdoorAir
828 0 : if (spaceNum == 0) {
829 0 : if (useOccSchFlag) {
830 0 : sumPeople = state.dataHeatBal->ZoneIntGain(zoneNum).NOFOCC;
831 : } else {
832 0 : sumPeople = state.dataHeatBal->Zone(zoneNum).TotOccupants;
833 : }
834 : } else {
835 0 : if (useOccSchFlag) {
836 0 : sumPeople = state.dataHeatBal->space(spaceNum).TotOccupants;
837 : } else {
838 0 : sumPeople = state.dataHeatBal->spaceIntGain(spaceNum).NOFOCC;
839 : }
840 : }
841 : } else {
842 : // This is a DesignSpecification:OutdoorAir:SpaceList
843 16 : for (int dsoaCount = 1; dsoaCount <= this->numDSOA; ++dsoaCount) {
844 12 : auto const &thisDSOA = state.dataSize->OARequirements(this->dsoaIndexes(dsoaCount));
845 12 : int const dsoaSpaceNum = this->dsoaSpaceIndexes(dsoaCount);
846 12 : if ((spaceNum == 0) || (spaceNum == dsoaSpaceNum)) {
847 12 : Real64 spacePeople = 0.0;
848 12 : if (useOccSchFlag) {
849 0 : spacePeople = state.dataHeatBal->spaceIntGain(spaceNum).NOFOCC;
850 : } else {
851 12 : spacePeople = state.dataHeatBal->space(dsoaSpaceNum).TotOccupants;
852 : }
853 12 : sumPeople += spacePeople;
854 : }
855 : }
856 : }
857 4 : auto &thisZone = state.dataHeatBal->Zone(zoneNum);
858 4 : sumPeople = sumPeople * thisZone.Multiplier * thisZone.ListMultiplier;
859 4 : return sumPeople;
860 : }
861 :
862 148 : Real64 OARequirementsData::desFlowPerZonePerson(EnergyPlusData &state, int const zoneNum, int const spaceNum)
863 : {
864 148 : Real64 desFlowPP = 0.0;
865 148 : if (this->numDSOA == 0) {
866 : // This is a simple DesignSpecification:OutdoorAir
867 144 : if (this->OAFlowMethod != OAFlowCalcMethod::PerArea && this->OAFlowMethod != OAFlowCalcMethod::PerZone &&
868 137 : this->OAFlowMethod != OAFlowCalcMethod::ACH) {
869 135 : desFlowPP = this->OAFlowPerPerson;
870 : }
871 : } else {
872 : // This is a DesignSpecification:OutdoorAir:SpaceList
873 4 : bool useOccSch = false; // Use the design people value
874 4 : bool useMinOASch = false;
875 4 : Real64 sumPeopleOA = this->oaFlowPeople(state, zoneNum, useOccSch, useMinOASch, spaceNum);
876 4 : Real64 sumPeople = this->people(state, zoneNum, useOccSch, spaceNum);
877 4 : if (sumPeople > 0.0) {
878 3 : desFlowPP = sumPeopleOA / sumPeople;
879 : }
880 : }
881 148 : return desFlowPP;
882 : }
883 :
884 5 : Real64 OARequirementsData::desFlowPerZone(EnergyPlusData &state, int const zoneNum, int const spaceNum)
885 : {
886 5 : Real64 desFlowPZ = 0.0; // [m3/s]
887 5 : if (this->numDSOA == 0) {
888 : // This is a simple DesignSpecification:OutdoorAir
889 5 : if (this->OAFlowMethod != OAFlowCalcMethod::PerPerson && this->OAFlowMethod != OAFlowCalcMethod::PerArea &&
890 4 : this->OAFlowMethod != OAFlowCalcMethod::ACH) {
891 4 : desFlowPZ = this->OAFlowPerZone;
892 : }
893 : } else {
894 : // This is a DesignSpecification:OutdoorAir:SpaceList
895 0 : for (int dsoaCount = 1; dsoaCount <= this->numDSOA; ++dsoaCount) {
896 0 : auto const &thisDSOA = state.dataSize->OARequirements(this->dsoaIndexes(dsoaCount));
897 0 : int const dsoaSpaceNum = this->dsoaSpaceIndexes(dsoaCount);
898 0 : if (thisDSOA.OAFlowMethod != OAFlowCalcMethod::PerPerson && thisDSOA.OAFlowMethod != OAFlowCalcMethod::PerArea &&
899 0 : thisDSOA.OAFlowMethod != OAFlowCalcMethod::ACH) {
900 0 : if ((spaceNum == 0) || (spaceNum == dsoaSpaceNum)) {
901 0 : desFlowPZ += thisDSOA.OAFlowPerZone;
902 : }
903 : }
904 : }
905 : }
906 5 : return desFlowPZ;
907 : }
908 :
909 5 : Real64 OARequirementsData::desFlowPerACH(EnergyPlusData &state, int const zoneNum, int const spaceNum)
910 : {
911 5 : Real64 desFlowPACH = 0.0; // [1/hr]
912 5 : if (this->numDSOA == 0) {
913 : // This is a simple DesignSpecification:OutdoorAir
914 5 : if (this->OAFlowMethod != OAFlowCalcMethod::PerPerson && this->OAFlowMethod != OAFlowCalcMethod::PerArea &&
915 4 : this->OAFlowMethod != OAFlowCalcMethod::PerZone) {
916 4 : desFlowPACH = this->OAFlowACH;
917 : }
918 : } else {
919 : // This is a DesignSpecification:OutdoorAir:SpaceList
920 0 : Real64 sumVolume = 0.0;
921 0 : Real64 sumACHFlow = 0.0;
922 0 : for (int dsoaCount = 1; dsoaCount <= this->numDSOA; ++dsoaCount) {
923 0 : auto const &thisDSOA = state.dataSize->OARequirements(this->dsoaIndexes(dsoaCount));
924 0 : int const dsoaSpaceNum = this->dsoaSpaceIndexes(dsoaCount);
925 0 : if (thisDSOA.OAFlowMethod != OAFlowCalcMethod::PerPerson && thisDSOA.OAFlowMethod != OAFlowCalcMethod::PerArea &&
926 0 : thisDSOA.OAFlowMethod != OAFlowCalcMethod::PerZone) {
927 0 : if ((spaceNum == 0) || (spaceNum == dsoaSpaceNum)) {
928 0 : Real64 spaceVol = state.dataHeatBal->space(this->dsoaSpaceIndexes(dsoaCount)).Volume;
929 0 : sumVolume += spaceVol;
930 0 : Real64 spaceOAACH = thisDSOA.OAFlowACH * spaceVol;
931 0 : sumACHFlow += spaceOAACH;
932 : }
933 : }
934 : }
935 0 : if (sumVolume > 0.0) {
936 0 : desFlowPACH = Constant::rSecsInHour * sumACHFlow / sumVolume;
937 : }
938 : }
939 5 : return desFlowPACH;
940 : }
941 :
942 : Real64
943 88817 : OARequirementsData::calcOAFlowRate(EnergyPlusData &state,
944 : int const ActualZoneNum, // Zone index
945 : bool const UseOccSchFlag, // Zone occupancy schedule will be used instead of using total zone occupancy
946 : bool const UseMinOASchFlag, // Use min OA schedule in DesignSpecification:OutdoorAir object
947 : bool const PerPersonNotSet, // when calculation should not include occupants (e.g., dual duct)
948 : bool const MaxOAVolFlowFlag, // TRUE when calculation uses occupancy schedule (e.g., dual duct)
949 : int const spaceNum, // Space index (if applicable)
950 : bool const calcIAQMethods // For IAQProcedure, PCOccSch, and PCDesOcc, calculate if true, return zero if false
951 : )
952 : {
953 :
954 : // FUNCTION INFORMATION:
955 : // AUTHOR Richard Raustad, FSEC
956 : // DATE WRITTEN October 2012
957 :
958 : // PURPOSE OF THIS FUNCTION:
959 : // This function returns the air volume flow rate based on DesignSpecification:OutdoorAir object.
960 :
961 : // METHODOLOGY EMPLOYED:
962 : // User inputs and zone index allows calculation of outdoor air quantity.
963 : // Sizing does not use occupancy or min OA schedule and will call with flags set to FALSE
964 : // Ventilation Rate Procedure uses occupancy schedule based on user input.
965 :
966 : // Return value
967 : Real64 OAVolumeFlowRate; // Return value for calculated outdoor air volume flow rate [m3/s]
968 :
969 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
970 : Real64 DSOAFlowPeople; // Outdoor air volume flow rate based on occupancy (m3/s)
971 : Real64 DSOAFlowPerZone; // Outdoor air volume flow rate (m3/s)
972 : Real64 DSOAFlowPerArea; // Outdoor air volume flow rate based on zone floor area (m3/s)
973 : Real64 DSOAFlowACH; // Outdoor air volume flow rate based on air changes per hour (m3/s)
974 : Real64 ZoneOAPeople; // Zone OA flow rate based on number of occupants [m3/s]
975 : Real64 ZoneOAArea; // Zone OA flow rate based on space floor area [m3/s]
976 : Real64 ZoneOAMin; // Minimum Zone OA flow rate when the zone is unoccupied (i.e. ZoneOAPeople = 0)
977 : // used for "ProportionalControl" System outdoor air method
978 : Real64 ZoneOAMax; // Maximum Zone OA flow rate (ZoneOAPeople + ZoneOAArea)
979 : // used for "ProportionalControl" System outdoor air method
980 : Real64 ZoneMaxCO2; // Breathing-zone CO2 concentration
981 : Real64 ZoneMinCO2; // Minimum CO2 concentration in zone
982 : Real64 ZoneContamControllerSched; // Schedule value for ZoneControl:ContaminantController
983 : Real64 CO2PeopleGeneration; // CO2 generation from people at design level
984 :
985 88817 : OAVolumeFlowRate = 0.0;
986 :
987 88817 : auto &thisZone = state.dataHeatBal->Zone(ActualZoneNum);
988 88817 : Real64 floorArea = 0.0;
989 88817 : Real64 volume = 0.0;
990 88817 : Real64 nomTotOccupants = 0.0;
991 88817 : Real64 curNumOccupants = 0.0;
992 88817 : Real64 maxOccupants = 0.0;
993 88817 : if (spaceNum > 0) {
994 5945 : auto const &thisSpace = state.dataHeatBal->space(spaceNum);
995 5945 : floorArea = thisSpace.FloorArea;
996 5945 : volume = thisSpace.Volume;
997 5945 : nomTotOccupants = thisSpace.TotOccupants;
998 5945 : curNumOccupants = state.dataHeatBal->spaceIntGain(spaceNum).NOFOCC;
999 5945 : maxOccupants = thisSpace.maxOccupants;
1000 : } else {
1001 82872 : floorArea = thisZone.FloorArea;
1002 82872 : volume = thisZone.Volume;
1003 82872 : nomTotOccupants = thisZone.TotOccupants;
1004 82872 : curNumOccupants = state.dataHeatBal->ZoneIntGain(ActualZoneNum).NOFOCC;
1005 82872 : maxOccupants = thisZone.maxOccupants;
1006 : }
1007 :
1008 88817 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::IAQProcedure && this->myEnvrnFlag) {
1009 0 : if (!state.dataContaminantBalance->Contaminant.CO2Simulation) {
1010 0 : ShowSevereError(state,
1011 0 : format("DesignSpecification:OutdoorAir=\"{}{}",
1012 0 : this->Name,
1013 : R"(" valid Outdoor Air Method =" IndoorAirQualityProcedure" requires CO2 simulation.)"));
1014 0 : ShowContinueError(state, "The choice must be Yes for the field Carbon Dioxide Concentration in ZoneAirContaminantBalance");
1015 0 : ShowFatalError(state, "CalcDesignSpecificationOutdoorAir: Errors found in input. Preceding condition(s) cause termination.");
1016 : }
1017 0 : this->myEnvrnFlag = false;
1018 : }
1019 88817 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCOccSch && this->myEnvrnFlag) {
1020 1 : if (!state.dataContaminantBalance->Contaminant.CO2Simulation) {
1021 0 : ShowSevereError(state,
1022 0 : format("DesignSpecification:OutdoorAir=\"{}{}",
1023 0 : this->Name,
1024 : R"(" valid Outdoor Air Method =" ProportionalControlBasedOnDesignOccupancy" requires CO2 simulation.)"));
1025 0 : ShowContinueError(state, "The choice must be Yes for the field Carbon Dioxide Concentration in ZoneAirContaminantBalance");
1026 0 : ShowFatalError(state, "CalcDesignSpecificationOutdoorAir: Errors found in input. Preceding condition(s) cause termination.");
1027 : }
1028 1 : this->myEnvrnFlag = false;
1029 : }
1030 88817 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCDesOcc && this->myEnvrnFlag) {
1031 2 : if (!state.dataContaminantBalance->Contaminant.CO2Simulation) {
1032 0 : ShowSevereError(state,
1033 0 : format("DesignSpecification:OutdoorAir=\"{}{}",
1034 0 : this->Name,
1035 : R"(" valid Outdoor Air Method =" ProportionalControlBasedOnOccupancySchedule" requires CO2 simulation.)"));
1036 0 : ShowContinueError(state, "The choice must be Yes for the field Carbon Dioxide Concentration in ZoneAirContaminantBalance");
1037 0 : ShowFatalError(state, "CalcDesignSpecificationOutdoorAir: Errors found in input. Preceding condition(s) cause termination.");
1038 : }
1039 2 : this->myEnvrnFlag = false;
1040 : }
1041 :
1042 88817 : if (!calcIAQMethods &&
1043 36637 : (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::IAQProcedure || this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCOccSch ||
1044 36637 : this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCDesOcc)) {
1045 12 : return OAVolumeFlowRate;
1046 : }
1047 :
1048 : // Calculate people outdoor air flow rate as needed
1049 88805 : switch (this->OAFlowMethod) {
1050 87544 : case OAFlowCalcMethod::PerPerson:
1051 : case OAFlowCalcMethod::Sum:
1052 : case OAFlowCalcMethod::Max: {
1053 87544 : if (UseOccSchFlag) {
1054 85338 : if (MaxOAVolFlowFlag) {
1055 : // OAPerPersonMode == PerPersonDCVByCurrentLevel (UseOccSchFlag = TRUE)
1056 : // for dual duct, get max people according to max schedule value when requesting MaxOAFlow
1057 0 : DSOAFlowPeople = maxOccupants * this->OAFlowPerPerson;
1058 : } else {
1059 85338 : DSOAFlowPeople = curNumOccupants * this->OAFlowPerPerson;
1060 : }
1061 : } else {
1062 2206 : if (MaxOAVolFlowFlag) {
1063 : // OAPerPersonMode == PerPersonByDesignLevel (UseOccSchFlag = FALSE)
1064 : // use total people when requesting MaxOAFlow
1065 0 : DSOAFlowPeople = nomTotOccupants * this->OAFlowPerPerson;
1066 : } else {
1067 2206 : DSOAFlowPeople = nomTotOccupants * this->OAFlowPerPerson;
1068 : }
1069 : }
1070 87544 : if (PerPersonNotSet) DSOAFlowPeople = 0.0; // for Dual Duct if Per Person Ventilation Rate Mode is not entered
1071 87544 : } break;
1072 1261 : default: {
1073 1261 : DSOAFlowPeople = 0.0;
1074 1261 : } break;
1075 : }
1076 :
1077 : // Calculate minimum outdoor air flow rate
1078 88805 : switch (this->OAFlowMethod) {
1079 46729 : case OAFlowCalcMethod::PerPerson: {
1080 : // Multiplied by occupancy
1081 46729 : OAVolumeFlowRate = DSOAFlowPeople;
1082 46729 : } break;
1083 1242 : case OAFlowCalcMethod::PerZone: {
1084 : // User input
1085 1242 : OAVolumeFlowRate = this->OAFlowPerZone;
1086 1242 : } break;
1087 7 : case OAFlowCalcMethod::PerArea: {
1088 : // Multiplied by zone floor area
1089 7 : OAVolumeFlowRate = this->OAFlowPerArea * floorArea;
1090 7 : } break;
1091 8 : case OAFlowCalcMethod::ACH: {
1092 : // Multiplied by zone volume
1093 8 : OAVolumeFlowRate = this->OAFlowACH * volume / 3600.0;
1094 8 : } break;
1095 40815 : case OAFlowCalcMethod::Sum:
1096 : case OAFlowCalcMethod::Max: {
1097 : // Use sum or max of per person and the following
1098 40815 : DSOAFlowPerZone = this->OAFlowPerZone;
1099 40815 : DSOAFlowPerArea = this->OAFlowPerArea * floorArea;
1100 40815 : DSOAFlowACH = this->OAFlowACH * volume / 3600.0;
1101 40815 : if (this->OAFlowMethod == OAFlowCalcMethod::Max) {
1102 10 : OAVolumeFlowRate = max(DSOAFlowPeople, DSOAFlowPerZone, DSOAFlowPerArea, DSOAFlowACH);
1103 : } else {
1104 40805 : OAVolumeFlowRate = DSOAFlowPeople + DSOAFlowPerZone + DSOAFlowPerArea + DSOAFlowACH;
1105 : }
1106 40815 : } break;
1107 1 : case DataSizing::OAFlowCalcMethod::IAQProcedure: {
1108 1 : if (state.dataGlobal->DoingSizing) {
1109 0 : DSOAFlowPeople = nomTotOccupants * this->OAFlowPerPerson;
1110 0 : DSOAFlowPerZone = this->OAFlowPerZone;
1111 0 : DSOAFlowPerArea = this->OAFlowPerArea * floorArea;
1112 0 : DSOAFlowACH = this->OAFlowACH * volume / 3600.0;
1113 0 : OAVolumeFlowRate = DSOAFlowPeople + DSOAFlowPerZone + DSOAFlowPerArea + DSOAFlowACH;
1114 : } else {
1115 1 : OAVolumeFlowRate = state.dataContaminantBalance->ZoneSysContDemand(ActualZoneNum).OutputRequiredToCO2SP / state.dataEnvrn->StdRhoAir;
1116 : }
1117 1 : } break;
1118 3 : case DataSizing::OAFlowCalcMethod::PCOccSch:
1119 : case DataSizing::OAFlowCalcMethod::PCDesOcc: {
1120 3 : ZoneOAPeople = 0.0;
1121 3 : if (this->OAFlowMethod != DataSizing::OAFlowCalcMethod::PCDesOcc) {
1122 2 : ZoneOAPeople = curNumOccupants * thisZone.Multiplier * thisZone.ListMultiplier * this->OAFlowPerPerson;
1123 : } else {
1124 1 : ZoneOAPeople = nomTotOccupants * thisZone.Multiplier * thisZone.ListMultiplier * this->OAFlowPerPerson;
1125 1 : CO2PeopleGeneration = 0.0;
1126 1 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCDesOcc) {
1127 : // Accumulate CO2 generation from people at design occupancy and current activity level
1128 2 : for (int PeopleNum = 1; PeopleNum <= state.dataHeatBal->TotPeople; ++PeopleNum) {
1129 1 : if (spaceNum > 0) {
1130 0 : if (state.dataHeatBal->People(PeopleNum).spaceIndex != spaceNum) continue;
1131 : } else {
1132 1 : if (state.dataHeatBal->People(PeopleNum).ZonePtr != ActualZoneNum) continue;
1133 : }
1134 2 : CO2PeopleGeneration += state.dataHeatBal->People(PeopleNum).NumberOfPeople * state.dataHeatBal->People(PeopleNum).CO2RateFactor *
1135 1 : state.dataHeatBal->People(PeopleNum).activityLevelSched->getCurrentVal();
1136 : }
1137 : }
1138 : }
1139 3 : ZoneOAArea = floorArea * thisZone.Multiplier * thisZone.ListMultiplier * this->OAFlowPerArea;
1140 3 : ZoneOAMin = ZoneOAArea;
1141 3 : ZoneOAMax = (ZoneOAArea + ZoneOAPeople);
1142 3 : if (thisZone.zoneContamControllerSched != nullptr) {
1143 : // Check the availability schedule value for ZoneControl:ContaminantController
1144 3 : ZoneContamControllerSched = thisZone.zoneContamControllerSched->getCurrentVal();
1145 3 : if (ZoneContamControllerSched > 0.0) {
1146 3 : if (ZoneOAPeople > 0.0) {
1147 3 : if (state.dataContaminantBalance->ZoneCO2GainFromPeople(ActualZoneNum) > 0.0) {
1148 3 : if (thisZone.zoneMinCO2Sched != nullptr) {
1149 : // Take the schedule value of "Minimum Carbon Dioxide Concentration Schedule Name"
1150 : // in the ZoneControl:ContaminantController
1151 0 : ZoneMinCO2 = thisZone.zoneMinCO2Sched->getCurrentVal();
1152 : } else {
1153 3 : ZoneMinCO2 = state.dataContaminantBalance->OutdoorCO2;
1154 : }
1155 :
1156 : // Calculate zone maximum target CO2 concentration in PPM
1157 3 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCDesOcc) {
1158 1 : ZoneMaxCO2 = state.dataContaminantBalance->OutdoorCO2 +
1159 1 : (CO2PeopleGeneration * thisZone.Multiplier * thisZone.ListMultiplier * 1.0e6) / ZoneOAMax;
1160 : } else {
1161 2 : ZoneMaxCO2 =
1162 2 : state.dataContaminantBalance->OutdoorCO2 + (state.dataContaminantBalance->ZoneCO2GainFromPeople(ActualZoneNum) *
1163 2 : thisZone.Multiplier * thisZone.ListMultiplier * 1.0e6) /
1164 : ZoneOAMax;
1165 : }
1166 :
1167 3 : if (ZoneMaxCO2 <= ZoneMinCO2) {
1168 0 : ++this->CO2MaxMinLimitErrorCount;
1169 0 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCOccSch) {
1170 0 : if (this->CO2MaxMinLimitErrorCount < 2) {
1171 0 : ShowSevereError(state,
1172 0 : format("CalcDesignSpecificationOutdoorAir DesignSpecification:OutdoorAir = \"{}\".", this->Name));
1173 0 : ShowContinueError(
1174 : state,
1175 0 : format("For System Outdoor Air Method = ProportionalControlBasedOnOccupancySchedule, maximum target "
1176 : "CO2 concentration ({:.2R}), is not greater than minimum target CO2 concentration ({:.2R}).",
1177 : ZoneMaxCO2,
1178 : ZoneMinCO2));
1179 0 : ShowContinueError(state,
1180 : "\"ProportionalControlBasedOnOccupancySchedule\" will not be modeled. "
1181 : "Default \"Flow/Person+Flow/Area\" will be modeled. Simulation continues...");
1182 0 : ShowContinueErrorTimeStamp(state, "");
1183 : } else {
1184 0 : ShowRecurringWarningErrorAtEnd(
1185 : state,
1186 0 : format("DesignSpecification:OutdoorAir = \"{}\", For System Outdoor Air Method = "
1187 : "ProportionalControlBasedOnOccupancySchedule, maximum target CO2 concentration is not greater than "
1188 : "minimum target CO2 concentration. Error continues...",
1189 0 : this->Name),
1190 0 : this->CO2MaxMinLimitErrorIndex);
1191 : }
1192 : }
1193 0 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCDesOcc) {
1194 0 : if (this->CO2MaxMinLimitErrorCount < 2) {
1195 0 : ShowSevereError(state,
1196 0 : format("CalcDesignSpecificationOutdoorAir DesignSpecification:OutdoorAir = \"{}\".", this->Name));
1197 0 : ShowContinueError(
1198 : state,
1199 0 : format("For System Outdoor Air Method = ProportionalControlBasedOnDesignOccupancy, maximum target "
1200 : "CO2 concentration ({:.2R}), is not greater than minimum target CO2 concentration ({:.2R}).",
1201 : ZoneMaxCO2,
1202 : ZoneMinCO2));
1203 0 : ShowContinueError(state,
1204 : "\"ProportionalControlBasedOnDesignOccupancy\" will not be modeled. "
1205 : "Default \"Flow/Person+Flow/Area\" will be modeled. Simulation continues...");
1206 0 : ShowContinueErrorTimeStamp(state, "");
1207 : } else {
1208 0 : ShowRecurringWarningErrorAtEnd(
1209 : state,
1210 0 : format("DesignSpecification:OutdoorAir = \"{}\", For System Outdoor Air Method = "
1211 : "ProportionalControlBasedOnDesignOccupancy, maximum target CO2 concentration is not greater than "
1212 : "minimum target CO2 concentration. Error continues...",
1213 0 : this->Name),
1214 0 : this->CO2MaxMinLimitErrorIndex);
1215 : }
1216 : }
1217 :
1218 0 : OAVolumeFlowRate = ZoneOAMax;
1219 : } else {
1220 :
1221 3 : if (state.dataContaminantBalance->ZoneAirCO2(ActualZoneNum) <= ZoneMinCO2) {
1222 : // Zone air CO2 concentration is less than minimum zone CO2 concentration, set the Zone OA flow rate to
1223 : // minimum Zone OA flow rate when the zone is unoccupied
1224 0 : OAVolumeFlowRate = ZoneOAMin;
1225 3 : } else if (state.dataContaminantBalance->ZoneAirCO2(ActualZoneNum) >= ZoneMaxCO2) {
1226 : // Zone air CO2 concentration is greater than maximum zone CO2 concentration, set the Zone OA flow rate to
1227 : // maximum Zone OA flow rate (i.e. ZoneOAArea + ZoneOAPeople)
1228 1 : OAVolumeFlowRate = ZoneOAMax;
1229 : } else {
1230 : // Zone air CO2 concentration is between maximum and minimum limits of zone CO2 concentration,
1231 : // set Zone OA flow rate by proportionally adjusting between ZoneOAMin and ZoneOAMax
1232 2 : OAVolumeFlowRate =
1233 2 : ZoneOAMin + (ZoneOAMax - ZoneOAMin) * ((state.dataContaminantBalance->ZoneAirCO2(ActualZoneNum) - ZoneMinCO2) /
1234 2 : (ZoneMaxCO2 - ZoneMinCO2));
1235 : }
1236 : }
1237 : } else {
1238 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1239 0 : ++this->CO2GainErrorCount;
1240 0 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCOccSch) {
1241 0 : if (this->CO2GainErrorCount < 2) {
1242 0 : ShowSevereError(state,
1243 0 : format("CalcDesignSpecificationOutdoorAir DesignSpecification:OutdoorAir = \"{}\".", this->Name));
1244 0 : ShowContinueError(state,
1245 0 : format("For System Outdoor Air Method = ProportionalControlBasedOnOccupancySchedule, CO2 "
1246 : "generation from people is not greater than zero. Occurs in Zone =\"{}\". ",
1247 0 : thisZone.Name));
1248 0 : ShowContinueError(state,
1249 : "\"ProportionalControlBasedOnOccupancySchedule\" will not be modeled. "
1250 : "Default \"Flow/Person+Flow/Area\" will be modeled. Simulation continues...");
1251 0 : ShowContinueErrorTimeStamp(state, "");
1252 : } else {
1253 0 : ShowRecurringWarningErrorAtEnd(state,
1254 0 : format("DesignSpecification:OutdoorAir = \"{}\", For System Outdoor Air Method = "
1255 : "ProportionalControlBasedOnOccupancySchedule, CO2 generation from people "
1256 : "is not greater than zero. Error continues...",
1257 0 : this->Name),
1258 0 : this->CO2GainErrorIndex);
1259 : }
1260 : }
1261 0 : if (this->OAFlowMethod == DataSizing::OAFlowCalcMethod::PCDesOcc) {
1262 0 : if (this->CO2GainErrorCount < 2) {
1263 0 : ShowSevereError(state,
1264 0 : format("CalcDesignSpecificationOutdoorAir DesignSpecification:OutdoorAir = \"{}\".", this->Name));
1265 0 : ShowContinueError(state,
1266 0 : format("For System Outdoor Air Method = ProportionalControlBasedOnDesignOccupancy, CO2 "
1267 : "generation from people is not greater than zero. Occurs in Zone =\"{}\". ",
1268 0 : thisZone.Name));
1269 0 : ShowContinueError(state,
1270 : "\"ProportionalControlBasedOnDesignOccupancy\" will not be modeled. "
1271 : "Default \"Flow/Person+Flow/Area\" will be modeled. Simulation continues...");
1272 0 : ShowContinueErrorTimeStamp(state, "");
1273 : } else {
1274 0 : ShowRecurringWarningErrorAtEnd(state,
1275 0 : format("DesignSpecification:OutdoorAir = \"{}\", For System Outdoor Air Method = "
1276 : "ProportionalControlBasedOnDesignOccupancy, CO2 generation from people is "
1277 : "not greater than zero. Error continues...",
1278 0 : this->Name),
1279 0 : this->CO2GainErrorIndex);
1280 : }
1281 : }
1282 : }
1283 0 : OAVolumeFlowRate = ZoneOAMax;
1284 : }
1285 : } else {
1286 : // ZoneOAPeople is less than or equal to zero
1287 0 : OAVolumeFlowRate = ZoneOAMax;
1288 : }
1289 : } else {
1290 : // ZoneControl:ContaminantController is scheduled off (not available)
1291 0 : OAVolumeFlowRate = ZoneOAMax;
1292 : }
1293 : } else {
1294 : // "Carbon Dioxide Control Availability Schedule" for ZoneControl:ContaminantController not found
1295 0 : OAVolumeFlowRate = ZoneOAMax;
1296 : }
1297 3 : } break;
1298 0 : default: {
1299 : // Will never get here
1300 0 : OAVolumeFlowRate = 0.0;
1301 0 : } break;
1302 : }
1303 :
1304 : // Apply zone multipliers and zone list multipliers
1305 : // TODO MJW: this looks like it's double-counting the multipliers - it *is* double counting for methods PCOccSch and PCDesOcc
1306 88805 : OAVolumeFlowRate *= thisZone.Multiplier * thisZone.ListMultiplier;
1307 :
1308 : // Apply schedule as needed. Sizing does not use schedule.
1309 88805 : if (this->oaFlowFracSched != nullptr && UseMinOASchFlag) {
1310 88685 : if (MaxOAVolFlowFlag) {
1311 0 : OAVolumeFlowRate *= this->oaFlowFracSched->getMaxVal(state);
1312 : } else {
1313 88685 : OAVolumeFlowRate *= this->oaFlowFracSched->getCurrentVal();
1314 : }
1315 : }
1316 :
1317 88805 : return OAVolumeFlowRate;
1318 : }
1319 :
1320 2 : Sched::Schedule *OARequirementsData::getZoneFlowFracSched(EnergyPlusData &state, bool notAllSame)
1321 : {
1322 2 : notAllSame = false;
1323 2 : Sched::Schedule *schedPtr = nullptr;
1324 2 : if (this->numDSOA == 0) {
1325 : // This is a simple DesignSpecification:OutdoorAir
1326 2 : schedPtr = this->oaFlowFracSched;
1327 : } else {
1328 : // This is a DesignSpecification:OutdoorAir:SpaceList
1329 0 : for (int dsoaCount = 1; dsoaCount <= this->numDSOA; ++dsoaCount) {
1330 0 : auto const &thisDSOA = state.dataSize->OARequirements(this->dsoaIndexes(dsoaCount));
1331 0 : if (dsoaCount == 1) {
1332 0 : schedPtr = thisDSOA.oaFlowFracSched;
1333 : } else {
1334 0 : if (schedPtr != thisDSOA.oaFlowFracSched) {
1335 0 : notAllSame = true;
1336 0 : ShowWarningError(state,
1337 0 : format("getZoneFlowFracSched: Outdoor Air Schedules are not the same for all spaces in "
1338 : "DesignSpecification:OutdoorAir:SpaceList={}.",
1339 0 : this->Name));
1340 0 : ShowContinueError(state, format("Using the first space schedule={}", schedPtr->Name));
1341 0 : break;
1342 : }
1343 : }
1344 : }
1345 : }
1346 2 : return schedPtr;
1347 : }
1348 :
1349 5 : Sched::Schedule *OARequirementsData::getZonePropCtlMinRateSched(EnergyPlusData &state, bool notAllSame)
1350 : {
1351 5 : notAllSame = false;
1352 5 : Sched::Schedule *schedPtr = nullptr;
1353 5 : if (this->numDSOA == 0) {
1354 : // This is a simple DesignSpecification:OutdoorAir
1355 5 : schedPtr = this->oaPropCtlMinRateSched;
1356 : } else {
1357 : // This is a DesignSpecification:OutdoorAir:SpaceList
1358 0 : for (int dsoaCount = 1; dsoaCount <= this->numDSOA; ++dsoaCount) {
1359 0 : auto const &thisDSOA = state.dataSize->OARequirements(this->dsoaIndexes(dsoaCount));
1360 0 : if (dsoaCount == 1) {
1361 0 : schedPtr = thisDSOA.oaPropCtlMinRateSched;
1362 : } else {
1363 0 : if (schedPtr != thisDSOA.oaPropCtlMinRateSched) {
1364 0 : notAllSame = true;
1365 0 : ShowWarningError(
1366 : state,
1367 0 : format(
1368 : "getZoneFlowFracSched: Proportional Control Minimum Outdoor Air Flow Rate Schedules are not the same for all spaces in "
1369 : "DesignSpecification:OutdoorAir:SpaceList={}.",
1370 0 : this->Name));
1371 0 : ShowContinueError(state, format("Using the first space schedule={}", schedPtr->Name));
1372 0 : break;
1373 : }
1374 : }
1375 : }
1376 : }
1377 5 : return schedPtr;
1378 : }
1379 :
1380 : } // namespace EnergyPlus::DataSizing
|