LCOV - code coverage report
Current view: top level - EnergyPlus - EvaporativeCoolers.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 1639 2174 75.4 %
Date: 2024-08-23 23:50:59 Functions: 30 34 88.2 %

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

Generated by: LCOV version 1.14