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