LCOV - code coverage report
Current view: top level - EnergyPlus - EvaporativeCoolers.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 49.9 % 2158 1076
Test Date: 2025-05-22 16:09:37 Functions: 67.6 % 34 23

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

Generated by: LCOV version 2.0-1