LCOV - code coverage report
Current view: top level - EnergyPlus - EvaporativeCoolers.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 75.1 % 2180 1638
Test Date: 2025-06-02 07:23:51 Functions: 88.2 % 34 30

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

Generated by: LCOV version 2.0-1