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 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 : #include <ObjexxFCL/string.functions.hh>
55 :
56 : // EnergyPlus Headers
57 : #include <EnergyPlus/Autosizing/CoolingAirFlowSizing.hh>
58 : #include <EnergyPlus/Autosizing/CoolingCapacitySizing.hh>
59 : #include <EnergyPlus/Autosizing/HeatingAirFlowSizing.hh>
60 : #include <EnergyPlus/Autosizing/HeatingCapacitySizing.hh>
61 : #include <EnergyPlus/Data/EnergyPlusData.hh>
62 : #include <EnergyPlus/DataContaminantBalance.hh>
63 : #include <EnergyPlus/DataEnvironment.hh>
64 : #include <EnergyPlus/DataHVACGlobals.hh>
65 : #include <EnergyPlus/DataHeatBalFanSys.hh>
66 : #include <EnergyPlus/DataHeatBalance.hh>
67 : #include <EnergyPlus/DataIPShortCuts.hh>
68 : #include <EnergyPlus/DataLoopNode.hh>
69 : #include <EnergyPlus/DataSizing.hh>
70 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
71 : #include <EnergyPlus/DataZoneEquipment.hh>
72 : #include <EnergyPlus/EMSManager.hh>
73 : #include <EnergyPlus/General.hh>
74 : #include <EnergyPlus/GeneralRoutines.hh>
75 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
76 : #include <EnergyPlus/NodeInputManager.hh>
77 : #include <EnergyPlus/OutAirNodeManager.hh>
78 : #include <EnergyPlus/OutputProcessor.hh>
79 : #include <EnergyPlus/Psychrometrics.hh>
80 : #include <EnergyPlus/PurchasedAirManager.hh>
81 : #include <EnergyPlus/ScheduleManager.hh>
82 : #include <EnergyPlus/UtilityRoutines.hh>
83 : #include <EnergyPlus/ZonePlenum.hh>
84 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
85 :
86 : namespace EnergyPlus::PurchasedAirManager {
87 :
88 : // Module containing data and routines dealing with Ideal Loads Air System (formerly PURCHASED AIR).
89 :
90 : // MODULE INFORMATION:
91 : // AUTHOR Russ Taylor
92 : // DATE WRITTEN May 1997
93 : // MODIFIED Fred Buhl Dec 1999
94 : // B. Griffith Dec 2006. added OA lookup function, moved getinputflag up to Module
95 : // M. Witte June 2011, add new features including DCV, economizer, dehumidification and humidification
96 : // NOTE: MJW Sep 13, 2011: Still need to review checks for negative loads and impossible supply temps???
97 : // There are no Deallocate statements in here - should there be?
98 : // RE-ENGINEERED na
99 :
100 : // PURPOSE OF THIS MODULE:
101 : // To encapsulate the data and algorithms required to simulate the
102 : // Zone Ideal Loads Air System component. This component supplies hot or cold air
103 : // at a fixed or variable temperature to a zone to meet the zone load.
104 : // With the June 2011 enhancements it will also supply outdoor air with optional demand-controlled ventilation
105 : // and economizer controls, plus new options for controlling zone humidity.
106 :
107 : // METHODOLOGY EMPLOYED:
108 : // The user can choose via input the max/min hot and cold supply air
109 : // temperature and humidity ratio. The air mass flow rate is chosen
110 : // to meet the (remaining) zone load or based on the outdoor air flow requirement.
111 : // If the outdoor air flow sets the flow rate, the supply air temperature and
112 : // humidity ratio are adjusted to meet the zone load.
113 :
114 : // Using/Aliasing
115 : using namespace DataHVACGlobals;
116 : using namespace ScheduleManager;
117 : using Psychrometrics::PsyCpAirFnW;
118 : using Psychrometrics::PsyHFnTdbW;
119 : using Psychrometrics::PsyRhoAirFnPbTdbW;
120 : using Psychrometrics::PsyTdbFnHW;
121 : using Psychrometrics::PsyTsatFnHPb;
122 : using Psychrometrics::PsyWFnTdbH;
123 : using Psychrometrics::PsyWFnTdbRhPb;
124 :
125 : // Delta humidity ratio limit, 0.00025 equals delta between 45F dewpoint and 46F dewpoint
126 : // used to prevent dividing by near zero
127 : Real64 constexpr SmallDeltaHumRat(0.00025);
128 :
129 1291226 : void SimPurchasedAir(EnergyPlusData &state,
130 : std::string const &PurchAirName,
131 : Real64 &SysOutputProvided,
132 : Real64 &MoistOutputProvided, // Moisture output provided (kg/s), dehumidification = negative
133 : bool const FirstHVACIteration,
134 : int const ControlledZoneNum,
135 : int &CompIndex)
136 : {
137 :
138 : // SUBROUTINE INFORMATION:
139 : // AUTHOR Russ Taylor
140 : // DATE WRITTEN May 1997
141 : // MODIFIED Don Shirey, Aug 2009 (LatOutputProvided - now MoistOutputProvided)
142 : // RE-ENGINEERED na
143 :
144 : // PURPOSE OF THIS SUBROUTINE:
145 : // This subroutine manages Purchased Air component simulation.
146 : // It is called from SimZoneEquipment in the ZoneEquipmentManager
147 : // at the system time step.
148 :
149 : int PurchAirNum;
150 :
151 1291226 : if (state.dataPurchasedAirMgr->GetPurchAirInputFlag) {
152 77 : GetPurchasedAir(state);
153 77 : state.dataPurchasedAirMgr->GetPurchAirInputFlag = false;
154 : }
155 :
156 : // Find the correct PurchasedAir Equipment
157 1291226 : if (CompIndex == 0) {
158 214 : PurchAirNum = UtilityRoutines::FindItemInList(PurchAirName, state.dataPurchasedAirMgr->PurchAir);
159 214 : if (PurchAirNum == 0) {
160 0 : ShowFatalError(state, "SimPurchasedAir: Unit not found=" + PurchAirName);
161 : }
162 214 : CompIndex = PurchAirNum;
163 : } else {
164 1291012 : PurchAirNum = CompIndex;
165 1291012 : if (PurchAirNum > state.dataPurchasedAirMgr->NumPurchAir || PurchAirNum < 1) {
166 0 : ShowFatalError(state,
167 0 : format("SimPurchasedAir: Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
168 : PurchAirNum,
169 0 : state.dataPurchasedAirMgr->NumPurchAir,
170 0 : PurchAirName));
171 : }
172 1291012 : if (state.dataPurchasedAirMgr->CheckEquipName(PurchAirNum)) {
173 214 : if (PurchAirName != state.dataPurchasedAirMgr->PurchAir(PurchAirNum).Name) {
174 0 : ShowFatalError(state,
175 0 : format("SimPurchasedAir: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
176 : PurchAirNum,
177 : PurchAirName,
178 0 : state.dataPurchasedAirMgr->PurchAir(PurchAirNum).Name));
179 : }
180 214 : state.dataPurchasedAirMgr->CheckEquipName(PurchAirNum) = false;
181 : }
182 : }
183 :
184 1291226 : InitPurchasedAir(state, PurchAirNum, ControlledZoneNum);
185 :
186 1291226 : CalcPurchAirLoads(state, PurchAirNum, SysOutputProvided, MoistOutputProvided, ControlledZoneNum);
187 :
188 1291226 : UpdatePurchasedAir(state, PurchAirNum, FirstHVACIteration);
189 :
190 1291226 : ReportPurchasedAir(state, PurchAirNum);
191 1291226 : }
192 :
193 257 : void GetPurchasedAir(EnergyPlusData &state)
194 : {
195 :
196 : // SUBROUTINE INFORMATION:
197 : // AUTHOR Russ Taylor
198 : // DATE WRITTEN June 1997
199 : // MODIFIED M. Witte, June 2011, add new features including DCV, economizer, dehumidification
200 : // and humidification controls
201 : // RE-ENGINEERED na
202 :
203 : // PURPOSE OF THIS SUBROUTINE:
204 : // Get the input data for the Purchased Air objects.
205 : // Set up output variables.
206 :
207 : // Using/Aliasing
208 : using NodeInputManager::CheckUniqueNodeNames;
209 : using NodeInputManager::EndUniqueNodeCheck;
210 : using NodeInputManager::GetOnlySingleNode;
211 : using NodeInputManager::InitUniqueNodeCheck;
212 : using OutAirNodeManager::CheckAndAddAirNodeNumber;
213 : using namespace DataLoopNode;
214 : using ZonePlenum::GetReturnPlenumIndex;
215 :
216 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
217 : int PurchAirNum;
218 : int NumAlphas;
219 : int NumNums;
220 : int IOStat;
221 : int CtrlZone; // zone index
222 : int NodeNum; // node index
223 : static constexpr std::string_view RoutineName("GetPurchasedAir: "); // include trailing blank space
224 257 : bool ErrorsFound(false); // If errors detected in input
225 : bool IsOANodeListed; // Flag for OA node name listed in OutdoorAir:Node or Nodelist
226 : bool UniqueNodeError; // Flag for non-unique node error(s)
227 257 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
228 257 : cCurrentModuleObject = "ZoneHVAC:IdealLoadsAirSystem";
229 :
230 257 : auto &PurchAir(state.dataPurchasedAirMgr->PurchAir);
231 :
232 257 : state.dataPurchasedAirMgr->NumPurchAir = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
233 :
234 257 : PurchAir.allocate(state.dataPurchasedAirMgr->NumPurchAir);
235 257 : state.dataPurchasedAirMgr->CheckEquipName.allocate(state.dataPurchasedAirMgr->NumPurchAir);
236 257 : state.dataPurchasedAirMgr->PurchAirNumericFields.allocate(state.dataPurchasedAirMgr->NumPurchAir);
237 257 : state.dataPurchasedAirMgr->CheckEquipName = true;
238 :
239 257 : if (state.dataPurchasedAirMgr->NumPurchAir > 0) {
240 77 : InitUniqueNodeCheck(state, cCurrentModuleObject);
241 291 : for (PurchAirNum = 1; PurchAirNum <= state.dataPurchasedAirMgr->NumPurchAir; ++PurchAirNum) {
242 214 : PurchAir(PurchAirNum).cObjectName = cCurrentModuleObject;
243 :
244 1498 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
245 : cCurrentModuleObject,
246 : PurchAirNum,
247 214 : state.dataIPShortCut->cAlphaArgs,
248 : NumAlphas,
249 214 : state.dataIPShortCut->rNumericArgs,
250 : NumNums,
251 : IOStat,
252 214 : state.dataIPShortCut->lNumericFieldBlanks,
253 214 : state.dataIPShortCut->lAlphaFieldBlanks,
254 214 : state.dataIPShortCut->cAlphaFieldNames,
255 214 : state.dataIPShortCut->cNumericFieldNames);
256 :
257 214 : state.dataPurchasedAirMgr->PurchAirNumericFields(PurchAirNum).FieldNames.allocate(NumNums);
258 214 : state.dataPurchasedAirMgr->PurchAirNumericFields(PurchAirNum).FieldNames = "";
259 214 : state.dataPurchasedAirMgr->PurchAirNumericFields(PurchAirNum).FieldNames = state.dataIPShortCut->cNumericFieldNames;
260 214 : UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
261 :
262 214 : PurchAir(PurchAirNum).Name = state.dataIPShortCut->cAlphaArgs(1);
263 : // get optional availability schedule
264 214 : PurchAir(PurchAirNum).AvailSched = state.dataIPShortCut->cAlphaArgs(2);
265 214 : if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
266 214 : PurchAir(PurchAirNum).AvailSchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
267 : } else {
268 0 : PurchAir(PurchAirNum).AvailSchedPtr = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
269 0 : if (PurchAir(PurchAirNum).AvailSchedPtr == 0) {
270 0 : ShowSevereError(state,
271 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + " invalid data");
272 0 : ShowContinueError(state,
273 0 : "Invalid-not found " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
274 : "\".");
275 0 : ErrorsFound = true;
276 : }
277 : }
278 : // Purchased air supply air node is an outlet node
279 214 : PurchAir(PurchAirNum).ZoneSupplyAirNodeNum = GetOnlySingleNode(state,
280 214 : state.dataIPShortCut->cAlphaArgs(3),
281 : ErrorsFound,
282 : DataLoopNode::ConnectionObjectType::ZoneHVACIdealLoadsAirSystem,
283 214 : state.dataIPShortCut->cAlphaArgs(1),
284 : DataLoopNode::NodeFluidType::Air,
285 : DataLoopNode::ConnectionType::Outlet,
286 : NodeInputManager::CompFluidStream::Primary,
287 214 : ObjectIsNotParent);
288 214 : UniqueNodeError = false;
289 214 : CheckUniqueNodeNames(state,
290 214 : state.dataIPShortCut->cAlphaFieldNames(3),
291 : UniqueNodeError,
292 214 : state.dataIPShortCut->cAlphaArgs(3),
293 214 : state.dataIPShortCut->cAlphaArgs(1));
294 214 : if (UniqueNodeError) ErrorsFound = true;
295 : // If new (optional) exhaust air node name is present, then register it as inlet
296 214 : if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
297 6 : if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
298 1 : PurchAir(PurchAirNum).ZoneExhaustAirNodeNum = GetOnlySingleNode(state,
299 1 : state.dataIPShortCut->cAlphaArgs(4),
300 : ErrorsFound,
301 : DataLoopNode::ConnectionObjectType::ZoneHVACIdealLoadsAirSystem,
302 1 : state.dataIPShortCut->cAlphaArgs(1),
303 : DataLoopNode::NodeFluidType::Air,
304 : DataLoopNode::ConnectionType::Inlet,
305 : NodeInputManager::CompFluidStream::Primary,
306 1 : ObjectIsNotParent);
307 : } else {
308 5 : PurchAir(PurchAirNum).ZoneExhaustAirNodeNum = GetOnlySingleNode(state,
309 5 : state.dataIPShortCut->cAlphaArgs(4),
310 : ErrorsFound,
311 : DataLoopNode::ConnectionObjectType::ZoneHVACIdealLoadsAirSystem,
312 5 : state.dataIPShortCut->cAlphaArgs(1),
313 : DataLoopNode::NodeFluidType::Air,
314 : DataLoopNode::ConnectionType::Outlet,
315 : NodeInputManager::CompFluidStream::Primary,
316 5 : ObjectIsNotParent);
317 : }
318 6 : UniqueNodeError = false;
319 6 : CheckUniqueNodeNames(state,
320 6 : state.dataIPShortCut->cAlphaFieldNames(4),
321 : UniqueNodeError,
322 6 : state.dataIPShortCut->cAlphaArgs(4),
323 6 : state.dataIPShortCut->cAlphaArgs(1));
324 6 : if (UniqueNodeError) ErrorsFound = true;
325 : }
326 214 : if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) {
327 5 : PurchAir(PurchAirNum).PlenumExhaustAirNodeNum = GetOnlySingleNode(state,
328 5 : state.dataIPShortCut->cAlphaArgs(5),
329 : ErrorsFound,
330 : DataLoopNode::ConnectionObjectType::ZoneHVACIdealLoadsAirSystem,
331 5 : state.dataIPShortCut->cAlphaArgs(1),
332 : DataLoopNode::NodeFluidType::Air,
333 : DataLoopNode::ConnectionType::Inlet,
334 : NodeInputManager::CompFluidStream::Primary,
335 5 : ObjectIsNotParent);
336 : }
337 214 : PurchAir(PurchAirNum).MaxHeatSuppAirTemp = state.dataIPShortCut->rNumericArgs(1);
338 214 : PurchAir(PurchAirNum).MinCoolSuppAirTemp = state.dataIPShortCut->rNumericArgs(2);
339 214 : PurchAir(PurchAirNum).MaxHeatSuppAirHumRat = state.dataIPShortCut->rNumericArgs(3);
340 214 : PurchAir(PurchAirNum).MinCoolSuppAirHumRat = state.dataIPShortCut->rNumericArgs(4);
341 :
342 214 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), "NoLimit")) {
343 212 : PurchAir(PurchAirNum).HeatingLimit = LimitType::NoLimit;
344 2 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), "LimitFlowRate")) {
345 2 : if (state.dataIPShortCut->lNumericFieldBlanks(5)) {
346 0 : PurchAir(PurchAirNum).HeatingLimit = LimitType::NoLimit;
347 : } else {
348 2 : PurchAir(PurchAirNum).HeatingLimit = LimitType::LimitFlowRate;
349 : }
350 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), "LimitCapacity")) {
351 0 : if (state.dataIPShortCut->lNumericFieldBlanks(6)) {
352 0 : PurchAir(PurchAirNum).HeatingLimit = LimitType::NoLimit;
353 : } else {
354 0 : PurchAir(PurchAirNum).HeatingLimit = LimitType::LimitCapacity;
355 : }
356 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), "LimitFlowRateAndCapacity")) {
357 0 : if (state.dataIPShortCut->lNumericFieldBlanks(5) && state.dataIPShortCut->lNumericFieldBlanks(6)) {
358 0 : PurchAir(PurchAirNum).HeatingLimit = LimitType::NoLimit;
359 0 : } else if (state.dataIPShortCut->lNumericFieldBlanks(5)) {
360 0 : PurchAir(PurchAirNum).HeatingLimit = LimitType::LimitCapacity;
361 0 : } else if (state.dataIPShortCut->lNumericFieldBlanks(6)) {
362 0 : PurchAir(PurchAirNum).HeatingLimit = LimitType::LimitFlowRate;
363 : } else {
364 0 : PurchAir(PurchAirNum).HeatingLimit = LimitType::LimitFlowRateAndCapacity;
365 : }
366 : } else {
367 0 : ShowSevereError(state,
368 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + " invalid data");
369 0 : ShowContinueError(state,
370 0 : "Invalid-entry " + state.dataIPShortCut->cAlphaFieldNames(6) + "=\"" + state.dataIPShortCut->cAlphaArgs(6) + "\".");
371 0 : ShowContinueError(state, "Valid entries are NoLimit, LimitFlowRate, LimitCapacity, or LimitFlowRateAndCapacity");
372 0 : ErrorsFound = true;
373 : }
374 214 : PurchAir(PurchAirNum).MaxHeatVolFlowRate = state.dataIPShortCut->rNumericArgs(5);
375 214 : PurchAir(PurchAirNum).MaxHeatSensCap = state.dataIPShortCut->rNumericArgs(6);
376 :
377 214 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "NoLimit")) {
378 210 : PurchAir(PurchAirNum).CoolingLimit = LimitType::NoLimit;
379 4 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "LimitFlowRate")) {
380 4 : if (state.dataIPShortCut->lNumericFieldBlanks(7)) {
381 0 : PurchAir(PurchAirNum).CoolingLimit = LimitType::NoLimit;
382 : } else {
383 4 : PurchAir(PurchAirNum).CoolingLimit = LimitType::LimitFlowRate;
384 : }
385 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "LimitCapacity")) {
386 0 : if (state.dataIPShortCut->lNumericFieldBlanks(8)) {
387 0 : PurchAir(PurchAirNum).CoolingLimit = LimitType::NoLimit;
388 : } else {
389 0 : PurchAir(PurchAirNum).CoolingLimit = LimitType::LimitCapacity;
390 : }
391 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "LimitFlowRateAndCapacity")) {
392 0 : if (state.dataIPShortCut->lNumericFieldBlanks(7) && state.dataIPShortCut->lNumericFieldBlanks(8)) {
393 0 : PurchAir(PurchAirNum).CoolingLimit = LimitType::NoLimit;
394 0 : } else if (state.dataIPShortCut->lNumericFieldBlanks(7)) {
395 0 : PurchAir(PurchAirNum).CoolingLimit = LimitType::LimitCapacity;
396 0 : } else if (state.dataIPShortCut->lNumericFieldBlanks(8)) {
397 0 : PurchAir(PurchAirNum).CoolingLimit = LimitType::LimitFlowRate;
398 : } else {
399 0 : PurchAir(PurchAirNum).CoolingLimit = LimitType::LimitFlowRateAndCapacity;
400 : }
401 : } else {
402 0 : ShowSevereError(state,
403 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + " invalid data");
404 0 : ShowContinueError(state,
405 0 : "Invalid-entry " + state.dataIPShortCut->cAlphaFieldNames(7) + "=\"" + state.dataIPShortCut->cAlphaArgs(7) + "\".");
406 0 : ShowContinueError(state, "Valid entries are NoLimit, LimitFlowRate, LimitCapacity, or LimitFlowRateAndCapacity");
407 0 : ErrorsFound = true;
408 : }
409 214 : PurchAir(PurchAirNum).MaxCoolVolFlowRate = state.dataIPShortCut->rNumericArgs(7);
410 214 : PurchAir(PurchAirNum).MaxCoolTotCap = state.dataIPShortCut->rNumericArgs(8);
411 :
412 : // get optional heating availability schedule
413 214 : PurchAir(PurchAirNum).HeatSched = state.dataIPShortCut->cAlphaArgs(8);
414 214 : if (state.dataIPShortCut->lAlphaFieldBlanks(8)) {
415 213 : PurchAir(PurchAirNum).HeatSchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
416 : } else {
417 1 : PurchAir(PurchAirNum).HeatSchedPtr = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(8));
418 1 : if (PurchAir(PurchAirNum).HeatSchedPtr == 0) {
419 0 : ShowSevereError(state,
420 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + " invalid data");
421 0 : ShowContinueError(state,
422 0 : "Invalid-not found " + state.dataIPShortCut->cAlphaFieldNames(8) + "=\"" + state.dataIPShortCut->cAlphaArgs(8) +
423 : "\".");
424 0 : ErrorsFound = true;
425 : }
426 : }
427 : // get optional cooling availability schedule
428 214 : PurchAir(PurchAirNum).CoolSched = state.dataIPShortCut->cAlphaArgs(9);
429 214 : if (state.dataIPShortCut->lAlphaFieldBlanks(9)) {
430 213 : PurchAir(PurchAirNum).CoolSchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
431 : } else {
432 1 : PurchAir(PurchAirNum).CoolSchedPtr = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(9));
433 1 : if (PurchAir(PurchAirNum).CoolSchedPtr == 0) {
434 0 : ShowSevereError(state,
435 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + " invalid data");
436 0 : ShowContinueError(state,
437 0 : "Invalid-not found " + state.dataIPShortCut->cAlphaFieldNames(9) + "=\"" + state.dataIPShortCut->cAlphaArgs(9) +
438 : "\".");
439 0 : ErrorsFound = true;
440 : }
441 : }
442 : // get Dehumidification control type
443 214 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(10), "None")) {
444 1 : PurchAir(PurchAirNum).DehumidCtrlType = HumControl::None;
445 213 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(10), "ConstantSensibleHeatRatio")) {
446 25 : PurchAir(PurchAirNum).DehumidCtrlType = HumControl::ConstantSensibleHeatRatio;
447 188 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(10), "Humidistat")) {
448 1 : PurchAir(PurchAirNum).DehumidCtrlType = HumControl::Humidistat;
449 187 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(10), "ConstantSupplyHumidityRatio")) {
450 187 : PurchAir(PurchAirNum).DehumidCtrlType = HumControl::ConstantSupplyHumidityRatio;
451 : } else {
452 0 : ShowSevereError(state,
453 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + " invalid data");
454 0 : ShowContinueError(
455 0 : state, "Invalid-entry " + state.dataIPShortCut->cAlphaFieldNames(10) + "=\"" + state.dataIPShortCut->cAlphaArgs(10) + "\".");
456 0 : ShowContinueError(state, "Valid entries are ConstantSensibleHeatRatio, Humidistat, or ConstantSupplyHumidityRatio");
457 0 : ErrorsFound = true;
458 : }
459 214 : PurchAir(PurchAirNum).CoolSHR = state.dataIPShortCut->rNumericArgs(9);
460 :
461 : // get Humidification control type
462 214 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(11), "None")) {
463 25 : PurchAir(PurchAirNum).HumidCtrlType = HumControl::None;
464 189 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(11), "Humidistat")) {
465 2 : PurchAir(PurchAirNum).HumidCtrlType = HumControl::Humidistat;
466 187 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(11), "ConstantSupplyHumidityRatio")) {
467 187 : PurchAir(PurchAirNum).HumidCtrlType = HumControl::ConstantSupplyHumidityRatio;
468 : } else {
469 0 : ShowSevereError(state,
470 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + " invalid data");
471 0 : ShowContinueError(
472 0 : state, "Invalid-entry " + state.dataIPShortCut->cAlphaFieldNames(11) + "=\"" + state.dataIPShortCut->cAlphaArgs(11) + "\".");
473 0 : ShowContinueError(state, "Valid entries are None, Humidistat, or ConstantSupplyHumidityRatio");
474 0 : ErrorsFound = true;
475 : }
476 :
477 : // get Design specification outdoor air object
478 214 : if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) {
479 4 : PurchAir(PurchAirNum).OARequirementsPtr =
480 4 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(12), state.dataSize->OARequirements);
481 4 : if (PurchAir(PurchAirNum).OARequirementsPtr == 0) {
482 0 : ShowSevereError(state,
483 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + " invalid data");
484 0 : ShowContinueError(state,
485 0 : "Invalid-not found" + state.dataIPShortCut->cAlphaFieldNames(12) + "=\"" +
486 0 : state.dataIPShortCut->cAlphaArgs(12) + "\".");
487 0 : ErrorsFound = true;
488 : } else {
489 4 : PurchAir(PurchAirNum).OutdoorAir = true;
490 : }
491 : }
492 :
493 : // If outdoor air specified, then get Outdoor air inlet node and other outdoor air inputs
494 214 : if (PurchAir(PurchAirNum).OutdoorAir) {
495 4 : if (state.dataIPShortCut->lAlphaFieldBlanks(13)) {
496 : // If there is outdoor air and outdoor air inlet node is blank, then create one
497 0 : if (len(state.dataIPShortCut->cAlphaArgs(1)) <
498 : DataGlobalConstants::MaxNameLength - 23) { // protect against long name leading to > 100 chars
499 0 : state.dataIPShortCut->cAlphaArgs(13) = state.dataIPShortCut->cAlphaArgs(1) + " OUTDOOR AIR INLET NODE";
500 : } else {
501 0 : state.dataIPShortCut->cAlphaArgs(13) = state.dataIPShortCut->cAlphaArgs(1).substr(0, 75) + " OUTDOOR AIR INLET NODE";
502 : }
503 0 : if (state.dataGlobal->DisplayExtraWarnings) {
504 0 : ShowWarningError(
505 0 : state, std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + " blank field");
506 0 : ShowContinueError(
507 0 : state, state.dataIPShortCut->cAlphaFieldNames(13) + " is blank, but there is outdoor air requested for this system.");
508 0 : ShowContinueError(state, "Creating node name =" + state.dataIPShortCut->cAlphaArgs(13));
509 : }
510 : }
511 : // Register OA node
512 4 : PurchAir(PurchAirNum).OutdoorAirNodeNum = GetOnlySingleNode(state,
513 4 : state.dataIPShortCut->cAlphaArgs(13),
514 : ErrorsFound,
515 : DataLoopNode::ConnectionObjectType::ZoneHVACIdealLoadsAirSystem,
516 4 : state.dataIPShortCut->cAlphaArgs(1),
517 : DataLoopNode::NodeFluidType::Air,
518 : DataLoopNode::ConnectionType::Outlet,
519 : NodeInputManager::CompFluidStream::Primary,
520 4 : ObjectIsNotParent);
521 : // Check if OA node is initialized in OutdoorAir:Node or OutdoorAir:Nodelist
522 4 : CheckAndAddAirNodeNumber(state, PurchAir(PurchAirNum).OutdoorAirNodeNum, IsOANodeListed);
523 4 : if ((!IsOANodeListed) && state.dataGlobal->DisplayExtraWarnings) {
524 0 : ShowWarningError(state,
525 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + " missing data");
526 0 : ShowContinueError(state,
527 0 : state.dataIPShortCut->cAlphaArgs(13) + " does not appear in an OutdoorAir:NodeList or as an OutdoorAir:Node.");
528 0 : ShowContinueError(state, "Adding OutdoorAir:Node=" + state.dataIPShortCut->cAlphaArgs(13));
529 : }
530 4 : UniqueNodeError = false;
531 4 : CheckUniqueNodeNames(state,
532 4 : state.dataIPShortCut->cAlphaFieldNames(13),
533 : UniqueNodeError,
534 4 : state.dataIPShortCut->cAlphaArgs(13),
535 4 : state.dataIPShortCut->cAlphaArgs(1));
536 4 : if (UniqueNodeError) ErrorsFound = true;
537 :
538 : // get Demand controlled ventilation type
539 4 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(14), "None")) {
540 3 : PurchAir(PurchAirNum).DCVType = DCV::None;
541 1 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(14), "OccupancySchedule")) {
542 1 : PurchAir(PurchAirNum).DCVType = DCV::OccupancySchedule;
543 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(14), "CO2Setpoint")) {
544 0 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
545 0 : PurchAir(PurchAirNum).DCVType = DCV::CO2SetPoint;
546 : } else {
547 0 : PurchAir(PurchAirNum).DCVType = DCV::None;
548 0 : ShowWarningError(
549 0 : state, std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + " invalid data");
550 0 : ShowContinueError(state,
551 0 : state.dataIPShortCut->cAlphaFieldNames(14) + '=' + state.dataIPShortCut->cAlphaArgs(14) +
552 : " but CO2 simulation is not active.");
553 0 : ShowContinueError(state, "Resetting " + state.dataIPShortCut->cAlphaFieldNames(14) + " to NoDCV");
554 0 : ShowContinueError(state,
555 : "To activate CO2 simulation, use ZoneAirContaminantBalance object and specify \"Carbon Dioxide "
556 : "Concentration\"=\"Yes\".");
557 : }
558 : } else {
559 0 : ShowSevereError(state,
560 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + " invalid data");
561 0 : ShowContinueError(state,
562 0 : "Invalid-entry " + state.dataIPShortCut->cAlphaFieldNames(14) + '=' + state.dataIPShortCut->cAlphaArgs(14));
563 0 : ShowContinueError(state, "Valid entries are None, OccupancySchedule, or CO2Setpoint");
564 0 : ErrorsFound = true;
565 : }
566 : // get Outdoor air economizer type
567 4 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(15), "NoEconomizer")) {
568 1 : PurchAir(PurchAirNum).EconomizerType = Econ::NoEconomizer;
569 3 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(15), "DifferentialDryBulb")) {
570 2 : PurchAir(PurchAirNum).EconomizerType = Econ::DifferentialDryBulb;
571 1 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(15), "DifferentialEnthalpy")) {
572 1 : PurchAir(PurchAirNum).EconomizerType = Econ::DifferentialEnthalpy;
573 : } else {
574 0 : ShowSevereError(state,
575 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + " invalid data");
576 0 : ShowContinueError(state,
577 0 : "Invalid-entry " + state.dataIPShortCut->cAlphaFieldNames(15) + '=' + state.dataIPShortCut->cAlphaArgs(15));
578 0 : ShowContinueError(state, "Valid entries are NoEconomizer, DifferentialDryBulb, or DifferentialEnthalpy");
579 0 : ErrorsFound = true;
580 : }
581 : // get Outdoor air heat recovery type and effectiveness
582 4 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(16), "None")) {
583 2 : PurchAir(PurchAirNum).HtRecType = HeatRecovery::None;
584 2 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(16), "Sensible")) {
585 1 : PurchAir(PurchAirNum).HtRecType = HeatRecovery::Sensible;
586 1 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(16), "Enthalpy")) {
587 1 : PurchAir(PurchAirNum).HtRecType = HeatRecovery::Enthalpy;
588 : } else {
589 0 : ShowSevereError(state,
590 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + " invalid data");
591 0 : ShowContinueError(state,
592 0 : "Invalid-entry " + state.dataIPShortCut->cAlphaFieldNames(16) + '=' + state.dataIPShortCut->cAlphaArgs(16));
593 0 : ShowContinueError(state, "Valid entries are None, Sensible, or Enthalpy");
594 0 : ErrorsFound = true;
595 : }
596 : } else { // No outdoorair
597 210 : PurchAir(PurchAirNum).DCVType = DCV::None;
598 210 : PurchAir(PurchAirNum).EconomizerType = Econ::NoEconomizer;
599 210 : PurchAir(PurchAirNum).HtRecType = HeatRecovery::None;
600 : }
601 :
602 214 : PurchAir(PurchAirNum).HtRecSenEff = state.dataIPShortCut->rNumericArgs(10);
603 214 : PurchAir(PurchAirNum).HtRecLatEff = state.dataIPShortCut->rNumericArgs(11);
604 :
605 1275 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
606 1061 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
607 2053 : for (NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++NodeNum) {
608 1015 : if (PurchAir(PurchAirNum).ZoneSupplyAirNodeNum == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(NodeNum)) {
609 214 : PurchAir(PurchAirNum).ZonePtr = CtrlZone;
610 : }
611 : }
612 : }
613 :
614 214 : PurchAir(PurchAirNum).HVACSizingIndex = 0;
615 214 : if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) {
616 0 : PurchAir(PurchAirNum).HVACSizingIndex =
617 0 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(17), state.dataSize->ZoneHVACSizing);
618 0 : if (PurchAir(PurchAirNum).HVACSizingIndex == 0) {
619 0 : ShowSevereError(state, state.dataIPShortCut->cAlphaFieldNames(17) + " = " + state.dataIPShortCut->cAlphaArgs(17) + " not found.");
620 0 : ShowContinueError(state, "Occurs in " + cCurrentModuleObject + " = " + PurchAir(PurchAirNum).Name);
621 0 : ErrorsFound = true;
622 : }
623 : }
624 :
625 : // initialize the calculated and report values
626 214 : PurchAir(PurchAirNum).MaxHeatMassFlowRate = 0.0;
627 214 : PurchAir(PurchAirNum).MaxCoolMassFlowRate = 0.0;
628 214 : PurchAir(PurchAirNum).SenHeatEnergy = 0.0;
629 214 : PurchAir(PurchAirNum).LatHeatEnergy = 0.0;
630 214 : PurchAir(PurchAirNum).TotHeatEnergy = 0.0;
631 214 : PurchAir(PurchAirNum).SenCoolEnergy = 0.0;
632 214 : PurchAir(PurchAirNum).LatCoolEnergy = 0.0;
633 214 : PurchAir(PurchAirNum).TotCoolEnergy = 0.0;
634 214 : PurchAir(PurchAirNum).ZoneSenHeatEnergy = 0.0;
635 214 : PurchAir(PurchAirNum).ZoneLatHeatEnergy = 0.0;
636 214 : PurchAir(PurchAirNum).ZoneTotHeatEnergy = 0.0;
637 214 : PurchAir(PurchAirNum).ZoneSenCoolEnergy = 0.0;
638 214 : PurchAir(PurchAirNum).ZoneLatCoolEnergy = 0.0;
639 214 : PurchAir(PurchAirNum).ZoneTotCoolEnergy = 0.0;
640 214 : PurchAir(PurchAirNum).OASenHeatEnergy = 0.0;
641 214 : PurchAir(PurchAirNum).OALatHeatEnergy = 0.0;
642 214 : PurchAir(PurchAirNum).OATotHeatEnergy = 0.0;
643 214 : PurchAir(PurchAirNum).OASenCoolEnergy = 0.0;
644 214 : PurchAir(PurchAirNum).OALatCoolEnergy = 0.0;
645 214 : PurchAir(PurchAirNum).OATotCoolEnergy = 0.0;
646 214 : PurchAir(PurchAirNum).HtRecSenHeatEnergy = 0.0;
647 214 : PurchAir(PurchAirNum).HtRecLatHeatEnergy = 0.0;
648 214 : PurchAir(PurchAirNum).HtRecTotHeatEnergy = 0.0;
649 214 : PurchAir(PurchAirNum).HtRecSenCoolEnergy = 0.0;
650 214 : PurchAir(PurchAirNum).HtRecLatCoolEnergy = 0.0;
651 214 : PurchAir(PurchAirNum).HtRecTotCoolEnergy = 0.0;
652 214 : PurchAir(PurchAirNum).SenHeatRate = 0.0;
653 214 : PurchAir(PurchAirNum).LatHeatRate = 0.0;
654 214 : PurchAir(PurchAirNum).TotHeatRate = 0.0;
655 214 : PurchAir(PurchAirNum).SenCoolRate = 0.0;
656 214 : PurchAir(PurchAirNum).LatCoolRate = 0.0;
657 214 : PurchAir(PurchAirNum).TotCoolRate = 0.0;
658 214 : PurchAir(PurchAirNum).ZoneSenHeatRate = 0.0;
659 214 : PurchAir(PurchAirNum).ZoneLatHeatRate = 0.0;
660 214 : PurchAir(PurchAirNum).ZoneTotHeatRate = 0.0;
661 214 : PurchAir(PurchAirNum).ZoneSenCoolRate = 0.0;
662 214 : PurchAir(PurchAirNum).ZoneLatCoolRate = 0.0;
663 214 : PurchAir(PurchAirNum).ZoneTotCoolRate = 0.0;
664 214 : PurchAir(PurchAirNum).OASenHeatRate = 0.0;
665 214 : PurchAir(PurchAirNum).OALatHeatRate = 0.0;
666 214 : PurchAir(PurchAirNum).OATotHeatRate = 0.0;
667 214 : PurchAir(PurchAirNum).OASenCoolRate = 0.0;
668 214 : PurchAir(PurchAirNum).OALatCoolRate = 0.0;
669 214 : PurchAir(PurchAirNum).OATotCoolRate = 0.0;
670 214 : PurchAir(PurchAirNum).HtRecSenHeatRate = 0.0;
671 214 : PurchAir(PurchAirNum).HtRecLatHeatRate = 0.0;
672 214 : PurchAir(PurchAirNum).HtRecTotHeatRate = 0.0;
673 214 : PurchAir(PurchAirNum).HtRecSenCoolRate = 0.0;
674 214 : PurchAir(PurchAirNum).HtRecLatCoolRate = 0.0;
675 214 : PurchAir(PurchAirNum).HtRecTotCoolRate = 0.0;
676 :
677 214 : PurchAir(PurchAirNum).OutdoorAirMassFlowRate = 0.0;
678 214 : PurchAir(PurchAirNum).OutdoorAirVolFlowRateStdRho = 0.0;
679 214 : PurchAir(PurchAirNum).SupplyAirMassFlowRate = 0.0;
680 214 : PurchAir(PurchAirNum).SupplyAirVolFlowRateStdRho = 0.0;
681 : }
682 77 : EndUniqueNodeCheck(state, cCurrentModuleObject);
683 : }
684 :
685 471 : for (PurchAirNum = 1; PurchAirNum <= state.dataPurchasedAirMgr->NumPurchAir; ++PurchAirNum) {
686 :
687 : // Setup Output variables
688 : // energy variables
689 856 : SetupOutputVariable(state,
690 : "Zone Ideal Loads Supply Air Sensible Heating Energy",
691 : OutputProcessor::Unit::J,
692 214 : PurchAir(PurchAirNum).SenHeatEnergy,
693 : OutputProcessor::SOVTimeStepType::System,
694 : OutputProcessor::SOVStoreType::Summed,
695 428 : PurchAir(PurchAirNum).Name);
696 856 : SetupOutputVariable(state,
697 : "Zone Ideal Loads Supply Air Latent Heating Energy",
698 : OutputProcessor::Unit::J,
699 214 : PurchAir(PurchAirNum).LatHeatEnergy,
700 : OutputProcessor::SOVTimeStepType::System,
701 : OutputProcessor::SOVStoreType::Summed,
702 428 : PurchAir(PurchAirNum).Name);
703 856 : SetupOutputVariable(state,
704 : "Zone Ideal Loads Supply Air Total Heating Energy",
705 : OutputProcessor::Unit::J,
706 214 : PurchAir(PurchAirNum).TotHeatEnergy,
707 : OutputProcessor::SOVTimeStepType::System,
708 : OutputProcessor::SOVStoreType::Summed,
709 214 : PurchAir(PurchAirNum).Name,
710 : _,
711 : "DISTRICTHEATING",
712 : "Heating",
713 : _,
714 214 : "System");
715 856 : SetupOutputVariable(state,
716 : "Zone Ideal Loads Supply Air Sensible Cooling Energy",
717 : OutputProcessor::Unit::J,
718 214 : PurchAir(PurchAirNum).SenCoolEnergy,
719 : OutputProcessor::SOVTimeStepType::System,
720 : OutputProcessor::SOVStoreType::Summed,
721 428 : PurchAir(PurchAirNum).Name);
722 856 : SetupOutputVariable(state,
723 : "Zone Ideal Loads Supply Air Latent Cooling Energy",
724 : OutputProcessor::Unit::J,
725 214 : PurchAir(PurchAirNum).LatCoolEnergy,
726 : OutputProcessor::SOVTimeStepType::System,
727 : OutputProcessor::SOVStoreType::Summed,
728 428 : PurchAir(PurchAirNum).Name);
729 856 : SetupOutputVariable(state,
730 : "Zone Ideal Loads Supply Air Total Cooling Energy",
731 : OutputProcessor::Unit::J,
732 214 : PurchAir(PurchAirNum).TotCoolEnergy,
733 : OutputProcessor::SOVTimeStepType::System,
734 : OutputProcessor::SOVStoreType::Summed,
735 214 : PurchAir(PurchAirNum).Name,
736 : _,
737 : "DISTRICTCOOLING",
738 : "Cooling",
739 : _,
740 214 : "System");
741 856 : SetupOutputVariable(state,
742 : "Zone Ideal Loads Zone Sensible Heating Energy",
743 : OutputProcessor::Unit::J,
744 214 : PurchAir(PurchAirNum).ZoneSenHeatEnergy,
745 : OutputProcessor::SOVTimeStepType::System,
746 : OutputProcessor::SOVStoreType::Summed,
747 428 : PurchAir(PurchAirNum).Name);
748 856 : SetupOutputVariable(state,
749 : "Zone Ideal Loads Zone Latent Heating Energy",
750 : OutputProcessor::Unit::J,
751 214 : PurchAir(PurchAirNum).ZoneLatHeatEnergy,
752 : OutputProcessor::SOVTimeStepType::System,
753 : OutputProcessor::SOVStoreType::Summed,
754 428 : PurchAir(PurchAirNum).Name);
755 856 : SetupOutputVariable(state,
756 : "Zone Ideal Loads Zone Total Heating Energy",
757 : OutputProcessor::Unit::J,
758 214 : PurchAir(PurchAirNum).ZoneTotHeatEnergy,
759 : OutputProcessor::SOVTimeStepType::System,
760 : OutputProcessor::SOVStoreType::Summed,
761 428 : PurchAir(PurchAirNum).Name);
762 856 : SetupOutputVariable(state,
763 : "Zone Ideal Loads Zone Sensible Cooling Energy",
764 : OutputProcessor::Unit::J,
765 214 : PurchAir(PurchAirNum).ZoneSenCoolEnergy,
766 : OutputProcessor::SOVTimeStepType::System,
767 : OutputProcessor::SOVStoreType::Summed,
768 428 : PurchAir(PurchAirNum).Name);
769 856 : SetupOutputVariable(state,
770 : "Zone Ideal Loads Zone Latent Cooling Energy",
771 : OutputProcessor::Unit::J,
772 214 : PurchAir(PurchAirNum).ZoneLatCoolEnergy,
773 : OutputProcessor::SOVTimeStepType::System,
774 : OutputProcessor::SOVStoreType::Summed,
775 428 : PurchAir(PurchAirNum).Name);
776 856 : SetupOutputVariable(state,
777 : "Zone Ideal Loads Zone Total Cooling Energy",
778 : OutputProcessor::Unit::J,
779 214 : PurchAir(PurchAirNum).ZoneTotCoolEnergy,
780 : OutputProcessor::SOVTimeStepType::System,
781 : OutputProcessor::SOVStoreType::Summed,
782 428 : PurchAir(PurchAirNum).Name);
783 856 : SetupOutputVariable(state,
784 : "Zone Ideal Loads Outdoor Air Sensible Heating Energy",
785 : OutputProcessor::Unit::J,
786 214 : PurchAir(PurchAirNum).OASenHeatEnergy,
787 : OutputProcessor::SOVTimeStepType::System,
788 : OutputProcessor::SOVStoreType::Summed,
789 428 : PurchAir(PurchAirNum).Name);
790 856 : SetupOutputVariable(state,
791 : "Zone Ideal Loads Outdoor Air Latent Heating Energy",
792 : OutputProcessor::Unit::J,
793 214 : PurchAir(PurchAirNum).OALatHeatEnergy,
794 : OutputProcessor::SOVTimeStepType::System,
795 : OutputProcessor::SOVStoreType::Summed,
796 428 : PurchAir(PurchAirNum).Name);
797 856 : SetupOutputVariable(state,
798 : "Zone Ideal Loads Outdoor Air Total Heating Energy",
799 : OutputProcessor::Unit::J,
800 214 : PurchAir(PurchAirNum).OATotHeatEnergy,
801 : OutputProcessor::SOVTimeStepType::System,
802 : OutputProcessor::SOVStoreType::Summed,
803 428 : PurchAir(PurchAirNum).Name);
804 856 : SetupOutputVariable(state,
805 : "Zone Ideal Loads Outdoor Air Sensible Cooling Energy",
806 : OutputProcessor::Unit::J,
807 214 : PurchAir(PurchAirNum).OASenCoolEnergy,
808 : OutputProcessor::SOVTimeStepType::System,
809 : OutputProcessor::SOVStoreType::Summed,
810 428 : PurchAir(PurchAirNum).Name);
811 856 : SetupOutputVariable(state,
812 : "Zone Ideal Loads Outdoor Air Latent Cooling Energy",
813 : OutputProcessor::Unit::J,
814 214 : PurchAir(PurchAirNum).OALatCoolEnergy,
815 : OutputProcessor::SOVTimeStepType::System,
816 : OutputProcessor::SOVStoreType::Summed,
817 428 : PurchAir(PurchAirNum).Name);
818 856 : SetupOutputVariable(state,
819 : "Zone Ideal Loads Outdoor Air Total Cooling Energy",
820 : OutputProcessor::Unit::J,
821 214 : PurchAir(PurchAirNum).OATotCoolEnergy,
822 : OutputProcessor::SOVTimeStepType::System,
823 : OutputProcessor::SOVStoreType::Summed,
824 428 : PurchAir(PurchAirNum).Name);
825 856 : SetupOutputVariable(state,
826 : "Zone Ideal Loads Heat Recovery Sensible Heating Energy",
827 : OutputProcessor::Unit::J,
828 214 : PurchAir(PurchAirNum).HtRecSenHeatEnergy,
829 : OutputProcessor::SOVTimeStepType::System,
830 : OutputProcessor::SOVStoreType::Summed,
831 428 : PurchAir(PurchAirNum).Name);
832 856 : SetupOutputVariable(state,
833 : "Zone Ideal Loads Heat Recovery Latent Heating Energy",
834 : OutputProcessor::Unit::J,
835 214 : PurchAir(PurchAirNum).HtRecLatHeatEnergy,
836 : OutputProcessor::SOVTimeStepType::System,
837 : OutputProcessor::SOVStoreType::Summed,
838 428 : PurchAir(PurchAirNum).Name);
839 856 : SetupOutputVariable(state,
840 : "Zone Ideal Loads Heat Recovery Total Heating Energy",
841 : OutputProcessor::Unit::J,
842 214 : PurchAir(PurchAirNum).HtRecTotHeatEnergy,
843 : OutputProcessor::SOVTimeStepType::System,
844 : OutputProcessor::SOVStoreType::Summed,
845 428 : PurchAir(PurchAirNum).Name);
846 856 : SetupOutputVariable(state,
847 : "Zone Ideal Loads Heat Recovery Sensible Cooling Energy",
848 : OutputProcessor::Unit::J,
849 214 : PurchAir(PurchAirNum).HtRecSenCoolEnergy,
850 : OutputProcessor::SOVTimeStepType::System,
851 : OutputProcessor::SOVStoreType::Summed,
852 428 : PurchAir(PurchAirNum).Name);
853 856 : SetupOutputVariable(state,
854 : "Zone Ideal Loads Heat Recovery Latent Cooling Energy",
855 : OutputProcessor::Unit::J,
856 214 : PurchAir(PurchAirNum).HtRecLatCoolEnergy,
857 : OutputProcessor::SOVTimeStepType::System,
858 : OutputProcessor::SOVStoreType::Summed,
859 428 : PurchAir(PurchAirNum).Name);
860 856 : SetupOutputVariable(state,
861 : "Zone Ideal Loads Heat Recovery Total Cooling Energy",
862 : OutputProcessor::Unit::J,
863 214 : PurchAir(PurchAirNum).HtRecTotCoolEnergy,
864 : OutputProcessor::SOVTimeStepType::System,
865 : OutputProcessor::SOVStoreType::Summed,
866 428 : PurchAir(PurchAirNum).Name);
867 :
868 : // rate variables
869 856 : SetupOutputVariable(state,
870 : "Zone Ideal Loads Supply Air Sensible Heating Rate",
871 : OutputProcessor::Unit::W,
872 214 : PurchAir(PurchAirNum).SenHeatRate,
873 : OutputProcessor::SOVTimeStepType::System,
874 : OutputProcessor::SOVStoreType::Average,
875 428 : PurchAir(PurchAirNum).Name);
876 856 : SetupOutputVariable(state,
877 : "Zone Ideal Loads Supply Air Latent Heating Rate",
878 : OutputProcessor::Unit::W,
879 214 : PurchAir(PurchAirNum).LatHeatRate,
880 : OutputProcessor::SOVTimeStepType::System,
881 : OutputProcessor::SOVStoreType::Average,
882 428 : PurchAir(PurchAirNum).Name);
883 856 : SetupOutputVariable(state,
884 : "Zone Ideal Loads Supply Air Total Heating Rate",
885 : OutputProcessor::Unit::W,
886 214 : PurchAir(PurchAirNum).TotHeatRate,
887 : OutputProcessor::SOVTimeStepType::System,
888 : OutputProcessor::SOVStoreType::Average,
889 428 : PurchAir(PurchAirNum).Name);
890 856 : SetupOutputVariable(state,
891 : "Zone Ideal Loads Supply Air Sensible Cooling Rate",
892 : OutputProcessor::Unit::W,
893 214 : PurchAir(PurchAirNum).SenCoolRate,
894 : OutputProcessor::SOVTimeStepType::System,
895 : OutputProcessor::SOVStoreType::Average,
896 428 : PurchAir(PurchAirNum).Name);
897 856 : SetupOutputVariable(state,
898 : "Zone Ideal Loads Supply Air Latent Cooling Rate",
899 : OutputProcessor::Unit::W,
900 214 : PurchAir(PurchAirNum).LatCoolRate,
901 : OutputProcessor::SOVTimeStepType::System,
902 : OutputProcessor::SOVStoreType::Average,
903 428 : PurchAir(PurchAirNum).Name);
904 856 : SetupOutputVariable(state,
905 : "Zone Ideal Loads Supply Air Total Cooling Rate",
906 : OutputProcessor::Unit::W,
907 214 : PurchAir(PurchAirNum).TotCoolRate,
908 : OutputProcessor::SOVTimeStepType::System,
909 : OutputProcessor::SOVStoreType::Average,
910 428 : PurchAir(PurchAirNum).Name);
911 856 : SetupOutputVariable(state,
912 : "Zone Ideal Loads Zone Sensible Heating Rate",
913 : OutputProcessor::Unit::W,
914 214 : PurchAir(PurchAirNum).ZoneSenHeatRate,
915 : OutputProcessor::SOVTimeStepType::System,
916 : OutputProcessor::SOVStoreType::Average,
917 428 : PurchAir(PurchAirNum).Name);
918 856 : SetupOutputVariable(state,
919 : "Zone Ideal Loads Zone Latent Heating Rate",
920 : OutputProcessor::Unit::W,
921 214 : PurchAir(PurchAirNum).ZoneLatHeatRate,
922 : OutputProcessor::SOVTimeStepType::System,
923 : OutputProcessor::SOVStoreType::Average,
924 428 : PurchAir(PurchAirNum).Name);
925 856 : SetupOutputVariable(state,
926 : "Zone Ideal Loads Zone Total Heating Rate",
927 : OutputProcessor::Unit::W,
928 214 : PurchAir(PurchAirNum).ZoneTotHeatRate,
929 : OutputProcessor::SOVTimeStepType::System,
930 : OutputProcessor::SOVStoreType::Average,
931 428 : PurchAir(PurchAirNum).Name);
932 856 : SetupOutputVariable(state,
933 : "Zone Ideal Loads Zone Sensible Cooling Rate",
934 : OutputProcessor::Unit::W,
935 214 : PurchAir(PurchAirNum).ZoneSenCoolRate,
936 : OutputProcessor::SOVTimeStepType::System,
937 : OutputProcessor::SOVStoreType::Average,
938 428 : PurchAir(PurchAirNum).Name);
939 856 : SetupOutputVariable(state,
940 : "Zone Ideal Loads Zone Latent Cooling Rate",
941 : OutputProcessor::Unit::W,
942 214 : PurchAir(PurchAirNum).ZoneLatCoolRate,
943 : OutputProcessor::SOVTimeStepType::System,
944 : OutputProcessor::SOVStoreType::Average,
945 428 : PurchAir(PurchAirNum).Name);
946 856 : SetupOutputVariable(state,
947 : "Zone Ideal Loads Zone Total Cooling Rate",
948 : OutputProcessor::Unit::W,
949 214 : PurchAir(PurchAirNum).ZoneTotCoolRate,
950 : OutputProcessor::SOVTimeStepType::System,
951 : OutputProcessor::SOVStoreType::Average,
952 428 : PurchAir(PurchAirNum).Name);
953 856 : SetupOutputVariable(state,
954 : "Zone Ideal Loads Outdoor Air Sensible Heating Rate",
955 : OutputProcessor::Unit::W,
956 214 : PurchAir(PurchAirNum).OASenHeatRate,
957 : OutputProcessor::SOVTimeStepType::System,
958 : OutputProcessor::SOVStoreType::Average,
959 428 : PurchAir(PurchAirNum).Name);
960 856 : SetupOutputVariable(state,
961 : "Zone Ideal Loads Outdoor Air Latent Heating Rate",
962 : OutputProcessor::Unit::W,
963 214 : PurchAir(PurchAirNum).OALatHeatRate,
964 : OutputProcessor::SOVTimeStepType::System,
965 : OutputProcessor::SOVStoreType::Average,
966 428 : PurchAir(PurchAirNum).Name);
967 856 : SetupOutputVariable(state,
968 : "Zone Ideal Loads Outdoor Air Total Heating Rate",
969 : OutputProcessor::Unit::W,
970 214 : PurchAir(PurchAirNum).OATotHeatRate,
971 : OutputProcessor::SOVTimeStepType::System,
972 : OutputProcessor::SOVStoreType::Average,
973 428 : PurchAir(PurchAirNum).Name);
974 856 : SetupOutputVariable(state,
975 : "Zone Ideal Loads Outdoor Air Sensible Cooling Rate",
976 : OutputProcessor::Unit::W,
977 214 : PurchAir(PurchAirNum).OASenCoolRate,
978 : OutputProcessor::SOVTimeStepType::System,
979 : OutputProcessor::SOVStoreType::Average,
980 428 : PurchAir(PurchAirNum).Name);
981 856 : SetupOutputVariable(state,
982 : "Zone Ideal Loads Outdoor Air Latent Cooling Rate",
983 : OutputProcessor::Unit::W,
984 214 : PurchAir(PurchAirNum).OALatCoolRate,
985 : OutputProcessor::SOVTimeStepType::System,
986 : OutputProcessor::SOVStoreType::Average,
987 428 : PurchAir(PurchAirNum).Name);
988 856 : SetupOutputVariable(state,
989 : "Zone Ideal Loads Outdoor Air Total Cooling Rate",
990 : OutputProcessor::Unit::W,
991 214 : PurchAir(PurchAirNum).OATotCoolRate,
992 : OutputProcessor::SOVTimeStepType::System,
993 : OutputProcessor::SOVStoreType::Average,
994 428 : PurchAir(PurchAirNum).Name);
995 856 : SetupOutputVariable(state,
996 : "Zone Ideal Loads Heat Recovery Sensible Heating Rate",
997 : OutputProcessor::Unit::W,
998 214 : PurchAir(PurchAirNum).HtRecSenHeatRate,
999 : OutputProcessor::SOVTimeStepType::System,
1000 : OutputProcessor::SOVStoreType::Average,
1001 428 : PurchAir(PurchAirNum).Name);
1002 856 : SetupOutputVariable(state,
1003 : "Zone Ideal Loads Heat Recovery Latent Heating Rate",
1004 : OutputProcessor::Unit::W,
1005 214 : PurchAir(PurchAirNum).HtRecLatHeatRate,
1006 : OutputProcessor::SOVTimeStepType::System,
1007 : OutputProcessor::SOVStoreType::Average,
1008 428 : PurchAir(PurchAirNum).Name);
1009 856 : SetupOutputVariable(state,
1010 : "Zone Ideal Loads Heat Recovery Total Heating Rate",
1011 : OutputProcessor::Unit::W,
1012 214 : PurchAir(PurchAirNum).HtRecTotHeatRate,
1013 : OutputProcessor::SOVTimeStepType::System,
1014 : OutputProcessor::SOVStoreType::Average,
1015 428 : PurchAir(PurchAirNum).Name);
1016 856 : SetupOutputVariable(state,
1017 : "Zone Ideal Loads Heat Recovery Sensible Cooling Rate",
1018 : OutputProcessor::Unit::W,
1019 214 : PurchAir(PurchAirNum).HtRecSenCoolRate,
1020 : OutputProcessor::SOVTimeStepType::System,
1021 : OutputProcessor::SOVStoreType::Average,
1022 428 : PurchAir(PurchAirNum).Name);
1023 856 : SetupOutputVariable(state,
1024 : "Zone Ideal Loads Heat Recovery Latent Cooling Rate",
1025 : OutputProcessor::Unit::W,
1026 214 : PurchAir(PurchAirNum).HtRecLatCoolRate,
1027 : OutputProcessor::SOVTimeStepType::System,
1028 : OutputProcessor::SOVStoreType::Average,
1029 428 : PurchAir(PurchAirNum).Name);
1030 856 : SetupOutputVariable(state,
1031 : "Zone Ideal Loads Heat Recovery Total Cooling Rate",
1032 : OutputProcessor::Unit::W,
1033 214 : PurchAir(PurchAirNum).HtRecTotCoolRate,
1034 : OutputProcessor::SOVTimeStepType::System,
1035 : OutputProcessor::SOVStoreType::Average,
1036 428 : PurchAir(PurchAirNum).Name);
1037 :
1038 856 : SetupOutputVariable(state,
1039 : "Zone Ideal Loads Economizer Active Time",
1040 : OutputProcessor::Unit::hr,
1041 214 : PurchAir(PurchAirNum).TimeEconoActive,
1042 : OutputProcessor::SOVTimeStepType::System,
1043 : OutputProcessor::SOVStoreType::Summed,
1044 428 : PurchAir(PurchAirNum).Name);
1045 856 : SetupOutputVariable(state,
1046 : "Zone Ideal Loads Heat Recovery Active Time",
1047 : OutputProcessor::Unit::hr,
1048 214 : PurchAir(PurchAirNum).TimeHtRecActive,
1049 : OutputProcessor::SOVTimeStepType::System,
1050 : OutputProcessor::SOVStoreType::Summed,
1051 428 : PurchAir(PurchAirNum).Name);
1052 :
1053 856 : SetupOutputVariable(state,
1054 : "Zone Ideal Loads Hybrid Ventilation Available Status",
1055 : OutputProcessor::Unit::None,
1056 214 : PurchAir(PurchAirNum).AvailStatus,
1057 : OutputProcessor::SOVTimeStepType::System,
1058 : OutputProcessor::SOVStoreType::Average,
1059 428 : PurchAir(PurchAirNum).Name);
1060 :
1061 : // air flows
1062 856 : SetupOutputVariable(state,
1063 : "Zone Ideal Loads Outdoor Air Mass Flow Rate",
1064 : OutputProcessor::Unit::kg_s,
1065 214 : PurchAir(PurchAirNum).OutdoorAirMassFlowRate,
1066 : OutputProcessor::SOVTimeStepType::System,
1067 : OutputProcessor::SOVStoreType::Average,
1068 428 : PurchAir(PurchAirNum).Name);
1069 856 : SetupOutputVariable(state,
1070 : "Zone Ideal Loads Outdoor Air Standard Density Volume Flow Rate",
1071 : OutputProcessor::Unit::m3_s,
1072 214 : PurchAir(PurchAirNum).OutdoorAirVolFlowRateStdRho,
1073 : OutputProcessor::SOVTimeStepType::System,
1074 : OutputProcessor::SOVStoreType::Average,
1075 428 : PurchAir(PurchAirNum).Name);
1076 856 : SetupOutputVariable(state,
1077 : "Zone Ideal Loads Supply Air Mass Flow Rate",
1078 : OutputProcessor::Unit::kg_s,
1079 214 : PurchAir(PurchAirNum).SupplyAirMassFlowRate,
1080 : OutputProcessor::SOVTimeStepType::System,
1081 : OutputProcessor::SOVStoreType::Average,
1082 428 : PurchAir(PurchAirNum).Name);
1083 856 : SetupOutputVariable(state,
1084 : "Zone Ideal Loads Supply Air Standard Density Volume Flow Rate",
1085 : OutputProcessor::Unit::m3_s,
1086 214 : PurchAir(PurchAirNum).SupplyAirVolFlowRateStdRho,
1087 : OutputProcessor::SOVTimeStepType::System,
1088 : OutputProcessor::SOVStoreType::Average,
1089 428 : PurchAir(PurchAirNum).Name);
1090 :
1091 : // Supply Air temperature
1092 856 : SetupOutputVariable(state,
1093 : "Zone Ideal Loads Supply Air Temperature",
1094 : OutputProcessor::Unit::C,
1095 214 : PurchAir(PurchAirNum).SupplyTemp,
1096 : OutputProcessor::SOVTimeStepType::System,
1097 : OutputProcessor::SOVStoreType::Average,
1098 428 : PurchAir(PurchAirNum).Name);
1099 : // Supply Air Humidity Ratio
1100 856 : SetupOutputVariable(state,
1101 : "Zone Ideal Loads Supply Air Humidity Ratio",
1102 : OutputProcessor::Unit::kgWater_kgDryAir,
1103 214 : PurchAir(PurchAirNum).SupplyHumRat,
1104 : OutputProcessor::SOVTimeStepType::System,
1105 : OutputProcessor::SOVStoreType::Average,
1106 428 : PurchAir(PurchAirNum).Name);
1107 :
1108 : // Mixed Air temperature
1109 856 : SetupOutputVariable(state,
1110 : "Zone Ideal Loads Mixed Air Temperature",
1111 : OutputProcessor::Unit::C,
1112 214 : PurchAir(PurchAirNum).MixedAirTemp,
1113 : OutputProcessor::SOVTimeStepType::System,
1114 : OutputProcessor::SOVStoreType::Average,
1115 428 : PurchAir(PurchAirNum).Name);
1116 : // Mixed Air Humidity Ratio
1117 856 : SetupOutputVariable(state,
1118 : "Zone Ideal Loads Mixed Air Humidity Ratio",
1119 : OutputProcessor::Unit::kgWater_kgDryAir,
1120 214 : PurchAir(PurchAirNum).MixedAirHumRat,
1121 : OutputProcessor::SOVTimeStepType::System,
1122 : OutputProcessor::SOVStoreType::Average,
1123 428 : PurchAir(PurchAirNum).Name);
1124 :
1125 214 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
1126 76 : SetupEMSActuator(state,
1127 : "Ideal Loads Air System",
1128 19 : PurchAir(PurchAirNum).Name,
1129 : "Air Mass Flow Rate",
1130 : "[kg/s]",
1131 19 : PurchAir(PurchAirNum).EMSOverrideMdotOn,
1132 57 : PurchAir(PurchAirNum).EMSValueMassFlowRate);
1133 76 : SetupEMSActuator(state,
1134 : "Ideal Loads Air System",
1135 19 : PurchAir(PurchAirNum).Name,
1136 : "Outdoor Air Mass Flow Rate",
1137 : "[kg/s]",
1138 19 : PurchAir(PurchAirNum).EMSOverrideOAMdotOn,
1139 57 : PurchAir(PurchAirNum).EMSValueOAMassFlowRate);
1140 76 : SetupEMSActuator(state,
1141 : "Ideal Loads Air System",
1142 19 : PurchAir(PurchAirNum).Name,
1143 : "Air Temperature",
1144 : "[C]",
1145 19 : PurchAir(PurchAirNum).EMSOverrideSupplyTempOn,
1146 57 : PurchAir(PurchAirNum).EMSValueSupplyTemp);
1147 76 : SetupEMSActuator(state,
1148 : "Ideal Loads Air System",
1149 19 : PurchAir(PurchAirNum).Name,
1150 : "Air Humidity Ratio",
1151 : "[kgWater/kgDryAir]",
1152 19 : PurchAir(PurchAirNum).EMSOverrideSupplyHumRatOn,
1153 57 : PurchAir(PurchAirNum).EMSValueSupplyHumRat);
1154 : }
1155 : }
1156 :
1157 257 : if (ErrorsFound) {
1158 0 : ShowFatalError(state, std::string{RoutineName} + "Errors found in input. Preceding conditions cause termination.");
1159 : }
1160 257 : }
1161 :
1162 1291226 : void InitPurchasedAir(EnergyPlusData &state, int const PurchAirNum, int const ControlledZoneNum)
1163 : {
1164 :
1165 : // SUBROUTINE INFORMATION:
1166 : // AUTHOR Russ Taylor
1167 : // DATE WRITTEN Nov 1997
1168 :
1169 : // PURPOSE OF THIS SUBROUTINE:
1170 : // Initialize the PurchAir data structure.
1171 :
1172 : // Using/Aliasing
1173 : using DataZoneEquipment::CheckZoneEquipmentList;
1174 : using General::FindNumberInList;
1175 : using ZonePlenum::GetReturnPlenumIndex;
1176 : using ZonePlenum::GetReturnPlenumName;
1177 :
1178 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1179 : int Loop;
1180 : bool UnitOn; // simple checks for error
1181 : bool CoolOn; // simple checks for error
1182 : bool HeatOn; // simple checks for error
1183 : int SupplyNodeNum; // Node number for ideal loads supply node
1184 : int ExhaustNodeNum; // Node number for ideal loads exhaust node
1185 : int NodeIndex; // Array index of zone inlet or zone exhaust node that matches ideal loads node
1186 : bool UseReturnNode; // simple checks for error
1187 :
1188 1291226 : auto &PurchAir(state.dataPurchasedAirMgr->PurchAir);
1189 :
1190 : // Do the Begin Simulation initializations
1191 1291226 : if (state.dataPurchasedAirMgr->InitPurchasedAirMyOneTimeFlag) {
1192 77 : state.dataPurchasedAirMgr->InitPurchasedAirMyEnvrnFlag.allocate(state.dataPurchasedAirMgr->NumPurchAir);
1193 77 : state.dataPurchasedAirMgr->InitPurchasedAirMySizeFlag.allocate(state.dataPurchasedAirMgr->NumPurchAir);
1194 77 : state.dataPurchasedAirMgr->InitPurchasedAirOneTimeUnitInitsDone.allocate(state.dataPurchasedAirMgr->NumPurchAir);
1195 77 : state.dataPurchasedAirMgr->InitPurchasedAirMyEnvrnFlag = true;
1196 77 : state.dataPurchasedAirMgr->InitPurchasedAirMySizeFlag = true;
1197 77 : state.dataPurchasedAirMgr->InitPurchasedAirOneTimeUnitInitsDone = false;
1198 77 : state.dataPurchasedAirMgr->InitPurchasedAirMyOneTimeFlag = false;
1199 : }
1200 :
1201 : // need to check all units to see if they are on Zone Equipment List or issue warning
1202 1291226 : if (!state.dataPurchasedAirMgr->InitPurchasedAirZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
1203 77 : state.dataPurchasedAirMgr->InitPurchasedAirZoneEquipmentListChecked = true;
1204 291 : for (Loop = 1; Loop <= state.dataPurchasedAirMgr->NumPurchAir; ++Loop) {
1205 :
1206 : // link with return plenum if used (i.e., PlenumExhaustAirNodeNum will be non-zero)
1207 214 : if (PurchAir(Loop).PlenumExhaustAirNodeNum > 0) {
1208 5 : PurchAir(Loop).ReturnPlenumIndex = GetReturnPlenumIndex(state, PurchAir(Loop).PlenumExhaustAirNodeNum);
1209 5 : if (PurchAir(Loop).ReturnPlenumIndex > 0) {
1210 5 : GetReturnPlenumName(state, PurchAir(Loop).ReturnPlenumIndex, PurchAir(Loop).ReturnPlenumName);
1211 5 : InitializePlenumArrays(state, Loop);
1212 : } else {
1213 0 : ShowSevereError(state,
1214 0 : "InitPurchasedAir: " + PurchAir(Loop).cObjectName + " = " + PurchAir(Loop).Name +
1215 : " cannot find ZoneHVAC:ReturnPlenum. It will not be simulated.");
1216 : }
1217 : }
1218 :
1219 214 : if (CheckZoneEquipmentList(state, PurchAir(Loop).cObjectName, PurchAir(Loop).Name)) continue;
1220 0 : ShowSevereError(state,
1221 0 : "InitPurchasedAir: " + PurchAir(Loop).cObjectName + " = " + PurchAir(Loop).Name +
1222 : " is not on any ZoneHVAC:EquipmentList. It will not be simulated.");
1223 : }
1224 : }
1225 :
1226 : // one time inits for each unit - links PurchAirNum with static input data from ControlledZoneNum and ActualZoneNum
1227 1291226 : if (!state.dataPurchasedAirMgr->InitPurchasedAirOneTimeUnitInitsDone(PurchAirNum)) {
1228 214 : state.dataPurchasedAirMgr->InitPurchasedAirOneTimeUnitInitsDone(PurchAirNum) = true;
1229 :
1230 : // Is the supply node really a zone inlet node?
1231 : // this check has to be done here because of SimPurchasedAir passing in ControlledZoneNum
1232 214 : SupplyNodeNum = PurchAir(PurchAirNum).ZoneSupplyAirNodeNum;
1233 214 : if (SupplyNodeNum > 0) {
1234 428 : NodeIndex = FindNumberInList(SupplyNodeNum,
1235 214 : state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode,
1236 214 : state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes);
1237 214 : if (NodeIndex == 0) {
1238 0 : ShowSevereError(state, "InitPurchasedAir: In " + PurchAir(PurchAirNum).cObjectName + " = " + PurchAir(PurchAirNum).Name);
1239 0 : ShowContinueError(state, "Zone Supply Air Node Name=" + state.dataLoopNodes->NodeID(SupplyNodeNum) + " is not a zone inlet node.");
1240 0 : ShowContinueError(state,
1241 0 : "Check ZoneHVAC:EquipmentConnections for zone=" + state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneName);
1242 0 : ShowFatalError(state, "Preceding condition causes termination.");
1243 : }
1244 : }
1245 :
1246 : // Set recirculation node number
1247 : // If exhaust node is specified, then recirculation is exhaust node, otherwise use zone return node
1248 : // this check has to be done here because of SimPurchasedAir passing in ControlledZoneNum
1249 214 : UseReturnNode = false;
1250 214 : if (PurchAir(PurchAirNum).ZoneExhaustAirNodeNum > 0) {
1251 6 : ExhaustNodeNum = PurchAir(PurchAirNum).ZoneExhaustAirNodeNum;
1252 12 : NodeIndex = FindNumberInList(ExhaustNodeNum,
1253 6 : state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ExhaustNode,
1254 6 : state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumExhaustNodes);
1255 6 : if (NodeIndex == 0) {
1256 0 : ShowSevereError(state, "InitPurchasedAir: In " + PurchAir(PurchAirNum).cObjectName + " = " + PurchAir(PurchAirNum).Name);
1257 0 : ShowContinueError(state,
1258 0 : "Zone Exhaust Air Node Name=" + state.dataLoopNodes->NodeID(ExhaustNodeNum) + " is not a zone exhaust node.");
1259 0 : ShowContinueError(state,
1260 0 : "Check ZoneHVAC:EquipmentConnections for zone=" + state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneName);
1261 0 : ShowContinueError(state, "Zone return air node will be used for ideal loads recirculation air.");
1262 0 : UseReturnNode = true;
1263 : } else {
1264 6 : PurchAir(PurchAirNum).ZoneRecircAirNodeNum = PurchAir(PurchAirNum).ZoneExhaustAirNodeNum;
1265 : }
1266 : } else {
1267 208 : UseReturnNode = true;
1268 : }
1269 214 : if (UseReturnNode) {
1270 208 : if (state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumReturnNodes == 1) {
1271 208 : PurchAir(PurchAirNum).ZoneRecircAirNodeNum = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ReturnNode(1);
1272 0 : } else if (state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumReturnNodes > 1) {
1273 0 : ShowWarningError(state, "InitPurchasedAir: In " + PurchAir(PurchAirNum).cObjectName + " = " + PurchAir(PurchAirNum).Name);
1274 0 : ShowContinueError(state,
1275 : "No Zone Exhaust Air Node Name has been specified for this system and the zone has more than one Return Air Node.");
1276 0 : ShowContinueError(state,
1277 0 : "Using the first return air node =" +
1278 0 : state.dataLoopNodes->NodeID(state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ReturnNode(1)));
1279 : } else {
1280 0 : ShowFatalError(state, "InitPurchasedAir: In " + PurchAir(PurchAirNum).cObjectName + " = " + PurchAir(PurchAirNum).Name);
1281 0 : ShowContinueError(
1282 : state,
1283 : " Invalid recirculation node. No exhaust or return node has been specified for this zone in ZoneHVAC:EquipmentConnections.");
1284 0 : ShowFatalError(state, "Preceding condition causes termination.");
1285 : }
1286 : }
1287 : // If there is OA and economizer is active, then there must be a limit on cooling flow rate
1288 214 : if (PurchAir(PurchAirNum).OutdoorAir && (PurchAir(PurchAirNum).EconomizerType != Econ::NoEconomizer)) {
1289 3 : if ((PurchAir(PurchAirNum).CoolingLimit == LimitType::NoLimit) || (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitCapacity)) {
1290 0 : ShowSevereError(state, "InitPurchasedAir: In " + PurchAir(PurchAirNum).cObjectName + " = " + PurchAir(PurchAirNum).Name);
1291 0 : ShowContinueError(state, "There is outdoor air with economizer active but there is no limit on cooling air flow rate.");
1292 0 : ShowContinueError(state,
1293 : "Cooling Limit must be set to LimitFlowRate or LimitFlowRateAndCapacity, and Maximum Cooling Air Flow Rate "
1294 : "must be set to a value or autosize.");
1295 0 : ShowContinueError(state, "Simulation will proceed with no limit on outdoor air flow rate.");
1296 : }
1297 : }
1298 : }
1299 :
1300 1291226 : if (!state.dataGlobal->SysSizingCalc && state.dataPurchasedAirMgr->InitPurchasedAirMySizeFlag(PurchAirNum)) {
1301 :
1302 214 : SizePurchasedAir(state, PurchAirNum);
1303 :
1304 214 : state.dataPurchasedAirMgr->InitPurchasedAirMySizeFlag(PurchAirNum) = false;
1305 : }
1306 :
1307 : // Do the Begin Environment initializations
1308 1291226 : if (state.dataGlobal->BeginEnvrnFlag && state.dataPurchasedAirMgr->InitPurchasedAirMyEnvrnFlag(PurchAirNum)) {
1309 :
1310 2220 : if ((PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRate) ||
1311 1104 : (PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRateAndCapacity)) {
1312 12 : PurchAir(PurchAirNum).MaxHeatMassFlowRate = state.dataEnvrn->StdRhoAir * PurchAir(PurchAirNum).MaxHeatVolFlowRate;
1313 : } else {
1314 1104 : PurchAir(PurchAirNum).MaxHeatMassFlowRate = 0.0;
1315 : }
1316 2208 : if ((PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRate) ||
1317 1092 : (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRateAndCapacity)) {
1318 24 : PurchAir(PurchAirNum).MaxCoolMassFlowRate = state.dataEnvrn->StdRhoAir * PurchAir(PurchAirNum).MaxCoolVolFlowRate;
1319 : } else {
1320 1092 : PurchAir(PurchAirNum).MaxCoolMassFlowRate = 0.0;
1321 : }
1322 1116 : state.dataPurchasedAirMgr->InitPurchasedAirMyEnvrnFlag(PurchAirNum) = false;
1323 : }
1324 :
1325 1291226 : if (!state.dataGlobal->BeginEnvrnFlag) {
1326 1283398 : state.dataPurchasedAirMgr->InitPurchasedAirMyEnvrnFlag(PurchAirNum) = true;
1327 : }
1328 :
1329 : // These initializations are done every iteration
1330 : // check that supply air temps can meet the zone thermostat setpoints
1331 3077910 : if (PurchAir(PurchAirNum).MinCoolSuppAirTemp > state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ControlledZoneNum) &&
1332 1291226 : state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ControlledZoneNum) != 0 && PurchAir(PurchAirNum).CoolingLimit == LimitType::NoLimit) {
1333 : // Check if the unit is scheduled off
1334 0 : UnitOn = true;
1335 : // IF (PurchAir(PurchAirNum)%AvailSchedPtr > 0) THEN
1336 0 : if (GetCurrentScheduleValue(state, PurchAir(PurchAirNum).AvailSchedPtr) <= 0) {
1337 0 : UnitOn = false;
1338 : }
1339 : // END IF
1340 : // Check if cooling available
1341 0 : CoolOn = true;
1342 : // IF (PurchAir(PurchAirNum)%CoolSchedPtr > 0) THEN
1343 0 : if (GetCurrentScheduleValue(state, PurchAir(PurchAirNum).CoolSchedPtr) <= 0) {
1344 0 : CoolOn = false;
1345 : }
1346 : // END IF
1347 0 : if (UnitOn && CoolOn) {
1348 0 : if (PurchAir(PurchAirNum).CoolErrIndex == 0) {
1349 0 : ShowSevereError(state,
1350 0 : "InitPurchasedAir: For " + PurchAir(PurchAirNum).cObjectName + " = " + PurchAir(PurchAirNum).Name + " serving Zone " +
1351 0 : state.dataHeatBal->Zone(ControlledZoneNum).Name);
1352 0 : ShowContinueError(state,
1353 0 : format("..the minimum supply air temperature for cooling [{:.2R}] is greater than the zone cooling mean air "
1354 : "temperature (MAT) setpoint [{:.2R}].",
1355 0 : PurchAir(PurchAirNum).MinCoolSuppAirTemp,
1356 0 : state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ControlledZoneNum)));
1357 0 : ShowContinueError(state, "..For operative and comfort thermostat controls, the MAT setpoint is computed.");
1358 0 : ShowContinueError(state, "..This error may indicate that the mean radiant temperature or another comfort factor is too warm.");
1359 0 : ShowContinueError(state, "Unit availability is nominally ON and Cooling availability is nominally ON.");
1360 0 : ShowContinueError(state, format("Limit Cooling Capacity Type={}", cLimitType(PurchAir(PurchAirNum).CoolingLimit)));
1361 : // could check for optemp control or comfort control here
1362 0 : ShowContinueErrorTimeStamp(state, "");
1363 : }
1364 0 : ShowRecurringSevereErrorAtEnd(state,
1365 0 : "InitPurchasedAir: For " + PurchAir(PurchAirNum).cObjectName + " = " + PurchAir(PurchAirNum).Name +
1366 0 : " serving Zone " + state.dataHeatBal->Zone(ControlledZoneNum).Name +
1367 : ", the minimum supply air temperature for cooling error continues",
1368 0 : PurchAir(PurchAirNum).CoolErrIndex,
1369 0 : PurchAir(PurchAirNum).MinCoolSuppAirTemp,
1370 0 : PurchAir(PurchAirNum).MinCoolSuppAirTemp,
1371 : _,
1372 : "C",
1373 : "C");
1374 : }
1375 : }
1376 2582452 : if (PurchAir(PurchAirNum).MaxHeatSuppAirTemp < state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ControlledZoneNum) &&
1377 1291226 : state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ControlledZoneNum) != 0 && PurchAir(PurchAirNum).HeatingLimit == LimitType::NoLimit) {
1378 : // Check if the unit is scheduled off
1379 0 : UnitOn = true;
1380 : // IF (PurchAir(PurchAirNum)%AvailSchedPtr > 0) THEN
1381 0 : if (GetCurrentScheduleValue(state, PurchAir(PurchAirNum).AvailSchedPtr) <= 0) {
1382 0 : UnitOn = false;
1383 : }
1384 : // END IF
1385 : // Check if heating and cooling available
1386 0 : HeatOn = true;
1387 : // IF (PurchAir(PurchAirNum)%HeatSchedPtr > 0) THEN
1388 0 : if (GetCurrentScheduleValue(state, PurchAir(PurchAirNum).HeatSchedPtr) <= 0) {
1389 0 : HeatOn = false;
1390 : }
1391 : // END IF
1392 0 : if (UnitOn && HeatOn) {
1393 0 : if (PurchAir(PurchAirNum).HeatErrIndex == 0) {
1394 0 : ShowSevereMessage(state,
1395 0 : "InitPurchasedAir: For " + PurchAir(PurchAirNum).cObjectName + " = " + PurchAir(PurchAirNum).Name +
1396 0 : " serving Zone " + state.dataHeatBal->Zone(ControlledZoneNum).Name);
1397 0 : ShowContinueError(state,
1398 0 : format("..the maximum supply air temperature for heating [{:.2R}] is less than the zone mean air temperature "
1399 : "heating setpoint [{:.2R}].",
1400 0 : PurchAir(PurchAirNum).MaxHeatSuppAirTemp,
1401 0 : state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ControlledZoneNum)));
1402 0 : ShowContinueError(state, "..For operative and comfort thermostat controls, the MAT setpoint is computed.");
1403 0 : ShowContinueError(state, "..This error may indicate that the mean radiant temperature or another comfort factor is too cold.");
1404 0 : ShowContinueError(state, "Unit availability is nominally ON and Heating availability is nominally ON.");
1405 0 : ShowContinueError(state, format("Limit Heating Capacity Type={}", cLimitType(PurchAir(PurchAirNum).HeatingLimit)));
1406 : // could check for optemp control or comfort control here
1407 0 : ShowContinueErrorTimeStamp(state, "");
1408 : }
1409 0 : ShowRecurringSevereErrorAtEnd(state,
1410 0 : "InitPurchasedAir: For " + PurchAir(PurchAirNum).cObjectName + " = " + PurchAir(PurchAirNum).Name +
1411 0 : " serving Zone " + state.dataHeatBal->Zone(ControlledZoneNum).Name +
1412 : ", maximum supply air temperature for heating error continues",
1413 0 : PurchAir(PurchAirNum).HeatErrIndex,
1414 0 : PurchAir(PurchAirNum).MaxHeatSuppAirTemp,
1415 0 : PurchAir(PurchAirNum).MaxHeatSuppAirTemp,
1416 : _,
1417 : "C",
1418 : "C");
1419 : }
1420 : }
1421 : // IF (ErrorsFound .and. .not. WarmupFlag) THEN
1422 : // CALL ShowFatalError(state, 'Preceding conditions cause termination.')
1423 : // ENDIF
1424 1291226 : }
1425 :
1426 214 : void SizePurchasedAir(EnergyPlusData &state, int const PurchAirNum)
1427 : {
1428 :
1429 : // SUBROUTINE INFORMATION:
1430 : // AUTHOR Fred Buhl
1431 : // DATE WRITTEN April 2003
1432 : // MODIFIED M. Witte, June 2011, add sizing for new capacity fields
1433 : // August 2013 Daeho Kang, add component sizing table entries
1434 : // RE-ENGINEERED na
1435 :
1436 : // PURPOSE OF THIS SUBROUTINE:
1437 : // This subroutine is for sizing Purchased Air Components for which flow rates have not been
1438 : // specified in the input.
1439 :
1440 : // METHODOLOGY EMPLOYED:
1441 : // Obtains flow rates from the zone sizing arrays.
1442 :
1443 : // Using/Aliasing
1444 : using namespace DataSizing;
1445 : using DataHVACGlobals::CoolingCapacitySizing;
1446 : using DataHVACGlobals::HeatingAirflowSizing;
1447 : using DataHVACGlobals::HeatingCapacitySizing;
1448 : using Psychrometrics::CPCW;
1449 : using Psychrometrics::CPHW;
1450 : using Psychrometrics::PsyCpAirFnW;
1451 : using Psychrometrics::PsyHFnTdbW;
1452 : using Psychrometrics::RhoH2O;
1453 :
1454 : // SUBROUTINE PARAMETER DEFINITIONS:
1455 : static constexpr std::string_view RoutineName("SizePurchasedAir: "); // include trailing blank space
1456 :
1457 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1458 : bool IsAutoSize; // Indicator to autosize
1459 : Real64 MaxHeatVolFlowRateDes; // Autosized maximum heating air flow for reporting
1460 : Real64 MaxHeatVolFlowRateUser; // Hardsized maximum heating air flow for reporting
1461 : Real64 MaxCoolVolFlowRateDes; // Autosized maximum cooling air flow for reporting
1462 : Real64 MaxCoolVolFlowRateUser; // Hardsized maximum cooling air flow for reporting
1463 : Real64 MaxHeatSensCapDes; // Autosized maximum sensible heating capacity for reporting
1464 : Real64 MaxHeatSensCapUser; // Hardsized maximum sensible heating capacity for reporting
1465 : Real64 MaxCoolTotCapDes; // Autosized maximum sensible cooling capacity for reporting
1466 : Real64 MaxCoolTotCapUser; // Hardsized maximum sensible cooling capacity for reporting
1467 428 : std::string CompName; // component name
1468 428 : std::string CompType; // component type
1469 428 : std::string SizingString; // input field sizing description (e.g., Nominal Capacity)
1470 : Real64 TempSize; // autosized value of coil input field
1471 214 : int FieldNum = 2; // IDD numeric field number where input field description is found
1472 : int SizingMethod; // Integer representation of sizing method name (e.g., CoolingAirflowSizing, HeatingAirflowSizing, CoolingCapacitySizing,
1473 : // HeatingCapacitySizing, etc.)
1474 : bool PrintFlag; // TRUE when sizing information is reported in the eio file
1475 : int zoneHVACIndex; // index of zoneHVAC equipment sizing specification
1476 214 : int SAFMethod(0); // supply air flow rate sizing method (SupplyAirFlowRate, FlowPerFloorArea, FractionOfAutosizedCoolingAirflow,
1477 : // FractionOfAutosizedHeatingAirflow ...)
1478 214 : int CapSizingMethod(0); // capacity sizing methods (HeatingDesignCapacity, CapacityPerFloorArea, FractionOfAutosizedCoolingCapacity, and
1479 : // FractionOfAutosizedHeatingCapacity )
1480 214 : Real64 CoolingAirVolFlowDes(0.0); // cooling supply air flow rate
1481 214 : Real64 HeatingAirVolFlowDes(0.0); // heating supply air flow rate
1482 :
1483 214 : auto &PurchAir(state.dataPurchasedAirMgr->PurchAir);
1484 214 : auto &ZoneEqSizing(state.dataSize->ZoneEqSizing);
1485 :
1486 214 : IsAutoSize = false;
1487 214 : MaxHeatVolFlowRateDes = 0.0;
1488 214 : MaxHeatVolFlowRateUser = 0.0;
1489 214 : MaxCoolVolFlowRateDes = 0.0;
1490 214 : MaxCoolVolFlowRateUser = 0.0;
1491 214 : MaxHeatSensCapDes = 0.0;
1492 214 : MaxHeatSensCapUser = 0.0;
1493 214 : MaxCoolTotCapDes = 0.0;
1494 214 : MaxCoolTotCapUser = 0.0;
1495 :
1496 214 : state.dataSize->ZoneHeatingOnlyFan = false;
1497 214 : state.dataSize->ZoneCoolingOnlyFan = false;
1498 214 : CompType = PurchAir(PurchAirNum).cObjectName;
1499 214 : CompName = PurchAir(PurchAirNum).Name;
1500 214 : bool ErrorsFound = false;
1501 :
1502 214 : if (state.dataSize->CurZoneEqNum > 0) {
1503 214 : if (PurchAir(PurchAirNum).HVACSizingIndex > 0) {
1504 0 : state.dataSize->DataZoneNumber = PurchAir(PurchAirNum).ZonePtr;
1505 0 : zoneHVACIndex = PurchAir(PurchAirNum).HVACSizingIndex;
1506 :
1507 0 : FieldNum = 5; // N5 , \field Maximum Heating Air Flow Rate
1508 0 : PrintFlag = true;
1509 0 : SizingString = state.dataPurchasedAirMgr->PurchAirNumericFields(PurchAirNum).FieldNames(FieldNum) + " [m3/s]";
1510 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).HeatingSAFMethod > 0) {
1511 0 : SizingMethod = HeatingAirflowSizing;
1512 0 : state.dataSize->ZoneHeatingOnlyFan = true;
1513 0 : SAFMethod = state.dataSize->ZoneHVACSizing(zoneHVACIndex).HeatingSAFMethod;
1514 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).SizingMethod(SizingMethod) = SAFMethod;
1515 0 : if (SAFMethod == SupplyAirFlowRate || SAFMethod == FlowPerFloorArea || SAFMethod == FractionOfAutosizedHeatingAirflow) {
1516 0 : if (SAFMethod == SupplyAirFlowRate) {
1517 0 : if ((state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow == AutoSize) &&
1518 0 : ((PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRate) ||
1519 0 : (PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRateAndCapacity))) {
1520 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow;
1521 0 : HeatingAirFlowSizer sizingHeatingAirFlow;
1522 0 : sizingHeatingAirFlow.overrideSizingString(SizingString);
1523 : // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1524 0 : sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1525 0 : HeatingAirVolFlowDes = sizingHeatingAirFlow.size(state, TempSize, ErrorsFound);
1526 : } else {
1527 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow > 0.0) {
1528 0 : HeatingAirFlowSizer sizingHeatingAirFlow;
1529 0 : sizingHeatingAirFlow.overrideSizingString(SizingString);
1530 : // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1531 0 : sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1532 0 : HeatingAirVolFlowDes =
1533 0 : sizingHeatingAirFlow.size(state, state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow, ErrorsFound);
1534 : }
1535 : }
1536 0 : } else if (SAFMethod == FlowPerFloorArea) {
1537 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).SystemAirFlow = true;
1538 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).AirVolFlow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow *
1539 0 : state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
1540 0 : TempSize = ZoneEqSizing(state.dataSize->CurZoneEqNum).AirVolFlow;
1541 0 : state.dataSize->DataScalableSizingON = true;
1542 0 : HeatingAirFlowSizer sizingHeatingAirFlow;
1543 0 : sizingHeatingAirFlow.overrideSizingString(SizingString);
1544 : // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1545 0 : sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1546 0 : HeatingAirVolFlowDes = sizingHeatingAirFlow.size(state, TempSize, ErrorsFound);
1547 0 : } else if (SAFMethod == FractionOfAutosizedHeatingAirflow) {
1548 0 : state.dataSize->DataFracOfAutosizedHeatingAirflow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow;
1549 0 : if ((state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow == AutoSize) &&
1550 0 : ((PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRate) ||
1551 0 : (PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRateAndCapacity))) {
1552 0 : TempSize = AutoSize;
1553 0 : state.dataSize->DataScalableSizingON = true;
1554 0 : HeatingAirFlowSizer sizingHeatingAirFlow;
1555 0 : sizingHeatingAirFlow.overrideSizingString(SizingString);
1556 : // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1557 0 : sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1558 0 : HeatingAirVolFlowDes = sizingHeatingAirFlow.size(state, TempSize, ErrorsFound);
1559 : }
1560 :
1561 : } else {
1562 : // Invalid sizing method
1563 0 : }
1564 0 : } else if (SAFMethod == FlowPerHeatingCapacity) {
1565 0 : SizingMethod = HeatingCapacitySizing;
1566 0 : TempSize = AutoSize;
1567 0 : PrintFlag = false;
1568 0 : if ((state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow == AutoSize) &&
1569 0 : ((PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRate) ||
1570 0 : (PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRateAndCapacity))) {
1571 0 : TempSize = AutoSize;
1572 0 : state.dataSize->DataScalableSizingON = true;
1573 0 : HeatingCapacitySizer sizerHeatingCapacity;
1574 0 : sizerHeatingCapacity.overrideSizingString(SizingString);
1575 0 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1576 0 : state.dataSize->DataAutosizedHeatingCapacity = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
1577 0 : state.dataSize->DataFlowPerHeatingCapacity = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxHeatAirVolFlow;
1578 0 : SizingMethod = HeatingAirflowSizing;
1579 0 : PrintFlag = true;
1580 0 : TempSize = AutoSize;
1581 0 : HeatingAirFlowSizer sizingHeatingAirFlow;
1582 0 : sizingHeatingAirFlow.overrideSizingString(SizingString);
1583 : // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1584 0 : sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1585 0 : HeatingAirVolFlowDes = sizingHeatingAirFlow.size(state, TempSize, ErrorsFound);
1586 : }
1587 : }
1588 0 : MaxHeatVolFlowRateDes = max(0.0, HeatingAirVolFlowDes);
1589 0 : PurchAir(PurchAirNum).MaxHeatVolFlowRate = MaxHeatVolFlowRateDes;
1590 0 : state.dataSize->ZoneHeatingOnlyFan = false;
1591 :
1592 0 : CapSizingMethod = state.dataSize->ZoneHVACSizing(zoneHVACIndex).HeatingCapMethod;
1593 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).CapSizingMethod = CapSizingMethod;
1594 0 : if (CapSizingMethod == HeatingDesignCapacity || CapSizingMethod == CapacityPerFloorArea ||
1595 0 : CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
1596 0 : if (CapSizingMethod == HeatingDesignCapacity) {
1597 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity > 0.0) {
1598 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).HeatingCapacity = true;
1599 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesHeatingLoad =
1600 0 : state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity;
1601 : }
1602 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity;
1603 0 : } else if (CapSizingMethod == CapacityPerFloorArea) {
1604 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).HeatingCapacity = true;
1605 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesHeatingLoad =
1606 0 : state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity *
1607 0 : state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
1608 0 : state.dataSize->DataScalableSizingON = true;
1609 0 : } else if (CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
1610 0 : state.dataSize->DataFracOfAutosizedHeatingCapacity = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledHeatingCapacity;
1611 0 : TempSize = AutoSize;
1612 : }
1613 : }
1614 0 : SizingMethod = HeatingCapacitySizing;
1615 0 : SizingString = "";
1616 0 : state.dataSize->ZoneHeatingOnlyFan = true;
1617 0 : PrintFlag = false;
1618 0 : HeatingCapacitySizer sizerHeatingCapacity;
1619 0 : sizerHeatingCapacity.overrideSizingString(SizingString);
1620 0 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1621 0 : MaxHeatSensCapDes = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
1622 0 : state.dataSize->ZoneHeatingOnlyFan = false;
1623 0 : if (MaxHeatSensCapDes < SmallLoad) {
1624 0 : MaxHeatSensCapDes = 0.0;
1625 : }
1626 0 : if (IsAutoSize) {
1627 0 : PurchAir(PurchAirNum).MaxHeatSensCap = MaxHeatSensCapDes;
1628 0 : BaseSizer::reportSizerOutput(state,
1629 0 : PurchAir(PurchAirNum).cObjectName,
1630 0 : PurchAir(PurchAirNum).Name,
1631 : "Design Size Maximum Sensible Heating Capacity [W]",
1632 0 : MaxHeatSensCapDes);
1633 : // If there is OA, check if sizing calcs have OA>0, throw warning if not
1634 0 : if ((PurchAir(PurchAirNum).OutdoorAir) && (state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA == 0.0)) {
1635 0 : ShowWarningError(state, "InitPurchasedAir: In " + PurchAir(PurchAirNum).cObjectName + " = " + PurchAir(PurchAirNum).Name);
1636 0 : ShowContinueError(state, "There is outdoor air specified in this object, but the design outdoor air flow rate for this ");
1637 0 : ShowContinueError(state, "zone is zero. The Maximum Sensible Heating Capacity will be autosized for zero outdoor air flow. ");
1638 0 : ShowContinueError(state,
1639 0 : "Check the outdoor air specifications in the Sizing:Zone object for zone " +
1640 0 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).ZoneName + '.');
1641 : }
1642 : } else {
1643 0 : if (PurchAir(PurchAirNum).MaxHeatSensCap > 0.0 && MaxHeatSensCapDes > 0.0) {
1644 0 : MaxHeatSensCapUser = PurchAir(PurchAirNum).MaxHeatSensCap;
1645 0 : BaseSizer::reportSizerOutput(state,
1646 0 : PurchAir(PurchAirNum).cObjectName,
1647 0 : PurchAir(PurchAirNum).Name,
1648 : "Design Size Maximum Sensible Heating Capacity [W]",
1649 : MaxHeatSensCapDes,
1650 : "User-Specified Maximum Sensible Heating Capacity [W]",
1651 0 : MaxHeatSensCapUser);
1652 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1653 0 : if ((std::abs(MaxHeatSensCapDes - MaxHeatSensCapUser) / MaxHeatSensCapUser) > state.dataSize->AutoVsHardSizingThreshold) {
1654 0 : ShowMessage(state,
1655 0 : "SizePurchasedAir: Potential issue with equipment sizing for " + PurchAir(PurchAirNum).cObjectName + ' ' +
1656 0 : PurchAir(PurchAirNum).Name);
1657 0 : ShowContinueError(state,
1658 0 : format("...User-Specified Maximum Sensible Heating Capacity of {:.2R} [W]", MaxHeatSensCapUser));
1659 0 : ShowContinueError(
1660 0 : state, format("...differs from Design Size Maximum Sensible Heating Capacity of {:.2R} [W]", MaxHeatSensCapDes));
1661 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1662 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1663 : }
1664 : }
1665 : }
1666 : }
1667 : }
1668 :
1669 0 : PrintFlag = true;
1670 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).CoolingSAFMethod > 0) {
1671 0 : state.dataSize->ZoneCoolingOnlyFan = true;
1672 0 : SAFMethod = state.dataSize->ZoneHVACSizing(zoneHVACIndex).CoolingSAFMethod;
1673 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).SizingMethod(SizingMethod) = SAFMethod;
1674 0 : if (SAFMethod == SupplyAirFlowRate || SAFMethod == FlowPerFloorArea || SAFMethod == FractionOfAutosizedCoolingAirflow) {
1675 0 : if (SAFMethod == SupplyAirFlowRate) {
1676 0 : if ((state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow == AutoSize) &&
1677 0 : ((PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRate) ||
1678 0 : (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRateAndCapacity) ||
1679 0 : (PurchAir(PurchAirNum).OutdoorAir && PurchAir(PurchAirNum).EconomizerType != Econ::NoEconomizer))) {
1680 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
1681 0 : CoolingAirFlowSizer sizingCoolingAirFlow;
1682 0 : sizingCoolingAirFlow.overrideSizingString(SizingString);
1683 0 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1684 0 : CoolingAirVolFlowDes = sizingCoolingAirFlow.size(state, TempSize, ErrorsFound);
1685 : } else {
1686 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow > 0.0) {
1687 0 : CoolingAirVolFlowDes = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
1688 0 : CoolingAirFlowSizer sizingCoolingAirFlow;
1689 0 : sizingCoolingAirFlow.overrideSizingString(SizingString);
1690 0 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1691 0 : CoolingAirVolFlowDes = sizingCoolingAirFlow.size(state, CoolingAirVolFlowDes, ErrorsFound);
1692 : }
1693 : }
1694 0 : } else if (SAFMethod == FlowPerFloorArea) {
1695 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).SystemAirFlow = true;
1696 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).AirVolFlow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow *
1697 0 : state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
1698 0 : TempSize = ZoneEqSizing(state.dataSize->CurZoneEqNum).AirVolFlow;
1699 0 : state.dataSize->DataScalableSizingON = true;
1700 0 : CoolingAirFlowSizer sizingCoolingAirFlow;
1701 0 : std::string stringOverride = "Maximum Cooling Air Flow Rate [m3/s]";
1702 0 : if (state.dataGlobal->isEpJSON) stringOverride = "maximum_cooling_air_flow_rate [m3/s]";
1703 0 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
1704 : // sizingCoolingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1705 0 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1706 0 : CoolingAirVolFlowDes = sizingCoolingAirFlow.size(state, TempSize, ErrorsFound);
1707 0 : } else if (SAFMethod == FractionOfAutosizedCoolingAirflow) {
1708 0 : if ((state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow == AutoSize) &&
1709 0 : ((PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRate) ||
1710 0 : (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRateAndCapacity) ||
1711 0 : (PurchAir(PurchAirNum).OutdoorAir && PurchAir(PurchAirNum).EconomizerType != Econ::NoEconomizer))) {
1712 0 : state.dataSize->DataFracOfAutosizedCoolingAirflow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
1713 0 : TempSize = AutoSize;
1714 0 : state.dataSize->DataScalableSizingON = true;
1715 0 : CoolingAirFlowSizer sizingCoolingAirFlow;
1716 0 : std::string stringOverride = "Maximum Cooling Air Flow Rate [m3/s]";
1717 0 : if (state.dataGlobal->isEpJSON) stringOverride = "maximum_cooling_air_flow_rate [m3/s]";
1718 0 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
1719 : // sizingCoolingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1720 0 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1721 0 : CoolingAirVolFlowDes = sizingCoolingAirFlow.size(state, TempSize, ErrorsFound);
1722 : }
1723 : } else {
1724 : // Invalid scalable sizing method
1725 0 : }
1726 0 : } else if (SAFMethod == FlowPerCoolingCapacity) {
1727 0 : if ((state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow == AutoSize) &&
1728 0 : ((PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRate) ||
1729 0 : (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRateAndCapacity) ||
1730 0 : (PurchAir(PurchAirNum).OutdoorAir && PurchAir(PurchAirNum).EconomizerType != Econ::NoEconomizer))) {
1731 0 : SizingMethod = CoolingCapacitySizing;
1732 0 : TempSize = AutoSize;
1733 0 : PrintFlag = false;
1734 0 : CoolingCapacitySizer sizerCoolingCapacity;
1735 0 : sizerCoolingCapacity.overrideSizingString(SizingString);
1736 0 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1737 0 : state.dataSize->DataAutosizedCoolingCapacity = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
1738 0 : state.dataSize->DataFlowPerCoolingCapacity = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
1739 0 : PrintFlag = true;
1740 0 : TempSize = AutoSize;
1741 0 : state.dataSize->DataScalableSizingON = true;
1742 0 : CoolingAirFlowSizer sizingCoolingAirFlow;
1743 0 : std::string stringOverride = "Maximum Cooling Air Flow Rate [m3/s]";
1744 0 : if (state.dataGlobal->isEpJSON) stringOverride = "maximum_cooling_air_flow_rate [m3/s]";
1745 0 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
1746 : // sizingCoolingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1747 0 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1748 0 : CoolingAirVolFlowDes = sizingCoolingAirFlow.size(state, TempSize, ErrorsFound);
1749 : }
1750 : }
1751 0 : MaxCoolVolFlowRateDes = max(0.0, CoolingAirVolFlowDes);
1752 0 : PurchAir(PurchAirNum).MaxCoolVolFlowRate = MaxCoolVolFlowRateDes;
1753 0 : state.dataSize->ZoneCoolingOnlyFan = false;
1754 0 : state.dataSize->DataScalableSizingON = false;
1755 :
1756 0 : CapSizingMethod = state.dataSize->ZoneHVACSizing(zoneHVACIndex).CoolingCapMethod;
1757 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).CapSizingMethod = CapSizingMethod;
1758 0 : if (CapSizingMethod == CoolingDesignCapacity || CapSizingMethod == CapacityPerFloorArea ||
1759 0 : CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
1760 0 : if (CapSizingMethod == CoolingDesignCapacity) {
1761 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity > 0.0) {
1762 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).CoolingCapacity = true;
1763 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesCoolingLoad =
1764 0 : state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity;
1765 : } else {
1766 0 : state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolMassFlow;
1767 : }
1768 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity;
1769 0 : } else if (CapSizingMethod == CapacityPerFloorArea) {
1770 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).CoolingCapacity = true;
1771 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesCoolingLoad =
1772 0 : state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity *
1773 0 : state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
1774 0 : state.dataSize->DataScalableSizingON = true;
1775 0 : } else if (CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
1776 0 : state.dataSize->DataFracOfAutosizedHeatingCapacity = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity;
1777 0 : state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolMassFlow;
1778 0 : TempSize = AutoSize;
1779 : }
1780 : }
1781 0 : SizingMethod = CoolingCapacitySizing;
1782 0 : SizingString = "";
1783 0 : state.dataSize->ZoneCoolingOnlyFan = true;
1784 0 : PrintFlag = false;
1785 0 : TempSize = PurchAir(PurchAirNum).MaxCoolTotCap;
1786 0 : CoolingCapacitySizer sizerCoolingCapacity;
1787 0 : sizerCoolingCapacity.overrideSizingString(SizingString);
1788 0 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1789 0 : MaxCoolTotCapDes = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
1790 0 : state.dataSize->ZoneCoolingOnlyFan = false;
1791 0 : if (MaxCoolTotCapDes < SmallLoad) {
1792 0 : MaxCoolTotCapDes = 0.0;
1793 : }
1794 0 : if (IsAutoSize) {
1795 0 : PurchAir(PurchAirNum).MaxCoolTotCap = MaxCoolTotCapDes;
1796 0 : BaseSizer::reportSizerOutput(state,
1797 0 : PurchAir(PurchAirNum).cObjectName,
1798 0 : PurchAir(PurchAirNum).Name,
1799 : "Design Size Maximum Total Cooling Capacity [W]",
1800 0 : MaxCoolTotCapDes);
1801 : // If there is OA, check if sizing calcs have OA>0, throw warning if not
1802 0 : if ((PurchAir(PurchAirNum).OutdoorAir) && (state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA == 0.0)) {
1803 0 : ShowWarningError(state, "SizePurchasedAir: In " + PurchAir(PurchAirNum).cObjectName + " = " + PurchAir(PurchAirNum).Name);
1804 0 : ShowContinueError(state, "There is outdoor air specified in this object, but the design outdoor air flow rate for this ");
1805 0 : ShowContinueError(state, "zone is zero. The Maximum Total Cooling Capacity will be autosized for zero outdoor air flow. ");
1806 0 : ShowContinueError(state,
1807 0 : "Check the outdoor air specifications in the Sizing:Zone object for zone " +
1808 0 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).ZoneName + '.');
1809 : }
1810 : } else {
1811 0 : if (PurchAir(PurchAirNum).MaxCoolTotCap > 0.0 && MaxCoolTotCapDes > 0.0) {
1812 0 : MaxCoolTotCapUser = PurchAir(PurchAirNum).MaxCoolTotCap;
1813 0 : BaseSizer::reportSizerOutput(state,
1814 0 : PurchAir(PurchAirNum).cObjectName,
1815 0 : PurchAir(PurchAirNum).Name,
1816 : "Design Size Maximum Total Cooling Capacity [W]",
1817 : MaxCoolTotCapDes,
1818 : "User-Specified Maximum Total Cooling Capacity [W]",
1819 0 : MaxCoolTotCapUser);
1820 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1821 0 : if ((std::abs(MaxCoolTotCapDes - MaxCoolTotCapUser) / MaxCoolTotCapUser) > state.dataSize->AutoVsHardSizingThreshold) {
1822 0 : ShowMessage(state,
1823 0 : "SizePurchasedAir: Potential issue with equipment sizing for " + PurchAir(PurchAirNum).cObjectName + ' ' +
1824 0 : PurchAir(PurchAirNum).Name);
1825 0 : ShowContinueError(state, format("User-Specified Maximum Total Cooling Capacity of {:.2R} [W]", MaxCoolTotCapUser));
1826 0 : ShowContinueError(state,
1827 0 : format("differs from Design Size Maximum Total Cooling Capacity of {:.2R} [W]", MaxCoolTotCapDes));
1828 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1829 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1830 : }
1831 : }
1832 : }
1833 : }
1834 : }
1835 :
1836 : } else {
1837 : // SizingString = "Maximum Heating Air Flow Rate [m3/s]";
1838 214 : SizingMethod = HeatingAirflowSizing;
1839 214 : FieldNum = 5;
1840 214 : SizingString = state.dataPurchasedAirMgr->PurchAirNumericFields(PurchAirNum).FieldNames(FieldNum) + " [m3/s]";
1841 214 : IsAutoSize = false;
1842 214 : PrintFlag = true;
1843 401 : if ((PurchAir(PurchAirNum).MaxHeatVolFlowRate == AutoSize) &&
1844 368 : ((PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRate) ||
1845 183 : (PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRateAndCapacity))) {
1846 2 : IsAutoSize = true;
1847 : }
1848 214 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1849 202 : if (PurchAir(PurchAirNum).MaxHeatVolFlowRate > 0.0) {
1850 4 : HeatingAirFlowSizer sizingHeatingAirFlow;
1851 2 : sizingHeatingAirFlow.overrideSizingString(SizingString);
1852 : // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1853 2 : sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1854 2 : PurchAir(PurchAirNum).MaxHeatVolFlowRate =
1855 2 : sizingHeatingAirFlow.size(state, PurchAir(PurchAirNum).MaxHeatVolFlowRate, ErrorsFound);
1856 : }
1857 202 : MaxHeatVolFlowRateDes = 0.0;
1858 : } else {
1859 12 : state.dataSize->ZoneHeatingOnlyFan = true;
1860 12 : TempSize = PurchAir(PurchAirNum).MaxHeatVolFlowRate;
1861 24 : HeatingAirFlowSizer sizingHeatingAirFlow;
1862 12 : sizingHeatingAirFlow.overrideSizingString(SizingString);
1863 : // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1864 12 : sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1865 12 : MaxHeatVolFlowRateDes = sizingHeatingAirFlow.size(state, PurchAir(PurchAirNum).MaxHeatVolFlowRate, ErrorsFound);
1866 12 : PurchAir(PurchAirNum).MaxHeatVolFlowRate = MaxHeatVolFlowRateDes;
1867 12 : state.dataSize->ZoneHeatingOnlyFan = false;
1868 : }
1869 :
1870 214 : IsAutoSize = false;
1871 214 : SizingMethod = HeatingCapacitySizing;
1872 214 : FieldNum = 6; // N6, \field Maximum Sensible Heating Capacity
1873 214 : SizingString = state.dataPurchasedAirMgr->PurchAirNumericFields(PurchAirNum).FieldNames(FieldNum) + " [m3/s]";
1874 214 : if ((PurchAir(PurchAirNum).MaxHeatSensCap == AutoSize) && ((PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitCapacity) ||
1875 0 : (PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRateAndCapacity))) {
1876 0 : IsAutoSize = true;
1877 : }
1878 214 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1879 202 : if (PurchAir(PurchAirNum).MaxHeatSensCap > 0.0) {
1880 0 : HeatingCapacitySizer sizerHeatingCapacity;
1881 0 : sizerHeatingCapacity.overrideSizingString(SizingString);
1882 0 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1883 0 : MaxHeatSensCapDes = sizerHeatingCapacity.size(state, PurchAir(PurchAirNum).MaxHeatSensCap, ErrorsFound);
1884 : }
1885 : } else {
1886 12 : TempSize = PurchAir(PurchAirNum).MaxHeatSensCap;
1887 12 : ZoneEqSizing(state.dataSize->CurZoneEqNum).OAVolFlow = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA;
1888 12 : state.dataSize->ZoneHeatingOnlyFan = true;
1889 12 : PrintFlag = false;
1890 24 : HeatingCapacitySizer sizerHeatingCapacity;
1891 12 : sizerHeatingCapacity.overrideSizingString(SizingString);
1892 12 : sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1893 12 : MaxHeatSensCapDes = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
1894 12 : state.dataSize->ZoneHeatingOnlyFan = false;
1895 : }
1896 214 : if (MaxHeatSensCapDes < SmallLoad) {
1897 214 : MaxHeatSensCapDes = 0.0;
1898 : }
1899 214 : if (IsAutoSize) {
1900 0 : PurchAir(PurchAirNum).MaxHeatSensCap = MaxHeatSensCapDes;
1901 0 : BaseSizer::reportSizerOutput(state,
1902 0 : PurchAir(PurchAirNum).cObjectName,
1903 0 : PurchAir(PurchAirNum).Name,
1904 : "Design Size Maximum Sensible Heating Capacity [W]",
1905 0 : MaxHeatSensCapDes);
1906 : // If there is OA, check if sizing calcs have OA>0, throw warning if not
1907 0 : if ((PurchAir(PurchAirNum).OutdoorAir) && (state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA == 0.0)) {
1908 0 : ShowWarningError(state, "InitPurchasedAir: In " + PurchAir(PurchAirNum).cObjectName + " = " + PurchAir(PurchAirNum).Name);
1909 0 : ShowContinueError(state, "There is outdoor air specified in this object, but the design outdoor air flow rate for this ");
1910 0 : ShowContinueError(state, "zone is zero. The Maximum Sensible Heating Capacity will be autosized for zero outdoor air flow. ");
1911 0 : ShowContinueError(state,
1912 0 : "Check the outdoor air specifications in the Sizing:Zone object for zone " +
1913 0 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).ZoneName + '.');
1914 : }
1915 : } else {
1916 214 : if (PurchAir(PurchAirNum).MaxHeatSensCap > 0.0 && MaxHeatSensCapDes > 0.0) {
1917 0 : MaxHeatSensCapUser = PurchAir(PurchAirNum).MaxHeatSensCap;
1918 0 : BaseSizer::reportSizerOutput(state,
1919 0 : PurchAir(PurchAirNum).cObjectName,
1920 0 : PurchAir(PurchAirNum).Name,
1921 : "Design Size Maximum Sensible Heating Capacity [W]",
1922 : MaxHeatSensCapDes,
1923 : "User-Specified Maximum Sensible Heating Capacity [W]",
1924 0 : MaxHeatSensCapUser);
1925 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1926 0 : if ((std::abs(MaxHeatSensCapDes - MaxHeatSensCapUser) / MaxHeatSensCapUser) > state.dataSize->AutoVsHardSizingThreshold) {
1927 0 : ShowMessage(state,
1928 0 : "SizePurchasedAir: Potential issue with equipment sizing for " + PurchAir(PurchAirNum).cObjectName + ' ' +
1929 0 : PurchAir(PurchAirNum).Name);
1930 0 : ShowContinueError(state, format("...User-Specified Maximum Sensible Heating Capacity of {:.2R} [W]", MaxHeatSensCapUser));
1931 0 : ShowContinueError(
1932 0 : state, format("...differs from Design Size Maximum Sensible Heating Capacity of {:.2R} [W]", MaxHeatSensCapDes));
1933 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1934 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1935 : }
1936 : }
1937 : }
1938 : }
1939 :
1940 214 : PrintFlag = true;
1941 214 : IsAutoSize = false;
1942 401 : if ((PurchAir(PurchAirNum).MaxCoolVolFlowRate == AutoSize) &&
1943 362 : ((PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRate) ||
1944 358 : (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRateAndCapacity) ||
1945 179 : (PurchAir(PurchAirNum).OutdoorAir && PurchAir(PurchAirNum).EconomizerType != Econ::NoEconomizer))) {
1946 4 : IsAutoSize = true;
1947 : }
1948 214 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1949 202 : if (PurchAir(PurchAirNum).MaxCoolVolFlowRate > 0.0) {
1950 4 : CoolingAirFlowSizer sizingCoolingAirFlow;
1951 4 : std::string stringOverride = "Maximum Cooling Air Flow Rate [m3/s]";
1952 2 : if (state.dataGlobal->isEpJSON) stringOverride = "maximum_cooling_air_flow_rate [m3/s]";
1953 2 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
1954 : // sizingCoolingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1955 2 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1956 2 : PurchAir(PurchAirNum).MaxCoolVolFlowRate =
1957 2 : sizingCoolingAirFlow.size(state, PurchAir(PurchAirNum).MaxCoolVolFlowRate, ErrorsFound);
1958 : }
1959 : } else {
1960 12 : state.dataSize->ZoneCoolingOnlyFan = true;
1961 12 : TempSize = PurchAir(PurchAirNum).MaxCoolVolFlowRate;
1962 24 : CoolingAirFlowSizer sizingCoolingAirFlow;
1963 24 : std::string stringOverride = "Maximum Cooling Air Flow Rate [m3/s]";
1964 12 : if (state.dataGlobal->isEpJSON) stringOverride = "maximum_cooling_air_flow_rate [m3/s]";
1965 12 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
1966 : // sizingCoolingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1967 12 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1968 12 : MaxCoolVolFlowRateDes = sizingCoolingAirFlow.size(state, TempSize, ErrorsFound);
1969 12 : PurchAir(PurchAirNum).MaxCoolVolFlowRate = MaxCoolVolFlowRateDes;
1970 12 : state.dataSize->ZoneCoolingOnlyFan = false;
1971 : }
1972 :
1973 214 : IsAutoSize = false;
1974 214 : SizingMethod = CoolingCapacitySizing;
1975 214 : FieldNum = 8; // N8, \field Maximum Total Cooling Capacity
1976 214 : SizingString = state.dataPurchasedAirMgr->PurchAirNumericFields(PurchAirNum).FieldNames(FieldNum) + " [m3/s]";
1977 214 : if ((PurchAir(PurchAirNum).MaxCoolTotCap == AutoSize) && ((PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitCapacity) ||
1978 0 : (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRateAndCapacity))) {
1979 0 : IsAutoSize = true;
1980 : }
1981 214 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1982 202 : if (PurchAir(PurchAirNum).MaxCoolTotCap > 0.0) {
1983 0 : CoolingCapacitySizer sizerCoolingCapacity;
1984 0 : sizerCoolingCapacity.overrideSizingString(SizingString);
1985 0 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1986 0 : PurchAir(PurchAirNum).MaxCoolTotCap = sizerCoolingCapacity.size(state, PurchAir(PurchAirNum).MaxCoolTotCap, ErrorsFound);
1987 : }
1988 : } else {
1989 12 : state.dataSize->ZoneCoolingOnlyFan = true;
1990 12 : ZoneEqSizing(state.dataSize->CurZoneEqNum).OAVolFlow = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA;
1991 12 : PrintFlag = false;
1992 12 : TempSize = PurchAir(PurchAirNum).MaxCoolTotCap;
1993 24 : CoolingCapacitySizer sizerCoolingCapacity;
1994 12 : sizerCoolingCapacity.overrideSizingString(SizingString);
1995 12 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1996 12 : MaxCoolTotCapDes = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
1997 12 : state.dataSize->ZoneCoolingOnlyFan = false;
1998 : }
1999 214 : if (MaxCoolTotCapDes < SmallLoad) {
2000 214 : MaxCoolTotCapDes = 0.0;
2001 : }
2002 214 : if (IsAutoSize) {
2003 0 : PurchAir(PurchAirNum).MaxCoolTotCap = MaxCoolTotCapDes;
2004 0 : BaseSizer::reportSizerOutput(state,
2005 0 : PurchAir(PurchAirNum).cObjectName,
2006 0 : PurchAir(PurchAirNum).Name,
2007 : "Design Size Maximum Total Cooling Capacity [W]",
2008 0 : MaxCoolTotCapDes);
2009 : // If there is OA, check if sizing calcs have OA>0, throw warning if not
2010 0 : if ((PurchAir(PurchAirNum).OutdoorAir) && (state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA == 0.0)) {
2011 0 : ShowWarningError(state, "SizePurchasedAir: In " + PurchAir(PurchAirNum).cObjectName + " = " + PurchAir(PurchAirNum).Name);
2012 0 : ShowContinueError(state, "There is outdoor air specified in this object, but the design outdoor air flow rate for this ");
2013 0 : ShowContinueError(state, "zone is zero. The Maximum Total Cooling Capacity will be autosized for zero outdoor air flow. ");
2014 0 : ShowContinueError(state,
2015 0 : "Check the outdoor air specifications in the Sizing:Zone object for zone " +
2016 0 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).ZoneName + '.');
2017 : }
2018 : } else {
2019 214 : if (PurchAir(PurchAirNum).MaxCoolTotCap > 0.0 && MaxCoolTotCapDes > 0.0) {
2020 0 : MaxCoolTotCapUser = PurchAir(PurchAirNum).MaxCoolTotCap;
2021 0 : BaseSizer::reportSizerOutput(state,
2022 0 : PurchAir(PurchAirNum).cObjectName,
2023 0 : PurchAir(PurchAirNum).Name,
2024 : "Design Size Maximum Total Cooling Capacity [W]",
2025 : MaxCoolTotCapDes,
2026 : "User-Specified Maximum Total Cooling Capacity [W]",
2027 0 : MaxCoolTotCapUser);
2028 0 : if (state.dataGlobal->DisplayExtraWarnings) {
2029 0 : if ((std::abs(MaxCoolTotCapDes - MaxCoolTotCapUser) / MaxCoolTotCapUser) > state.dataSize->AutoVsHardSizingThreshold) {
2030 0 : ShowMessage(state,
2031 0 : "SizePurchasedAir: Potential issue with equipment sizing for " + PurchAir(PurchAirNum).cObjectName + ' ' +
2032 0 : PurchAir(PurchAirNum).Name);
2033 0 : ShowContinueError(state, format("User-Specified Maximum Total Cooling Capacity of {:.2R} [W]", MaxCoolTotCapUser));
2034 0 : ShowContinueError(state,
2035 0 : format("differs from Design Size Maximum Total Cooling Capacity of {:.2R} [W]", MaxCoolTotCapDes));
2036 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
2037 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
2038 : }
2039 : }
2040 : }
2041 : }
2042 : }
2043 : }
2044 :
2045 : // IF (PurchAir(PurchAirNum)%OutdoorAir .AND. PurchAir(PurchAirNum)%OutsideAirVolFlowRate == AutoSize) THEN
2046 : // IF (CurZoneEqNum > 0) THEN
2047 : // CALL CheckZoneSizing(TRIM(PurchAir(PurchAirNum)%cObjectName), PurchAir(PurchAirNum)%Name)
2048 : // PurchAir(PurchAirNum)%OutsideAirVolFlowRate = FinalZoneSizing(CurZoneEqNum)%MinOA
2049 : // IF (PurchAir(PurchAirNum)%OutsideAirVolFlowRate < SmallAirVolFlow) THEN
2050 : // PurchAir(PurchAirNum)%OutsideAirVolFlowRate = 0.0
2051 : // END IF
2052 : // CALL BaseSizer::reportSizerOutput(TRIM(PurchAir(PurchAirNum)%cObjectName), PurchAir(PurchAirNum)%Name, &
2053 : // 'Outdoor Air Flow Rate [m3/s]', PurchAir(PurchAirNum)%OutsideAirVolFlowRate )
2054 : // END IF
2055 : // END IF
2056 214 : }
2057 :
2058 1291226 : void CalcPurchAirLoads(EnergyPlusData &state,
2059 : int const PurchAirNum,
2060 : Real64 &SysOutputProvided, // Sensible output provided [W] cooling = negative
2061 : Real64 &MoistOutputProvided, // Moisture output provided [kg/s] dehumidification = negative
2062 : int const ControlledZoneNum)
2063 : {
2064 :
2065 : // SUBROUTINE INFORMATION:
2066 : // AUTHOR Russ Taylor
2067 : // DATE WRITTEN Nov 1997
2068 : // MODIFIED Shirey, Aug 2009 (LatOutputProvided - now MoistOutputProvided)
2069 : // M. Witte June 2011, add new features including DCV, economizer, dehumidification
2070 : // and humidification,
2071 : // July 2012, Chandan Sharma - FSEC: Added hybrid ventilation manager
2072 : // RE-ENGINEERED na
2073 :
2074 : // Using/Aliasing
2075 : using DataHVACGlobals::ForceOff;
2076 : using DataHVACGlobals::SmallLoad;
2077 1291226 : auto &ZoneComp = state.dataHVACGlobal->ZoneComp;
2078 :
2079 : // SUBROUTINE PARAMETER DEFINITIONS:
2080 : static constexpr std::string_view RoutineName("CalcPurchAirLoads");
2081 :
2082 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2083 : int InNodeNum; // Ideal loads supply node to zone
2084 : // INTEGER :: ExhNodeNum ! Ideal loads exhaust node from zone
2085 : int ZoneNodeNum; // Zone air node
2086 : int OANodeNum; // Outdoor air inlet node
2087 : int RecircNodeNum; // Return air or zone exhaust node
2088 : OpMode OperatingMode; // current operating mode, Off, Heat, Cool, or DeadBand
2089 : Real64 SupplyMassFlowRate; // System supply air mass flow rate [kg/s]
2090 : Real64 SupplyMassFlowRateForHumid; // System supply air mass flow rate required to meet humdification load [kg/s]
2091 : Real64 SupplyMassFlowRateForDehum; // System supply air mass flow rate required to meet dehumidification load [kg/s]
2092 : Real64 SupplyMassFlowRateForCool; // System supply air mass flow rate required to meet sensible cooling load[kg/s]
2093 : Real64 SupplyMassFlowRateForHeat; // System supply air mass flow rate required to meet sensible heating load[kg/s]
2094 : Real64 SupplyHumRatForHumid; // Supply air humidity ratio require to meet the humidification load [kgWater/kgDryAir]
2095 : Real64 SupplyHumRatForDehum; // Supply air humidity ratio require to meet the dehumidification load [kgWater/kgDryAir]
2096 : Real64 OAMassFlowRate; // Outdoor air mass flow rate [kg/s]
2097 : Real64 OAVolFlowRate; // Outdoor air volume flow rate at standard density [m3/s]
2098 : Real64 MinOASensOutput; // Minimum Outdoor air sensible output [W], <0 means OA is cooler than zone air
2099 : Real64 MinOALatOutput; // Minimum Outdoor air moisture load [kg/s]
2100 : Real64 SensOutput; // Sensible output [W] (psitive means heating, negative means cooling)
2101 : Real64 HeatSensOutput; // Heating sensible output [W]
2102 : Real64 CoolSensOutput; // Cooling sensible output [W] (positive value menas cooling)
2103 : Real64 LatOutput; // Latent output [W] (positive value means hudmification, negative means dehumidification)
2104 : Real64 CoolLatOutput; // Cooling latent output [W] (positive value means dehumidification)
2105 : Real64 CoolTotOutput; // Cooling total output [W] (positive value means cooling)
2106 : Real64 DeltaT; // Delta temperature - reused in multiple places
2107 : Real64 DeltaHumRat; // Delta humidity ratio - reused in multiple places
2108 : Real64 QZnHeatSP; // Load required to meet heating setpoint [W] (>0 is a heating load)
2109 : Real64 QZnCoolSP; // Load required to meet cooling setpoint [W] (<0 is a cooling load)
2110 : Real64 MdotZnHumidSP; // Load required to meet humidifying setpoint [kgWater/s] (>0 = a humidify load)
2111 : Real64 MdotZnDehumidSP; // Load required to meet dehumidifying setpoint [kgWater/s] (<0 = a dehumidify load)
2112 : bool UnitOn;
2113 : bool HeatOn; // Flag for heating and humidification availbility schedule, true if heating is on
2114 : bool CoolOn; // Flag for cooling and dehumidification availbility schedule, true if cooling is on
2115 : bool EconoOn; // Flag for economizer operation, true if economizer is on
2116 : Real64 SupplyHumRatOrig; // Supply inlet to zone humidity ratio before saturation check [kgWater/kgDryAir]
2117 : Real64 SupplyHumRatSat; // Supply inlet to zone humidity ratio saturation at SupplyTemp [kgWater/kgDryAir]
2118 : Real64 SupplyEnthalpy; // Supply inlet to zone enthalpy [J/kg]
2119 : Real64 MixedAirEnthalpy; // Mixed air enthalpy [J/kg]
2120 : Real64 CpAir; // Specific heat [J/kg-C] reused in multiple places
2121 : // REAL(r64) :: SpecHumOut ! Specific humidity ratio of outlet air (kg moisture / kg moist air)
2122 : // REAL(r64) :: SpecHumIn ! Specific humidity ratio of inlet [zone] air (kg moisture / kg moist air)
2123 :
2124 1291226 : auto &PurchAir(state.dataPurchasedAirMgr->PurchAir);
2125 :
2126 : // Sign convention: SysOutputProvided <0 Supply air is heated on entering zone (zone is cooled)
2127 : // SysOutputProvided >0 Supply air is cooled on entering zone (zone is heated)
2128 1291226 : InNodeNum = PurchAir(PurchAirNum).ZoneSupplyAirNodeNum;
2129 1291226 : ZoneNodeNum = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
2130 1291226 : OANodeNum = PurchAir(PurchAirNum).OutdoorAirNodeNum;
2131 1291226 : RecircNodeNum = PurchAir(PurchAirNum).ZoneRecircAirNodeNum;
2132 1291226 : SupplyMassFlowRate = 0.0;
2133 1291226 : OAMassFlowRate = 0.0;
2134 1291226 : PurchAir(PurchAirNum).MinOAMassFlowRate = 0.0;
2135 1291226 : PurchAir(PurchAirNum).TimeEconoActive = 0.0;
2136 1291226 : PurchAir(PurchAirNum).TimeHtRecActive = 0.0;
2137 1291226 : SysOutputProvided = 0.0;
2138 1291226 : MoistOutputProvided = 0.0;
2139 1291226 : CoolSensOutput = 0.0;
2140 1291226 : CoolLatOutput = 0.0;
2141 1291226 : CoolTotOutput = 0.0;
2142 1291226 : HeatSensOutput = 0.0;
2143 1291226 : LatOutput = 0.0;
2144 :
2145 : // default unit to ON
2146 1291226 : UnitOn = true;
2147 1291226 : EconoOn = false;
2148 : // get current zone requirements
2149 1291226 : QZnHeatSP = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ControlledZoneNum).RemainingOutputReqToHeatSP;
2150 1291226 : QZnCoolSP = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ControlledZoneNum).RemainingOutputReqToCoolSP;
2151 :
2152 1291226 : if (allocated(ZoneComp)) {
2153 1291214 : ZoneComp(DataZoneEquipment::ZoneEquip::PurchasedAir).ZoneCompAvailMgrs(PurchAirNum).ZoneNum = ControlledZoneNum;
2154 1291214 : PurchAir(PurchAirNum).AvailStatus = ZoneComp(DataZoneEquipment::ZoneEquip::PurchasedAir).ZoneCompAvailMgrs(PurchAirNum).AvailStatus;
2155 : // Check if the hybrid ventilation availability manager is turning the unit off
2156 1291214 : if (PurchAir(PurchAirNum).AvailStatus == ForceOff) {
2157 0 : UnitOn = false;
2158 : }
2159 : }
2160 :
2161 : // Check if the unit is scheduled off
2162 : // IF (PurchAir(PurchAirNum)%AvailSchedPtr > 0) THEN
2163 1291226 : if (GetCurrentScheduleValue(state, PurchAir(PurchAirNum).AvailSchedPtr) <= 0) {
2164 0 : UnitOn = false;
2165 : }
2166 : // END IF
2167 : // Check if heating and cooling available
2168 1291226 : HeatOn = true;
2169 : // IF (PurchAir(PurchAirNum)%HeatSchedPtr > 0) THEN
2170 1291226 : if (GetCurrentScheduleValue(state, PurchAir(PurchAirNum).HeatSchedPtr) <= 0) {
2171 0 : HeatOn = false;
2172 : }
2173 : // END IF
2174 1291226 : CoolOn = true;
2175 : // IF (PurchAir(PurchAirNum)%CoolSchedPtr > 0) THEN
2176 1291226 : if (GetCurrentScheduleValue(state, PurchAir(PurchAirNum).CoolSchedPtr) <= 0) {
2177 8485 : CoolOn = false;
2178 : }
2179 : // END IF
2180 :
2181 1291226 : if (UnitOn) {
2182 1291226 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ControlledZoneNum);
2183 : // Calculate current minimum outdoor air flow rate based on design OA specifications and DCV or CO2 control
2184 1291226 : CalcPurchAirMinOAMassFlow(state, PurchAirNum, ControlledZoneNum, OAMassFlowRate);
2185 :
2186 : // EMS override point Purch air outdoor air massflow rate.....
2187 1291226 : if (PurchAir(PurchAirNum).EMSOverrideOAMdotOn) {
2188 0 : OAMassFlowRate = PurchAir(PurchAirNum).EMSValueOAMassFlowRate;
2189 : }
2190 :
2191 : // Calculate minimum outdoor air sensible and latent load
2192 1291226 : if (PurchAir(PurchAirNum).OutdoorAir) {
2193 14796 : CpAir = PsyCpAirFnW(state.dataLoopNodes->Node(OANodeNum).HumRat);
2194 14796 : MinOASensOutput = OAMassFlowRate * CpAir * (state.dataLoopNodes->Node(OANodeNum).Temp - state.dataLoopNodes->Node(ZoneNodeNum).Temp);
2195 14796 : MinOALatOutput = OAMassFlowRate * (state.dataLoopNodes->Node(OANodeNum).HumRat - state.dataLoopNodes->Node(ZoneNodeNum).HumRat);
2196 : } else {
2197 1276430 : MinOASensOutput = 0.0;
2198 1276430 : MinOALatOutput = 0.0;
2199 : }
2200 1291226 : SupplyMassFlowRate = OAMassFlowRate;
2201 :
2202 : // Check if cooling of the supply air stream is required
2203 :
2204 : // Cooling operation
2205 1781616 : if ((MinOASensOutput >= QZnCoolSP) &&
2206 490390 : (state.dataHeatBalFanSys->TempControlType(ControlledZoneNum) != DataHVACGlobals::ThermostatType::SingleHeating)) {
2207 383719 : OperatingMode = OpMode::Cool;
2208 : // Calculate supply mass flow, temp and humidity with the following constraints:
2209 : // Min cooling supply temp
2210 : // Max total cooling capacity
2211 : // Max cooling airflow
2212 : // Min cooling supply humrat (and Max heating supply humrat)
2213 : // Min OA mass flow rate
2214 :
2215 : // Check if OA flow rate greater than max cooling airflow limit
2216 1138682 : if (((PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRate) ||
2217 396194 : (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRateAndCapacity)) &&
2218 12475 : (OAMassFlowRate > PurchAir(PurchAirNum).MaxCoolMassFlowRate)) {
2219 0 : OAVolFlowRate = OAMassFlowRate / state.dataEnvrn->StdRhoAir;
2220 0 : if (PurchAir(PurchAirNum).OAFlowMaxCoolOutputError < 1) {
2221 0 : ++PurchAir(PurchAirNum).OAFlowMaxCoolOutputError;
2222 0 : ShowWarningError(state,
2223 0 : format("{} \"{}\" Requested outdoor air flow rate = {:.5T} [m3/s] exceeds limit.",
2224 0 : PurchAir(PurchAirNum).cObjectName,
2225 0 : PurchAir(PurchAirNum).Name,
2226 0 : OAVolFlowRate));
2227 0 : ShowContinueError(
2228 : state,
2229 0 : format(" Will be reduced to the Maximum Cooling Air Flow Rate = {:.5T} [m3/s]", PurchAir(PurchAirNum).MaxCoolVolFlowRate));
2230 0 : ShowContinueErrorTimeStamp(state, "");
2231 : } else {
2232 0 : ShowRecurringWarningErrorAtEnd(
2233 : state,
2234 0 : PurchAir(PurchAirNum).cObjectName + " \"" + PurchAir(PurchAirNum).Name +
2235 : "\" Requested outdoor air flow rate [m3/s] reduced to Maximum Cooling Air Flow Rate warning continues...",
2236 0 : PurchAir(PurchAirNum).OAFlowMaxCoolOutputIndex,
2237 : OAVolFlowRate);
2238 : }
2239 0 : OAMassFlowRate = PurchAir(PurchAirNum).MaxCoolMassFlowRate;
2240 :
2241 : } else {
2242 : // Model economizer
2243 383719 : if (PurchAir(PurchAirNum).EconomizerType != Econ::NoEconomizer) {
2244 13658 : if (((PurchAir(PurchAirNum).EconomizerType == Econ::DifferentialDryBulb) &&
2245 10240 : (state.dataLoopNodes->Node(OANodeNum).Temp < state.dataLoopNodes->Node(PurchAir(PurchAirNum).ZoneRecircAirNodeNum).Temp)) ||
2246 6640 : ((PurchAir(PurchAirNum).EconomizerType == Econ::DifferentialEnthalpy) &&
2247 1702 : (state.dataLoopNodes->Node(OANodeNum).Enthalpy <
2248 1702 : state.dataLoopNodes->Node(PurchAir(PurchAirNum).ZoneRecircAirNodeNum).Enthalpy))) {
2249 :
2250 : // Calculate supply MassFlowRate based on sensible load but limit to Max Cooling Supply Air Flow Rate if specified
2251 182 : CpAir = PsyCpAirFnW(thisZoneHB.ZoneAirHumRat);
2252 182 : DeltaT = (state.dataLoopNodes->Node(OANodeNum).Temp - state.dataLoopNodes->Node(ZoneNodeNum).Temp);
2253 182 : if (DeltaT < -SmallTempDiff) {
2254 182 : SupplyMassFlowRate = QZnCoolSP / CpAir / DeltaT;
2255 364 : if (((PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRate) ||
2256 364 : (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRateAndCapacity)) &&
2257 182 : (PurchAir(PurchAirNum).MaxCoolMassFlowRate > 0.0)) {
2258 182 : SupplyMassFlowRate = min(max(SupplyMassFlowRate, 0.0), PurchAir(PurchAirNum).MaxCoolMassFlowRate);
2259 : }
2260 182 : if (SupplyMassFlowRate > OAMassFlowRate) {
2261 182 : EconoOn = true;
2262 182 : OAMassFlowRate = SupplyMassFlowRate;
2263 182 : PurchAir(PurchAirNum).TimeEconoActive = state.dataHVACGlobal->TimeStepSys;
2264 : }
2265 : }
2266 : }
2267 : }
2268 : }
2269 :
2270 : // Determine supply mass flow rate
2271 : // Mass flow rate to meet sensible load, at Minimum Cooling Supply Air Temperature
2272 383719 : SupplyMassFlowRateForCool = 0.0;
2273 383719 : if (CoolOn) {
2274 379202 : CpAir = PsyCpAirFnW(thisZoneHB.ZoneAirHumRat);
2275 379202 : DeltaT = (PurchAir(PurchAirNum).MinCoolSuppAirTemp - state.dataLoopNodes->Node(ZoneNodeNum).Temp);
2276 379202 : if (DeltaT < -SmallTempDiff) {
2277 378326 : SupplyMassFlowRateForCool = QZnCoolSP / CpAir / DeltaT;
2278 : }
2279 : }
2280 :
2281 : // Mass flow rate to meet dehumidification load, if applicable, at Minimum Cooling Supply Humidity Ratio
2282 383719 : SupplyMassFlowRateForDehum = 0.0;
2283 383719 : if (CoolOn) {
2284 379202 : if (PurchAir(PurchAirNum).DehumidCtrlType == HumControl::Humidistat) {
2285 1702 : MdotZnDehumidSP = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(ControlledZoneNum).RemainingOutputReqToDehumidSP;
2286 1702 : DeltaHumRat = (PurchAir(PurchAirNum).MinCoolSuppAirHumRat - state.dataLoopNodes->Node(ZoneNodeNum).HumRat);
2287 1702 : if ((DeltaHumRat < -SmallDeltaHumRat) && (MdotZnDehumidSP < 0.0)) {
2288 188 : SupplyMassFlowRateForDehum = MdotZnDehumidSP / DeltaHumRat;
2289 : }
2290 : }
2291 : }
2292 :
2293 : // Mass flow rate to meet humidification load, if applicable, at Maximum Heating Supply Humidity Ratio
2294 : // This section is the cooling section, so humidification should activate only if humidification control = humidistat
2295 : // and if dehumidification control = humidistat or none
2296 383719 : SupplyMassFlowRateForHumid = 0.0;
2297 383719 : if (HeatOn) {
2298 383719 : if (PurchAir(PurchAirNum).HumidCtrlType == HumControl::Humidistat) {
2299 4994 : if ((PurchAir(PurchAirNum).DehumidCtrlType == HumControl::Humidistat) ||
2300 1646 : (PurchAir(PurchAirNum).DehumidCtrlType == HumControl::None)) {
2301 1702 : MdotZnHumidSP = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(ControlledZoneNum).RemainingOutputReqToHumidSP;
2302 1702 : DeltaHumRat = (PurchAir(PurchAirNum).MaxHeatSuppAirHumRat - state.dataLoopNodes->Node(ZoneNodeNum).HumRat);
2303 1702 : if ((DeltaHumRat > SmallDeltaHumRat) && (MdotZnHumidSP > 0.0)) {
2304 0 : SupplyMassFlowRateForHumid = MdotZnHumidSP / DeltaHumRat;
2305 : }
2306 : }
2307 : }
2308 : }
2309 :
2310 : // If cooling capacity is limited to zero, SupplyMassFlowRate* should be set to zero
2311 1151157 : if (((PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitCapacity) ||
2312 383719 : (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRateAndCapacity)) &&
2313 0 : (PurchAir(PurchAirNum).MaxCoolTotCap == 0)) {
2314 0 : SupplyMassFlowRateForCool = 0;
2315 0 : SupplyMassFlowRateForDehum = 0;
2316 0 : SupplyMassFlowRateForHumid = 0;
2317 : }
2318 :
2319 : // Supply mass flow is greatest of these, but limit to cooling max flow rate, if applicable
2320 383719 : SupplyMassFlowRate = max(0.0, OAMassFlowRate, SupplyMassFlowRateForCool, SupplyMassFlowRateForDehum, SupplyMassFlowRateForHumid);
2321 : // EMS override point Purch air massflow rate..... but only if unit is on, i.e. SupplyMassFlowRate>0.0
2322 383719 : if (PurchAir(PurchAirNum).EMSOverrideMdotOn) {
2323 79816 : SupplyMassFlowRate = PurchAir(PurchAirNum).EMSValueMassFlowRate;
2324 79816 : OAMassFlowRate = min(OAMassFlowRate, SupplyMassFlowRate);
2325 : }
2326 1138682 : if (((PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRate) ||
2327 396194 : (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRateAndCapacity)) &&
2328 12475 : (PurchAir(PurchAirNum).MaxCoolMassFlowRate > 0.0)) {
2329 12474 : SupplyMassFlowRate = min(SupplyMassFlowRate, PurchAir(PurchAirNum).MaxCoolMassFlowRate);
2330 : }
2331 :
2332 383719 : if (SupplyMassFlowRate <= VerySmallMassFlow) SupplyMassFlowRate = 0.0;
2333 :
2334 : // Calculate mixed air conditions
2335 767438 : CalcPurchAirMixedAir(state,
2336 : PurchAirNum,
2337 : OAMassFlowRate,
2338 : SupplyMassFlowRate,
2339 383719 : PurchAir(PurchAirNum).MixedAirTemp,
2340 383719 : PurchAir(PurchAirNum).MixedAirHumRat,
2341 : MixedAirEnthalpy,
2342 : OperatingMode);
2343 :
2344 : // Calculate supply air conditions using final massflow rate, imposing capacity limits if specified
2345 : // If capacity limits are exceeded, keep massflow rate where it is and adjust supply temp
2346 : // In general, in the cooling section, don't let SupplyTemp be set to something that results in heating
2347 383719 : if (SupplyMassFlowRate > 0.0) {
2348 : // Calculate supply temp at SupplyMassFlowRate and recheck limit on Minimum Cooling Supply Air Temperature
2349 378326 : CpAir = PsyCpAirFnW(thisZoneHB.ZoneAirHumRat);
2350 378326 : PurchAir(PurchAirNum).SupplyTemp = QZnCoolSP / (CpAir * SupplyMassFlowRate) + state.dataLoopNodes->Node(ZoneNodeNum).Temp;
2351 378326 : PurchAir(PurchAirNum).SupplyTemp = max(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).MinCoolSuppAirTemp);
2352 : // This is the cooling mode, so SupplyTemp can't be more than MixedAirTemp
2353 378326 : PurchAir(PurchAirNum).SupplyTemp = min(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).MixedAirTemp);
2354 378326 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MixedAirHumRat;
2355 378326 : SupplyEnthalpy = PsyHFnTdbW(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).SupplyHumRat);
2356 :
2357 : // Check sensible load vs max total cooling capacity, if specified, and adjust supply temp before applying humidity controls
2358 : // Will check again later, too
2359 756652 : if ((PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitCapacity) ||
2360 378326 : (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRateAndCapacity)) {
2361 0 : CpAir = PsyCpAirFnW(PurchAir(PurchAirNum).MixedAirHumRat);
2362 0 : CoolSensOutput = SupplyMassFlowRate * (MixedAirEnthalpy - SupplyEnthalpy);
2363 0 : if (CoolSensOutput >= PurchAir(PurchAirNum).MaxCoolTotCap) {
2364 0 : CoolSensOutput = PurchAir(PurchAirNum).MaxCoolTotCap;
2365 0 : SupplyEnthalpy = MixedAirEnthalpy - CoolSensOutput / SupplyMassFlowRate;
2366 0 : PurchAir(PurchAirNum).SupplyTemp = PsyTdbFnHW(SupplyEnthalpy, PurchAir(PurchAirNum).SupplyHumRat);
2367 : // This is the cooling mode, so SupplyTemp can't be more than MixedAirTemp
2368 0 : PurchAir(PurchAirNum).SupplyTemp = min(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).MixedAirTemp);
2369 : } // Capacity limit exceeded
2370 : }
2371 :
2372 : // Set supply humidity ratio for cooling/dehumidification
2373 378326 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MixedAirHumRat;
2374 378326 : switch (PurchAir(PurchAirNum).DehumidCtrlType) {
2375 30 : case HumControl::None: {
2376 30 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MixedAirHumRat; // Unnecessary line?
2377 30 : } break;
2378 35749 : case HumControl::ConstantSensibleHeatRatio: {
2379 : // SHR = CoolSensOutput/CoolTotOutput
2380 : // CoolTotOutput = CoolSensOutput/SHR
2381 35749 : CpAir = PsyCpAirFnW(PurchAir(PurchAirNum).MixedAirHumRat);
2382 35749 : CoolSensOutput = SupplyMassFlowRate * CpAir * (PurchAir(PurchAirNum).MixedAirTemp - PurchAir(PurchAirNum).SupplyTemp);
2383 35749 : CoolTotOutput = CoolSensOutput / PurchAir(PurchAirNum).CoolSHR;
2384 35749 : SupplyEnthalpy = MixedAirEnthalpy - CoolTotOutput / SupplyMassFlowRate;
2385 : // Limit for overdrying (avoid Pysch errors which occur if SupplyEnthalpy is too low for SupplyTemp)
2386 35749 : SupplyEnthalpy = max(SupplyEnthalpy, PsyHFnTdbW(PurchAir(PurchAirNum).SupplyTemp, 0.00001));
2387 35749 : PurchAir(PurchAirNum).SupplyHumRat =
2388 35749 : min(PurchAir(PurchAirNum).SupplyHumRat, PsyWFnTdbH(state, PurchAir(PurchAirNum).SupplyTemp, SupplyEnthalpy, RoutineName));
2389 : // Apply min cooling humidity ratio limit
2390 35749 : PurchAir(PurchAirNum).SupplyHumRat = max(PurchAir(PurchAirNum).SupplyHumRat, PurchAir(PurchAirNum).MinCoolSuppAirHumRat);
2391 : // But don't let it be higher than incoming MixedAirHumRat
2392 35749 : PurchAir(PurchAirNum).SupplyHumRat = min(PurchAir(PurchAirNum).SupplyHumRat, PurchAir(PurchAirNum).MixedAirHumRat);
2393 35749 : } break;
2394 1702 : case HumControl::Humidistat: {
2395 1702 : MdotZnDehumidSP = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(ControlledZoneNum).RemainingOutputReqToDehumidSP;
2396 1702 : SupplyHumRatForDehum = MdotZnDehumidSP / SupplyMassFlowRate + state.dataLoopNodes->Node(ZoneNodeNum).HumRat;
2397 1702 : SupplyHumRatForDehum = max(SupplyHumRatForDehum, PurchAir(PurchAirNum).MinCoolSuppAirHumRat);
2398 1702 : PurchAir(PurchAirNum).SupplyHumRat = min(PurchAir(PurchAirNum).MixedAirHumRat, SupplyHumRatForDehum);
2399 1702 : } break;
2400 340845 : case HumControl::ConstantSupplyHumidityRatio: {
2401 340845 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MinCoolSuppAirHumRat;
2402 340845 : } break;
2403 0 : default: {
2404 0 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MixedAirHumRat;
2405 0 : } break;
2406 : }
2407 :
2408 : // Check supply humidity ratio for humidification (SupplyHumRatForHum should always be < SupplyHumRatForDehum)
2409 : // This section is the cooling section, so humidification should activate only if humidification control = humidistat
2410 : // and if dehumidification control = humidistat or none
2411 378326 : if (HeatOn) {
2412 378326 : if (PurchAir(PurchAirNum).HumidCtrlType == HumControl::Humidistat) {
2413 4994 : if ((PurchAir(PurchAirNum).DehumidCtrlType == HumControl::Humidistat) ||
2414 1646 : (PurchAir(PurchAirNum).DehumidCtrlType == HumControl::None)) {
2415 1702 : MdotZnHumidSP = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(ControlledZoneNum).RemainingOutputReqToHumidSP;
2416 1702 : SupplyHumRatForHumid = MdotZnHumidSP / SupplyMassFlowRate + state.dataLoopNodes->Node(ZoneNodeNum).HumRat;
2417 1702 : SupplyHumRatForHumid = min(SupplyHumRatForHumid, PurchAir(PurchAirNum).MaxHeatSuppAirHumRat);
2418 1702 : PurchAir(PurchAirNum).SupplyHumRat = max(PurchAir(PurchAirNum).SupplyHumRat, SupplyHumRatForHumid);
2419 : }
2420 : }
2421 : }
2422 :
2423 : // Limit supply humidity ratio to saturation at supply outlet temp
2424 :
2425 378326 : SupplyHumRatOrig = PurchAir(PurchAirNum).SupplyHumRat;
2426 378326 : SupplyHumRatSat = PsyWFnTdbRhPb(state, PurchAir(PurchAirNum).SupplyTemp, 1.0, state.dataEnvrn->OutBaroPress, RoutineName);
2427 378326 : PurchAir(PurchAirNum).SupplyHumRat = min(SupplyHumRatOrig, SupplyHumRatSat);
2428 378326 : SupplyEnthalpy = PsyHFnTdbW(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).SupplyHumRat);
2429 :
2430 : // Check max total Cooling capacity, if specified
2431 756652 : if ((PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitCapacity) ||
2432 378326 : (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRateAndCapacity)) {
2433 : // If dehumidifying, compare total cooling to the limit
2434 0 : if (PurchAir(PurchAirNum).SupplyHumRat < PurchAir(PurchAirNum).MixedAirHumRat) { // Dehumidifying
2435 0 : CoolTotOutput = SupplyMassFlowRate * (MixedAirEnthalpy - SupplyEnthalpy);
2436 0 : if ((CoolTotOutput) > PurchAir(PurchAirNum).MaxCoolTotCap) {
2437 0 : CoolTotOutput = PurchAir(PurchAirNum).MaxCoolTotCap;
2438 0 : SupplyEnthalpy = MixedAirEnthalpy - CoolTotOutput / SupplyMassFlowRate;
2439 : // Adjust output based on dehumidification control type
2440 0 : switch (PurchAir(PurchAirNum).DehumidCtrlType) {
2441 0 : case HumControl::ConstantSensibleHeatRatio: {
2442 : // Adjust both supply temp and humidity ratio to maintain SHR
2443 : // SHR = CoolSensOutput/CoolTotOutput
2444 : // CoolSensOutput = SHR*CoolTotOutput
2445 0 : CpAir = PsyCpAirFnW(PurchAir(PurchAirNum).MixedAirHumRat);
2446 0 : CoolSensOutput = CoolTotOutput * PurchAir(PurchAirNum).CoolSHR;
2447 0 : PurchAir(PurchAirNum).SupplyTemp = PurchAir(PurchAirNum).MixedAirTemp - CoolSensOutput / (CpAir * SupplyMassFlowRate);
2448 : // This is the cooling mode, so SupplyTemp can't be more than MixedAirTemp
2449 0 : PurchAir(PurchAirNum).SupplyTemp = min(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).MixedAirTemp);
2450 : // Limit for overdrying (avoid Pysch errors which occur if SupplyEnthalpy is too low for SupplyTemp)
2451 0 : SupplyEnthalpy = max(SupplyEnthalpy, PsyHFnTdbW(PurchAir(PurchAirNum).SupplyTemp, 0.00001));
2452 0 : PurchAir(PurchAirNum).SupplyHumRat = PsyWFnTdbH(state, PurchAir(PurchAirNum).SupplyTemp, SupplyEnthalpy, RoutineName);
2453 0 : } break;
2454 0 : case HumControl::Humidistat: {
2455 : // Keep supply temp and adjust humidity ratio to reduce load
2456 0 : PurchAir(PurchAirNum).SupplyHumRat = PsyWFnTdbH(state, PurchAir(PurchAirNum).SupplyTemp, SupplyEnthalpy, RoutineName);
2457 0 : } break;
2458 0 : case HumControl::None:
2459 : case HumControl::ConstantSupplyHumidityRatio: {
2460 : // Keep humidity ratio and adjust supply temp
2461 : // Check if latent output exceeds capacity
2462 0 : CpAir = PsyCpAirFnW(PurchAir(PurchAirNum).MixedAirHumRat);
2463 0 : CoolSensOutput = SupplyMassFlowRate * CpAir * (PurchAir(PurchAirNum).MixedAirTemp - PurchAir(PurchAirNum).SupplyTemp);
2464 0 : CoolLatOutput = CoolTotOutput - CoolSensOutput;
2465 0 : if (CoolLatOutput >= PurchAir(PurchAirNum).MaxCoolTotCap) {
2466 0 : PurchAir(PurchAirNum).SupplyTemp = PurchAir(PurchAirNum).MixedAirTemp;
2467 0 : PurchAir(PurchAirNum).SupplyHumRat =
2468 0 : PsyWFnTdbH(state, PurchAir(PurchAirNum).SupplyTemp, SupplyEnthalpy, RoutineName);
2469 0 : CoolLatOutput = PurchAir(PurchAirNum).MaxCoolTotCap;
2470 : } else {
2471 0 : PurchAir(PurchAirNum).SupplyTemp = PsyTdbFnHW(SupplyEnthalpy, PurchAir(PurchAirNum).SupplyHumRat);
2472 : // This is the cooling mode, so SupplyTemp can't be more than MixedAirTemp
2473 0 : PurchAir(PurchAirNum).SupplyTemp = min(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).MixedAirTemp);
2474 : }
2475 0 : } break;
2476 0 : default:
2477 0 : break;
2478 : }
2479 : // Limit supply humidity ratio to saturation at supply outlet temp
2480 : // If saturation exceeded, then honor capacity limit and set to dew point at supplyenthalpy
2481 :
2482 0 : SupplyHumRatOrig = PurchAir(PurchAirNum).SupplyHumRat;
2483 0 : SupplyHumRatSat = PsyWFnTdbRhPb(state, PurchAir(PurchAirNum).SupplyTemp, 1.0, state.dataEnvrn->OutBaroPress, RoutineName);
2484 0 : if (SupplyHumRatSat < SupplyHumRatOrig) {
2485 0 : PurchAir(PurchAirNum).SupplyTemp = PsyTsatFnHPb(state, SupplyEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName);
2486 :
2487 : // This is the cooling mode, so SupplyTemp can't be more than MixedAirTemp
2488 0 : PurchAir(PurchAirNum).SupplyTemp = min(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).MixedAirTemp);
2489 0 : PurchAir(PurchAirNum).SupplyHumRat = PsyWFnTdbH(state, PurchAir(PurchAirNum).SupplyTemp, SupplyEnthalpy, RoutineName);
2490 0 : SupplyEnthalpy = PsyHFnTdbW(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).SupplyHumRat);
2491 : // CpAir = PsyCpAirFnW(MixedAirHumRat)
2492 : // CoolSensOutput = SupplyMassFlowRate * CpAir * (MixedAirTemp - SupplyTemp)
2493 : // CoolTotOutput = SupplyMassFlowRate * (MixedAirEnthalpy - SupplyEnthalpy)
2494 : }
2495 : } // Capacity limit exceeded
2496 : } else { // Not dehumidifying
2497 : // If not dehumidifying, compare sensible cooling to the limit
2498 : // This section will only increase supply temp, so no need to recheck for super-saturation
2499 0 : CpAir = PsyCpAirFnW(PurchAir(PurchAirNum).MixedAirHumRat);
2500 0 : CoolSensOutput = SupplyMassFlowRate * CpAir * (PurchAir(PurchAirNum).MixedAirTemp - PurchAir(PurchAirNum).SupplyTemp);
2501 0 : if (CoolSensOutput >= PurchAir(PurchAirNum).MaxCoolTotCap) {
2502 0 : CoolSensOutput = PurchAir(PurchAirNum).MaxCoolTotCap;
2503 0 : PurchAir(PurchAirNum).SupplyTemp = PurchAir(PurchAirNum).MixedAirTemp - CoolSensOutput / (SupplyMassFlowRate * CpAir);
2504 : } // Capacity limit exceeded
2505 : } // Dehumidifying or not
2506 : } // Capacity limit active
2507 :
2508 : } else { // SupplyMassFlowRate is zero
2509 5393 : SupplyEnthalpy = MixedAirEnthalpy;
2510 5393 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MixedAirHumRat;
2511 5393 : PurchAir(PurchAirNum).SupplyTemp = PurchAir(PurchAirNum).MixedAirTemp;
2512 5393 : CoolSensOutput = 0.0;
2513 5393 : CoolTotOutput = 0.0;
2514 : }
2515 : // Heating or no-load operation
2516 : } else { // Heating or no-load case
2517 1627439 : if ((MinOASensOutput < QZnHeatSP) &&
2518 719932 : (state.dataHeatBalFanSys->TempControlType(ControlledZoneNum) != DataHVACGlobals::ThermostatType::SingleCooling)) {
2519 546273 : OperatingMode = OpMode::Heat;
2520 : } else { // DeadBand mode shuts off heat recovery and economizer
2521 361234 : OperatingMode = OpMode::DeadBand;
2522 : }
2523 : // Calculate supply mass flow, temp and humidity with the following constraints:
2524 : // Max heating supply temp
2525 : // Max sensible heating capacity
2526 : // Max heating airflow
2527 : // Max heating supply humrat (and Min cooling supply humrat)
2528 : // Min OA mass flow rate
2529 :
2530 : // Check if OA flow rate greater than max heating airflow limit
2531 2713712 : if (((PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRate) ||
2532 916316 : (PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRateAndCapacity)) &&
2533 8809 : (OAMassFlowRate > PurchAir(PurchAirNum).MaxHeatMassFlowRate)) {
2534 0 : OAVolFlowRate = OAMassFlowRate / state.dataEnvrn->StdRhoAir;
2535 0 : if (PurchAir(PurchAirNum).OAFlowMaxHeatOutputError < 1) {
2536 0 : ++PurchAir(PurchAirNum).OAFlowMaxHeatOutputError;
2537 0 : ShowWarningError(state,
2538 0 : format("{} \"{}\" Requested outdoor air flow rate = {:.5T} [m3/s] exceeds limit.",
2539 0 : PurchAir(PurchAirNum).cObjectName,
2540 0 : PurchAir(PurchAirNum).Name,
2541 0 : OAVolFlowRate));
2542 0 : ShowContinueError(
2543 : state,
2544 0 : format(" Will be reduced to the Maximum Heating Air Flow Rate = {:.5T} [m3/s]", PurchAir(PurchAirNum).MaxHeatVolFlowRate));
2545 0 : ShowContinueErrorTimeStamp(state, "");
2546 : } else {
2547 0 : ShowRecurringWarningErrorAtEnd(
2548 : state,
2549 0 : PurchAir(PurchAirNum).cObjectName + " \"" + PurchAir(PurchAirNum).Name +
2550 : "\" Requested outdoor air flow rate [m3/s] reduced to Maximum Heating Air Flow Rate warning continues...",
2551 0 : PurchAir(PurchAirNum).OAFlowMaxHeatOutputIndex,
2552 : OAVolFlowRate);
2553 : }
2554 0 : OAMassFlowRate = PurchAir(PurchAirNum).MaxHeatMassFlowRate;
2555 : }
2556 :
2557 907507 : SupplyMassFlowRate = OAMassFlowRate;
2558 :
2559 : // Determine supply mass flow rate
2560 : // Mass flow rate to meet sensible load, at Minimum Cooling Supply Air Temperature
2561 907507 : SupplyMassFlowRateForHeat = 0.0;
2562 907507 : if ((HeatOn) && (OperatingMode == OpMode::Heat)) {
2563 546273 : CpAir = PsyCpAirFnW(thisZoneHB.ZoneAirHumRat);
2564 546273 : DeltaT = (PurchAir(PurchAirNum).MaxHeatSuppAirTemp - state.dataLoopNodes->Node(ZoneNodeNum).Temp);
2565 546273 : if (DeltaT > SmallTempDiff) {
2566 546273 : SupplyMassFlowRateForHeat = QZnHeatSP / CpAir / DeltaT;
2567 : }
2568 : }
2569 :
2570 : // Mass flow rate to meet dehumidification load, if applicable, at Minimum Cooling Supply Humidity Ratio
2571 : // This section is the heating/deadband section, so dehumidification should activate
2572 : // only if dehumidification control = humidistat
2573 : // and if humidification control = humidistat or none or if operating in deadband mode
2574 907507 : SupplyMassFlowRateForDehum = 0.0;
2575 907507 : if (CoolOn) {
2576 903539 : if (PurchAir(PurchAirNum).DehumidCtrlType == HumControl::Humidistat) {
2577 3994 : if ((PurchAir(PurchAirNum).HumidCtrlType == HumControl::Humidistat) ||
2578 1997 : (PurchAir(PurchAirNum).HumidCtrlType == HumControl::None) || (OperatingMode == OpMode::DeadBand)) {
2579 1997 : MdotZnDehumidSP = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(ControlledZoneNum).RemainingOutputReqToDehumidSP;
2580 1997 : DeltaHumRat = (PurchAir(PurchAirNum).MinCoolSuppAirHumRat - state.dataLoopNodes->Node(ZoneNodeNum).HumRat);
2581 1997 : if ((DeltaHumRat < -SmallDeltaHumRat) && (MdotZnDehumidSP < 0.0)) {
2582 449 : SupplyMassFlowRateForDehum = MdotZnDehumidSP / DeltaHumRat;
2583 : }
2584 : }
2585 : }
2586 : }
2587 :
2588 : // Mass flow rate to meet humidification load, if applicable, at Maximum Heating Supply Humidity Ratio
2589 907507 : SupplyMassFlowRateForHumid = 0.0;
2590 907507 : if (HeatOn) {
2591 907507 : if (PurchAir(PurchAirNum).HumidCtrlType == HumControl::Humidistat) {
2592 4050 : MdotZnHumidSP = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(ControlledZoneNum).RemainingOutputReqToHumidSP;
2593 4050 : DeltaHumRat = (PurchAir(PurchAirNum).MaxHeatSuppAirHumRat - state.dataLoopNodes->Node(ZoneNodeNum).HumRat);
2594 4050 : if ((DeltaHumRat > SmallDeltaHumRat) && (MdotZnHumidSP > 0.0)) {
2595 2788 : SupplyMassFlowRateForHumid = MdotZnHumidSP / DeltaHumRat;
2596 : }
2597 : }
2598 : }
2599 :
2600 : // If heating capacity is limited to zero, SupplyMassFlowRate* should be set to zero
2601 2722521 : if (((PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitCapacity) ||
2602 907507 : (PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRateAndCapacity)) &&
2603 0 : (PurchAir(PurchAirNum).MaxHeatSensCap == 0)) {
2604 0 : SupplyMassFlowRateForHeat = 0;
2605 0 : SupplyMassFlowRateForDehum = 0;
2606 0 : SupplyMassFlowRateForHumid = 0;
2607 : }
2608 :
2609 : // Supply mass flow is greatest of these, but limit to heating max flow rate, if applicable
2610 907507 : SupplyMassFlowRate = max(0.0, OAMassFlowRate, SupplyMassFlowRateForHeat, SupplyMassFlowRateForDehum, SupplyMassFlowRateForHumid);
2611 : // EMS override point Purch air massflow rate..... but only if unit is on, i.e. SupplyMassFlowRate>0.0
2612 907507 : if (PurchAir(PurchAirNum).EMSOverrideMdotOn) {
2613 162170 : SupplyMassFlowRate = PurchAir(PurchAirNum).EMSValueMassFlowRate;
2614 162170 : OAMassFlowRate = min(OAMassFlowRate, SupplyMassFlowRate);
2615 : }
2616 2713712 : if (((PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRate) ||
2617 916316 : (PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRateAndCapacity)) &&
2618 8809 : (PurchAir(PurchAirNum).MaxHeatMassFlowRate > 0.0)) {
2619 8808 : SupplyMassFlowRate = min(SupplyMassFlowRate, PurchAir(PurchAirNum).MaxHeatMassFlowRate);
2620 : }
2621 :
2622 907507 : if (SupplyMassFlowRate <= VerySmallMassFlow) SupplyMassFlowRate = 0.0;
2623 :
2624 : // Calculate mixed air conditions
2625 1815014 : CalcPurchAirMixedAir(state,
2626 : PurchAirNum,
2627 : OAMassFlowRate,
2628 : SupplyMassFlowRate,
2629 907507 : PurchAir(PurchAirNum).MixedAirTemp,
2630 907507 : PurchAir(PurchAirNum).MixedAirHumRat,
2631 : MixedAirEnthalpy,
2632 : OperatingMode);
2633 :
2634 : // Calculate supply air conditions using final massflow rate, imposing capacity limits if specified
2635 : // If capacity limits are exceeded, keep massflow rate where it is and adjust supply temp
2636 907507 : if (SupplyMassFlowRate > 0.0) {
2637 600413 : if ((HeatOn) && (OperatingMode == OpMode::Heat)) {
2638 : // Calculate supply temp at SupplyMassFlowRate and check limit on Maximum Heating Supply Air Temperature
2639 546273 : CpAir = PsyCpAirFnW(thisZoneHB.ZoneAirHumRat);
2640 546273 : PurchAir(PurchAirNum).SupplyTemp = QZnHeatSP / (CpAir * SupplyMassFlowRate) + state.dataLoopNodes->Node(ZoneNodeNum).Temp;
2641 546273 : PurchAir(PurchAirNum).SupplyTemp = min(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).MaxHeatSuppAirTemp);
2642 : // This is the heating mode, so SupplyTemp can't be less than MixedAirTemp
2643 546273 : PurchAir(PurchAirNum).SupplyTemp = max(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).MixedAirTemp);
2644 : // Check max heating capacity, if specified
2645 1638819 : if ((PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitCapacity) ||
2646 546273 : (PurchAir(PurchAirNum).HeatingLimit == LimitType::LimitFlowRateAndCapacity)) {
2647 0 : CpAir = PsyCpAirFnW(PurchAir(PurchAirNum).MixedAirHumRat);
2648 0 : HeatSensOutput = SupplyMassFlowRate * CpAir * (PurchAir(PurchAirNum).SupplyTemp - PurchAir(PurchAirNum).MixedAirTemp);
2649 0 : if (HeatSensOutput > PurchAir(PurchAirNum).MaxHeatSensCap) {
2650 0 : PurchAir(PurchAirNum).SupplyTemp =
2651 0 : PurchAir(PurchAirNum).MaxHeatSensCap / (SupplyMassFlowRate * CpAir) + PurchAir(PurchAirNum).MixedAirTemp;
2652 0 : HeatSensOutput = PurchAir(PurchAirNum).MaxHeatSensCap;
2653 : }
2654 : }
2655 : } else { // Heat is off or operating mode is deadband (i.e. don't do any heating)
2656 54140 : PurchAir(PurchAirNum).SupplyTemp = PurchAir(PurchAirNum).MixedAirTemp;
2657 : }
2658 :
2659 : // Set supply humidity ratio first for heating/humidification
2660 600413 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MixedAirHumRat;
2661 600413 : switch (PurchAir(PurchAirNum).HumidCtrlType) {
2662 48974 : case HumControl::None: {
2663 48974 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MixedAirHumRat;
2664 48974 : } break;
2665 3916 : case HumControl::Humidistat: {
2666 3916 : MdotZnHumidSP = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(ControlledZoneNum).RemainingOutputReqToHumidSP;
2667 3916 : SupplyHumRatForHumid = MdotZnHumidSP / SupplyMassFlowRate + state.dataLoopNodes->Node(ZoneNodeNum).HumRat;
2668 3916 : SupplyHumRatForHumid = min(SupplyHumRatForHumid, PurchAir(PurchAirNum).MaxHeatSuppAirHumRat);
2669 3916 : PurchAir(PurchAirNum).SupplyHumRat = max(PurchAir(PurchAirNum).SupplyHumRat, SupplyHumRatForHumid);
2670 3916 : } break;
2671 547523 : case HumControl::ConstantSupplyHumidityRatio: {
2672 547523 : if (OperatingMode == OpMode::Heat) {
2673 : // If this results in dehumidification, must check cooling capacity limit
2674 495497 : if (PurchAir(PurchAirNum).MixedAirHumRat > PurchAir(PurchAirNum).MaxHeatSuppAirHumRat) {
2675 121414 : if ((PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitCapacity) ||
2676 60707 : (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRateAndCapacity)) {
2677 0 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MaxHeatSuppAirHumRat;
2678 0 : SupplyEnthalpy = PsyHFnTdbW(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).SupplyHumRat);
2679 0 : CoolTotOutput = SupplyMassFlowRate * (MixedAirEnthalpy - SupplyEnthalpy);
2680 0 : CpAir = PsyCpAirFnW(PurchAir(PurchAirNum).MixedAirHumRat);
2681 0 : CoolSensOutput = SupplyMassFlowRate * CpAir * (PurchAir(PurchAirNum).MixedAirTemp - PurchAir(PurchAirNum).SupplyTemp);
2682 0 : CoolLatOutput = CoolTotOutput - CoolSensOutput;
2683 0 : if (CoolLatOutput >= PurchAir(PurchAirNum).MaxCoolTotCap) {
2684 0 : CoolLatOutput = PurchAir(PurchAirNum).MaxCoolTotCap;
2685 0 : CoolTotOutput = CoolSensOutput + CoolLatOutput;
2686 0 : SupplyEnthalpy = MixedAirEnthalpy - CoolTotOutput / SupplyMassFlowRate;
2687 0 : PurchAir(PurchAirNum).SupplyHumRat =
2688 0 : PsyWFnTdbH(state, PurchAir(PurchAirNum).SupplyTemp, SupplyEnthalpy, RoutineName);
2689 : }
2690 : } else {
2691 60707 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MaxHeatSuppAirHumRat;
2692 : }
2693 : } else {
2694 434790 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MaxHeatSuppAirHumRat;
2695 : }
2696 : } else {
2697 52026 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MixedAirHumRat;
2698 : }
2699 547523 : } break;
2700 0 : default: {
2701 0 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MixedAirHumRat;
2702 0 : } break;
2703 : }
2704 600413 : SupplyEnthalpy = PsyHFnTdbW(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).SupplyHumRat);
2705 :
2706 : // Check supply humidity ratio for dehumidification (SupplyHumRatForHumid should always be < SupplyHumRatForDehum)
2707 : // This section is the heating/deadband section, so dehumidification should activate
2708 : // only if dehumidification control = humidistat
2709 : // and if humidification control = humidistat or none or if operating in deadband mode
2710 600413 : if (CoolOn) {
2711 596515 : if (PurchAir(PurchAirNum).DehumidCtrlType == HumControl::Humidistat) {
2712 3748 : if ((PurchAir(PurchAirNum).HumidCtrlType == HumControl::Humidistat) ||
2713 1874 : (PurchAir(PurchAirNum).HumidCtrlType == HumControl::None) || (OperatingMode == OpMode::DeadBand)) {
2714 1874 : MdotZnDehumidSP = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(ControlledZoneNum).RemainingOutputReqToDehumidSP;
2715 1874 : SupplyHumRatForDehum = MdotZnDehumidSP / SupplyMassFlowRate + state.dataLoopNodes->Node(ZoneNodeNum).HumRat;
2716 1874 : SupplyHumRatForDehum = max(SupplyHumRatForDehum, PurchAir(PurchAirNum).MinCoolSuppAirHumRat);
2717 1874 : PurchAir(PurchAirNum).SupplyHumRat = min(PurchAir(PurchAirNum).SupplyHumRat, SupplyHumRatForDehum);
2718 1874 : SupplyEnthalpy = PsyHFnTdbW(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).SupplyHumRat);
2719 1874 : if (PurchAir(PurchAirNum).SupplyHumRat < PurchAir(PurchAirNum).MixedAirHumRat) {
2720 : // At this point, the system is heating or deadband but dehumidifying, check max cooling cap limit
2721 449 : CpAir = PsyCpAirFnW(PurchAir(PurchAirNum).MixedAirHumRat);
2722 449 : SensOutput = SupplyMassFlowRate * CpAir * (PurchAir(PurchAirNum).SupplyTemp - PurchAir(PurchAirNum).MixedAirTemp);
2723 449 : LatOutput = SupplyMassFlowRate * (SupplyEnthalpy - MixedAirEnthalpy) - SensOutput;
2724 898 : if ((PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitCapacity) ||
2725 449 : (PurchAir(PurchAirNum).CoolingLimit == LimitType::LimitFlowRateAndCapacity)) {
2726 0 : if (LatOutput > PurchAir(PurchAirNum).MaxCoolTotCap) {
2727 0 : LatOutput = PurchAir(PurchAirNum).MaxCoolTotCap;
2728 0 : SupplyEnthalpy = MixedAirEnthalpy + (LatOutput + SensOutput) / SupplyMassFlowRate;
2729 0 : PurchAir(PurchAirNum).SupplyHumRat =
2730 0 : PsyWFnTdbH(state, PurchAir(PurchAirNum).SupplyTemp, SupplyEnthalpy, RoutineName);
2731 : }
2732 : }
2733 : }
2734 : }
2735 : }
2736 : }
2737 :
2738 : // Limit supply humidity ratio to saturation at supply outlet temp
2739 :
2740 600413 : SupplyHumRatOrig = PurchAir(PurchAirNum).SupplyHumRat;
2741 600413 : PurchAir(PurchAirNum).SupplyHumRat =
2742 1200826 : min(PurchAir(PurchAirNum).SupplyHumRat,
2743 1200826 : PsyWFnTdbRhPb(state, PurchAir(PurchAirNum).SupplyTemp, 1.0, state.dataEnvrn->OutBaroPress, RoutineName));
2744 600413 : SupplyEnthalpy = PsyHFnTdbW(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).SupplyHumRat);
2745 :
2746 : } else { // SupplyMassFlowRate is zero
2747 307094 : SupplyEnthalpy = MixedAirEnthalpy;
2748 307094 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MixedAirHumRat;
2749 307094 : PurchAir(PurchAirNum).SupplyTemp = PurchAir(PurchAirNum).MixedAirTemp;
2750 307094 : HeatSensOutput = 0.0;
2751 : }
2752 :
2753 : } // Cooling or heating required
2754 :
2755 1291226 : if (SupplyMassFlowRate > 0.0) {
2756 : // EMS override point Purch air supply temp and humidty ratio ..... but only if unit is on, SupplyMassFlowRate>0.0
2757 978739 : if (PurchAir(PurchAirNum).EMSOverrideSupplyTempOn) {
2758 241986 : PurchAir(PurchAirNum).SupplyTemp = PurchAir(PurchAirNum).EMSValueSupplyTemp;
2759 : }
2760 978739 : if (PurchAir(PurchAirNum).EMSOverrideSupplyHumRatOn) {
2761 241986 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).EMSValueSupplyHumRat;
2762 : }
2763 978739 : SupplyEnthalpy = PsyHFnTdbW(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).SupplyHumRat);
2764 :
2765 : // compute coil loads
2766 1055948 : if ((PurchAir(PurchAirNum).SupplyHumRat == PurchAir(PurchAirNum).MixedAirHumRat) &&
2767 77209 : (PurchAir(PurchAirNum).SupplyTemp == PurchAir(PurchAirNum).MixedAirTemp)) {
2768 : // If no change in humrat or temp, then set loads to zero
2769 1715 : PurchAir(PurchAirNum).SenCoilLoad = 0.0;
2770 1715 : PurchAir(PurchAirNum).LatCoilLoad = 0.0;
2771 1052518 : } else if ((PurchAir(PurchAirNum).SupplyHumRat == PurchAir(PurchAirNum).MixedAirHumRat) &&
2772 75494 : (PurchAir(PurchAirNum).SupplyTemp != PurchAir(PurchAirNum).MixedAirTemp)) {
2773 : // If no change in humrat, then set latent load to zero and use enthalpies to calculate sensible load
2774 75494 : PurchAir(PurchAirNum).SenCoilLoad = SupplyMassFlowRate * (SupplyEnthalpy - MixedAirEnthalpy);
2775 75494 : PurchAir(PurchAirNum).LatCoilLoad = 0.0;
2776 : } else {
2777 901530 : CpAir = PsyCpAirFnW(PurchAir(PurchAirNum).MixedAirHumRat);
2778 901530 : PurchAir(PurchAirNum).SenCoilLoad =
2779 901530 : SupplyMassFlowRate * CpAir * (PurchAir(PurchAirNum).SupplyTemp - PurchAir(PurchAirNum).MixedAirTemp);
2780 901530 : PurchAir(PurchAirNum).LatCoilLoad = SupplyMassFlowRate * (SupplyEnthalpy - MixedAirEnthalpy) - PurchAir(PurchAirNum).SenCoilLoad;
2781 : }
2782 :
2783 : // Apply heating and cooling availability schedules to sensible load
2784 978739 : if (((PurchAir(PurchAirNum).SenCoilLoad > 0.0) && !HeatOn) || ((PurchAir(PurchAirNum).SenCoilLoad < 0.0) && !CoolOn)) {
2785 : // Coil is off
2786 0 : PurchAir(PurchAirNum).SenCoilLoad = 0.0;
2787 0 : PurchAir(PurchAirNum).SupplyTemp = PurchAir(PurchAirNum).MixedAirTemp;
2788 : }
2789 :
2790 : // Apply heating and cooling availability schedules to latent load
2791 978739 : if (((PurchAir(PurchAirNum).LatCoilLoad > 0.0) && !HeatOn) || ((PurchAir(PurchAirNum).LatCoilLoad < 0.0) && !CoolOn)) {
2792 : // Coil is off
2793 292 : PurchAir(PurchAirNum).LatCoilLoad = 0.0;
2794 292 : PurchAir(PurchAirNum).SupplyHumRat = PurchAir(PurchAirNum).MixedAirHumRat;
2795 : }
2796 :
2797 : // Double-check if saturation exceeded, then thow warning, shouldn't happen here, don't reset, just warn
2798 :
2799 978739 : SupplyHumRatOrig = PurchAir(PurchAirNum).SupplyHumRat;
2800 978739 : SupplyHumRatSat = PsyWFnTdbRhPb(state, PurchAir(PurchAirNum).SupplyTemp, 1.0, state.dataEnvrn->OutBaroPress, RoutineName);
2801 :
2802 978739 : DeltaHumRat = SupplyHumRatOrig - SupplyHumRatSat;
2803 978739 : if (DeltaHumRat > SmallDeltaHumRat) {
2804 0 : if (PurchAir(PurchAirNum).SaturationOutputError < 1) {
2805 0 : ++PurchAir(PurchAirNum).SaturationOutputError;
2806 0 : ShowWarningError(state,
2807 0 : format("{} \"{}\" Supply humidity ratio = {:.5T} exceeds saturation limit {:.5T} [kgWater/kgDryAir]",
2808 0 : PurchAir(PurchAirNum).cObjectName,
2809 0 : PurchAir(PurchAirNum).Name,
2810 : SupplyHumRatOrig,
2811 0 : SupplyHumRatSat));
2812 0 : ShowContinueError(state, " Simulation continuing . . . ");
2813 0 : ShowContinueErrorTimeStamp(state, "");
2814 : } else {
2815 0 : ShowRecurringWarningErrorAtEnd(
2816 : state,
2817 0 : PurchAir(PurchAirNum).cObjectName + " \"" + PurchAir(PurchAirNum).Name +
2818 : "\" Supply humidity ratio exceeds saturation limit warning continues, delta max/min [kgWater/kgDryAir]...",
2819 0 : PurchAir(PurchAirNum).SaturationOutputIndex,
2820 : DeltaHumRat,
2821 : DeltaHumRat);
2822 : }
2823 : }
2824 :
2825 978739 : SupplyEnthalpy = PsyHFnTdbW(PurchAir(PurchAirNum).SupplyTemp, PurchAir(PurchAirNum).SupplyHumRat);
2826 :
2827 978739 : CpAir = PsyCpAirFnW(thisZoneHB.ZoneAirHumRat);
2828 978739 : SysOutputProvided = SupplyMassFlowRate * CpAir * (PurchAir(PurchAirNum).SupplyTemp - state.dataLoopNodes->Node(ZoneNodeNum).Temp);
2829 978739 : MoistOutputProvided =
2830 978739 : SupplyMassFlowRate * (PurchAir(PurchAirNum).SupplyHumRat - state.dataLoopNodes->Node(ZoneNodeNum).HumRat); // Latent rate, kg/s
2831 :
2832 978739 : PurchAir(PurchAirNum).SenOutputToZone = SysOutputProvided;
2833 978739 : PurchAir(PurchAirNum).LatOutputToZone =
2834 978739 : SupplyMassFlowRate * (SupplyEnthalpy - state.dataLoopNodes->Node(ZoneNodeNum).Enthalpy) - PurchAir(PurchAirNum).SenOutputToZone;
2835 :
2836 978739 : CpAir = PsyCpAirFnW(thisZoneHB.ZoneAirHumRat);
2837 978739 : if (PurchAir(PurchAirNum).OutdoorAir) {
2838 14662 : PurchAir(PurchAirNum).OASenOutput =
2839 14662 : OAMassFlowRate * CpAir * (state.dataLoopNodes->Node(OANodeNum).Temp - state.dataLoopNodes->Node(ZoneNodeNum).Temp);
2840 14662 : PurchAir(PurchAirNum).OALatOutput =
2841 29324 : OAMassFlowRate * (state.dataLoopNodes->Node(OANodeNum).Enthalpy - state.dataLoopNodes->Node(ZoneNodeNum).Enthalpy) -
2842 14662 : PurchAir(PurchAirNum).OASenOutput;
2843 : } else {
2844 964077 : PurchAir(PurchAirNum).OASenOutput = 0.0;
2845 964077 : PurchAir(PurchAirNum).OALatOutput = 0.0;
2846 : }
2847 978739 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
2848 131718 : if (PurchAir(PurchAirNum).OutdoorAir) {
2849 0 : state.dataLoopNodes->Node(InNodeNum).CO2 = ((SupplyMassFlowRate - OAMassFlowRate) * state.dataLoopNodes->Node(RecircNodeNum).CO2 +
2850 0 : OAMassFlowRate * state.dataLoopNodes->Node(OANodeNum).CO2) /
2851 : SupplyMassFlowRate;
2852 : } else {
2853 131718 : state.dataLoopNodes->Node(InNodeNum).CO2 = state.dataLoopNodes->Node(RecircNodeNum).CO2;
2854 : }
2855 : }
2856 978739 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
2857 116434 : if (PurchAir(PurchAirNum).OutdoorAir) {
2858 0 : state.dataLoopNodes->Node(InNodeNum).GenContam =
2859 0 : ((SupplyMassFlowRate - OAMassFlowRate) * state.dataLoopNodes->Node(RecircNodeNum).GenContam +
2860 0 : OAMassFlowRate * state.dataLoopNodes->Node(OANodeNum).GenContam) /
2861 : SupplyMassFlowRate;
2862 : } else {
2863 116434 : state.dataLoopNodes->Node(InNodeNum).GenContam = state.dataLoopNodes->Node(RecircNodeNum).GenContam;
2864 : }
2865 : }
2866 : } else { // SupplyMassFlowRate = 0.0
2867 312487 : SysOutputProvided = 0.0;
2868 312487 : MoistOutputProvided = 0.0;
2869 :
2870 312487 : PurchAir(PurchAirNum).SenOutputToZone = 0.0;
2871 312487 : PurchAir(PurchAirNum).LatOutputToZone = 0.0;
2872 312487 : PurchAir(PurchAirNum).SenCoilLoad = 0.0;
2873 312487 : PurchAir(PurchAirNum).LatCoilLoad = 0.0;
2874 312487 : PurchAir(PurchAirNum).OASenOutput = 0.0;
2875 312487 : PurchAir(PurchAirNum).OALatOutput = 0.0;
2876 :
2877 312487 : PurchAir(PurchAirNum).MixedAirTemp = state.dataLoopNodes->Node(RecircNodeNum).Temp;
2878 312487 : PurchAir(PurchAirNum).MixedAirHumRat = state.dataLoopNodes->Node(RecircNodeNum).HumRat;
2879 312487 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
2880 :
2881 48138 : state.dataLoopNodes->Node(InNodeNum).CO2 = state.dataLoopNodes->Node(ZoneNodeNum).CO2;
2882 : }
2883 312487 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
2884 24830 : state.dataLoopNodes->Node(InNodeNum).GenContam = state.dataLoopNodes->Node(ZoneNodeNum).GenContam;
2885 : }
2886 : }
2887 :
2888 1291226 : state.dataLoopNodes->Node(InNodeNum).Temp = PurchAir(PurchAirNum).SupplyTemp;
2889 1291226 : state.dataLoopNodes->Node(InNodeNum).HumRat = PurchAir(PurchAirNum).SupplyHumRat;
2890 1291226 : state.dataLoopNodes->Node(InNodeNum).Enthalpy = SupplyEnthalpy;
2891 1291226 : state.dataLoopNodes->Node(InNodeNum).MassFlowRate = SupplyMassFlowRate;
2892 1291226 : if (PurchAir(PurchAirNum).OutdoorAir) state.dataLoopNodes->Node(OANodeNum).MassFlowRate = OAMassFlowRate;
2893 :
2894 : } else { // purchased air OFF
2895 :
2896 0 : SysOutputProvided = 0.0;
2897 0 : MoistOutputProvided = 0.0;
2898 0 : SupplyMassFlowRate = 0.0;
2899 0 : OAMassFlowRate = 0.0;
2900 0 : state.dataLoopNodes->Node(InNodeNum).Temp = state.dataLoopNodes->Node(ZoneNodeNum).Temp;
2901 0 : state.dataLoopNodes->Node(InNodeNum).HumRat = state.dataLoopNodes->Node(ZoneNodeNum).HumRat;
2902 0 : state.dataLoopNodes->Node(InNodeNum).Enthalpy = state.dataLoopNodes->Node(ZoneNodeNum).Enthalpy;
2903 0 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
2904 0 : state.dataLoopNodes->Node(InNodeNum).CO2 = state.dataLoopNodes->Node(ZoneNodeNum).CO2;
2905 : }
2906 0 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
2907 0 : state.dataLoopNodes->Node(InNodeNum).GenContam = state.dataLoopNodes->Node(ZoneNodeNum).GenContam;
2908 : }
2909 :
2910 0 : state.dataLoopNodes->Node(InNodeNum).MassFlowRate = 0.0;
2911 0 : if (PurchAir(PurchAirNum).OutdoorAir) state.dataLoopNodes->Node(OANodeNum).MassFlowRate = 0.0;
2912 0 : PurchAir(PurchAirNum).SenHeatRate = 0.0;
2913 0 : PurchAir(PurchAirNum).SenCoolRate = 0.0;
2914 0 : PurchAir(PurchAirNum).TotCoolRate = 0.0;
2915 :
2916 0 : PurchAir(PurchAirNum).SenOutputToZone = 0.0;
2917 0 : PurchAir(PurchAirNum).LatOutputToZone = 0.0;
2918 0 : PurchAir(PurchAirNum).SenCoilLoad = 0.0;
2919 0 : PurchAir(PurchAirNum).LatCoilLoad = 0.0;
2920 0 : PurchAir(PurchAirNum).OASenOutput = 0.0;
2921 0 : PurchAir(PurchAirNum).OALatOutput = 0.0;
2922 0 : PurchAir(PurchAirNum).MixedAirTemp = state.dataLoopNodes->Node(RecircNodeNum).Temp;
2923 0 : PurchAir(PurchAirNum).MixedAirHumRat = state.dataLoopNodes->Node(RecircNodeNum).HumRat;
2924 0 : PurchAir(PurchAirNum).SupplyTemp = state.dataLoopNodes->Node(InNodeNum).Temp;
2925 0 : PurchAir(PurchAirNum).SupplyHumRat = state.dataLoopNodes->Node(InNodeNum).HumRat;
2926 : }
2927 :
2928 1291226 : PurchAir(PurchAirNum).OutdoorAirMassFlowRate = OAMassFlowRate;
2929 1291226 : PurchAir(PurchAirNum).OutdoorAirVolFlowRateStdRho = OAMassFlowRate / state.dataEnvrn->StdRhoAir;
2930 1291226 : PurchAir(PurchAirNum).SupplyAirMassFlowRate = SupplyMassFlowRate;
2931 :
2932 1291226 : PurchAir(PurchAirNum).SupplyAirVolFlowRateStdRho = SupplyMassFlowRate / state.dataEnvrn->StdRhoAir;
2933 :
2934 1291226 : if (PurchAir(PurchAirNum).PlenumExhaustAirNodeNum > 0) {
2935 15075 : state.dataLoopNodes->Node(PurchAir(PurchAirNum).PlenumExhaustAirNodeNum).MassFlowRate = SupplyMassFlowRate;
2936 : }
2937 1291226 : state.dataLoopNodes->Node(RecircNodeNum).MassFlowRate = SupplyMassFlowRate;
2938 1291226 : }
2939 :
2940 1291226 : void CalcPurchAirMinOAMassFlow(EnergyPlusData &state,
2941 : int const PurchAirNum, // index to ideal loads unit
2942 : int const ZoneNum, // index to zone
2943 : Real64 &OAMassFlowRate // outside air mass flow rate [kg/s] from volume flow using std density
2944 : )
2945 : {
2946 :
2947 : // SUBROUTINE INFORMATION:
2948 : // AUTHOR M. Witte (GARD)
2949 : // DATE WRITTEN Jun 2011 (taken from HVACSingleDuctSystem.cc and adapted for Ideal Loads System)
2950 : // MODIFIED na
2951 : // RE-ENGINEERED na
2952 :
2953 : // PURPOSE OF THIS SUBROUTINE:
2954 : // Calculates the amount of outside air required based on optional user input.
2955 : // Zone multipliers have been applied in GetInput.
2956 :
2957 : // METHODOLOGY EMPLOYED:
2958 : // User input defines method used to calculate OA.
2959 :
2960 : // FUNCTION PARAMETER DEFINITIONS:
2961 1291226 : bool constexpr UseMinOASchFlag(true); // Always use min OA schedule in calculations.
2962 :
2963 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
2964 : bool UseOccSchFlag; // TRUE = use actual occupancy, FALSE = use total zone people
2965 : Real64 OAVolumeFlowRate; // outside air flow rate (m3/s)
2966 :
2967 1291226 : auto &PurchAir(state.dataPurchasedAirMgr->PurchAir);
2968 :
2969 1291226 : if (PurchAir(PurchAirNum).OutdoorAir) {
2970 :
2971 14796 : if (PurchAir(PurchAirNum).DCVType == DCV::OccupancySchedule) {
2972 3699 : UseOccSchFlag = true;
2973 : } else {
2974 11097 : UseOccSchFlag = false;
2975 : }
2976 14796 : OAVolumeFlowRate =
2977 14796 : DataSizing::calcDesignSpecificationOutdoorAir(state, PurchAir(PurchAirNum).OARequirementsPtr, ZoneNum, UseOccSchFlag, UseMinOASchFlag);
2978 14796 : OAMassFlowRate = OAVolumeFlowRate * state.dataEnvrn->StdRhoAir;
2979 :
2980 : // If DCV with CO2SetPoint then check required OA flow to meet CO2 setpoint
2981 14796 : if (PurchAir(PurchAirNum).DCVType == DCV::CO2SetPoint) {
2982 0 : OAMassFlowRate = max(OAMassFlowRate, state.dataContaminantBalance->ZoneSysContDemand(ZoneNum).OutputRequiredToCO2SP);
2983 : }
2984 :
2985 14796 : if (OAMassFlowRate <= VerySmallMassFlow) OAMassFlowRate = 0.0;
2986 :
2987 : } else { // No outdoor air
2988 1276430 : OAMassFlowRate = 0.0;
2989 : }
2990 1291226 : PurchAir(PurchAirNum).MinOAMassFlowRate = OAMassFlowRate;
2991 1291226 : }
2992 :
2993 1291226 : void CalcPurchAirMixedAir(EnergyPlusData &state,
2994 : int const PurchAirNum, // index to ideal loads unit
2995 : Real64 const OAMassFlowRate, // outside air mass flow rate [kg/s]
2996 : Real64 const SupplyMassFlowRate, // supply air mass flow rate [kg/s]
2997 : Real64 &MixedAirTemp, // Mixed air dry bulb temperature [C]
2998 : Real64 &MixedAirHumRat, // Mixed air humidity ratio [kgWater/kgDryAir]
2999 : Real64 &MixedAirEnthalpy, // Mixed air enthalpy [J/kg]
3000 : OpMode const OperatingMode // current operating mode, Off, Heating, Cooling, or DeadBand
3001 : )
3002 : {
3003 :
3004 : // SUBROUTINE INFORMATION:
3005 : // AUTHOR M. Witte (GARD)
3006 : // DATE WRITTEN Sep 2011
3007 : // MODIFIED na
3008 : // RE-ENGINEERED na
3009 :
3010 : // PURPOSE OF THIS SUBROUTINE:
3011 : // Calculates the mixed air conditions, accounting for heat recovery.
3012 :
3013 : // SUBROUTINE PARAMETER DEFINITIONS:
3014 : static constexpr std::string_view RoutineName("CalcPurchAirMixedAir");
3015 :
3016 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3017 : int RecircNodeNum; // Zone return air node
3018 : int OANodeNum; // Outdoor air inlet node
3019 : Real64 RecircTemp; // Recirculated air from zone dry bulb temperature [C]
3020 : Real64 RecircHumRat; // Recirculated air from zone humidity ratio [kgWater/kgDryAir]
3021 : Real64 RecircEnthalpy; // Recirculated air from zone enthalpy [J/kg]
3022 : Real64 RecircMassFlowRate; // Recirculated air mass flow rate [kg/s]
3023 : Real64 OAInletTemp; // Outdoor air inlet dry bulb temperature [C]
3024 : Real64 OAInletHumRat; // Outdoor air inlet humidity ratio [kgWater/kgDryAir]
3025 : Real64 OAInletEnthalpy; // Outdoor air inlet enthalpy [J/kg]
3026 : Real64 OAAfterHtRecTemp; // Outdoor air after heat recovery to mixing box dry bulb temperature [C]
3027 : Real64 OAAfterHtRecHumRat; // Outdoor air after heat recovery to mixing box humidity ratio [kgWater/kgDryAir]
3028 : Real64 OAAfterHtRecEnthalpy; // Outdoor air after heat recovery to mixing box enthalpy [J/kg]
3029 : bool HeatRecOn;
3030 : Real64 CpAir; // Specific heat [J/kg-C] reused in multiple places
3031 :
3032 1291226 : auto &PurchAir(state.dataPurchasedAirMgr->PurchAir);
3033 :
3034 : // Initializations
3035 1291226 : OANodeNum = PurchAir(PurchAirNum).OutdoorAirNodeNum;
3036 1291226 : RecircNodeNum = PurchAir(PurchAirNum).ZoneRecircAirNodeNum;
3037 :
3038 1291226 : RecircMassFlowRate = 0.0;
3039 1291226 : RecircTemp = state.dataLoopNodes->Node(RecircNodeNum).Temp;
3040 1291226 : RecircHumRat = state.dataLoopNodes->Node(RecircNodeNum).HumRat;
3041 1291226 : RecircEnthalpy = state.dataLoopNodes->Node(RecircNodeNum).Enthalpy;
3042 1291226 : if (PurchAir(PurchAirNum).OutdoorAir) {
3043 14796 : OAInletTemp = state.dataLoopNodes->Node(OANodeNum).Temp;
3044 14796 : OAInletHumRat = state.dataLoopNodes->Node(OANodeNum).HumRat;
3045 14796 : OAInletEnthalpy = state.dataLoopNodes->Node(OANodeNum).Enthalpy;
3046 14796 : OAAfterHtRecTemp = OAInletTemp;
3047 14796 : OAAfterHtRecHumRat = OAInletHumRat;
3048 14796 : OAAfterHtRecEnthalpy = OAInletEnthalpy;
3049 : } else {
3050 1276430 : OAInletTemp = 0.0;
3051 1276430 : OAInletHumRat = 0.0;
3052 1276430 : OAInletEnthalpy = 0.0;
3053 1276430 : OAAfterHtRecTemp = OAInletTemp;
3054 1276430 : OAAfterHtRecHumRat = OAInletHumRat;
3055 1276430 : OAAfterHtRecEnthalpy = OAInletEnthalpy;
3056 : }
3057 1291226 : HeatRecOn = false;
3058 :
3059 1291226 : if (PurchAir(PurchAirNum).OutdoorAir && (OAMassFlowRate > 0.0)) {
3060 : // Determine if heat recovery is beneficial
3061 12519 : if (PurchAir(PurchAirNum).HtRecType == HeatRecovery::Sensible) {
3062 3685 : if ((OperatingMode == OpMode::Heat) && (RecircTemp > OAInletTemp)) HeatRecOn = true;
3063 3685 : if ((OperatingMode == OpMode::Cool) && (RecircTemp < OAInletTemp)) HeatRecOn = true;
3064 : }
3065 12519 : if (PurchAir(PurchAirNum).HtRecType == HeatRecovery::Enthalpy) {
3066 1436 : if ((OperatingMode == OpMode::Heat) && (RecircEnthalpy > OAInletEnthalpy)) HeatRecOn = true;
3067 1436 : if ((OperatingMode == OpMode::Cool) && (RecircEnthalpy < OAInletEnthalpy)) HeatRecOn = true;
3068 : }
3069 : // Calculate heat recovery if active
3070 12519 : if (HeatRecOn) {
3071 4474 : PurchAir(PurchAirNum).TimeHtRecActive = state.dataHVACGlobal->TimeStepSys;
3072 4474 : OAAfterHtRecTemp = OAInletTemp + PurchAir(PurchAirNum).HtRecSenEff * (RecircTemp - OAInletTemp);
3073 4474 : if (PurchAir(PurchAirNum).HtRecType == HeatRecovery::Enthalpy)
3074 1436 : OAAfterHtRecHumRat = OAInletHumRat + PurchAir(PurchAirNum).HtRecLatEff * (RecircHumRat - OAInletHumRat);
3075 4474 : OAAfterHtRecEnthalpy = PsyHFnTdbW(OAAfterHtRecTemp, OAAfterHtRecHumRat);
3076 : // Check for saturation in supply outlet and reset temp, then humidity ratio at constant enthalpy
3077 4474 : if (PsyTsatFnHPb(state, OAAfterHtRecEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName) > OAAfterHtRecTemp) {
3078 0 : OAAfterHtRecTemp = PsyTsatFnHPb(state, OAAfterHtRecEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName);
3079 0 : OAAfterHtRecHumRat = PsyWFnTdbH(state, OAAfterHtRecTemp, OAAfterHtRecEnthalpy, RoutineName);
3080 : }
3081 : }
3082 :
3083 12519 : if (SupplyMassFlowRate > OAMassFlowRate) {
3084 4918 : RecircMassFlowRate = SupplyMassFlowRate - OAMassFlowRate;
3085 4918 : MixedAirEnthalpy =
3086 4918 : (RecircMassFlowRate * state.dataLoopNodes->Node(RecircNodeNum).Enthalpy + OAMassFlowRate * OAAfterHtRecEnthalpy) / SupplyMassFlowRate;
3087 4918 : MixedAirHumRat =
3088 4918 : (RecircMassFlowRate * state.dataLoopNodes->Node(RecircNodeNum).HumRat + OAMassFlowRate * OAAfterHtRecHumRat) / SupplyMassFlowRate;
3089 : // Mixed air temperature is calculated from the mixed air enthalpy and humidity ratio.
3090 4918 : MixedAirTemp = PsyTdbFnHW(MixedAirEnthalpy, MixedAirHumRat);
3091 : } else {
3092 7601 : RecircMassFlowRate = 0.0;
3093 7601 : MixedAirEnthalpy = OAAfterHtRecEnthalpy;
3094 7601 : MixedAirHumRat = OAAfterHtRecHumRat;
3095 7601 : MixedAirTemp = OAAfterHtRecTemp;
3096 : }
3097 :
3098 : // Calculate OA and heat recovery sensible and latent rates
3099 12519 : CpAir = PsyCpAirFnW(OAInletHumRat);
3100 12519 : PurchAir(PurchAirNum).HtRecSenOutput = OAMassFlowRate * CpAir * (OAAfterHtRecTemp - OAInletTemp);
3101 12519 : PurchAir(PurchAirNum).HtRecLatOutput = OAMassFlowRate * (OAAfterHtRecEnthalpy - OAInletEnthalpy) - PurchAir(PurchAirNum).HtRecSenOutput;
3102 :
3103 : } else { // No outdoor air
3104 1278707 : RecircMassFlowRate = SupplyMassFlowRate;
3105 1278707 : MixedAirTemp = RecircTemp;
3106 1278707 : MixedAirHumRat = RecircHumRat;
3107 1278707 : MixedAirEnthalpy = RecircEnthalpy;
3108 1278707 : PurchAir(PurchAirNum).HtRecSenOutput = 0.0;
3109 1278707 : PurchAir(PurchAirNum).HtRecLatOutput = 0.0;
3110 : }
3111 1291226 : }
3112 :
3113 1291226 : void UpdatePurchasedAir(EnergyPlusData &state, int const PurchAirNum, bool const FirstHVACIteration)
3114 : {
3115 :
3116 : // SUBROUTINE INFORMATION:
3117 : // AUTHOR M. J. Witte
3118 : // DATE WRITTEN Sep 2011
3119 : // MODIFIED R. Raustad, July 2017, added return plenum
3120 : // RE-ENGINEERED na
3121 :
3122 : // PURPOSE OF THIS SUBROUTINE:
3123 : // Update node data for Ideal Loads (purchased air) system
3124 :
3125 : // USE STATEMENTS:
3126 : using ZonePlenum::SimAirZonePlenum;
3127 :
3128 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3129 : // na
3130 : bool FirstCall;
3131 : bool SupPathInletChanged;
3132 :
3133 1291226 : FirstCall = true; // just used to avoid redundant calulations
3134 1291226 : SupPathInletChanged = false; // don't care if something changes
3135 :
3136 1291226 : auto &PurchAir(state.dataPurchasedAirMgr->PurchAir);
3137 :
3138 1291226 : if (PurchAir(PurchAirNum).ReturnPlenumIndex > 0) {
3139 :
3140 : // if connected to a return plenum, set the flag that this ideal loads air system was simulated
3141 15075 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(PurchAir(PurchAirNum).ReturnPlenumIndex)
3142 15075 : .IsSimulated(PurchAir(PurchAirNum).PurchAirArrayIndex) = true;
3143 :
3144 : // if all ideal loads air systems connected to the same plenum have been simulated, simulate the zone air plenum
3145 15075 : if (all(state.dataPurchasedAirMgr->PurchAirPlenumArrays(PurchAir(PurchAirNum).ReturnPlenumIndex).IsSimulated)) {
3146 9045 : SimAirZonePlenum(state,
3147 3015 : PurchAir(PurchAirNum).ReturnPlenumName,
3148 : DataZoneEquipment::AirLoopHVACZone::ReturnPlenum,
3149 3015 : PurchAir(PurchAirNum).ReturnPlenumIndex,
3150 : FirstHVACIteration,
3151 : FirstCall,
3152 : SupPathInletChanged);
3153 : // reset this plenums flags for next iteration
3154 3015 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(PurchAir(PurchAirNum).ReturnPlenumIndex).IsSimulated = false;
3155 : }
3156 : }
3157 1291226 : }
3158 :
3159 1291226 : void ReportPurchasedAir(EnergyPlusData &state, int const PurchAirNum)
3160 : {
3161 :
3162 : // SUBROUTINE INFORMATION:
3163 : // AUTHOR Russ Taylor
3164 : // DATE WRITTEN Nov 1997
3165 : // MODIFIED na
3166 : // RE-ENGINEERED na
3167 :
3168 : // PURPOSE OF THIS SUBROUTINE:
3169 : // Calculate values of report variables, if necessary.
3170 :
3171 : // Using/Aliasing
3172 1291226 : auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
3173 :
3174 1291226 : auto &PurchAir(state.dataPurchasedAirMgr->PurchAir);
3175 :
3176 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3177 : Real64 ReportingConstant;
3178 :
3179 : // Sort out heating and cooling rates
3180 1291226 : PurchAir(PurchAirNum).SenHeatRate = max(PurchAir(PurchAirNum).SenCoilLoad, 0.0);
3181 1291226 : PurchAir(PurchAirNum).SenCoolRate = std::abs(min(PurchAir(PurchAirNum).SenCoilLoad, 0.0));
3182 1291226 : PurchAir(PurchAirNum).LatHeatRate = max(PurchAir(PurchAirNum).LatCoilLoad, 0.0);
3183 1291226 : PurchAir(PurchAirNum).LatCoolRate = std::abs(min(PurchAir(PurchAirNum).LatCoilLoad, 0.0));
3184 1291226 : PurchAir(PurchAirNum).TotHeatRate = PurchAir(PurchAirNum).SenHeatRate + PurchAir(PurchAirNum).LatHeatRate;
3185 1291226 : PurchAir(PurchAirNum).TotCoolRate = PurchAir(PurchAirNum).SenCoolRate + PurchAir(PurchAirNum).LatCoolRate;
3186 :
3187 1291226 : PurchAir(PurchAirNum).ZoneSenHeatRate = max(PurchAir(PurchAirNum).SenOutputToZone, 0.0);
3188 1291226 : PurchAir(PurchAirNum).ZoneSenCoolRate = std::abs(min(PurchAir(PurchAirNum).SenOutputToZone, 0.0));
3189 1291226 : PurchAir(PurchAirNum).ZoneLatHeatRate = max(PurchAir(PurchAirNum).LatOutputToZone, 0.0);
3190 1291226 : PurchAir(PurchAirNum).ZoneLatCoolRate = std::abs(min(PurchAir(PurchAirNum).LatOutputToZone, 0.0));
3191 1291226 : PurchAir(PurchAirNum).ZoneTotHeatRate = PurchAir(PurchAirNum).ZoneSenHeatRate + PurchAir(PurchAirNum).ZoneLatHeatRate;
3192 1291226 : PurchAir(PurchAirNum).ZoneTotCoolRate = PurchAir(PurchAirNum).ZoneSenCoolRate + PurchAir(PurchAirNum).ZoneLatCoolRate;
3193 :
3194 : // Sort out outdoor air "loads"
3195 : // OASenOutput = Outdoor air sensible output relative to zone conditions [W], <0 means OA is cooler than zone air
3196 : // OALatOutput = Outdoor air latent output relative to zone conditions [W], <0 means OA is drier than zone air
3197 1291226 : if (PurchAir(PurchAirNum).SenCoilLoad > 0.0) { // Heating is active
3198 587444 : PurchAir(PurchAirNum).OASenHeatRate = std::abs(min(PurchAir(PurchAirNum).OASenOutput, 0.0));
3199 : } else {
3200 703782 : PurchAir(PurchAirNum).OASenHeatRate = 0.0;
3201 : }
3202 1291226 : if (PurchAir(PurchAirNum).SenCoilLoad < 0.0) { // Cooling is active
3203 389109 : PurchAir(PurchAirNum).OASenCoolRate = max(PurchAir(PurchAirNum).OASenOutput, 0.0);
3204 : } else {
3205 902117 : PurchAir(PurchAirNum).OASenCoolRate = 0.0;
3206 : }
3207 1291226 : if (PurchAir(PurchAirNum).LatCoilLoad > 0.0) { // Humidification is active
3208 581987 : PurchAir(PurchAirNum).OALatHeatRate = std::abs(min(PurchAir(PurchAirNum).OALatOutput, 0.0));
3209 : } else {
3210 709239 : PurchAir(PurchAirNum).OALatHeatRate = 0.0;
3211 : }
3212 1291226 : if (PurchAir(PurchAirNum).LatCoilLoad < 0.0) { // Dehumidification is active
3213 317534 : PurchAir(PurchAirNum).OALatCoolRate = max(PurchAir(PurchAirNum).OALatOutput, 0.0);
3214 : } else {
3215 973692 : PurchAir(PurchAirNum).OALatCoolRate = 0.0;
3216 : }
3217 :
3218 1291226 : PurchAir(PurchAirNum).OATotHeatRate = PurchAir(PurchAirNum).OASenHeatRate + PurchAir(PurchAirNum).OALatHeatRate;
3219 1291226 : PurchAir(PurchAirNum).OATotCoolRate = PurchAir(PurchAirNum).OASenCoolRate + PurchAir(PurchAirNum).OALatCoolRate;
3220 :
3221 1291226 : PurchAir(PurchAirNum).HtRecSenHeatRate = max(PurchAir(PurchAirNum).HtRecSenOutput, 0.0);
3222 1291226 : PurchAir(PurchAirNum).HtRecSenCoolRate = std::abs(min(PurchAir(PurchAirNum).HtRecSenOutput, 0.0));
3223 1291226 : PurchAir(PurchAirNum).HtRecLatHeatRate = max(PurchAir(PurchAirNum).HtRecLatOutput, 0.0);
3224 1291226 : PurchAir(PurchAirNum).HtRecLatCoolRate = std::abs(min(PurchAir(PurchAirNum).HtRecLatOutput, 0.0));
3225 1291226 : PurchAir(PurchAirNum).HtRecTotHeatRate = PurchAir(PurchAirNum).HtRecSenHeatRate + PurchAir(PurchAirNum).HtRecLatHeatRate;
3226 1291226 : PurchAir(PurchAirNum).HtRecTotCoolRate = PurchAir(PurchAirNum).HtRecSenCoolRate + PurchAir(PurchAirNum).HtRecLatCoolRate;
3227 :
3228 1291226 : ReportingConstant = TimeStepSys * DataGlobalConstants::SecInHour;
3229 :
3230 1291226 : PurchAir(PurchAirNum).SenHeatEnergy = PurchAir(PurchAirNum).SenHeatRate * ReportingConstant;
3231 1291226 : PurchAir(PurchAirNum).SenCoolEnergy = PurchAir(PurchAirNum).SenCoolRate * ReportingConstant;
3232 1291226 : PurchAir(PurchAirNum).LatHeatEnergy = PurchAir(PurchAirNum).LatHeatRate * ReportingConstant;
3233 1291226 : PurchAir(PurchAirNum).LatCoolEnergy = PurchAir(PurchAirNum).LatCoolRate * ReportingConstant;
3234 1291226 : PurchAir(PurchAirNum).TotHeatEnergy = PurchAir(PurchAirNum).TotHeatRate * ReportingConstant;
3235 1291226 : PurchAir(PurchAirNum).TotCoolEnergy = PurchAir(PurchAirNum).TotCoolRate * ReportingConstant;
3236 :
3237 1291226 : PurchAir(PurchAirNum).ZoneSenHeatEnergy = PurchAir(PurchAirNum).ZoneSenHeatRate * ReportingConstant;
3238 1291226 : PurchAir(PurchAirNum).ZoneSenCoolEnergy = PurchAir(PurchAirNum).ZoneSenCoolRate * ReportingConstant;
3239 1291226 : PurchAir(PurchAirNum).ZoneLatHeatEnergy = PurchAir(PurchAirNum).ZoneLatHeatRate * ReportingConstant;
3240 1291226 : PurchAir(PurchAirNum).ZoneLatCoolEnergy = PurchAir(PurchAirNum).ZoneLatCoolRate * ReportingConstant;
3241 1291226 : PurchAir(PurchAirNum).ZoneTotHeatEnergy = PurchAir(PurchAirNum).ZoneTotHeatRate * ReportingConstant;
3242 1291226 : PurchAir(PurchAirNum).ZoneTotCoolEnergy = PurchAir(PurchAirNum).ZoneTotCoolRate * ReportingConstant;
3243 :
3244 1291226 : PurchAir(PurchAirNum).OASenHeatEnergy = PurchAir(PurchAirNum).OASenHeatRate * ReportingConstant;
3245 1291226 : PurchAir(PurchAirNum).OASenCoolEnergy = PurchAir(PurchAirNum).OASenCoolRate * ReportingConstant;
3246 1291226 : PurchAir(PurchAirNum).OALatHeatEnergy = PurchAir(PurchAirNum).OALatHeatRate * ReportingConstant;
3247 1291226 : PurchAir(PurchAirNum).OALatCoolEnergy = PurchAir(PurchAirNum).OALatCoolRate * ReportingConstant;
3248 1291226 : PurchAir(PurchAirNum).OATotHeatEnergy = PurchAir(PurchAirNum).OATotHeatRate * ReportingConstant;
3249 1291226 : PurchAir(PurchAirNum).OATotCoolEnergy = PurchAir(PurchAirNum).OATotCoolRate * ReportingConstant;
3250 :
3251 1291226 : PurchAir(PurchAirNum).HtRecSenHeatEnergy = PurchAir(PurchAirNum).HtRecSenHeatRate * ReportingConstant;
3252 1291226 : PurchAir(PurchAirNum).HtRecSenCoolEnergy = PurchAir(PurchAirNum).HtRecSenCoolRate * ReportingConstant;
3253 1291226 : PurchAir(PurchAirNum).HtRecLatHeatEnergy = PurchAir(PurchAirNum).HtRecLatHeatRate * ReportingConstant;
3254 1291226 : PurchAir(PurchAirNum).HtRecLatCoolEnergy = PurchAir(PurchAirNum).HtRecLatCoolRate * ReportingConstant;
3255 1291226 : PurchAir(PurchAirNum).HtRecTotHeatEnergy = PurchAir(PurchAirNum).HtRecTotHeatRate * ReportingConstant;
3256 1291226 : PurchAir(PurchAirNum).HtRecTotCoolEnergy = PurchAir(PurchAirNum).HtRecTotCoolRate * ReportingConstant;
3257 1291226 : }
3258 :
3259 81105 : Real64 GetPurchasedAirOutAirMassFlow(EnergyPlusData &state, int const PurchAirNum)
3260 : {
3261 :
3262 : // FUNCTION INFORMATION:
3263 : // AUTHOR B Griffith
3264 : // DATE WRITTEN Dec 2006
3265 : // MODIFIED na
3266 : // RE-ENGINEERED na
3267 :
3268 : // PURPOSE OF THIS FUNCTION:
3269 : // lookup function for OA inlet mass flow for ventilation rate reporting
3270 :
3271 : // METHODOLOGY EMPLOYED:
3272 : // most analagous functions look up an outside air node but this function
3273 : // gets the actual mass flow of outdoor air, following the features of the model
3274 :
3275 81105 : if (state.dataPurchasedAirMgr->GetPurchAirInputFlag) {
3276 0 : GetPurchasedAir(state);
3277 0 : state.dataPurchasedAirMgr->GetPurchAirInputFlag = false;
3278 : }
3279 81105 : return state.dataPurchasedAirMgr->PurchAir(PurchAirNum).OutdoorAirMassFlowRate;
3280 : }
3281 :
3282 81105 : int GetPurchasedAirZoneInletAirNode(EnergyPlusData &state, int const PurchAirNum)
3283 : {
3284 :
3285 : // FUNCTION INFORMATION:
3286 : // AUTHOR B Griffith
3287 : // DATE WRITTEN Dec 2006
3288 : // MODIFIED Adapted for purchased air by M.J. Witte, Oct 2013
3289 : // RE-ENGINEERED na
3290 :
3291 : // PURPOSE OF THIS FUNCTION:
3292 : // lookup function for zone inlet node for ventilation rate reporting
3293 :
3294 81105 : if (state.dataPurchasedAirMgr->GetPurchAirInputFlag) {
3295 0 : GetPurchasedAir(state);
3296 0 : state.dataPurchasedAirMgr->GetPurchAirInputFlag = false;
3297 : }
3298 :
3299 81105 : int GetPurchasedAirZoneInletAirNode = 0;
3300 81105 : if (PurchAirNum > 0 && PurchAirNum <= state.dataPurchasedAirMgr->NumPurchAir) {
3301 81105 : GetPurchasedAirZoneInletAirNode = state.dataPurchasedAirMgr->PurchAir(PurchAirNum).ZoneSupplyAirNodeNum;
3302 : }
3303 :
3304 81105 : return GetPurchasedAirZoneInletAirNode;
3305 : }
3306 :
3307 81105 : int GetPurchasedAirReturnAirNode(EnergyPlusData &state, int const PurchAirNum)
3308 : {
3309 :
3310 : // FUNCTION INFORMATION:
3311 : // AUTHOR B Griffith
3312 : // DATE WRITTEN Dec 2006
3313 : // MODIFIED Adapted for purchased air by M.J. Witte, Oct 2013
3314 : // RE-ENGINEERED na
3315 :
3316 : // PURPOSE OF THIS FUNCTION:
3317 : // lookup function for recirculation air node for ventilation rate reporting
3318 :
3319 81105 : if (state.dataPurchasedAirMgr->GetPurchAirInputFlag) {
3320 0 : GetPurchasedAir(state);
3321 0 : state.dataPurchasedAirMgr->GetPurchAirInputFlag = false;
3322 : }
3323 :
3324 81105 : int GetPurchasedAirReturnAirNode = 0;
3325 81105 : if (PurchAirNum > 0 && PurchAirNum <= state.dataPurchasedAirMgr->NumPurchAir) {
3326 81105 : GetPurchasedAirReturnAirNode = state.dataPurchasedAirMgr->PurchAir(PurchAirNum).ZoneRecircAirNodeNum;
3327 : }
3328 :
3329 81105 : return GetPurchasedAirReturnAirNode;
3330 : }
3331 :
3332 81105 : Real64 GetPurchasedAirMixedAirTemp(EnergyPlusData &state, int const PurchAirNum)
3333 : {
3334 :
3335 : // FUNCTION INFORMATION:
3336 : // AUTHOR B Griffith
3337 : // DATE WRITTEN Dec 2006
3338 : // MODIFIED Adapted for purchased air by M.J. Witte, Oct 2013
3339 : // RE-ENGINEERED na
3340 :
3341 : // PURPOSE OF THIS FUNCTION:
3342 : // lookup function for mixed air Temp for ventilation rate reporting
3343 :
3344 : // METHODOLOGY EMPLOYED:
3345 : // most analagous functions look up an outside air node but this function
3346 : // gets the actual mass flow of outdoor air, following the features of the model
3347 :
3348 81105 : if (state.dataPurchasedAirMgr->GetPurchAirInputFlag) {
3349 0 : GetPurchasedAir(state);
3350 0 : state.dataPurchasedAirMgr->GetPurchAirInputFlag = false;
3351 : }
3352 :
3353 81105 : return state.dataPurchasedAirMgr->PurchAir(PurchAirNum).MixedAirTemp;
3354 : }
3355 :
3356 81105 : Real64 GetPurchasedAirMixedAirHumRat(EnergyPlusData &state, int const PurchAirNum)
3357 : {
3358 :
3359 : // FUNCTION INFORMATION:
3360 : // AUTHOR B Griffith
3361 : // DATE WRITTEN Dec 2006
3362 : // MODIFIED Adapted for purchased air by M.J. Witte, Oct 2013
3363 : // RE-ENGINEERED na
3364 :
3365 : // PURPOSE OF THIS FUNCTION:
3366 : // lookup function for mixed air HumRat for ventilation rate reporting
3367 :
3368 : // METHODOLOGY EMPLOYED:
3369 : // most analogous functions look up an outside air node but this function
3370 : // gets the actual mass flow of outdoor air, following the features of the model
3371 :
3372 81105 : if (state.dataPurchasedAirMgr->GetPurchAirInputFlag) {
3373 0 : GetPurchasedAir(state);
3374 0 : state.dataPurchasedAirMgr->GetPurchAirInputFlag = false;
3375 : }
3376 :
3377 81105 : return state.dataPurchasedAirMgr->PurchAir(PurchAirNum).MixedAirHumRat;
3378 : }
3379 :
3380 281 : bool CheckPurchasedAirForReturnPlenum(EnergyPlusData &state, int const ReturnPlenumIndex)
3381 : {
3382 :
3383 : // FUNCTION INFORMATION:
3384 : // AUTHOR R Raustad
3385 : // DATE WRITTEN July 2017
3386 :
3387 : // PURPOSE OF THIS FUNCTION:
3388 : // lookup function to check if return plenum is used
3389 :
3390 : // Return value
3391 : bool CheckPurchasedAirForReturnPlenum;
3392 :
3393 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
3394 : int PurchAirNum;
3395 :
3396 281 : if (state.dataPurchasedAirMgr->GetPurchAirInputFlag) {
3397 180 : GetPurchasedAir(state);
3398 180 : state.dataPurchasedAirMgr->GetPurchAirInputFlag = false;
3399 : }
3400 :
3401 281 : CheckPurchasedAirForReturnPlenum = false;
3402 307 : for (PurchAirNum = 1; PurchAirNum <= state.dataPurchasedAirMgr->NumPurchAir; ++PurchAirNum) {
3403 26 : if (ReturnPlenumIndex != state.dataPurchasedAirMgr->PurchAir(PurchAirNum).ReturnPlenumIndex) continue;
3404 5 : CheckPurchasedAirForReturnPlenum = true;
3405 : }
3406 :
3407 281 : return CheckPurchasedAirForReturnPlenum;
3408 : }
3409 :
3410 5 : void InitializePlenumArrays(EnergyPlusData &state, int const PurchAirNum)
3411 : {
3412 : // FUNCTION INFORMATION:
3413 : // AUTHOR R Raustad
3414 : // DATE WRITTEN July 2017
3415 :
3416 : // PURPOSE OF THIS FUNCTION:
3417 : // to initialize arrays needed to manage ideal load air system used with return plenums
3418 : //
3419 : // Example:
3420 : // NumPlenumArrays = 2 (same as there are two ZoneHVAC:ReturnPlenums objects connected to two or more ideal loads air systems
3421 : // In this example ideal loads air system #4 is not connected to a zone return plenum
3422 : //
3423 : // ZoneHVAC:ReturnPlenum( 1 ) = ReturnPlenum1 is not connected to any ideal loads air systems
3424 : // ZoneHVAC:ReturnPlenum( 2 ) = ReturnPlenum2 is connected to PurchAirPlenumArrays( 1 )
3425 : // ZoneHVAC:ReturnPlenum( 3 ) = ReturnPlenum3 is connected to PurchAirPlenumArrays( 2 )
3426 : //
3427 : // PurchAirPlenumArrays( 1 )
3428 : // PurchAirPlenumArrays( 1 ).NumPurchAir = 2, there are 2 ideal loads air systems connected to this plenum
3429 : // PurchAirPlenumArrays( 1 ).PurchAirArray( 1 ) = 1, ideal loads air system #1 is attached to this plenum
3430 : // PurchAirPlenumArrays( 1 ).PurchAirArray( 2 ) = 3, ideal loads air system #3 is attached to this plenum
3431 : // PurchAirPlenumArrays( 1 ).IsSimulated( 1 ) = true, ideal loads air system #1 has been simulated this iteration
3432 : // PurchAirPlenumArrays( 1 ).IsSimulated( 2 ) = false, ideal loads air system #3 has not yet been simulated this iteration
3433 : //
3434 : // Ideal loads air sytems keep track of which plenum they are connected to
3435 : // PurchAir( 1 ).PlenumArrayIndex = 1
3436 : // PurchAir( 1 ).ReturnPlenumName = ReturnPlenum2;
3437 : // PurchAir( 3 ).PlenumArrayIndex = 1
3438 : // PurchAir( 3 ).ReturnPlenumName = ReturnPlenum2;
3439 : //
3440 : // The ideal loads air sytems also keep track of which item they are in the int and bool arrays
3441 : // PurchAir( 1 ).PurchAirArrayIndex = 1
3442 : // PurchAir( 3 ).PurchAirArrayIndex = 2
3443 : //
3444 : // PurchAirPlenumArrays( 2 )
3445 : // PurchAirPlenumArrays( 2 ).NumPurchAir = 3, there are 3 ideal loads air systems connected to this plenum
3446 : // PurchAirPlenumArrays( 2 ).PurchAirArray( 1 ) = 2, ideal loads air system #2 is attached to this plenum
3447 : // PurchAirPlenumArrays( 2 ).PurchAirArray( 2 ) = 5, ideal loads air system #5 is attached to this plenum
3448 : // PurchAirPlenumArrays( 2 ).PurchAirArray( 3 ) = 6, ideal loads air system #6 is attached to this plenum
3449 : // PurchAirPlenumArrays( 2 ).IsSimulated( 1 ) = true, ideal loads air system #4 has been simulated this iteration
3450 : // PurchAirPlenumArrays( 2 ).IsSimulated( 2 ) = false, ideal loads air system #5 has not yet been simulated this iteration
3451 : // PurchAirPlenumArrays( 2 ).IsSimulated( 3 ) = false, ideal loads air system #6 has not yet been simulated this iteration
3452 : //
3453 : // Ideal loads air sytems keep track of which plenum they are connected to
3454 : // PurchAir( 2 ).PlenumArrayIndex = 2;
3455 : // PurchAir( 2 ).ReturnPlenumName = ReturnPlenum3;
3456 : // PurchAir( 5 ).PlenumArrayIndex = 2;
3457 : // PurchAir( 5 ).ReturnPlenumName = ReturnPlenum3;
3458 : // PurchAir( 6 ).PlenumArrayIndex = 2;
3459 : // PurchAir( 6 ).ReturnPlenumName = ReturnPlenum3;
3460 : //
3461 : // The ideal loads air sytems also keep track of which item they are in the int and bool arrays
3462 : // PurchAir( 2 ).PurchAirArrayIndex = 1;
3463 : // PurchAir( 5 ).PurchAirArrayIndex = 2;
3464 : // PurchAir( 6 ).PurchAirArrayIndex = 3;
3465 : //
3466 : // Given these connections, the data in the IsSimulated array can be set (or checked) according to this syntax:
3467 : //
3468 : // Each time an ideal loads air system is simulated the IsSimulated flag is set to true
3469 : // PurchAirPlenumArrays( PurchAir( PurchNum ).PlenumArrayIndex ).IsSimulated( PurchAir( PurchNum ).PurchAirArrayIndex ) = true;
3470 : //
3471 : // if all ideal loads air systems connected to the same plenum have been simulated, simulate the zone air return plenum (once per set of
3472 : // ideal loads systems) if ( all( PurchAirPlenumArrays( PurchAir( PurchAirNum ).ReturnPlenumIndex ).IsSimulated ) ) {
3473 : // SimAirZonePlenum( PurchAir( PurchAirNum ).ReturnPlenumName, DataZoneEquipment::ZoneReturnPlenum_Type, PurchAir( PurchAirNum
3474 : // ).ReturnPlenumIndex, FirstHVACIteration, FirstCall, SupPathInletChanged ); reset all IsSimulated flags for next iteration
3475 : // PurchAirPlenumArrays( PurchAir( PurchAirNum ).ReturnPlenumIndex ).IsSimulated = false;
3476 : // }
3477 :
3478 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
3479 : int ReturnPlenumIndex; // index to ZoneHVAC:ReturnPlenum object
3480 : int ReturnPlenumNum; // loop counter
3481 : bool PlenumNotFound; // logical to determine if same plenum is used by other ideal loads air systems
3482 : int Loop; // loop counters
3483 : int Loop2; // loop counters
3484 10 : Array1D_int TempPurchArray; // temporary array used for dynamic allocation
3485 10 : Array1D_bool TempIsSimulated; // temporary array used for dynamic allocation
3486 :
3487 : // index to ZoneHVAC:ReturnPlenum object
3488 5 : ReturnPlenumIndex = state.dataPurchasedAirMgr->PurchAir(PurchAirNum).ReturnPlenumIndex;
3489 5 : PlenumNotFound = true;
3490 :
3491 : // if first time through, set up arrays
3492 5 : if (!state.dataPurchasedAirMgr->PurchAirPlenumArrays.allocated()) {
3493 :
3494 : // the ideal loads air system keeps track of which item this system is in a list
3495 1 : state.dataPurchasedAirMgr->PurchAir(PurchAirNum).PurchAirArrayIndex = 1;
3496 : // keep track of how many arrays (i.e., how many different plenums are attached to different ideal loads air systems
3497 1 : state.dataPurchasedAirMgr->NumPlenumArrays = 1;
3498 :
3499 : // allocate new array
3500 1 : state.dataPurchasedAirMgr->PurchAirPlenumArrays.allocate(state.dataPurchasedAirMgr->NumPlenumArrays);
3501 : // set counter for how many ideal loads air systems are attached to this plenum
3502 1 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(state.dataPurchasedAirMgr->NumPlenumArrays).NumPurchAir =
3503 : 1; // keeps track of how many ideal loads air system are connected to this return plenum
3504 : // keep track of which plenum this is ( i.e., PurchAirPlenumArrays(1) is ZoneHVAC:ReturnPlenum #4 )
3505 1 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(state.dataPurchasedAirMgr->NumPlenumArrays).ReturnPlenumIndex =
3506 : ReturnPlenumIndex; // stores index of return plenum (e.g., 4 of 5)
3507 : // allocate array holding index to one or more ideal loads air systems
3508 1 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(state.dataPurchasedAirMgr->NumPlenumArrays).PurchAirArray.allocate(1);
3509 : // allocate boolean to keep track of whether or not this ideal loads air system has been simulated
3510 1 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(state.dataPurchasedAirMgr->NumPlenumArrays).IsSimulated.allocate(1);
3511 : // save the data
3512 1 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(state.dataPurchasedAirMgr->NumPlenumArrays).PurchAirArray(1) = PurchAirNum;
3513 1 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(state.dataPurchasedAirMgr->NumPlenumArrays).IsSimulated(1) = false;
3514 :
3515 : } else {
3516 :
3517 : // find the correct index to PurchAirPlenumArrays
3518 4 : for (ReturnPlenumNum = 1; ReturnPlenumNum <= state.dataPurchasedAirMgr->NumPlenumArrays; ++ReturnPlenumNum) {
3519 4 : if (ReturnPlenumIndex != state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum).ReturnPlenumIndex) continue;
3520 :
3521 : // allocate temporary arrays and save existing data
3522 4 : TempPurchArray.allocate(state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum).NumPurchAir);
3523 4 : TempIsSimulated.allocate(state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum).NumPurchAir);
3524 : // these are the member arrays in an existing PurchAirPlenumArrays
3525 4 : TempPurchArray = state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum).PurchAirArray;
3526 4 : TempIsSimulated = state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum).IsSimulated;
3527 :
3528 : // if this array has been used before, we need to increase member array space to save new PurchAir data
3529 4 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum).NumPurchAir += 1;
3530 : // save the location of this ideal loads air system in the member arrays
3531 4 : state.dataPurchasedAirMgr->PurchAir(PurchAirNum).PurchAirArrayIndex =
3532 4 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum).NumPurchAir;
3533 :
3534 : // allocate more space, this will wipe out data previously stored
3535 4 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum)
3536 4 : .PurchAirArray.allocate(state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum).NumPurchAir);
3537 4 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum)
3538 4 : .IsSimulated.allocate(state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum).NumPurchAir);
3539 :
3540 : // re-initialize previous data
3541 14 : for (Loop = 1; Loop < state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum).NumPurchAir; ++Loop) {
3542 10 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum).PurchAirArray(Loop) = TempPurchArray(Loop);
3543 10 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum).IsSimulated(Loop) = TempIsSimulated(Loop);
3544 : }
3545 : // delete temporary array
3546 4 : TempPurchArray.deallocate();
3547 4 : TempIsSimulated.deallocate();
3548 :
3549 : // save new data in expanded member array
3550 4 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum)
3551 8 : .PurchAirArray(state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum).NumPurchAir) = PurchAirNum;
3552 4 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum)
3553 4 : .IsSimulated(state.dataPurchasedAirMgr->PurchAirPlenumArrays(ReturnPlenumNum).NumPurchAir) = false;
3554 :
3555 4 : PlenumNotFound = false;
3556 4 : break;
3557 : }
3558 :
3559 4 : if (PlenumNotFound) {
3560 :
3561 : // need to allocate additional space for new plenum array
3562 : // keep track of how many arrays (i.e., how many different plenums are attached to different ideal loads air systems)
3563 0 : state.dataPurchasedAirMgr->NumPlenumArrays += 1;
3564 :
3565 : // allocate temporary array and save existing data
3566 0 : state.dataPurchasedAirMgr->TempPurchAirPlenumArrays.allocate(state.dataPurchasedAirMgr->NumPlenumArrays);
3567 0 : for (Loop = 1; Loop < state.dataPurchasedAirMgr->NumPlenumArrays; ++Loop) {
3568 0 : state.dataPurchasedAirMgr->TempPurchAirPlenumArrays(Loop).NumPurchAir =
3569 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(Loop).NumPurchAir;
3570 0 : state.dataPurchasedAirMgr->TempPurchAirPlenumArrays(Loop).ReturnPlenumIndex =
3571 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(Loop).ReturnPlenumIndex;
3572 0 : state.dataPurchasedAirMgr->TempPurchAirPlenumArrays(Loop).PurchAirArray.allocate(
3573 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(Loop).NumPurchAir);
3574 0 : state.dataPurchasedAirMgr->TempPurchAirPlenumArrays(Loop).IsSimulated.allocate(
3575 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(Loop).NumPurchAir);
3576 0 : for (Loop2 = 1; Loop2 <= state.dataPurchasedAirMgr->PurchAirPlenumArrays(Loop).NumPurchAir; ++Loop2) {
3577 0 : state.dataPurchasedAirMgr->TempPurchAirPlenumArrays(Loop).PurchAirArray(Loop2) =
3578 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(Loop).PurchAirArray(Loop2);
3579 0 : state.dataPurchasedAirMgr->TempPurchAirPlenumArrays(Loop).IsSimulated(Loop2) =
3580 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(Loop).IsSimulated(Loop2);
3581 : }
3582 : }
3583 :
3584 : // delete primary array (probably could just re-allocate, but this is only done a few times per simulation)
3585 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays.deallocate();
3586 : // reallocate to new size
3587 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays.allocate(state.dataPurchasedAirMgr->NumPlenumArrays);
3588 :
3589 : // allocate member arrays to same size as before
3590 0 : for (Loop = 1; Loop < state.dataPurchasedAirMgr->NumPlenumArrays; ++Loop) {
3591 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(Loop).PurchAirArray.allocate(
3592 0 : state.dataPurchasedAirMgr->TempPurchAirPlenumArrays(Loop).NumPurchAir);
3593 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(Loop).IsSimulated.allocate(
3594 0 : state.dataPurchasedAirMgr->TempPurchAirPlenumArrays(Loop).NumPurchAir);
3595 : }
3596 :
3597 : // save the data
3598 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays = state.dataPurchasedAirMgr->TempPurchAirPlenumArrays;
3599 : // delete temporary data
3600 0 : state.dataPurchasedAirMgr->TempPurchAirPlenumArrays.deallocate();
3601 :
3602 : // save the index to where this ideal loads air system data is stored
3603 0 : state.dataPurchasedAirMgr->PurchAir(PurchAirNum).PurchAirArrayIndex = 1;
3604 : // save the number of ideal loads air systems stored in these arrays
3605 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(state.dataPurchasedAirMgr->NumPlenumArrays).NumPurchAir = 1;
3606 : // save the index the the ZoneHVAC:ReturnPlenum
3607 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(state.dataPurchasedAirMgr->NumPlenumArrays).ReturnPlenumIndex = ReturnPlenumIndex;
3608 : // allocate member array and store data
3609 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(state.dataPurchasedAirMgr->NumPlenumArrays).PurchAirArray.allocate(1);
3610 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(state.dataPurchasedAirMgr->NumPlenumArrays).PurchAirArray(1) = PurchAirNum;
3611 : // allocate member array and store data
3612 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(state.dataPurchasedAirMgr->NumPlenumArrays).IsSimulated.allocate(1);
3613 0 : state.dataPurchasedAirMgr->PurchAirPlenumArrays(state.dataPurchasedAirMgr->NumPlenumArrays).IsSimulated(1) = false;
3614 : }
3615 : }
3616 5 : }
3617 :
3618 2313 : } // namespace EnergyPlus::PurchasedAirManager
|