Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, 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 <cassert>
50 : #include <cmath>
51 :
52 : // ObjexxFCL Headers
53 : #include <ObjexxFCL/Array.functions.hh>
54 : #include <ObjexxFCL/Fmath.hh>
55 :
56 : // EnergyPlus Headers
57 : #include <EnergyPlus/Autosizing/CoolingAirFlowSizing.hh>
58 : #include <EnergyPlus/Autosizing/CoolingCapacitySizing.hh>
59 : #include <EnergyPlus/BranchNodeConnections.hh>
60 : #include <EnergyPlus/CurveManager.hh>
61 : #include <EnergyPlus/Data/EnergyPlusData.hh>
62 : #include <EnergyPlus/DataContaminantBalance.hh>
63 : #include <EnergyPlus/DataEnvironment.hh>
64 : #include <EnergyPlus/DataGlobalConstants.hh>
65 : #include <EnergyPlus/DataHVACGlobals.hh>
66 : #include <EnergyPlus/DataHeatBalFanSys.hh>
67 : #include <EnergyPlus/DataHeatBalance.hh>
68 : #include <EnergyPlus/DataIPShortCuts.hh>
69 : #include <EnergyPlus/DataLoopNode.hh>
70 : #include <EnergyPlus/DataSizing.hh>
71 : #include <EnergyPlus/DataWater.hh>
72 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
73 : #include <EnergyPlus/EMSManager.hh>
74 : #include <EnergyPlus/EvaporativeCoolers.hh>
75 : #include <EnergyPlus/Fans.hh>
76 : #include <EnergyPlus/FaultsManager.hh>
77 : #include <EnergyPlus/General.hh>
78 : #include <EnergyPlus/GeneralRoutines.hh>
79 : #include <EnergyPlus/GlobalNames.hh>
80 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
81 : #include <EnergyPlus/NodeInputManager.hh>
82 : #include <EnergyPlus/OutAirNodeManager.hh>
83 : #include <EnergyPlus/OutputProcessor.hh>
84 : #include <EnergyPlus/Psychrometrics.hh>
85 : #include <EnergyPlus/ScheduleManager.hh>
86 : #include <EnergyPlus/UtilityRoutines.hh>
87 : #include <EnergyPlus/WaterManager.hh>
88 :
89 : namespace EnergyPlus::EvaporativeCoolers {
90 : // Module containing the EvaporativeCoolers simulation routines
91 :
92 : // MODULE INFORMATION:
93 : // AUTHOR Richard J. Liesen
94 : // DATE WRITTEN Oct 2000
95 : // MODIFIED BG July 2003 ResearchSpecial Indirect
96 : // BG Febraury 2007 outside air nodes
97 : // BG March 2009 ResearchSpecial Direct
98 : // RE-ENGINEERED na
99 :
100 : // PURPOSE OF THIS MODULE:
101 : // To encapsulate the data and algorithms required for
102 : // Evaporative Coolers Components for use in mechanical air systems
103 :
104 : // provide models for evaporative coolers as zone forced air units.
105 :
106 : // METHODOLOGY EMPLOYED:
107 : // various evaporative component models in this module
108 : // different models share common module level data structure.
109 :
110 : constexpr std::array<std::string_view, static_cast<int>(EvapCoolerType::Num)> evapCoolerTypeNamesUC = {"EVAPORATIVECOOLER:DIRECT:CELDEKPAD",
111 : "EVAPORATIVECOOLER:INDIRECT:CELDEKPAD",
112 : "EVAPORATIVECOOLER:INDIRECT:WETCOIL",
113 : "EVAPORATIVECOOLER:INDIRECT:RESEARCHSPECIAL",
114 : "EVAPORATIVECOOLER:DIRECT:RESEARCHSPECIAL"};
115 : constexpr std::array<std::string_view, static_cast<int>(EvapCoolerType::Num)> evapCoolerTypeNames = {"EvaporativeCooler:Direct:CelDekPad",
116 : "EvaporativeCooler:Indirect:CelDekPad",
117 : "EvaporativeCooler:Indirect:WetCoil",
118 : "EvaporativeCooler:Indirect:ResearchSpecial",
119 : "EvaporativeCooler:Direct:ResearchSpecial"};
120 :
121 2962542 : void SimEvapCooler(EnergyPlusData &state, std::string_view CompName, int &CompIndex, Real64 const ZoneEvapCoolerPLR)
122 : {
123 :
124 : // SUBROUTINE INFORMATION:
125 : // AUTHOR Richard Liesen
126 : // DATE WRITTEN October 2000
127 :
128 : // PURPOSE OF THIS SUBROUTINE:
129 : // This subroutine manages EvapCooler component simulation.
130 : // It is called from the SimAirLoopComponent
131 : // at the system time step.
132 :
133 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
134 : int EvapCoolNum; // The EvapCooler that you are currently loading input into
135 :
136 2962542 : auto &EvapCond(state.dataEvapCoolers->EvapCond);
137 :
138 : // Obtains and Allocates EvapCooler related parameters from input file
139 2962542 : if (state.dataEvapCoolers->GetInputEvapComponentsFlag) { // First time subroutine has been entered
140 13 : GetEvapInput(state);
141 13 : state.dataEvapCoolers->GetInputEvapComponentsFlag = false;
142 : }
143 :
144 : // Find the correct EvapCoolNumber
145 2962542 : if (CompIndex == 0) {
146 51 : EvapCoolNum = Util::FindItemInList(CompName, EvapCond, &EvapConditions::Name);
147 51 : if (EvapCoolNum == 0) {
148 0 : ShowFatalError(state, format("SimEvapCooler: Unit not found={}", CompName));
149 : }
150 51 : CompIndex = EvapCoolNum;
151 : } else {
152 2962491 : EvapCoolNum = CompIndex;
153 2962491 : if (EvapCoolNum > state.dataEvapCoolers->NumEvapCool || EvapCoolNum < 1) {
154 0 : ShowFatalError(state,
155 0 : format("SimEvapCooler: Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
156 : EvapCoolNum,
157 0 : state.dataEvapCoolers->NumEvapCool,
158 : CompName));
159 : }
160 2962491 : if (state.dataEvapCoolers->CheckEquipName(EvapCoolNum)) {
161 103 : if (CompName != EvapCond(EvapCoolNum).Name) {
162 0 : ShowFatalError(state,
163 0 : format("SimEvapCooler: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
164 : EvapCoolNum,
165 : CompName,
166 0 : EvapCond(EvapCoolNum).Name));
167 : }
168 103 : state.dataEvapCoolers->CheckEquipName(EvapCoolNum) = false;
169 : }
170 : }
171 :
172 : // With the correct EvapCoolNum Initialize
173 2962542 : InitEvapCooler(state, EvapCoolNum); // Initialize all related parameters
174 :
175 2962542 : switch (EvapCond(EvapCoolNum).evapCoolerType) {
176 258218 : case EvapCoolerType::DirectCELDEKPAD: {
177 258218 : CalcDirectEvapCooler(state, EvapCoolNum, ZoneEvapCoolerPLR);
178 258218 : } break;
179 38920 : case EvapCoolerType::IndirectCELDEKPAD: {
180 38920 : CalcDryIndirectEvapCooler(state, EvapCoolNum, ZoneEvapCoolerPLR);
181 38920 : } break;
182 92337 : case EvapCoolerType::IndirectWETCOIL: {
183 92337 : CalcWetIndirectEvapCooler(state, EvapCoolNum, ZoneEvapCoolerPLR);
184 92337 : } break;
185 1156449 : case EvapCoolerType::IndirectRDDSpecial: {
186 1156449 : CalcResearchSpecialPartLoad(state, EvapCoolNum);
187 1156449 : CalcIndirectResearchSpecialEvapCooler(state, EvapCoolNum, ZoneEvapCoolerPLR);
188 1156449 : } break;
189 1416618 : case EvapCoolerType::DirectResearchSpecial: {
190 1416618 : CalcResearchSpecialPartLoad(state, EvapCoolNum);
191 1416618 : CalcDirectResearchSpecialEvapCooler(state, EvapCoolNum, ZoneEvapCoolerPLR);
192 1416618 : } break;
193 0 : default:
194 0 : break;
195 : }
196 : // Update the current Evap Cooler to the outlet nodes
197 2962542 : UpdateEvapCooler(state, EvapCoolNum);
198 :
199 : // Report the current Evap Cooler
200 2962542 : ReportEvapCooler(state, EvapCoolNum);
201 2962542 : }
202 :
203 17 : void GetEvapInput(EnergyPlusData &state)
204 : {
205 :
206 : // SUBROUTINE INFORMATION:
207 : // AUTHOR Richard J. Liesen
208 : // DATE WRITTEN Oct 2000
209 : // MODIFIED BTG, adding in EVAPCOOLER:INDIRECT:RDDSPECIAL
210 :
211 : // PURPOSE OF THIS SUBROUTINE:
212 : // This subroutine is the main routine to call other input routines and Get routines
213 :
214 : // METHODOLOGY EMPLOYED:
215 : // Uses the status flags to trigger events.
216 :
217 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
218 : int NumDirectEvapCool; // The number of Direct CelDek EvapCooler in this simulation
219 : int NumDryInDirectEvapCool; // The number of dry indirect evap coolers
220 : int NumWetInDirectEvapCool; // The number of wet indirect evap coolers
221 : int NumRDDEvapCool; // the number of special research indirect evap coolers
222 : int NumDirectResearchSpecialEvapCool; // the number of special research direct evap coolers
223 :
224 : int NumAlphas;
225 : int NumNums;
226 : int IOStat;
227 17 : bool ErrorsFound(false);
228 :
229 17 : auto &EvapCond(state.dataEvapCoolers->EvapCond);
230 17 : auto &UniqueEvapCondNames(state.dataEvapCoolers->UniqueEvapCondNames);
231 :
232 17 : state.dataEvapCoolers->GetInputEvapComponentsFlag = false;
233 : // Start getting the input data
234 17 : NumDirectEvapCool = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "EvaporativeCooler:Direct:CelDekPad");
235 17 : NumDryInDirectEvapCool = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "EvaporativeCooler:Indirect:CelDekPad");
236 17 : NumWetInDirectEvapCool = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "EvaporativeCooler:Indirect:WetCoil");
237 17 : NumRDDEvapCool = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "EvaporativeCooler:Indirect:ResearchSpecial");
238 : NumDirectResearchSpecialEvapCool =
239 17 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "EvaporativeCooler:Direct:ResearchSpecial");
240 :
241 : // Sum up all of the Evap Cooler Types
242 34 : state.dataEvapCoolers->NumEvapCool =
243 17 : NumDirectEvapCool + NumDryInDirectEvapCool + NumWetInDirectEvapCool + NumRDDEvapCool + NumDirectResearchSpecialEvapCool;
244 :
245 17 : if (state.dataEvapCoolers->NumEvapCool > 0) {
246 17 : EvapCond.allocate(state.dataEvapCoolers->NumEvapCool);
247 17 : UniqueEvapCondNames.reserve(state.dataEvapCoolers->NumEvapCool);
248 : }
249 17 : state.dataEvapCoolers->CheckEquipName.dimension(state.dataEvapCoolers->NumEvapCool, true);
250 17 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
251 17 : cCurrentModuleObject = "EvaporativeCooler:Direct:CelDekPad";
252 :
253 44 : for (int EvapCoolNum = 1; EvapCoolNum <= NumDirectEvapCool; ++EvapCoolNum) {
254 27 : auto &thisEvapCooler = EvapCond(EvapCoolNum);
255 81 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
256 : cCurrentModuleObject,
257 : EvapCoolNum,
258 27 : state.dataIPShortCut->cAlphaArgs,
259 : NumAlphas,
260 27 : state.dataIPShortCut->rNumericArgs,
261 : NumNums,
262 : IOStat,
263 : _,
264 27 : state.dataIPShortCut->lAlphaFieldBlanks,
265 27 : state.dataIPShortCut->cAlphaFieldNames,
266 27 : state.dataIPShortCut->cNumericFieldNames);
267 27 : GlobalNames::VerifyUniqueInterObjectName(state,
268 : UniqueEvapCondNames,
269 27 : state.dataIPShortCut->cAlphaArgs(1),
270 : cCurrentModuleObject,
271 27 : state.dataIPShortCut->cAlphaFieldNames(1),
272 : ErrorsFound);
273 27 : thisEvapCooler.Name = state.dataIPShortCut->cAlphaArgs(1);
274 27 : thisEvapCooler.evapCoolerType = EvapCoolerType::DirectCELDEKPAD;
275 :
276 27 : thisEvapCooler.Schedule = state.dataIPShortCut->cAlphaArgs(2);
277 27 : if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
278 0 : thisEvapCooler.SchedPtr = ScheduleManager::ScheduleAlwaysOn;
279 : } else {
280 27 : thisEvapCooler.SchedPtr = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
281 27 : if (thisEvapCooler.SchedPtr == 0) {
282 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
283 0 : ShowContinueError(state, format("Entered in {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
284 0 : ErrorsFound = true;
285 : }
286 : }
287 :
288 27 : thisEvapCooler.InletNode = GetOnlySingleNode(state,
289 27 : state.dataIPShortCut->cAlphaArgs(3),
290 : ErrorsFound,
291 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerDirectCelDekPad,
292 27 : state.dataIPShortCut->cAlphaArgs(1),
293 : DataLoopNode::NodeFluidType::Air,
294 : DataLoopNode::ConnectionType::Inlet,
295 : NodeInputManager::CompFluidStream::Primary,
296 : DataLoopNode::ObjectIsNotParent);
297 :
298 27 : thisEvapCooler.OutletNode = GetOnlySingleNode(state,
299 27 : state.dataIPShortCut->cAlphaArgs(4),
300 : ErrorsFound,
301 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerDirectCelDekPad,
302 27 : state.dataIPShortCut->cAlphaArgs(1),
303 : DataLoopNode::NodeFluidType::Air,
304 : DataLoopNode::ConnectionType::Outlet,
305 : NodeInputManager::CompFluidStream::Primary,
306 : DataLoopNode::ObjectIsNotParent);
307 :
308 54 : BranchNodeConnections::TestCompSet(state,
309 : cCurrentModuleObject,
310 27 : state.dataIPShortCut->cAlphaArgs(1),
311 27 : state.dataIPShortCut->cAlphaArgs(3),
312 27 : state.dataIPShortCut->cAlphaArgs(4),
313 : "Evap Air Nodes");
314 :
315 27 : thisEvapCooler.EvapControlType = state.dataIPShortCut->cAlphaArgs(5);
316 :
317 : // input the numerical data
318 27 : thisEvapCooler.PadArea = state.dataIPShortCut->rNumericArgs(1);
319 27 : thisEvapCooler.PadDepth = state.dataIPShortCut->rNumericArgs(2);
320 27 : thisEvapCooler.RecircPumpPower = state.dataIPShortCut->rNumericArgs(3);
321 :
322 54 : SetupOutputVariable(state,
323 : "Evaporative Cooler Wet Bulb Effectiveness",
324 : Constant::Units::None,
325 27 : thisEvapCooler.SatEff,
326 : OutputProcessor::TimeStepType::System,
327 : OutputProcessor::StoreType::Average,
328 27 : thisEvapCooler.Name);
329 :
330 : // A6 ; \Field Name of Water Supply Storage Tank
331 27 : thisEvapCooler.EvapWaterSupplyName = state.dataIPShortCut->cAlphaArgs(6);
332 27 : if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
333 27 : thisEvapCooler.EvapWaterSupplyMode = WaterSupply::FromMains;
334 : } else {
335 0 : thisEvapCooler.EvapWaterSupplyMode = WaterSupply::FromTank;
336 0 : WaterManager::SetupTankDemandComponent(state,
337 : thisEvapCooler.Name,
338 : cCurrentModuleObject,
339 : thisEvapCooler.EvapWaterSupplyName,
340 : ErrorsFound,
341 0 : thisEvapCooler.EvapWaterSupTankID,
342 0 : thisEvapCooler.EvapWaterTankDemandARRID);
343 : }
344 :
345 : } // end Number of EvapCooler Loop
346 :
347 : //**************************************************************
348 : // This is the start of the Dry Indirect Evap Cooler Loop
349 17 : cCurrentModuleObject = "EvaporativeCooler:Indirect:CelDekPad";
350 :
351 22 : for (int IndEvapCoolNum = 1; IndEvapCoolNum <= NumDryInDirectEvapCool; ++IndEvapCoolNum) {
352 5 : int EvapCoolNum = NumDirectEvapCool + IndEvapCoolNum;
353 5 : auto &thisEvapCooler = EvapCond(EvapCoolNum);
354 15 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
355 : cCurrentModuleObject,
356 : IndEvapCoolNum,
357 5 : state.dataIPShortCut->cAlphaArgs,
358 : NumAlphas,
359 5 : state.dataIPShortCut->rNumericArgs,
360 : NumNums,
361 : IOStat,
362 : _,
363 5 : state.dataIPShortCut->lAlphaFieldBlanks,
364 5 : state.dataIPShortCut->cAlphaFieldNames,
365 5 : state.dataIPShortCut->cNumericFieldNames);
366 5 : GlobalNames::VerifyUniqueInterObjectName(state,
367 : UniqueEvapCondNames,
368 5 : state.dataIPShortCut->cAlphaArgs(1),
369 : cCurrentModuleObject,
370 5 : state.dataIPShortCut->cAlphaFieldNames(1),
371 : ErrorsFound);
372 5 : thisEvapCooler.Name = state.dataIPShortCut->cAlphaArgs(1);
373 5 : thisEvapCooler.evapCoolerType = EvapCoolerType::IndirectCELDEKPAD; //'EvaporativeCooler:Indirect:CelDekPad'
374 :
375 5 : thisEvapCooler.Schedule = state.dataIPShortCut->cAlphaArgs(2);
376 5 : if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
377 0 : thisEvapCooler.SchedPtr = ScheduleManager::ScheduleAlwaysOn;
378 : } else {
379 5 : thisEvapCooler.SchedPtr = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
380 5 : if (thisEvapCooler.SchedPtr == 0) {
381 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
382 0 : ShowContinueError(state, format("Entered in {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
383 0 : ErrorsFound = true;
384 : }
385 : }
386 :
387 5 : thisEvapCooler.InletNode = GetOnlySingleNode(state,
388 5 : state.dataIPShortCut->cAlphaArgs(3),
389 : ErrorsFound,
390 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerIndirectCelDekPad,
391 5 : state.dataIPShortCut->cAlphaArgs(1),
392 : DataLoopNode::NodeFluidType::Air,
393 : DataLoopNode::ConnectionType::Inlet,
394 : NodeInputManager::CompFluidStream::Primary,
395 : DataLoopNode::ObjectIsNotParent);
396 :
397 5 : thisEvapCooler.OutletNode = GetOnlySingleNode(state,
398 5 : state.dataIPShortCut->cAlphaArgs(4),
399 : ErrorsFound,
400 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerIndirectCelDekPad,
401 5 : state.dataIPShortCut->cAlphaArgs(1),
402 : DataLoopNode::NodeFluidType::Air,
403 : DataLoopNode::ConnectionType::Outlet,
404 : NodeInputManager::CompFluidStream::Primary,
405 : DataLoopNode::ObjectIsNotParent);
406 :
407 10 : BranchNodeConnections::TestCompSet(state,
408 : cCurrentModuleObject,
409 5 : state.dataIPShortCut->cAlphaArgs(1),
410 5 : state.dataIPShortCut->cAlphaArgs(3),
411 5 : state.dataIPShortCut->cAlphaArgs(4),
412 : "Evap Air Nodes");
413 :
414 5 : thisEvapCooler.EvapControlType = state.dataIPShortCut->cAlphaArgs(5);
415 :
416 : // input the numerical data
417 5 : thisEvapCooler.IndirectPadArea = state.dataIPShortCut->rNumericArgs(1);
418 5 : thisEvapCooler.IndirectPadDepth = state.dataIPShortCut->rNumericArgs(2);
419 5 : thisEvapCooler.IndirectRecircPumpPower = state.dataIPShortCut->rNumericArgs(3);
420 5 : thisEvapCooler.IndirectVolFlowRate = state.dataIPShortCut->rNumericArgs(4);
421 5 : thisEvapCooler.IndirectFanEff = state.dataIPShortCut->rNumericArgs(5);
422 5 : thisEvapCooler.IndirectFanDeltaPress = state.dataIPShortCut->rNumericArgs(6);
423 5 : thisEvapCooler.IndirectHXEffectiveness = state.dataIPShortCut->rNumericArgs(7);
424 :
425 10 : SetupOutputVariable(state,
426 : "Evaporative Cooler Wetbulb Effectiveness",
427 : Constant::Units::None,
428 5 : thisEvapCooler.SatEff,
429 : OutputProcessor::TimeStepType::System,
430 : OutputProcessor::StoreType::Average,
431 5 : thisEvapCooler.Name);
432 10 : SetupOutputVariable(state,
433 : "Evaporative Cooler Total Stage Effectiveness",
434 : Constant::Units::None,
435 5 : thisEvapCooler.StageEff,
436 : OutputProcessor::TimeStepType::System,
437 : OutputProcessor::StoreType::Average,
438 5 : thisEvapCooler.Name);
439 :
440 : // A6 ; \Field Name of Water Supply Storage Tank
441 5 : thisEvapCooler.EvapWaterSupplyName = state.dataIPShortCut->cAlphaArgs(6);
442 5 : if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
443 5 : thisEvapCooler.EvapWaterSupplyMode = WaterSupply::FromMains;
444 : } else {
445 0 : thisEvapCooler.EvapWaterSupplyMode = WaterSupply::FromTank;
446 0 : WaterManager::SetupTankDemandComponent(state,
447 : thisEvapCooler.Name,
448 : cCurrentModuleObject,
449 : thisEvapCooler.EvapWaterSupplyName,
450 : ErrorsFound,
451 0 : thisEvapCooler.EvapWaterSupTankID,
452 0 : thisEvapCooler.EvapWaterTankDemandARRID);
453 : }
454 :
455 : // A7 ; \field Secondary Outside Air Inlet node.
456 5 : if (state.dataIPShortCut->lAlphaFieldBlanks(7)) {
457 0 : thisEvapCooler.SecondaryInletNode = 0;
458 : } else {
459 5 : thisEvapCooler.SecondaryInletNode = GetOnlySingleNode(state,
460 5 : state.dataIPShortCut->cAlphaArgs(7),
461 : ErrorsFound,
462 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerIndirectCelDekPad,
463 5 : state.dataIPShortCut->cAlphaArgs(1),
464 : DataLoopNode::NodeFluidType::Air,
465 : DataLoopNode::ConnectionType::OutsideAirReference,
466 : NodeInputManager::CompFluidStream::Primary,
467 : DataLoopNode::ObjectIsNotParent);
468 5 : if (!OutAirNodeManager::CheckOutAirNodeNumber(state, thisEvapCooler.SecondaryInletNode)) {
469 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(7), state.dataIPShortCut->cAlphaArgs(7)));
470 0 : ShowContinueError(state, format("Entered in {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
471 : // TODO rename point
472 0 : ShowContinueError(state, "Node does not appear in an OutdoorAir:NodeList or as an OutdoorAir:Node.");
473 0 : ErrorsFound = true;
474 : }
475 : }
476 :
477 : } // end Number of Dry Indirect EvapCooler Loop
478 :
479 : //**************************************************************
480 : // This is the start of the WetIndirect Evap Cooler Loop
481 17 : cCurrentModuleObject = "EvaporativeCooler:Indirect:WetCoil";
482 26 : for (int IndEvapCoolNum = 1; IndEvapCoolNum <= NumWetInDirectEvapCool; ++IndEvapCoolNum) {
483 9 : int EvapCoolNum = NumDirectEvapCool + NumDryInDirectEvapCool + IndEvapCoolNum;
484 9 : auto &thisEvapCooler = EvapCond(EvapCoolNum);
485 27 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
486 : cCurrentModuleObject,
487 : IndEvapCoolNum,
488 9 : state.dataIPShortCut->cAlphaArgs,
489 : NumAlphas,
490 9 : state.dataIPShortCut->rNumericArgs,
491 : NumNums,
492 : IOStat,
493 : _,
494 9 : state.dataIPShortCut->lAlphaFieldBlanks,
495 9 : state.dataIPShortCut->cAlphaFieldNames,
496 9 : state.dataIPShortCut->cNumericFieldNames);
497 9 : GlobalNames::VerifyUniqueInterObjectName(state,
498 : UniqueEvapCondNames,
499 9 : state.dataIPShortCut->cAlphaArgs(1),
500 : cCurrentModuleObject,
501 9 : state.dataIPShortCut->cAlphaFieldNames(1),
502 : ErrorsFound);
503 9 : thisEvapCooler.Name = state.dataIPShortCut->cAlphaArgs(1);
504 9 : thisEvapCooler.evapCoolerType = EvapCoolerType::IndirectWETCOIL; //'EvaporativeCooler:Indirect:WetCoil'
505 :
506 9 : thisEvapCooler.Schedule = state.dataIPShortCut->cAlphaArgs(2);
507 9 : if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
508 0 : thisEvapCooler.SchedPtr = ScheduleManager::ScheduleAlwaysOn;
509 : } else {
510 9 : thisEvapCooler.SchedPtr = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
511 9 : if (thisEvapCooler.SchedPtr == 0) {
512 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
513 0 : ShowContinueError(state, format("Entered in {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
514 0 : ErrorsFound = true;
515 : }
516 : }
517 :
518 9 : thisEvapCooler.InletNode = GetOnlySingleNode(state,
519 9 : state.dataIPShortCut->cAlphaArgs(3),
520 : ErrorsFound,
521 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerIndirectWetCoil,
522 9 : state.dataIPShortCut->cAlphaArgs(1),
523 : DataLoopNode::NodeFluidType::Air,
524 : DataLoopNode::ConnectionType::Inlet,
525 : NodeInputManager::CompFluidStream::Primary,
526 : DataLoopNode::ObjectIsNotParent);
527 :
528 9 : thisEvapCooler.OutletNode = GetOnlySingleNode(state,
529 9 : state.dataIPShortCut->cAlphaArgs(4),
530 : ErrorsFound,
531 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerIndirectWetCoil,
532 9 : state.dataIPShortCut->cAlphaArgs(1),
533 : DataLoopNode::NodeFluidType::Air,
534 : DataLoopNode::ConnectionType::Outlet,
535 : NodeInputManager::CompFluidStream::Primary,
536 : DataLoopNode::ObjectIsNotParent);
537 :
538 18 : BranchNodeConnections::TestCompSet(state,
539 : cCurrentModuleObject,
540 9 : state.dataIPShortCut->cAlphaArgs(1),
541 9 : state.dataIPShortCut->cAlphaArgs(3),
542 9 : state.dataIPShortCut->cAlphaArgs(4),
543 : "Evap Air Nodes");
544 :
545 9 : thisEvapCooler.EvapControlType = state.dataIPShortCut->cAlphaArgs(5);
546 :
547 : // input the numerical data
548 9 : thisEvapCooler.WetCoilMaxEfficiency = state.dataIPShortCut->rNumericArgs(1);
549 9 : thisEvapCooler.WetCoilFlowRatio = state.dataIPShortCut->rNumericArgs(2);
550 9 : thisEvapCooler.IndirectRecircPumpPower = state.dataIPShortCut->rNumericArgs(3);
551 9 : thisEvapCooler.IndirectVolFlowRate = state.dataIPShortCut->rNumericArgs(4);
552 9 : thisEvapCooler.IndirectFanEff = state.dataIPShortCut->rNumericArgs(5);
553 9 : thisEvapCooler.IndirectFanDeltaPress = state.dataIPShortCut->rNumericArgs(6);
554 :
555 18 : SetupOutputVariable(state,
556 : "Evaporative Cooler Total Stage Effectiveness",
557 : Constant::Units::None,
558 9 : thisEvapCooler.StageEff,
559 : OutputProcessor::TimeStepType::System,
560 : OutputProcessor::StoreType::Average,
561 9 : thisEvapCooler.Name);
562 :
563 : // A6 ; \Field Name of Water Supply Storage Tank
564 9 : thisEvapCooler.EvapWaterSupplyName = state.dataIPShortCut->cAlphaArgs(6);
565 9 : if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
566 9 : thisEvapCooler.EvapWaterSupplyMode = WaterSupply::FromMains;
567 : } else {
568 0 : thisEvapCooler.EvapWaterSupplyMode = WaterSupply::FromTank;
569 0 : WaterManager::SetupTankDemandComponent(state,
570 : thisEvapCooler.Name,
571 : cCurrentModuleObject,
572 : thisEvapCooler.EvapWaterSupplyName,
573 : ErrorsFound,
574 0 : thisEvapCooler.EvapWaterSupTankID,
575 0 : thisEvapCooler.EvapWaterTankDemandARRID);
576 : }
577 :
578 : // A7 ; \field Secondary Outside Air Inlet node.
579 9 : if (state.dataIPShortCut->lAlphaFieldBlanks(7)) {
580 0 : thisEvapCooler.SecondaryInletNode = 0;
581 : } else {
582 9 : thisEvapCooler.SecondaryInletNode = GetOnlySingleNode(state,
583 9 : state.dataIPShortCut->cAlphaArgs(7),
584 : ErrorsFound,
585 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerIndirectWetCoil,
586 9 : state.dataIPShortCut->cAlphaArgs(1),
587 : DataLoopNode::NodeFluidType::Air,
588 : DataLoopNode::ConnectionType::OutsideAirReference,
589 : NodeInputManager::CompFluidStream::Primary,
590 : DataLoopNode::ObjectIsNotParent);
591 9 : if (!OutAirNodeManager::CheckOutAirNodeNumber(state, thisEvapCooler.SecondaryInletNode)) {
592 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(7), state.dataIPShortCut->cAlphaArgs(7)));
593 0 : ShowContinueError(state, format("Entered in {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
594 : // TODO rename point
595 0 : ShowContinueError(state, "Node does not appear in an OutdoorAir:NodeList or as an OutdoorAir:Node.");
596 0 : ErrorsFound = true;
597 : }
598 : }
599 :
600 : } // end Number of Wet Coil Indirect EvapCooler Loop
601 : //**************************************************************
602 : // This is the start of the Indirect Research Special Evap Cooler
603 17 : cCurrentModuleObject = "EvaporativeCooler:Indirect:ResearchSpecial";
604 55 : for (int IndEvapCoolNum = 1; IndEvapCoolNum <= NumRDDEvapCool; ++IndEvapCoolNum) {
605 38 : int EvapCoolNum = NumDirectEvapCool + NumDryInDirectEvapCool + NumWetInDirectEvapCool + IndEvapCoolNum;
606 38 : auto &thisEvapCooler = EvapCond(EvapCoolNum);
607 76 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
608 : cCurrentModuleObject,
609 : IndEvapCoolNum,
610 38 : state.dataIPShortCut->cAlphaArgs,
611 : NumAlphas,
612 38 : state.dataIPShortCut->rNumericArgs,
613 : NumNums,
614 : IOStat,
615 38 : state.dataIPShortCut->lNumericFieldBlanks,
616 38 : state.dataIPShortCut->lAlphaFieldBlanks,
617 38 : state.dataIPShortCut->cAlphaFieldNames,
618 38 : state.dataIPShortCut->cNumericFieldNames);
619 38 : GlobalNames::VerifyUniqueInterObjectName(state,
620 : UniqueEvapCondNames,
621 38 : state.dataIPShortCut->cAlphaArgs(1),
622 : cCurrentModuleObject,
623 38 : state.dataIPShortCut->cAlphaFieldNames(1),
624 : ErrorsFound);
625 38 : thisEvapCooler.Name = state.dataIPShortCut->cAlphaArgs(1);
626 38 : thisEvapCooler.evapCoolerType = EvapCoolerType::IndirectRDDSpecial; //'EvaporativeCooler:Indirect:ResearchSpecial'
627 :
628 38 : thisEvapCooler.Schedule = state.dataIPShortCut->cAlphaArgs(2);
629 38 : if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
630 0 : thisEvapCooler.SchedPtr = ScheduleManager::ScheduleAlwaysOn;
631 : } else {
632 38 : thisEvapCooler.SchedPtr = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
633 38 : if (thisEvapCooler.SchedPtr == 0) {
634 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
635 0 : ShowContinueError(state, format("Entered in {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
636 0 : ErrorsFound = true;
637 : }
638 : }
639 :
640 38 : thisEvapCooler.InletNode = GetOnlySingleNode(state,
641 38 : state.dataIPShortCut->cAlphaArgs(7),
642 : ErrorsFound,
643 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerIndirectResearchSpecial,
644 38 : state.dataIPShortCut->cAlphaArgs(1),
645 : DataLoopNode::NodeFluidType::Air,
646 : DataLoopNode::ConnectionType::Inlet,
647 : NodeInputManager::CompFluidStream::Primary,
648 : DataLoopNode::ObjectIsNotParent);
649 :
650 38 : thisEvapCooler.OutletNode = GetOnlySingleNode(state,
651 38 : state.dataIPShortCut->cAlphaArgs(8),
652 : ErrorsFound,
653 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerIndirectResearchSpecial,
654 38 : state.dataIPShortCut->cAlphaArgs(1),
655 : DataLoopNode::NodeFluidType::Air,
656 : DataLoopNode::ConnectionType::Outlet,
657 : NodeInputManager::CompFluidStream::Primary,
658 : DataLoopNode::ObjectIsNotParent);
659 :
660 76 : BranchNodeConnections::TestCompSet(state,
661 : cCurrentModuleObject,
662 38 : state.dataIPShortCut->cAlphaArgs(1),
663 38 : state.dataIPShortCut->cAlphaArgs(7),
664 38 : state.dataIPShortCut->cAlphaArgs(8),
665 : "Evap Air Nodes");
666 :
667 38 : if (state.dataIPShortCut->lAlphaFieldBlanks(9)) {
668 0 : thisEvapCooler.SecondaryInletNode = 0;
669 : } else {
670 76 : thisEvapCooler.SecondaryInletNode = GetOnlySingleNode(state,
671 38 : state.dataIPShortCut->cAlphaArgs(9),
672 : ErrorsFound,
673 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerIndirectResearchSpecial,
674 38 : state.dataIPShortCut->cAlphaArgs(1),
675 : DataLoopNode::NodeFluidType::Air,
676 : DataLoopNode::ConnectionType::Inlet,
677 : NodeInputManager::CompFluidStream::Secondary,
678 : DataLoopNode::ObjectIsNotParent);
679 : }
680 :
681 38 : if (state.dataIPShortCut->lAlphaFieldBlanks(10)) {
682 0 : thisEvapCooler.SecondaryOutletNode = 0;
683 : } else {
684 76 : thisEvapCooler.SecondaryOutletNode = GetOnlySingleNode(state,
685 38 : state.dataIPShortCut->cAlphaArgs(10),
686 : ErrorsFound,
687 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerIndirectResearchSpecial,
688 38 : state.dataIPShortCut->cAlphaArgs(1),
689 : DataLoopNode::NodeFluidType::Air,
690 : DataLoopNode::ConnectionType::Outlet,
691 : NodeInputManager::CompFluidStream::Secondary,
692 : DataLoopNode::ObjectIsNotParent);
693 : }
694 :
695 38 : thisEvapCooler.EvapControlNodeNum = GetOnlySingleNode(state,
696 38 : state.dataIPShortCut->cAlphaArgs(11),
697 : ErrorsFound,
698 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerIndirectResearchSpecial,
699 38 : state.dataIPShortCut->cAlphaArgs(1),
700 : DataLoopNode::NodeFluidType::Air,
701 : DataLoopNode::ConnectionType::Sensor,
702 : NodeInputManager::CompFluidStream::Primary,
703 : DataLoopNode::ObjectIsNotParent);
704 :
705 38 : thisEvapCooler.TertiaryInletNode = GetOnlySingleNode(state,
706 38 : state.dataIPShortCut->cAlphaArgs(12),
707 : ErrorsFound,
708 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerIndirectResearchSpecial,
709 38 : state.dataIPShortCut->cAlphaArgs(1),
710 : DataLoopNode::NodeFluidType::Air,
711 : DataLoopNode::ConnectionType::Inlet,
712 : NodeInputManager::CompFluidStream::Tertiary,
713 : DataLoopNode::ObjectIsNotParent);
714 :
715 38 : thisEvapCooler.EvapWaterSupplyName = state.dataIPShortCut->cAlphaArgs(13);
716 38 : if (state.dataIPShortCut->lAlphaFieldBlanks(13)) {
717 38 : thisEvapCooler.EvapWaterSupplyMode = WaterSupply::FromMains;
718 : } else {
719 0 : thisEvapCooler.EvapWaterSupplyMode = WaterSupply::FromTank;
720 0 : WaterManager::SetupTankDemandComponent(state,
721 : thisEvapCooler.Name,
722 : cCurrentModuleObject,
723 : thisEvapCooler.EvapWaterSupplyName,
724 : ErrorsFound,
725 0 : thisEvapCooler.EvapWaterSupTankID,
726 0 : thisEvapCooler.EvapWaterTankDemandARRID);
727 : }
728 :
729 : // input the numerical data
730 38 : thisEvapCooler.WetCoilMaxEfficiency = state.dataIPShortCut->rNumericArgs(1);
731 38 : if (state.dataIPShortCut->lNumericFieldBlanks(2)) {
732 34 : thisEvapCooler.DryCoilMaxEfficiency = 0.0;
733 : } else {
734 4 : thisEvapCooler.DryCoilMaxEfficiency = state.dataIPShortCut->rNumericArgs(2);
735 : }
736 38 : thisEvapCooler.IndirectRecircPumpPower = state.dataIPShortCut->rNumericArgs(3);
737 38 : thisEvapCooler.RecircPumpSizingFactor = state.dataIPShortCut->rNumericArgs(4);
738 38 : thisEvapCooler.IndirectVolFlowRate = state.dataIPShortCut->rNumericArgs(5);
739 38 : thisEvapCooler.IndirectVolFlowScalingFactor = state.dataIPShortCut->rNumericArgs(6);
740 38 : thisEvapCooler.IndirectFanPower = state.dataIPShortCut->rNumericArgs(7);
741 38 : thisEvapCooler.FanSizingSpecificPower = state.dataIPShortCut->rNumericArgs(8);
742 38 : thisEvapCooler.DesVolFlowRate = state.dataIPShortCut->rNumericArgs(9);
743 38 : thisEvapCooler.DPBoundFactor = state.dataIPShortCut->rNumericArgs(10);
744 38 : if (state.dataIPShortCut->lNumericFieldBlanks(11)) {
745 24 : thisEvapCooler.DriftFraction = 0.0;
746 : } else {
747 14 : thisEvapCooler.DriftFraction = state.dataIPShortCut->rNumericArgs(11);
748 : }
749 38 : if (state.dataIPShortCut->lNumericFieldBlanks(12)) {
750 28 : thisEvapCooler.BlowDownRatio = 0.0;
751 : } else {
752 10 : thisEvapCooler.BlowDownRatio = state.dataIPShortCut->rNumericArgs(12);
753 : }
754 42 : if (state.dataIPShortCut->lNumericFieldBlanks(2) || state.dataIPShortCut->lNumericFieldBlanks(13) ||
755 42 : state.dataIPShortCut->lNumericFieldBlanks(14) || state.dataIPShortCut->lNumericFieldBlanks(15)) {
756 34 : thisEvapCooler.EvapCoolerOperationControlFlag = false;
757 : } else {
758 8 : if (!state.dataIPShortCut->lNumericFieldBlanks(2) && !state.dataIPShortCut->lNumericFieldBlanks(13) &&
759 8 : !state.dataIPShortCut->lNumericFieldBlanks(14) && !state.dataIPShortCut->lNumericFieldBlanks(15)) {
760 4 : thisEvapCooler.EvapCoolerOperationControlFlag = true;
761 4 : thisEvapCooler.MinOATDBEvapCooler = state.dataIPShortCut->rNumericArgs(13);
762 4 : thisEvapCooler.MaxOATWBEvapCooler = state.dataIPShortCut->rNumericArgs(14);
763 4 : thisEvapCooler.MaxOATDBEvapCooler = state.dataIPShortCut->rNumericArgs(15);
764 : } else {
765 0 : thisEvapCooler.EvapCoolerOperationControlFlag = false;
766 : }
767 : }
768 38 : thisEvapCooler.WetbulbEffecCurveIndex = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(3));
769 38 : thisEvapCooler.DrybulbEffecCurveIndex = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(4));
770 38 : thisEvapCooler.PumpPowerModifierCurveIndex = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(5));
771 38 : thisEvapCooler.FanPowerModifierCurveIndex = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(6));
772 :
773 76 : SetupOutputVariable(state,
774 : "Evaporative Cooler Total Stage Effectiveness",
775 : Constant::Units::None,
776 38 : thisEvapCooler.StageEff,
777 : OutputProcessor::TimeStepType::System,
778 : OutputProcessor::StoreType::Average,
779 38 : thisEvapCooler.Name);
780 76 : SetupOutputVariable(state,
781 : "Evaporative Cooler Part Load Ratio",
782 : Constant::Units::None,
783 38 : thisEvapCooler.PartLoadFract,
784 : OutputProcessor::TimeStepType::System,
785 : OutputProcessor::StoreType::Average,
786 38 : thisEvapCooler.Name);
787 :
788 38 : SetupOutputVariable(state,
789 : "Evaporative Cooler Dewpoint Bound Status",
790 : Constant::Units::None,
791 38 : thisEvapCooler.DewPointBoundFlag,
792 : OutputProcessor::TimeStepType::System,
793 : OutputProcessor::StoreType::Average,
794 38 : thisEvapCooler.Name);
795 38 : SetupOutputVariable(state,
796 : "Evaporative Cooler Operating Mode Status",
797 : Constant::Units::None,
798 38 : thisEvapCooler.IECOperatingStatus,
799 : OutputProcessor::TimeStepType::System,
800 : OutputProcessor::StoreType::Average,
801 38 : thisEvapCooler.Name);
802 :
803 : } // end of Indirect Research Special cooler input loop
804 :
805 17 : cCurrentModuleObject = "EvaporativeCooler:Direct:ResearchSpecial";
806 41 : for (int DirectEvapCoolNum = 1; DirectEvapCoolNum <= NumDirectResearchSpecialEvapCool; ++DirectEvapCoolNum) {
807 24 : int EvapCoolNum = NumDirectEvapCool + NumDryInDirectEvapCool + NumWetInDirectEvapCool + NumRDDEvapCool + DirectEvapCoolNum;
808 24 : auto &thisEvapCooler = EvapCond(EvapCoolNum);
809 48 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
810 : cCurrentModuleObject,
811 : DirectEvapCoolNum,
812 24 : state.dataIPShortCut->cAlphaArgs,
813 : NumAlphas,
814 24 : state.dataIPShortCut->rNumericArgs,
815 : NumNums,
816 : IOStat,
817 24 : state.dataIPShortCut->lNumericFieldBlanks,
818 24 : state.dataIPShortCut->lAlphaFieldBlanks,
819 24 : state.dataIPShortCut->cAlphaFieldNames,
820 24 : state.dataIPShortCut->cNumericFieldNames);
821 24 : GlobalNames::VerifyUniqueInterObjectName(state,
822 : UniqueEvapCondNames,
823 24 : state.dataIPShortCut->cAlphaArgs(1),
824 : cCurrentModuleObject,
825 24 : state.dataIPShortCut->cAlphaFieldNames(1),
826 : ErrorsFound);
827 24 : thisEvapCooler.Name = state.dataIPShortCut->cAlphaArgs(1);
828 24 : thisEvapCooler.evapCoolerType = EvapCoolerType::DirectResearchSpecial;
829 :
830 24 : thisEvapCooler.Schedule = state.dataIPShortCut->cAlphaArgs(2);
831 24 : if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
832 0 : thisEvapCooler.SchedPtr = ScheduleManager::ScheduleAlwaysOn;
833 : } else {
834 24 : thisEvapCooler.SchedPtr = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
835 24 : if (thisEvapCooler.SchedPtr == 0) {
836 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
837 0 : ShowContinueError(state, format("Entered in {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
838 0 : ErrorsFound = true;
839 : }
840 : }
841 :
842 24 : thisEvapCooler.InletNode = GetOnlySingleNode(state,
843 24 : state.dataIPShortCut->cAlphaArgs(5),
844 : ErrorsFound,
845 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerDirectResearchSpecial,
846 24 : state.dataIPShortCut->cAlphaArgs(1),
847 : DataLoopNode::NodeFluidType::Air,
848 : DataLoopNode::ConnectionType::Inlet,
849 : NodeInputManager::CompFluidStream::Primary,
850 : DataLoopNode::ObjectIsNotParent);
851 :
852 24 : thisEvapCooler.OutletNode = GetOnlySingleNode(state,
853 24 : state.dataIPShortCut->cAlphaArgs(6),
854 : ErrorsFound,
855 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerDirectResearchSpecial,
856 24 : state.dataIPShortCut->cAlphaArgs(1),
857 : DataLoopNode::NodeFluidType::Air,
858 : DataLoopNode::ConnectionType::Outlet,
859 : NodeInputManager::CompFluidStream::Primary,
860 : DataLoopNode::ObjectIsNotParent);
861 :
862 48 : BranchNodeConnections::TestCompSet(state,
863 : cCurrentModuleObject,
864 24 : state.dataIPShortCut->cAlphaArgs(1),
865 24 : state.dataIPShortCut->cAlphaArgs(5),
866 24 : state.dataIPShortCut->cAlphaArgs(6),
867 : "Evap Air Nodes");
868 :
869 24 : thisEvapCooler.EvapControlNodeNum = GetOnlySingleNode(state,
870 24 : state.dataIPShortCut->cAlphaArgs(7),
871 : ErrorsFound,
872 : DataLoopNode::ConnectionObjectType::EvaporativeCoolerDirectResearchSpecial,
873 24 : state.dataIPShortCut->cAlphaArgs(1),
874 : DataLoopNode::NodeFluidType::Air,
875 : DataLoopNode::ConnectionType::Sensor,
876 : NodeInputManager::CompFluidStream::Primary,
877 : DataLoopNode::ObjectIsNotParent);
878 :
879 24 : thisEvapCooler.EvapWaterSupplyName = state.dataIPShortCut->cAlphaArgs(8);
880 :
881 24 : if (state.dataIPShortCut->lAlphaFieldBlanks(8)) {
882 24 : thisEvapCooler.EvapWaterSupplyMode = WaterSupply::FromMains;
883 : } else {
884 0 : thisEvapCooler.EvapWaterSupplyMode = WaterSupply::FromTank;
885 0 : WaterManager::SetupTankDemandComponent(state,
886 : thisEvapCooler.Name,
887 : cCurrentModuleObject,
888 : thisEvapCooler.EvapWaterSupplyName,
889 : ErrorsFound,
890 0 : thisEvapCooler.EvapWaterSupTankID,
891 0 : thisEvapCooler.EvapWaterTankDemandARRID);
892 : }
893 24 : thisEvapCooler.DirectEffectiveness = state.dataIPShortCut->rNumericArgs(1);
894 :
895 24 : thisEvapCooler.DesVolFlowRate = state.dataIPShortCut->rNumericArgs(2);
896 24 : thisEvapCooler.RecircPumpPower = state.dataIPShortCut->rNumericArgs(3);
897 24 : thisEvapCooler.RecircPumpSizingFactor = state.dataIPShortCut->rNumericArgs(4);
898 24 : if (state.dataIPShortCut->lNumericFieldBlanks(5)) {
899 0 : thisEvapCooler.DriftFraction = 0.0;
900 : } else {
901 24 : thisEvapCooler.DriftFraction = state.dataIPShortCut->rNumericArgs(5);
902 : }
903 24 : if (state.dataIPShortCut->lNumericFieldBlanks(6)) {
904 0 : thisEvapCooler.BlowDownRatio = 0.0;
905 : } else {
906 24 : thisEvapCooler.BlowDownRatio = state.dataIPShortCut->rNumericArgs(6);
907 : }
908 28 : if (state.dataIPShortCut->lNumericFieldBlanks(7) || state.dataIPShortCut->lNumericFieldBlanks(8) ||
909 4 : state.dataIPShortCut->lNumericFieldBlanks(9)) {
910 20 : thisEvapCooler.EvapCoolerOperationControlFlag = false;
911 : } else {
912 8 : if (!state.dataIPShortCut->lNumericFieldBlanks(7) && !state.dataIPShortCut->lNumericFieldBlanks(8) &&
913 4 : !state.dataIPShortCut->lNumericFieldBlanks(9)) {
914 4 : thisEvapCooler.EvapCoolerOperationControlFlag = true;
915 4 : thisEvapCooler.MinOATDBEvapCooler = state.dataIPShortCut->rNumericArgs(7);
916 4 : thisEvapCooler.MaxOATWBEvapCooler = state.dataIPShortCut->rNumericArgs(8);
917 4 : thisEvapCooler.MaxOATDBEvapCooler = state.dataIPShortCut->rNumericArgs(9);
918 : } else {
919 0 : thisEvapCooler.EvapCoolerOperationControlFlag = false;
920 : }
921 : }
922 24 : thisEvapCooler.WetbulbEffecCurveIndex = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(3));
923 24 : thisEvapCooler.PumpPowerModifierCurveIndex = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(4));
924 :
925 48 : SetupOutputVariable(state,
926 : "Evaporative Cooler Stage Effectiveness",
927 : Constant::Units::None,
928 24 : thisEvapCooler.StageEff,
929 : OutputProcessor::TimeStepType::System,
930 : OutputProcessor::StoreType::Average,
931 24 : thisEvapCooler.Name);
932 : }
933 :
934 17 : if (ErrorsFound) {
935 0 : ShowFatalError(state, "Errors found in processing input for evaporative coolers");
936 : }
937 :
938 120 : for (int EvapCoolNum = 1; EvapCoolNum <= state.dataEvapCoolers->NumEvapCool; ++EvapCoolNum) {
939 103 : auto &thisEvapCooler = EvapCond(EvapCoolNum);
940 : // Setup Report variables for the Evap Coolers
941 206 : SetupOutputVariable(state,
942 : "Evaporative Cooler Electricity Energy",
943 : Constant::Units::J,
944 103 : thisEvapCooler.EvapCoolerEnergy,
945 : OutputProcessor::TimeStepType::System,
946 : OutputProcessor::StoreType::Sum,
947 103 : thisEvapCooler.Name,
948 : Constant::eResource::Electricity,
949 : OutputProcessor::Group::HVAC,
950 : OutputProcessor::EndUseCat::Cooling);
951 206 : SetupOutputVariable(state,
952 : "Evaporative Cooler Electricity Rate",
953 : Constant::Units::W,
954 103 : thisEvapCooler.EvapCoolerPower,
955 : OutputProcessor::TimeStepType::System,
956 : OutputProcessor::StoreType::Average,
957 103 : thisEvapCooler.Name);
958 : // this next report variable is setup differently depending on how the water should be metered here.
959 103 : if (thisEvapCooler.EvapWaterSupplyMode == WaterSupply::FromMains) {
960 206 : SetupOutputVariable(state,
961 : "Evaporative Cooler Water Volume",
962 : Constant::Units::m3,
963 103 : thisEvapCooler.EvapWaterConsump,
964 : OutputProcessor::TimeStepType::System,
965 : OutputProcessor::StoreType::Sum,
966 103 : thisEvapCooler.Name,
967 : Constant::eResource::Water,
968 : OutputProcessor::Group::HVAC,
969 : OutputProcessor::EndUseCat::Cooling);
970 206 : SetupOutputVariable(state,
971 : "Evaporative Cooler Mains Water Volume",
972 : Constant::Units::m3,
973 103 : thisEvapCooler.EvapWaterConsump,
974 : OutputProcessor::TimeStepType::System,
975 : OutputProcessor::StoreType::Sum,
976 103 : thisEvapCooler.Name,
977 : Constant::eResource::MainsWater,
978 : OutputProcessor::Group::HVAC,
979 : OutputProcessor::EndUseCat::Cooling);
980 :
981 0 : } else if (thisEvapCooler.EvapWaterSupplyMode == WaterSupply::FromTank) {
982 0 : SetupOutputVariable(state,
983 : "Evaporative Cooler Storage Tank Water Volume",
984 : Constant::Units::m3,
985 0 : thisEvapCooler.EvapWaterConsump,
986 : OutputProcessor::TimeStepType::System,
987 : OutputProcessor::StoreType::Sum,
988 0 : thisEvapCooler.Name,
989 : Constant::eResource::Water,
990 : OutputProcessor::Group::HVAC,
991 : OutputProcessor::EndUseCat::Cooling);
992 0 : SetupOutputVariable(state,
993 : "Evaporative Cooler Starved Water Volume",
994 : Constant::Units::m3,
995 0 : thisEvapCooler.EvapWaterStarvMakup,
996 : OutputProcessor::TimeStepType::System,
997 : OutputProcessor::StoreType::Sum,
998 0 : thisEvapCooler.Name,
999 : Constant::eResource::Water,
1000 : OutputProcessor::Group::HVAC,
1001 : OutputProcessor::EndUseCat::Cooling);
1002 0 : SetupOutputVariable(state,
1003 : "Evaporative Cooler Starved Mains Water Volume",
1004 : Constant::Units::m3,
1005 0 : thisEvapCooler.EvapWaterStarvMakup,
1006 : OutputProcessor::TimeStepType::System,
1007 : OutputProcessor::StoreType::Sum,
1008 0 : thisEvapCooler.Name,
1009 : Constant::eResource::MainsWater,
1010 : OutputProcessor::Group::HVAC,
1011 : OutputProcessor::EndUseCat::Cooling);
1012 : }
1013 : }
1014 17 : }
1015 :
1016 5303237 : void InitEvapCooler(EnergyPlusData &state, int const EvapCoolNum)
1017 : {
1018 :
1019 : // SUBROUTINE INFORMATION:
1020 : // AUTHOR Richard J. Liesen
1021 : // DATE WRITTEN October 2000
1022 : // MODIFIED B. Griffith, May 2009, added EMS setpoint check
1023 :
1024 : // PURPOSE OF THIS SUBROUTINE:
1025 : // This subroutine is for initializations of the EvapCooler Components.
1026 :
1027 : // METHODOLOGY EMPLOYED:
1028 : // Uses the status flags to trigger events.
1029 :
1030 : // Using/Aliasing
1031 5303237 : auto &evapCond = state.dataEvapCoolers->EvapCond(EvapCoolNum);
1032 :
1033 : // Check that setpoint is active
1034 5303237 : if (!state.dataGlobal->SysSizingCalc && state.dataEvapCoolers->MySetPointCheckFlag && state.dataHVACGlobal->DoSetPointTest) {
1035 120 : for (int EvapUnitNum = 1; EvapUnitNum <= state.dataEvapCoolers->NumEvapCool; ++EvapUnitNum) {
1036 :
1037 : // only check evap coolers that are supposed to have a control node
1038 103 : if ((evapCond.evapCoolerType != EvapCoolerType::IndirectRDDSpecial) && (evapCond.evapCoolerType != EvapCoolerType::DirectResearchSpecial))
1039 61 : continue;
1040 :
1041 42 : int ControlNode = state.dataEvapCoolers->EvapCond(EvapUnitNum).EvapControlNodeNum;
1042 42 : if (ControlNode > 0) {
1043 42 : if (state.dataLoopNodes->Node(ControlNode).TempSetPoint == DataLoopNode::SensedNodeFlagValue) {
1044 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
1045 0 : ShowSevereError(state, format("Missing temperature setpoint for Evap Cooler unit {}", evapCond.Name));
1046 0 : ShowContinueError(state, " use a Setpoint Manager to establish a setpoint at the unit control node.");
1047 : } else {
1048 0 : bool localSetPointCheck = false;
1049 0 : EMSManager::CheckIfNodeSetPointManagedByEMS(state, ControlNode, HVAC::CtrlVarType::Temp, localSetPointCheck);
1050 0 : state.dataLoopNodes->NodeSetpointCheck(ControlNode).needsSetpointChecking = false;
1051 : // Let it slide apparently
1052 0 : if (localSetPointCheck) {
1053 0 : ShowSevereError(state, format("Missing temperature setpoint for Evap Cooler unit {}", evapCond.Name));
1054 0 : ShowContinueError(state, " use a Setpoint Manager to establish a setpoint at the unit control node.");
1055 0 : ShowContinueError(state, " or use an EMS actuator to establish a setpoint at the unit control node.");
1056 : }
1057 : }
1058 : }
1059 : }
1060 : }
1061 17 : state.dataEvapCoolers->MySetPointCheckFlag = false;
1062 : }
1063 :
1064 5303237 : if (!state.dataGlobal->SysSizingCalc && evapCond.MySizeFlag) {
1065 : // for each cooler, do the sizing once.
1066 103 : SizeEvapCooler(state, EvapCoolNum);
1067 103 : evapCond.MySizeFlag = false;
1068 : }
1069 :
1070 : // Do the following initializations (every time step): This should be the info from
1071 : // the previous components outlets or the node data in this section.
1072 :
1073 : // Transfer the node data to EvapCond data structure
1074 5303237 : auto &thisInletNode = state.dataLoopNodes->Node(evapCond.InletNode);
1075 :
1076 5303237 : Real64 const RhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisInletNode.Temp, thisInletNode.HumRat);
1077 :
1078 : // set the volume flow rates from the input mass flow rates
1079 5303237 : evapCond.VolFlowRate = thisInletNode.MassFlowRate / RhoAir;
1080 :
1081 : // Calculate the entering wet bulb temperature for inlet conditions
1082 5303237 : evapCond.InletWetBulbTemp = Psychrometrics::PsyTwbFnTdbWPb(state, thisInletNode.Temp, thisInletNode.HumRat, state.dataEnvrn->OutBaroPress);
1083 :
1084 : // Set all of the inlet mass flow variables from the nodes
1085 5303237 : evapCond.InletMassFlowRate = thisInletNode.MassFlowRate;
1086 5303237 : evapCond.InletMassFlowRateMaxAvail = thisInletNode.MassFlowRateMaxAvail;
1087 5303237 : evapCond.InletMassFlowRateMinAvail = thisInletNode.MassFlowRateMinAvail;
1088 : // Set all of the inlet state variables from the inlet nodes
1089 5303237 : evapCond.InletTemp = thisInletNode.Temp;
1090 5303237 : evapCond.InletHumRat = thisInletNode.HumRat;
1091 5303237 : evapCond.InletEnthalpy = thisInletNode.Enthalpy;
1092 5303237 : evapCond.InletPressure = thisInletNode.Press;
1093 : // Set default outlet state to inlet states(?)
1094 5303237 : evapCond.OutletTemp = evapCond.InletTemp;
1095 5303237 : evapCond.OutletHumRat = evapCond.InletHumRat;
1096 5303237 : evapCond.OutletEnthalpy = evapCond.InletEnthalpy;
1097 5303237 : evapCond.OutletPressure = evapCond.InletPressure;
1098 :
1099 5303237 : evapCond.OutletMassFlowRate = evapCond.InletMassFlowRate;
1100 5303237 : evapCond.OutletMassFlowRateMaxAvail = evapCond.InletMassFlowRateMaxAvail;
1101 5303237 : evapCond.OutletMassFlowRateMinAvail = evapCond.InletMassFlowRateMinAvail;
1102 :
1103 : // Set all of the secondary inlet mass flow variables from the nodes
1104 5303237 : if (evapCond.SecondaryInletNode != 0) {
1105 2322163 : auto const &thisSecInletNode = state.dataLoopNodes->Node(evapCond.SecondaryInletNode);
1106 2322163 : evapCond.SecInletMassFlowRate = thisSecInletNode.MassFlowRate;
1107 2322163 : evapCond.SecInletMassFlowRateMaxAvail = thisSecInletNode.MassFlowRateMaxAvail;
1108 2322163 : evapCond.SecInletMassFlowRateMinAvail = thisSecInletNode.MassFlowRateMinAvail;
1109 2322163 : evapCond.SecInletTemp = thisSecInletNode.Temp;
1110 2322163 : evapCond.SecInletHumRat = thisSecInletNode.HumRat;
1111 2322163 : evapCond.SecInletEnthalpy = thisSecInletNode.Enthalpy;
1112 2322163 : evapCond.SecInletPressure = thisSecInletNode.Press;
1113 : } else {
1114 2981074 : evapCond.SecInletMassFlowRate = evapCond.IndirectVolFlowRate * state.dataEnvrn->OutAirDensity;
1115 2981074 : evapCond.SecInletMassFlowRateMaxAvail = evapCond.IndirectVolFlowRate * state.dataEnvrn->OutAirDensity;
1116 2981074 : evapCond.SecInletMassFlowRateMinAvail = 0.0;
1117 2981074 : evapCond.SecInletTemp = state.dataEnvrn->OutDryBulbTemp;
1118 2981074 : evapCond.SecInletHumRat =
1119 2981074 : Psychrometrics::PsyWFnTdbTwbPb(state, state.dataEnvrn->OutDryBulbTemp, state.dataEnvrn->OutWetBulbTemp, state.dataEnvrn->OutBaroPress);
1120 2981074 : evapCond.SecInletEnthalpy = state.dataEnvrn->OutEnthalpy;
1121 2981074 : evapCond.SecInletPressure = state.dataEnvrn->OutBaroPress;
1122 : }
1123 : // Set the energy consumption to zero each time through for reporting
1124 5303237 : evapCond.EvapCoolerEnergy = 0.0;
1125 5303237 : evapCond.EvapCoolerPower = 0.0;
1126 5303237 : evapCond.DewPointBoundFlag = 0;
1127 : // Set the water consumption to zero each time through for reporting
1128 5303237 : evapCond.EvapWaterConsumpRate = 0.0;
1129 5303237 : evapCond.EvapWaterConsump = 0.0;
1130 5303237 : evapCond.EvapWaterStarvMakup = 0.0;
1131 :
1132 : // Set the Saturation and Stage Efficiency to zero each time through for reporting
1133 5303237 : evapCond.StageEff = 0.0;
1134 5303237 : evapCond.SatEff = 0.0;
1135 :
1136 : // These initializations are done every iteration
1137 5303237 : int OutNode = evapCond.OutletNode;
1138 5303237 : int ControlNode = evapCond.EvapControlNodeNum;
1139 5303237 : evapCond.IECOperatingStatus = 0;
1140 :
1141 5303237 : if (ControlNode == 0) {
1142 389475 : evapCond.DesiredOutletTemp = 0.0;
1143 4913762 : } else if (ControlNode == OutNode) {
1144 2810418 : evapCond.DesiredOutletTemp = state.dataLoopNodes->Node(ControlNode).TempSetPoint;
1145 : } else {
1146 2103344 : evapCond.DesiredOutletTemp = state.dataLoopNodes->Node(ControlNode).TempSetPoint -
1147 2103344 : (state.dataLoopNodes->Node(ControlNode).Temp - state.dataLoopNodes->Node(OutNode).Temp);
1148 : }
1149 5303237 : }
1150 :
1151 103 : void SizeEvapCooler(EnergyPlusData &state, int const EvapCoolNum)
1152 : {
1153 :
1154 : // SUBROUTINE INFORMATION:
1155 : // AUTHOR B. Griffith
1156 : // DATE WRITTEN March 2009
1157 : // MODIFIED March 2014 Daeho Kang, Add sizing additional fields
1158 :
1159 : // PURPOSE OF THIS SUBROUTINE:
1160 : // Size calculations for Evap coolers
1161 : // currently just for secondary side of Research Special Indirect evap cooler
1162 :
1163 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1164 : bool IsAutoSize; // Indicator to autosize
1165 :
1166 : Real64 volFlowRateDes; // Autosized volume flow rate for reporting
1167 103 : std::string CompType; // for ease in getting objects
1168 :
1169 : // inits
1170 103 : bool CoolerOnOApath = false;
1171 103 : bool CoolerOnMainAirLoop = false;
1172 103 : Real64 IndirectVolFlowRateDes = 0.0; // Autosized volume flow rate for reporting
1173 103 : Real64 IndirectVolFlowRateUser = 0.0; // Hardsized volume flow rate for reporting
1174 103 : Real64 PadAreaDes = 0.0; // Autosized celdek pad area for reporting
1175 103 : Real64 PadAreaUser = 0.0; // Hardsized celdek pad area for reporting
1176 103 : Real64 PadDepthDes = 0.0; // Autosized celdek pad depth for reporting
1177 103 : Real64 PadDepthUser = 0.0; // Hardsized celdek pad depth for reporting
1178 :
1179 103 : auto &CurSysNum(state.dataSize->CurSysNum);
1180 103 : auto &CurZoneEqNum(state.dataSize->CurZoneEqNum);
1181 103 : auto &FinalSysSizing(state.dataSize->FinalSysSizing);
1182 103 : auto &EvapCond(state.dataEvapCoolers->EvapCond);
1183 103 : auto &thisEvapCond(EvapCond(EvapCoolNum));
1184 :
1185 103 : bool HardSizeNoDesRun = !((state.dataSize->SysSizingRunDone || state.dataSize->ZoneSizingRunDone));
1186 103 : bool SizingDesRunThisAirSys = false; // true if a particular air system had a Sizing:System object and system sizing done
1187 103 : bool SizingDesRunThisZone = false; // true if a particular zone had a Sizing:Zone object and zone sizing was done
1188 :
1189 103 : if (CurSysNum > 0) {
1190 51 : CheckThisAirSystemForSizing(state, CurSysNum, SizingDesRunThisAirSys);
1191 51 : if (SizingDesRunThisAirSys) {
1192 42 : HardSizeNoDesRun = false; // Check if design infomation is available
1193 : }
1194 : }
1195 103 : if (CurZoneEqNum > 0) {
1196 52 : CheckThisZoneForSizing(state, CurZoneEqNum, SizingDesRunThisZone);
1197 : // This next check was added during CppCheck corrections. This does not cause diffs
1198 : // because SizingDesRunThisZone is not used below this point.
1199 : // This check was commented to get back to original code and an issue is needed to correct.
1200 : // Why no check for zone equipment?
1201 : // if (SizingDesRunThisZone) {
1202 : // HardSizeNoDesRun = false; // Check if design infomation is available
1203 : //}
1204 : }
1205 : // I don't think the sizing logic is correct when it comes to autosized vs hard-sized inputs
1206 : // or input files that use Sizing:Zone or Sizing:System with autosized and/or hard-sized inputs
1207 :
1208 103 : CompType = evapCoolerTypeNames[static_cast<int>(thisEvapCond.evapCoolerType)];
1209 :
1210 : // Search once for the object on an air system
1211 103 : if (CurSysNum > 0) { // central system
1212 : // where is this cooler located, is it on OA system or main loop?
1213 : // search for this component in Air loop branches.
1214 102 : for (int AirSysBranchLoop = 1; AirSysBranchLoop <= state.dataAirSystemsData->PrimaryAirSystems(CurSysNum).NumBranches; ++AirSysBranchLoop) {
1215 258 : for (int BranchComp = 1; BranchComp <= state.dataAirSystemsData->PrimaryAirSystems(CurSysNum).Branch(AirSysBranchLoop).TotalComponents;
1216 : ++BranchComp) {
1217 :
1218 207 : if (Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(CurSysNum).Branch(AirSysBranchLoop).Comp(BranchComp).Name,
1219 : thisEvapCond.Name)) {
1220 37 : CoolerOnMainAirLoop = true;
1221 : }
1222 : }
1223 : }
1224 51 : if (!CoolerOnMainAirLoop) CoolerOnOApath = true;
1225 : }
1226 :
1227 : // Start with the indirect volume flow rate
1228 103 : IsAutoSize = false;
1229 103 : if (thisEvapCond.IndirectVolFlowRate == DataSizing::AutoSize) {
1230 10 : IsAutoSize = true;
1231 : }
1232 103 : if (CurSysNum > 0 && !IsAutoSize && !SizingDesRunThisAirSys) {
1233 9 : HardSizeNoDesRun = true;
1234 : }
1235 103 : if (CurSysNum > 0) { // central system
1236 51 : if (!IsAutoSize && !SizingDesRunThisAirSys) {
1237 9 : if (thisEvapCond.IndirectVolFlowRate > 0.0) {
1238 2 : if (thisEvapCond.evapCoolerType == EvapCoolerType::IndirectCELDEKPAD ||
1239 1 : thisEvapCond.evapCoolerType == EvapCoolerType::IndirectWETCOIL ||
1240 0 : thisEvapCond.evapCoolerType == EvapCoolerType::IndirectRDDSpecial) {
1241 2 : BaseSizer::reportSizerOutput(
1242 : state, CompType, thisEvapCond.Name, "User-Specified Secondary Fan Flow Rate [m3/s]", thisEvapCond.IndirectVolFlowRate);
1243 : }
1244 : }
1245 : } else { // Autosize or hardsize with design data
1246 42 : CheckSysSizing(state, CompType, thisEvapCond.Name);
1247 42 : if (CoolerOnMainAirLoop) {
1248 28 : IndirectVolFlowRateDes = FinalSysSizing(CurSysNum).DesMainVolFlow;
1249 14 : } else if (CoolerOnOApath) {
1250 14 : IndirectVolFlowRateDes = max(FinalSysSizing(CurSysNum).DesOutAirVolFlow, 0.5 * FinalSysSizing(CurSysNum).DesMainVolFlow);
1251 : }
1252 : // apply scaling factor the secondary air fan flow rate
1253 42 : if (thisEvapCond.evapCoolerType == EvapCoolerType::IndirectRDDSpecial) {
1254 30 : IndirectVolFlowRateDes = IndirectVolFlowRateDes * thisEvapCond.IndirectVolFlowScalingFactor;
1255 : }
1256 : }
1257 52 : } else if (CurZoneEqNum > 0) { // zone equipment
1258 52 : if (!IsAutoSize && !SizingDesRunThisAirSys) { // this should be SizingDesRunThisZone
1259 52 : if (thisEvapCond.IndirectVolFlowRate > 0.0) {
1260 : // report for the indirect evap cooler types only
1261 20 : if (thisEvapCond.evapCoolerType == EvapCoolerType::IndirectCELDEKPAD ||
1262 16 : thisEvapCond.evapCoolerType == EvapCoolerType::IndirectWETCOIL ||
1263 8 : thisEvapCond.evapCoolerType == EvapCoolerType::IndirectRDDSpecial) {
1264 20 : BaseSizer::reportSizerOutput(
1265 : state, CompType, thisEvapCond.Name, "User-Specified Secondary Fan Flow Rate [m3/s]", thisEvapCond.IndirectVolFlowRate);
1266 : }
1267 : }
1268 : } else { // Autosize or hardsize with design data
1269 : // zone equip evap coolers
1270 0 : IndirectVolFlowRateDes = state.dataSize->FinalZoneSizing(CurZoneEqNum).DesCoolVolFlow;
1271 : // apply scaling factor the secondary air fan flow rate
1272 0 : if (thisEvapCond.evapCoolerType == EvapCoolerType::IndirectRDDSpecial) {
1273 0 : IndirectVolFlowRateDes = IndirectVolFlowRateDes * thisEvapCond.IndirectVolFlowScalingFactor;
1274 : }
1275 : }
1276 : }
1277 103 : if (!HardSizeNoDesRun) {
1278 94 : if (IsAutoSize) {
1279 10 : thisEvapCond.IndirectVolFlowRate = IndirectVolFlowRateDes;
1280 10 : if (thisEvapCond.evapCoolerType == EvapCoolerType::IndirectCELDEKPAD || thisEvapCond.evapCoolerType == EvapCoolerType::IndirectWETCOIL ||
1281 10 : thisEvapCond.evapCoolerType == EvapCoolerType::IndirectRDDSpecial) {
1282 10 : BaseSizer::reportSizerOutput(
1283 : state, CompType, thisEvapCond.Name, "Design Size Secondary Fan Flow Rate [m3/s]", thisEvapCond.IndirectVolFlowRate);
1284 : }
1285 : } else {
1286 84 : if (thisEvapCond.IndirectVolFlowRate > 0.0 && IndirectVolFlowRateDes > 0.0) {
1287 20 : IndirectVolFlowRateUser = thisEvapCond.IndirectVolFlowRate;
1288 20 : BaseSizer::reportSizerOutput(state,
1289 : "EvaporativeCooler:Indirect:ResearchSpecial",
1290 : thisEvapCond.Name,
1291 : "Design Size Secondary Fan Flow Rate [m3/s]",
1292 : IndirectVolFlowRateDes,
1293 : "User-Specified Secondary Fan Flow Rate [m3/s]",
1294 : IndirectVolFlowRateUser);
1295 20 : if (state.dataGlobal->DisplayExtraWarnings) {
1296 0 : if ((std::abs(IndirectVolFlowRateDes - IndirectVolFlowRateUser) / IndirectVolFlowRateUser) >
1297 0 : state.dataSize->AutoVsHardSizingThreshold) {
1298 0 : ShowMessage(state,
1299 0 : format("SizeEvaporativeCooler:Indirect:ResearchSpecial: Potential issue with equipment sizing for {}",
1300 0 : thisEvapCond.Name));
1301 0 : ShowContinueError(state, format("User-Specified Secondary Fan Flow Rate of {:.5R} [m3/s]", IndirectVolFlowRateUser));
1302 0 : ShowContinueError(state, format("differs from Design Size Secondary Fan Flow Rate of {:.5R} [m3/s]", IndirectVolFlowRateDes));
1303 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1304 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1305 : }
1306 : }
1307 : }
1308 : }
1309 : }
1310 :
1311 : // Next up the other volume flow rate
1312 103 : IsAutoSize = false;
1313 103 : if (thisEvapCond.DesVolFlowRate == DataSizing::AutoSize) {
1314 62 : IsAutoSize = true;
1315 : }
1316 103 : if (CurSysNum > 0 && !IsAutoSize && !SizingDesRunThisAirSys) {
1317 9 : HardSizeNoDesRun = true;
1318 : }
1319 103 : if (CurSysNum > 0) { // central system
1320 51 : if (!IsAutoSize && !SizingDesRunThisAirSys) {
1321 : // the .VolFlowRate variable wasn't reported to the eio in develop, so not doing it here
1322 : // if ( EvapCond( EvapCoolNum ).VolFlowRate > 0.0 ) {
1323 : // BaseSizer::reportSizerOutput( CompType, EvapCond( EvapCoolNum ).Name,
1324 : //"User-Specified Secondary Fan Flow Rate [m3/s]", EvapCond( EvapCoolNum ).VolFlowRate );
1325 : //}
1326 : } else { // Autosize or hardsize with design data
1327 42 : CheckSysSizing(state, CompType, thisEvapCond.Name);
1328 42 : if (CoolerOnMainAirLoop) {
1329 28 : volFlowRateDes = FinalSysSizing(CurSysNum).DesMainVolFlow;
1330 14 : } else if (CoolerOnOApath) {
1331 14 : volFlowRateDes = max(FinalSysSizing(CurSysNum).DesOutAirVolFlow, 0.5 * FinalSysSizing(CurSysNum).DesMainVolFlow);
1332 : }
1333 : // no scaling factor on the volFlowRate in develop, so not doing it here
1334 : }
1335 52 : } else if (CurZoneEqNum > 0) { // zone equipment
1336 : // zone equip evap coolers
1337 :
1338 : // this should be SizingDesRunThisZone
1339 52 : if (!IsAutoSize && !SizingDesRunThisAirSys) {
1340 : // the .VolFlowRate variable wasn't reported to the eio in develop, so not doing it here
1341 : // if ( EvapCond( EvapCoolNum ).VolFlowRate > 0.0 ) {
1342 : // BaseSizer::reportSizerOutput( "EvaporativeCooler:Indirect:ResearchSpecial", EvapCond( EvapCoolNum ).Name,
1343 : //"User-Specified Secondary Fan Flow Rate [m3/s]", EvapCond( EvapCoolNum ).VolFlowRate );
1344 : //}
1345 : } else { // Autosize or hardsize with design data
1346 20 : volFlowRateDes = state.dataSize->FinalZoneSizing(CurZoneEqNum).DesCoolVolFlow;
1347 : }
1348 :
1349 : } else { // zone equipment
1350 : // can't do zone equip evap coolers yet
1351 : }
1352 103 : if (!HardSizeNoDesRun) {
1353 94 : if (IsAutoSize) {
1354 62 : thisEvapCond.DesVolFlowRate = volFlowRateDes;
1355 : // only these two evap coolers has primary air design flow rate
1356 62 : if (thisEvapCond.evapCoolerType == EvapCoolerType::IndirectRDDSpecial) {
1357 38 : BaseSizer::reportSizerOutput(state,
1358 : "EvaporativeCooler:Indirect:ResearchSpecial",
1359 : thisEvapCond.Name,
1360 : "Primary Air Design Flow Rate [m3/s]",
1361 : thisEvapCond.DesVolFlowRate);
1362 38 : BaseSizer::reportSizerOutput(state,
1363 : "EvaporativeCooler:Indirect:ResearchSpecial",
1364 : thisEvapCond.Name,
1365 : "Secondary Air Design Flow Rate [m3/s]",
1366 : thisEvapCond.IndirectVolFlowRate);
1367 24 : } else if (thisEvapCond.evapCoolerType == EvapCoolerType::DirectResearchSpecial) {
1368 24 : BaseSizer::reportSizerOutput(state,
1369 : "EvaporativeCooler:Direct:ResearchSpecial",
1370 : thisEvapCond.Name,
1371 : "Primary Air Design Flow Rate [m3/s]",
1372 : thisEvapCond.DesVolFlowRate);
1373 : }
1374 : } else {
1375 : // the .VolFlowRate variable wasn't reported to the eio in develop, so not doing it here
1376 : // if ( EvapCond( EvapCoolNum ).IndirectVolFlowRate > 0.0 && IndirectVolFlowRateDes > 0.0 ) {
1377 : // IndirectVolFlowRateUser = EvapCond( EvapCoolNum ).IndirectVolFlowRate;
1378 : // BaseSizer::reportSizerOutput( "EvaporativeCooler:Indirect:ResearchSpecial", EvapCond( EvapCoolNum ).Name,
1379 : //"Design Size Secondary Fan Flow Rate [m3/s]", IndirectVolFlowRateDes,
1380 : //"User-Specified Secondary Fan Flow Rate [m3/s]", IndirectVolFlowRateUser );
1381 : // if ( DisplayExtraWarnings ) {
1382 : // if ( ( std::abs( IndirectVolFlowRateDes - IndirectVolFlowRateUser ) / IndirectVolFlowRateUser ) > AutoVsHardSizingThreshold ) {
1383 : // ShowMessage(state, format("SizeEvaporativeCooler:Indirect:ResearchSpecial: \nPotential issue with equipment sizing for {}", EvapCond(
1384 : // EvapCoolNum
1385 : // ).Name)); ShowContinueError(state, format("User-Specified Secondary Fan Flow Rate of {} [m3/s]", RoundSigDigits(
1386 : // IndirectVolFlowRateUser, 5 ))); ShowContinueError(state, format("differs from Design Size Secondary Fan Flow Rate of
1387 : // {:.5R}", IndirectVolFlowRateDes) + " [m3/s]" ); ShowContinueError(state, "This may, or may not, indicate mismatched component
1388 : // sizes." ); ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components." );
1389 : //}
1390 : //}
1391 : //}
1392 : }
1393 : }
1394 :
1395 103 : if (thisEvapCond.evapCoolerType == EvapCoolerType::DirectCELDEKPAD) {
1396 27 : IsAutoSize = false;
1397 27 : if (thisEvapCond.PadArea == DataSizing::AutoSize) {
1398 1 : IsAutoSize = true;
1399 : }
1400 27 : if (CurSysNum > 0 && !IsAutoSize && !SizingDesRunThisAirSys) {
1401 7 : HardSizeNoDesRun = true;
1402 : }
1403 27 : if (SizingDesRunThisAirSys) HardSizeNoDesRun = false; // Check if design infomation is available
1404 : // Design air flow rate
1405 27 : if (CurSysNum > 0) { // central system
1406 7 : if (!IsAutoSize && !SizingDesRunThisAirSys) {
1407 7 : HardSizeNoDesRun = true;
1408 7 : if (thisEvapCond.PadArea > 0.0) {
1409 7 : BaseSizer::reportSizerOutput(
1410 : state, "EvaporativeCooler:Direct:CelDekPad", thisEvapCond.Name, "User-Specified Celdek Pad Area [m2]", thisEvapCond.PadArea);
1411 : }
1412 : } else { // Autosize or hardsize with design data
1413 0 : CheckSysSizing(state, CompType, thisEvapCond.Name);
1414 0 : if (CoolerOnMainAirLoop) {
1415 0 : IndirectVolFlowRateDes = FinalSysSizing(CurSysNum).DesMainVolFlow;
1416 0 : } else if (CoolerOnOApath) {
1417 0 : IndirectVolFlowRateDes = std::max(FinalSysSizing(CurSysNum).DesOutAirVolFlow, 0.50 * FinalSysSizing(CurSysNum).DesMainVolFlow);
1418 : }
1419 : // Face air velocity of 3m/s is assumed
1420 0 : PadAreaDes = IndirectVolFlowRateDes / 3.0;
1421 : }
1422 20 : } else if (CurZoneEqNum > 0) { // zone equipment
1423 : // zone equip evap coolers
1424 :
1425 : // this should be SizingDesRunThisZone
1426 20 : if (!IsAutoSize && !SizingDesRunThisAirSys) {
1427 19 : HardSizeNoDesRun = true;
1428 19 : if (thisEvapCond.PadArea > 0.0) {
1429 : // report for the indirect evap cooler types only
1430 19 : BaseSizer::reportSizerOutput(
1431 : state, "EvaporativeCooler:Direct:CelDekPad", thisEvapCond.Name, "User-Specified Celdek Pad Area [m2]", thisEvapCond.PadArea);
1432 : }
1433 : } else { // Autosize or hardsize with design data
1434 : // zone equip evap coolers
1435 1 : IndirectVolFlowRateDes = state.dataSize->FinalZoneSizing(CurZoneEqNum).DesCoolVolFlow;
1436 : // Face air velocity of 3m/s is assumed
1437 1 : PadAreaDes = IndirectVolFlowRateDes / 3.0;
1438 : }
1439 : } else {
1440 : }
1441 :
1442 27 : if (!HardSizeNoDesRun) {
1443 1 : if (IsAutoSize) {
1444 1 : thisEvapCond.PadArea = PadAreaDes;
1445 1 : BaseSizer::reportSizerOutput(
1446 : state, "EvaporativeCooler:Direct:CelDekPad", thisEvapCond.Name, "Design Size Celdek Pad Area [m2]", PadAreaDes);
1447 : } else {
1448 0 : if (thisEvapCond.PadArea > 0.0 && PadAreaDes > 0.0) {
1449 0 : PadAreaUser = thisEvapCond.PadArea;
1450 0 : BaseSizer::reportSizerOutput(state,
1451 : "EvaporativeCooler:Direct:CelDekPad",
1452 : thisEvapCond.Name,
1453 : "Design Size Celdek Pad Area [m2]",
1454 : PadAreaDes,
1455 : "User-Specified Celdek Pad Area [m2]",
1456 : PadAreaUser);
1457 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1458 0 : if ((std::abs(PadAreaDes - PadAreaUser) / PadAreaUser) > state.dataSize->AutoVsHardSizingThreshold) {
1459 0 : ShowMessage(
1460 : state,
1461 0 : format("SizeEvaporativeCooler:Direct:CelDekPad: Potential issue with equipment sizing for {}", thisEvapCond.Name));
1462 0 : ShowContinueError(state, format("User-Specified Celdek Pad Area of{:.2R} [m2]", PadAreaUser));
1463 0 : ShowContinueError(state, format("differs from Design Size Celdek Pad Area of {:.2R} [m2]", PadAreaDes));
1464 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1465 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1466 : }
1467 : }
1468 : }
1469 : }
1470 : }
1471 :
1472 27 : IsAutoSize = false;
1473 27 : if (thisEvapCond.PadDepth == DataSizing::AutoSize) {
1474 1 : IsAutoSize = true;
1475 : }
1476 27 : if (CurSysNum > 0 && !IsAutoSize && !SizingDesRunThisAirSys) {
1477 7 : HardSizeNoDesRun = true;
1478 : }
1479 : // The following regression equation is used to determine pad depth,
1480 : // assuming saturation effectiveness of 70% and face air velocity of 3m/s:
1481 : // Effectiveness = 0.792714 + 0.958569D - 0.25193V - 1.03215D^2 + 0.0262659V^2 + 0.914869DV -
1482 : // 1.48241VD^2 - 0.018992V^3D + 1.13137D^3V + 0.0327622V^3D^2 - 0.145384D^3V^2
1483 27 : PadDepthDes = 0.17382;
1484 27 : if (IsAutoSize) {
1485 1 : thisEvapCond.PadDepth = PadDepthDes;
1486 1 : BaseSizer::reportSizerOutput(
1487 : state, "EvaporativeCooler:Direct:CelDekPad", thisEvapCond.Name, "Design Size Celdek Pad Depth [m]", PadDepthDes);
1488 : } else {
1489 26 : if (thisEvapCond.PadDepth > 0.0 && PadDepthDes > 0.0) {
1490 26 : PadDepthUser = thisEvapCond.PadDepth;
1491 26 : BaseSizer::reportSizerOutput(state,
1492 : "EvaporativeCooler:Direct:CelDekPad",
1493 : thisEvapCond.Name,
1494 : "Design Size Celdek Pad Depth [m]",
1495 : PadDepthDes,
1496 : "User-Specified Celdek Pad Depth [m]",
1497 : PadDepthUser);
1498 26 : if (state.dataGlobal->DisplayExtraWarnings) {
1499 0 : if ((std::abs(PadDepthDes - PadDepthUser) / PadDepthUser) > state.dataSize->AutoVsHardSizingThreshold) {
1500 0 : ShowMessage(
1501 0 : state, format("SizeEvaporativeCooler:Direct:CelDekPad: Potential issue with equipment sizing for {}", thisEvapCond.Name));
1502 0 : ShowContinueError(state, format("User-Specified Celdek Pad Depth of {:.2R} [m]", PadDepthUser));
1503 0 : ShowContinueError(state, format("differs from Design Size Celdek Pad Depth of {:.2R} [m]", PadDepthDes));
1504 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1505 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1506 : }
1507 : }
1508 : }
1509 : }
1510 : }
1511 :
1512 103 : if (thisEvapCond.evapCoolerType == EvapCoolerType::IndirectCELDEKPAD) {
1513 5 : IsAutoSize = false;
1514 :
1515 5 : if (thisEvapCond.IndirectPadArea == DataSizing::AutoSize) {
1516 1 : IsAutoSize = true;
1517 : }
1518 5 : if (SizingDesRunThisAirSys) {
1519 0 : HardSizeNoDesRun = false; // Check if design infomation is available
1520 : }
1521 : // Design air flow rate
1522 5 : if (CurSysNum > 0) { // central system
1523 : // where is this cooler located, is it on OA system or main loop?
1524 : // search for this component in Air loop branches.
1525 2 : for (int AirSysBranchLoop = 1; AirSysBranchLoop <= state.dataAirSystemsData->PrimaryAirSystems(CurSysNum).NumBranches;
1526 : ++AirSysBranchLoop) {
1527 5 : for (int BranchComp = 1;
1528 5 : BranchComp <= state.dataAirSystemsData->PrimaryAirSystems(CurSysNum).Branch(AirSysBranchLoop).TotalComponents;
1529 : ++BranchComp) {
1530 4 : if (Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(CurSysNum).Branch(AirSysBranchLoop).Comp(BranchComp).Name,
1531 : thisEvapCond.Name)) {
1532 1 : CoolerOnMainAirLoop = true;
1533 : }
1534 : }
1535 : }
1536 1 : if (!IsAutoSize && !SizingDesRunThisAirSys) {
1537 1 : HardSizeNoDesRun = true;
1538 1 : if (thisEvapCond.IndirectPadArea > 0.0) {
1539 1 : BaseSizer::reportSizerOutput(state,
1540 : "EvaporativeCooler:Indirect:CelDekPad",
1541 : thisEvapCond.Name,
1542 : "User-Specified Celdek Pad Area [m2]",
1543 : thisEvapCond.IndirectPadArea);
1544 : }
1545 : } else { // Autosize or hardsize with design data
1546 0 : CheckSysSizing(state, CompType, thisEvapCond.Name);
1547 0 : if (!CoolerOnMainAirLoop) {
1548 0 : CoolerOnOApath = true;
1549 : }
1550 0 : if (CoolerOnMainAirLoop) {
1551 0 : IndirectVolFlowRateDes = FinalSysSizing(CurSysNum).DesMainVolFlow;
1552 0 : } else if (CoolerOnOApath) {
1553 0 : IndirectVolFlowRateDes = std::max(FinalSysSizing(CurSysNum).DesOutAirVolFlow, 0.5 * FinalSysSizing(CurSysNum).DesMainVolFlow);
1554 : }
1555 : // Face air velocity of 3m/s is assumed
1556 0 : PadAreaDes = IndirectVolFlowRateDes / 3.0;
1557 : }
1558 4 : } else if (CurZoneEqNum > 0) { // zone equipment
1559 : // zone equip evap coolers
1560 4 : if (!IsAutoSize && !SizingDesRunThisAirSys) { // this should be SizingDesRunThisZone
1561 3 : HardSizeNoDesRun = true;
1562 3 : if (thisEvapCond.IndirectPadArea > 0.0) {
1563 : // report for the indirect evap cooler types only
1564 3 : if (thisEvapCond.PadArea > 0.0) {
1565 0 : BaseSizer::reportSizerOutput(state,
1566 : "EvaporativeCooler:Indirect:CelDekPad",
1567 : thisEvapCond.Name,
1568 : "User-Specified Celdek Pad Area [m2]",
1569 : thisEvapCond.IndirectPadArea);
1570 : }
1571 : }
1572 : } else { // Autosize or hardsize with design data
1573 : // zone equip evap coolers
1574 1 : IndirectVolFlowRateDes = state.dataSize->FinalZoneSizing(CurZoneEqNum).DesCoolVolFlow;
1575 : // Face air velocity of 3m/s is assumed
1576 1 : PadAreaDes = IndirectVolFlowRateDes / 3.0;
1577 : }
1578 : } else {
1579 : }
1580 :
1581 5 : if (!HardSizeNoDesRun) {
1582 1 : if (IsAutoSize) {
1583 1 : thisEvapCond.IndirectPadArea = PadAreaDes;
1584 1 : BaseSizer::reportSizerOutput(
1585 : state, "EvaporativeCooler:Indirect:CelDekPad", thisEvapCond.Name, "Design Size Celdek Pad Area [m2]", PadAreaDes);
1586 : } else {
1587 0 : if (thisEvapCond.IndirectPadArea > 0.0 && PadAreaDes > 0.0) {
1588 0 : PadAreaUser = thisEvapCond.IndirectPadArea;
1589 0 : BaseSizer::reportSizerOutput(state,
1590 : "EvaporativeCooler:Indirect:CelDekPad",
1591 : thisEvapCond.Name,
1592 : "Design Size Celdek Pad Area [m2]",
1593 : PadAreaDes,
1594 : "User-Specified Celdek Pad Area [m2]",
1595 : PadAreaUser);
1596 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1597 0 : if ((std::abs(PadAreaDes - PadAreaUser) / PadAreaUser) > state.dataSize->AutoVsHardSizingThreshold) {
1598 0 : ShowMessage(
1599 : state,
1600 0 : format("SizeEvaporativeCooler:Indirect:CelDekPad: Potential issue with equipment sizing for {}", thisEvapCond.Name));
1601 0 : ShowContinueError(state, format("User-Specified Celdek Pad Area {:.2R} [m2]", PadAreaUser));
1602 0 : ShowContinueError(state, format("differs from Design Size Celdek Pad Area of {:.2R} [m2]", PadAreaDes));
1603 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1604 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1605 : }
1606 : }
1607 : }
1608 : }
1609 : }
1610 :
1611 5 : IsAutoSize = thisEvapCond.IndirectPadDepth == DataSizing::AutoSize;
1612 : // The following regression equation is used to determine pad depth,
1613 : // assuming saturation effectiveness of 70% and face air velocity of 3m/s:
1614 : // Effectiveness = 0.792714 + 0.958569D - 0.25193V - 1.03215D^2 + 0.0262659V^2 + 0.914869DV -
1615 : // 1.48241VD^2 - 0.018992V^3D + 1.13137D^3V + 0.0327622V^3D^2 - 0.145384D^3V^2
1616 :
1617 5 : PadDepthDes = 0.17382;
1618 5 : if (IsAutoSize) {
1619 1 : thisEvapCond.IndirectPadDepth = PadDepthDes;
1620 1 : BaseSizer::reportSizerOutput(
1621 : state, "EvaporativeCooler:Indirect:CelDekPad", thisEvapCond.Name, "Design Size Celdek Pad Depth [m]", PadDepthDes);
1622 : } else {
1623 4 : if (thisEvapCond.IndirectPadDepth > 0.0 && PadDepthDes > 0.0) {
1624 4 : PadDepthUser = thisEvapCond.IndirectPadDepth;
1625 4 : BaseSizer::reportSizerOutput(state,
1626 : "EvaporativeCooler:Indirect:CelDekPad",
1627 : thisEvapCond.Name,
1628 : "Design Size Celdek Pad Depth [m]",
1629 : PadDepthDes,
1630 : "User-Specified Celdek Pad Depth [m]",
1631 : PadDepthUser);
1632 4 : if (state.dataGlobal->DisplayExtraWarnings) {
1633 0 : if ((std::abs(PadDepthDes - PadDepthUser) / PadDepthUser) > state.dataSize->AutoVsHardSizingThreshold) {
1634 0 : ShowMessage(
1635 : state,
1636 0 : format("SizeEvaporativeCooler:Indirect:CelDekPad: Potential issue with equipment sizing for {}", thisEvapCond.Name));
1637 0 : ShowContinueError(state, format("User-Specified Celdek Pad Depth of {:.2R} [m]", PadDepthUser));
1638 0 : ShowContinueError(state, format("differs from Design Size Celdek Pad Depth of {:.2R} [m]", PadDepthDes));
1639 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1640 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1641 : }
1642 : }
1643 : }
1644 : }
1645 : }
1646 :
1647 103 : if (thisEvapCond.evapCoolerType == EvapCoolerType::IndirectRDDSpecial) {
1648 : // secondary air fan sizing: Secondary flow Rate (m3/s) * Fan Flow Sizing Factor (W/(m3/s)
1649 38 : if (thisEvapCond.IndirectFanPower == DataSizing::AutoSize) {
1650 38 : thisEvapCond.IndirectFanPower = thisEvapCond.IndirectVolFlowRate * thisEvapCond.FanSizingSpecificPower;
1651 38 : BaseSizer::reportSizerOutput(
1652 : state, "EvaporativeCooler:Indirect:ResearchSpecial", thisEvapCond.Name, "Secondary Fan Power [W]", thisEvapCond.IndirectFanPower);
1653 : }
1654 : // recirculating water pump sizing: Secondary flow Rate (m3/s) * Pump Sizing Factor (W/(m3/s)
1655 38 : if (thisEvapCond.IndirectRecircPumpPower == DataSizing::AutoSize) {
1656 4 : thisEvapCond.IndirectRecircPumpPower = thisEvapCond.IndirectVolFlowRate * thisEvapCond.RecircPumpSizingFactor;
1657 4 : BaseSizer::reportSizerOutput(state,
1658 : "EvaporativeCooler:Indirect:ResearchSpecial",
1659 : thisEvapCond.Name,
1660 : "Recirculating Pump Power [W]",
1661 : thisEvapCond.IndirectRecircPumpPower);
1662 : }
1663 : }
1664 :
1665 103 : if (thisEvapCond.evapCoolerType == EvapCoolerType::DirectResearchSpecial) {
1666 : // recirculating water pump sizing: Primary Air Design flow Rate (m3/s) * Pump Sizing Factor (W/(m3/s)
1667 24 : if (thisEvapCond.RecircPumpPower == DataSizing::AutoSize) {
1668 0 : thisEvapCond.RecircPumpPower = thisEvapCond.DesVolFlowRate * thisEvapCond.RecircPumpSizingFactor;
1669 0 : BaseSizer::reportSizerOutput(
1670 : state, "EvaporativeCooler:Direct:ResearchSpecial", thisEvapCond.Name, "Recirculating Pump Power [W]", thisEvapCond.RecircPumpPower);
1671 : }
1672 : }
1673 103 : }
1674 :
1675 258218 : void CalcDirectEvapCooler(EnergyPlusData &state, int EvapCoolNum, Real64 const PartLoadRatio)
1676 : {
1677 :
1678 : // SUBROUTINE INFORMATION:
1679 : // AUTHOR Richard J. Liesen
1680 : // DATE WRITTEN October 2000
1681 :
1682 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1683 : Real64 PadDepth; // EvapCooler Pad Depth in Meters as input by the User
1684 : Real64 SatEff; // Saturation Efficiency of the CelDek Pad
1685 : Real64 AirVel; // The Calculated Air Velocity through the Pad
1686 : Real64 TEDB; // Entering Dry Bulb Temperature
1687 : Real64 TEWB; // Entering Wet Bulb Temperature
1688 : Real64 RhoWater;
1689 :
1690 258218 : auto &thisEvapCond(state.dataEvapCoolers->EvapCond(EvapCoolNum));
1691 :
1692 : // If the Evaporative Cooler is operating there should be some mass flow rate
1693 : // Also the evap cooler has to be scheduled to be available
1694 258218 : if ((thisEvapCond.InletMassFlowRate > 0.0) && (ScheduleManager::GetCurrentScheduleValue(state, thisEvapCond.SchedPtr) > 0.0)) {
1695 :
1696 133226 : PadDepth = thisEvapCond.PadDepth;
1697 : //******************************************************************************
1698 : // THIS SUBROUTINE WILL CACULATE THE TEMPERATURE OF THE LEAVING AIR DRY BULB
1699 : // FOR A DIRECT EVAPORATIVE AIR COOLER SUPPLIED WITH CFMAir,DIRPAD,TEWB,TEDB,
1700 : // AND PB (ATM. PRESS.) FOR AIR DENSITY CALCULATIONS.
1701 : //******************************************************************************
1702 :
1703 133226 : AirVel = thisEvapCond.VolFlowRate / thisEvapCond.PadArea;
1704 :
1705 : //******************************************************************************
1706 : // SAT EFF IS FOR DIFFERENT THICKNESS CELDEK PAD (CURVE FIT FROM DATA)
1707 : //******************************************************************************
1708 133226 : SatEff = 0.792714 + 0.958569 * PadDepth - 0.25193 * AirVel - 1.03215 * pow_2(PadDepth) + 2.62659e-2 * pow_2(AirVel) +
1709 133226 : 0.914869 * PadDepth * AirVel - 1.48241 * AirVel * pow_2(PadDepth) - 1.89919e-2 * pow_3(AirVel) * PadDepth +
1710 133226 : 1.13137 * pow_3(PadDepth) * AirVel + 3.27622e-2 * pow_3(AirVel) * pow_2(PadDepth) - 0.145384 * pow_3(PadDepth) * pow_2(AirVel);
1711 :
1712 133226 : if (SatEff >= 1.0) SatEff = 1.0;
1713 133226 : if (SatEff < 0.0) { // we have a serious problem. Pad Area and/or depth not suitable for system air flow rates
1714 0 : ShowSevereError(state, format("EVAPCOOLER:DIRECT:CELDEKPAD: {} has a problem", thisEvapCond.Name));
1715 0 : ShowContinueError(state, "Check size of Pad Area and/or Pad Depth in input");
1716 0 : ShowContinueError(state, format("Cooler Effectiveness calculated as: {:.2R}", SatEff));
1717 0 : ShowContinueError(state, format("Air velocity (m/s) through pads calculated as: {:.2R}", AirVel));
1718 0 : ShowFatalError(state, "Program Terminates due to previous error condition");
1719 : }
1720 133226 : thisEvapCond.SatEff = SatEff;
1721 : //***************************************************************************
1722 : // TEMP LEAVING DRY BULB IS CALCULATED FROM SATURATION EFFICIENCY AS THE
1723 : // DRY BULB TEMP APPROACHES THE WET BULB TEMP. WET BULB TEMP IS CONSTANT
1724 : // ACROSS A DIRECT EVAPORATION COOLER.
1725 133226 : TEWB = thisEvapCond.InletWetBulbTemp;
1726 133226 : TEDB = thisEvapCond.InletTemp;
1727 :
1728 133226 : thisEvapCond.OutletTemp = TEDB - ((TEDB - TEWB) * SatEff);
1729 :
1730 133226 : thisEvapCond.OuletWetBulbTemp = thisEvapCond.InletWetBulbTemp;
1731 :
1732 133226 : thisEvapCond.OutletHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, thisEvapCond.OutletTemp, TEWB, state.dataEnvrn->OutBaroPress);
1733 :
1734 133226 : thisEvapCond.OutletEnthalpy = Psychrometrics::PsyHFnTdbW(thisEvapCond.OutletTemp, thisEvapCond.OutletHumRat);
1735 :
1736 : //***************************************************************************
1737 : // ENERGY CONSUMED BY THE RECIRCULATING PUMP
1738 : // Add the pump energy to the total Evap Cooler energy comsumption
1739 133226 : thisEvapCond.EvapCoolerPower += PartLoadRatio * thisEvapCond.RecircPumpPower;
1740 : //******************
1741 : // WATER CONSUMPTION IN m3 OF WATER FOR DIRECT
1742 : // H2O [m3/s] = Delta W[kgWater/kDryAir]*Mass Flow Air[kgDryAir/s]
1743 : // /RhoWater [kgWater/m3]
1744 : //******************
1745 133226 : RhoWater = Psychrometrics::RhoH2O(thisEvapCond.OutletTemp);
1746 133226 : thisEvapCond.EvapWaterConsumpRate = (thisEvapCond.OutletHumRat - thisEvapCond.InletHumRat) * thisEvapCond.InletMassFlowRate / RhoWater;
1747 : // A numerical check to keep from having very tiny negative water consumption values being reported
1748 133226 : if (thisEvapCond.EvapWaterConsumpRate < 0.0) thisEvapCond.EvapWaterConsumpRate = 0.0;
1749 :
1750 : } else {
1751 : // The evap cooler is not running and does not change conditions from inlet to outlet
1752 124992 : thisEvapCond.OutletTemp = thisEvapCond.InletTemp;
1753 :
1754 124992 : thisEvapCond.OuletWetBulbTemp = thisEvapCond.InletWetBulbTemp;
1755 :
1756 124992 : thisEvapCond.OutletHumRat = thisEvapCond.InletHumRat;
1757 :
1758 124992 : thisEvapCond.OutletEnthalpy = thisEvapCond.InletEnthalpy;
1759 :
1760 124992 : thisEvapCond.EvapCoolerEnergy = 0.0;
1761 :
1762 124992 : thisEvapCond.EvapWaterConsumpRate = 0.0;
1763 : }
1764 : // all of the mass flowrates are not changed across the evap cooler
1765 258218 : thisEvapCond.OutletMassFlowRate = thisEvapCond.InletMassFlowRate;
1766 258218 : thisEvapCond.OutletMassFlowRateMaxAvail = thisEvapCond.InletMassFlowRateMaxAvail;
1767 258218 : thisEvapCond.OutletMassFlowRateMinAvail = thisEvapCond.InletMassFlowRateMinAvail;
1768 :
1769 : // the pressure is not changed across the evap cooler
1770 258218 : thisEvapCond.OutletPressure = thisEvapCond.InletPressure;
1771 258218 : }
1772 :
1773 38920 : void CalcDryIndirectEvapCooler(EnergyPlusData &state, int EvapCoolNum, Real64 const PartLoadRatio)
1774 : {
1775 :
1776 : // SUBROUTINE INFORMATION:
1777 : // AUTHOR Richard J. Liesen
1778 : // DATE WRITTEN October 2000
1779 : // MODIFIED BG Feb. 2007 secondary air inlet node
1780 :
1781 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1782 : Real64 PadDepth; // EvapCooler Pad Depth in Meters as input by the User
1783 : Real64 SatEff; // Saturation Efficiency of the CelDek Pad
1784 : Real64 AirVel; // The Calculated Air Velocity through the Pad
1785 : Real64 TDBSec; // Secondary leaving dry bulb
1786 : Real64 TWBSec; // Secondary Leaving Wet Bulb
1787 : Real64 HumRatSec; // Secondary leaving Humidity Ratio
1788 : Real64 EffHX; // Effectiveness of Secondary Heat Exchanger
1789 : Real64 QHX; // Q Across Sec HX
1790 : Real64 RhoWater;
1791 : Real64 RhoAir; // Density of the primary side air
1792 : Real64 CpAir; // Cp of the primary side air
1793 : Real64 CFMAir;
1794 : Real64 CFMSec;
1795 :
1796 38920 : auto &thisEvapCond(state.dataEvapCoolers->EvapCond(EvapCoolNum));
1797 :
1798 : // If the Evaporative Cooler is operating there should be some mass flow rate
1799 : // Also the evap cooler has to be scheduled to be available
1800 38920 : if ((thisEvapCond.InletMassFlowRate > 0.0) && (ScheduleManager::GetCurrentScheduleValue(state, thisEvapCond.SchedPtr) > 0.0)) {
1801 :
1802 18464 : PadDepth = thisEvapCond.IndirectPadDepth;
1803 : //******************************************************************************
1804 : // THIS SUBROUTINE WILL CACULATE THE TEMPERATURE OF THE LEAVING AIR DRY BULB
1805 : // FOR A DIRECT EVAPORATIVE AIR COOLER SUPPLIED WITH CFMAir,DIRPAD,TEWB,TEDB,
1806 : // AND PB (ATM. PRESS.) FOR AIR DENSITY CALCULATIONS.
1807 : //******************************************************************************
1808 :
1809 18464 : AirVel = thisEvapCond.IndirectVolFlowRate / thisEvapCond.IndirectPadArea;
1810 :
1811 : //******************************************************************************
1812 : // SAT EFF IS FOR DIFFERENT THICKNESS CELDEK PAD (CURVE FIT FROM DATA)
1813 : //******************************************************************************
1814 18464 : SatEff = 0.792714 + 0.958569 * PadDepth - 0.25193 * AirVel - 1.03215 * pow_2(PadDepth) + 2.62659e-2 * pow_2(AirVel) +
1815 18464 : 0.914869 * PadDepth * AirVel - 1.48241 * AirVel * pow_2(PadDepth) - 1.89919e-2 * pow_3(AirVel) * PadDepth +
1816 18464 : 1.13137 * pow_3(PadDepth) * AirVel + 3.27622e-2 * pow_3(AirVel) * pow_2(PadDepth) - 0.145384 * pow_3(PadDepth) * pow_2(AirVel);
1817 :
1818 18464 : if (SatEff >= 1.0) SatEff = 1.0;
1819 18464 : thisEvapCond.SatEff = SatEff;
1820 : //***************************************************************************
1821 : // TEMP LEAVING DRY BULB IS CALCULATED FROM SATURATION EFFICIENCY AS THE
1822 : // DRY BULB TEMP APPROACHES THE WET BULB TEMP ACROSS THE PAD BEFORE THE HX.
1823 : //***************************************************************************
1824 : //***** FIRST CHECK IF THIS TEWB IS A FEASIBLE POINT ON PSYCH CHART**********
1825 :
1826 : // BG Feb 2007 mods for oa node (eg. height-dependent outside air model)
1827 18464 : TWBSec = Psychrometrics::PsyTwbFnTdbWPb(state,
1828 : thisEvapCond.SecInletTemp,
1829 : thisEvapCond.SecInletHumRat,
1830 : thisEvapCond.SecInletPressure); // OutWetBulbTemp
1831 18464 : TDBSec = thisEvapCond.SecInletTemp - ((thisEvapCond.SecInletTemp - TWBSec) * SatEff);
1832 :
1833 18464 : HumRatSec = Psychrometrics::PsyWFnTdbTwbPb(state, TDBSec, TWBSec, thisEvapCond.SecInletPressure);
1834 :
1835 : //***************************************************************************
1836 : // CALCULATE THE TLDB FROM HX EQUATIONS GIVEN AN EFFICIENCY
1837 : //***************************************************************************
1838 18464 : EffHX = thisEvapCond.IndirectHXEffectiveness;
1839 18464 : CpAir = Psychrometrics::PsyCpAirFnW(thisEvapCond.InletHumRat);
1840 18464 : RhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisEvapCond.InletTemp, thisEvapCond.InletHumRat);
1841 18464 : CFMAir = thisEvapCond.VolFlowRate; // Volume Flow Rate Primary Side
1842 18464 : CFMSec = thisEvapCond.IndirectVolFlowRate; // Volume Flolw Rate Secondary Side
1843 :
1844 18464 : QHX = EffHX * min(CFMSec, CFMAir) * RhoAir * CpAir * (thisEvapCond.InletTemp - TDBSec);
1845 18464 : thisEvapCond.OutletTemp = thisEvapCond.InletTemp - QHX / (RhoAir * CFMAir * CpAir);
1846 : // This is a rough approximation of the Total Indirect Stage Efficiency for the Dry stage which
1847 : // is a 2 step process the first being teh pad efficiency and then the HX Effectiveness. I think that
1848 : // this would mainly be used for evap sizing purposes.
1849 18464 : thisEvapCond.StageEff = SatEff * EffHX;
1850 : //***************************************************************************
1851 : // CALCULATE THE WET BULB TEMP in the primary system air USING PSYCH ROUTINES
1852 : // There is a constant humidity ratio across the primary side but a reduction in the dry bulb temp
1853 18464 : thisEvapCond.OuletWetBulbTemp =
1854 18464 : Psychrometrics::PsyTwbFnTdbWPb(state, thisEvapCond.OutletTemp, thisEvapCond.InletHumRat, state.dataEnvrn->OutBaroPress);
1855 : //***************************************************************************
1856 : // TEMP LEAVING DRY BULB IS CALCULATED FROM SATURATION EFFICIENCY AS THE
1857 : // DRY BULB TEMP APPROACHES THE WET BULB TEMP. WET BULB TEMP IS CONSTANT
1858 : // ACROSS A DIRECT EVAPORATION COOLER.
1859 :
1860 18464 : thisEvapCond.OutletHumRat = thisEvapCond.InletHumRat;
1861 :
1862 18464 : thisEvapCond.OutletEnthalpy = Psychrometrics::PsyHFnTdbW(thisEvapCond.OutletTemp, thisEvapCond.OutletHumRat);
1863 :
1864 : //***************************************************************************
1865 : // POWER OF THE SECONDARY AIR FAN
1866 18464 : if (thisEvapCond.IndirectFanEff > 0.0) {
1867 18464 : thisEvapCond.EvapCoolerPower +=
1868 18464 : PartLoadRatio * thisEvapCond.IndirectFanDeltaPress * thisEvapCond.IndirectVolFlowRate / thisEvapCond.IndirectFanEff;
1869 : }
1870 :
1871 : // ENERGY CONSUMED BY THE RECIRCULATING PUMP
1872 : // ENERGY CONSUMED BY THE RECIRCULATING PUMP
1873 : // Add the pump energy to the total Evap Cooler energy comsumption
1874 18464 : thisEvapCond.EvapCoolerPower += PartLoadRatio * thisEvapCond.IndirectRecircPumpPower;
1875 :
1876 : //******************
1877 : // WATER CONSUMPTION IN m3 OF WATER FOR DIRECT
1878 : // H2O [m3/s] = Delta W[kgWater/kgDryAir]*Mass Flow Air[kgDryAir/s]
1879 : // /RhoWater [kgWater/m3]
1880 : //******************
1881 18464 : RhoWater = Psychrometrics::RhoH2O(TDBSec);
1882 18464 : RhoAir = (Psychrometrics::PsyRhoAirFnPbTdbW(state, thisEvapCond.SecInletPressure, thisEvapCond.SecInletTemp, thisEvapCond.SecInletHumRat) +
1883 18464 : Psychrometrics::PsyRhoAirFnPbTdbW(state, thisEvapCond.SecInletPressure, TDBSec, HumRatSec)) /
1884 : 2.0;
1885 18464 : thisEvapCond.EvapWaterConsumpRate =
1886 18464 : PartLoadRatio * (HumRatSec - thisEvapCond.SecInletHumRat) * thisEvapCond.IndirectVolFlowRate * RhoAir / RhoWater;
1887 : // A numerical check to keep from having very tiny negative water consumption values being reported
1888 18464 : if (thisEvapCond.EvapWaterConsumpRate < 0.0) thisEvapCond.EvapWaterConsumpRate = 0.0;
1889 :
1890 : } else {
1891 : // The evap cooler is not running and does not change conditions from inlet to outlet
1892 20456 : thisEvapCond.OutletTemp = thisEvapCond.InletTemp;
1893 :
1894 20456 : thisEvapCond.OuletWetBulbTemp = thisEvapCond.InletWetBulbTemp;
1895 :
1896 20456 : thisEvapCond.OutletHumRat = thisEvapCond.InletHumRat;
1897 :
1898 20456 : thisEvapCond.OutletEnthalpy = thisEvapCond.InletEnthalpy;
1899 :
1900 20456 : thisEvapCond.EvapCoolerEnergy = 0.0;
1901 :
1902 20456 : thisEvapCond.EvapWaterConsumpRate = 0.0;
1903 : }
1904 : // all of the mass flowrates are not changed across the evap cooler
1905 38920 : thisEvapCond.OutletMassFlowRate = thisEvapCond.InletMassFlowRate;
1906 38920 : thisEvapCond.OutletMassFlowRateMaxAvail = thisEvapCond.InletMassFlowRateMaxAvail;
1907 38920 : thisEvapCond.OutletMassFlowRateMinAvail = thisEvapCond.InletMassFlowRateMinAvail;
1908 :
1909 : // the pressure is not changed across the evap cooler
1910 38920 : thisEvapCond.OutletPressure = thisEvapCond.InletPressure;
1911 38920 : }
1912 :
1913 92337 : void CalcWetIndirectEvapCooler(EnergyPlusData &state, int EvapCoolNum, Real64 const PartLoadRatio)
1914 : {
1915 :
1916 : // SUBROUTINE INFORMATION:
1917 : // AUTHOR Richard J. Liesen
1918 : // DATE WRITTEN October 2000
1919 : // RE-ENGINEERED Jan. 2017, Rongpeng Zhang, added fouling fault for evaporative coolers
1920 :
1921 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1922 : Real64 StageEff; // Stage Efficiency of the Heat Exchanger
1923 : Real64 TEDB; // Entering Dry Bulb Temperature
1924 : Real64 TEWB; // Entering Wet Bulb Temperature
1925 : Real64 QHX; // Q Across Sec HX in Watts or J/sec
1926 : Real64 RhoWater;
1927 : Real64 RhoAir; // Density of the primary side air
1928 : Real64 CFMAir;
1929 : Real64 CFMSec;
1930 : Real64 TWBSec; // wet bulb of secondary air
1931 :
1932 92337 : auto &thisEvapCond(state.dataEvapCoolers->EvapCond(EvapCoolNum));
1933 :
1934 : // If the Evaporative Cooler is operating there should be some mass flow rate
1935 : // Also the evap cooler has to be scheduled to be available
1936 92337 : if ((thisEvapCond.InletMassFlowRate > 0.0) && (ScheduleManager::GetCurrentScheduleValue(state, thisEvapCond.SchedPtr) > 0.0)) {
1937 :
1938 : //******************************************************************************
1939 : // THIS SUBROUTINE WILL CACULATE THE TEMPERATURE OF THE LEAVING AIR DRY BULB
1940 : // FOR A WET COIL EVAPORATIVE COOLER
1941 : //******************************************************************************
1942 : // INDIRECT STAGE EFFICIENCY FOR WET COIL INDIRECT EVAP COOLERS
1943 56064 : CFMAir = thisEvapCond.VolFlowRate; // Volume Flow Rate Primary Side
1944 56064 : CFMSec = thisEvapCond.IndirectVolFlowRate; // Volume Flolw Rate Secondary Side
1945 :
1946 56064 : StageEff = thisEvapCond.WetCoilMaxEfficiency - min(thisEvapCond.WetCoilFlowRatio * CFMAir / CFMSec, thisEvapCond.WetCoilMaxEfficiency);
1947 :
1948 56064 : if (StageEff >= 1.0) StageEff = 1.0;
1949 : // This is a rough approximation of the Total Indirect Stage Efficiency. I think that
1950 : // this would mainly be used for evap sizing purposes.
1951 :
1952 : // If there is a fault of fouling
1953 57586 : if (thisEvapCond.FaultyEvapCoolerFoulingFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
1954 1522 : (!state.dataGlobal->KickOffSimulation)) {
1955 1522 : int FaultIndex = thisEvapCond.FaultyEvapCoolerFoulingIndex;
1956 1522 : Real64 StageEff_ff = StageEff;
1957 :
1958 : // calculate the Faulty Evaporative Cooler Fouling Factor using fault information
1959 1522 : thisEvapCond.FaultyEvapCoolerFoulingFactor = state.dataFaultsMgr->FaultsEvapCoolerFouling(FaultIndex).CalFoulingFactor(state);
1960 :
1961 : // update the StageEff at faulty cases
1962 1522 : StageEff = StageEff_ff * thisEvapCond.FaultyEvapCoolerFoulingFactor;
1963 : }
1964 :
1965 56064 : thisEvapCond.StageEff = StageEff;
1966 : //***************************************************************************
1967 : // TEMP LEAVING DRY BULB IS CALCULATED FROM A SIMPLE WET BULB APPROACH
1968 : // MODEL GIVEN THE INDIRECT STAGE EFFICIENCY.
1969 : // DRY BULB TEMP APPROACHES THE WET BULB TEMP ACROSS THE INDIRECT STAGE.
1970 : //***************************************************************************
1971 : // CALCULATE THE TLDB
1972 56064 : TEWB = thisEvapCond.InletWetBulbTemp;
1973 56064 : TEDB = thisEvapCond.InletTemp;
1974 56064 : TWBSec = Psychrometrics::PsyTwbFnTdbWPb(state, thisEvapCond.SecInletTemp, thisEvapCond.SecInletHumRat, thisEvapCond.SecInletPressure);
1975 56064 : thisEvapCond.OutletTemp = TEDB - StageEff * (TEDB - TWBSec);
1976 :
1977 : //***************************************************************************
1978 : // CALCULATE THE WET BULB TEMP in the primary system air using PSYCH ROUTINES
1979 : // There is a constant humidity ratio across the primary side but a reduction in the dry bulb temp
1980 56064 : thisEvapCond.OuletWetBulbTemp =
1981 56064 : Psychrometrics::PsyTwbFnTdbWPb(state, thisEvapCond.OutletTemp, thisEvapCond.InletHumRat, state.dataEnvrn->OutBaroPress);
1982 : //***************************************************************************
1983 : // CALCULATE other outlet properties using PSYCH ROUTINES
1984 56064 : thisEvapCond.OutletHumRat = thisEvapCond.InletHumRat;
1985 :
1986 56064 : thisEvapCond.OutletEnthalpy = Psychrometrics::PsyHFnTdbW(thisEvapCond.OutletTemp, thisEvapCond.OutletHumRat);
1987 :
1988 : //***************************************************************************
1989 : // Real64 FlowFraction = 1.0;
1990 : // Real64 MassFlowRateMax = Node(thisEvapCond.InletNode).MassFlowRateMax;
1991 : // if (MassFlowRateMax > 0) {
1992 : // FlowFraction = thisEvapCond.InletMassFlowRate / MassFlowRateMax;
1993 : //}
1994 : // POWER OF THE SECONDARY AIR FAN
1995 56064 : if (thisEvapCond.IndirectFanEff > 0.0) {
1996 56064 : thisEvapCond.EvapCoolerPower +=
1997 56064 : PartLoadRatio * thisEvapCond.IndirectFanDeltaPress * thisEvapCond.IndirectVolFlowRate / thisEvapCond.IndirectFanEff;
1998 : }
1999 :
2000 : // ENERGY CONSUMED BY THE RECIRCULATING PUMP
2001 : // ENERGY CONSUMED BY THE RECIRCULATING PUMP
2002 : // Add the pump energy to the total Evap Cooler energy comsumption
2003 56064 : thisEvapCond.EvapCoolerPower += PartLoadRatio * thisEvapCond.IndirectRecircPumpPower;
2004 :
2005 : //******************
2006 : // WATER CONSUMPTION IN m3 OF WATER FOR Wet InDIRECT
2007 : // H2O [m3/s] = (QHX [J/s])/(2,500,000 [J/kgWater] * RhoWater [kgWater/m3])
2008 : //******************
2009 : //***** FIRST calculate the heat exchange on the primary air side**********
2010 56064 : RhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisEvapCond.InletTemp, thisEvapCond.InletHumRat);
2011 56064 : QHX = PartLoadRatio * CFMAir * RhoAir * (thisEvapCond.InletEnthalpy - thisEvapCond.OutletEnthalpy);
2012 :
2013 56064 : RhoWater = Psychrometrics::RhoH2O(thisEvapCond.SecInletTemp);
2014 56064 : thisEvapCond.EvapWaterConsumpRate = (QHX / StageEff) / (2500000.0 * RhoWater);
2015 : // A numerical check to keep from having very tiny negative water consumption values being reported
2016 56064 : if (thisEvapCond.EvapWaterConsumpRate < 0.0) thisEvapCond.EvapWaterConsumpRate = 0.0;
2017 :
2018 : } else {
2019 : // The evap cooler is not running and does not change conditions from inlet to outlet
2020 36273 : thisEvapCond.OutletTemp = thisEvapCond.InletTemp;
2021 :
2022 36273 : thisEvapCond.OuletWetBulbTemp = thisEvapCond.InletWetBulbTemp;
2023 :
2024 36273 : thisEvapCond.OutletHumRat = thisEvapCond.InletHumRat;
2025 :
2026 36273 : thisEvapCond.OutletEnthalpy = thisEvapCond.InletEnthalpy;
2027 :
2028 36273 : thisEvapCond.EvapCoolerEnergy = 0.0;
2029 :
2030 36273 : thisEvapCond.EvapWaterConsumpRate = 0.0;
2031 : }
2032 : // all of the mass flowrates are not changed across the evap cooler
2033 92337 : thisEvapCond.OutletMassFlowRate = thisEvapCond.InletMassFlowRate;
2034 92337 : thisEvapCond.OutletMassFlowRateMaxAvail = thisEvapCond.InletMassFlowRateMaxAvail;
2035 92337 : thisEvapCond.OutletMassFlowRateMinAvail = thisEvapCond.InletMassFlowRateMinAvail;
2036 :
2037 : // the pressure is not changed across the evap cooler
2038 92337 : thisEvapCond.OutletPressure = thisEvapCond.InletPressure;
2039 92337 : }
2040 :
2041 2573067 : void CalcResearchSpecialPartLoad(EnergyPlusData &state, int EvapCoolNum)
2042 : {
2043 : // SUBROUTINE INFORMATION:
2044 : // AUTHOR B. Griffith
2045 : // DATE WRITTEN July 2003
2046 :
2047 : // REFERENCES:
2048 : // copied CalcWetIndirectEvapCooler as template for new cooler
2049 :
2050 2573067 : Real64 constexpr MinAirMassFlow(0.001);
2051 :
2052 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2053 2573067 : Real64 FullOutput = 0.0;
2054 2573067 : Real64 ReqOutput = 0.0;
2055 : // Set local variables
2056 :
2057 2573067 : auto &thisEvapCond = state.dataEvapCoolers->EvapCond(EvapCoolNum);
2058 :
2059 : // Retrieve the load on the controlled zone
2060 2573067 : int OutletNode = thisEvapCond.OutletNode;
2061 2573067 : int InletNode = thisEvapCond.InletNode;
2062 2573067 : int ControlNode = thisEvapCond.EvapControlNodeNum;
2063 2573067 : Real64 DesOutTemp = thisEvapCond.DesiredOutletTemp;
2064 2573067 : Real64 PartLoadFrac = 0.0;
2065 :
2066 : // If Evap Cooler runs with a cooling load then set PartLoadFrac on Cooling System and the Mass Flow
2067 2573067 : if ((ScheduleManager::GetCurrentScheduleValue(state, thisEvapCond.SchedPtr) > 0.0) &&
2068 2555247 : (state.dataLoopNodes->Node(InletNode).MassFlowRate > MinAirMassFlow) &&
2069 7492867 : (state.dataLoopNodes->Node(InletNode).Temp > state.dataLoopNodes->Node(ControlNode).TempSetPoint) &&
2070 2364553 : (std::abs(state.dataLoopNodes->Node(InletNode).Temp - DesOutTemp) > HVAC::TempControlTol)) {
2071 :
2072 : // Get full load result, depending on model
2073 2340695 : thisEvapCond.PartLoadFract = 1.0;
2074 2340695 : switch (thisEvapCond.evapCoolerType) {
2075 1034457 : case EvapCoolerType::IndirectRDDSpecial: {
2076 1034457 : CalcIndirectResearchSpecialEvapCooler(state, EvapCoolNum);
2077 1034457 : UpdateEvapCooler(state, EvapCoolNum);
2078 1034457 : FullOutput = state.dataLoopNodes->Node(InletNode).MassFlowRate *
2079 1034457 : (Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat) -
2080 1034457 : Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat));
2081 :
2082 1034457 : ReqOutput = state.dataLoopNodes->Node(InletNode).MassFlowRate *
2083 1034457 : (Psychrometrics::PsyHFnTdbW(thisEvapCond.DesiredOutletTemp, state.dataLoopNodes->Node(InletNode).HumRat) -
2084 1034457 : Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat));
2085 :
2086 : // now reinit after test call
2087 1034457 : InitEvapCooler(state, EvapCoolNum);
2088 :
2089 1034457 : } break;
2090 1306238 : case EvapCoolerType::DirectResearchSpecial: {
2091 1306238 : CalcDirectResearchSpecialEvapCooler(state, EvapCoolNum);
2092 1306238 : UpdateEvapCooler(state, EvapCoolNum);
2093 1306238 : FullOutput = state.dataLoopNodes->Node(OutletNode).Temp - state.dataLoopNodes->Node(InletNode).Temp;
2094 1306238 : ReqOutput = thisEvapCond.DesiredOutletTemp - state.dataLoopNodes->Node(InletNode).Temp;
2095 :
2096 : // now reinit after test call
2097 1306238 : InitEvapCooler(state, EvapCoolNum);
2098 :
2099 1306238 : } break;
2100 0 : default: {
2101 0 : assert(false);
2102 : } break;
2103 : }
2104 :
2105 : // Since we are cooling, we expect FullOutput to be < 0 and FullOutput < NoCoolOutput
2106 : // Check that this is the case; if not set PartLoadFrac = 0.0 (off) and return
2107 : // Calculate the part load fraction
2108 2340695 : if (FullOutput == 0.0) {
2109 8982 : FullOutput = 0.00001;
2110 : }
2111 2340695 : PartLoadFrac = ReqOutput / FullOutput;
2112 2340695 : if (PartLoadFrac > 1.0) {
2113 2290790 : PartLoadFrac = 1.0;
2114 49905 : } else if (PartLoadFrac < 0.0) {
2115 8984 : PartLoadFrac = 0.0;
2116 : }
2117 :
2118 : } else { // No cooling
2119 232372 : PartLoadFrac = 0.0;
2120 :
2121 : } // End of the cooler running If block
2122 : // Set the final results
2123 2573067 : thisEvapCond.PartLoadFract = PartLoadFrac;
2124 2573067 : }
2125 :
2126 2190906 : void CalcIndirectResearchSpecialEvapCooler(EnergyPlusData &state, int const EvapCoolNum, Real64 const FanPLR)
2127 : {
2128 :
2129 : // SUBROUTINE INFORMATION:
2130 : // AUTHOR B. Griffith
2131 : // DATE WRITTEN July 2003
2132 : // RE-ENGINEERED October 2014, B Nigusse, added dry and wet operating modes
2133 : // and secondary air flow control
2134 :
2135 : // PURPOSE OF THIS SUBROUTINE:
2136 : // Subroutine models a "special" cooler that allows high effectiveness and controls
2137 :
2138 : // REFERENCES:
2139 : // copied CalcWetIndirectEvapCooler as template for new cooler
2140 :
2141 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2142 : Real64 SecondaryInletDryBulbTemp; // entering drybulb for secondary/purge side
2143 : Real64 SecondaryInletWetBulbTemp; // entering wet bulb for secondary/purge side
2144 : Real64 SecondaryInletDewPointTemp; // entering dewpoint for secondary/purge side
2145 : Real64 SecondaryInletHumRatio; // entering humidity ratio for secondary/purge side
2146 : Real64 StageEff; // Stage Efficiency of the Heat Exchanger
2147 : Real64 TEDB; // Entering Dry Bulb Temperature
2148 : Real64 TEWB; // Entering Wet Bulb Temperature
2149 : Real64 QHX; // Q Across Sec HX in Watts or J/sec
2150 : Real64 RhoWater;
2151 : Real64 RhoAir; // Density of the primary side air
2152 : Real64 CFMAir;
2153 : Real64 BoundTemp; // temperature limit for outlet
2154 : Real64 PartLoad;
2155 : Real64 TotalVolFlow;
2156 : Real64 TertMdot;
2157 : Real64 TertHumRate;
2158 : Real64 TertTemp;
2159 : Real64 TertRho;
2160 : Real64 TertVdot;
2161 : Real64 SecVdot;
2162 : Real64 SecRho;
2163 : Real64 SecMdot;
2164 : Real64 PurgeMdot;
2165 : Real64 PurgeHumRat;
2166 : Real64 PurgeEnthalpy;
2167 : Real64 PurgeTemp;
2168 2190906 : Real64 BlowDownVdot(0.0);
2169 2190906 : Real64 DriftVdot(0.0);
2170 2190906 : Real64 EvapVdot(0.0);
2171 :
2172 2190906 : auto &thisEvapCond(state.dataEvapCoolers->EvapCond(EvapCoolNum));
2173 :
2174 : // If the Evaporative Cooler is operating there should be some mass flow rate
2175 : // Also the evap cooler has to be scheduled to be available
2176 2190906 : if ((thisEvapCond.InletMassFlowRate > 0.0) && (ScheduleManager::GetCurrentScheduleValue(state, thisEvapCond.SchedPtr) > 0.0)) {
2177 :
2178 : //******************************************************************************
2179 : // THIS SUBROUTINE WILL CACULATE THE TEMPERATURE OF THE LEAVING AIR DRY BULB
2180 : // FOR A WET COIL EVAPORATIVE COOLER
2181 : //******************************************************************************
2182 : // INDIRECT STAGE EFFICIENCY FOR WET COIL INDIRECT EVAP COOLERS
2183 2143688 : CFMAir = thisEvapCond.VolFlowRate; // Volume Flow Rate Primary Side
2184 2143688 : StageEff = thisEvapCond.WetCoilMaxEfficiency;
2185 :
2186 : // This is model is for special indirect cooler with efficiency greater than 1.0
2187 2143688 : if (StageEff >= 1.5) StageEff = 1.5;
2188 :
2189 2143688 : thisEvapCond.StageEff = StageEff;
2190 :
2191 : //***********************************************
2192 : // Unit is allowed to mix relief air that would otherwise be exhausted outdoors for ventilation
2193 : // If tertiary node is set >0 then it assumed that this node is the exhaust out of the building
2194 : // and the remainder will be made up with outside air from the secondary node
2195 : //*********************************************
2196 :
2197 2143688 : int TertNode = thisEvapCond.TertiaryInletNode;
2198 2143688 : if (TertNode == 0) {
2199 2086461 : SecondaryInletDryBulbTemp = thisEvapCond.SecInletTemp;
2200 : SecondaryInletWetBulbTemp =
2201 2086461 : Psychrometrics::PsyTwbFnTdbWPb(state, thisEvapCond.SecInletTemp, thisEvapCond.SecInletHumRat, state.dataEnvrn->OutBaroPress);
2202 : SecondaryInletDewPointTemp =
2203 2086461 : Psychrometrics::PsyTdpFnTdbTwbPb(state, thisEvapCond.SecInletTemp, SecondaryInletWetBulbTemp, state.dataEnvrn->OutBaroPress);
2204 2086461 : SecondaryInletHumRatio = thisEvapCond.SecInletHumRat;
2205 :
2206 : } else {
2207 :
2208 57227 : TotalVolFlow = thisEvapCond.IndirectVolFlowRate;
2209 57227 : TertMdot = state.dataLoopNodes->Node(TertNode).MassFlowRate;
2210 57227 : TertHumRate = state.dataLoopNodes->Node(TertNode).HumRat;
2211 57227 : TertTemp = state.dataLoopNodes->Node(TertNode).Temp;
2212 : // is Node pressure available or better? using outdoor pressure for now
2213 57227 : TertRho = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, TertTemp, TertHumRate);
2214 57227 : TertVdot = TertMdot / TertRho;
2215 :
2216 57227 : SecVdot = TotalVolFlow - TertVdot;
2217 :
2218 57227 : if (SecVdot < 0.0) { // all tertiary/releif air e.g. econonizer wide open
2219 0 : SecVdot = 0.0;
2220 0 : SecondaryInletDryBulbTemp = TertTemp;
2221 0 : SecondaryInletWetBulbTemp = Psychrometrics::PsyTwbFnTdbWPb(state, TertTemp, TertHumRate, state.dataEnvrn->OutBaroPress);
2222 : SecondaryInletDewPointTemp =
2223 0 : Psychrometrics::PsyTdpFnTdbTwbPb(state, TertTemp, SecondaryInletWetBulbTemp, state.dataEnvrn->OutBaroPress);
2224 0 : SecondaryInletHumRatio = TertHumRate;
2225 : } else {
2226 :
2227 : // First determine mass flow of OA, in secondary
2228 : SecRho =
2229 57227 : Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisEvapCond.SecInletTemp, thisEvapCond.SecInletHumRat);
2230 57227 : SecMdot = SecRho * SecVdot;
2231 : // Mass balance on moisture to get outlet air humidity ratio
2232 : // this mixing takes place before wet media.
2233 57227 : PurgeMdot = SecMdot + TertMdot;
2234 57227 : PurgeHumRat = (SecMdot * thisEvapCond.SecInletHumRat + TertMdot * TertHumRate) / PurgeMdot;
2235 :
2236 : // Energy balance to get outlet air enthalpy
2237 :
2238 57227 : PurgeEnthalpy = (SecMdot * Psychrometrics::PsyHFnTdbW(thisEvapCond.SecInletTemp, thisEvapCond.SecInletHumRat) +
2239 57227 : TertMdot * Psychrometrics::PsyHFnTdbW(TertTemp, TertHumRate)) /
2240 : PurgeMdot;
2241 :
2242 : // Use Enthalpy and humidity ratio to get outlet temperature from psych chart
2243 :
2244 57227 : PurgeTemp = Psychrometrics::PsyTdbFnHW(PurgeEnthalpy, PurgeHumRat);
2245 57227 : SecondaryInletDryBulbTemp = PurgeTemp;
2246 57227 : SecondaryInletWetBulbTemp = Psychrometrics::PsyTwbFnTdbWPb(state, PurgeTemp, PurgeHumRat, state.dataEnvrn->OutBaroPress);
2247 : SecondaryInletDewPointTemp =
2248 57227 : Psychrometrics::PsyTdpFnTdbTwbPb(state, PurgeTemp, SecondaryInletWetBulbTemp, state.dataEnvrn->OutBaroPress);
2249 57227 : SecondaryInletHumRatio = PurgeHumRat;
2250 : }
2251 : }
2252 2143688 : if (thisEvapCond.EvapCoolerOperationControlFlag) {
2253 : // addvanced mode: runs either in dry or wet depending on the entering conditions
2254 34302 : CalcIndirectResearchSpecialEvapCoolerAdvanced(
2255 : state, EvapCoolNum, SecondaryInletDryBulbTemp, SecondaryInletWetBulbTemp, SecondaryInletDewPointTemp, SecondaryInletHumRatio);
2256 :
2257 : } else {
2258 :
2259 2109386 : TEWB = thisEvapCond.InletWetBulbTemp;
2260 2109386 : TEDB = thisEvapCond.InletTemp;
2261 2109386 : PartLoad = thisEvapCond.PartLoadFract;
2262 :
2263 : //***************************************************************************
2264 : // TEMP LEAVING DRY BULB IS CALCULATED FROM A SIMPLE WET BULB APPROACH
2265 : // MODEL GIVEN THE INDIRECT STAGE EFFICIENCY.
2266 : // DRY BULB TEMP APPROACHES THE WET BULB TEMP ACROSS THE INDIRECT STAGE.
2267 : //***************************************************************************
2268 2109386 : if (PartLoad == 1.0) {
2269 : // Tout = Tin - ( 0.7 (Tin - Tpurge,wb,in)
2270 2014804 : thisEvapCond.OutletTemp = TEDB - StageEff * (TEDB - SecondaryInletWetBulbTemp);
2271 : // now bound with secondary dewpoint.
2272 : // unless the resulting Tout<=Tpurge,dp,in ; in which case Tout = Tin - 0.9(Tin-Tpurge,dp,in)
2273 :
2274 2014804 : BoundTemp = TEDB - thisEvapCond.DPBoundFactor * (TEDB - SecondaryInletDewPointTemp);
2275 2014804 : if (thisEvapCond.OutletTemp < BoundTemp) {
2276 1329 : thisEvapCond.OutletTemp = BoundTemp;
2277 1329 : thisEvapCond.DewPointBoundFlag = 1;
2278 : }
2279 94582 : } else if ((PartLoad < 1.0) && (PartLoad > 0.0)) {
2280 : // assume perfect control Use PLF for energy consumption
2281 36240 : if (thisEvapCond.DesiredOutletTemp < TEDB) {
2282 36239 : thisEvapCond.OutletTemp = thisEvapCond.DesiredOutletTemp;
2283 : }
2284 : } else {
2285 : // part load set to zero so no cooling
2286 58342 : thisEvapCond.OutletTemp = thisEvapCond.InletTemp;
2287 : }
2288 :
2289 : //***************************************************************************
2290 : // POWER OF THE SECONDARY AIR FAN with part load factor applied (assumes const efficiency)
2291 2109386 : thisEvapCond.EvapCoolerPower += thisEvapCond.IndirectVolFlowRate * thisEvapCond.FanSizingSpecificPower * PartLoad * FanPLR;
2292 :
2293 : // ENERGY CONSUMED BY THE RECIRCULATING PUMP
2294 : // ENERGY CONSUMED BY THE RECIRCULATING PUMP
2295 : // Add the pump energy to the total Evap Cooler energy comsumption
2296 2109386 : thisEvapCond.EvapCoolerPower += thisEvapCond.IndirectRecircPumpPower * PartLoad * FanPLR;
2297 :
2298 : //***************************************************************************
2299 : // CALCULATE THE WET BULB TEMP in the primary system air using PSYCH ROUTINES
2300 : // There is a constant humidity ratio across the primary side but a reduction in the dry bulb temp
2301 2109386 : thisEvapCond.OuletWetBulbTemp =
2302 2109386 : Psychrometrics::PsyTwbFnTdbWPb(state, thisEvapCond.OutletTemp, thisEvapCond.InletHumRat, state.dataEnvrn->OutBaroPress);
2303 : //***************************************************************************
2304 : // CALCULATE other outlet propertiesusing PSYCH ROUTINES
2305 2109386 : thisEvapCond.OutletHumRat = thisEvapCond.InletHumRat;
2306 :
2307 2109386 : thisEvapCond.OutletEnthalpy = Psychrometrics::PsyHFnTdbW(thisEvapCond.OutletTemp, thisEvapCond.OutletHumRat);
2308 : //******************
2309 : // WATER CONSUMPTION IN m3 OF WATER FOR Wet InDIRECT
2310 : // H2O [m3/s] = (QHX [J/s])/(2,500,000 [J/kgWater] * RhoWater [kgWater/m3])
2311 : //******************
2312 : //***** FIRST calculate the heat exchange on the primary air side**********
2313 2109386 : RhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisEvapCond.InletTemp, thisEvapCond.InletHumRat);
2314 2109386 : QHX = CFMAir * RhoAir * (thisEvapCond.InletEnthalpy - thisEvapCond.OutletEnthalpy);
2315 :
2316 2109386 : RhoWater = Psychrometrics::RhoH2O(state.dataEnvrn->OutDryBulbTemp);
2317 2109386 : EvapVdot = (QHX) / (2500000.0 * RhoWater);
2318 2109386 : DriftVdot = EvapVdot * thisEvapCond.DriftFraction;
2319 2109386 : if (thisEvapCond.BlowDownRatio > 0.0) {
2320 723624 : BlowDownVdot = EvapVdot / (thisEvapCond.BlowDownRatio - 1) - DriftVdot;
2321 723624 : if (BlowDownVdot < 0.0) BlowDownVdot = 0.0;
2322 : } else {
2323 1385762 : BlowDownVdot = 0.0;
2324 : }
2325 2109386 : thisEvapCond.EvapWaterConsumpRate = EvapVdot + DriftVdot + BlowDownVdot;
2326 : // A numerical check to keep from having very tiny negative water consumption values being reported
2327 2109386 : if (thisEvapCond.EvapWaterConsumpRate < 0.0) thisEvapCond.EvapWaterConsumpRate = 0.0;
2328 : }
2329 :
2330 : } else {
2331 : // The evap cooler is not running and does not change conditions from inlet to outlet
2332 47218 : thisEvapCond.OutletTemp = thisEvapCond.InletTemp;
2333 47218 : thisEvapCond.OuletWetBulbTemp = thisEvapCond.InletWetBulbTemp;
2334 47218 : thisEvapCond.OutletHumRat = thisEvapCond.InletHumRat;
2335 47218 : thisEvapCond.OutletEnthalpy = thisEvapCond.InletEnthalpy;
2336 47218 : thisEvapCond.EvapCoolerEnergy = 0.0;
2337 47218 : thisEvapCond.EvapCoolerPower = 0.0;
2338 47218 : thisEvapCond.EvapWaterConsumpRate = 0.0;
2339 47218 : thisEvapCond.SecInletMassFlowRate = 0.0;
2340 : }
2341 :
2342 : // all of the mass flowrates are not changed across the evap cooler
2343 2190906 : thisEvapCond.OutletMassFlowRate = thisEvapCond.InletMassFlowRate;
2344 2190906 : thisEvapCond.OutletMassFlowRateMaxAvail = thisEvapCond.InletMassFlowRateMaxAvail;
2345 2190906 : thisEvapCond.OutletMassFlowRateMinAvail = thisEvapCond.InletMassFlowRateMinAvail;
2346 : // set secondary air side inlet mass flow rate to the outlet node
2347 2190906 : thisEvapCond.SecOutletMassFlowRate = thisEvapCond.SecInletMassFlowRate;
2348 2190906 : state.dataLoopNodes->Node(thisEvapCond.SecondaryInletNode).MassFlowRate = thisEvapCond.SecInletMassFlowRate;
2349 :
2350 : // the pressure is not changed across the evap cooler
2351 2190906 : thisEvapCond.OutletPressure = thisEvapCond.InletPressure;
2352 2190906 : }
2353 :
2354 34302 : void CalcIndirectResearchSpecialEvapCoolerAdvanced(EnergyPlusData &state,
2355 : int const EvapCoolNum,
2356 : Real64 const InletDryBulbTempSec,
2357 : Real64 const InletWetBulbTempSec,
2358 : Real64 const InletDewPointTempSec,
2359 : Real64 const InletHumRatioSec)
2360 : {
2361 :
2362 : // SUBROUTINE INFORMATION:
2363 : // AUTHOR B. Bigusse
2364 : // DATE WRITTEN October 2014
2365 :
2366 : // PURPOSE OF THIS SUBROUTINE:
2367 : // Subroutine models indirect evaporative cooler with variable effectiveness for wet and dry
2368 : // operating modes depending on entering conditions
2369 :
2370 : // SUBROUTINE PARAMETER DEFINITIONS:
2371 34302 : int constexpr MaxIte(500); // Maximum number of iterations for solver
2372 34302 : Real64 constexpr TempTol(0.01); // convergence tollerance
2373 :
2374 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2375 : Real64 BoundTemp; // temperature limit for outlet
2376 : Real64 PartLoad;
2377 : Real64 TdbOutSysWetMin; // system( primary ) air drybulb outlet temperature minimum based on wet coil
2378 : Real64 TdbOutSysDryMin; // system (primary) air drybulb outlet temperature minimum based on dry coil
2379 : Real64 AirMassFlowSec; // current secondary air mass flow rate
2380 : Real64 AirMassFlowSecDry; // current secondary air mass flow rate in dry mode
2381 : Real64 AirMassFlowSecWet; // current secondary air mass flow rate in wet mode
2382 : Real64 FlowRatioSec; // secondary air flow ratio in dry and wet mode
2383 : Real64 EvapCoolerTotalElectricPowerDry; // evaporative cooler current total electric power drawn
2384 : Real64 EvapCoolerTotalElectricPowerWet; // evaporative cooler current total electric power drawn
2385 : Real64 QHXLatent; // evaporative cooler latent heat transfer rate
2386 : Real64 hfg; // latent heat of vaporization of water at the secondary air inlet condition
2387 :
2388 : Real64 QHX; // Q Across Sec HX in Watts or J/sec
2389 : Real64 RhoWater;
2390 : Real64 RhoAir; // Density of the primary side air
2391 : Real64 MassFlowRateSecMin;
2392 34302 : Real64 BlowDownVdot(0.0);
2393 34302 : Real64 DriftVdot(0.0);
2394 34302 : Real64 EvapVdot(0.0);
2395 :
2396 34302 : auto &thisEvapCond(state.dataEvapCoolers->EvapCond(EvapCoolNum));
2397 :
2398 34302 : Real64 FlowRatioSecDry = 0.0; // current secondary air mass flow ratio in dry mode
2399 34302 : Real64 FlowRatioSecWet = 0.0; // current secondary air mass flow ratio in wet mode
2400 34302 : thisEvapCond.EvapCoolerRDDOperatingMode = OperatingMode::None;
2401 34302 : Real64 TEDB = thisEvapCond.InletTemp; // Entering Dry Bulb Temperature
2402 34302 : Real64 SysTempSetPoint = thisEvapCond.DesiredOutletTemp; // evaporative cooler outlet setpoint temperature, drybulb
2403 34302 : Real64 SecRho = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, InletDryBulbTempSec, InletHumRatioSec);
2404 34302 : Real64 MassFlowRateSecMax = SecRho * thisEvapCond.IndirectVolFlowRate; // Design secondary air mass flow rate
2405 34302 : CalcIndirectRDDEvapCoolerOutletTemp(
2406 : state, EvapCoolNum, OperatingMode::WetFull, MassFlowRateSecMax, InletDryBulbTempSec, InletWetBulbTempSec, InletHumRatioSec);
2407 34302 : TdbOutSysWetMin = thisEvapCond.OutletTemp;
2408 34302 : CalcIndirectRDDEvapCoolerOutletTemp(
2409 : state, EvapCoolNum, OperatingMode::DryFull, MassFlowRateSecMax, InletDryBulbTempSec, InletWetBulbTempSec, InletHumRatioSec);
2410 34302 : TdbOutSysDryMin = thisEvapCond.OutletTemp;
2411 :
2412 : // get current operating modes of indirect evaporative cooler research special
2413 34302 : thisEvapCond.EvapCoolerRDDOperatingMode = IndirectResearchSpecialEvapCoolerOperatingMode(
2414 : state, EvapCoolNum, InletDryBulbTempSec, InletWetBulbTempSec, TdbOutSysWetMin, TdbOutSysDryMin);
2415 :
2416 34302 : MassFlowRateSecMin = 0.0;
2417 34302 : AirMassFlowSec = MassFlowRateSecMax;
2418 34302 : PartLoad = thisEvapCond.PartLoadFract;
2419 : {
2420 34302 : if (thisEvapCond.EvapCoolerRDDOperatingMode == OperatingMode::DryModulated) {
2421 188536 : auto f = [&state, EvapCoolNum, SysTempSetPoint, InletDryBulbTempSec, InletWetBulbTempSec, InletHumRatioSec](Real64 AirMassFlowSec) {
2422 47134 : auto &EvapCond(state.dataEvapCoolers->EvapCond(EvapCoolNum));
2423 47134 : EvapCond.SecInletMassFlowRate = AirMassFlowSec;
2424 47134 : CalcIndirectRDDEvapCoolerOutletTemp(
2425 : state, EvapCoolNum, OperatingMode::DryModulated, AirMassFlowSec, InletDryBulbTempSec, InletWetBulbTempSec, InletHumRatioSec);
2426 47134 : Real64 const OutletAirTemp = EvapCond.OutletTemp; // evap Coler outlet air temperature
2427 47134 : return SysTempSetPoint - OutletAirTemp;
2428 13226 : };
2429 13226 : int SolFla = 0; // Flag of solver
2430 13226 : General::SolveRoot(state, TempTol, MaxIte, SolFla, AirMassFlowSec, f, MassFlowRateSecMin, MassFlowRateSecMax);
2431 : // if the numerical inversion failed, issue error messages.
2432 13226 : if (SolFla == -1) {
2433 0 : if (!state.dataGlobal->WarmupFlag) {
2434 0 : if (thisEvapCond.IterationLimit == 0) {
2435 0 : ShowSevereError(state,
2436 0 : format("CalcIndirectResearchSpecialEvapCooler: calculate secondary air mass flow failed for Indirect "
2437 : "Evaporative Cooler Research Special = {}",
2438 0 : thisEvapCond.Name));
2439 0 : ShowContinueErrorTimeStamp(state, "");
2440 0 : ShowContinueError(state, format(" Iteration limit [{}] exceeded in calculating secondary air mass flow rate", MaxIte));
2441 0 : ShowContinueError(state, " Simulation continues");
2442 : }
2443 0 : ShowRecurringWarningErrorAtEnd(
2444 : state,
2445 0 : "Secondary air mass flow Iteration limit exceeded in Indirect Evaporative Cooler Research Special = " + thisEvapCond.Name,
2446 0 : thisEvapCond.IterationLimit);
2447 : }
2448 13226 : } else if (SolFla == -2) {
2449 0 : if (!state.dataGlobal->WarmupFlag) {
2450 0 : if (thisEvapCond.IterationFailed == 0) {
2451 0 : ShowSevereError(state,
2452 0 : format("CalcIndirectResearchSpecialEvapCooler: calculate secondary air mass flow failed for Indirect "
2453 : "Evaporative Cooler Research Special = {}",
2454 0 : thisEvapCond.Name));
2455 0 : ShowContinueErrorTimeStamp(state, "");
2456 0 : ShowContinueError(state, "...Bad secondary air mass flow rate limits");
2457 0 : ShowContinueError(state, format("...Given minimum secondary air mass flow rate={:.3R} kg/s", MassFlowRateSecMin));
2458 0 : ShowContinueError(state, format("...Given maximum secondary air mass flow rate={:.3R} kg/s", MassFlowRateSecMax));
2459 0 : ShowContinueError(state, " Simulation continues");
2460 : }
2461 0 : ShowRecurringWarningErrorAtEnd(state,
2462 0 : "Secondary air mass flow control failed in Indirect Evaporative Cooler Research Special = " +
2463 0 : thisEvapCond.Name,
2464 0 : thisEvapCond.IterationFailed);
2465 : }
2466 : }
2467 13226 : thisEvapCond.SecInletMassFlowRate = AirMassFlowSec;
2468 13226 : if (AirMassFlowSec > 0.0) {
2469 13226 : if (MassFlowRateSecMax > 0.0) {
2470 13226 : FlowRatioSec = AirMassFlowSec / MassFlowRateSecMax;
2471 : } else {
2472 0 : FlowRatioSec = 0.0;
2473 : }
2474 : } else {
2475 0 : FlowRatioSec = 0.0;
2476 : }
2477 13226 : thisEvapCond.EvapCoolerPower = IndEvapCoolerPower(state, EvapCoolNum, OperatingMode::DryModulated, FlowRatioSec);
2478 13226 : thisEvapCond.IECOperatingStatus = 1;
2479 21076 : } else if (thisEvapCond.EvapCoolerRDDOperatingMode == OperatingMode::DryFull) {
2480 8 : CalcIndirectRDDEvapCoolerOutletTemp(
2481 : state, EvapCoolNum, OperatingMode::DryFull, MassFlowRateSecMax, InletDryBulbTempSec, InletWetBulbTempSec, InletHumRatioSec);
2482 8 : thisEvapCond.SecInletMassFlowRate = MassFlowRateSecMax;
2483 8 : FlowRatioSec = 1.0;
2484 8 : thisEvapCond.EvapCoolerPower = IndEvapCoolerPower(state, EvapCoolNum, OperatingMode::DryFull, FlowRatioSec);
2485 8 : thisEvapCond.IECOperatingStatus = 1;
2486 21068 : } else if (thisEvapCond.EvapCoolerRDDOperatingMode == OperatingMode::DryWetModulated) {
2487 0 : auto f = [&state, EvapCoolNum, SysTempSetPoint, InletDryBulbTempSec, InletWetBulbTempSec, InletHumRatioSec](Real64 AirMassFlowSec) {
2488 0 : auto &EvapCond(state.dataEvapCoolers->EvapCond(EvapCoolNum));
2489 0 : EvapCond.SecInletMassFlowRate = AirMassFlowSec;
2490 0 : CalcIndirectRDDEvapCoolerOutletTemp(
2491 : state, EvapCoolNum, OperatingMode::DryModulated, AirMassFlowSec, InletDryBulbTempSec, InletWetBulbTempSec, InletHumRatioSec);
2492 0 : Real64 const OutletAirTemp = EvapCond.OutletTemp; // evap Coler outlet air temperature
2493 0 : return SysTempSetPoint - OutletAirTemp;
2494 0 : };
2495 0 : int SolFla = 0; // Flag of solver
2496 0 : General::SolveRoot(state, TempTol, MaxIte, SolFla, AirMassFlowSec, f, MassFlowRateSecMin, MassFlowRateSecMax);
2497 : // if the numerical inversion failed, issue error messages.
2498 0 : if (SolFla == -1) {
2499 0 : if (!state.dataGlobal->WarmupFlag) {
2500 0 : if (thisEvapCond.IterationLimit == 0) {
2501 0 : ShowSevereError(state,
2502 0 : format("CalcIndirectResearchSpecialEvapCooler: calculate secondary air mass flow failed for Indirect "
2503 : "Evaporative Cooler Research Special = {}",
2504 0 : thisEvapCond.Name));
2505 0 : ShowContinueErrorTimeStamp(state, "");
2506 0 : ShowContinueError(state, format(" Iteration limit [{}] exceeded in calculating secondary air mass flow rate", MaxIte));
2507 0 : ShowContinueError(state, " Simulation continues");
2508 : }
2509 0 : ShowRecurringWarningErrorAtEnd(
2510 : state,
2511 0 : "Secondary air mass flow Iteration limit exceeded in Indirect Evaporative Cooler Research Special = " + thisEvapCond.Name,
2512 0 : thisEvapCond.IterationLimit);
2513 : }
2514 0 : } else if (SolFla == -2) {
2515 0 : if (!state.dataGlobal->WarmupFlag) {
2516 0 : if (thisEvapCond.IterationFailed == 0) {
2517 0 : ShowSevereError(state,
2518 0 : format("CalcIndirectResearchSpecialEvapCooler: calculate secondary air mass flow failed for Indirect "
2519 : "Evaporative Cooler Research Special = {}",
2520 0 : thisEvapCond.Name));
2521 0 : ShowContinueErrorTimeStamp(state, "");
2522 0 : ShowContinueError(state, "...Bad secondary air mass flow rate limits");
2523 0 : ShowContinueError(state, format("...Given minimum secondary air mass flow rate={:.3R} kg/s", MassFlowRateSecMin));
2524 0 : ShowContinueError(state, format("...Given maximum secondary air mass flow rate={:.3R} kg/s", MassFlowRateSecMax));
2525 0 : ShowContinueError(state, " Simulation continues");
2526 : }
2527 0 : ShowRecurringWarningErrorAtEnd(state,
2528 0 : "Secondary air mass flow control failed in Indirect Evaporative Cooler Research Special = " +
2529 0 : thisEvapCond.Name,
2530 0 : thisEvapCond.IterationFailed);
2531 : }
2532 : }
2533 0 : if (AirMassFlowSec > 0.0) {
2534 0 : if (MassFlowRateSecMax > 0.0) {
2535 0 : FlowRatioSec = AirMassFlowSec / MassFlowRateSecMax;
2536 : } else {
2537 0 : FlowRatioSec = 0.0;
2538 : }
2539 : } else {
2540 0 : FlowRatioSec = 0.0;
2541 : }
2542 0 : FlowRatioSecDry = FlowRatioSec;
2543 0 : AirMassFlowSecDry = AirMassFlowSec;
2544 0 : EvapCoolerTotalElectricPowerDry = IndEvapCoolerPower(state, EvapCoolNum, OperatingMode::DryModulated, FlowRatioSecDry);
2545 : // get wet operation performance
2546 0 : auto f2 = [&state, EvapCoolNum, SysTempSetPoint, InletDryBulbTempSec, InletWetBulbTempSec, InletHumRatioSec](Real64 AirMassFlowSec) {
2547 0 : auto &EvapCond(state.dataEvapCoolers->EvapCond(EvapCoolNum));
2548 0 : EvapCond.SecInletMassFlowRate = AirMassFlowSec;
2549 0 : CalcIndirectRDDEvapCoolerOutletTemp(
2550 : state, EvapCoolNum, OperatingMode::WetModulated, AirMassFlowSec, InletDryBulbTempSec, InletWetBulbTempSec, InletHumRatioSec);
2551 0 : Real64 const OutletAirTemp = EvapCond.OutletTemp; // evap Coler outlet air temperature
2552 0 : return SysTempSetPoint - OutletAirTemp;
2553 0 : };
2554 0 : General::SolveRoot(state, TempTol, MaxIte, SolFla, AirMassFlowSec, f2, MassFlowRateSecMin, MassFlowRateSecMax);
2555 : // if the numerical inversion failed, issue error messages.
2556 0 : if (SolFla == -1) {
2557 0 : if (!state.dataGlobal->WarmupFlag) {
2558 0 : if (thisEvapCond.IterationLimit == 0) {
2559 0 : ShowSevereError(state,
2560 0 : format("CalcIndirectResearchSpecialEvapCooler: calculate secondary air mass flow failed for Indirect "
2561 : "Evaporative Cooler Research Special = {}",
2562 0 : thisEvapCond.Name));
2563 0 : ShowContinueErrorTimeStamp(state, "");
2564 0 : ShowContinueError(state, format(" Iteration limit [{}] exceeded in calculating secondary air mass flow rate", MaxIte));
2565 0 : ShowContinueError(state, " Simulation continues");
2566 : }
2567 0 : ShowRecurringWarningErrorAtEnd(
2568 : state,
2569 0 : "Secondary air mass flow Iteration limit exceeded in Indirect Evaporative Cooler Research Special = " + thisEvapCond.Name,
2570 0 : thisEvapCond.IterationLimit);
2571 : }
2572 0 : } else if (SolFla == -2) {
2573 0 : if (!state.dataGlobal->WarmupFlag) {
2574 0 : if (thisEvapCond.IterationFailed == 0) {
2575 0 : ShowSevereError(state,
2576 0 : format("CalcIndirectResearchSpecialEvapCooler: calculate secondary air mass flow failed for Indirect "
2577 : "Evaporative Cooler Research Special = {}",
2578 0 : thisEvapCond.Name));
2579 0 : ShowContinueErrorTimeStamp(state, "");
2580 0 : ShowContinueError(state, "...Bad secondary air mass flow rate limits");
2581 0 : ShowContinueError(state, format("...Given minimum secondary air mass flow rate={:.3R} kg/s", MassFlowRateSecMin));
2582 0 : ShowContinueError(state, format("...Given maximum secondary air mass flow rate={:.3R} kg/s", MassFlowRateSecMax));
2583 0 : ShowContinueError(state, " Simulation continues");
2584 : }
2585 0 : ShowRecurringWarningErrorAtEnd(state,
2586 0 : "Secondary air mass flow control failed in Indirect Evaporative Cooler Research Special = " +
2587 0 : thisEvapCond.Name,
2588 0 : thisEvapCond.IterationFailed);
2589 : }
2590 : }
2591 0 : if (AirMassFlowSec > 0.0) {
2592 0 : if (MassFlowRateSecMax > 0.0) {
2593 0 : FlowRatioSec = AirMassFlowSec / MassFlowRateSecMax;
2594 : } else {
2595 0 : FlowRatioSec = 0.0;
2596 : }
2597 : } else {
2598 0 : FlowRatioSec = 0.0;
2599 : }
2600 0 : FlowRatioSecWet = FlowRatioSec;
2601 0 : AirMassFlowSecWet = AirMassFlowSec;
2602 0 : EvapCoolerTotalElectricPowerWet = IndEvapCoolerPower(state, EvapCoolNum, OperatingMode::WetModulated, FlowRatioSecWet);
2603 : // compare the dry and wet operation total electric power
2604 0 : if (EvapCoolerTotalElectricPowerDry < EvapCoolerTotalElectricPowerWet) {
2605 0 : thisEvapCond.EvapCoolerRDDOperatingMode = OperatingMode::DryModulated;
2606 0 : FlowRatioSec = FlowRatioSecDry;
2607 0 : thisEvapCond.SecInletMassFlowRate = AirMassFlowSecDry;
2608 0 : CalcIndirectRDDEvapCoolerOutletTemp(
2609 : state, EvapCoolNum, OperatingMode::DryModulated, AirMassFlowSecDry, InletDryBulbTempSec, InletWetBulbTempSec, InletHumRatioSec);
2610 0 : thisEvapCond.EvapCoolerPower = IndEvapCoolerPower(state, EvapCoolNum, OperatingMode::DryModulated, FlowRatioSec);
2611 0 : thisEvapCond.IECOperatingStatus = 1;
2612 : } else {
2613 0 : thisEvapCond.EvapCoolerRDDOperatingMode = OperatingMode::WetModulated;
2614 0 : FlowRatioSec = FlowRatioSecWet;
2615 0 : thisEvapCond.SecInletMassFlowRate = AirMassFlowSecWet;
2616 0 : CalcIndirectRDDEvapCoolerOutletTemp(
2617 : state, EvapCoolNum, OperatingMode::WetModulated, AirMassFlowSecWet, InletDryBulbTempSec, InletWetBulbTempSec, InletHumRatioSec);
2618 0 : thisEvapCond.EvapCoolerPower = IndEvapCoolerPower(state, EvapCoolNum, OperatingMode::WetModulated, FlowRatioSec);
2619 0 : thisEvapCond.IECOperatingStatus = 2;
2620 : }
2621 21068 : } else if (thisEvapCond.EvapCoolerRDDOperatingMode == OperatingMode::WetModulated) {
2622 211056 : auto f = [&state, EvapCoolNum, SysTempSetPoint, InletDryBulbTempSec, InletWetBulbTempSec, InletHumRatioSec](Real64 AirMassFlowSec) {
2623 52764 : auto &EvapCond(state.dataEvapCoolers->EvapCond(EvapCoolNum));
2624 52764 : EvapCond.SecInletMassFlowRate = AirMassFlowSec;
2625 52764 : CalcIndirectRDDEvapCoolerOutletTemp(
2626 : state, EvapCoolNum, OperatingMode::WetModulated, AirMassFlowSec, InletDryBulbTempSec, InletWetBulbTempSec, InletHumRatioSec);
2627 52764 : Real64 const OutletAirTemp = EvapCond.OutletTemp; // evap Coler outlet air temperature
2628 52764 : return SysTempSetPoint - OutletAirTemp;
2629 4452 : };
2630 4452 : int SolFla = 0; // Flag of solver
2631 4452 : General::SolveRoot(state, TempTol, MaxIte, SolFla, AirMassFlowSec, f, MassFlowRateSecMin, MassFlowRateSecMax);
2632 : // if the numerical inversion failed, issue error messages.
2633 4452 : if (SolFla == -1) {
2634 0 : if (!state.dataGlobal->WarmupFlag) {
2635 0 : if (thisEvapCond.IterationLimit == 0) {
2636 0 : ShowSevereError(state,
2637 0 : format("CalcIndirectResearchSpecialEvapCooler: calculate secondary air mass flow failed for Indirect "
2638 : "Evaporative Cooler Research Special = {}",
2639 0 : thisEvapCond.Name));
2640 0 : ShowContinueErrorTimeStamp(state, "");
2641 0 : ShowContinueError(state, format(" Iteration limit [{}] exceeded in calculating secondary air mass flow rate", MaxIte));
2642 0 : ShowContinueError(state, " Simulation continues");
2643 : }
2644 0 : ShowRecurringWarningErrorAtEnd(
2645 : state,
2646 0 : "Secondary air mass flow Iteration limit exceeded in Indirect Evaporative Cooler Research Special = " + thisEvapCond.Name,
2647 0 : thisEvapCond.IterationLimit);
2648 : }
2649 4452 : } else if (SolFla == -2) {
2650 0 : if (!state.dataGlobal->WarmupFlag) {
2651 0 : if (thisEvapCond.IterationFailed == 0) {
2652 0 : ShowSevereError(state,
2653 0 : format("CalcIndirectResearchSpecialEvapCooler: calculate secondary air mass flow failed for Indirect "
2654 : "Evaporative Cooler Research Special = {}",
2655 0 : thisEvapCond.Name));
2656 0 : ShowContinueErrorTimeStamp(state, "");
2657 0 : ShowContinueError(state, "...Bad secondary air mass flow rate limits");
2658 0 : ShowContinueError(state, format("...Given minimum secondary air mass flow rate={:.3R} kg/s", MassFlowRateSecMin));
2659 0 : ShowContinueError(state, format("...Given maximum secondary air mass flow rate={:.3R} kg/s", MassFlowRateSecMax));
2660 0 : ShowContinueError(state, " Simulation continues");
2661 : }
2662 0 : ShowRecurringWarningErrorAtEnd(state,
2663 0 : "Secondary air mass flow control failed in Indirect Evaporative Cooler Research Special = " +
2664 0 : thisEvapCond.Name,
2665 0 : thisEvapCond.IterationFailed);
2666 : }
2667 : }
2668 4452 : thisEvapCond.SecInletMassFlowRate = AirMassFlowSec;
2669 4452 : if (AirMassFlowSec > 0.0) {
2670 4452 : if (MassFlowRateSecMax > 0.0) {
2671 4452 : FlowRatioSec = AirMassFlowSec / MassFlowRateSecMax;
2672 : } else {
2673 0 : FlowRatioSec = 0.0;
2674 : }
2675 : } else {
2676 0 : FlowRatioSec = 0.0;
2677 : }
2678 4452 : thisEvapCond.EvapCoolerPower = IndEvapCoolerPower(state, EvapCoolNum, OperatingMode::WetModulated, FlowRatioSec);
2679 4452 : thisEvapCond.IECOperatingStatus = 2;
2680 16616 : } else if (thisEvapCond.EvapCoolerRDDOperatingMode == OperatingMode::WetFull) {
2681 236 : CalcIndirectRDDEvapCoolerOutletTemp(
2682 : state, EvapCoolNum, OperatingMode::WetFull, MassFlowRateSecMax, InletDryBulbTempSec, InletWetBulbTempSec, InletHumRatioSec);
2683 236 : thisEvapCond.SecInletMassFlowRate = MassFlowRateSecMax;
2684 236 : FlowRatioSec = 1.0;
2685 236 : thisEvapCond.EvapCoolerPower = IndEvapCoolerPower(state, EvapCoolNum, OperatingMode::WetFull, FlowRatioSec);
2686 236 : thisEvapCond.IECOperatingStatus = 2;
2687 : }
2688 : }
2689 34302 : if (PartLoad == 1.0) {
2690 9148 : if (thisEvapCond.EvapCoolerRDDOperatingMode == OperatingMode::WetModulated ||
2691 6860 : thisEvapCond.EvapCoolerRDDOperatingMode == OperatingMode::WetFull) {
2692 2524 : BoundTemp = TEDB - thisEvapCond.DPBoundFactor * (TEDB - InletDewPointTempSec);
2693 2524 : if (thisEvapCond.OutletTemp < BoundTemp) {
2694 0 : thisEvapCond.OutletTemp = BoundTemp;
2695 0 : thisEvapCond.DewPointBoundFlag = 1;
2696 : }
2697 : }
2698 25154 : } else if ((PartLoad < 1.0) && (PartLoad > 0.0)) {
2699 : // assume perfect control Use PLF for energy consumption
2700 2912 : if (thisEvapCond.DesiredOutletTemp < TEDB) {
2701 2912 : thisEvapCond.OutletTemp = thisEvapCond.DesiredOutletTemp;
2702 : }
2703 : } else {
2704 : // part load set to zero so no cooling
2705 22242 : thisEvapCond.OutletTemp = thisEvapCond.InletTemp;
2706 : }
2707 34302 : if (thisEvapCond.EvapCoolerRDDOperatingMode != OperatingMode::None) {
2708 : // There is a constant humidity ratio across the primary side but a reduction in the dry bulb temp
2709 17922 : thisEvapCond.OuletWetBulbTemp =
2710 17922 : Psychrometrics::PsyTwbFnTdbWPb(state, thisEvapCond.OutletTemp, thisEvapCond.InletHumRat, state.dataEnvrn->OutBaroPress);
2711 17922 : thisEvapCond.OutletHumRat = thisEvapCond.InletHumRat;
2712 17922 : thisEvapCond.OutletEnthalpy = Psychrometrics::PsyHFnTdbW(thisEvapCond.OutletTemp, thisEvapCond.OutletHumRat);
2713 17922 : RhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisEvapCond.InletTemp, thisEvapCond.InletHumRat);
2714 17922 : QHX = thisEvapCond.VolFlowRate * RhoAir * (thisEvapCond.InletEnthalpy - thisEvapCond.OutletEnthalpy);
2715 17922 : if (QHX > HVAC::SmallLoad) {
2716 : // get secondary air outlet condition
2717 6252 : CalcSecondaryAirOutletCondition(state,
2718 : EvapCoolNum,
2719 : thisEvapCond.EvapCoolerRDDOperatingMode,
2720 : thisEvapCond.SecInletMassFlowRate,
2721 : InletDryBulbTempSec,
2722 : InletWetBulbTempSec,
2723 : InletHumRatioSec,
2724 : QHX,
2725 : QHXLatent);
2726 6252 : RhoWater = Psychrometrics::RhoH2O(state.dataEnvrn->OutDryBulbTemp); // this if it is at the outside air inlet node condition
2727 6252 : hfg = Psychrometrics::PsyHfgAirFnWTdb(InletHumRatioSec, InletDryBulbTempSec);
2728 6252 : EvapVdot = (QHXLatent) / (hfg * RhoWater);
2729 6252 : DriftVdot = EvapVdot * thisEvapCond.DriftFraction;
2730 6252 : if (thisEvapCond.BlowDownRatio > 0.0) {
2731 0 : BlowDownVdot = EvapVdot / (thisEvapCond.BlowDownRatio - 1) - DriftVdot;
2732 0 : if (BlowDownVdot < 0.0) BlowDownVdot = 0.0;
2733 : } else {
2734 6252 : BlowDownVdot = 0.0;
2735 : }
2736 6252 : thisEvapCond.EvapWaterConsumpRate = EvapVdot + DriftVdot + BlowDownVdot;
2737 : // A numerical check to keep from having very tiny negative water consumption values being reported
2738 6252 : if (thisEvapCond.EvapWaterConsumpRate < 0.0) thisEvapCond.EvapWaterConsumpRate = 0.0;
2739 : } else {
2740 11670 : thisEvapCond.OutletTemp = thisEvapCond.InletTemp;
2741 11670 : thisEvapCond.OuletWetBulbTemp = thisEvapCond.InletWetBulbTemp;
2742 11670 : thisEvapCond.OutletEnthalpy = thisEvapCond.InletEnthalpy;
2743 11670 : thisEvapCond.EvapCoolerEnergy = 0.0;
2744 11670 : thisEvapCond.EvapCoolerPower = 0.0;
2745 11670 : thisEvapCond.EvapWaterConsumpRate = 0.0;
2746 11670 : thisEvapCond.SecInletMassFlowRate = 0.0;
2747 11670 : thisEvapCond.IECOperatingStatus = 0;
2748 11670 : thisEvapCond.StageEff = 0.0;
2749 11670 : CalcSecondaryAirOutletCondition(state,
2750 : EvapCoolNum,
2751 : thisEvapCond.EvapCoolerRDDOperatingMode,
2752 : 0.0,
2753 : InletDryBulbTempSec,
2754 : InletWetBulbTempSec,
2755 : InletHumRatioSec,
2756 : QHX,
2757 : QHXLatent);
2758 : }
2759 :
2760 : } else {
2761 : // The evap cooler is not running and does not change conditions from inlet to outlet
2762 16380 : thisEvapCond.OutletTemp = thisEvapCond.InletTemp;
2763 16380 : thisEvapCond.OuletWetBulbTemp = thisEvapCond.InletWetBulbTemp;
2764 16380 : thisEvapCond.OutletHumRat = thisEvapCond.InletHumRat;
2765 16380 : thisEvapCond.OutletEnthalpy = thisEvapCond.InletEnthalpy;
2766 16380 : thisEvapCond.SecOutletTemp = thisEvapCond.SecInletTemp;
2767 16380 : thisEvapCond.SecOutletHumRat = thisEvapCond.SecInletHumRat;
2768 16380 : thisEvapCond.SecOutletEnthalpy = thisEvapCond.SecInletEnthalpy;
2769 16380 : thisEvapCond.SecOutletMassFlowRate = thisEvapCond.SecInletMassFlowRate;
2770 16380 : thisEvapCond.EvapCoolerEnergy = 0.0;
2771 16380 : thisEvapCond.EvapCoolerPower = 0.0;
2772 16380 : thisEvapCond.EvapWaterConsumpRate = 0.0;
2773 16380 : thisEvapCond.SecInletMassFlowRate = 0.0;
2774 16380 : thisEvapCond.IECOperatingStatus = 0;
2775 16380 : thisEvapCond.StageEff = 0.0;
2776 : }
2777 34302 : }
2778 :
2779 34302 : OperatingMode IndirectResearchSpecialEvapCoolerOperatingMode(EnergyPlusData &state,
2780 : int const EvapCoolNum,
2781 : Real64 const InletDryBulbTempSec,
2782 : Real64 const InletWetBulbTempSec,
2783 : Real64 const TdbOutSysWetMin,
2784 : Real64 const TdbOutSysDryMin)
2785 : {
2786 :
2787 : // PURPOSE OF THIS SUBROUTINE:
2788 : // Determines current operating mode of indirect research special evaporative cooler
2789 : // from the five valid operating modes depending the primary and secondary air
2790 : // temperatures, setpoint temperature, and full capacity air outlet temperature.
2791 :
2792 : // METHODOLOGY EMPLOYED:
2793 : // compares various temperatures to determine the operating mode
2794 :
2795 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2796 : Real64 InletDryBulbTempPri; // entering air dry bulb temperature of primary air
2797 : Real64 SysTempSetPoint; // evaporative cooler outlet setpoint temperature, drybulb
2798 : OperatingMode OperatingMode; // current operating mode of indrect evaporative cooler
2799 :
2800 34302 : auto const &thisEvapCond = state.dataEvapCoolers->EvapCond(EvapCoolNum);
2801 :
2802 34302 : InletDryBulbTempPri = thisEvapCond.InletTemp;
2803 34302 : SysTempSetPoint = thisEvapCond.DesiredOutletTemp;
2804 :
2805 : // Now determine the operating modes of indirect evaporative cooler research special. There are five allowed operating modes
2806 34302 : if ((InletDryBulbTempPri <= SysTempSetPoint) ||
2807 29538 : (InletDryBulbTempPri > thisEvapCond.MaxOATDBEvapCooler && InletWetBulbTempSec > thisEvapCond.MaxOATWBEvapCooler) ||
2808 : (InletDryBulbTempPri < InletDryBulbTempSec)) {
2809 16380 : OperatingMode = OperatingMode::None;
2810 17922 : } else if ((InletDryBulbTempSec < thisEvapCond.MinOATDBEvapCooler && TdbOutSysDryMin < SysTempSetPoint)) {
2811 13226 : OperatingMode = OperatingMode::DryModulated; // dry mode capacity modulated
2812 4696 : } else if ((InletDryBulbTempSec < thisEvapCond.MinOATDBEvapCooler && SysTempSetPoint <= TdbOutSysDryMin)) {
2813 8 : OperatingMode = OperatingMode::DryFull; // dry mode in full capacity
2814 4688 : } else if ((InletDryBulbTempSec >= thisEvapCond.MinOATDBEvapCooler && InletWetBulbTempSec < thisEvapCond.MaxOATWBEvapCooler &&
2815 : SysTempSetPoint <= TdbOutSysWetMin)) {
2816 236 : OperatingMode = OperatingMode::WetFull; // wet mode in full capacity
2817 4452 : } else if ((InletDryBulbTempSec >= thisEvapCond.MinOATDBEvapCooler && InletWetBulbTempSec < thisEvapCond.MaxOATWBEvapCooler &&
2818 : TdbOutSysWetMin < SysTempSetPoint)) { // && SysTempSetPoint < TdbOutSysDryMin
2819 4452 : OperatingMode = OperatingMode::WetModulated; // wet mode capacity modulated
2820 0 : } else if ((InletDryBulbTempSec >= thisEvapCond.MinOATDBEvapCooler && InletDryBulbTempSec < thisEvapCond.MaxOATDBEvapCooler &&
2821 0 : InletWetBulbTempSec < thisEvapCond.MaxOATWBEvapCooler && SysTempSetPoint < TdbOutSysDryMin && TdbOutSysWetMin < SysTempSetPoint)) {
2822 0 : OperatingMode = OperatingMode::DryWetModulated; // modulated in dry and wet mode, and the lower total power will be used
2823 : } else {
2824 0 : OperatingMode = OperatingMode::None; // this condition should not happen unless the bounds do not cover all combinations possible
2825 : }
2826 34302 : return OperatingMode;
2827 : }
2828 :
2829 168746 : void CalcIndirectRDDEvapCoolerOutletTemp(EnergyPlusData &state,
2830 : int const EvapCoolNum,
2831 : OperatingMode DryOrWetOperatingMode,
2832 : Real64 const AirMassFlowSec,
2833 : Real64 const EDBTSec,
2834 : Real64 const EWBTSec,
2835 : Real64 const EHumRatSec)
2836 : {
2837 : // SUBROUTINE INFORMATION:
2838 : // AUTHOR B. Nigusse
2839 : // DATE WRITTEN Sep 2014
2840 :
2841 : // PURPOSE OF THIS SUBROUTINE:
2842 : // Indirect research special evaporative cooler perfomance:
2843 : // determines the IEC primary air outlet temperature
2844 :
2845 : // METHODOLOGY EMPLOYED:
2846 : // Uses effectiveness and energy balance equations to determine
2847 : // primary air outlet temperature. The dry and wet effectiveness
2848 : // values are used depending on operating modes.
2849 :
2850 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2851 : Real64 OutletTemp; // evaporative cooler current outlet air drybulb temperature
2852 : Real64 RhoAirSec; // density of secondary air at inlet condition
2853 : Real64 RhoAirSys; // density of primary air at inlet condition
2854 : Real64 EffectivenessDry; // dry coil effectiveness
2855 : Real64 EffectivenessWet; // wet coil effectiveness
2856 : Real64 FlowRatio; // flow ratio based on current to the design of secondary air flow rate
2857 : Real64 EffModDryMode; // dry mode effectiveness modifier for flow ratio
2858 : Real64 EffModWetMode; // wet mode effectiveness modifier for flow ratio
2859 : Real64 CapFlowSys; // capacity flow (massFlowRate * Specific Heat) of primary air system
2860 : Real64 CapFlowSec; // capacity flow (massFlowRate * Specific Heat) of secondary system
2861 : Real64 CpAirSec; // specific heat of secondary air at inlet condition
2862 : Real64 CpAirSys; // specific heat of primary air at inlet condition
2863 :
2864 : Real64 QHXRate; // total heat transfer rate
2865 : Real64 OutletTempSec; // secondary air outlet temperature
2866 : Real64 SecOutletAirHumRat; // secondary air humidity ratio at constant temperature (Pure mass transfer)
2867 : Real64 SecOutletEnthalpy; // secondary air outlet enthalpy
2868 :
2869 168746 : auto &thisEvapCond(state.dataEvapCoolers->EvapCond(EvapCoolNum));
2870 :
2871 168746 : if (thisEvapCond.InletMassFlowRate > 0.0) {
2872 168746 : FlowRatio = AirMassFlowSec / thisEvapCond.InletMassFlowRate; // ratio of current secondary air flow to current primary air flow
2873 : } else {
2874 0 : FlowRatio = 1.0;
2875 : }
2876 168746 : if (AirMassFlowSec > 0.0) {
2877 151068 : RhoAirSec = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, EDBTSec, EHumRatSec);
2878 151068 : RhoAirSys = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisEvapCond.InletTemp, thisEvapCond.InletHumRat);
2879 151068 : if (DryOrWetOperatingMode == OperatingMode::DryModulated || DryOrWetOperatingMode == OperatingMode::DryFull) {
2880 68218 : if (thisEvapCond.DrybulbEffecCurveIndex > 0) {
2881 68218 : EffModDryMode = Curve::CurveValue(state, thisEvapCond.DrybulbEffecCurveIndex, FlowRatio);
2882 : } else {
2883 0 : EffModDryMode = 1.0;
2884 : }
2885 68218 : EffectivenessDry = thisEvapCond.DryCoilMaxEfficiency * EffModDryMode;
2886 68218 : thisEvapCond.StageEff = EffectivenessDry;
2887 68218 : OutletTemp = thisEvapCond.InletTemp - EffectivenessDry * (thisEvapCond.InletTemp - EDBTSec);
2888 68218 : if (OutletTemp > thisEvapCond.InletTemp) {
2889 11646 : OutletTemp = thisEvapCond.InletTemp;
2890 : }
2891 68218 : CpAirSys = Psychrometrics::PsyCpAirFnW(thisEvapCond.InletHumRat);
2892 68218 : CapFlowSys = thisEvapCond.InletMassFlowRate * CpAirSys;
2893 68218 : QHXRate = CapFlowSys * (thisEvapCond.InletTemp - OutletTemp);
2894 68218 : CpAirSec = Psychrometrics::PsyCpAirFnW(EHumRatSec);
2895 68218 : CapFlowSec = AirMassFlowSec * CpAirSec;
2896 68218 : OutletTempSec = EDBTSec + QHXRate / CapFlowSec;
2897 68218 : if (OutletTempSec >= thisEvapCond.InletTemp) {
2898 25588 : OutletTempSec = thisEvapCond.InletTemp - 0.2;
2899 25588 : QHXRate = CapFlowSec * (OutletTempSec - EDBTSec);
2900 25588 : OutletTemp = thisEvapCond.InletTemp - QHXRate / CapFlowSys;
2901 : }
2902 68218 : thisEvapCond.SecOutletTemp = OutletTempSec;
2903 82850 : } else if (DryOrWetOperatingMode == OperatingMode::WetModulated || DryOrWetOperatingMode == OperatingMode::WetFull) {
2904 82850 : if (thisEvapCond.WetbulbEffecCurveIndex > 0) {
2905 82850 : EffModWetMode = Curve::CurveValue(state, thisEvapCond.WetbulbEffecCurveIndex, FlowRatio);
2906 : } else {
2907 0 : EffModWetMode = 1.0;
2908 : }
2909 82850 : EffectivenessWet = thisEvapCond.WetCoilMaxEfficiency * EffModWetMode;
2910 82850 : thisEvapCond.StageEff = EffectivenessWet;
2911 82850 : OutletTemp = thisEvapCond.InletTemp - EffectivenessWet * (thisEvapCond.InletTemp - EWBTSec);
2912 82850 : if (OutletTemp > thisEvapCond.InletTemp) {
2913 11530 : OutletTemp = thisEvapCond.InletTemp;
2914 : }
2915 82850 : CpAirSys = Psychrometrics::PsyCpAirFnW(thisEvapCond.InletHumRat);
2916 82850 : CapFlowSys = thisEvapCond.InletMassFlowRate * CpAirSys;
2917 82850 : QHXRate = CapFlowSys * (thisEvapCond.InletTemp - OutletTemp);
2918 82850 : SecOutletEnthalpy = thisEvapCond.SecInletEnthalpy + QHXRate / AirMassFlowSec;
2919 82850 : SecOutletAirHumRat = Psychrometrics::PsyWFnTdbH(state, EDBTSec,
2920 : SecOutletEnthalpy); // assumes constant temperature moisture addition
2921 : // we may need check based on maximum allowed humidity ratio
2922 82850 : thisEvapCond.SecOutletTemp = EDBTSec;
2923 82850 : thisEvapCond.SecOutletHumRat = SecOutletAirHumRat;
2924 82850 : thisEvapCond.SecOutletEnthalpy = SecOutletEnthalpy;
2925 : } else {
2926 0 : OutletTemp = thisEvapCond.InletTemp;
2927 0 : thisEvapCond.StageEff = 0.0;
2928 : }
2929 : } else {
2930 17678 : OutletTemp = thisEvapCond.InletTemp;
2931 17678 : thisEvapCond.StageEff = 0.0;
2932 : }
2933 : // set results to into output variables
2934 168746 : thisEvapCond.OutletTemp = OutletTemp;
2935 168746 : }
2936 :
2937 17922 : void CalcSecondaryAirOutletCondition(EnergyPlusData &state,
2938 : int const EvapCoolNum,
2939 : OperatingMode OperatingMode,
2940 : Real64 const AirMassFlowSec,
2941 : Real64 const EDBTSec,
2942 : Real64 const EWBTSec,
2943 : Real64 const EHumRatSec,
2944 : Real64 const QHXTotal,
2945 : Real64 &QHXLatent)
2946 : {
2947 : // SUBROUTINE INFORMATION:
2948 : // AUTHOR B. Nigusse
2949 : // DATE WRITTEN Oct 2014
2950 :
2951 : // PURPOSE OF THIS SUBROUTINE:
2952 : // Indirect research special evaporative cooler: determines the secondary air outlet conditions
2953 :
2954 : // METHODOLOGY EMPLOYED:
2955 : // applies energy balance equations to determine the secondary air outlet condition
2956 : // For wt operations assumes the secondary air leaves at at inlet temperature, i.e.,
2957 : // latent heat transfer only. For dry operation the humdity ratio remains constant.
2958 :
2959 : // REFERENCES:
2960 : // CalculateWaterUsage routine of cooling towers for wet operation mode
2961 :
2962 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2963 : Real64 SecOutletAirHumRat; // secondary air humidity ratio at the outlet node
2964 : Real64 SecOutletEnthalpy; // secondary air outlet enthalpy
2965 : Real64 CpAirSec; // specific heat of secondary air at inlet condition
2966 : Real64 hfg; // secondary air side enthaly of evaporation
2967 :
2968 17922 : auto &thisEvapCond(state.dataEvapCoolers->EvapCond(EvapCoolNum));
2969 :
2970 17922 : QHXLatent = 0.0;
2971 17922 : if (AirMassFlowSec > 0.0) {
2972 6252 : if ((OperatingMode == OperatingMode::DryModulated || OperatingMode == OperatingMode::DryFull)) {
2973 1564 : thisEvapCond.SecOutletHumRat = EHumRatSec;
2974 1564 : CpAirSec = Psychrometrics::PsyCpAirFnW(EHumRatSec);
2975 1564 : thisEvapCond.SecOutletTemp = EDBTSec + QHXTotal / AirMassFlowSec / CpAirSec;
2976 1564 : thisEvapCond.SecOutletEnthalpy = Psychrometrics::PsyHFnTdbW(thisEvapCond.SecOutletTemp, EHumRatSec);
2977 1564 : thisEvapCond.SecOuletWetBulbTemp =
2978 1564 : Psychrometrics::PsyTwbFnTdbWPb(state, thisEvapCond.SecOutletTemp, EHumRatSec, state.dataEnvrn->OutBaroPress);
2979 4688 : } else if ((OperatingMode == OperatingMode::WetModulated || OperatingMode == OperatingMode::WetFull)) {
2980 4688 : SecOutletEnthalpy = thisEvapCond.SecInletEnthalpy + QHXTotal / AirMassFlowSec;
2981 4688 : SecOutletAirHumRat = Psychrometrics::PsyWFnTdbH(state, EDBTSec,
2982 : SecOutletEnthalpy); // assumes a constant temperature moisture addition
2983 4688 : thisEvapCond.SecOutletTemp = EDBTSec;
2984 4688 : thisEvapCond.SecOutletHumRat = SecOutletAirHumRat;
2985 4688 : thisEvapCond.SecOutletEnthalpy = SecOutletEnthalpy;
2986 4688 : thisEvapCond.SecOuletWetBulbTemp =
2987 4688 : Psychrometrics::PsyTwbFnTdbWPb(state, thisEvapCond.SecOutletTemp, SecOutletAirHumRat, state.dataEnvrn->OutBaroPress);
2988 4688 : hfg = Psychrometrics::PsyHfgAirFnWTdb(EHumRatSec, EDBTSec);
2989 4688 : QHXLatent = min(QHXTotal, AirMassFlowSec * (SecOutletAirHumRat - EHumRatSec) * hfg);
2990 : } else {
2991 : // set results to into output variables
2992 0 : thisEvapCond.SecOutletTemp = EDBTSec;
2993 0 : thisEvapCond.SecOuletWetBulbTemp = EWBTSec;
2994 0 : thisEvapCond.SecOutletHumRat = EHumRatSec;
2995 0 : thisEvapCond.SecOutletEnthalpy = thisEvapCond.SecInletEnthalpy;
2996 : }
2997 : } else {
2998 11670 : thisEvapCond.SecOutletTemp = EDBTSec;
2999 11670 : thisEvapCond.SecOuletWetBulbTemp = EWBTSec;
3000 11670 : thisEvapCond.SecOutletHumRat = EHumRatSec;
3001 11670 : thisEvapCond.SecOutletEnthalpy = thisEvapCond.SecInletEnthalpy;
3002 : }
3003 17922 : }
3004 :
3005 17922 : Real64 IndEvapCoolerPower(EnergyPlusData &state,
3006 : int const EvapCoolIndex, // Unit index
3007 : OperatingMode DryWetMode, // dry or wet operating mode of evaporator cooler
3008 : Real64 const FlowRatio // secondary air flow fraction
3009 : )
3010 : {
3011 :
3012 : // SUBROUTINE INFORMATION:
3013 : // AUTHOR B. Nigusse
3014 : // DATE WRITTEN Sep 2014
3015 :
3016 : // PURPOSE OF THIS SUBROUTINE:
3017 : // Calculates the Indirect Evaporative Cooler Total Electric Power
3018 :
3019 : // METHODOLOGY EMPLOYED:
3020 : // Scales the design fan and pump power depending on secondary air flow fraction
3021 : // and sums the two to determine the evaporative cooler total electric power.
3022 :
3023 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3024 : Real64 FanPowerModCurveValue; // fan power modifier curve value
3025 : Real64 PumpPowerModCurveValue; // fan power modifier curve value
3026 : Real64 EvapCoolertotalPower; // current evaporative cooler total electric power
3027 :
3028 17922 : auto &thisEvapCond(state.dataEvapCoolers->EvapCond(EvapCoolIndex));
3029 :
3030 17922 : EvapCoolertotalPower = 0.0;
3031 17922 : if (FlowRatio > 0.0) {
3032 17922 : if (thisEvapCond.FanPowerModifierCurveIndex > 0) {
3033 17922 : FanPowerModCurveValue = Curve::CurveValue(state, thisEvapCond.FanPowerModifierCurveIndex, FlowRatio);
3034 : } else {
3035 0 : FanPowerModCurveValue = thisEvapCond.PartLoadFract * FlowRatio;
3036 : }
3037 17922 : EvapCoolertotalPower += thisEvapCond.IndirectFanPower * FanPowerModCurveValue;
3038 17922 : if (DryWetMode == OperatingMode::WetModulated || DryWetMode == OperatingMode::WetFull) {
3039 : // Add the pump power to the total Evap Cooler power for wet operating mode
3040 4688 : if (thisEvapCond.PumpPowerModifierCurveIndex > 0) {
3041 4688 : PumpPowerModCurveValue = Curve::CurveValue(state, thisEvapCond.PumpPowerModifierCurveIndex, FlowRatio);
3042 : } else {
3043 : // linearly scale pump power using part-load-fraction when pump power modifier curve is not specified
3044 0 : PumpPowerModCurveValue = thisEvapCond.PartLoadFract * FlowRatio;
3045 : }
3046 4688 : EvapCoolertotalPower += thisEvapCond.IndirectRecircPumpPower * PumpPowerModCurveValue;
3047 : }
3048 : } else {
3049 0 : EvapCoolertotalPower = 0.0;
3050 : }
3051 17922 : return EvapCoolertotalPower;
3052 : }
3053 :
3054 2722856 : void CalcDirectResearchSpecialEvapCooler(EnergyPlusData &state, int const EvapCoolNum, Real64 const FanPLR)
3055 : {
3056 :
3057 : // SUBROUTINE INFORMATION:
3058 : // AUTHOR B. Griffith
3059 : // DATE WRITTEN March 2009
3060 :
3061 : // PURPOSE OF THIS SUBROUTINE:
3062 : // calculate model for direct evaporative cooler that is simple and controllable
3063 :
3064 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3065 : Real64 SatEff; // Saturation Efficiency of the CelDek Pad
3066 : Real64 TEDB; // Entering Dry Bulb Temperature
3067 : Real64 TEWB; // Entering Wet Bulb Temperature
3068 : Real64 RhoWater;
3069 : Real64 PartLoad;
3070 : Real64 EffModCurveValue; // effectiveness modifier curve value
3071 : Real64 PumpPowerModCurveValue; // recirculation pump power modifier curve value
3072 2722856 : Real64 FlowRatio(0); // primary air flow frcation (current flow divided by the design flow rate)
3073 : Real64 MassFlowRateSysDesign; // primary air design mass flow rate
3074 : Real64 MassFlowRateSys; // primary air current mass flow rate
3075 2722856 : Real64 BlowDownVdot(0.0);
3076 2722856 : Real64 DriftVdot(0.0);
3077 2722856 : Real64 EvapVdot(0.0);
3078 2722856 : bool EvapCoolerOperatingLimitFlag(false);
3079 :
3080 2722856 : auto &thisEvapCond(state.dataEvapCoolers->EvapCond(EvapCoolNum));
3081 :
3082 2722856 : EvapCoolerOperatingLimitFlag = false;
3083 2722856 : TEDB = thisEvapCond.InletTemp;
3084 2722856 : TEWB = thisEvapCond.InletWetBulbTemp;
3085 2722856 : if (thisEvapCond.EvapCoolerOperationControlFlag) {
3086 34382 : if (TEDB >= thisEvapCond.MinOATDBEvapCooler && (TEWB <= thisEvapCond.MaxOATWBEvapCooler || TEDB <= thisEvapCond.MaxOATDBEvapCooler)) {
3087 24432 : EvapCoolerOperatingLimitFlag = true;
3088 : }
3089 : } else {
3090 2688474 : EvapCoolerOperatingLimitFlag = true;
3091 : }
3092 :
3093 : // If the Evaporative Cooler is operating there should be some mass flow rate
3094 : // Also the evap cooler has to be scheduled to be available
3095 2722856 : if ((thisEvapCond.InletMassFlowRate > 0.0) && (ScheduleManager::GetCurrentScheduleValue(state, thisEvapCond.SchedPtr) > 0.0) &&
3096 : EvapCoolerOperatingLimitFlag) {
3097 :
3098 : //***************************************************************************
3099 : // TEMP LEAVING DRY BULB IS CALCULATED FROM SATURATION EFFICIENCY AS THE
3100 : // DRY BULB TEMP APPROACHES THE WET BULB TEMP. WET BULB TEMP IS CONSTANT
3101 : // ACROSS A DIRECT EVAPORATION COOLER.
3102 2669246 : TEWB = thisEvapCond.InletWetBulbTemp;
3103 2669246 : TEDB = thisEvapCond.InletTemp;
3104 :
3105 2669246 : MassFlowRateSys = thisEvapCond.InletMassFlowRate;
3106 2669246 : MassFlowRateSysDesign = state.dataLoopNodes->Node(thisEvapCond.InletNode).MassFlowRateMax;
3107 2669246 : if (MassFlowRateSysDesign > 0.0) {
3108 691680 : if (MassFlowRateSys > 0.0) {
3109 691680 : FlowRatio = MassFlowRateSys / MassFlowRateSysDesign;
3110 : } else {
3111 0 : FlowRatio = 1.0;
3112 : }
3113 : }
3114 2669246 : if (thisEvapCond.WetbulbEffecCurveIndex > 0) {
3115 0 : EffModCurveValue = Curve::CurveValue(state, thisEvapCond.WetbulbEffecCurveIndex, FlowRatio);
3116 : } else {
3117 : // if no curve specified assume constant effectiveness
3118 2669246 : EffModCurveValue = 1.0;
3119 : }
3120 2669246 : SatEff = thisEvapCond.DirectEffectiveness * EffModCurveValue;
3121 2669246 : thisEvapCond.StageEff = SatEff;
3122 2669246 : PartLoad = thisEvapCond.PartLoadFract;
3123 2669246 : if (PartLoad == 1.0) {
3124 2605152 : thisEvapCond.OutletTemp = TEDB - ((TEDB - TEWB) * SatEff);
3125 2605152 : thisEvapCond.OuletWetBulbTemp = TEWB;
3126 2605152 : thisEvapCond.OutletHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, thisEvapCond.OutletTemp, TEWB, state.dataEnvrn->OutBaroPress);
3127 2605152 : thisEvapCond.OutletEnthalpy = Psychrometrics::PsyHFnTdbW(thisEvapCond.OutletTemp, thisEvapCond.OutletHumRat);
3128 64094 : } else if ((PartLoad < 1.0) && (PartLoad > 0.0)) {
3129 : // assume perfect control Use PLF for energy consumption
3130 976 : if (thisEvapCond.DesiredOutletTemp < TEDB) {
3131 976 : thisEvapCond.OutletTemp = thisEvapCond.DesiredOutletTemp;
3132 976 : thisEvapCond.OuletWetBulbTemp = TEWB;
3133 976 : thisEvapCond.OutletHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, thisEvapCond.OutletTemp, TEWB, state.dataEnvrn->OutBaroPress);
3134 :
3135 976 : thisEvapCond.OutletEnthalpy = Psychrometrics::PsyHFnTdbW(thisEvapCond.OutletTemp, thisEvapCond.OutletHumRat);
3136 : } else { // do no cooling
3137 0 : thisEvapCond.OutletTemp = TEDB;
3138 0 : thisEvapCond.OuletWetBulbTemp = TEWB;
3139 0 : thisEvapCond.OutletHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, thisEvapCond.OutletTemp, TEWB, state.dataEnvrn->OutBaroPress);
3140 0 : thisEvapCond.OutletEnthalpy = Psychrometrics::PsyHFnTdbW(thisEvapCond.OutletTemp, thisEvapCond.OutletHumRat);
3141 : }
3142 : } else {
3143 : // part load set to zero so no cooling
3144 63118 : thisEvapCond.OutletTemp = TEDB;
3145 63118 : thisEvapCond.OuletWetBulbTemp = TEWB;
3146 63118 : thisEvapCond.OutletHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, thisEvapCond.OutletTemp, TEWB, state.dataEnvrn->OutBaroPress);
3147 63118 : thisEvapCond.OutletEnthalpy = Psychrometrics::PsyHFnTdbW(thisEvapCond.OutletTemp, thisEvapCond.OutletHumRat);
3148 : }
3149 :
3150 : //***************************************************************************
3151 : // ENERGY CONSUMED BY THE RECIRCULATING PUMP
3152 : // Add the pump energy to the total Evap Cooler energy comsumption
3153 2669246 : if (thisEvapCond.PumpPowerModifierCurveIndex > 0) {
3154 0 : PumpPowerModCurveValue = Curve::CurveValue(state, thisEvapCond.PumpPowerModifierCurveIndex, FlowRatio);
3155 : } else {
3156 : // if no pump power modifier curve specified, then assume linear variation with part-load and primary fan PLR
3157 2669246 : PumpPowerModCurveValue = PartLoad * FanPLR;
3158 : }
3159 2669246 : thisEvapCond.EvapCoolerPower = thisEvapCond.RecircPumpPower * PumpPowerModCurveValue;
3160 : //******************
3161 : // WATER CONSUMPTION IN m3 OF WATER FOR DIRECT
3162 : // H2O [m3/s] = Delta W[kgWater/kgDryAir]*Mass Flow Air[kgDryAir]
3163 : // /RhoWater [kgWater/m3]
3164 : //******************
3165 2669246 : RhoWater = Psychrometrics::RhoH2O(thisEvapCond.OutletTemp);
3166 2669246 : EvapVdot = (thisEvapCond.OutletHumRat - thisEvapCond.InletHumRat) * thisEvapCond.InletMassFlowRate / RhoWater;
3167 2669246 : DriftVdot = EvapVdot * thisEvapCond.DriftFraction;
3168 :
3169 2669246 : if (thisEvapCond.BlowDownRatio > 0.0) {
3170 2669246 : BlowDownVdot = EvapVdot / (thisEvapCond.BlowDownRatio - 1.0) - DriftVdot;
3171 2669246 : if (BlowDownVdot < 0.0) BlowDownVdot = 0.0;
3172 : } else {
3173 0 : BlowDownVdot = 0.0;
3174 : }
3175 :
3176 2669246 : thisEvapCond.EvapWaterConsumpRate = EvapVdot + DriftVdot + BlowDownVdot;
3177 :
3178 : // A numerical check to keep from having very tiny negative water consumption values being reported
3179 2669246 : if (thisEvapCond.EvapWaterConsumpRate < 0.0) thisEvapCond.EvapWaterConsumpRate = 0.0;
3180 :
3181 : } else {
3182 : // The evap cooler is not running and does not change conditions from inlet to outlet
3183 53610 : thisEvapCond.OutletTemp = thisEvapCond.InletTemp;
3184 :
3185 53610 : thisEvapCond.OuletWetBulbTemp = thisEvapCond.InletWetBulbTemp;
3186 :
3187 53610 : thisEvapCond.OutletHumRat = thisEvapCond.InletHumRat;
3188 :
3189 53610 : thisEvapCond.OutletEnthalpy = thisEvapCond.InletEnthalpy;
3190 53610 : thisEvapCond.EvapCoolerPower = 0.0;
3191 53610 : thisEvapCond.EvapCoolerEnergy = 0.0;
3192 :
3193 53610 : thisEvapCond.EvapWaterConsumpRate = 0.0;
3194 : }
3195 : // all of the mass flowrates are not changed across the evap cooler
3196 2722856 : thisEvapCond.OutletMassFlowRate = thisEvapCond.InletMassFlowRate;
3197 2722856 : thisEvapCond.OutletMassFlowRateMaxAvail = thisEvapCond.InletMassFlowRateMaxAvail;
3198 2722856 : thisEvapCond.OutletMassFlowRateMinAvail = thisEvapCond.InletMassFlowRateMinAvail;
3199 :
3200 : // the pressure is not changed across the evap cooler
3201 2722856 : thisEvapCond.OutletPressure = thisEvapCond.InletPressure;
3202 2722856 : }
3203 :
3204 5303237 : void UpdateEvapCooler(EnergyPlusData &state, int const EvapCoolNum)
3205 : {
3206 :
3207 : // SUBROUTINE INFORMATION:
3208 : // AUTHOR Richard J. Liesen
3209 : // DATE WRITTEN October 2000
3210 :
3211 5303237 : auto &thisEvapCond = state.dataEvapCoolers->EvapCond(EvapCoolNum);
3212 5303237 : auto &thisOutletNode = state.dataLoopNodes->Node(thisEvapCond.OutletNode);
3213 5303237 : auto const &thisInletNode = state.dataLoopNodes->Node(thisEvapCond.InletNode);
3214 :
3215 : // Set the outlet air nodes of the EvapCooler
3216 5303237 : thisOutletNode.MassFlowRate = thisEvapCond.OutletMassFlowRate;
3217 5303237 : thisOutletNode.MassFlowRateMaxAvail = thisEvapCond.OutletMassFlowRateMaxAvail;
3218 5303237 : thisOutletNode.MassFlowRateMinAvail = thisEvapCond.OutletMassFlowRateMinAvail;
3219 5303237 : thisOutletNode.Temp = thisEvapCond.OutletTemp;
3220 5303237 : thisOutletNode.HumRat = thisEvapCond.OutletHumRat;
3221 5303237 : thisOutletNode.Enthalpy = thisEvapCond.OutletEnthalpy;
3222 5303237 : thisOutletNode.Press = thisEvapCond.OutletPressure;
3223 :
3224 5303237 : if (thisEvapCond.SecondaryOutletNode > 0) {
3225 2190906 : auto &thisOutletNodeSec = state.dataLoopNodes->Node(thisEvapCond.SecondaryOutletNode);
3226 : // set outlet nodes of the secondary air side of the EvapCooler (mass Flow Rate Only)
3227 2190906 : if (thisEvapCond.evapCoolerType == EvapCoolerType::IndirectRDDSpecial && thisEvapCond.EvapCoolerOperationControlFlag) {
3228 34302 : thisOutletNodeSec.Temp = thisEvapCond.SecOutletTemp;
3229 34302 : thisOutletNodeSec.HumRat = thisEvapCond.SecOutletHumRat;
3230 34302 : thisOutletNodeSec.Enthalpy = thisEvapCond.SecOutletEnthalpy;
3231 34302 : thisOutletNodeSec.MassFlowRate = thisEvapCond.SecOutletMassFlowRate;
3232 : }
3233 : }
3234 :
3235 : // Set the outlet nodes for properties that just pass through & not used
3236 5303237 : thisOutletNode.Quality = thisInletNode.Quality;
3237 :
3238 : // Set the demand request for supply water from water storage tank (if needed)
3239 5303237 : if (thisEvapCond.EvapWaterSupplyMode == WaterSupply::FromTank) {
3240 0 : state.dataWaterData->WaterStorage(thisEvapCond.EvapWaterSupTankID).VdotRequestDemand(thisEvapCond.EvapWaterTankDemandARRID) =
3241 0 : thisEvapCond.EvapWaterConsumpRate;
3242 : }
3243 :
3244 : // check if should be starved by restricted flow from tank
3245 5303237 : if (thisEvapCond.EvapWaterSupplyMode == WaterSupply::FromTank) {
3246 : Real64 AvailWaterRate =
3247 0 : state.dataWaterData->WaterStorage(thisEvapCond.EvapWaterSupTankID).VdotAvailDemand(thisEvapCond.EvapWaterTankDemandARRID);
3248 0 : if (AvailWaterRate < thisEvapCond.EvapWaterConsumpRate) {
3249 0 : thisEvapCond.EvapWaterStarvMakupRate = thisEvapCond.EvapWaterConsumpRate - AvailWaterRate;
3250 0 : thisEvapCond.EvapWaterConsumpRate = AvailWaterRate;
3251 : } else {
3252 0 : thisEvapCond.EvapWaterStarvMakupRate = 0.0;
3253 : }
3254 : }
3255 :
3256 5303237 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
3257 0 : thisOutletNode.CO2 = thisInletNode.CO2;
3258 : }
3259 :
3260 5303237 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
3261 0 : thisOutletNode.GenContam = thisInletNode.GenContam;
3262 : }
3263 5303237 : }
3264 :
3265 2962542 : void ReportEvapCooler(EnergyPlusData &state, int const EvapCoolNum)
3266 : {
3267 :
3268 : // SUBROUTINE INFORMATION:
3269 : // AUTHOR Richard J. Liesen
3270 : // DATE WRITTEN Oct 2000
3271 :
3272 2962542 : Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
3273 2962542 : auto &thisEvapCond(state.dataEvapCoolers->EvapCond(EvapCoolNum));
3274 :
3275 : // report the Evap Cooler energy from this component
3276 2962542 : thisEvapCond.EvapCoolerPower = thisEvapCond.EvapCoolerPower;
3277 2962542 : thisEvapCond.EvapCoolerEnergy = thisEvapCond.EvapCoolerPower * TimeStepSysSec;
3278 :
3279 : // Report Water comsumption in cubic meters per timestep
3280 2962542 : thisEvapCond.EvapWaterConsump = thisEvapCond.EvapWaterConsumpRate * TimeStepSysSec;
3281 2962542 : thisEvapCond.EvapWaterStarvMakup = thisEvapCond.EvapWaterStarvMakupRate * TimeStepSysSec;
3282 2962542 : }
3283 :
3284 170440 : void SimZoneEvaporativeCoolerUnit(EnergyPlusData &state,
3285 : std::string_view CompName, // name of the packaged terminal heat pump
3286 : int const ZoneNum, // number of zone being served
3287 : Real64 &SensibleOutputProvided, // sensible capacity delivered to zone
3288 : Real64 &LatentOutputProvided, // Latent add/removal (kg/s), dehumid = negative
3289 : int &CompIndex // index to zone hvac unit
3290 : )
3291 : {
3292 :
3293 : // SUBROUTINE INFORMATION:
3294 : // AUTHOR B. Griffith
3295 : // DATE WRITTEN July 2013
3296 : // MODIFIED na
3297 : // RE-ENGINEERED na
3298 :
3299 : // PURPOSE OF THIS SUBROUTINE:
3300 : // public simulation routine for managing zone hvac evaporative cooler unit
3301 :
3302 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3303 : int CompNum;
3304 :
3305 170440 : auto &ZoneEvapUnit(state.dataEvapCoolers->ZoneEvapUnit);
3306 :
3307 170440 : if (state.dataEvapCoolers->GetInputZoneEvapUnit) {
3308 4 : GetInputZoneEvaporativeCoolerUnit(state);
3309 4 : state.dataEvapCoolers->GetInputZoneEvapUnit = false;
3310 : }
3311 :
3312 : // Find the correct Equipment
3313 170440 : if (CompIndex == 0) {
3314 40 : CompNum = Util::FindItemInList(CompName, ZoneEvapUnit);
3315 40 : if (CompNum == 0) {
3316 0 : ShowFatalError(state, "SimZoneEvaporativeCoolerUnit: Zone evaporative cooler unit not found.");
3317 : }
3318 40 : CompIndex = CompNum;
3319 : } else {
3320 170400 : CompNum = CompIndex;
3321 170400 : if (CompNum < 1 || CompNum > state.dataEvapCoolers->NumZoneEvapUnits) {
3322 0 : ShowFatalError(state,
3323 0 : format("SimZoneEvaporativeCoolerUnit: Invalid CompIndex passed={}, Number of units ={}, Entered Unit name = {}",
3324 : CompNum,
3325 0 : state.dataEvapCoolers->NumZoneEvapUnits,
3326 : CompName));
3327 : }
3328 170400 : if (state.dataEvapCoolers->CheckZoneEvapUnitName(CompNum)) {
3329 40 : if (CompName != ZoneEvapUnit(CompNum).Name) {
3330 0 : ShowFatalError(state,
3331 0 : format("SimZoneEvaporativeCoolerUnit: Invalid CompIndex passed={}, Unit name={}, stored unit name for that index={}",
3332 : CompNum,
3333 : CompName,
3334 0 : ZoneEvapUnit(CompNum).Name));
3335 : }
3336 40 : state.dataEvapCoolers->CheckZoneEvapUnitName(CompNum) = false;
3337 : }
3338 : }
3339 :
3340 170440 : InitZoneEvaporativeCoolerUnit(state, CompNum, ZoneNum);
3341 :
3342 170440 : CalcZoneEvaporativeCoolerUnit(state, CompNum, ZoneNum, SensibleOutputProvided, LatentOutputProvided);
3343 :
3344 170440 : ReportZoneEvaporativeCoolerUnit(state, CompNum);
3345 170440 : }
3346 :
3347 4 : void GetInputZoneEvaporativeCoolerUnit(EnergyPlusData &state)
3348 : {
3349 :
3350 : // SUBROUTINE INFORMATION:
3351 : // AUTHOR B. Griffith
3352 : // DATE WRITTEN July 2013
3353 :
3354 : // PURPOSE OF THIS SUBROUTINE:
3355 : // get input for zone evap cooler unit
3356 :
3357 : // SUBROUTINE PARAMETER DEFINITIONS:
3358 : static constexpr std::string_view routineName = "GetInputZoneEvaporativeCoolerUnit";
3359 : static constexpr std::string_view RoutineName("GetInputZoneEvaporativeCoolerUnit: ");
3360 :
3361 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3362 4 : std::string CurrentModuleObject; // Object type for getting and error messages
3363 4 : Array1D_string Alphas; // Alpha items for object
3364 4 : Array1D<Real64> Numbers; // Numeric items for object
3365 4 : Array1D_string cAlphaFields; // Alpha field names
3366 4 : Array1D_string cNumericFields; // Numeric field names
3367 4 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
3368 4 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
3369 : int NumAlphas; // Number of Alphas for each GetObjectItem call
3370 : int NumNumbers; // Number of Numbers for each GetObjectItem call
3371 : int NumFields; // Total number of fields in object
3372 4 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
3373 : Real64 FanVolFlow;
3374 :
3375 4 : auto &EvapCond(state.dataEvapCoolers->EvapCond);
3376 4 : auto &ZoneEvapUnit(state.dataEvapCoolers->ZoneEvapUnit);
3377 :
3378 4 : if (state.dataEvapCoolers->GetInputEvapComponentsFlag) {
3379 4 : GetEvapInput(state);
3380 4 : state.dataEvapCoolers->GetInputEvapComponentsFlag = false;
3381 : }
3382 :
3383 4 : state.dataEvapCoolers->GetInputZoneEvapUnit = false;
3384 4 : int MaxNumbers = 0;
3385 4 : int MaxAlphas = 0;
3386 :
3387 4 : CurrentModuleObject = "ZoneHVAC:EvaporativeCoolerUnit";
3388 4 : state.dataEvapCoolers->NumZoneEvapUnits = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
3389 4 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNumbers);
3390 4 : MaxNumbers = max(MaxNumbers, NumNumbers);
3391 4 : MaxAlphas = max(MaxAlphas, NumAlphas);
3392 4 : Alphas.allocate(MaxAlphas);
3393 4 : Numbers.dimension(MaxNumbers, 0.0);
3394 4 : cAlphaFields.allocate(MaxAlphas);
3395 4 : cNumericFields.allocate(MaxNumbers);
3396 4 : lAlphaBlanks.dimension(MaxAlphas, true);
3397 4 : lNumericBlanks.dimension(MaxNumbers, true);
3398 :
3399 4 : if (state.dataEvapCoolers->NumZoneEvapUnits > 0) {
3400 : int IOStatus; // Used in GetObjectItem
3401 4 : state.dataEvapCoolers->CheckZoneEvapUnitName.dimension(state.dataEvapCoolers->NumZoneEvapUnits, true);
3402 4 : ZoneEvapUnit.allocate(state.dataEvapCoolers->NumZoneEvapUnits);
3403 :
3404 44 : for (int UnitLoop = 1; UnitLoop <= state.dataEvapCoolers->NumZoneEvapUnits; ++UnitLoop) {
3405 40 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
3406 : CurrentModuleObject,
3407 : UnitLoop,
3408 : Alphas,
3409 : NumAlphas,
3410 : Numbers,
3411 : NumNumbers,
3412 : IOStatus,
3413 : lNumericBlanks,
3414 : lAlphaBlanks,
3415 : cAlphaFields,
3416 : cNumericFields);
3417 :
3418 40 : ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
3419 :
3420 40 : auto &thisZoneEvapUnit = ZoneEvapUnit(UnitLoop);
3421 40 : thisZoneEvapUnit.Name = Alphas(1);
3422 40 : if (lAlphaBlanks(2)) {
3423 0 : thisZoneEvapUnit.AvailSchedIndex = ScheduleManager::ScheduleAlwaysOn;
3424 : } else {
3425 80 : thisZoneEvapUnit.AvailSchedIndex = ScheduleManager::GetScheduleIndex(state,
3426 40 : Alphas(2)); // convert schedule name to pointer (index number)
3427 40 : if (thisZoneEvapUnit.AvailSchedIndex == 0) {
3428 0 : ShowSevereError(state, format("{}=\"{}\" invalid data.", CurrentModuleObject, thisZoneEvapUnit.Name));
3429 0 : ShowContinueError(state, format("invalid-not found {}=\"{}\".", cAlphaFields(2), Alphas(2)));
3430 0 : ErrorsFound = true;
3431 : }
3432 : }
3433 :
3434 40 : if (!lAlphaBlanks(3)) {
3435 0 : thisZoneEvapUnit.AvailManagerListName = Alphas(3);
3436 : }
3437 :
3438 40 : thisZoneEvapUnit.OAInletNodeNum = GetOnlySingleNode(state,
3439 40 : Alphas(4),
3440 : ErrorsFound,
3441 : DataLoopNode::ConnectionObjectType::ZoneHVACEvaporativeCoolerUnit,
3442 40 : Alphas(1),
3443 : DataLoopNode::NodeFluidType::Air,
3444 : DataLoopNode::ConnectionType::OutsideAir,
3445 : NodeInputManager::CompFluidStream::Primary,
3446 : DataLoopNode::ObjectIsParent);
3447 :
3448 40 : thisZoneEvapUnit.UnitOutletNodeNum = GetOnlySingleNode(state,
3449 40 : Alphas(5),
3450 : ErrorsFound,
3451 : DataLoopNode::ConnectionObjectType::ZoneHVACEvaporativeCoolerUnit,
3452 40 : Alphas(1),
3453 : DataLoopNode::NodeFluidType::Air,
3454 : DataLoopNode::ConnectionType::Outlet,
3455 : NodeInputManager::CompFluidStream::Primary,
3456 : DataLoopNode::ObjectIsParent);
3457 :
3458 40 : if (!lAlphaBlanks(6)) {
3459 80 : thisZoneEvapUnit.UnitReliefNodeNum = GetOnlySingleNode(state,
3460 40 : Alphas(6),
3461 : ErrorsFound,
3462 : DataLoopNode::ConnectionObjectType::ZoneHVACEvaporativeCoolerUnit,
3463 40 : Alphas(1),
3464 : DataLoopNode::NodeFluidType::Air,
3465 : DataLoopNode::ConnectionType::Inlet,
3466 : NodeInputManager::CompFluidStream::Primary,
3467 : DataLoopNode::ObjectIsParent);
3468 : }
3469 :
3470 40 : thisZoneEvapUnit.FanName = Alphas(8);
3471 40 : bool errFlag = false;
3472 :
3473 40 : thisZoneEvapUnit.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(7)));
3474 40 : assert(thisZoneEvapUnit.fanType != HVAC::FanType::Invalid);
3475 :
3476 40 : thisZoneEvapUnit.FanIndex = Fans::GetFanIndex(state, thisZoneEvapUnit.FanName);
3477 40 : if (thisZoneEvapUnit.FanIndex == 0) {
3478 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(8), thisZoneEvapUnit.FanName);
3479 0 : ErrorsFound = true;
3480 : } else {
3481 40 : auto *fan = state.dataFans->fans(thisZoneEvapUnit.FanIndex);
3482 40 : assert(thisZoneEvapUnit.fanType == fan->type);
3483 40 : thisZoneEvapUnit.FanInletNodeNum = fan->inletNodeNum;
3484 40 : thisZoneEvapUnit.FanOutletNodeNum = fan->outletNodeNum;
3485 40 : thisZoneEvapUnit.ActualFanVolFlowRate = fan->maxAirFlowRate;
3486 40 : thisZoneEvapUnit.FanAvailSchedPtr = fan->availSchedNum;
3487 : }
3488 :
3489 : // set evap unit to cycling mode for all fan types. Note OpMode var is not used
3490 : // with used for ZONECOOLINGLOADVARIABLESPEEDFAN Cooler Unit Control Method
3491 40 : thisZoneEvapUnit.fanOp = HVAC::FanOp::Cycling;
3492 :
3493 40 : FanVolFlow = 0.0;
3494 40 : if (errFlag) {
3495 0 : ShowContinueError(state, format("specified in {} = {}", CurrentModuleObject, thisZoneEvapUnit.Name));
3496 0 : ErrorsFound = true;
3497 : }
3498 :
3499 40 : thisZoneEvapUnit.DesignAirVolumeFlowRate = Numbers(1);
3500 :
3501 40 : thisZoneEvapUnit.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(9)));
3502 40 : assert(thisZoneEvapUnit.fanPlace != HVAC::FanPlace::Invalid);
3503 :
3504 : // get the zone numer served by the zoneHVAC evaporative cooler
3505 440 : for (int CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
3506 400 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
3507 760 : for (int NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++NodeNum) {
3508 400 : if (thisZoneEvapUnit.UnitOutletNodeNum == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(NodeNum)) {
3509 40 : thisZoneEvapUnit.ZonePtr = CtrlZone;
3510 40 : break;
3511 : }
3512 : }
3513 : }
3514 :
3515 40 : constexpr std::array<std::string_view, static_cast<int>(ControlType::Num)> controlTypeNamesUC = {
3516 : "ZONETEMPERATUREDEADBANDONOFFCYCLING", "ZONECOOLINGLOADONOFFCYCLING", "ZONECOOLINGLOADVARIABLESPEEDFAN"};
3517 40 : thisZoneEvapUnit.ControlSchemeType = static_cast<ControlType>(getEnumValue(controlTypeNamesUC, Alphas(10)));
3518 40 : if (thisZoneEvapUnit.ControlSchemeType == ControlType::Invalid) {
3519 0 : ShowSevereError(state, format("{}=\"{}\" invalid data.", CurrentModuleObject, thisZoneEvapUnit.Name));
3520 0 : ShowContinueError(state, format("invalid choice found {}=\"{}\".", cAlphaFields(10), Alphas(10)));
3521 0 : ErrorsFound = true;
3522 : }
3523 :
3524 40 : thisZoneEvapUnit.ThrottlingRange = Numbers(2);
3525 40 : thisZoneEvapUnit.ThresholdCoolingLoad = Numbers(3);
3526 :
3527 40 : thisZoneEvapUnit.EvapCooler_1_Type_Num = static_cast<EvapCoolerType>(getEnumValue(evapCoolerTypeNamesUC, Alphas(11)));
3528 40 : if (thisZoneEvapUnit.EvapCooler_1_Type_Num != EvapCoolerType::Invalid) {
3529 40 : thisZoneEvapUnit.EvapCooler_1_ObjectClassName = evapCoolerTypeNames[static_cast<int>(thisZoneEvapUnit.EvapCooler_1_Type_Num)];
3530 : } else {
3531 0 : ShowSevereError(state, format("{}=\"{}\" invalid data.", CurrentModuleObject, thisZoneEvapUnit.Name));
3532 0 : ShowContinueError(state, format("invalid choice found {}=\"{}\".", cAlphaFields(11), Alphas(11)));
3533 0 : ErrorsFound = true;
3534 : }
3535 :
3536 40 : thisZoneEvapUnit.EvapCooler_1_Name = Alphas(12);
3537 40 : thisZoneEvapUnit.EvapCooler_1_Index = Util::FindItemInList(Alphas(12), state.dataEvapCoolers->EvapCond, &EvapConditions::Name);
3538 40 : if (thisZoneEvapUnit.EvapCooler_1_Index == 0) {
3539 0 : ShowSevereError(state, format("{}=\"{}\" invalid data.", CurrentModuleObject, thisZoneEvapUnit.Name));
3540 0 : ShowContinueError(state, format("invalid, not found {}=\"{}\".", cAlphaFields(12), Alphas(12)));
3541 0 : ErrorsFound = true;
3542 : }
3543 :
3544 40 : if (!lAlphaBlanks(13)) {
3545 12 : thisZoneEvapUnit.EvapCooler_2_Type_Num = static_cast<EvapCoolerType>(getEnumValue(evapCoolerTypeNamesUC, Alphas(13)));
3546 12 : if (thisZoneEvapUnit.EvapCooler_2_Type_Num != EvapCoolerType::Invalid) {
3547 12 : thisZoneEvapUnit.EvapCooler_2_ObjectClassName = evapCoolerTypeNames[static_cast<int>(thisZoneEvapUnit.EvapCooler_2_Type_Num)];
3548 : } else {
3549 0 : ShowSevereError(state, format("{}=\"{}\" invalid data.", CurrentModuleObject, thisZoneEvapUnit.Name));
3550 0 : ShowContinueError(state, format("invalid choice found {}=\"{}\".", cAlphaFields(13), Alphas(13)));
3551 0 : ErrorsFound = true;
3552 : }
3553 :
3554 12 : if (!lAlphaBlanks(14)) {
3555 12 : thisZoneEvapUnit.EvapCooler_2_Name = Alphas(14);
3556 12 : thisZoneEvapUnit.EvapCooler_2_Index = Util::FindItemInList(Alphas(14), state.dataEvapCoolers->EvapCond, &EvapConditions::Name);
3557 12 : if (thisZoneEvapUnit.EvapCooler_2_Index == 0) {
3558 0 : ShowSevereError(state, format("{}=\"{}\" invalid data.", CurrentModuleObject, thisZoneEvapUnit.Name));
3559 0 : ShowContinueError(state, format("invalid, not found {}=\"{}\".", cAlphaFields(14), Alphas(14)));
3560 0 : ErrorsFound = true;
3561 : }
3562 : } else {
3563 0 : ShowSevereError(state, format("{}=\"{}\" invalid data.", CurrentModuleObject, thisZoneEvapUnit.Name));
3564 0 : ShowContinueError(state, format("missing input for {}", cAlphaFields(14)));
3565 0 : ErrorsFound = true;
3566 : }
3567 : }
3568 :
3569 40 : thisZoneEvapUnit.HVACSizingIndex = 0;
3570 40 : if (!lAlphaBlanks(15)) {
3571 0 : thisZoneEvapUnit.HVACSizingIndex = Util::FindItemInList(Alphas(15), state.dataSize->ZoneHVACSizing);
3572 0 : if (thisZoneEvapUnit.HVACSizingIndex == 0) {
3573 0 : ShowSevereError(state, format("{} = {} not found.", cAlphaFields(15), Alphas(15)));
3574 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, thisZoneEvapUnit.Name));
3575 0 : ErrorsFound = true;
3576 : }
3577 : }
3578 :
3579 40 : if (!lNumericBlanks(4)) {
3580 : // Shut Off Relative Humidity
3581 1 : thisZoneEvapUnit.ShutOffRelativeHumidity = Numbers(4);
3582 : }
3583 :
3584 : // Add fan to component sets array
3585 120 : BranchNodeConnections::SetUpCompSets(state,
3586 : CurrentModuleObject,
3587 : thisZoneEvapUnit.Name,
3588 40 : HVAC::fanTypeNamesUC[(int)thisZoneEvapUnit.fanType],
3589 : thisZoneEvapUnit.FanName,
3590 40 : state.dataLoopNodes->NodeID(thisZoneEvapUnit.FanInletNodeNum),
3591 40 : state.dataLoopNodes->NodeID(thisZoneEvapUnit.FanOutletNodeNum));
3592 :
3593 : // Add first evap cooler to component sets array
3594 80 : BranchNodeConnections::SetUpCompSets(state,
3595 : CurrentModuleObject,
3596 : thisZoneEvapUnit.Name,
3597 : thisZoneEvapUnit.EvapCooler_1_ObjectClassName,
3598 : thisZoneEvapUnit.EvapCooler_1_Name,
3599 40 : state.dataLoopNodes->NodeID(EvapCond(thisZoneEvapUnit.EvapCooler_1_Index).InletNode),
3600 40 : state.dataLoopNodes->NodeID(EvapCond(thisZoneEvapUnit.EvapCooler_1_Index).OutletNode));
3601 :
3602 40 : if (thisZoneEvapUnit.EvapCooler_2_Index > 0) {
3603 : // Add second evap cooler to component sets array
3604 24 : BranchNodeConnections::SetUpCompSets(state,
3605 : CurrentModuleObject,
3606 : thisZoneEvapUnit.Name,
3607 : thisZoneEvapUnit.EvapCooler_2_ObjectClassName,
3608 : thisZoneEvapUnit.EvapCooler_2_Name,
3609 12 : state.dataLoopNodes->NodeID(EvapCond(thisZoneEvapUnit.EvapCooler_2_Index).InletNode),
3610 12 : state.dataLoopNodes->NodeID(EvapCond(thisZoneEvapUnit.EvapCooler_2_Index).OutletNode));
3611 : }
3612 :
3613 : // check that fan type is consistent with control method
3614 40 : if (thisZoneEvapUnit.ControlSchemeType == ControlType::ZoneCoolingLoadVariableSpeedFan) { // must have a VS fan type
3615 20 : if (thisZoneEvapUnit.fanType == HVAC::FanType::Constant) {
3616 0 : ShowSevereError(state, format("{}=\"{}\" invalid data.", CurrentModuleObject, thisZoneEvapUnit.Name));
3617 0 : ShowContinueError(state, "Fan:ConstantVolume is not consistent with control method ZoneCoolingLoadVariableSpeedFan.");
3618 0 : ShowContinueError(state, "Change to a variable speed fan object type");
3619 0 : ErrorsFound = true;
3620 20 : } else if (thisZoneEvapUnit.fanType == HVAC::FanType::OnOff) {
3621 0 : ShowSevereError(state, format("{}=\"{}\" invalid data.", CurrentModuleObject, thisZoneEvapUnit.Name));
3622 0 : ShowContinueError(state, "Fan:OnOff is not consistent with control method ZoneCoolingLoadVariableSpeedFan.");
3623 0 : ShowContinueError(state, "Change to a variable speed fan object type");
3624 0 : ErrorsFound = true;
3625 : }
3626 : }
3627 :
3628 : } // unit loop
3629 : }
3630 :
3631 : //***********************************************************************************
3632 :
3633 4 : Alphas.deallocate();
3634 4 : Numbers.deallocate();
3635 4 : cAlphaFields.deallocate();
3636 4 : cNumericFields.deallocate();
3637 4 : lAlphaBlanks.deallocate();
3638 4 : lNumericBlanks.deallocate();
3639 :
3640 4 : if (ErrorsFound) {
3641 0 : ShowFatalError(state, format("{}Errors found in getting input.", RoutineName));
3642 0 : ShowContinueError(state, "... Preceding condition causes termination.");
3643 : }
3644 :
3645 : // setup output variables
3646 44 : for (int UnitLoop = 1; UnitLoop <= state.dataEvapCoolers->NumZoneEvapUnits; ++UnitLoop) {
3647 40 : auto &thisZoneEvapUnit = ZoneEvapUnit(UnitLoop);
3648 80 : SetupOutputVariable(state,
3649 : "Zone Evaporative Cooler Unit Total Cooling Rate",
3650 : Constant::Units::W,
3651 40 : thisZoneEvapUnit.UnitTotalCoolingRate,
3652 : OutputProcessor::TimeStepType::System,
3653 : OutputProcessor::StoreType::Average,
3654 40 : thisZoneEvapUnit.Name);
3655 80 : SetupOutputVariable(state,
3656 : "Zone Evaporative Cooler Unit Total Cooling Energy",
3657 : Constant::Units::J,
3658 40 : thisZoneEvapUnit.UnitTotalCoolingEnergy,
3659 : OutputProcessor::TimeStepType::System,
3660 : OutputProcessor::StoreType::Sum,
3661 40 : thisZoneEvapUnit.Name,
3662 : Constant::eResource::EnergyTransfer,
3663 : OutputProcessor::Group::HVAC,
3664 : OutputProcessor::EndUseCat::CoolingCoils);
3665 80 : SetupOutputVariable(state,
3666 : "Zone Evaporative Cooler Unit Sensible Cooling Rate",
3667 : Constant::Units::W,
3668 40 : thisZoneEvapUnit.UnitSensibleCoolingRate,
3669 : OutputProcessor::TimeStepType::System,
3670 : OutputProcessor::StoreType::Average,
3671 40 : thisZoneEvapUnit.Name);
3672 80 : SetupOutputVariable(state,
3673 : "Zone Evaporative Cooler Unit Sensible Cooling Energy",
3674 : Constant::Units::J,
3675 40 : thisZoneEvapUnit.UnitSensibleCoolingEnergy,
3676 : OutputProcessor::TimeStepType::System,
3677 : OutputProcessor::StoreType::Sum,
3678 40 : thisZoneEvapUnit.Name);
3679 80 : SetupOutputVariable(state,
3680 : "Zone Evaporative Cooler Unit Latent Heating Rate",
3681 : Constant::Units::W,
3682 40 : thisZoneEvapUnit.UnitLatentHeatingRate,
3683 : OutputProcessor::TimeStepType::System,
3684 : OutputProcessor::StoreType::Average,
3685 40 : thisZoneEvapUnit.Name);
3686 80 : SetupOutputVariable(state,
3687 : "Zone Evaporative Cooler Unit Latent Heating Energy",
3688 : Constant::Units::J,
3689 40 : thisZoneEvapUnit.UnitLatentHeatingEnergy,
3690 : OutputProcessor::TimeStepType::System,
3691 : OutputProcessor::StoreType::Sum,
3692 40 : thisZoneEvapUnit.Name);
3693 80 : SetupOutputVariable(state,
3694 : "Zone Evaporative Cooler Unit Latent Cooling Rate",
3695 : Constant::Units::W,
3696 40 : thisZoneEvapUnit.UnitLatentCoolingRate,
3697 : OutputProcessor::TimeStepType::System,
3698 : OutputProcessor::StoreType::Average,
3699 40 : thisZoneEvapUnit.Name);
3700 80 : SetupOutputVariable(state,
3701 : "Zone Evaporative Cooler Unit Latent Cooling Energy",
3702 : Constant::Units::J,
3703 40 : thisZoneEvapUnit.UnitLatentCoolingEnergy,
3704 : OutputProcessor::TimeStepType::System,
3705 : OutputProcessor::StoreType::Sum,
3706 40 : thisZoneEvapUnit.Name);
3707 80 : SetupOutputVariable(state,
3708 : "Zone Evaporative Cooler Unit Fan Speed Ratio",
3709 : Constant::Units::None,
3710 40 : thisZoneEvapUnit.UnitFanSpeedRatio,
3711 : OutputProcessor::TimeStepType::System,
3712 : OutputProcessor::StoreType::Average,
3713 40 : thisZoneEvapUnit.Name);
3714 40 : SetupOutputVariable(state,
3715 : "Zone Evaporative Cooler Unit Fan Availability Status",
3716 : Constant::Units::None,
3717 40 : (int &)thisZoneEvapUnit.FanAvailStatus,
3718 : OutputProcessor::TimeStepType::System,
3719 : OutputProcessor::StoreType::Average,
3720 40 : thisZoneEvapUnit.Name);
3721 40 : if (thisZoneEvapUnit.ControlSchemeType != ControlType::ZoneCoolingLoadVariableSpeedFan) {
3722 40 : SetupOutputVariable(state,
3723 : "Zone Evaporative Cooler Unit Part Load Ratio",
3724 : Constant::Units::None,
3725 20 : thisZoneEvapUnit.UnitPartLoadRatio,
3726 : OutputProcessor::TimeStepType::System,
3727 : OutputProcessor::StoreType::Average,
3728 20 : thisZoneEvapUnit.Name);
3729 : }
3730 : }
3731 4 : }
3732 :
3733 170440 : void InitZoneEvaporativeCoolerUnit(EnergyPlusData &state,
3734 : int const UnitNum, // unit number
3735 : int const ZoneNum // number of zone being served
3736 : )
3737 : {
3738 :
3739 : // SUBROUTINE INFORMATION:
3740 : // AUTHOR B. Griffith
3741 : // DATE WRITTEN July 2013
3742 :
3743 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3744 170440 : auto &zoneEvapUnit = state.dataEvapCoolers->ZoneEvapUnit(UnitNum);
3745 :
3746 170440 : if (allocated(state.dataAvail->ZoneComp)) {
3747 170400 : if (zoneEvapUnit.MyZoneEq) { // initialize the name of each availability manager list and zone number
3748 40 : state.dataAvail->ZoneComp(DataZoneEquipment::ZoneEquipType::EvaporativeCooler).ZoneCompAvailMgrs(UnitNum).AvailManagerListName =
3749 80 : zoneEvapUnit.AvailManagerListName;
3750 40 : state.dataAvail->ZoneComp(DataZoneEquipment::ZoneEquipType::EvaporativeCooler).ZoneCompAvailMgrs(UnitNum).ZoneNum = ZoneNum;
3751 40 : zoneEvapUnit.MyZoneEq = false;
3752 : }
3753 170400 : zoneEvapUnit.FanAvailStatus =
3754 170400 : state.dataAvail->ZoneComp(DataZoneEquipment::ZoneEquipType::EvaporativeCooler).ZoneCompAvailMgrs(UnitNum).availStatus;
3755 : }
3756 :
3757 170440 : if (!state.dataEvapCoolers->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
3758 4 : state.dataEvapCoolers->ZoneEquipmentListChecked = true;
3759 44 : for (int Loop = 1; Loop <= state.dataEvapCoolers->NumZoneEvapUnits; ++Loop) {
3760 40 : if (DataZoneEquipment::CheckZoneEquipmentList(state, "ZoneHVAC:EvaporativeCoolerUnit", state.dataEvapCoolers->ZoneEvapUnit(Loop).Name)) {
3761 40 : state.dataEvapCoolers->ZoneEvapUnit(Loop).ZoneNodeNum = state.dataZoneEquip->ZoneEquipConfig(ZoneNum).ZoneNode;
3762 : } else {
3763 0 : ShowSevereError(state,
3764 0 : format("InitZoneEvaporativeCoolerUnit: ZoneHVAC:EvaporativeCoolerUnit = {}, is not on any ZoneHVAC:EquipmentList. "
3765 : "It will not be simulated.",
3766 0 : state.dataEvapCoolers->ZoneEvapUnit(Loop).Name));
3767 : }
3768 : }
3769 : }
3770 :
3771 170440 : if (!state.dataGlobal->SysSizingCalc && zoneEvapUnit.MySize) {
3772 40 : SizeZoneEvaporativeCoolerUnit(state, UnitNum);
3773 40 : zoneEvapUnit.MySize = false;
3774 : }
3775 :
3776 170440 : if (zoneEvapUnit.MyFan) {
3777 112 : if (zoneEvapUnit.ActualFanVolFlowRate != DataSizing::AutoSize) {
3778 :
3779 40 : if (zoneEvapUnit.ActualFanVolFlowRate < zoneEvapUnit.DesignAirVolumeFlowRate) {
3780 4 : ShowSevereError(state, format("InitZoneEvaporativeCoolerUnit: ZoneHVAC:EvaporativeCoolerUnit = {}", zoneEvapUnit.Name));
3781 4 : ShowContinueError(state, "...unit fan volumetric flow rate less than evaporative cooler unit design supply air flow rate.");
3782 4 : ShowContinueError(state, format("...fan volumetric flow rate = {:.5T} m3/s.", zoneEvapUnit.ActualFanVolFlowRate));
3783 4 : ShowContinueError(state, format("...evap cooler unit volumetric flow rate = {:.5T} m3/s.", zoneEvapUnit.DesignAirVolumeFlowRate));
3784 4 : zoneEvapUnit.DesignAirVolumeFlowRate = zoneEvapUnit.ActualFanVolFlowRate;
3785 4 : ShowContinueError(state, "...evaporative cooler unit design supply air flow rate will match fan flow rate and simulation continues.");
3786 4 : zoneEvapUnit.MyEnvrn = true; // re-initialize to set mass flow rate and max mass flow rate
3787 : }
3788 :
3789 40 : if (zoneEvapUnit.ActualFanVolFlowRate > 0.0) {
3790 40 : zoneEvapUnit.DesignFanSpeedRatio = zoneEvapUnit.DesignAirVolumeFlowRate / zoneEvapUnit.ActualFanVolFlowRate;
3791 : }
3792 :
3793 40 : zoneEvapUnit.MyFan = false;
3794 : } else {
3795 72 : zoneEvapUnit.ActualFanVolFlowRate = state.dataFans->fans(zoneEvapUnit.FanIndex)->maxAirFlowRate;
3796 : }
3797 : }
3798 :
3799 170440 : if (zoneEvapUnit.FanAvailSchedPtr > 0) {
3800 : // include fan is not available, then unit is not available
3801 340880 : zoneEvapUnit.UnitIsAvailable = ((ScheduleManager::GetCurrentScheduleValue(state, zoneEvapUnit.FanAvailSchedPtr) > 0.0) &&
3802 170440 : (ScheduleManager::GetCurrentScheduleValue(state, zoneEvapUnit.AvailSchedIndex) > 0.0));
3803 : } else {
3804 0 : zoneEvapUnit.UnitIsAvailable = (ScheduleManager::GetCurrentScheduleValue(state, zoneEvapUnit.AvailSchedIndex) > 0.0);
3805 : }
3806 :
3807 170440 : zoneEvapUnit.EvapCooler_1_AvailStatus =
3808 170440 : (ScheduleManager::GetCurrentScheduleValue(state, state.dataEvapCoolers->EvapCond(zoneEvapUnit.EvapCooler_1_Index).SchedPtr) > 0.0);
3809 :
3810 170440 : if (zoneEvapUnit.EvapCooler_2_Index > 0) {
3811 51132 : zoneEvapUnit.EvapCooler_2_AvailStatus =
3812 51132 : (ScheduleManager::GetCurrentScheduleValue(state, state.dataEvapCoolers->EvapCond(zoneEvapUnit.EvapCooler_2_Index).SchedPtr) > 0.0);
3813 : }
3814 : // Do the Begin Environment initializations
3815 170440 : if (state.dataGlobal->BeginEnvrnFlag && zoneEvapUnit.MyEnvrn) {
3816 200 : zoneEvapUnit.DesignAirMassFlowRate = state.dataEnvrn->StdRhoAir * zoneEvapUnit.DesignAirVolumeFlowRate;
3817 200 : state.dataLoopNodes->Node(zoneEvapUnit.OAInletNodeNum).MassFlowRateMax = zoneEvapUnit.DesignAirMassFlowRate;
3818 200 : state.dataLoopNodes->Node(zoneEvapUnit.OAInletNodeNum).MassFlowRateMin = 0.0;
3819 200 : state.dataLoopNodes->Node(zoneEvapUnit.OAInletNodeNum).MassFlowRateMinAvail = 0.0;
3820 :
3821 200 : state.dataLoopNodes->Node(zoneEvapUnit.UnitOutletNodeNum).MassFlowRateMax = zoneEvapUnit.DesignAirMassFlowRate;
3822 200 : state.dataLoopNodes->Node(zoneEvapUnit.UnitOutletNodeNum).MassFlowRateMin = 0.0;
3823 200 : state.dataLoopNodes->Node(zoneEvapUnit.UnitOutletNodeNum).MassFlowRateMinAvail = 0.0;
3824 :
3825 200 : if (zoneEvapUnit.UnitReliefNodeNum > 0) {
3826 200 : state.dataLoopNodes->Node(zoneEvapUnit.UnitReliefNodeNum).MassFlowRateMax = zoneEvapUnit.DesignAirMassFlowRate;
3827 200 : state.dataLoopNodes->Node(zoneEvapUnit.UnitReliefNodeNum).MassFlowRateMin = 0.0;
3828 200 : state.dataLoopNodes->Node(zoneEvapUnit.UnitReliefNodeNum).MassFlowRateMinAvail = 0.0;
3829 : }
3830 200 : zoneEvapUnit.WasOnLastTimestep = false;
3831 200 : zoneEvapUnit.IsOnThisTimestep = false;
3832 200 : zoneEvapUnit.FanSpeedRatio = 0.0;
3833 200 : zoneEvapUnit.UnitFanSpeedRatio = 0.0;
3834 200 : zoneEvapUnit.UnitTotalCoolingRate = 0.0;
3835 200 : zoneEvapUnit.UnitTotalCoolingEnergy = 0.0;
3836 200 : zoneEvapUnit.UnitSensibleCoolingRate = 0.0;
3837 200 : zoneEvapUnit.UnitSensibleCoolingEnergy = 0.0;
3838 200 : zoneEvapUnit.UnitLatentHeatingRate = 0.0;
3839 200 : zoneEvapUnit.UnitLatentHeatingEnergy = 0.0;
3840 200 : zoneEvapUnit.UnitLatentCoolingRate = 0.0;
3841 200 : zoneEvapUnit.UnitLatentCoolingEnergy = 0.0;
3842 200 : zoneEvapUnit.FanAvailStatus = Avail::Status::NoAction;
3843 :
3844 : // place default cold setpoints on control nodes of select evap coolers
3845 200 : if ((zoneEvapUnit.EvapCooler_1_Type_Num == EvapCoolerType::DirectResearchSpecial) ||
3846 180 : (zoneEvapUnit.EvapCooler_1_Type_Num == EvapCoolerType::IndirectRDDSpecial)) {
3847 60 : if (state.dataEvapCoolers->EvapCond(zoneEvapUnit.EvapCooler_1_Index).EvapControlNodeNum > 0) {
3848 60 : state.dataLoopNodes->Node(state.dataEvapCoolers->EvapCond(zoneEvapUnit.EvapCooler_1_Index).EvapControlNodeNum).TempSetPoint = -20.0;
3849 : }
3850 : }
3851 200 : if ((zoneEvapUnit.EvapCooler_2_Type_Num == EvapCoolerType::DirectResearchSpecial) ||
3852 160 : (zoneEvapUnit.EvapCooler_2_Type_Num == EvapCoolerType::IndirectRDDSpecial)) {
3853 40 : if (state.dataEvapCoolers->EvapCond(zoneEvapUnit.EvapCooler_2_Index).EvapControlNodeNum > 0) {
3854 40 : state.dataLoopNodes->Node(state.dataEvapCoolers->EvapCond(zoneEvapUnit.EvapCooler_2_Index).EvapControlNodeNum).TempSetPoint = -20.0;
3855 : }
3856 : }
3857 :
3858 200 : zoneEvapUnit.MyEnvrn = false;
3859 : }
3860 170440 : if (!state.dataGlobal->BeginEnvrnFlag) {
3861 169140 : zoneEvapUnit.MyEnvrn = true;
3862 : }
3863 :
3864 : Real64 TimeElapsed =
3865 170440 : state.dataGlobal->HourOfDay + state.dataGlobal->TimeStep * state.dataGlobal->TimeStepZone + state.dataHVACGlobal->SysTimeElapsed;
3866 170440 : if (zoneEvapUnit.TimeElapsed != TimeElapsed) {
3867 83960 : zoneEvapUnit.WasOnLastTimestep = zoneEvapUnit.IsOnThisTimestep;
3868 83960 : zoneEvapUnit.TimeElapsed = TimeElapsed;
3869 : }
3870 170440 : }
3871 :
3872 40 : void SizeZoneEvaporativeCoolerUnit(EnergyPlusData &state, int const UnitNum) // unit number
3873 : {
3874 :
3875 : // SUBROUTINE INFORMATION:
3876 : // AUTHOR B. Griffith
3877 : // DATE WRITTEN July 2013
3878 : // MODIFIED August 2014 Bereket Nigusse, added scalable sizing
3879 : // MODIFIED January 2013 Daeho Kang, add component sizing table entries
3880 :
3881 : // SUBROUTINE PARAMETER DEFINITIONS:
3882 : static constexpr std::string_view RoutineName("SizeZoneEvaporativeCoolerUnit: "); // include trailing blank space
3883 :
3884 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3885 : Real64 TempSize; // autosized value of coil input field
3886 :
3887 40 : auto &zoneEvapUnit = state.dataEvapCoolers->ZoneEvapUnit(UnitNum);
3888 :
3889 40 : state.dataSize->DataScalableSizingON = false;
3890 40 : state.dataSize->ZoneHeatingOnlyFan = false;
3891 40 : state.dataSize->ZoneCoolingOnlyFan = false;
3892 :
3893 40 : state.dataSize->DataZoneNumber = zoneEvapUnit.ZonePtr;
3894 :
3895 40 : if (state.dataSize->CurZoneEqNum > 0) {
3896 40 : std::string CompName = zoneEvapUnit.Name;
3897 40 : std::string CompType = "ZoneHVAC:EvaporativeCoolerUnit";
3898 40 : bool errorsFound = false;
3899 40 : auto &zoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
3900 40 : bool PrintFlag = true; // TRUE when sizing information is reported in the eio file
3901 :
3902 40 : if (zoneEvapUnit.HVACSizingIndex > 0) {
3903 0 : state.dataSize->ZoneCoolingOnlyFan = true;
3904 : // index of zoneHVAC equipment sizing specification
3905 0 : int zoneHVACIndex = zoneEvapUnit.HVACSizingIndex;
3906 : // Integer representation of sizing method name (e.g., CoolingAirflowSizing, HeatingAirflowSizing,
3907 : // CoolingCapacitySizing, HeatingCapacitySizing, etc.)
3908 0 : int SizingMethod = HVAC::CoolingAirflowSizing;
3909 : // supply air flow rate sizing method (SupplyAirFlowRate, FlowPerFloorArea, FractionOfAutosizedCoolingAirflow,
3910 : // FractionOfAutosizedHeatingAirflow ...)
3911 0 : int SAFMethod = state.dataSize->ZoneHVACSizing(zoneHVACIndex).CoolingSAFMethod;
3912 0 : zoneEqSizing.SizingMethod(SizingMethod) = SAFMethod;
3913 0 : if (SAFMethod == DataSizing::None || SAFMethod == DataSizing::SupplyAirFlowRate || SAFMethod == DataSizing::FlowPerFloorArea ||
3914 : SAFMethod == DataSizing::FractionOfAutosizedCoolingAirflow) {
3915 0 : switch (SAFMethod) {
3916 0 : case DataSizing::SupplyAirFlowRate:
3917 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow > 0.0) {
3918 0 : zoneEqSizing.AirVolFlow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
3919 0 : zoneEqSizing.SystemAirFlow = true;
3920 : }
3921 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
3922 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow > 0.0) {
3923 0 : PrintFlag = false;
3924 : }
3925 0 : break;
3926 0 : case DataSizing::FlowPerFloorArea:
3927 0 : zoneEqSizing.SystemAirFlow = true;
3928 0 : zoneEqSizing.AirVolFlow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow *
3929 0 : state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
3930 0 : TempSize = zoneEqSizing.AirVolFlow;
3931 0 : state.dataSize->DataScalableSizingON = true;
3932 0 : break;
3933 0 : case DataSizing::FractionOfAutosizedCoolingAirflow:
3934 0 : state.dataSize->DataFracOfAutosizedCoolingAirflow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
3935 0 : TempSize = DataSizing::AutoSize;
3936 0 : state.dataSize->DataScalableSizingON = true;
3937 0 : break;
3938 0 : default:
3939 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
3940 : }
3941 :
3942 0 : CoolingAirFlowSizer sizingCoolingAirFlow;
3943 0 : std::string stringOverride = "Design Supply Air Flow Rate [m3/s]";
3944 0 : if (state.dataGlobal->isEpJSON) stringOverride = "design_supply_air_flow_rate [m3/s]";
3945 0 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
3946 0 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
3947 0 : zoneEvapUnit.DesignAirVolumeFlowRate = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
3948 :
3949 0 : } else if (SAFMethod == DataSizing::FlowPerCoolingCapacity) {
3950 0 : SizingMethod = HVAC::CoolingCapacitySizing;
3951 0 : TempSize = DataSizing::AutoSize;
3952 0 : PrintFlag = false;
3953 0 : state.dataSize->DataScalableSizingON = true;
3954 0 : state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolVolFlow;
3955 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).CoolingCapMethod == DataSizing::FractionOfAutosizedCoolingCapacity) {
3956 0 : state.dataSize->DataFracOfAutosizedCoolingCapacity = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity;
3957 : }
3958 0 : CoolingCapacitySizer sizerCoolingCapacity;
3959 0 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
3960 0 : state.dataSize->DataCapacityUsedForSizing = sizerCoolingCapacity.size(state, TempSize, errorsFound);
3961 0 : state.dataSize->DataFlowPerCoolingCapacity = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
3962 0 : PrintFlag = true;
3963 0 : TempSize = DataSizing::AutoSize;
3964 :
3965 0 : CoolingAirFlowSizer sizingCoolingAirFlow;
3966 0 : std::string stringOverride = "Design Supply Air Flow Rate [m3/s]";
3967 0 : if (state.dataGlobal->isEpJSON) stringOverride = "design_supply_air_flow_rate [m3/s]";
3968 0 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
3969 0 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
3970 0 : zoneEvapUnit.DesignAirVolumeFlowRate = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
3971 0 : }
3972 0 : state.dataSize->DataScalableSizingON = false;
3973 0 : state.dataSize->ZoneCoolingOnlyFan = false;
3974 : } else {
3975 : // no scalble sizing method has been specified. Sizing proceeds using the method
3976 : // specified in the zoneHVAC object
3977 : // N1 , \field Maximum Supply Air Flow Rate
3978 40 : state.dataSize->ZoneCoolingOnlyFan = true;
3979 40 : if (zoneEvapUnit.DesignAirVolumeFlowRate > 0.0) {
3980 16 : PrintFlag = false;
3981 : }
3982 40 : TempSize = zoneEvapUnit.DesignAirVolumeFlowRate;
3983 40 : CoolingAirFlowSizer sizingCoolingAirFlow;
3984 40 : std::string stringOverride = "Design Supply Air Flow Rate [m3/s]";
3985 40 : if (state.dataGlobal->isEpJSON) stringOverride = "design_supply_air_flow_rate [m3/s]";
3986 40 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
3987 40 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
3988 40 : zoneEvapUnit.DesignAirVolumeFlowRate = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
3989 40 : state.dataSize->ZoneCoolingOnlyFan = false;
3990 40 : }
3991 40 : }
3992 40 : }
3993 :
3994 170440 : void CalcZoneEvaporativeCoolerUnit(EnergyPlusData &state,
3995 : int const UnitNum, // unit number
3996 : int const ZoneNum, // number of zone being served
3997 : Real64 &SensibleOutputProvided, // sensible capacity delivered to zone
3998 : Real64 &LatentOutputProvided // Latent add/removal (kg/s), dehumid = negative
3999 : )
4000 : {
4001 :
4002 : // SUBROUTINE INFORMATION:
4003 : // AUTHOR B. Griffith
4004 : // DATE WRITTEN July 2013
4005 :
4006 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4007 : Real64 ZoneCoolingLoad;
4008 : Real64 CoolingLoadThreashold;
4009 : Real64 ZoneTemp;
4010 : Real64 CoolSetLowThrottle;
4011 : Real64 CoolSetHiThrottle;
4012 : Real64 PartLoadRatio;
4013 :
4014 : {
4015 170440 : auto &zoneEvapUnit = state.dataEvapCoolers->ZoneEvapUnit(UnitNum);
4016 :
4017 170440 : Real64 relativeHumidity = 100.0 * Psychrometrics::PsyRhFnTdbWPb(state,
4018 170440 : state.dataLoopNodes->Node(zoneEvapUnit.ZoneNodeNum).Temp,
4019 170440 : state.dataLoopNodes->Node(zoneEvapUnit.ZoneNodeNum).HumRat,
4020 170440 : state.dataEnvrn->OutBaroPress,
4021 170440 : "CalcZoneEvaporativeCoolerUnit");
4022 170440 : if (relativeHumidity > zoneEvapUnit.ShutOffRelativeHumidity) {
4023 : // unit is off when humidity is too high
4024 4250 : PartLoadRatio = 0.0;
4025 4250 : zoneEvapUnit.UnitPartLoadRatio = PartLoadRatio;
4026 4250 : CalcZoneEvapUnitOutput(state, UnitNum, PartLoadRatio, SensibleOutputProvided, LatentOutputProvided);
4027 4250 : zoneEvapUnit.IsOnThisTimestep = false;
4028 4250 : return;
4029 : }
4030 :
4031 166190 : if (zoneEvapUnit.ControlSchemeType == ControlType::ZoneTemperatureDeadBandOnOffCycling) {
4032 51132 : ZoneTemp = state.dataLoopNodes->Node(zoneEvapUnit.ZoneNodeNum).Temp;
4033 51132 : CoolSetLowThrottle = state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ZoneNum) - (0.5 * zoneEvapUnit.ThrottlingRange);
4034 51132 : CoolSetHiThrottle = state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ZoneNum) + (0.5 * zoneEvapUnit.ThrottlingRange);
4035 :
4036 51132 : if ((ZoneTemp < CoolSetLowThrottle) || !zoneEvapUnit.UnitIsAvailable) {
4037 35178 : zoneEvapUnit.IsOnThisTimestep = false;
4038 15954 : } else if (ZoneTemp > CoolSetHiThrottle) {
4039 9840 : zoneEvapUnit.IsOnThisTimestep = true;
4040 : } else {
4041 6114 : if (zoneEvapUnit.WasOnLastTimestep) {
4042 6114 : zoneEvapUnit.IsOnThisTimestep = true;
4043 : } else {
4044 0 : zoneEvapUnit.IsOnThisTimestep = false;
4045 : }
4046 : }
4047 :
4048 51132 : if (zoneEvapUnit.IsOnThisTimestep) {
4049 :
4050 15954 : if (zoneEvapUnit.fanOp == HVAC::FanOp::Continuous) {
4051 0 : PartLoadRatio = 1.0;
4052 0 : zoneEvapUnit.UnitPartLoadRatio = PartLoadRatio;
4053 0 : CalcZoneEvapUnitOutput(state, UnitNum, PartLoadRatio, SensibleOutputProvided, LatentOutputProvided);
4054 : } else {
4055 15954 : ZoneCoolingLoad = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToCoolSP;
4056 : // calculate part load ratio for cycling fan/unit first
4057 15954 : ControlZoneEvapUnitOutput(state, UnitNum, ZoneCoolingLoad);
4058 15954 : PartLoadRatio = zoneEvapUnit.UnitPartLoadRatio;
4059 15954 : CalcZoneEvapUnitOutput(state, UnitNum, PartLoadRatio, SensibleOutputProvided, LatentOutputProvided);
4060 : }
4061 :
4062 : } else { // not running
4063 :
4064 35178 : PartLoadRatio = 0.0;
4065 35178 : zoneEvapUnit.UnitPartLoadRatio = PartLoadRatio;
4066 35178 : CalcZoneEvapUnitOutput(state, UnitNum, PartLoadRatio, SensibleOutputProvided, LatentOutputProvided);
4067 : }
4068 :
4069 115058 : } else if (zoneEvapUnit.ControlSchemeType == ControlType::ZoneCoolingLoadOnOffCycling) {
4070 :
4071 : // get zone loads
4072 34088 : ZoneCoolingLoad = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToCoolSP;
4073 34088 : CoolingLoadThreashold = -1.0 * zoneEvapUnit.ThresholdCoolingLoad;
4074 :
4075 34088 : if ((ZoneCoolingLoad < CoolingLoadThreashold) && zoneEvapUnit.UnitIsAvailable) {
4076 :
4077 10636 : if (zoneEvapUnit.fanOp == HVAC::FanOp::Continuous) {
4078 0 : PartLoadRatio = 1.0;
4079 0 : zoneEvapUnit.UnitPartLoadRatio = PartLoadRatio;
4080 0 : CalcZoneEvapUnitOutput(state, UnitNum, PartLoadRatio, SensibleOutputProvided, LatentOutputProvided);
4081 : } else {
4082 : // calculate part load ratio for cycling fan/unit first
4083 10636 : ControlZoneEvapUnitOutput(state, UnitNum, ZoneCoolingLoad);
4084 10636 : PartLoadRatio = zoneEvapUnit.UnitPartLoadRatio;
4085 10636 : CalcZoneEvapUnitOutput(state, UnitNum, PartLoadRatio, SensibleOutputProvided, LatentOutputProvided);
4086 : }
4087 :
4088 : } else {
4089 : // unit is off
4090 23452 : PartLoadRatio = 0.0;
4091 23452 : zoneEvapUnit.UnitPartLoadRatio = PartLoadRatio;
4092 23452 : CalcZoneEvapUnitOutput(state, UnitNum, PartLoadRatio, SensibleOutputProvided, LatentOutputProvided);
4093 : }
4094 :
4095 80970 : } else if (zoneEvapUnit.ControlSchemeType == ControlType::ZoneCoolingLoadVariableSpeedFan) {
4096 : // get zone loads
4097 80970 : ZoneCoolingLoad = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToCoolSP;
4098 80970 : CoolingLoadThreashold = -1.0 * zoneEvapUnit.ThresholdCoolingLoad;
4099 80970 : if ((ZoneCoolingLoad < CoolingLoadThreashold) && zoneEvapUnit.UnitIsAvailable) {
4100 :
4101 : // determine fan speed to meet load
4102 25218 : ControlVSEvapUnitToMeetLoad(state, UnitNum, ZoneCoolingLoad);
4103 : // variable speed fan used fan speed ratio instead of partload ratio
4104 25218 : CalcZoneEvapUnitOutput(state, UnitNum, zoneEvapUnit.FanSpeedRatio, SensibleOutputProvided, LatentOutputProvided);
4105 :
4106 : } else {
4107 : // unit is off
4108 55752 : PartLoadRatio = 0.0;
4109 55752 : CalcZoneEvapUnitOutput(state, UnitNum, PartLoadRatio, SensibleOutputProvided, LatentOutputProvided);
4110 : }
4111 : }
4112 : }
4113 : }
4114 :
4115 271800 : void CalcZoneEvapUnitOutput(EnergyPlusData &state,
4116 : int const UnitNum, // unit number
4117 : Real64 const PartLoadRatio, // zone evap unit part load ratiod
4118 : Real64 &SensibleOutputProvided, // target cooling load
4119 : Real64 &LatentOutputProvided // target cooling load
4120 : )
4121 : {
4122 : // caculates zone evaporative cooler sensible and latent outputs
4123 :
4124 : Real64 MinHumRat; // minimum humidity ratio
4125 :
4126 271800 : auto &zoneEvapUnit = state.dataEvapCoolers->ZoneEvapUnit(UnitNum);
4127 :
4128 271800 : int const ZoneNodeNum = zoneEvapUnit.ZoneNodeNum;
4129 271800 : int const OAInletNodeNum = zoneEvapUnit.OAInletNodeNum;
4130 271800 : int const OutletNodeNum = zoneEvapUnit.UnitOutletNodeNum;
4131 271800 : int const ReliefNodeNum = zoneEvapUnit.UnitReliefNodeNum;
4132 271800 : int const FanInletNodeNum = zoneEvapUnit.FanInletNodeNum;
4133 271800 : int const FanOutletNodeNum = zoneEvapUnit.FanOutletNodeNum;
4134 271800 : int const EvapCooler_1_Index = zoneEvapUnit.EvapCooler_1_Index;
4135 271800 : int const EvapCooler_2_Index = zoneEvapUnit.EvapCooler_2_Index;
4136 :
4137 : // calculate unit sensible cooling output
4138 271800 : if (PartLoadRatio > 0) {
4139 139366 : state.dataLoopNodes->Node(OAInletNodeNum).MassFlowRate = zoneEvapUnit.DesignAirMassFlowRate * PartLoadRatio;
4140 139366 : state.dataLoopNodes->Node(OAInletNodeNum).MassFlowRateMaxAvail = state.dataLoopNodes->Node(OAInletNodeNum).MassFlowRate;
4141 139366 : state.dataLoopNodes->Node(OutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(OAInletNodeNum).MassFlowRate;
4142 139366 : state.dataLoopNodes->Node(OutletNodeNum).MassFlowRateMaxAvail = state.dataLoopNodes->Node(OutletNodeNum).MassFlowRate;
4143 : } else { // not running
4144 132434 : state.dataLoopNodes->Node(OAInletNodeNum).MassFlowRate = 0.0;
4145 132434 : state.dataLoopNodes->Node(OAInletNodeNum).MassFlowRateMaxAvail = 0.0;
4146 132434 : state.dataLoopNodes->Node(FanInletNodeNum).MassFlowRate = 0.0;
4147 132434 : state.dataLoopNodes->Node(FanInletNodeNum).MassFlowRateMaxAvail = 0.0;
4148 132434 : state.dataLoopNodes->Node(FanOutletNodeNum).MassFlowRate = 0.0;
4149 132434 : state.dataLoopNodes->Node(FanOutletNodeNum).MassFlowRateMaxAvail = 0.0;
4150 132434 : state.dataLoopNodes->Node(OutletNodeNum).MassFlowRate = 0.0;
4151 132434 : state.dataLoopNodes->Node(OutletNodeNum).MassFlowRateMaxAvail = 0.0;
4152 :
4153 132434 : state.dataLoopNodes->Node(state.dataEvapCoolers->EvapCond(EvapCooler_1_Index).InletNode).MassFlowRate = 0.0;
4154 132434 : state.dataLoopNodes->Node(state.dataEvapCoolers->EvapCond(EvapCooler_1_Index).InletNode).MassFlowRateMaxAvail = 0.0;
4155 132434 : state.dataLoopNodes->Node(state.dataEvapCoolers->EvapCond(EvapCooler_1_Index).OutletNode).MassFlowRate = 0.0;
4156 132434 : state.dataLoopNodes->Node(state.dataEvapCoolers->EvapCond(EvapCooler_1_Index).OutletNode).MassFlowRateMaxAvail = 0.0;
4157 :
4158 132434 : if (EvapCooler_2_Index > 0) {
4159 41026 : state.dataLoopNodes->Node(state.dataEvapCoolers->EvapCond(EvapCooler_2_Index).InletNode).MassFlowRate = 0.0;
4160 41026 : state.dataLoopNodes->Node(state.dataEvapCoolers->EvapCond(EvapCooler_2_Index).InletNode).MassFlowRateMaxAvail = 0.0;
4161 41026 : state.dataLoopNodes->Node(state.dataEvapCoolers->EvapCond(EvapCooler_2_Index).OutletNode).MassFlowRate = 0.0;
4162 41026 : state.dataLoopNodes->Node(state.dataEvapCoolers->EvapCond(EvapCooler_2_Index).OutletNode).MassFlowRateMaxAvail = 0.0;
4163 : }
4164 : }
4165 271800 : if (ReliefNodeNum > 0) {
4166 271800 : state.dataLoopNodes->Node(ReliefNodeNum).MassFlowRate = state.dataLoopNodes->Node(OAInletNodeNum).MassFlowRate;
4167 271800 : state.dataLoopNodes->Node(ReliefNodeNum).MassFlowRateMaxAvail = state.dataLoopNodes->Node(OAInletNodeNum).MassFlowRate;
4168 : }
4169 271800 : if (zoneEvapUnit.fanPlace == HVAC::FanPlace::BlowThru) {
4170 105062 : state.dataLoopNodes->Node(FanOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(OAInletNodeNum).MassFlowRate;
4171 105062 : state.dataLoopNodes->Node(FanOutletNodeNum).MassFlowRateMaxAvail = state.dataLoopNodes->Node(OAInletNodeNum).MassFlowRate;
4172 105062 : state.dataFans->fans(zoneEvapUnit.FanIndex)->simulate(state, false, _, _);
4173 : }
4174 :
4175 271800 : if (zoneEvapUnit.EvapCooler_1_AvailStatus) {
4176 271800 : SimEvapCooler(state, zoneEvapUnit.EvapCooler_1_Name, zoneEvapUnit.EvapCooler_1_Index, PartLoadRatio);
4177 : }
4178 :
4179 271800 : if ((zoneEvapUnit.EvapCooler_2_Index > 0) && zoneEvapUnit.EvapCooler_2_AvailStatus) {
4180 82502 : SimEvapCooler(state, zoneEvapUnit.EvapCooler_2_Name, zoneEvapUnit.EvapCooler_2_Index, PartLoadRatio);
4181 : }
4182 271800 : if (zoneEvapUnit.fanPlace == HVAC::FanPlace::DrawThru) {
4183 166738 : state.dataFans->fans(zoneEvapUnit.FanIndex)->simulate(state, false, _, _);
4184 : }
4185 :
4186 : // calculate sensible and latent outputs delivered
4187 271800 : MinHumRat = min(state.dataLoopNodes->Node(ZoneNodeNum).HumRat, state.dataLoopNodes->Node(OutletNodeNum).HumRat);
4188 271800 : SensibleOutputProvided = state.dataLoopNodes->Node(OutletNodeNum).MassFlowRate *
4189 271800 : (Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(OutletNodeNum).Temp, MinHumRat) -
4190 271800 : Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(ZoneNodeNum).Temp, MinHumRat));
4191 271800 : LatentOutputProvided = state.dataLoopNodes->Node(OutletNodeNum).MassFlowRate *
4192 271800 : (state.dataLoopNodes->Node(OutletNodeNum).HumRat - state.dataLoopNodes->Node(ZoneNodeNum).HumRat);
4193 271800 : }
4194 :
4195 26590 : void ControlZoneEvapUnitOutput(EnergyPlusData &state,
4196 : int const UnitNum, // unit number
4197 : Real64 const ZoneCoolingLoad // target cooling load
4198 : )
4199 : {
4200 :
4201 : // calculates unit cooling part load ratio using root solver numerical method
4202 :
4203 : // local variables
4204 26590 : int constexpr MaxIte(50); // maximum number of iterations
4205 26590 : Real64 constexpr Tol(0.01); // error tolerance
4206 : Real64 PartLoadRatio; // cooling part load ratio
4207 : Real64 FullFlowSensibleOutput; // full flow sensible cooling output
4208 : Real64 FullFlowLatentOutput; // full flow sensible cooling output
4209 :
4210 26590 : auto &zoneEvapUnit = state.dataEvapCoolers->ZoneEvapUnit(UnitNum);
4211 :
4212 : // get full flow sensible cooling output
4213 26590 : PartLoadRatio = 1.0;
4214 26590 : CalcZoneEvapUnitOutput(state, UnitNum, PartLoadRatio, FullFlowSensibleOutput, FullFlowLatentOutput);
4215 :
4216 : // calculate part load ratio
4217 26590 : if (FullFlowSensibleOutput < ZoneCoolingLoad) {
4218 149540 : auto f = [&state, UnitNum, ZoneCoolingLoad](Real64 PartLoadRatio) {
4219 : // calculates cooling load residual by varying part load ratio
4220 : Real64 QSensOutputProvided; // sensible output at a given PLR
4221 : Real64 QLatOutputProvided; // latent output at a given PLR
4222 74770 : CalcZoneEvapUnitOutput(state, UnitNum, PartLoadRatio, QSensOutputProvided, QLatOutputProvided);
4223 74770 : return QSensOutputProvided - ZoneCoolingLoad;
4224 13802 : };
4225 : int SolFla; // Flag of root solver
4226 13802 : General::SolveRoot(state, Tol, MaxIte, SolFla, PartLoadRatio, f, 0.0, 1.0);
4227 13802 : if (SolFla == -1) {
4228 0 : if (zoneEvapUnit.UnitLoadControlMaxIterErrorIndex == 0) {
4229 0 : ShowWarningError(state, format("Iteration limit exceeded calculating evap unit part load ratio, for unit={}", zoneEvapUnit.Name));
4230 0 : ShowContinueErrorTimeStamp(state, "");
4231 0 : ShowContinueError(state, format("Unit part load ratio returned={:.2R}", PartLoadRatio));
4232 0 : ShowContinueError(state, "Check input for Fan Placement.");
4233 : }
4234 0 : ShowRecurringWarningErrorAtEnd(
4235 : state,
4236 0 : format("Zone Evaporative Cooler unit part load ratio control failed (iteration limit [{}]) for ZoneHVAC:EvaporativeCoolerUnit =\"{}",
4237 : MaxIte,
4238 0 : zoneEvapUnit.Name),
4239 0 : zoneEvapUnit.UnitLoadControlMaxIterErrorIndex);
4240 :
4241 13802 : } else if (SolFla == -2) {
4242 0 : if (zoneEvapUnit.UnitLoadControlLimitsErrorIndex == 0) {
4243 0 : ShowWarningError(state,
4244 0 : format("Zone Evaporative Cooler unit calculation failed: unit part load ratio limits exceeded, for unit = {}",
4245 0 : zoneEvapUnit.Name));
4246 0 : ShowContinueError(state, "Check input for Fan Placement.");
4247 0 : ShowContinueErrorTimeStamp(state, "");
4248 0 : if (state.dataGlobal->WarmupFlag) ShowContinueError(state, "Error occurred during warmup days.");
4249 : }
4250 0 : ShowRecurringWarningErrorAtEnd(
4251 : state,
4252 0 : "Zone Evaporative Cooler unit part load ratio control failed (limits exceeded) for ZoneHVAC:EvaporativeCoolerUnit =\"" +
4253 0 : zoneEvapUnit.Name,
4254 0 : zoneEvapUnit.UnitLoadControlLimitsErrorIndex);
4255 : }
4256 :
4257 : } else {
4258 12788 : PartLoadRatio = 1.0;
4259 : }
4260 26590 : zoneEvapUnit.UnitPartLoadRatio = PartLoadRatio;
4261 26590 : }
4262 :
4263 25218 : void ControlVSEvapUnitToMeetLoad(EnergyPlusData &state,
4264 : int const UnitNum, // unit number
4265 : Real64 const ZoneCoolingLoad // target cooling load
4266 : )
4267 : {
4268 :
4269 : // SUBROUTINE PARAMETER DEFINITIONS:
4270 25218 : int constexpr MaxIte(500); // maximum number of iterations
4271 25218 : auto &zoneEvapUnit = state.dataEvapCoolers->ZoneEvapUnit(UnitNum);
4272 :
4273 : // first get full load result
4274 25218 : zoneEvapUnit.FanSpeedRatio = 1.0;
4275 25218 : state.dataLoopNodes->Node(zoneEvapUnit.OAInletNodeNum).MassFlowRate = zoneEvapUnit.DesignAirMassFlowRate;
4276 25218 : state.dataLoopNodes->Node(zoneEvapUnit.OAInletNodeNum).MassFlowRateMaxAvail = state.dataLoopNodes->Node(zoneEvapUnit.OAInletNodeNum).MassFlowRate;
4277 25218 : state.dataLoopNodes->Node(zoneEvapUnit.UnitOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(zoneEvapUnit.OAInletNodeNum).MassFlowRate;
4278 25218 : state.dataLoopNodes->Node(zoneEvapUnit.UnitOutletNodeNum).MassFlowRateMaxAvail =
4279 25218 : state.dataLoopNodes->Node(zoneEvapUnit.UnitOutletNodeNum).MassFlowRate;
4280 :
4281 25218 : if (zoneEvapUnit.UnitReliefNodeNum > 0) {
4282 25218 : state.dataLoopNodes->Node(zoneEvapUnit.UnitReliefNodeNum).MassFlowRate = state.dataLoopNodes->Node(zoneEvapUnit.OAInletNodeNum).MassFlowRate;
4283 25218 : state.dataLoopNodes->Node(zoneEvapUnit.UnitReliefNodeNum).MassFlowRateMaxAvail =
4284 25218 : state.dataLoopNodes->Node(zoneEvapUnit.OAInletNodeNum).MassFlowRate;
4285 : }
4286 25218 : if (zoneEvapUnit.fanPlace == HVAC::FanPlace::BlowThru) {
4287 19900 : state.dataLoopNodes->Node(zoneEvapUnit.FanOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(zoneEvapUnit.OAInletNodeNum).MassFlowRate;
4288 19900 : state.dataLoopNodes->Node(zoneEvapUnit.FanOutletNodeNum).MassFlowRateMaxAvail =
4289 19900 : state.dataLoopNodes->Node(zoneEvapUnit.OAInletNodeNum).MassFlowRate;
4290 19900 : state.dataFans->fans(zoneEvapUnit.FanIndex)->simulate(state, false, _, _);
4291 : }
4292 :
4293 25218 : if (zoneEvapUnit.EvapCooler_1_AvailStatus) {
4294 25218 : SimEvapCooler(state, zoneEvapUnit.EvapCooler_1_Name, zoneEvapUnit.EvapCooler_1_Index);
4295 : }
4296 :
4297 25218 : if ((zoneEvapUnit.EvapCooler_2_Index > 0) && zoneEvapUnit.EvapCooler_2_AvailStatus) {
4298 9264 : SimEvapCooler(state, zoneEvapUnit.EvapCooler_2_Name, zoneEvapUnit.EvapCooler_2_Index);
4299 : }
4300 25218 : if (zoneEvapUnit.fanPlace == HVAC::FanPlace::DrawThru) {
4301 5318 : state.dataFans->fans(zoneEvapUnit.FanIndex)->simulate(state, false, _, _);
4302 : }
4303 :
4304 : // calculate sensible load met using delta enthalpy at a constant (minimum) humidity ratio)
4305 : Real64 MinHumRat =
4306 25218 : min(state.dataLoopNodes->Node(zoneEvapUnit.ZoneNodeNum).HumRat, state.dataLoopNodes->Node(zoneEvapUnit.UnitOutletNodeNum).HumRat);
4307 25218 : Real64 FullFlowSensibleOutputProvided = state.dataLoopNodes->Node(zoneEvapUnit.UnitOutletNodeNum).MassFlowRate *
4308 25218 : (Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(zoneEvapUnit.UnitOutletNodeNum).Temp, MinHumRat) -
4309 25218 : Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(zoneEvapUnit.ZoneNodeNum).Temp, MinHumRat));
4310 :
4311 25218 : if (FullFlowSensibleOutputProvided < ZoneCoolingLoad) { // find speed ratio by regula falsi numerical method
4312 11612 : Real64 FanSpeedRatio = 1.0;
4313 1563762 : auto f = [&state, UnitNum, ZoneCoolingLoad](Real64 FanSpeedRatio) {
4314 61240 : auto &unit = state.dataEvapCoolers->ZoneEvapUnit(UnitNum);
4315 61240 : state.dataLoopNodes->Node(unit.OAInletNodeNum).MassFlowRate = unit.DesignAirMassFlowRate * FanSpeedRatio;
4316 61240 : state.dataLoopNodes->Node(unit.OAInletNodeNum).MassFlowRateMaxAvail = state.dataLoopNodes->Node(unit.OAInletNodeNum).MassFlowRate;
4317 61240 : state.dataLoopNodes->Node(unit.UnitOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(unit.OAInletNodeNum).MassFlowRate;
4318 61240 : state.dataLoopNodes->Node(unit.UnitOutletNodeNum).MassFlowRateMaxAvail = state.dataLoopNodes->Node(unit.UnitOutletNodeNum).MassFlowRate;
4319 :
4320 61240 : if (unit.UnitReliefNodeNum > 0) {
4321 61240 : state.dataLoopNodes->Node(unit.UnitReliefNodeNum).MassFlowRate = state.dataLoopNodes->Node(unit.OAInletNodeNum).MassFlowRate;
4322 61240 : state.dataLoopNodes->Node(unit.UnitReliefNodeNum).MassFlowRateMaxAvail = state.dataLoopNodes->Node(unit.OAInletNodeNum).MassFlowRate;
4323 : }
4324 61240 : if (unit.fanPlace == HVAC::FanPlace::BlowThru) {
4325 47550 : state.dataLoopNodes->Node(unit.FanOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(unit.OAInletNodeNum).MassFlowRate;
4326 47550 : state.dataLoopNodes->Node(unit.FanOutletNodeNum).MassFlowRateMaxAvail = state.dataLoopNodes->Node(unit.OAInletNodeNum).MassFlowRate;
4327 47550 : state.dataFans->fans(unit.FanIndex)->simulate(state, false, _, _);
4328 : }
4329 :
4330 61240 : if (unit.EvapCooler_1_AvailStatus) {
4331 61240 : SimEvapCooler(state, unit.EvapCooler_1_Name, unit.EvapCooler_1_Index, FanSpeedRatio);
4332 : }
4333 :
4334 61240 : if ((unit.EvapCooler_2_Index > 0) && unit.EvapCooler_2_AvailStatus) {
4335 26282 : SimEvapCooler(state, unit.EvapCooler_2_Name, unit.EvapCooler_2_Index, FanSpeedRatio);
4336 : }
4337 61240 : if (unit.fanPlace == HVAC::FanPlace::DrawThru) {
4338 13690 : state.dataFans->fans(unit.FanIndex)->simulate(state, false, _, _);
4339 : }
4340 :
4341 : Real64 const MinHumRat =
4342 61240 : min(state.dataLoopNodes->Node(unit.ZoneNodeNum).HumRat, state.dataLoopNodes->Node(unit.UnitOutletNodeNum).HumRat);
4343 61240 : Real64 const SensibleOutputProvided = state.dataLoopNodes->Node(unit.UnitOutletNodeNum).MassFlowRate *
4344 61240 : (Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(unit.UnitOutletNodeNum).Temp, MinHumRat) -
4345 61240 : Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(unit.ZoneNodeNum).Temp, MinHumRat));
4346 :
4347 61240 : return SensibleOutputProvided - ZoneCoolingLoad;
4348 11612 : };
4349 11612 : int SolFla = 0; // Flag of RegulaFalsi solver
4350 11612 : Real64 ErrorToler = 0.01;
4351 11612 : General::SolveRoot(state, ErrorToler, MaxIte, SolFla, FanSpeedRatio, f, 0.0, 1.0);
4352 11612 : if (SolFla == -1) {
4353 0 : if (zoneEvapUnit.UnitVSControlMaxIterErrorIndex == 0) {
4354 0 : ShowWarningError(
4355 0 : state, format("Iteration limit exceeded calculating variable speed evap unit fan speed ratio, for unit={}", zoneEvapUnit.Name));
4356 0 : ShowContinueErrorTimeStamp(state, "");
4357 0 : ShowContinueError(state, format("Fan speed ratio returned={:.2R}", FanSpeedRatio));
4358 0 : ShowContinueError(state, "Check input for Fan Placement.");
4359 : }
4360 0 : ShowRecurringWarningErrorAtEnd(
4361 : state,
4362 0 : format("Zone Evaporative Cooler unit control failed (iteration limit [{}]) for ZoneHVAC:EvaporativeCoolerUnit =\"{}",
4363 : MaxIte,
4364 0 : zoneEvapUnit.Name),
4365 0 : zoneEvapUnit.UnitVSControlMaxIterErrorIndex);
4366 :
4367 11612 : } else if (SolFla == -2) {
4368 0 : if (zoneEvapUnit.UnitVSControlLimitsErrorIndex == 0) {
4369 0 : ShowWarningError(state,
4370 0 : format("Variable speed evaporative cooler unit calculation failed: fan speed ratio limits exceeded, for unit = {}",
4371 0 : zoneEvapUnit.Name));
4372 0 : ShowContinueError(state, "Check input for Fan Placement.");
4373 0 : ShowContinueErrorTimeStamp(state, "");
4374 0 : if (state.dataGlobal->WarmupFlag) ShowContinueError(state, "Error occurred during warmup days.");
4375 : }
4376 0 : ShowRecurringWarningErrorAtEnd(state,
4377 0 : "Zone Evaporative Cooler unit control failed (limits exceeded) for ZoneHVAC:EvaporativeCoolerUnit =\"" +
4378 0 : zoneEvapUnit.Name,
4379 0 : zoneEvapUnit.UnitVSControlLimitsErrorIndex);
4380 : }
4381 11612 : zoneEvapUnit.FanSpeedRatio = FanSpeedRatio;
4382 : }
4383 25218 : }
4384 :
4385 170440 : void ReportZoneEvaporativeCoolerUnit(EnergyPlusData &state, int const UnitNum) // unit number
4386 : {
4387 :
4388 : // SUBROUTINE INFORMATION:
4389 : // AUTHOR B. Griffith
4390 : // DATE WRITTEN July 2013
4391 :
4392 : // PURPOSE OF THIS SUBROUTINE:
4393 : // update output variables for the zone evap unit
4394 :
4395 : // Using/Aliasing
4396 170440 : Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
4397 :
4398 170440 : auto &zoneEvapUnit = state.dataEvapCoolers->ZoneEvapUnit(UnitNum);
4399 :
4400 170440 : int ZoneNodeNum = zoneEvapUnit.ZoneNodeNum;
4401 170440 : int UnitOutletNodeNum = zoneEvapUnit.UnitOutletNodeNum;
4402 170440 : Real64 AirMassFlow = state.dataLoopNodes->Node(UnitOutletNodeNum).MassFlowRate;
4403 170440 : Real64 QTotUnitOut = AirMassFlow * (state.dataLoopNodes->Node(UnitOutletNodeNum).Enthalpy - state.dataLoopNodes->Node(ZoneNodeNum).Enthalpy);
4404 170440 : Real64 MinHumRat = min(state.dataLoopNodes->Node(ZoneNodeNum).HumRat, state.dataLoopNodes->Node(UnitOutletNodeNum).HumRat);
4405 170440 : Real64 QSensUnitOut = AirMassFlow * (Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(UnitOutletNodeNum).Temp, MinHumRat) -
4406 170440 : Psychrometrics::PsyHFnTdbW(state.dataLoopNodes->Node(ZoneNodeNum).Temp, MinHumRat));
4407 :
4408 170440 : zoneEvapUnit.UnitTotalCoolingRate = std::abs(min(0.0, QTotUnitOut));
4409 170440 : zoneEvapUnit.UnitTotalCoolingEnergy = zoneEvapUnit.UnitTotalCoolingRate * TimeStepSysSec;
4410 170440 : zoneEvapUnit.UnitSensibleCoolingRate = std::abs(min(0.0, QSensUnitOut));
4411 170440 : zoneEvapUnit.UnitSensibleCoolingEnergy = zoneEvapUnit.UnitSensibleCoolingRate * TimeStepSysSec;
4412 170440 : zoneEvapUnit.UnitLatentHeatingRate = std::abs(max(0.0, (QTotUnitOut - QSensUnitOut)));
4413 170440 : zoneEvapUnit.UnitLatentHeatingEnergy = zoneEvapUnit.UnitLatentHeatingRate * TimeStepSysSec;
4414 170440 : zoneEvapUnit.UnitLatentCoolingRate = std::abs(min(0.0, (QTotUnitOut - QSensUnitOut)));
4415 170440 : zoneEvapUnit.UnitLatentCoolingEnergy = zoneEvapUnit.UnitLatentCoolingRate * TimeStepSysSec;
4416 170440 : zoneEvapUnit.UnitFanSpeedRatio = zoneEvapUnit.FanSpeedRatio;
4417 170440 : }
4418 :
4419 0 : int GetInletNodeNum(EnergyPlusData &state, std::string const &EvapCondName, bool &ErrorsFound)
4420 : {
4421 : // FUNCTION INFORMATION:
4422 : // AUTHOR Lixing Gu
4423 : // DATE WRITTEN May 2019
4424 :
4425 : // PURPOSE OF THIS FUNCTION:
4426 : // This function looks up the given EvapCond and returns the air inlet node number.
4427 : // If incorrect EvapCond name is given, ErrorsFound is returned as true and node number as zero.
4428 :
4429 0 : if (state.dataEvapCoolers->GetInputEvapComponentsFlag) { // First time subroutine has been entered
4430 0 : GetEvapInput(state);
4431 0 : state.dataEvapCoolers->GetInputEvapComponentsFlag = false;
4432 : }
4433 :
4434 : int WhichEvapCond =
4435 0 : Util::FindItemInList(EvapCondName, state.dataEvapCoolers->EvapCond, &EvapConditions::Name, state.dataEvapCoolers->NumEvapCool);
4436 0 : if (WhichEvapCond != 0) {
4437 0 : return state.dataEvapCoolers->EvapCond(WhichEvapCond).InletNode;
4438 : } else {
4439 0 : ShowSevereError(state, format("GetInletNodeNum: Could not find EvaporativeCooler = \"{}\"", EvapCondName));
4440 0 : ErrorsFound = true;
4441 0 : return 0;
4442 : }
4443 : }
4444 :
4445 0 : int GetOutletNodeNum(EnergyPlusData &state, std::string const &EvapCondName, bool &ErrorsFound)
4446 : {
4447 : // FUNCTION INFORMATION:
4448 : // AUTHOR Lixing Gu
4449 : // DATE WRITTEN May 2019
4450 :
4451 : // PURPOSE OF THIS FUNCTION:
4452 : // This function looks up the given EvapCond and returns the air outlet node number.
4453 : // If incorrect EvapCond name is given, ErrorsFound is returned as true and node number as zero.
4454 :
4455 0 : if (state.dataEvapCoolers->GetInputEvapComponentsFlag) { // First time subroutine has been entered
4456 0 : GetEvapInput(state);
4457 0 : state.dataEvapCoolers->GetInputEvapComponentsFlag = false;
4458 : }
4459 : int WhichEvapCond =
4460 0 : Util::FindItemInList(EvapCondName, state.dataEvapCoolers->EvapCond, &EvapConditions::Name, state.dataEvapCoolers->NumEvapCool);
4461 0 : if (WhichEvapCond != 0) {
4462 0 : return state.dataEvapCoolers->EvapCond(WhichEvapCond).OutletNode;
4463 : } else {
4464 0 : ShowSevereError(state, format("GetOutletNodeNum: Could not find EvaporativeCooler = \"{}\"", EvapCondName));
4465 0 : ErrorsFound = true;
4466 0 : return 0;
4467 : }
4468 : }
4469 :
4470 : } // namespace EnergyPlus::EvaporativeCoolers
|