LCOV - code coverage report
Current view: top level - EnergyPlus - WaterCoils.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 79.8 % 2828 2256
Test Date: 2025-06-02 07:23:51 Functions: 88.1 % 42 37

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <cmath>
      50              : 
      51              : // ObjexxFCL Headers
      52              : #include <ObjexxFCL/Array.functions.hh>
      53              : 
      54              : // EnergyPlus Headers
      55              : #include <EnergyPlus/Autosizing/All_Simple_Sizing.hh>
      56              : #include <EnergyPlus/Autosizing/CoolingAirFlowSizing.hh>
      57              : #include <EnergyPlus/Autosizing/CoolingCapacitySizing.hh>
      58              : #include <EnergyPlus/Autosizing/CoolingWaterDesAirInletHumRatSizing.hh>
      59              : #include <EnergyPlus/Autosizing/CoolingWaterDesAirInletTempSizing.hh>
      60              : #include <EnergyPlus/Autosizing/CoolingWaterDesAirOutletHumRatSizing.hh>
      61              : #include <EnergyPlus/Autosizing/CoolingWaterDesAirOutletTempSizing.hh>
      62              : #include <EnergyPlus/Autosizing/CoolingWaterDesWaterInletTempSizing.hh>
      63              : #include <EnergyPlus/Autosizing/CoolingWaterNumofTubesPerRowSizing.hh>
      64              : #include <EnergyPlus/Autosizing/CoolingWaterflowSizing.hh>
      65              : #include <EnergyPlus/Autosizing/HeatingAirFlowSizing.hh>
      66              : #include <EnergyPlus/Autosizing/HeatingAirflowUASizing.hh>
      67              : #include <EnergyPlus/Autosizing/HeatingCapacitySizing.hh>
      68              : #include <EnergyPlus/Autosizing/HeatingWaterDesAirInletHumRatSizing.hh>
      69              : #include <EnergyPlus/Autosizing/HeatingWaterDesAirInletTempSizing.hh>
      70              : #include <EnergyPlus/Autosizing/HeatingWaterDesCoilLoadUsedForUASizing.hh>
      71              : #include <EnergyPlus/Autosizing/HeatingWaterDesCoilWaterVolFlowUsedForUASizing.hh>
      72              : #include <EnergyPlus/Autosizing/HeatingWaterflowSizing.hh>
      73              : #include <EnergyPlus/Autosizing/WaterHeatingCapacitySizing.hh>
      74              : #include <EnergyPlus/Autosizing/WaterHeatingCoilUASizing.hh>
      75              : #include <EnergyPlus/BranchNodeConnections.hh>
      76              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      77              : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
      78              : #include <EnergyPlus/DataContaminantBalance.hh>
      79              : #include <EnergyPlus/DataEnvironment.hh>
      80              : #include <EnergyPlus/DataHVACGlobals.hh>
      81              : #include <EnergyPlus/DataIPShortCuts.hh>
      82              : #include <EnergyPlus/DataLoopNode.hh>
      83              : #include <EnergyPlus/DataSizing.hh>
      84              : #include <EnergyPlus/DataWater.hh>
      85              : #include <EnergyPlus/EMSManager.hh>
      86              : #include <EnergyPlus/FaultsManager.hh>
      87              : #include <EnergyPlus/FluidProperties.hh>
      88              : #include <EnergyPlus/General.hh>
      89              : #include <EnergyPlus/GeneralRoutines.hh>
      90              : #include <EnergyPlus/GlobalNames.hh>
      91              : #include <EnergyPlus/HVACControllers.hh>
      92              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      93              : #include <EnergyPlus/NodeInputManager.hh>
      94              : #include <EnergyPlus/OutputProcessor.hh>
      95              : #include <EnergyPlus/OutputReportPredefined.hh>
      96              : #include <EnergyPlus/Plant/DataPlant.hh>
      97              : #include <EnergyPlus/PlantUtilities.hh>
      98              : #include <EnergyPlus/Psychrometrics.hh>
      99              : #include <EnergyPlus/ReportCoilSelection.hh>
     100              : #include <EnergyPlus/ScheduleManager.hh>
     101              : #include <EnergyPlus/SetPointManager.hh>
     102              : #include <EnergyPlus/SimAirServingZones.hh>
     103              : #include <EnergyPlus/UtilityRoutines.hh>
     104              : #include <EnergyPlus/WaterCoils.hh>
     105              : #include <EnergyPlus/WaterManager.hh>
     106              : 
     107              : namespace EnergyPlus::WaterCoils {
     108              : // Module containing the WaterCoil simulation routines
     109              : 
     110              : // MODULE INFORMATION:
     111              : //       AUTHOR         Richard J. Liesen
     112              : //       DATE WRITTEN   April 1998
     113              : //       MODIFIED       April 2004: Rahul Chillar
     114              : //                      Feb. 2010, Brent Griffith, Plant Demand Side Update, general fluid properties
     115              : //       RE-ENGINEERED  na
     116              : 
     117              : // PURPOSE OF THIS MODULE:
     118              : // To encapsulate the data and algorithms required to
     119              : // manage the WaterCoil System Component
     120              : 
     121              : using namespace DataLoopNode;
     122              : 
     123              : using Psychrometrics::PsyCpAirFnW;
     124              : using Psychrometrics::PsyHFnTdbRhPb;
     125              : using Psychrometrics::PsyHFnTdbW;
     126              : using Psychrometrics::PsyRhoAirFnPbTdbW;
     127              : using Psychrometrics::PsyTdbFnHW;
     128              : using Psychrometrics::PsyTdpFnWPb;
     129              : using Psychrometrics::PsyTsatFnHPb;
     130              : using Psychrometrics::PsyWFnTdbH;
     131              : using Psychrometrics::PsyWFnTdbRhPb;
     132              : using Psychrometrics::PsyWFnTdbTwbPb;
     133              : using Psychrometrics::PsyWFnTdpPb;
     134              : 
     135    149968186 : void SimulateWaterCoilComponents(EnergyPlusData &state,
     136              :                                  std::string_view CompName,
     137              :                                  bool const FirstHVACIteration,
     138              :                                  int &CompIndex,
     139              :                                  ObjexxFCL::Optional<Real64> QActual,
     140              :                                  ObjexxFCL::Optional<HVAC::FanOp const> fanOpMode,
     141              :                                  ObjexxFCL::Optional<Real64 const> PartLoadRatio)
     142              : {
     143              : 
     144              :     // SUBROUTINE INFORMATION:
     145              :     //       AUTHOR         Richard Liesen
     146              :     //       DATE WRITTEN   February 1998
     147              : 
     148              :     // PURPOSE OF THIS SUBROUTINE:
     149              :     // This subroutine manages WaterCoil component simulation.
     150              : 
     151              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     152              :     int CoilNum;         // The WaterCoil that you are currently loading input into
     153              :     HVAC::FanOp fanOp;   // fan operating mode
     154              :     Real64 PartLoadFrac; // part-load fraction of heating coil
     155              : 
     156              :     // Obtains and Allocates WaterCoil related parameters from input file
     157    149968186 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) { // First time subroutine has been entered
     158            0 :         GetWaterCoilInput(state);
     159            0 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
     160              :     }
     161              : 
     162              :     // Find the correct WaterCoilNumber with the Coil Name
     163    149968186 :     if (CompIndex == 0) {
     164       754287 :         CoilNum = Util::FindItemInList(CompName, state.dataWaterCoils->WaterCoil);
     165       754287 :         if (CoilNum == 0) {
     166            0 :             ShowFatalError(state, format("SimulateWaterCoilComponents: Coil not found={}", CompName));
     167              :         }
     168       754287 :         CompIndex = CoilNum;
     169              :     } else {
     170    149213899 :         CoilNum = CompIndex;
     171    149213899 :         if (CoilNum > state.dataWaterCoils->NumWaterCoils || CoilNum < 1) {
     172            0 :             ShowFatalError(state,
     173            0 :                            format("SimulateWaterCoilComponents: Invalid CompIndex passed={}, Number of Water Coils={}, Coil name={}",
     174              :                                   CoilNum,
     175            0 :                                   state.dataWaterCoils->NumWaterCoils,
     176              :                                   CompName));
     177              :         }
     178    149213899 :         if (state.dataWaterCoils->CheckEquipName(CoilNum)) {
     179         3343 :             auto const &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
     180         3343 :             if (CompName != waterCoil.Name) {
     181            0 :                 ShowFatalError(state,
     182            0 :                                format("SimulateWaterCoilComponents: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
     183              :                                       CoilNum,
     184              :                                       CompName,
     185            0 :                                       waterCoil.Name));
     186              :             }
     187         3343 :             state.dataWaterCoils->CheckEquipName(CoilNum) = false;
     188              :         }
     189              :     }
     190              : 
     191              :     // With the correct CoilNum Initialize
     192    149968186 :     InitWaterCoil(state, CoilNum, FirstHVACIteration); // Initialize all WaterCoil related parameters
     193              : 
     194    149968186 :     if (present(fanOpMode)) {
     195      6216245 :         fanOp = fanOpMode;
     196              :     } else {
     197    143751941 :         fanOp = HVAC::FanOp::Continuous;
     198              :     }
     199    149968186 :     if (present(PartLoadRatio)) {
     200      4815531 :         PartLoadFrac = PartLoadRatio;
     201              :     } else {
     202    145152655 :         PartLoadFrac = 1.0;
     203              :     }
     204              : 
     205    149968186 :     auto const &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
     206              : 
     207              :     // Calculate the Correct WaterCoil Model with the current CoilNum
     208    149968186 :     if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling) {
     209      4920098 :         CalcDetailFlatFinCoolingCoil(state, CoilNum, state.dataWaterCoils->SimCalc, fanOp, PartLoadFrac);
     210      4920098 :         if (present(QActual)) {
     211      4427826 :             QActual = waterCoil.SenWaterCoolingCoilRate;
     212              :         }
     213    145048088 :     } else if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) {
     214     23076407 :         CoolingCoil(state, CoilNum, FirstHVACIteration, state.dataWaterCoils->SimCalc, fanOp, PartLoadFrac);
     215     23076407 :         if (present(QActual)) {
     216     14324993 :             QActual = waterCoil.SenWaterCoolingCoilRate;
     217              :         }
     218              :     }
     219              : 
     220    149968186 :     if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
     221    121971681 :         CalcSimpleHeatingCoil(state, CoilNum, fanOp, PartLoadFrac, state.dataWaterCoils->SimCalc);
     222    121971681 :         if (present(QActual)) {
     223     20779883 :             QActual = waterCoil.TotWaterHeatingCoilRate;
     224              :         }
     225              :     }
     226              : 
     227              :     // Update the current WaterCoil to the outlet nodes
     228    149968186 :     UpdateWaterCoil(state, CoilNum);
     229              : 
     230              :     // Report the current WaterCoil
     231    149968186 :     ReportWaterCoil(state, CoilNum);
     232    149968186 : }
     233              : 
     234              : // Get Input Section of the Module
     235              : //******************************************************************************
     236              : 
     237          337 : void GetWaterCoilInput(EnergyPlusData &state)
     238              : {
     239              : 
     240              :     // SUBROUTINE INFORMATION:
     241              :     //       AUTHOR         Richard Liesen
     242              :     //       DATE WRITTEN   April 1998
     243              :     //       MODIFIED       April 2004: Rahul Chillar
     244              :     //                      November 2013: Tianzhen Hong for fouling coils
     245              :     //       RE-ENGINEERED  na
     246              : 
     247              :     // PURPOSE OF THIS SUBROUTINE:
     248              :     // Obtains input data for coils and stores it in coil data structures
     249              : 
     250              :     // METHODOLOGY EMPLOYED:
     251              :     // Uses "Get" routines to read in data.
     252              : 
     253              :     // SUBROUTINE PARAMETER DEFINITIONS:
     254              :     static constexpr std::string_view RoutineName("GetWaterCoilInput: "); // include trailing blank space
     255              :     static constexpr std::string_view routineName = "GetWaterCoilInput";
     256              : 
     257              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     258              :     int CoilNum; // The WaterCoil that you are currently loading input into
     259          337 :     int NumSimpHeat(0);
     260          337 :     int NumFlatFin(0);
     261          337 :     int NumCooling(0);
     262              :     int SimpHeatNum;
     263              :     int FlatFinNum;
     264              :     int CoolingNum;
     265              :     int NumAlphas;
     266              :     int NumNums;
     267              :     int IOStat;
     268          337 :     std::string CurrentModuleObject; // for ease in getting objects
     269          337 :     Array1D_string AlphArray;        // Alpha input items for object
     270          337 :     Array1D_string cAlphaFields;     // Alpha field names
     271          337 :     Array1D_string cNumericFields;   // Numeric field names
     272          337 :     Array1D<Real64> NumArray;        // Numeric input items for object
     273          337 :     Array1D_bool lAlphaBlanks;       // Logical array, alpha field input BLANK = .TRUE.
     274          337 :     Array1D_bool lNumericBlanks;     // Logical array, numeric field input BLANK = .TRUE.
     275          337 :     int MaxNums(0);                  // Maximum number of numeric input fields
     276          337 :     int MaxAlphas(0);                // Maximum number of alpha input fields
     277          337 :     int TotalArgs(0);                // Total number of alpha and numeric arguments (max) for a certain object in the input file
     278          337 :     bool ErrorsFound(false);         // If errors detected in input
     279              : 
     280          337 :     NumSimpHeat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Heating:Water");
     281          337 :     NumFlatFin = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Cooling:Water:DetailedGeometry");
     282          337 :     NumCooling = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Cooling:Water");
     283          337 :     state.dataWaterCoils->NumWaterCoils = NumSimpHeat + NumFlatFin + NumCooling;
     284              : 
     285          337 :     if (state.dataWaterCoils->NumWaterCoils > 0) {
     286          326 :         state.dataWaterCoils->WaterCoil.allocate(state.dataWaterCoils->NumWaterCoils);
     287          326 :         state.dataWaterCoils->WaterCoilNumericFields.allocate(state.dataWaterCoils->NumWaterCoils);
     288          326 :         state.dataWaterCoils->WaterTempCoolCoilErrs.dimension(state.dataWaterCoils->NumWaterCoils, 0);
     289          326 :         state.dataWaterCoils->PartWetCoolCoilErrs.dimension(state.dataWaterCoils->NumWaterCoils, 0);
     290          326 :         state.dataWaterCoils->CheckEquipName.dimension(state.dataWaterCoils->NumWaterCoils, true);
     291              :     }
     292              : 
     293          337 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "Coil:Heating:Water", TotalArgs, NumAlphas, NumNums);
     294          337 :     MaxNums = max(MaxNums, NumNums);
     295          337 :     MaxAlphas = max(MaxAlphas, NumAlphas);
     296          337 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "Coil:Cooling:Water:DetailedGeometry", TotalArgs, NumAlphas, NumNums);
     297          337 :     MaxNums = max(MaxNums, NumNums);
     298          337 :     MaxAlphas = max(MaxAlphas, NumAlphas);
     299          337 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "Coil:Cooling:Water", TotalArgs, NumAlphas, NumNums);
     300          337 :     MaxNums = max(MaxNums, NumNums);
     301          337 :     MaxAlphas = max(MaxAlphas, NumAlphas);
     302              : 
     303          337 :     AlphArray.allocate(MaxAlphas);
     304          337 :     cAlphaFields.allocate(MaxAlphas);
     305          337 :     cNumericFields.allocate(MaxNums);
     306          337 :     NumArray.dimension(MaxNums, 0.0);
     307          337 :     lAlphaBlanks.dimension(MaxAlphas, true);
     308          337 :     lNumericBlanks.dimension(MaxNums, true);
     309          337 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     310          337 :     CurrentModuleObject = "Coil:Heating:Water";
     311              :     // Get the data for simple heating coils
     312         3092 :     for (SimpHeatNum = 1; SimpHeatNum <= NumSimpHeat; ++SimpHeatNum) {
     313              : 
     314         2755 :         CoilNum = SimpHeatNum;
     315              : 
     316         2755 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     317              :                                                                  CurrentModuleObject,
     318              :                                                                  SimpHeatNum,
     319              :                                                                  AlphArray,
     320              :                                                                  NumAlphas,
     321              :                                                                  NumArray,
     322              :                                                                  NumNums,
     323              :                                                                  IOStat,
     324              :                                                                  lNumericBlanks,
     325              :                                                                  lAlphaBlanks,
     326              :                                                                  cAlphaFields,
     327              :                                                                  cNumericFields);
     328              : 
     329         2755 :         ErrorObjectHeader eoh{routineName, CurrentModuleObject, AlphArray(1)};
     330              : 
     331         2755 :         state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames.allocate(MaxNums);
     332         2755 :         state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames = "";
     333         2755 :         state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames = cNumericFields;
     334         2755 :         Util::IsNameEmpty(state, AlphArray(1), cCurrentModuleObject, ErrorsFound);
     335              : 
     336              :         // ErrorsFound will be set to True if problem was found, left untouched otherwise
     337         2755 :         GlobalNames::VerifyUniqueCoilName(state, CurrentModuleObject, AlphArray(1), ErrorsFound, CurrentModuleObject + " Name");
     338         2755 :         auto &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
     339              : 
     340         2755 :         waterCoil.Name = AlphArray(1);
     341         2755 :         if (lAlphaBlanks(2)) {
     342           49 :             waterCoil.availSched = Sched::GetScheduleAlwaysOn(state);
     343         2706 :         } else if ((waterCoil.availSched = Sched::GetSchedule(state, AlphArray(2))) == nullptr) {
     344            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(2), AlphArray(2));
     345            0 :             ErrorsFound = true;
     346              :         }
     347              : 
     348         2755 :         waterCoil.WaterCoilModelA = "SIMPLE";
     349         2755 :         waterCoil.WaterCoilModel = CoilModel::HeatingSimple; // 'SIMPLE'
     350         2755 :         waterCoil.WaterCoilType = DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
     351              : 
     352         2755 :         waterCoil.UACoil = NumArray(1);
     353         2755 :         waterCoil.UACoilVariable = waterCoil.UACoil;
     354         2755 :         waterCoil.MaxWaterVolFlowRate = NumArray(2);
     355         2755 :         waterCoil.WaterInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     356         2755 :                                                                           AlphArray(3),
     357              :                                                                           ErrorsFound,
     358              :                                                                           DataLoopNode::ConnectionObjectType::CoilHeatingWater,
     359         2755 :                                                                           AlphArray(1),
     360              :                                                                           DataLoopNode::NodeFluidType::Water,
     361              :                                                                           DataLoopNode::ConnectionType::Inlet,
     362              :                                                                           NodeInputManager::CompFluidStream::Secondary,
     363              :                                                                           ObjectIsNotParent);
     364         2755 :         waterCoil.WaterOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     365         2755 :                                                                            AlphArray(4),
     366              :                                                                            ErrorsFound,
     367              :                                                                            DataLoopNode::ConnectionObjectType::CoilHeatingWater,
     368         2755 :                                                                            AlphArray(1),
     369              :                                                                            DataLoopNode::NodeFluidType::Water,
     370              :                                                                            DataLoopNode::ConnectionType::Outlet,
     371              :                                                                            NodeInputManager::CompFluidStream::Secondary,
     372              :                                                                            ObjectIsNotParent);
     373         2755 :         waterCoil.AirInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     374         2755 :                                                                         AlphArray(5),
     375              :                                                                         ErrorsFound,
     376              :                                                                         DataLoopNode::ConnectionObjectType::CoilHeatingWater,
     377         2755 :                                                                         AlphArray(1),
     378              :                                                                         DataLoopNode::NodeFluidType::Air,
     379              :                                                                         DataLoopNode::ConnectionType::Inlet,
     380              :                                                                         NodeInputManager::CompFluidStream::Primary,
     381              :                                                                         ObjectIsNotParent);
     382         2755 :         waterCoil.AirOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     383         2755 :                                                                          AlphArray(6),
     384              :                                                                          ErrorsFound,
     385              :                                                                          DataLoopNode::ConnectionObjectType::CoilHeatingWater,
     386         2755 :                                                                          AlphArray(1),
     387              :                                                                          DataLoopNode::NodeFluidType::Air,
     388              :                                                                          DataLoopNode::ConnectionType::Outlet,
     389              :                                                                          NodeInputManager::CompFluidStream::Primary,
     390              :                                                                          ObjectIsNotParent);
     391              : 
     392         2755 :         if (AlphArray(7) == "NOMINALCAPACITY") { // not "UFACTORTIMESAREAANDDESIGNWATERFLOWRATE"
     393           52 :             waterCoil.CoilPerfInpMeth = state.dataWaterCoils->NomCap;
     394              : 
     395              :         } else {
     396              :             // will be caught by input processor
     397         2703 :             waterCoil.CoilPerfInpMeth = state.dataWaterCoils->UAandFlow;
     398              :         }
     399              : 
     400         2755 :         waterCoil.DesTotWaterCoilLoad = NumArray(3);
     401              : 
     402         2755 :         if (waterCoil.UACoil == DataSizing::AutoSize && waterCoil.CoilPerfInpMeth == state.dataWaterCoils->UAandFlow) {
     403         2401 :             waterCoil.RequestingAutoSize = true;
     404              :         }
     405         2755 :         if (waterCoil.MaxWaterVolFlowRate == DataSizing::AutoSize) {
     406         2449 :             waterCoil.RequestingAutoSize = true;
     407              :         }
     408         2755 :         if (waterCoil.DesTotWaterCoilLoad == DataSizing::AutoSize && waterCoil.CoilPerfInpMeth == state.dataWaterCoils->NomCap) {
     409            9 :             waterCoil.RequestingAutoSize = true;
     410              :         }
     411              : 
     412         2755 :         waterCoil.DesInletWaterTemp = NumArray(4);
     413         2755 :         waterCoil.DesInletAirTemp = NumArray(5);
     414         2755 :         waterCoil.DesOutletWaterTemp = NumArray(6);
     415         2755 :         waterCoil.DesOutletAirTemp = NumArray(7);
     416         2755 :         waterCoil.RatioAirSideToWaterSideConvect = NumArray(8);
     417         2755 :         if (!lNumericBlanks(9)) {
     418          114 :             waterCoil.DesignWaterDeltaTemp = NumArray(9);
     419          114 :             waterCoil.UseDesignWaterDeltaTemp = true;
     420              :         } else {
     421         2641 :             waterCoil.UseDesignWaterDeltaTemp = false;
     422              :         }
     423         2755 :         if (waterCoil.DesInletWaterTemp <= waterCoil.DesOutletWaterTemp) {
     424            0 :             ShowSevereError(state, format("For {}, {}", CurrentModuleObject, AlphArray(1)));
     425            0 :             ShowContinueError(state, format("  the {} must be greater than the {}.", cNumericFields(4), cNumericFields(6)));
     426            0 :             ErrorsFound = true;
     427              :         }
     428         2755 :         if (waterCoil.DesInletAirTemp >= waterCoil.DesOutletAirTemp) {
     429            0 :             ShowSevereError(state, format("For {}, {}", CurrentModuleObject, AlphArray(1)));
     430            0 :             ShowContinueError(state, format("  the {} must be less than the {}.", cNumericFields(5), cNumericFields(7)));
     431            0 :             ErrorsFound = true;
     432              :         }
     433         2755 :         if (waterCoil.DesInletAirTemp >= waterCoil.DesInletWaterTemp) {
     434            0 :             ShowSevereError(state, format("For {}, {}", CurrentModuleObject, AlphArray(1)));
     435            0 :             ShowContinueError(state, format("  the {} must be less than the {}.", cNumericFields(5), cNumericFields(4)));
     436            0 :             ErrorsFound = true;
     437              :         }
     438              : 
     439         5510 :         BranchNodeConnections::TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(3), AlphArray(4), "Water Nodes");
     440         2755 :         BranchNodeConnections::TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(5), AlphArray(6), "Air Nodes");
     441              : 
     442              :         // Setup the Simple Heating Coil reporting variables
     443              :         // CurrentModuleObject = "Coil:Heating:Water"
     444         5510 :         SetupOutputVariable(state,
     445              :                             "Heating Coil Heating Energy",
     446              :                             Constant::Units::J,
     447         2755 :                             waterCoil.TotWaterHeatingCoilEnergy,
     448              :                             OutputProcessor::TimeStepType::System,
     449              :                             OutputProcessor::StoreType::Sum,
     450         2755 :                             waterCoil.Name,
     451              :                             Constant::eResource::EnergyTransfer,
     452              :                             OutputProcessor::Group::HVAC,
     453              :                             OutputProcessor::EndUseCat::HeatingCoils);
     454         5510 :         SetupOutputVariable(state,
     455              :                             "Heating Coil Source Side Heat Transfer Energy",
     456              :                             Constant::Units::J,
     457         2755 :                             waterCoil.TotWaterHeatingCoilEnergy,
     458              :                             OutputProcessor::TimeStepType::System,
     459              :                             OutputProcessor::StoreType::Sum,
     460         2755 :                             waterCoil.Name,
     461              :                             Constant::eResource::PlantLoopHeatingDemand,
     462              :                             OutputProcessor::Group::HVAC,
     463              :                             OutputProcessor::EndUseCat::HeatingCoils);
     464         5510 :         SetupOutputVariable(state,
     465              :                             "Heating Coil Heating Rate",
     466              :                             Constant::Units::W,
     467         2755 :                             waterCoil.TotWaterHeatingCoilRate,
     468              :                             OutputProcessor::TimeStepType::System,
     469              :                             OutputProcessor::StoreType::Average,
     470         2755 :                             waterCoil.Name);
     471         5510 :         SetupOutputVariable(state,
     472              :                             "Heating Coil U Factor Times Area Value",
     473              :                             Constant::Units::W_K,
     474         2755 :                             waterCoil.UACoilVariable,
     475              :                             OutputProcessor::TimeStepType::System,
     476              :                             OutputProcessor::StoreType::Average,
     477         2755 :                             waterCoil.Name);
     478              :     }
     479              : 
     480          337 :     CurrentModuleObject = "Coil:Cooling:Water:DetailedGeometry";
     481              :     // Get the data for detailed cooling coils.
     482          499 :     for (FlatFinNum = 1; FlatFinNum <= NumFlatFin; ++FlatFinNum) {
     483              : 
     484          162 :         CoilNum = NumSimpHeat + FlatFinNum;
     485              : 
     486          162 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     487              :                                                                  CurrentModuleObject,
     488              :                                                                  FlatFinNum,
     489              :                                                                  AlphArray,
     490              :                                                                  NumAlphas,
     491              :                                                                  NumArray,
     492              :                                                                  NumNums,
     493              :                                                                  IOStat,
     494              :                                                                  lNumericBlanks,
     495              :                                                                  lAlphaBlanks,
     496              :                                                                  cAlphaFields,
     497              :                                                                  cNumericFields);
     498              : 
     499          162 :         ErrorObjectHeader eoh{routineName, CurrentModuleObject, AlphArray(1)};
     500              : 
     501          162 :         state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames.allocate(MaxNums);
     502          162 :         state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames = "";
     503          162 :         state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames = cNumericFields;
     504          162 :         Util::IsNameEmpty(state, AlphArray(1), cCurrentModuleObject, ErrorsFound);
     505              : 
     506              :         // ErrorsFound will be set to True if problem was found, left untouched otherwise
     507          162 :         GlobalNames::VerifyUniqueCoilName(state, CurrentModuleObject, AlphArray(1), ErrorsFound, CurrentModuleObject + " Name");
     508              : 
     509          162 :         auto &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
     510          162 :         waterCoil.Name = AlphArray(1);
     511              : 
     512          162 :         if (lAlphaBlanks(2)) {
     513            0 :             waterCoil.availSched = Sched::GetScheduleAlwaysOn(state);
     514          162 :         } else if ((waterCoil.availSched = Sched::GetSchedule(state, AlphArray(2))) == nullptr) {
     515            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(2), AlphArray(2));
     516            0 :             ErrorsFound = true;
     517              :         }
     518              : 
     519          162 :         waterCoil.WaterCoilModelA = "DETAILED FLAT FIN";
     520          162 :         waterCoil.WaterCoilModel = CoilModel::CoolingDetailed; // 'DETAILED FLAT FIN'
     521          162 :         waterCoil.WaterCoilType = DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling;
     522              : 
     523          162 :         waterCoil.MaxWaterVolFlowRate = NumArray(1);
     524          162 :         if (waterCoil.MaxWaterVolFlowRate == DataSizing::AutoSize) {
     525           81 :             waterCoil.RequestingAutoSize = true;
     526              :         }
     527          162 :         waterCoil.TubeOutsideSurfArea = NumArray(2);
     528          162 :         if (waterCoil.TubeOutsideSurfArea == DataSizing::AutoSize) {
     529           81 :             waterCoil.RequestingAutoSize = true;
     530              :         }
     531          162 :         waterCoil.TotTubeInsideArea = NumArray(3);
     532          162 :         if (waterCoil.TotTubeInsideArea == DataSizing::AutoSize) {
     533           81 :             waterCoil.RequestingAutoSize = true;
     534              :         }
     535          162 :         waterCoil.FinSurfArea = NumArray(4);
     536          162 :         if (waterCoil.FinSurfArea == DataSizing::AutoSize) {
     537           81 :             waterCoil.RequestingAutoSize = true;
     538              :         }
     539          162 :         waterCoil.MinAirFlowArea = NumArray(5);
     540          162 :         if (waterCoil.MinAirFlowArea == DataSizing::AutoSize) {
     541           81 :             waterCoil.RequestingAutoSize = true;
     542              :         }
     543          162 :         waterCoil.CoilDepth = NumArray(6);
     544          162 :         if (waterCoil.CoilDepth == DataSizing::AutoSize) {
     545           81 :             waterCoil.RequestingAutoSize = true;
     546              :         }
     547          162 :         waterCoil.FinDiam = NumArray(7);
     548          162 :         if (waterCoil.FinDiam == DataSizing::AutoSize) {
     549           81 :             waterCoil.RequestingAutoSize = true;
     550              :         }
     551          162 :         waterCoil.FinThickness = NumArray(8);
     552          162 :         if (waterCoil.FinThickness <= 0.0) {
     553            0 :             ShowSevereError(state,
     554            0 :                             format("{}: {} must be > 0.0, for {} = {}", CurrentModuleObject, cNumericFields(8), cAlphaFields(1), waterCoil.Name));
     555            0 :             ErrorsFound = true;
     556              :         }
     557          162 :         waterCoil.TubeInsideDiam = NumArray(9);
     558          162 :         waterCoil.TubeOutsideDiam = NumArray(10);
     559          162 :         waterCoil.TubeThermConductivity = NumArray(11);
     560          162 :         if (waterCoil.TubeThermConductivity <= 0.0) {
     561            0 :             ShowSevereError(state,
     562            0 :                             format("{}: {} must be > 0.0, for {} = {}", CurrentModuleObject, cNumericFields(11), cAlphaFields(1), waterCoil.Name));
     563            0 :             ErrorsFound = true;
     564              :         }
     565          162 :         waterCoil.FinThermConductivity = NumArray(12);
     566          162 :         if (waterCoil.FinThermConductivity <= 0.0) {
     567            0 :             ShowSevereError(state,
     568            0 :                             format("{}: {} must be > 0.0, for {} = {}", CurrentModuleObject, cNumericFields(12), cAlphaFields(1), waterCoil.Name));
     569            0 :             ErrorsFound = true;
     570              :         }
     571          162 :         waterCoil.FinSpacing = NumArray(13);
     572          162 :         waterCoil.TubeDepthSpacing = NumArray(14);
     573          162 :         waterCoil.NumOfTubeRows = NumArray(15);
     574          162 :         waterCoil.NumOfTubesPerRow = NumArray(16);
     575          162 :         if (waterCoil.NumOfTubesPerRow == DataSizing::AutoSize) {
     576           78 :             waterCoil.RequestingAutoSize = true;
     577              :         }
     578          162 :         if (!lNumericBlanks(17)) {
     579            1 :             waterCoil.DesignWaterDeltaTemp = NumArray(17);
     580            1 :             waterCoil.UseDesignWaterDeltaTemp = true;
     581              :         } else {
     582          161 :             waterCoil.UseDesignWaterDeltaTemp = false;
     583              :         }
     584          162 :         waterCoil.WaterInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     585          162 :                                                                           AlphArray(3),
     586              :                                                                           ErrorsFound,
     587              :                                                                           DataLoopNode::ConnectionObjectType::CoilCoolingWaterDetailedGeometry,
     588          162 :                                                                           AlphArray(1),
     589              :                                                                           DataLoopNode::NodeFluidType::Water,
     590              :                                                                           DataLoopNode::ConnectionType::Inlet,
     591              :                                                                           NodeInputManager::CompFluidStream::Secondary,
     592              :                                                                           ObjectIsNotParent);
     593          162 :         waterCoil.WaterOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     594          162 :                                                                            AlphArray(4),
     595              :                                                                            ErrorsFound,
     596              :                                                                            DataLoopNode::ConnectionObjectType::CoilCoolingWaterDetailedGeometry,
     597          162 :                                                                            AlphArray(1),
     598              :                                                                            DataLoopNode::NodeFluidType::Water,
     599              :                                                                            DataLoopNode::ConnectionType::Outlet,
     600              :                                                                            NodeInputManager::CompFluidStream::Secondary,
     601              :                                                                            ObjectIsNotParent);
     602          162 :         waterCoil.AirInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     603          162 :                                                                         AlphArray(5),
     604              :                                                                         ErrorsFound,
     605              :                                                                         DataLoopNode::ConnectionObjectType::CoilCoolingWaterDetailedGeometry,
     606          162 :                                                                         AlphArray(1),
     607              :                                                                         DataLoopNode::NodeFluidType::Air,
     608              :                                                                         DataLoopNode::ConnectionType::Inlet,
     609              :                                                                         NodeInputManager::CompFluidStream::Primary,
     610              :                                                                         ObjectIsNotParent);
     611          162 :         waterCoil.AirOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     612          162 :                                                                          AlphArray(6),
     613              :                                                                          ErrorsFound,
     614              :                                                                          DataLoopNode::ConnectionObjectType::CoilCoolingWaterDetailedGeometry,
     615          162 :                                                                          AlphArray(1),
     616              :                                                                          DataLoopNode::NodeFluidType::Air,
     617              :                                                                          DataLoopNode::ConnectionType::Outlet,
     618              :                                                                          NodeInputManager::CompFluidStream::Primary,
     619              :                                                                          ObjectIsNotParent);
     620              : 
     621              :         // A7 ; \field Name of Water Storage Tank for Condensate Collection
     622          162 :         waterCoil.CondensateCollectName = AlphArray(7);
     623          162 :         if (lAlphaBlanks(7)) {
     624          162 :             waterCoil.CondensateCollectMode = state.dataWaterCoils->CondensateDiscarded;
     625              :         } else {
     626            0 :             waterCoil.CondensateCollectMode = state.dataWaterCoils->CondensateToTank;
     627            0 :             WaterManager::SetupTankSupplyComponent(state,
     628              :                                                    waterCoil.Name,
     629              :                                                    CurrentModuleObject,
     630              :                                                    waterCoil.CondensateCollectName,
     631              :                                                    ErrorsFound,
     632            0 :                                                    waterCoil.CondensateTankID,
     633            0 :                                                    waterCoil.CondensateTankSupplyARRID);
     634              :         }
     635              : 
     636          324 :         BranchNodeConnections::TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(3), AlphArray(4), "Water Nodes");
     637          162 :         BranchNodeConnections::TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(5), AlphArray(6), "Air Nodes");
     638              : 
     639              :         // Setup Report variables for the Detailed Flat Fin Cooling Coils
     640              :         // CurrentModuleObject = "Coil:Cooling:Water:DetailedGeometry"
     641          324 :         SetupOutputVariable(state,
     642              :                             "Cooling Coil Total Cooling Energy",
     643              :                             Constant::Units::J,
     644          162 :                             waterCoil.TotWaterCoolingCoilEnergy,
     645              :                             OutputProcessor::TimeStepType::System,
     646              :                             OutputProcessor::StoreType::Sum,
     647          162 :                             waterCoil.Name,
     648              :                             Constant::eResource::EnergyTransfer,
     649              :                             OutputProcessor::Group::HVAC,
     650              :                             OutputProcessor::EndUseCat::CoolingCoils);
     651          324 :         SetupOutputVariable(state,
     652              :                             "Cooling Coil Source Side Heat Transfer Energy",
     653              :                             Constant::Units::J,
     654          162 :                             waterCoil.TotWaterCoolingCoilEnergy,
     655              :                             OutputProcessor::TimeStepType::System,
     656              :                             OutputProcessor::StoreType::Sum,
     657          162 :                             waterCoil.Name,
     658              :                             Constant::eResource::PlantLoopCoolingDemand,
     659              :                             OutputProcessor::Group::HVAC,
     660              :                             OutputProcessor::EndUseCat::CoolingCoils);
     661          324 :         SetupOutputVariable(state,
     662              :                             "Cooling Coil Sensible Cooling Energy",
     663              :                             Constant::Units::J,
     664          162 :                             waterCoil.SenWaterCoolingCoilEnergy,
     665              :                             OutputProcessor::TimeStepType::System,
     666              :                             OutputProcessor::StoreType::Sum,
     667          162 :                             waterCoil.Name);
     668          324 :         SetupOutputVariable(state,
     669              :                             "Cooling Coil Total Cooling Rate",
     670              :                             Constant::Units::W,
     671          162 :                             waterCoil.TotWaterCoolingCoilRate,
     672              :                             OutputProcessor::TimeStepType::System,
     673              :                             OutputProcessor::StoreType::Average,
     674          162 :                             waterCoil.Name);
     675          324 :         SetupOutputVariable(state,
     676              :                             "Cooling Coil Sensible Cooling Rate",
     677              :                             Constant::Units::W,
     678          162 :                             waterCoil.SenWaterCoolingCoilRate,
     679              :                             OutputProcessor::TimeStepType::System,
     680              :                             OutputProcessor::StoreType::Average,
     681          162 :                             waterCoil.Name);
     682              : 
     683          162 :         if (waterCoil.CondensateCollectMode == state.dataWaterCoils->CondensateToTank) {
     684              : 
     685            0 :             SetupOutputVariable(state,
     686              :                                 "Cooling Coil Condensate Volume Flow Rate",
     687              :                                 Constant::Units::m3_s,
     688            0 :                                 waterCoil.CondensateVdot,
     689              :                                 OutputProcessor::TimeStepType::System,
     690              :                                 OutputProcessor::StoreType::Average,
     691            0 :                                 waterCoil.Name);
     692            0 :             SetupOutputVariable(state,
     693              :                                 "Cooling Coil Condensate Volume",
     694              :                                 Constant::Units::m3,
     695            0 :                                 waterCoil.CondensateVol,
     696              :                                 OutputProcessor::TimeStepType::System,
     697              :                                 OutputProcessor::StoreType::Sum,
     698            0 :                                 waterCoil.Name,
     699              :                                 Constant::eResource::OnSiteWater,
     700              :                                 OutputProcessor::Group::HVAC,
     701              :                                 OutputProcessor::EndUseCat::Condensate);
     702              :         }
     703              :     }
     704              : 
     705          337 :     CurrentModuleObject = "Coil:Cooling:Water";
     706              :     // Get the data for Cooling coils.
     707          771 :     for (CoolingNum = 1; CoolingNum <= NumCooling; ++CoolingNum) {
     708              : 
     709          434 :         CoilNum = NumSimpHeat + NumFlatFin + CoolingNum;
     710              : 
     711          434 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     712              :                                                                  CurrentModuleObject,
     713              :                                                                  CoolingNum,
     714              :                                                                  AlphArray,
     715              :                                                                  NumAlphas,
     716              :                                                                  NumArray,
     717              :                                                                  NumNums,
     718              :                                                                  IOStat,
     719              :                                                                  lNumericBlanks,
     720              :                                                                  lAlphaBlanks,
     721              :                                                                  cAlphaFields,
     722              :                                                                  cNumericFields);
     723              : 
     724          434 :         ErrorObjectHeader eoh{routineName, CurrentModuleObject, AlphArray(1)};
     725          434 :         state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames.allocate(MaxNums);
     726          434 :         state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames = "";
     727          434 :         state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames = cNumericFields;
     728          434 :         Util::IsNameEmpty(state, AlphArray(1), cCurrentModuleObject, ErrorsFound);
     729              : 
     730              :         // ErrorsFound will be set to True if problem was found, left untouched otherwise
     731          434 :         GlobalNames::VerifyUniqueCoilName(state, CurrentModuleObject, AlphArray(1), ErrorsFound, CurrentModuleObject + " Name");
     732              : 
     733          434 :         auto &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
     734          434 :         waterCoil.Name = AlphArray(1);
     735              : 
     736          434 :         if (lAlphaBlanks(2)) {
     737           24 :             waterCoil.availSched = Sched::GetScheduleAlwaysOn(state);
     738          410 :         } else if ((waterCoil.availSched = Sched::GetSchedule(state, AlphArray(2))) == nullptr) {
     739            0 :             ShowSevereItemNotFound(state, eoh, cAlphaFields(2), AlphArray(2));
     740            0 :             ErrorsFound = true;
     741              :         }
     742              : 
     743          434 :         waterCoil.WaterCoilModelA = "Cooling";
     744          434 :         waterCoil.WaterCoilModel = CoilModel::CoolingSimple; // 'Cooling'
     745          434 :         waterCoil.WaterCoilType = DataPlant::PlantEquipmentType::CoilWaterCooling;
     746              : 
     747          434 :         waterCoil.MaxWaterVolFlowRate = NumArray(1); // Liquid mass flow rate at Design  kg/s
     748          434 :         if (waterCoil.MaxWaterVolFlowRate == DataSizing::AutoSize) {
     749          412 :             waterCoil.RequestingAutoSize = true;
     750              :         }
     751          434 :         waterCoil.DesAirVolFlowRate = NumArray(2); // Dry air mass flow rate at Design (kg/s)
     752          434 :         if (waterCoil.DesAirVolFlowRate == DataSizing::AutoSize) {
     753          412 :             waterCoil.RequestingAutoSize = true;
     754              :         }
     755          434 :         waterCoil.DesInletWaterTemp = NumArray(3); // Entering water temperature at Design C
     756          434 :         if (waterCoil.DesInletWaterTemp == DataSizing::AutoSize) {
     757          399 :             waterCoil.RequestingAutoSize = true;
     758              :         }
     759          434 :         waterCoil.DesInletAirTemp = NumArray(4); // Entering air dry bulb temperature at Design(C)
     760          434 :         if (waterCoil.DesInletAirTemp == DataSizing::AutoSize) {
     761          407 :             waterCoil.RequestingAutoSize = true;
     762              :         }
     763          434 :         waterCoil.DesOutletAirTemp = NumArray(5); // Leaving air dry bulb temperature at Design(C)
     764          434 :         if (waterCoil.DesOutletAirTemp == DataSizing::AutoSize) {
     765          407 :             waterCoil.RequestingAutoSize = true;
     766              :         }
     767          434 :         waterCoil.DesInletAirHumRat = NumArray(6); // Entering air humidity ratio  at Design
     768          434 :         if (waterCoil.DesInletAirHumRat == DataSizing::AutoSize) {
     769          407 :             waterCoil.RequestingAutoSize = true;
     770              :         }
     771          434 :         waterCoil.DesOutletAirHumRat = NumArray(7); // Leaving air humidity ratio  at Design
     772          434 :         if (waterCoil.DesOutletAirHumRat == DataSizing::AutoSize) {
     773          407 :             waterCoil.RequestingAutoSize = true;
     774              :         }
     775          434 :         if (!lNumericBlanks(8)) {
     776           33 :             waterCoil.DesignWaterDeltaTemp = NumArray(8);
     777           33 :             waterCoil.UseDesignWaterDeltaTemp = true;
     778              :         } else {
     779          401 :             waterCoil.UseDesignWaterDeltaTemp = false;
     780              :         }
     781              : 
     782          434 :         waterCoil.WaterInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     783          434 :                                                                           AlphArray(3),
     784              :                                                                           ErrorsFound,
     785              :                                                                           DataLoopNode::ConnectionObjectType::CoilCoolingWater,
     786          434 :                                                                           AlphArray(1),
     787              :                                                                           DataLoopNode::NodeFluidType::Water,
     788              :                                                                           DataLoopNode::ConnectionType::Inlet,
     789              :                                                                           NodeInputManager::CompFluidStream::Secondary,
     790              :                                                                           ObjectIsNotParent);
     791          434 :         waterCoil.WaterOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     792          434 :                                                                            AlphArray(4),
     793              :                                                                            ErrorsFound,
     794              :                                                                            DataLoopNode::ConnectionObjectType::CoilCoolingWater,
     795          434 :                                                                            AlphArray(1),
     796              :                                                                            DataLoopNode::NodeFluidType::Water,
     797              :                                                                            DataLoopNode::ConnectionType::Outlet,
     798              :                                                                            NodeInputManager::CompFluidStream::Secondary,
     799              :                                                                            ObjectIsNotParent);
     800          434 :         waterCoil.AirInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     801          434 :                                                                         AlphArray(5),
     802              :                                                                         ErrorsFound,
     803              :                                                                         DataLoopNode::ConnectionObjectType::CoilCoolingWater,
     804          434 :                                                                         AlphArray(1),
     805              :                                                                         DataLoopNode::NodeFluidType::Air,
     806              :                                                                         DataLoopNode::ConnectionType::Inlet,
     807              :                                                                         NodeInputManager::CompFluidStream::Primary,
     808              :                                                                         ObjectIsNotParent);
     809          434 :         waterCoil.AirOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     810          434 :                                                                          AlphArray(6),
     811              :                                                                          ErrorsFound,
     812              :                                                                          DataLoopNode::ConnectionObjectType::CoilCoolingWater,
     813          434 :                                                                          AlphArray(1),
     814              :                                                                          DataLoopNode::NodeFluidType::Air,
     815              :                                                                          DataLoopNode::ConnectionType::Outlet,
     816              :                                                                          NodeInputManager::CompFluidStream::Primary,
     817              :                                                                          ObjectIsNotParent);
     818              : 
     819              :         // The default is SimpleAnalysis = 2.  and DetailedAnalysis   =1
     820          434 :         if (AlphArray(7) == "DETAILEDANALYSIS") { // not "SIMPLEANALYSIS"
     821           54 :             waterCoil.CoolingCoilAnalysisMode = state.dataWaterCoils->DetailedAnalysis;
     822              : 
     823              :         } else {
     824          380 :             waterCoil.CoolingCoilAnalysisMode = state.dataWaterCoils->SimpleAnalysis;
     825              :         }
     826              : 
     827              :         // The default is CrossFlow = 2.  and CounterFlow=1
     828          434 :         if (AlphArray(8) == "COUNTERFLOW") { // not "CROSSFLOW"
     829            1 :             waterCoil.HeatExchType = state.dataWaterCoils->CounterFlow;
     830              : 
     831              :         } else {
     832          433 :             waterCoil.HeatExchType = state.dataWaterCoils->CrossFlow;
     833              :         }
     834              : 
     835              :         // A9; \field Name of Water Storage Tank for Condensate Collection
     836          434 :         waterCoil.CondensateCollectName = AlphArray(9);
     837          434 :         if (lAlphaBlanks(9)) {
     838          434 :             waterCoil.CondensateCollectMode = state.dataWaterCoils->CondensateDiscarded;
     839              :         } else {
     840            0 :             waterCoil.CondensateCollectMode = state.dataWaterCoils->CondensateToTank;
     841            0 :             WaterManager::SetupTankSupplyComponent(state,
     842              :                                                    waterCoil.Name,
     843              :                                                    CurrentModuleObject,
     844              :                                                    waterCoil.CondensateCollectName,
     845              :                                                    ErrorsFound,
     846            0 :                                                    waterCoil.CondensateTankID,
     847            0 :                                                    waterCoil.CondensateTankSupplyARRID);
     848              :         }
     849              : 
     850          868 :         BranchNodeConnections::TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(3), AlphArray(4), "Water Nodes");
     851          434 :         BranchNodeConnections::TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(5), AlphArray(6), "Air Nodes");
     852              : 
     853              :         // Setup Report variables for the Design input Cooling Coils
     854              :         // CurrentModuleObject = "Coil:Cooling:Water"
     855          868 :         SetupOutputVariable(state,
     856              :                             "Cooling Coil Total Cooling Energy",
     857              :                             Constant::Units::J,
     858          434 :                             waterCoil.TotWaterCoolingCoilEnergy,
     859              :                             OutputProcessor::TimeStepType::System,
     860              :                             OutputProcessor::StoreType::Sum,
     861          434 :                             waterCoil.Name,
     862              :                             Constant::eResource::EnergyTransfer,
     863              :                             OutputProcessor::Group::HVAC,
     864              :                             OutputProcessor::EndUseCat::CoolingCoils);
     865          868 :         SetupOutputVariable(state,
     866              :                             "Cooling Coil Source Side Heat Transfer Energy",
     867              :                             Constant::Units::J,
     868          434 :                             waterCoil.TotWaterCoolingCoilEnergy,
     869              :                             OutputProcessor::TimeStepType::System,
     870              :                             OutputProcessor::StoreType::Sum,
     871          434 :                             waterCoil.Name,
     872              :                             Constant::eResource::PlantLoopCoolingDemand,
     873              :                             OutputProcessor::Group::HVAC,
     874              :                             OutputProcessor::EndUseCat::CoolingCoils);
     875          868 :         SetupOutputVariable(state,
     876              :                             "Cooling Coil Sensible Cooling Energy",
     877              :                             Constant::Units::J,
     878          434 :                             waterCoil.SenWaterCoolingCoilEnergy,
     879              :                             OutputProcessor::TimeStepType::System,
     880              :                             OutputProcessor::StoreType::Sum,
     881          434 :                             waterCoil.Name);
     882          868 :         SetupOutputVariable(state,
     883              :                             "Cooling Coil Total Cooling Rate",
     884              :                             Constant::Units::W,
     885          434 :                             waterCoil.TotWaterCoolingCoilRate,
     886              :                             OutputProcessor::TimeStepType::System,
     887              :                             OutputProcessor::StoreType::Average,
     888          434 :                             waterCoil.Name);
     889          868 :         SetupOutputVariable(state,
     890              :                             "Cooling Coil Sensible Cooling Rate",
     891              :                             Constant::Units::W,
     892          434 :                             waterCoil.SenWaterCoolingCoilRate,
     893              :                             OutputProcessor::TimeStepType::System,
     894              :                             OutputProcessor::StoreType::Average,
     895          434 :                             waterCoil.Name);
     896          868 :         SetupOutputVariable(state,
     897              :                             "Cooling Coil Wetted Area Fraction",
     898              :                             Constant::Units::None,
     899          434 :                             waterCoil.SurfAreaWetFraction,
     900              :                             OutputProcessor::TimeStepType::System,
     901              :                             OutputProcessor::StoreType::Average,
     902          434 :                             waterCoil.Name);
     903              : 
     904          434 :         if (waterCoil.CondensateCollectMode == state.dataWaterCoils->CondensateToTank) {
     905              : 
     906            0 :             SetupOutputVariable(state,
     907              :                                 "Cooling Coil Condensate Volume Flow Rate",
     908              :                                 Constant::Units::m3_s,
     909            0 :                                 waterCoil.CondensateVdot,
     910              :                                 OutputProcessor::TimeStepType::System,
     911              :                                 OutputProcessor::StoreType::Average,
     912            0 :                                 waterCoil.Name);
     913            0 :             SetupOutputVariable(state,
     914              :                                 "Cooling Coil Condensate Volume",
     915              :                                 Constant::Units::m3,
     916            0 :                                 waterCoil.CondensateVol,
     917              :                                 OutputProcessor::TimeStepType::System,
     918              :                                 OutputProcessor::StoreType::Sum,
     919            0 :                                 waterCoil.Name,
     920              :                                 Constant::eResource::OnSiteWater,
     921              :                                 OutputProcessor::Group::HVAC,
     922              :                                 OutputProcessor::EndUseCat::Condensate);
     923              :         }
     924              :     }
     925              : 
     926          337 :     if (ErrorsFound) {
     927            0 :         ShowFatalError(state, format("{}Errors found in getting input.", RoutineName));
     928              :     }
     929              : 
     930          337 :     AlphArray.deallocate();
     931          337 :     cAlphaFields.deallocate();
     932          337 :     cNumericFields.deallocate();
     933          337 :     NumArray.deallocate();
     934          337 :     lAlphaBlanks.deallocate();
     935          337 :     lNumericBlanks.deallocate();
     936          337 : }
     937              : 
     938    149968186 : void InitWaterCoil(EnergyPlusData &state, int const CoilNum, bool const FirstHVACIteration)
     939              : {
     940              : 
     941              :     // SUBROUTINE INFORMATION:
     942              :     //       AUTHOR         Richard J. Liesen
     943              :     //       DATE WRITTEN   February 1998
     944              :     //       MODIFIED       April 2004: Rahul Chillar
     945              :     //                      November 2013: XP, Tianzhen Hong to handle fouling coils
     946              :     //       RE-ENGINEERED  na
     947              : 
     948              :     // PURPOSE OF THIS SUBROUTINE:
     949              :     // This subroutine is for initializations of the WaterCoil Components.
     950              : 
     951              :     // METHODOLOGY EMPLOYED:
     952              :     // Uses the status flags to trigger initializations.
     953              : 
     954              :     // SUBROUTINE PARAMETER DEFINITIONS:
     955    149968186 :     constexpr Real64 SmallNo(1.e-9); // SmallNo number in place of zero
     956    149968186 :     constexpr int itmax(10);
     957    149968186 :     constexpr int MaxIte(500); // Maximum number of iterations
     958              :     static constexpr std::string_view RoutineName("InitWaterCoil");
     959              : 
     960              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     961              :     int tempCoilNum;                   // loop variable
     962              :     Real64 DesInletAirEnth;            // Entering air enthalpy at rating (J/kg)
     963              :     Real64 DesOutletAirEnth;           // Leaving air enthalpy at rating(J/kg)
     964              :     Real64 DesAirApparatusDewPtEnth;   // Air enthalpy at apparatus dew point at rating(J/kg)
     965              :     Real64 DesSatEnthAtWaterInTemp;    // Saturated enthalpy at entering liquid temp(J/kg)
     966              :     Real64 DesHumRatAtWaterInTemp;     // Enthalpy at water inlet temp and entering air HumRat (J/kg)
     967              :     Real64 CapacitanceAir;             // Air-side capacity rate(W/C)
     968              :     Real64 DesAirTempApparatusDewPt;   // Temperature apparatus dew point at design capacity
     969              :     Real64 DesAirHumRatApparatusDewPt; // Humidity Ratio at apparatus dew point at design capacity
     970              :     Real64 DesBypassFactor;            // ByPass Factor at design condition
     971              :     Real64 SlopeTempVsHumRatio;        // Ratio temperature difference to humidity difference
     972              :     // between entering and leaving air states
     973              :     Real64 TempApparatusDewPtEstimate; // Estimate of TAdp from SlopeTempVsHumRatio
     974              :     Real64 Y1;                         // Previous values of dependent variable in ITERATE
     975              :     Real64 X1;                         // Previous values of independent variable in ITERATE
     976              :     Real64 error;                      // Deviation of dependent variable in iteration
     977              :     int iter;                          // Iteration counter
     978              :     int icvg;                          // Iteration convergence flag
     979              :     Real64 ResultX;                    // Output variable from ITERATE function.
     980              :     int Ipass;                         // loop index for App_Dewpoint_Loop
     981              :     int AirInletNode;
     982              :     int WaterInletNode;
     983              :     int WaterOutletNode;
     984              :     Real64 FinDiamVar;
     985              :     Real64 TubeToFinDiamRatio;
     986              :     Real64 CpAirStd; // specific heat of air at std conditions
     987              :     int SolFla;      // Flag of solver
     988              :     Real64 UA0;      // lower bound for UA
     989              :     Real64 UA1;      // upper bound for UA
     990              :     Real64 UA;
     991              :     Real64 DesUACoilExternalEnth; // enthalpy based UAExternal for wet coil surface {kg/s}
     992              :     Real64 LogMeanEnthDiff;       // long mean enthalpy difference {J/kg}
     993              :     Real64 LogMeanTempDiff;       // long mean temperature difference {C}
     994              :     Real64 DesOutletWaterTemp;
     995              :     Real64 DesSatEnthAtWaterOutTemp;
     996              :     Real64 DesEnthAtWaterOutTempAirInHumRat;
     997              :     Real64 DesEnthWaterOut;
     998              :     Real64 Cp;  // local fluid specific heat
     999              :     Real64 rho; // local fluid density
    1000              :     bool errFlag;
    1001    149968186 :     Real64 EnthCorrFrac(0.0); // enthalpy correction factor
    1002    149968186 :     Real64 TempCorrFrac(0.0); // temperature correction factor
    1003              : 
    1004    149968186 :     if (state.dataWaterCoils->InitWaterCoilOneTimeFlag) {
    1005              :         // initialize the environment and sizing flags
    1006          326 :         state.dataWaterCoils->MyEnvrnFlag.allocate(state.dataWaterCoils->NumWaterCoils);
    1007          326 :         state.dataWaterCoils->MySizeFlag.allocate(state.dataWaterCoils->NumWaterCoils);
    1008          326 :         state.dataWaterCoils->CoilWarningOnceFlag.allocate(state.dataWaterCoils->NumWaterCoils);
    1009          326 :         state.dataWaterCoils->DesCpAir.allocate(state.dataWaterCoils->NumWaterCoils);
    1010          326 :         state.dataWaterCoils->MyUAAndFlowCalcFlag.allocate(state.dataWaterCoils->NumWaterCoils);
    1011          326 :         state.dataWaterCoils->MyCoilDesignFlag.allocate(state.dataWaterCoils->NumWaterCoils);
    1012          326 :         state.dataWaterCoils->MyCoilReportFlag.allocate(state.dataWaterCoils->NumWaterCoils);
    1013          326 :         state.dataWaterCoils->DesUARangeCheck.allocate(state.dataWaterCoils->NumWaterCoils);
    1014          326 :         state.dataWaterCoils->PlantLoopScanFlag.allocate(state.dataWaterCoils->NumWaterCoils);
    1015              : 
    1016          326 :         state.dataWaterCoils->DesCpAir = 0.0;
    1017          326 :         state.dataWaterCoils->DesUARangeCheck = 0.0;
    1018          326 :         state.dataWaterCoils->MyEnvrnFlag = true;
    1019          326 :         state.dataWaterCoils->MySizeFlag = true;
    1020          326 :         state.dataWaterCoils->CoilWarningOnceFlag = true;
    1021          326 :         state.dataWaterCoils->MyUAAndFlowCalcFlag = true;
    1022          326 :         state.dataWaterCoils->MyCoilDesignFlag = true;
    1023          326 :         state.dataWaterCoils->MyCoilReportFlag = true;
    1024          326 :         state.dataWaterCoils->InitWaterCoilOneTimeFlag = false;
    1025          326 :         state.dataWaterCoils->PlantLoopScanFlag = true;
    1026              : 
    1027         3677 :         for (tempCoilNum = 1; tempCoilNum <= state.dataWaterCoils->NumWaterCoils; ++tempCoilNum) {
    1028         3351 :             HVACControllers::GetControllerNameAndIndex(state,
    1029         3351 :                                                        state.dataWaterCoils->WaterCoil(tempCoilNum).WaterInletNodeNum,
    1030         3351 :                                                        state.dataWaterCoils->WaterCoil(tempCoilNum).ControllerName,
    1031         3351 :                                                        state.dataWaterCoils->WaterCoil(tempCoilNum).ControllerIndex,
    1032              :                                                        errFlag);
    1033              :         }
    1034              :     }
    1035              : 
    1036    149968186 :     if (state.dataWaterCoils->WaterCoilControllerCheckOneTimeFlag && (state.dataHVACGlobal->GetAirPathDataDone)) {
    1037          326 :         bool ErrorsFound = false;
    1038          326 :         bool WaterCoilOnAirLoop = true;
    1039         3677 :         for (tempCoilNum = 1; tempCoilNum <= state.dataWaterCoils->NumWaterCoils; ++tempCoilNum) {
    1040         3351 :             if (state.dataWaterCoils->WaterCoil(tempCoilNum).ControllerIndex > 0) {
    1041          902 :                 SimAirServingZones::CompType CoilTypeNum(SimAirServingZones::CompType::Invalid);
    1042          902 :                 std::string CompType;
    1043          902 :                 std::string const &CompName = state.dataWaterCoils->WaterCoil(tempCoilNum).Name;
    1044          902 :                 if (state.dataWaterCoils->WaterCoil(tempCoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) {
    1045          309 :                     CoilTypeNum = SimAirServingZones::CompType::WaterCoil_Cooling;
    1046          309 :                     CompType = HVAC::cAllCoilTypes(HVAC::Coil_CoolingWater);
    1047          593 :                 } else if (state.dataWaterCoils->WaterCoil(tempCoilNum).WaterCoilType ==
    1048              :                            DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling) {
    1049          162 :                     CoilTypeNum = SimAirServingZones::CompType::WaterCoil_DetailedCool;
    1050          162 :                     CompType = HVAC::cAllCoilTypes(HVAC::Coil_CoolingWaterDetailed);
    1051          431 :                 } else if (state.dataWaterCoils->WaterCoil(tempCoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
    1052          431 :                     CoilTypeNum = SimAirServingZones::CompType::WaterCoil_SimpleHeat;
    1053          431 :                     CompType = HVAC::cAllCoilTypes(HVAC::Coil_HeatingWater);
    1054              :                 }
    1055          902 :                 WaterCoilOnAirLoop = true;
    1056          902 :                 SimAirServingZones::CheckWaterCoilIsOnAirLoop(state, CoilTypeNum, CompType, CompName, WaterCoilOnAirLoop);
    1057          902 :                 if (!WaterCoilOnAirLoop) {
    1058            0 :                     ShowContinueError(state,
    1059            0 :                                       format("Controller:WaterCoil = {}. Invalid water controller entry.",
    1060            0 :                                              state.dataWaterCoils->WaterCoil(tempCoilNum).ControllerName));
    1061            0 :                     ErrorsFound = true;
    1062              :                 }
    1063          902 :             }
    1064              :         }
    1065          326 :         state.dataWaterCoils->WaterCoilControllerCheckOneTimeFlag = false;
    1066          326 :         if (ErrorsFound) {
    1067            0 :             ShowFatalError(state, "Program terminated for previous condition.");
    1068              :         }
    1069              :     }
    1070              : 
    1071    149968186 :     auto &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    1072    149968186 :     if (state.dataWaterCoils->PlantLoopScanFlag(CoilNum) && allocated(state.dataPlnt->PlantLoop)) {
    1073         3351 :         errFlag = false;
    1074         3351 :         PlantUtilities::ScanPlantLoopsForObject(state, waterCoil.Name, waterCoil.WaterCoilType, waterCoil.WaterPlantLoc, errFlag, _, _, _, _, _);
    1075         3351 :         if (errFlag) {
    1076            0 :             ShowFatalError(state, "InitWaterCoil: Program terminated for previous conditions.");
    1077              :         }
    1078         3351 :         state.dataWaterCoils->PlantLoopScanFlag(CoilNum) = false;
    1079              :     }
    1080    149968186 :     if (!state.dataGlobal->SysSizingCalc && state.dataWaterCoils->MySizeFlag(CoilNum)) {
    1081              :         // for each coil, do the sizing once.
    1082         3351 :         SizeWaterCoil(state, CoilNum);
    1083              : 
    1084         3351 :         state.dataWaterCoils->MySizeFlag(CoilNum) = false;
    1085              :     }
    1086              : 
    1087              :     // Do the Begin Environment initializations
    1088    149968186 :     if (state.dataGlobal->BeginEnvrnFlag && state.dataWaterCoils->MyEnvrnFlag(CoilNum)) {
    1089        22164 :         rho = state.dataPlnt->PlantLoop(waterCoil.WaterPlantLoc.loopNum).glycol->getDensity(state, Constant::InitConvTemp, RoutineName);
    1090              :         // Initialize all report variables to a known state at beginning of simulation
    1091        22164 :         waterCoil.TotWaterHeatingCoilEnergy = 0.0;
    1092        22164 :         waterCoil.TotWaterCoolingCoilEnergy = 0.0;
    1093        22164 :         waterCoil.SenWaterCoolingCoilEnergy = 0.0;
    1094        22164 :         waterCoil.TotWaterHeatingCoilRate = 0.0;
    1095        22164 :         waterCoil.TotWaterCoolingCoilRate = 0.0;
    1096        22164 :         waterCoil.SenWaterCoolingCoilRate = 0.0;
    1097              : 
    1098              :         // The rest of the one time initializations
    1099        22164 :         AirInletNode = waterCoil.AirInletNodeNum;
    1100        22164 :         WaterInletNode = waterCoil.WaterInletNodeNum;
    1101        22164 :         WaterOutletNode = waterCoil.WaterOutletNodeNum;
    1102              : 
    1103        22164 :         state.dataWaterCoils->DesCpAir(CoilNum) = PsyCpAirFnW(0.0);
    1104        22164 :         state.dataWaterCoils->DesUARangeCheck(CoilNum) = (-1568.6 * waterCoil.DesInletAirHumRat + 20.157);
    1105              : 
    1106        22164 :         if ((waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) ||
    1107        19302 :             (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling)) { // 'Cooling'
    1108         3867 :             auto &waterInletNode = state.dataLoopNodes->Node(WaterInletNode);
    1109         3867 :             waterInletNode.Temp = 5.0;
    1110              : 
    1111         3867 :             Cp = state.dataPlnt->PlantLoop(waterCoil.WaterPlantLoc.loopNum).glycol->getSpecificHeat(state, waterInletNode.Temp, RoutineName);
    1112              : 
    1113         3867 :             waterInletNode.Enthalpy = Cp * waterInletNode.Temp;
    1114         3867 :             waterInletNode.Quality = 0.0;
    1115         3867 :             waterInletNode.Press = 0.0;
    1116         3867 :             waterInletNode.HumRat = 0.0;
    1117              :         }
    1118              : 
    1119        22164 :         if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) { // 'Heating'
    1120        18297 :             auto &waterInletNode = state.dataLoopNodes->Node(WaterInletNode);
    1121        18297 :             waterInletNode.Temp = 60.0;
    1122              : 
    1123        18297 :             Cp = state.dataPlnt->PlantLoop(waterCoil.WaterPlantLoc.loopNum).glycol->getSpecificHeat(state, waterInletNode.Temp, RoutineName);
    1124              : 
    1125        18297 :             waterInletNode.Enthalpy = Cp * waterInletNode.Temp;
    1126        18297 :             waterInletNode.Quality = 0.0;
    1127        18297 :             waterInletNode.Press = 0.0;
    1128        18297 :             waterInletNode.HumRat = 0.0;
    1129        18297 :             state.dataWaterCoils->MyUAAndFlowCalcFlag(CoilNum) = false;
    1130              :             // fill values for variable UA
    1131        18297 :             CpAirStd = PsyCpAirFnW(0.0);
    1132        18297 :             waterCoil.DesAirMassFlowRate = state.dataEnvrn->StdRhoAir * waterCoil.DesAirVolFlowRate;
    1133        18297 :             waterCoil.LiquidSideNominalConvect =
    1134        18297 :                 waterCoil.UACoil * (waterCoil.RatioAirSideToWaterSideConvect + 1) / waterCoil.RatioAirSideToWaterSideConvect;
    1135        18297 :             waterCoil.AirSideNominalConvect = waterCoil.RatioAirSideToWaterSideConvect * waterCoil.LiquidSideNominalConvect;
    1136              :         } else {
    1137         3867 :             state.dataWaterCoils->MyUAAndFlowCalcFlag(CoilNum) = false;
    1138              :         }
    1139              : 
    1140        22164 :         waterCoil.MaxWaterMassFlowRate = rho * waterCoil.MaxWaterVolFlowRate;
    1141              : 
    1142        22164 :         PlantUtilities::InitComponentNodes(state, 0.0, waterCoil.MaxWaterMassFlowRate, waterCoil.WaterInletNodeNum, waterCoil.WaterOutletNodeNum);
    1143              : 
    1144              :         // effective fin diameter for detailed flat fin coil
    1145        22164 :         if (waterCoil.WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
    1146         1005 :             waterCoil.EffectiveFinDiam =
    1147         1005 :                 std::sqrt(4.0 * waterCoil.FinDiam * waterCoil.CoilDepth / (Constant::Pi * waterCoil.NumOfTubeRows * waterCoil.NumOfTubesPerRow));
    1148              : 
    1149              :             //   calculate fixed geometric parameters of the coil:
    1150              :             //   Total Area
    1151         1005 :             waterCoil.TotCoilOutsideSurfArea = waterCoil.TubeOutsideSurfArea + waterCoil.FinSurfArea;
    1152              :             //   Effective Tube Inside Diameter - the model assumes that the coil
    1153              :             //   can be simulated as a tube with an equivalent hydraulic diameter.
    1154         1005 :             waterCoil.CoilEffectiveInsideDiam = 4.0 * waterCoil.MinAirFlowArea * waterCoil.CoilDepth / waterCoil.TotCoilOutsideSurfArea;
    1155              :             //   Ratio of tube outside diameter to effective fin diameter should always
    1156              :             //   be less than 1
    1157         1005 :             TubeToFinDiamRatio = waterCoil.TubeOutsideDiam / waterCoil.EffectiveFinDiam;
    1158         1005 :             if (TubeToFinDiamRatio > 1.0) {
    1159            0 :                 ShowWarningError(state, format("InitWaterCoil: Detailed Flat Fin Coil, TubetoFinDiamRatio > 1.0, [{:.4R}]", TubeToFinDiamRatio));
    1160              :                 // reset tube depth spacing and recalc dependent parameters
    1161            0 :                 waterCoil.TubeDepthSpacing *= (pow_2(TubeToFinDiamRatio) + 0.1);
    1162            0 :                 waterCoil.CoilDepth = waterCoil.TubeDepthSpacing * waterCoil.NumOfTubeRows;
    1163            0 :                 waterCoil.EffectiveFinDiam =
    1164            0 :                     std::sqrt(4.0 * waterCoil.FinDiam * waterCoil.CoilDepth / (Constant::Pi * waterCoil.NumOfTubeRows * waterCoil.NumOfTubesPerRow));
    1165            0 :                 waterCoil.CoilEffectiveInsideDiam = 4.0 * waterCoil.MinAirFlowArea * waterCoil.CoilDepth / waterCoil.TotCoilOutsideSurfArea;
    1166            0 :                 TubeToFinDiamRatio = waterCoil.TubeOutsideDiam / waterCoil.EffectiveFinDiam;
    1167            0 :                 ShowContinueError(state, format("  Resetting tube depth spacing to {:.4R} meters", waterCoil.TubeDepthSpacing));
    1168            0 :                 ShowContinueError(state, format("  Resetting coil depth to {:.4R} meters", waterCoil.CoilDepth));
    1169              :             }
    1170              : 
    1171         1005 :             CalcDryFinEffCoef(state, TubeToFinDiamRatio, state.dataWaterCoils->CoefSeries);
    1172              : 
    1173         1005 :             waterCoil.DryFinEfficncyCoef = state.dataWaterCoils->CoefSeries;
    1174              : 
    1175         1005 :             FinDiamVar = 0.5 * (waterCoil.EffectiveFinDiam - waterCoil.TubeOutsideDiam);
    1176              : 
    1177         1005 :             waterCoil.GeometryCoef1 = 0.159 * std::pow(waterCoil.FinThickness / waterCoil.CoilEffectiveInsideDiam, -0.065) *
    1178         1005 :                                       std::pow(waterCoil.FinThickness / FinDiamVar, 0.141);
    1179         1005 :             waterCoil.GeometryCoef2 = -0.323 * std::pow(waterCoil.FinSpacing / FinDiamVar, 0.049) *
    1180         1005 :                                       std::pow(waterCoil.EffectiveFinDiam / waterCoil.TubeDepthSpacing, 0.549) *
    1181         1005 :                                       std::pow(waterCoil.FinThickness / waterCoil.FinSpacing, -0.028);
    1182              : 
    1183              :             // Set some initial values for simulation
    1184         1005 :             waterCoil.SatEnthlCurveConstCoef = -10.57;
    1185         1005 :             waterCoil.SatEnthlCurveSlope = 3.3867;
    1186         1005 :             waterCoil.EnthVsTempCurveAppxSlope = 3.3867;
    1187         1005 :             waterCoil.EnthVsTempCurveConst = -10.57;
    1188              :             // Set Saved Values to Zero
    1189         1005 :             waterCoil.SurfAreaWetSaved = 0.0;
    1190         1005 :             waterCoil.MeanWaterTempSaved = 0.0;
    1191         1005 :             waterCoil.InWaterTempSaved = 0.0;
    1192         1005 :             waterCoil.OutWaterTempSaved = 0.0;
    1193              : 
    1194              :         } // End the Detailed Flat Fin Coil Initialization
    1195              : 
    1196              :         // Calculation for Cooling Coil, The part between the '@@@' are design condition
    1197              :         // and are calculated only once to calculate standard values for UAs and other physical parameters of
    1198              :         // the cooling coil.
    1199              :         // Basic Idea for UA:  Heat Transfer= UAenthalpybased*(Delta enthalpy), this is a necessity since the
    1200              :         // coil may be Wet or Dry or Partially Wet-Dry, so latent effects are accounted for in this model while
    1201              :         // calculating the UA. A fictitious specific heat is also defined to calculate the conventional UA.
    1202              :         // On the air side, enthalpy capacity rate is the air mass flow rate,while on water side it is
    1203              :         // enthalpy of saturated air at water temperature.
    1204              :         //@@@ DESIGN CONDITION BEGIN HERE @@@
    1205              : 
    1206              :         // Check for zero design cooling capacity as specified by coil design inputs
    1207        41908 :         if (state.dataWaterCoils->MyCoilDesignFlag(CoilNum) && (waterCoil.WaterCoilModel == CoilModel::CoolingSimple) &&
    1208        41908 :             (waterCoil.DesAirVolFlowRate > 0.0) && (waterCoil.MaxWaterMassFlowRate > 0.0)) {
    1209              : 
    1210          432 :             DesInletAirEnth = PsyHFnTdbW(waterCoil.DesInletAirTemp, waterCoil.DesInletAirHumRat);
    1211          432 :             DesOutletAirEnth = PsyHFnTdbW(waterCoil.DesOutletAirTemp, waterCoil.DesOutletAirHumRat);
    1212              :             DesSatEnthAtWaterInTemp =
    1213          432 :                 PsyHFnTdbW(waterCoil.DesInletWaterTemp, PsyWFnTdpPb(state, waterCoil.DesInletWaterTemp, state.dataEnvrn->StdBaroPress));
    1214              :             // check for dry coil
    1215          432 :             DesHumRatAtWaterInTemp = PsyWFnTdbH(state, waterCoil.DesInletWaterTemp, DesSatEnthAtWaterInTemp, RoutineName);
    1216          432 :             if (DesHumRatAtWaterInTemp > waterCoil.DesOutletAirHumRat && waterCoil.DesOutletAirTemp > waterCoil.DesInletWaterTemp) {
    1217              :                 // if the design outlet air humrat is lower than the saturated air humrat at the design inlet water temp
    1218              :                 // and the design outlet air temperature is higher than the design inlet water temp (i.e, cooling possible),
    1219              :                 // move the design outlet air saturated enthalpy down (i.e., to Twaterin, Wair,out) to allow the coil to size.
    1220           36 :                 DesSatEnthAtWaterInTemp = PsyHFnTdbW(waterCoil.DesInletWaterTemp, waterCoil.DesOutletAirHumRat) - 0.0001;
    1221              :             }
    1222          432 :             if (DesOutletAirEnth >= DesInletAirEnth || waterCoil.DesInletWaterTemp >= waterCoil.DesInletAirTemp) {
    1223            0 :                 ShowWarningError(state, format("The design cooling capacity is zero for Coil:Cooling:Water {}", waterCoil.Name));
    1224            0 :                 ShowContinueError(state, "  The maximum water flow rate for this coil will be set to zero and the coil will do no cooling.");
    1225            0 :                 ShowContinueError(state,
    1226            0 :                                   format("  Check the following coil design inputs for problems: Tair,in = {:.4R}", waterCoil.DesInletAirTemp));
    1227            0 :                 ShowContinueError(state,
    1228            0 :                                   format("                                                       Wair,in = {:.6R}", waterCoil.DesInletAirHumRat));
    1229            0 :                 ShowContinueError(state,
    1230            0 :                                   format("                                                       Twater,in = {:.4R}", waterCoil.DesInletWaterTemp));
    1231            0 :                 ShowContinueError(state,
    1232            0 :                                   format("                                                       Tair,out = {:.4R}", waterCoil.DesOutletAirTemp));
    1233            0 :                 ShowContinueError(state,
    1234            0 :                                   format("                                                       Wair,out = {:.6R}", waterCoil.DesOutletAirHumRat));
    1235            0 :                 waterCoil.MaxWaterVolFlowRate = 0.0;
    1236            0 :                 waterCoil.MaxWaterMassFlowRate = 0.0;
    1237              :             }
    1238              :         }
    1239              : 
    1240        41908 :         if (state.dataWaterCoils->MyCoilDesignFlag(CoilNum) && (waterCoil.WaterCoilModel == CoilModel::CoolingSimple) &&
    1241        41908 :             (waterCoil.DesAirVolFlowRate > 0.0) && (waterCoil.MaxWaterMassFlowRate > 0.0)) { // 'Cooling'
    1242              : 
    1243          432 :             state.dataWaterCoils->MyCoilDesignFlag(CoilNum) = false;
    1244          432 :             state.dataWaterCoils->NoSatCurveIntersect = false;
    1245          432 :             state.dataWaterCoils->BelowInletWaterTemp = false;
    1246          432 :             state.dataWaterCoils->CBFTooLarge = false;
    1247          432 :             state.dataWaterCoils->NoExitCondReset = false;
    1248          899 :             for (Ipass = 1; Ipass <= 2; ++Ipass) {
    1249          819 :                 if (Ipass == 2) {
    1250          753 :                     if (!state.dataWaterCoils->NoSatCurveIntersect && !state.dataWaterCoils->BelowInletWaterTemp &&
    1251          366 :                         !state.dataWaterCoils->CBFTooLarge) {
    1252          307 :                         goto Inlet_Conditions_Loop_exit; // coil UA calcs OK
    1253              :                     } else {
    1254           80 :                         ShowWarningError(state, format("In calculating the design coil UA for Coil:Cooling:Water {}", waterCoil.Name));
    1255           80 :                         if (state.dataWaterCoils->NoSatCurveIntersect) {
    1256           45 :                             ShowContinueError(state, "no apparatus dew-point can be found for the initial entering and leaving conditions;");
    1257              :                         }
    1258           80 :                         if (state.dataWaterCoils->BelowInletWaterTemp) {
    1259           24 :                             ShowContinueError(state, "the apparatus dew-point is below the coil design inlet water temperature;");
    1260              :                         }
    1261           80 :                         if (state.dataWaterCoils->CBFTooLarge) {
    1262          180 :                             ShowContinueError(state, "the coil bypass factor is unrealistically large;");
    1263              :                         }
    1264           80 :                         if (!state.dataWaterCoils->NoExitCondReset) {
    1265           24 :                             ShowContinueError(state, "the coil outlet design conditions will be changed to correct the problem.");
    1266              :                         }
    1267           80 :                         ShowContinueError(state, format("The initial design conditions are: Tair,in = {:.4R}", waterCoil.DesInletAirTemp));
    1268           80 :                         ShowContinueError(state, format("                                   Wair,in = {:.6R}", waterCoil.DesInletAirHumRat));
    1269           80 :                         ShowContinueError(state, format("                                   Twater,in = {:.4R}", waterCoil.DesInletWaterTemp));
    1270           80 :                         ShowContinueError(state, format("                                   Tair,out = {:.4R}", waterCoil.DesOutletAirTemp));
    1271           80 :                         ShowContinueError(state, format("                                   Wair,out = {:.6R}", waterCoil.DesOutletAirHumRat));
    1272           80 :                         if (!state.dataWaterCoils->NoExitCondReset) {
    1273            8 :                             ShowContinueError(state, format("The revised design conditions are: Tair,out = {:.4R}", state.dataWaterCoils->TOutNew));
    1274            8 :                             ShowContinueError(state, format("                                   Wair,out = {:.6R}", state.dataWaterCoils->WOutNew));
    1275            8 :                             waterCoil.DesOutletAirHumRat = state.dataWaterCoils->WOutNew;
    1276            8 :                             waterCoil.DesOutletAirTemp = state.dataWaterCoils->TOutNew;
    1277              :                             // update outlet air conditions used for sizing
    1278            8 :                             std::string CompType;
    1279            8 :                             if (waterCoil.WaterCoilModel == CoilModel::CoolingDetailed) {
    1280            0 :                                 CompType = HVAC::cAllCoilTypes(HVAC::Coil_CoolingWaterDetailed);
    1281              :                             } else {
    1282            8 :                                 CompType = HVAC::cAllCoilTypes(HVAC::Coil_CoolingWater);
    1283              :                             }
    1284            8 :                             state.dataRptCoilSelection->coilSelectionReportObj->setCoilLvgAirTemp(
    1285            8 :                                 state, waterCoil.Name, CompType, state.dataWaterCoils->TOutNew);
    1286            8 :                             state.dataRptCoilSelection->coilSelectionReportObj->setCoilLvgAirHumRat(
    1287            8 :                                 state, waterCoil.Name, CompType, state.dataWaterCoils->WOutNew);
    1288              :                             // end update outlet air conditions used for sizing
    1289            8 :                         }
    1290              :                     }
    1291              :                 }
    1292              : 
    1293              :                 // Volume flow rate being converted to mass flow rate for water
    1294          512 :                 waterCoil.DesAirMassFlowRate = state.dataEnvrn->StdRhoAir * waterCoil.DesAirVolFlowRate;
    1295              : 
    1296              :                 // Enthalpy of Air at Inlet design conditions
    1297          512 :                 DesInletAirEnth = PsyHFnTdbW(waterCoil.DesInletAirTemp, waterCoil.DesInletAirHumRat);
    1298              : 
    1299              :                 // Enthalpy of Air at outlet at design conditions
    1300          512 :                 DesOutletAirEnth = PsyHFnTdbW(waterCoil.DesOutletAirTemp, waterCoil.DesOutletAirHumRat);
    1301              : 
    1302              :                 // already calculated above and possibly reset if dry coil
    1303              :                 //        ! Enthalpy of Water at Inlet design conditions
    1304              :                 //        DesSatEnthAtWaterInTemp =PsyHFnTdbW(WaterCoil(CoilNum)%DesInletWaterTemp, &
    1305              :                 //                                             PsyWFnTdpPb(state, WaterCoil(CoilNum)%DesInletWaterTemp,StdBaroPress))
    1306              : 
    1307              :                 // Total Coil Load from Inlet and Outlet Air States (which include fan heat as appropriate).
    1308          512 :                 waterCoil.DesTotWaterCoilLoad = waterCoil.DesAirMassFlowRate * (DesInletAirEnth - DesOutletAirEnth);
    1309              : 
    1310              :                 // Enthalpy of Water at Inlet design conditions
    1311          512 :                 Cp = state.dataPlnt->PlantLoop(waterCoil.WaterPlantLoc.loopNum)
    1312          512 :                          .glycol->getSpecificHeat(state, waterCoil.DesInletWaterTemp, RoutineName);
    1313              : 
    1314          512 :                 DesOutletWaterTemp = waterCoil.DesInletWaterTemp + waterCoil.DesTotWaterCoilLoad / (waterCoil.MaxWaterMassFlowRate * Cp);
    1315              : 
    1316          512 :                 DesSatEnthAtWaterOutTemp = PsyHFnTdbW(DesOutletWaterTemp, PsyWFnTdpPb(state, DesOutletWaterTemp, state.dataEnvrn->StdBaroPress));
    1317          512 :                 DesEnthAtWaterOutTempAirInHumRat = PsyHFnTdbW(DesOutletWaterTemp, waterCoil.DesInletAirHumRat);
    1318          512 :                 DesEnthWaterOut = min(DesSatEnthAtWaterOutTemp, DesEnthAtWaterOutTempAirInHumRat);
    1319              : 
    1320              :                 // dry coil test
    1321          512 :                 if (waterCoil.DesOutletAirHumRat < waterCoil.DesInletAirHumRat && DesHumRatAtWaterInTemp < waterCoil.DesInletAirHumRat) { // wet coil
    1322              : 
    1323              :                     // Calculations for BYPASS FACTOR at design conditions
    1324              :                     // Calculate "slope" of temperature vs. humidity ratio between entering and leaving states
    1325          934 :                     SlopeTempVsHumRatio = (waterCoil.DesInletAirTemp - waterCoil.DesOutletAirTemp) /
    1326          467 :                                           max((waterCoil.DesInletAirHumRat - waterCoil.DesOutletAirHumRat), SmallNo);
    1327              : 
    1328              :                     // Initialize iteration parameters
    1329          467 :                     DesAirTempApparatusDewPt = PsyTdpFnWPb(state, waterCoil.DesOutletAirHumRat, state.dataEnvrn->OutBaroPress);
    1330              : 
    1331              :                     // Iterating to calculate Apparatus Dew Point Temperature at Design Conditions
    1332         2410 :                     for (iter = 1; iter <= itmax; ++iter) {
    1333              : 
    1334              :                         // Calculate apparatus dewpoint and compare with predicted value
    1335              :                         // using entering conditions and SlopeTempVsHumRatio
    1336         2410 :                         DesAirHumRatApparatusDewPt = PsyWFnTdpPb(state, DesAirTempApparatusDewPt, state.dataEnvrn->OutBaroPress);
    1337              : 
    1338              :                         // Initial Estimate for apparatus Dew Point Temperature
    1339         2410 :                         TempApparatusDewPtEstimate =
    1340         2410 :                             waterCoil.DesInletAirTemp - SlopeTempVsHumRatio * (waterCoil.DesInletAirHumRat - DesAirHumRatApparatusDewPt);
    1341              : 
    1342              :                         // Iterating to calculate Apparatus Dew Point Temperature at Design Condition
    1343         2410 :                         error = DesAirTempApparatusDewPt - TempApparatusDewPtEstimate;
    1344         2410 :                         General::Iterate(ResultX, 0.01, DesAirTempApparatusDewPt, error, X1, Y1, iter, icvg);
    1345         2410 :                         DesAirTempApparatusDewPt = ResultX;
    1346              : 
    1347              :                         // If converged, exit loop
    1348         2410 :                         if (icvg == 1) {
    1349          439 :                             goto App_DewPoint_Loop1_exit;
    1350              :                         }
    1351              : 
    1352              :                         // If not converged due to low Humidity Ratio approximate value at outlet conditions
    1353         1971 :                         if (iter == itmax) {
    1354           28 :                             state.dataWaterCoils->NoSatCurveIntersect = true;
    1355           28 :                             DesAirTempApparatusDewPt = PsyTdpFnWPb(state, waterCoil.DesOutletAirHumRat, state.dataEnvrn->OutBaroPress);
    1356           28 :                             DesAirHumRatApparatusDewPt = PsyWFnTdpPb(state, DesAirTempApparatusDewPt, state.dataEnvrn->OutBaroPress);
    1357           28 :                             goto App_DewPoint_Loop1_exit;
    1358              :                         }
    1359              : 
    1360              :                         // End of Loop for Iteration
    1361              :                     }
    1362            0 :                 App_DewPoint_Loop1_exit:;
    1363              : 
    1364              :                     // Air enthalpy at apparatus dew point at design conditions
    1365          467 :                     DesAirApparatusDewPtEnth = PsyHFnTdbW(DesAirTempApparatusDewPt, DesAirHumRatApparatusDewPt);
    1366              : 
    1367              :                     // Calculate bypass factor from enthalpies calculated above.
    1368          467 :                     DesBypassFactor = (DesOutletAirEnth - DesAirApparatusDewPtEnth) / (DesInletAirEnth - DesAirApparatusDewPtEnth);
    1369              : 
    1370              :                     // Check for bypass factor for unsuitable value. Note that bypass factor is never used in the coil calculation
    1371          467 :                     if ((DesBypassFactor > 0.5) || (DesBypassFactor < 0.0)) {
    1372          120 :                         state.dataWaterCoils->CBFTooLarge = true;
    1373          120 :                         DesBypassFactor = 0.37;
    1374              :                     }
    1375              : 
    1376          467 :                     if (DesEnthWaterOut > DesInletAirEnth) {
    1377            0 :                         ShowWarningError(state, format("In calculating the design coil UA for Coil:Cooling:Water {}", waterCoil.Name));
    1378            0 :                         ShowContinueError(state, "the outlet chilled water design enthalpy is greater than the inlet air design enthalpy.");
    1379            0 :                         ShowContinueError(state,
    1380            0 :                                           format("To correct this condition the design chilled water flow rate will be increased from {:.5R}",
    1381            0 :                                                  waterCoil.MaxWaterVolFlowRate));
    1382            0 :                         EnthCorrFrac = (DesEnthWaterOut - DesInletAirEnth) / (DesEnthWaterOut - DesSatEnthAtWaterInTemp);
    1383            0 :                         waterCoil.MaxWaterVolFlowRate *= (1.0 + 2.0 * EnthCorrFrac);
    1384            0 :                         ShowContinueError(state, format("to {:.5R} m3/s", waterCoil.MaxWaterVolFlowRate));
    1385            0 :                         waterCoil.MaxWaterMassFlowRate = rho * waterCoil.MaxWaterVolFlowRate;
    1386            0 :                         DesOutletWaterTemp = waterCoil.DesInletWaterTemp + waterCoil.DesTotWaterCoilLoad / (waterCoil.MaxWaterMassFlowRate * Cp);
    1387              :                         DesSatEnthAtWaterOutTemp =
    1388            0 :                             PsyHFnTdbW(DesOutletWaterTemp, PsyWFnTdpPb(state, DesOutletWaterTemp, state.dataEnvrn->StdBaroPress));
    1389            0 :                         DesEnthAtWaterOutTempAirInHumRat = PsyHFnTdbW(DesOutletWaterTemp, waterCoil.DesInletAirHumRat);
    1390            0 :                         DesEnthWaterOut = min(DesSatEnthAtWaterOutTemp, DesEnthAtWaterOutTempAirInHumRat);
    1391              :                     }
    1392              : 
    1393              :                     // Determine air-side coefficient, UACoilExternal, assuming that the
    1394              :                     // surface temperature is at the apparatus dewpoint temperature
    1395          467 :                     if (DesAirApparatusDewPtEnth <= DesSatEnthAtWaterInTemp) {
    1396           11 :                         state.dataWaterCoils->BelowInletWaterTemp = true;
    1397              :                     }
    1398          467 :                     if ((DesInletAirEnth - DesEnthWaterOut) > SmallNo && (DesOutletAirEnth - DesSatEnthAtWaterInTemp) > SmallNo) {
    1399          467 :                         LogMeanEnthDiff = ((DesInletAirEnth - DesEnthWaterOut) - (DesOutletAirEnth - DesSatEnthAtWaterInTemp)) /
    1400          467 :                                           std::log((DesInletAirEnth - DesEnthWaterOut) / (DesOutletAirEnth - DesSatEnthAtWaterInTemp));
    1401              :                     } else {
    1402            0 :                         LogMeanEnthDiff = 2000.0; // UA will be 1/2 the design coil load
    1403              :                     }
    1404          467 :                     DesUACoilExternalEnth = waterCoil.DesTotWaterCoilLoad / LogMeanEnthDiff;
    1405          467 :                     waterCoil.UACoilExternal = DesUACoilExternalEnth * PsyCpAirFnW(waterCoil.DesInletAirHumRat);
    1406              : 
    1407          779 :                     if (Ipass == 1 && (state.dataWaterCoils->NoSatCurveIntersect || state.dataWaterCoils->CBFTooLarge ||
    1408          312 :                                        state.dataWaterCoils->BelowInletWaterTemp)) {
    1409              :                         // reset outlet conditions to 90% relative humidity at the same outlet enthalpy
    1410           80 :                         state.dataWaterCoils->TOutNew = TdbFnHRhPb(state, DesOutletAirEnth, 0.9, state.dataEnvrn->StdBaroPress);
    1411           80 :                         state.dataWaterCoils->WOutNew = PsyWFnTdbH(state, state.dataWaterCoils->TOutNew, DesOutletAirEnth);
    1412          159 :                         if (state.dataWaterCoils->WOutNew >= waterCoil.DesInletAirHumRat ||
    1413           79 :                             state.dataWaterCoils->TOutNew > waterCoil.DesOutletAirTemp) {
    1414           72 :                             state.dataWaterCoils->NoExitCondReset = true;
    1415              :                         }
    1416           80 :                         goto Inlet_Conditions_Loop_loop;
    1417              :                     }
    1418              : 
    1419          387 :                     waterCoil.UACoilInternal = waterCoil.UACoilExternal * 3.30;
    1420              :                     // Overall heat transfer coefficient
    1421          387 :                     waterCoil.UACoilTotal = 1.0 / (1.0 / waterCoil.UACoilExternal + 1.0 / waterCoil.UACoilInternal);
    1422              : 
    1423              :                 } else { // dry coil
    1424              : 
    1425           45 :                     if (DesOutletWaterTemp > waterCoil.DesInletAirTemp) {
    1426            0 :                         ShowWarningError(state, format("In calculating the design coil UA for Coil:Cooling:Water {}", waterCoil.Name));
    1427            0 :                         ShowContinueError(state, "the outlet chilled water design temperature is greater than the inlet air design temperature.");
    1428            0 :                         ShowContinueError(state,
    1429            0 :                                           format("To correct this condition the design chilled water flow rate will be increased from {:.5R}",
    1430            0 :                                                  waterCoil.MaxWaterVolFlowRate));
    1431            0 :                         TempCorrFrac = (DesOutletWaterTemp - waterCoil.DesInletAirTemp) / (DesOutletWaterTemp - waterCoil.DesInletWaterTemp);
    1432            0 :                         waterCoil.MaxWaterVolFlowRate *= (1.0 + 2.0 * TempCorrFrac);
    1433            0 :                         ShowContinueError(state, format("to {:.5R} m3/s", waterCoil.MaxWaterVolFlowRate));
    1434            0 :                         waterCoil.MaxWaterMassFlowRate = rho * waterCoil.MaxWaterVolFlowRate;
    1435            0 :                         DesOutletWaterTemp = waterCoil.DesInletWaterTemp + waterCoil.DesTotWaterCoilLoad / (waterCoil.MaxWaterMassFlowRate * Cp);
    1436              :                     }
    1437              : 
    1438           45 :                     if ((waterCoil.DesInletAirTemp - DesOutletWaterTemp) > SmallNo &&
    1439           45 :                         (waterCoil.DesOutletAirTemp - waterCoil.DesInletWaterTemp) > SmallNo) {
    1440           45 :                         LogMeanTempDiff =
    1441           45 :                             ((waterCoil.DesInletAirTemp - DesOutletWaterTemp) - (waterCoil.DesOutletAirTemp - waterCoil.DesInletWaterTemp)) /
    1442           45 :                             std::log((waterCoil.DesInletAirTemp - DesOutletWaterTemp) / (waterCoil.DesOutletAirTemp - waterCoil.DesInletWaterTemp));
    1443           45 :                         waterCoil.UACoilExternal = waterCoil.DesTotWaterCoilLoad / LogMeanTempDiff;
    1444              :                     } else {
    1445            0 :                         waterCoil.UACoilExternal = waterCoil.DesTotWaterCoilLoad / 2.0; // make the UA large
    1446              :                     }
    1447           45 :                     waterCoil.UACoilInternal = waterCoil.UACoilExternal * 3.30;
    1448              :                     // Overall heat transfer coefficient
    1449           45 :                     waterCoil.UACoilTotal = 1.0 / (1.0 / waterCoil.UACoilExternal + 1.0 / waterCoil.UACoilInternal);
    1450           45 :                     goto Inlet_Conditions_Loop_exit;
    1451              :                 }
    1452              : 
    1453          467 :             Inlet_Conditions_Loop_loop:;
    1454              :             }
    1455           80 :         Inlet_Conditions_Loop_exit:;
    1456              : 
    1457              :             // estimate the heat external transfer surface area using typical design over all U value
    1458          432 :             waterCoil.TotCoilOutsideSurfArea = EstimateHEXSurfaceArea(state, CoilNum);
    1459              :             // calculate internal and external "UA per external surface area"
    1460          432 :             waterCoil.UACoilInternalPerUnitArea = waterCoil.UACoilInternal / waterCoil.TotCoilOutsideSurfArea;
    1461          432 :             waterCoil.UAWetExtPerUnitArea = waterCoil.UACoilExternal / waterCoil.TotCoilOutsideSurfArea;
    1462              :             // approximate the dry UA as 1.0 times wet UA
    1463          432 :             waterCoil.UADryExtPerUnitArea = waterCoil.UAWetExtPerUnitArea;
    1464              : 
    1465              :             // Now use SolveRoot to "invert" the cooling coil model to obtain the UA given the specified design inlet and outlet conditions
    1466              :             // Note that the UAs we have obtained so far are rough estimates that are the starting points for the the following iterative
    1467              :             //   calculation of the actual UAs.
    1468          432 :             waterCoil.InletAirTemp = waterCoil.DesInletAirTemp;
    1469          432 :             waterCoil.InletAirHumRat = waterCoil.DesInletAirHumRat;
    1470          432 :             waterCoil.InletWaterTemp = waterCoil.DesInletWaterTemp;
    1471          432 :             waterCoil.InletWaterMassFlowRate = rho * waterCoil.MaxWaterVolFlowRate;
    1472          432 :             waterCoil.InletAirMassFlowRate = waterCoil.DesAirMassFlowRate;
    1473              :             // set the lower and upper limits on the UA
    1474          432 :             UA0 = 0.1 * waterCoil.UACoilExternal;
    1475          432 :             UA1 = 10.0 * waterCoil.UACoilExternal;
    1476              :             // Invert the simple cooling coil model: given the design inlet conditions and the design load, find the design UA
    1477         8641 :             auto f = [&state, CoilNum](Real64 const UA) {
    1478         8641 :                 HVAC::FanOp fanOp = HVAC::FanOp::Continuous;
    1479         8641 :                 Real64 PartLoadRatio = 1.0;
    1480         8641 :                 auto &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    1481         8641 :                 waterCoil.UACoilExternal = UA;
    1482         8641 :                 waterCoil.UACoilInternal = waterCoil.UACoilExternal * 3.3;
    1483         8641 :                 waterCoil.UACoilTotal = 1.0 / (1.0 / waterCoil.UACoilExternal + 1.0 / waterCoil.UACoilInternal);
    1484         8641 :                 waterCoil.TotCoilOutsideSurfArea = EstimateHEXSurfaceArea(state, CoilNum);
    1485         8641 :                 waterCoil.UACoilInternalPerUnitArea = waterCoil.UACoilInternal / waterCoil.TotCoilOutsideSurfArea;
    1486         8641 :                 waterCoil.UAWetExtPerUnitArea = waterCoil.UACoilExternal / waterCoil.TotCoilOutsideSurfArea;
    1487         8641 :                 waterCoil.UADryExtPerUnitArea = waterCoil.UAWetExtPerUnitArea;
    1488              : 
    1489         8641 :                 CoolingCoil(state, CoilNum, true, state.dataWaterCoils->DesignCalc, fanOp, PartLoadRatio);
    1490              : 
    1491         8641 :                 return (waterCoil.DesTotWaterCoilLoad - waterCoil.TotWaterCoolingCoilRate) / waterCoil.DesTotWaterCoilLoad;
    1492          432 :             };
    1493          432 :             General::SolveRoot(state, 0.001, MaxIte, SolFla, UA, f, UA0, UA1);
    1494              :             // if the numerical inversion failed, issue error messages.
    1495          432 :             if (SolFla == -1) {
    1496            0 :                 ShowSevereError(state, format("Calculation of cooling coil design UA failed for coil {}", waterCoil.Name));
    1497            0 :                 ShowContinueError(state, "  Iteration limit exceeded in calculating coil UA");
    1498            0 :                 waterCoil.UACoilExternal = UA0 * 10.0;
    1499            0 :                 waterCoil.UACoilInternal = waterCoil.UACoilExternal * 3.3;
    1500            0 :                 waterCoil.UACoilTotal = 1.0 / (1.0 / waterCoil.UACoilExternal + 1.0 / waterCoil.UACoilInternal);
    1501            0 :                 waterCoil.TotCoilOutsideSurfArea = EstimateHEXSurfaceArea(state, CoilNum);
    1502            0 :                 waterCoil.UACoilInternalPerUnitArea = waterCoil.UACoilInternal / waterCoil.TotCoilOutsideSurfArea;
    1503            0 :                 waterCoil.UAWetExtPerUnitArea = waterCoil.UACoilExternal / waterCoil.TotCoilOutsideSurfArea;
    1504            0 :                 waterCoil.UADryExtPerUnitArea = waterCoil.UAWetExtPerUnitArea;
    1505            0 :                 ShowContinueError(state, format(" Coil design UA set to {:.6R} [W/C]", waterCoil.UACoilTotal));
    1506          432 :             } else if (SolFla == -2) {
    1507           12 :                 ShowSevereError(state, format("Calculation of cooling coil design UA failed for coil {}", waterCoil.Name));
    1508           24 :                 ShowContinueError(state, "  Bad starting values for UA");
    1509           12 :                 waterCoil.UACoilExternal = UA0 * 10.0;
    1510           12 :                 waterCoil.UACoilInternal = waterCoil.UACoilExternal * 3.3;
    1511           12 :                 waterCoil.UACoilTotal = 1.0 / (1.0 / waterCoil.UACoilExternal + 1.0 / waterCoil.UACoilInternal);
    1512           12 :                 waterCoil.TotCoilOutsideSurfArea = EstimateHEXSurfaceArea(state, CoilNum);
    1513           12 :                 waterCoil.UACoilInternalPerUnitArea = waterCoil.UACoilInternal / waterCoil.TotCoilOutsideSurfArea;
    1514           12 :                 waterCoil.UAWetExtPerUnitArea = waterCoil.UACoilExternal / waterCoil.TotCoilOutsideSurfArea;
    1515           12 :                 waterCoil.UADryExtPerUnitArea = waterCoil.UAWetExtPerUnitArea;
    1516           12 :                 ShowContinueError(state, format(" Coil design UA set to {:.6R} [W/C]", waterCoil.UACoilTotal));
    1517              :             }
    1518              : 
    1519              :             // cooling coil surface area
    1520          432 :             state.dataWaterCoils->SurfaceArea = waterCoil.TotCoilOutsideSurfArea;
    1521              : 
    1522              :             // cooling coil overall UA value
    1523          432 :             state.dataWaterCoils->UATotal = waterCoil.UACoilTotal;
    1524              : 
    1525              :             // save the design internal and external UAs
    1526          432 :             waterCoil.UACoilExternalDes = waterCoil.UACoilExternal;
    1527          432 :             waterCoil.UACoilInternalDes = waterCoil.UACoilInternal;
    1528              :         }
    1529              : 
    1530              :         //@@@@ DESIGN CONDITION END HERE @@@@
    1531              : 
    1532              :         // Calculate rated Total, latent, sensible capacity, SHR, effectiveness
    1533        22164 :         if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
    1534        18297 :             waterCoil.InletAirTemp = 16.6;
    1535        18297 :             waterCoil.InletAirHumRat = PsyWFnTdbRhPb(state, 16.6, 0.5, state.dataEnvrn->StdBaroPress, RoutineName);
    1536        18297 :             waterCoil.InletWaterTemp = 82.2;
    1537              :         } else {
    1538         3867 :             waterCoil.InletAirTemp = 26.67;
    1539         3867 :             waterCoil.InletAirHumRat = PsyWFnTdbTwbPb(state, 26.67, 19.44, state.dataEnvrn->StdBaroPress, RoutineName);
    1540         3867 :             waterCoil.InletWaterTemp = 6.67;
    1541              :         }
    1542        22164 :         waterCoil.InletAirEnthalpy = PsyHFnTdbW(waterCoil.InletAirTemp, waterCoil.InletAirHumRat);
    1543        22164 :         waterCoil.InletWaterMassFlowRate = waterCoil.MaxWaterMassFlowRate;
    1544        22164 :         waterCoil.InletAirMassFlowRate = state.dataEnvrn->StdRhoAir * waterCoil.DesAirVolFlowRate;
    1545        22164 :         CapacitanceAir = waterCoil.InletAirMassFlowRate * PsyCpAirFnW(waterCoil.InletAirHumRat);
    1546              : 
    1547        22164 :         Cp = state.dataPlnt->PlantLoop(waterCoil.WaterPlantLoc.loopNum).glycol->getSpecificHeat(state, waterCoil.InletWaterTemp, RoutineName);
    1548              : 
    1549        22164 :         state.dataWaterCoils->CapacitanceWater = waterCoil.InletWaterMassFlowRate * Cp;
    1550        22164 :         state.dataWaterCoils->CMin = min(CapacitanceAir, state.dataWaterCoils->CapacitanceWater);
    1551        22164 :         if (state.dataWaterCoils->CMin > 0.0) {
    1552        21893 :             if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) {
    1553         2852 :                 CoolingCoil(state, CoilNum, FirstHVACIteration, state.dataWaterCoils->DesignCalc, HVAC::FanOp::Continuous, 1.0);
    1554         8556 :                 state.dataWaterCoils->CoilEffectiveness = (waterCoil.InletAirTemp - waterCoil.OutletAirTemp) /
    1555         5704 :                                                           (waterCoil.InletAirTemp - waterCoil.InletWaterTemp) *
    1556         2852 :                                                           (CapacitanceAir / state.dataWaterCoils->CMin);
    1557         2852 :                 state.dataWaterCoils->RatedLatentCapacity = waterCoil.TotWaterCoolingCoilRate - waterCoil.SenWaterCoolingCoilRate;
    1558         2852 :                 state.dataWaterCoils->RatedSHR = waterCoil.SenWaterCoolingCoilRate / waterCoil.TotWaterCoolingCoilRate;
    1559        19041 :             } else if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling) {
    1560         1005 :                 CalcDetailFlatFinCoolingCoil(state, CoilNum, state.dataWaterCoils->DesignCalc, HVAC::FanOp::Continuous, 1.0);
    1561         3015 :                 state.dataWaterCoils->CoilEffectiveness = (waterCoil.InletAirTemp - waterCoil.OutletAirTemp) /
    1562         2010 :                                                           (waterCoil.InletAirTemp - waterCoil.InletWaterTemp) *
    1563         1005 :                                                           (CapacitanceAir / state.dataWaterCoils->CMin);
    1564         1005 :                 state.dataWaterCoils->RatedLatentCapacity = waterCoil.TotWaterCoolingCoilRate - waterCoil.SenWaterCoolingCoilRate;
    1565         1005 :                 state.dataWaterCoils->RatedSHR = waterCoil.SenWaterCoolingCoilRate / waterCoil.TotWaterCoolingCoilRate;
    1566        18036 :             } else if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
    1567        18036 :                 CalcSimpleHeatingCoil(state, CoilNum, HVAC::FanOp::Continuous, 1.0, state.dataWaterCoils->DesignCalc);
    1568        18036 :                 state.dataWaterCoils->CoilEffectiveness = (waterCoil.OutletAirTemp - waterCoil.InletAirTemp) /
    1569        36072 :                                                           (waterCoil.InletWaterTemp - waterCoil.InletAirTemp) *
    1570        18036 :                                                           (CapacitanceAir / state.dataWaterCoils->CMin);
    1571              :             }
    1572              :         } else {
    1573          271 :             state.dataWaterCoils->CoilEffectiveness = 0.0;
    1574          271 :             waterCoil.TotWaterHeatingCoilRate = 0.0;
    1575          271 :             waterCoil.TotWaterCoolingCoilRate = 0.0;
    1576          271 :             waterCoil.SenWaterCoolingCoilRate = 0.0;
    1577          271 :             state.dataWaterCoils->RatedLatentCapacity = 0.0;
    1578          271 :             state.dataWaterCoils->RatedSHR = 0.0;
    1579              :         }
    1580        22164 :         state.dataWaterCoils->MyEnvrnFlag(CoilNum) = false;
    1581              : 
    1582              :     } // End If for the Begin Environment initializations
    1583              : 
    1584    149968186 :     if (!state.dataGlobal->BeginEnvrnFlag) {
    1585    149579089 :         state.dataWaterCoils->MyEnvrnFlag(CoilNum) = true;
    1586              :     }
    1587              : 
    1588    149968186 :     if (!state.dataGlobal->DoingSizing) {
    1589    149965851 :         if (state.dataWaterCoils->MyCoilReportFlag(CoilNum)) {
    1590              :             // create predefined report entries
    1591         3351 :             state.dataWaterCoils->MyCoilReportFlag(CoilNum) = false;
    1592         3351 :             switch (waterCoil.WaterCoilType) {
    1593         2755 :             case DataPlant::PlantEquipmentType::CoilWaterSimpleHeating: {
    1594         2755 :                 if (state.dataWaterCoils->RptCoilHeaderFlag(1)) {
    1595          314 :                     print(state.files.eio, "{}", "! <Water Heating Coil Capacity Information>,Component Type,Name,Nominal Total Capacity {W}\n");
    1596          314 :                     state.dataWaterCoils->RptCoilHeaderFlag(1) = false;
    1597              :                 }
    1598         2755 :                 OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilType, waterCoil.Name, "Coil:Heating:Water");
    1599         5510 :                 OutputReportPredefined::PreDefTableEntry(
    1600         2755 :                     state, state.dataOutRptPredefined->pdchHeatCoilDesCap, waterCoil.Name, waterCoil.DesWaterHeatingCoilRate);
    1601         5510 :                 OutputReportPredefined::PreDefTableEntry(
    1602         2755 :                     state, state.dataOutRptPredefined->pdchHeatCoilNomCap, waterCoil.Name, waterCoil.TotWaterHeatingCoilRate);
    1603         2755 :                 OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilNomEff, waterCoil.Name, "-");
    1604         5510 :                 OutputReportPredefined::addFootNoteSubTable(
    1605              :                     state,
    1606         2755 :                     state.dataOutRptPredefined->pdstHeatCoil,
    1607              :                     "Nominal values are gross at rated conditions, i.e., the supply air fan heat and electric power NOT accounted for.");
    1608         2755 :                 print(state.files.eio,
    1609              :                       "{},{},{:.2R}\n",
    1610              :                       "Water Heating Coil Capacity Information,Coil:Heating:Water",
    1611         2755 :                       waterCoil.Name,
    1612         2755 :                       waterCoil.TotWaterHeatingCoilRate);
    1613         8265 :                 state.dataRptCoilSelection->coilSelectionReportObj->setCoilAirFlow(
    1614         5510 :                     state, waterCoil.Name, "Coil:Heating:Water", waterCoil.DesAirVolFlowRate, waterCoil.RequestingAutoSize);
    1615         8265 :                 state.dataRptCoilSelection->coilSelectionReportObj->setCoilWaterHeaterCapacityNodeNums(
    1616              :                     state,
    1617         2755 :                     waterCoil.Name,
    1618              :                     "Coil:Heating:Water",
    1619              :                     waterCoil.DesWaterHeatingCoilRate,
    1620         2755 :                     waterCoil.RequestingAutoSize,
    1621              :                     waterCoil.WaterInletNodeNum,
    1622              :                     waterCoil.WaterOutletNodeNum,
    1623              :                     waterCoil.WaterPlantLoc.loopNum); // coil report
    1624         2755 :                 break;
    1625              :             }
    1626          162 :             case DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling: {
    1627          162 :                 if (state.dataWaterCoils->RptCoilHeaderFlag(2)) {
    1628          119 :                     print(state.files.eio,
    1629              :                           "{}\n",
    1630              :                           "! <Water Cooling Coil Capacity Information>,Component Type,Name,Nominal Total "
    1631              :                           "Capacity {W},Nominal Sensible Capacity {W},Nominal Latent Capacity {W},Nominal "
    1632              :                           "Sensible Heat Ratio");
    1633          119 :                     state.dataWaterCoils->RptCoilHeaderFlag(2) = false;
    1634              :                 }
    1635          162 :                 state.dataWaterCoils->RatedLatentCapacity = waterCoil.TotWaterCoolingCoilRate - waterCoil.SenWaterCoolingCoilRate;
    1636          162 :                 state.dataWaterCoils->RatedSHR = General::SafeDivide(waterCoil.SenWaterCoolingCoilRate, waterCoil.TotWaterCoolingCoilRate);
    1637          324 :                 OutputReportPredefined::PreDefTableEntry(
    1638          162 :                     state, state.dataOutRptPredefined->pdchCoolCoilType, waterCoil.Name, "Coil:Cooling:Water:DetailedGeometry");
    1639          324 :                 OutputReportPredefined::PreDefTableEntry(
    1640          162 :                     state, state.dataOutRptPredefined->pdchCoolCoilDesCap, waterCoil.Name, waterCoil.DesWaterCoolingCoilRate);
    1641          324 :                 OutputReportPredefined::PreDefTableEntry(
    1642          162 :                     state, state.dataOutRptPredefined->pdchCoolCoilTotCap, waterCoil.Name, waterCoil.TotWaterCoolingCoilRate);
    1643          324 :                 OutputReportPredefined::PreDefTableEntry(
    1644          162 :                     state, state.dataOutRptPredefined->pdchCoolCoilSensCap, waterCoil.Name, waterCoil.SenWaterCoolingCoilRate);
    1645          486 :                 OutputReportPredefined::PreDefTableEntry(
    1646          324 :                     state, state.dataOutRptPredefined->pdchCoolCoilLatCap, waterCoil.Name, state.dataWaterCoils->RatedLatentCapacity);
    1647          486 :                 OutputReportPredefined::PreDefTableEntry(
    1648          324 :                     state, state.dataOutRptPredefined->pdchCoolCoilSHR, waterCoil.Name, state.dataWaterCoils->RatedSHR);
    1649          162 :                 OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilNomEff, waterCoil.Name, "-");
    1650          324 :                 OutputReportPredefined::addFootNoteSubTable(
    1651              :                     state,
    1652          162 :                     state.dataOutRptPredefined->pdstCoolCoil,
    1653              :                     "Nominal values are gross at rated conditions, i.e., the supply air fan heat and electric power NOT accounted for.");
    1654          162 :                 print(state.files.eio,
    1655              :                       "{},{},{:.2R},{:.2R},{:.2R},{:.2R}\n",
    1656              :                       "Water Cooling Coil Capacity Information,Coil:Cooling:Water:DetailedGeometry",
    1657          162 :                       waterCoil.Name,
    1658          162 :                       waterCoil.TotWaterCoolingCoilRate,
    1659          162 :                       waterCoil.SenWaterCoolingCoilRate,
    1660          162 :                       state.dataWaterCoils->RatedLatentCapacity,
    1661          162 :                       state.dataWaterCoils->RatedSHR);
    1662          486 :                 state.dataRptCoilSelection->coilSelectionReportObj->setCoilAirFlow(state,
    1663          162 :                                                                                    waterCoil.Name,
    1664              :                                                                                    "Coil:Cooling:Water:DetailedGeometry",
    1665              :                                                                                    waterCoil.DesAirVolFlowRate,
    1666          162 :                                                                                    waterCoil.RequestingAutoSize); // Coil Report
    1667          486 :                 state.dataRptCoilSelection->coilSelectionReportObj->setCoilWaterCoolingCapacity(state,
    1668          162 :                                                                                                 waterCoil.Name,
    1669              :                                                                                                 "Coil:Cooling:Water:DetailedGeometry",
    1670              :                                                                                                 waterCoil.DesWaterCoolingCoilRate,
    1671          162 :                                                                                                 waterCoil.RequestingAutoSize,
    1672              :                                                                                                 waterCoil.WaterInletNodeNum,
    1673              :                                                                                                 waterCoil.WaterOutletNodeNum,
    1674              :                                                                                                 waterCoil.WaterPlantLoc.loopNum); // Coil Report
    1675          162 :                 break;
    1676              :             }
    1677          434 :             case DataPlant::PlantEquipmentType::CoilWaterCooling: {
    1678          434 :                 if (state.dataWaterCoils->RptCoilHeaderFlag(2)) {
    1679          191 :                     print(state.files.eio,
    1680              :                           "{}\n",
    1681              :                           "! <Water Cooling Coil Capacity Information>,Component Type,Name,Nominal Total "
    1682              :                           "Capacity {W},Nominal Sensible Capacity {W},Nominal Latent Capacity {W},Nominal "
    1683              :                           "Sensible Heat Ratio, Nominal Coil UA Value {W/C}, Nominal Coil Surface Area {m2}");
    1684          191 :                     state.dataWaterCoils->RptCoilHeaderFlag(2) = false;
    1685              :                 }
    1686          434 :                 state.dataWaterCoils->RatedLatentCapacity = waterCoil.TotWaterCoolingCoilRate - waterCoil.SenWaterCoolingCoilRate;
    1687          434 :                 state.dataWaterCoils->RatedSHR = General::SafeDivide(waterCoil.SenWaterCoolingCoilRate, waterCoil.TotWaterCoolingCoilRate);
    1688          434 :                 OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilType, waterCoil.Name, "Coil:Cooling:Water");
    1689          868 :                 OutputReportPredefined::PreDefTableEntry(
    1690          434 :                     state, state.dataOutRptPredefined->pdchCoolCoilDesCap, waterCoil.Name, waterCoil.DesWaterCoolingCoilRate);
    1691          868 :                 OutputReportPredefined::PreDefTableEntry(
    1692          434 :                     state, state.dataOutRptPredefined->pdchCoolCoilTotCap, waterCoil.Name, waterCoil.TotWaterCoolingCoilRate);
    1693          868 :                 OutputReportPredefined::PreDefTableEntry(
    1694          434 :                     state, state.dataOutRptPredefined->pdchCoolCoilSensCap, waterCoil.Name, waterCoil.SenWaterCoolingCoilRate);
    1695         1302 :                 OutputReportPredefined::PreDefTableEntry(
    1696          868 :                     state, state.dataOutRptPredefined->pdchCoolCoilLatCap, waterCoil.Name, state.dataWaterCoils->RatedLatentCapacity);
    1697         1302 :                 OutputReportPredefined::PreDefTableEntry(
    1698          868 :                     state, state.dataOutRptPredefined->pdchCoolCoilSHR, waterCoil.Name, state.dataWaterCoils->RatedSHR);
    1699          434 :                 OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilNomEff, waterCoil.Name, "-");
    1700          868 :                 OutputReportPredefined::PreDefTableEntry(
    1701          434 :                     state, state.dataOutRptPredefined->pdchCoolCoilUATotal, waterCoil.Name, waterCoil.UACoilTotal);
    1702          868 :                 OutputReportPredefined::PreDefTableEntry(
    1703          434 :                     state, state.dataOutRptPredefined->pdchCoolCoilArea, waterCoil.Name, waterCoil.TotCoilOutsideSurfArea);
    1704          868 :                 OutputReportPredefined::addFootNoteSubTable(
    1705              :                     state,
    1706          434 :                     state.dataOutRptPredefined->pdstCoolCoil,
    1707              :                     "Nominal values are gross at rated conditions, i.e., the supply air fan heat and electric power NOT accounted for.");
    1708          434 :                 print(state.files.eio,
    1709              :                       "{},{},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R}\n",
    1710              :                       "Water Cooling Coil Capacity Information,Coil:Cooling:Water",
    1711          434 :                       waterCoil.Name,
    1712          434 :                       waterCoil.TotWaterCoolingCoilRate,
    1713          434 :                       waterCoil.SenWaterCoolingCoilRate,
    1714          434 :                       state.dataWaterCoils->RatedLatentCapacity,
    1715          434 :                       state.dataWaterCoils->RatedSHR,
    1716          434 :                       state.dataWaterCoils->UATotal,
    1717          434 :                       state.dataWaterCoils->SurfaceArea);
    1718         1302 :                 state.dataRptCoilSelection->coilSelectionReportObj->setCoilAirFlow(state,
    1719          434 :                                                                                    waterCoil.Name,
    1720              :                                                                                    "Coil:Cooling:Water",
    1721              :                                                                                    waterCoil.DesAirVolFlowRate,
    1722          434 :                                                                                    waterCoil.RequestingAutoSize); // Coil Report
    1723         1302 :                 state.dataRptCoilSelection->coilSelectionReportObj->setCoilWaterCoolingCapacity(state,
    1724          434 :                                                                                                 waterCoil.Name,
    1725              :                                                                                                 "Coil:Cooling:Water",
    1726              :                                                                                                 waterCoil.DesWaterCoolingCoilRate,
    1727          434 :                                                                                                 waterCoil.RequestingAutoSize,
    1728              :                                                                                                 waterCoil.WaterInletNodeNum,
    1729              :                                                                                                 waterCoil.WaterOutletNodeNum,
    1730              :                                                                                                 waterCoil.WaterPlantLoc.loopNum); // Coil Report
    1731          434 :                 break;
    1732              :             }
    1733            0 :             default:
    1734            0 :                 break;
    1735              :             }
    1736         3351 :             if (waterCoil.DesWaterCoolingCoilRate <= 0.0) {
    1737         2858 :                 waterCoil.DesWaterCoolingCoilRate = waterCoil.TotWaterCoolingCoilRate;
    1738              :             }
    1739         3351 :             if (waterCoil.DesWaterHeatingCoilRate <= 0.0) {
    1740          933 :                 waterCoil.DesWaterHeatingCoilRate = waterCoil.TotWaterHeatingCoilRate;
    1741              :             }
    1742              : 
    1743              :             // call coil model with everything set at rating point
    1744         3351 :             waterCoil.InletAirMassFlowRate = waterCoil.DesAirMassFlowRate;
    1745         3351 :             waterCoil.InletAirTemp = waterCoil.DesInletAirTemp;
    1746         3351 :             waterCoil.InletAirHumRat = waterCoil.DesInletAirHumRat; // fixed in sizing routine
    1747         3351 :             waterCoil.InletAirEnthalpy = Psychrometrics::PsyHFnTdbW(waterCoil.DesInletAirTemp, waterCoil.DesInletAirHumRat);
    1748         3351 :             Real64 DesInletWetBulb = Psychrometrics::PsyTwbFnTdbWPb(
    1749              :                 state, waterCoil.DesInletAirTemp, waterCoil.DesInletAirHumRat, DataEnvironment::StdPressureSeaLevel, "InitWaterCoils");
    1750         3351 :             waterCoil.InletWaterMassFlowRate = waterCoil.MaxWaterMassFlowRate;
    1751         3351 :             waterCoil.InletWaterTemp = waterCoil.DesInletWaterTemp;
    1752         3351 :             Real64 cp = state.dataPlnt->PlantLoop(waterCoil.WaterPlantLoc.loopNum)
    1753         3351 :                             .glycol->getSpecificHeat(state, waterCoil.DesInletWaterTemp, "InitWaterCoil");
    1754         3351 :             waterCoil.InletWaterEnthalpy = cp * waterCoil.InletWaterTemp;
    1755              : 
    1756         3351 :             waterCoil.UACoilVariable = waterCoil.UACoil;
    1757         3351 :             waterCoil.FaultyCoilFoulingFactor = 0.0;
    1758         3351 :             Real64 holdOutBaroPress = state.dataEnvrn->OutBaroPress;
    1759         3351 :             state.dataEnvrn->OutBaroPress = DataEnvironment::StdPressureSeaLevel; // assume rating is for sea level.
    1760         3351 :             CalcAdjustedCoilUA(state, CoilNum);
    1761              : 
    1762         3351 :             std::string coilTypeName(" ");
    1763              :             // calculate coil sim model at rating point, full load, continuous fan
    1764         3351 :             if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling) {
    1765          162 :                 CalcDetailFlatFinCoolingCoil(state, CoilNum, state.dataWaterCoils->SimCalc, HVAC::FanOp::Continuous, 1.0);
    1766          162 :                 coilTypeName = "Coil:Cooling:Water:DetailedGeometry";
    1767         3189 :             } else if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) {
    1768          434 :                 CoolingCoil(state, CoilNum, FirstHVACIteration, state.dataWaterCoils->SimCalc, HVAC::FanOp::Continuous, 1.0);
    1769          434 :                 coilTypeName = "Coil:Cooling:Water";
    1770         2755 :             } else if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
    1771         2755 :                 CalcSimpleHeatingCoil(state, CoilNum, HVAC::FanOp::Continuous, 1.0, state.dataWaterCoils->SimCalc);
    1772         2755 :                 coilTypeName = "Coil:Heating:Water";
    1773              :             }
    1774         3351 :             state.dataRptCoilSelection->coilSelectionReportObj->setCoilEqNum(
    1775         3351 :                 state, waterCoil.Name, coilTypeName, state.dataSize->CurSysNum, state.dataSize->CurOASysNum, state.dataSize->CurZoneEqNum);
    1776              : 
    1777              :             // coil outlets
    1778         3351 :             Real64 RatedOutletWetBulb(0.0);
    1779         3351 :             RatedOutletWetBulb = Psychrometrics::PsyTwbFnTdbWPb(
    1780              :                 state, waterCoil.OutletAirTemp, waterCoil.OutletAirHumRat, DataEnvironment::StdPressureSeaLevel, "InitWaterCoil");
    1781              : 
    1782              :             // call set routine in coil report
    1783         3351 :             if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling ||
    1784         3189 :                 waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) {
    1785          596 :                 state.dataRptCoilSelection->coilSelectionReportObj->setRatedCoilConditions(
    1786              :                     state,
    1787          596 :                     waterCoil.Name,
    1788              :                     coilTypeName,
    1789              :                     waterCoil.TotWaterCoolingCoilRate, // this is the report variable
    1790              :                     waterCoil.SenWaterCoolingCoilRate, // this is the report variable
    1791              :                     waterCoil.InletAirMassFlowRate,
    1792              :                     waterCoil.InletAirTemp,
    1793              :                     waterCoil.InletAirHumRat,
    1794              :                     DesInletWetBulb,
    1795              :                     waterCoil.OutletAirTemp,
    1796              :                     waterCoil.OutletAirHumRat,
    1797              :                     RatedOutletWetBulb,
    1798              :                     -999.0,
    1799              :                     -999.0,
    1800              :                     -999.0,
    1801              :                     -999.0); // coil effectiveness
    1802         2755 :             } else if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
    1803         2755 :                 state.dataRptCoilSelection->coilSelectionReportObj->setRatedCoilConditions(
    1804              :                     state,
    1805         2755 :                     waterCoil.Name,
    1806              :                     coilTypeName,
    1807              :                     waterCoil.TotWaterHeatingCoilRate, // this is the report variable
    1808              :                     waterCoil.TotWaterHeatingCoilRate, // this is the report variable
    1809              :                     waterCoil.InletAirMassFlowRate,
    1810              :                     waterCoil.InletAirTemp,
    1811              :                     waterCoil.InletAirHumRat,
    1812              :                     DesInletWetBulb,
    1813              :                     waterCoil.OutletAirTemp,
    1814              :                     waterCoil.OutletAirHumRat,
    1815              :                     RatedOutletWetBulb,
    1816              :                     -999.0,
    1817              :                     -999.0,
    1818              :                     -999.0,
    1819              :                     -999.0); // coil effectiveness
    1820              :             }
    1821              :             // now replace the outdoor air conditions set above for one time rating point calc
    1822         3351 :             state.dataEnvrn->OutBaroPress = holdOutBaroPress;
    1823              :         }
    1824              :     }
    1825              : 
    1826              :     // Do the Begin Day initializations
    1827              :     // NONE
    1828              : 
    1829              :     // Do the begin HVAC time step initializations
    1830              :     // NONE
    1831              : 
    1832              :     // Do the following initializations (every time step): This should be the info from
    1833              :     // the previous components outlets or the node data in this section.
    1834              :     // First set the conditions for the air into the coil model
    1835    149968186 :     AirInletNode = waterCoil.AirInletNodeNum;
    1836    149968186 :     WaterInletNode = waterCoil.WaterInletNodeNum;
    1837    149968186 :     auto const &airInletNode = state.dataLoopNodes->Node(AirInletNode);
    1838    149968186 :     waterCoil.InletAirMassFlowRate = airInletNode.MassFlowRate;
    1839    149968186 :     waterCoil.InletAirTemp = airInletNode.Temp;
    1840    149968186 :     waterCoil.InletAirHumRat = airInletNode.HumRat;
    1841    149968186 :     waterCoil.InletAirEnthalpy = airInletNode.Enthalpy;
    1842              : 
    1843    149968186 :     auto const &waterInletNode = state.dataLoopNodes->Node(WaterInletNode);
    1844    149968186 :     waterCoil.InletWaterMassFlowRate = waterInletNode.MassFlowRate;
    1845    149968186 :     waterCoil.InletWaterTemp = waterInletNode.Temp;
    1846    149968186 :     waterCoil.InletWaterEnthalpy = waterInletNode.Enthalpy;
    1847              : 
    1848    149968186 :     waterCoil.UACoilVariable = waterCoil.UACoil;
    1849              : 
    1850    149968186 :     CalcAdjustedCoilUA(state, CoilNum);
    1851              : 
    1852    149968186 :     waterCoil.TotWaterHeatingCoilRate = 0.0;
    1853    149968186 :     waterCoil.TotWaterCoolingCoilRate = 0.0;
    1854    149968186 :     waterCoil.SenWaterCoolingCoilRate = 0.0;
    1855    149968186 : }
    1856              : 
    1857              : // refactor coilUA adjustment into separate routine, for use with rating calc
    1858    149971537 : void CalcAdjustedCoilUA(EnergyPlusData &state, int const CoilNum)
    1859              : {
    1860              :     // Pull these precalc routines out of big init routine
    1861              :     // modify the coil UA based on model in Wetter 1999
    1862              :     Real64 x_a;                  // result of Eq.70 in Wetter 1999
    1863              :     Real64 x_w;                  // result of Eq.72 in Wetter 1999
    1864              :     Real64 AirConvectTerm;       // result of Eq.71 in Wetter 1999
    1865              :     Real64 WaterConvectTerm;     // result of Eq.73 in Wetter 1999
    1866              :     Real64 WaterConvSensitivity; // "s" in Wetter 1999, temperature sensitivity in water side convection
    1867              : 
    1868    149971537 :     auto &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    1869              :     // Coil:Heating:Water
    1870    271945973 :     if ((waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) &&
    1871    121974436 :         (!(state.dataWaterCoils->MyUAAndFlowCalcFlag(CoilNum)))) { // update Coil UA based on inlet mass flows and temps
    1872    121972271 :         x_a = 1.0 + 4.769E-3 * (waterCoil.InletAirTemp - waterCoil.DesInletAirTemp);
    1873    121972271 :         if (waterCoil.DesAirMassFlowRate > 0.0) {
    1874    121320201 :             AirConvectTerm = x_a * std::pow(waterCoil.InletAirMassFlowRate / waterCoil.DesAirMassFlowRate, 0.8) * waterCoil.AirSideNominalConvect;
    1875              :         } else {
    1876       652070 :             AirConvectTerm = 0.0;
    1877              :         }
    1878    121972271 :         WaterConvSensitivity = 0.014 / (1.0 + 0.014 * waterCoil.DesInletWaterTemp);
    1879    121972271 :         x_w = 1.0 + WaterConvSensitivity * (waterCoil.InletWaterTemp - waterCoil.DesInletWaterTemp);
    1880    121972271 :         if (waterCoil.MaxWaterMassFlowRate > 0.0) {
    1881    120849286 :             WaterConvectTerm =
    1882    120849286 :                 x_w * std::pow(waterCoil.InletWaterMassFlowRate / waterCoil.MaxWaterMassFlowRate, 0.85) * waterCoil.LiquidSideNominalConvect;
    1883              :         } else {
    1884      1122985 :             WaterConvectTerm = 0.0;
    1885              :         }
    1886    121972271 :         if ((AirConvectTerm > 0.0) && (WaterConvectTerm > 0.0)) {
    1887     76796206 :             waterCoil.UACoilVariable = 1.0 / ((1.0 / WaterConvectTerm) + (1.0 / AirConvectTerm));
    1888              :         } else {
    1889              :             // use nominal UA since variable UA cannot be calculated
    1890     45176065 :             waterCoil.UACoilVariable = waterCoil.UACoil;
    1891              :         }
    1892              : 
    1893              :         // calculate the Faulty Coil Fouling (thermal insulance) Factor using fault information
    1894    243960300 :         if (waterCoil.FaultyCoilFoulingFlag &&
    1895              :             // The fault shouldn't apply during sizing.
    1896    121973598 :             (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) && (!state.dataGlobal->KickOffSimulation) &&
    1897              :             // This was preexisting
    1898         1327 :             !(state.dataWaterCoils->MyUAAndFlowCalcFlag(CoilNum))) {
    1899              :             // Store original value
    1900         1327 :             waterCoil.OriginalUACoilVariable = waterCoil.UACoilVariable;
    1901              : 
    1902         1327 :             int FaultIndex = waterCoil.FaultyCoilFoulingIndex;
    1903         1327 :             FaultsManager::FaultPropertiesFoulingCoil &fouling = state.dataFaultsMgr->FouledCoils(FaultIndex);
    1904         1327 :             Real64 FaultFrac = fouling.FaultFraction(state);
    1905              : 
    1906         1327 :             if (fouling.FoulingInputMethod == FaultsManager::FouledCoil::UARated) {
    1907              :                 // 1/UA' = Frac * (1/UAFouled) + (1-Frac) / UA
    1908         1327 :                 waterCoil.UACoilVariable = 1 / (FaultFrac / (fouling.UAFouled) + (1 - FaultFrac) / waterCoil.UACoilVariable);
    1909              :             } else {
    1910              :                 // R' = R + Rfoul
    1911              :                 // Rfoul = r_air/A_air + r_water/A_water (FoulingFactor = thermal insulance [K/W, A] = Area [m2], r=fouling factor [m2.K/W]
    1912            0 :                 Real64 FoulingFactor = FaultFrac * (fouling.Rfw / (fouling.Aratio * fouling.Aout) + fouling.Rfa / fouling.Aout);
    1913            0 :                 waterCoil.UACoilVariable = 1.0 / ((1.0 / waterCoil.UACoilVariable) + FoulingFactor);
    1914              :             }
    1915              : 
    1916              :             // Do not allow improving coil performance
    1917         1327 :             waterCoil.UACoilVariable = min(waterCoil.UACoilVariable, waterCoil.OriginalUACoilVariable);
    1918              : 
    1919              :             // Only for reporting purposes
    1920         1327 :             waterCoil.FaultyCoilFoulingFactor = (1.0 / waterCoil.UACoilVariable) - (1.0 / waterCoil.OriginalUACoilVariable);
    1921              :         } else {
    1922    121970944 :             waterCoil.FaultyCoilFoulingFactor = 0;
    1923              :         }
    1924              :     }
    1925              : 
    1926              :     // Coil:Cooling:Water
    1927              :     // update Coil UA based on inlet mass flows and temps
    1928    149971537 :     if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling && (!state.dataWaterCoils->MyCoilDesignFlag(CoilNum))) {
    1929     23067487 :         if (waterCoil.DesAirMassFlowRate > 0.0) {
    1930     23067487 :             x_a = 1.0 + 4.769E-3 * (waterCoil.InletAirTemp - waterCoil.DesInletAirTemp);
    1931     23067487 :             waterCoil.UACoilExternal =
    1932     23067487 :                 x_a * std::pow(waterCoil.InletAirMassFlowRate / waterCoil.DesAirMassFlowRate, 0.8) * waterCoil.UACoilExternalDes;
    1933              :         } else {
    1934            0 :             waterCoil.UACoilExternal = waterCoil.UACoilExternalDes;
    1935              :         }
    1936              : 
    1937     23067487 :         if (waterCoil.MaxWaterMassFlowRate > 0.0) {
    1938     23067487 :             WaterConvSensitivity = 0.014 / (1.0 + 0.014 * waterCoil.DesInletWaterTemp);
    1939     23067487 :             x_w = 1.0 + WaterConvSensitivity * (waterCoil.InletWaterTemp - waterCoil.DesInletWaterTemp);
    1940     23067487 :             waterCoil.UACoilInternal =
    1941     23067487 :                 x_w * std::pow(waterCoil.InletWaterMassFlowRate / waterCoil.MaxWaterMassFlowRate, 0.85) * waterCoil.UACoilInternalDes;
    1942              :         } else {
    1943            0 :             waterCoil.UACoilInternal = waterCoil.UACoilInternalDes;
    1944              :         }
    1945              : 
    1946     23067487 :         if (!(waterCoil.UACoilInternal > 0.0 && waterCoil.UACoilExternal > 0.0)) {
    1947     10295719 :             waterCoil.UACoilInternal = waterCoil.UACoilInternalDes;
    1948     10295719 :             waterCoil.UACoilExternal = waterCoil.UACoilExternalDes;
    1949              :         }
    1950              : 
    1951              :         // If Fouling
    1952     46150732 :         if (waterCoil.FaultyCoilFoulingFlag &&
    1953              :             // The fault shouldn't apply during sizing.
    1954     23068814 :             (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) && (!state.dataGlobal->KickOffSimulation) &&
    1955              :             // This was preexisting
    1956         1327 :             !(state.dataWaterCoils->MyUAAndFlowCalcFlag(CoilNum))) {
    1957              :             // Store original value
    1958              :             // This is really UACoilTotal technically, but I don't see the point of declaring another Real on the struct just for that
    1959         1327 :             waterCoil.OriginalUACoilVariable = 1.0 / (1.0 / waterCoil.UACoilExternal + 1.0 / waterCoil.UACoilInternal);
    1960              : 
    1961         1327 :             waterCoil.OriginalUACoilExternal = waterCoil.UACoilExternal;
    1962         1327 :             waterCoil.OriginalUACoilInternal = waterCoil.UACoilInternal;
    1963              : 
    1964         1327 :             int FaultIndex = waterCoil.FaultyCoilFoulingIndex;
    1965              : 
    1966         1327 :             FaultsManager::FaultPropertiesFoulingCoil &fouling = state.dataFaultsMgr->FouledCoils(FaultIndex);
    1967         1327 :             Real64 FaultFrac = fouling.FaultFraction(state);
    1968              : 
    1969         1327 :             if (fouling.FoulingInputMethod == FaultsManager::FouledCoil::FoulingFactor) {
    1970              :                 // Adjust the External (air) UA and Internal (water) UA accordingly
    1971            0 :                 Real64 Rfoul_air = FaultFrac * (fouling.Rfa / fouling.Aout);
    1972            0 :                 Real64 Rfoul_water = FaultFrac * (fouling.Rfw / (fouling.Aratio * fouling.Aout));
    1973              : 
    1974            0 :                 waterCoil.UACoilInternal = 1.0 / (1.0 / waterCoil.UACoilInternal + Rfoul_water);
    1975            0 :                 waterCoil.UACoilExternal = 1.0 / (1.0 / waterCoil.UACoilExternal + Rfoul_air);
    1976              :                 //
    1977              :             } else { // iFouledCoil_UARated
    1978              :                 // FouledUARated is supposed to be the overall UA. So we need to split between Internal and External UAs
    1979              : 
    1980              :                 // How should I split fouling between internal/external?
    1981              :                 // We can actually use the current ratio before fouling...
    1982              :                 // splitRatio = UACoilInternal/UACoilExternal
    1983              :                 // UACoilInternal = UACoilExternal * splitRatio
    1984              : 
    1985              :                 // UACoilTotal = 1 / (1 / UACoilExternal + 1 / UACoilInternal)
    1986              :                 // UACoilTotal = 1 / (1 / UACoilExternal + 1 / (UACoilExernal * splitRatio))
    1987              :                 // UACoilTotal = UACoilExternal / (1 + 1 / splitRatio) = UACoilExternal  * splitRatio / (1 + splitRatio)
    1988              :                 // UACoilExternal = UACoilTotal * (1 + splitRatio) / splitRatio
    1989              :                 // UACoilInternal = UACoilTotal * (1 + splitRatio)
    1990              : 
    1991              :                 // Adding in FaultFrac:
    1992              :                 // UACoilExternal = FaultFrac * [UAFouled * (1+splitRatio) / splitRatio] + (1-FaultFrac) * UACoilExternal
    1993              :                 // UACoilInternal = FaultFrac * [UAFouled * splitRatio] + (1-FaultFrac) * UACoilInternal
    1994              : 
    1995         1327 :                 Real64 splitRatio = waterCoil.UACoilInternal / waterCoil.UACoilExternal;
    1996              : 
    1997         1327 :                 waterCoil.UACoilExternal =
    1998         1327 :                     1.0 / ((FaultFrac * splitRatio) / ((1 + splitRatio) * fouling.UAFouled) + (1 - FaultFrac) / waterCoil.UACoilExternal);
    1999              : 
    2000              :                 // WaterCoil(CoilNum).UACoilInternal =   1.0 /
    2001              :                 //( FaultFrac / ((1 + splitRatio) * fouling.UAFouled) +
    2002              :                 //(1-FaultFrac) / WaterCoil(CoilNum).UACoilInternal);
    2003              : 
    2004         1327 :                 waterCoil.UACoilInternal = splitRatio * waterCoil.UACoilExternal;
    2005              :             }
    2006              : 
    2007              :             // Do not allow improving coil performance
    2008         1327 :             waterCoil.UACoilExternal = min(waterCoil.UACoilExternal, waterCoil.OriginalUACoilExternal);
    2009         1327 :             waterCoil.UACoilInternal = min(waterCoil.UACoilInternal, waterCoil.OriginalUACoilInternal);
    2010              : 
    2011              :             // Only for reporting purposes
    2012         1327 :             waterCoil.FaultyCoilFoulingFactor = (1.0 / waterCoil.UACoilExternal) - (1.0 / waterCoil.OriginalUACoilExternal) +
    2013         1327 :                                                 (1.0 / waterCoil.UACoilInternal) - (1.0 / waterCoil.OriginalUACoilInternal);
    2014              :         } else {
    2015     23066160 :             waterCoil.FaultyCoilFoulingFactor = 0;
    2016              :         }
    2017              : 
    2018     23067487 :         waterCoil.UACoilTotal = 1.0 / (1.0 / waterCoil.UACoilExternal + 1.0 / waterCoil.UACoilInternal);
    2019              : 
    2020     23067487 :         waterCoil.UACoilInternalPerUnitArea = waterCoil.UACoilInternal / waterCoil.TotCoilOutsideSurfArea;
    2021     23067487 :         waterCoil.UAWetExtPerUnitArea = waterCoil.UACoilExternal / waterCoil.TotCoilOutsideSurfArea;
    2022     23067487 :         waterCoil.UADryExtPerUnitArea = waterCoil.UAWetExtPerUnitArea;
    2023              :     }
    2024    149971537 : }
    2025              : 
    2026         3351 : void SizeWaterCoil(EnergyPlusData &state, int const CoilNum)
    2027              : {
    2028              : 
    2029              :     // SUBROUTINE INFORMATION:
    2030              :     //       AUTHOR         Fred Buhl
    2031              :     //       DATE WRITTEN   November 2001
    2032              :     //       MODIFIED       August 2013 Daeho Kang, add component sizing table entries
    2033              :     //       RE-ENGINEERED  na
    2034              : 
    2035              :     // PURPOSE OF THIS SUBROUTINE:
    2036              :     // This subroutine is for sizing Water Coil Components for which flow rates and UAs have not been
    2037              :     // specified in the input.
    2038              : 
    2039              :     // METHODOLOGY EMPLOYED:
    2040              :     // Obtains flow rates from the zone or system sizing arrays and plant sizing data. UAs are
    2041              :     // calculated by numerically inverting the individual coil calculation routines.
    2042              : 
    2043              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2044              :     static constexpr std::string_view RoutineName("SizeWaterCoil");
    2045              : 
    2046              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2047              :     Real64 rho;
    2048         3351 :     std::string CompType;                  // component type
    2049         3351 :     std::string SizingString;              // input field sizing description (e.g., Nominal Capacity)
    2050              :     Real64 TempSize;                       // autosized value
    2051              :     Real64 DesCoilWaterInTempSaved;        // coil water inlet temp used for error checking UA sizing
    2052         3351 :     Real64 DesCoilInletWaterTempUsed(0.0); // coil design inlet water temp for UA sizing only
    2053              :     Real64 Cp;
    2054              : 
    2055         3351 :     bool ErrorsFound = false;
    2056         3351 :     bool LoopErrorsFound = false;
    2057         3351 :     int PltSizCoolNum = 0;
    2058         3351 :     int PltSizHeatNum = 0;
    2059         3351 :     Real64 DesCoilAirFlow = 0.0;
    2060         3351 :     Real64 DesCoilExitTemp = 0.0;
    2061         3351 :     Real64 CpAirStd = PsyCpAirFnW(0.0);
    2062              : 
    2063         3351 :     auto &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    2064              :     // cooling coils
    2065         3351 :     if (((waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) ||
    2066         2917 :          (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling)) &&
    2067          596 :         waterCoil.RequestingAutoSize) {
    2068              :         // find the appropriate Plant Sizing object
    2069          493 :         PltSizCoolNum = PlantUtilities::MyPlantSizingIndex(
    2070              :             state, "chilled water coil", waterCoil.Name, waterCoil.WaterInletNodeNum, waterCoil.WaterOutletNodeNum, LoopErrorsFound);
    2071              :     }
    2072              : 
    2073         3351 :     if (((waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) ||
    2074         2917 :          (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling))) { // 'Cooling'
    2075              : 
    2076          596 :         if (waterCoil.UseDesignWaterDeltaTemp) {
    2077           34 :             state.dataSize->DataWaterCoilSizCoolDeltaT = waterCoil.DesignWaterDeltaTemp;
    2078              :         } else {
    2079          562 :             if (PltSizCoolNum > 0) {
    2080          459 :                 state.dataSize->DataWaterCoilSizCoolDeltaT = state.dataSize->PlantSizData(PltSizCoolNum).DeltaT;
    2081              :             }
    2082              :         }
    2083              : 
    2084          596 :         if (PltSizCoolNum > 0) {
    2085              : 
    2086              :             // int FieldNum = 0;
    2087          493 :             state.dataSize->DataPltSizCoolNum = PltSizCoolNum;
    2088          493 :             state.dataSize->DataWaterLoopNum = waterCoil.WaterPlantLoc.loopNum;
    2089              : 
    2090          493 :             if (waterCoil.WaterCoilModel == CoilModel::CoolingDetailed) {        // 'DETAILED FLAT FIN'
    2091           81 :                 CompType = HVAC::cAllCoilTypes(HVAC::Coil_CoolingWaterDetailed); // Coil:Cooling:Water:DetailedGeometry
    2092              :             } else {
    2093          412 :                 CompType = HVAC::cAllCoilTypes(HVAC::Coil_CoolingWater); // Coil:Cooling:Water
    2094              :             }
    2095              : 
    2096          493 :             bool bPRINT = false; // do not print this sizing request since the autosized value is needed and this input may not be autosized (we
    2097              :                                  // should print this!)
    2098          493 :             if (waterCoil.DesAirVolFlowRate == state.dataSize->DataFlowUsedForSizing) {
    2099           84 :                 TempSize = waterCoil.DesAirVolFlowRate; // represents parent object has hard-sized airflow
    2100              :             } else {
    2101          409 :                 TempSize = DataSizing::AutoSize; // get the autosized air volume flow rate for use in other calculations
    2102              :             }
    2103              : 
    2104          493 :             ErrorsFound = false;
    2105          493 :             CoolingAirFlowSizer sizingCoolingAirFlow;
    2106          493 :             std::string const &CompName = waterCoil.Name;
    2107          493 :             sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2108          493 :             Real64 autoSizedValue = sizingCoolingAirFlow.size(state, TempSize, ErrorsFound);
    2109          493 :             waterCoil.InletAirMassFlowRate = state.dataEnvrn->StdRhoAir * autoSizedValue; // inlet air mass flow rate is the autosized value
    2110              : 
    2111              :             // Check if the air volume flow rate is defined in parent HVAC equipment and set water coil design air volume flow rate accordingly
    2112          493 :             if (state.dataSize->CurZoneEqNum > 0) {
    2113          107 :                 auto const &ZoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
    2114          107 :                 if (ZoneEqSizing.DesignSizeFromParent && waterCoil.DesAirVolFlowRate == autoSizedValue) {
    2115           80 :                     state.dataSize->DataAirFlowUsedForSizing = ZoneEqSizing.AirVolFlow;
    2116           80 :                     state.dataSize->DataFlowUsedForSizing = ZoneEqSizing.AirVolFlow;
    2117           80 :                     waterCoil.DesAirVolFlowRate = DataSizing::AutoSize; // represents water coil being autosized
    2118              :                 } else {
    2119           27 :                     state.dataSize->DataAirFlowUsedForSizing =
    2120              :                         autoSizedValue; // many autosized inputs use the design (autosized) air volume flow rate, save this value
    2121           27 :                     state.dataSize->DataFlowUsedForSizing = autoSizedValue;
    2122              :                 }
    2123              :             } else {
    2124          386 :                 state.dataSize->DataAirFlowUsedForSizing =
    2125              :                     autoSizedValue; // many autosized inputs use the design (autosized) air volume flow rate, save this value
    2126          386 :                 state.dataSize->DataFlowUsedForSizing = autoSizedValue;
    2127              :             }
    2128              : 
    2129          493 :             if (state.dataSize->CurSysNum > 0 && state.dataSize->CurOASysNum == 0) {
    2130          355 :                 Real64 DesCoilExitHumRat(0.0); // fix coil sizing inconsistency
    2131          355 :                 DataSizing::GetCoilDesFlowT(state, state.dataSize->CurSysNum, CpAirStd, DesCoilAirFlow, DesCoilExitTemp, DesCoilExitHumRat);
    2132          355 :                 state.dataSize->DataAirFlowUsedForSizing = DesCoilAirFlow;
    2133          355 :                 state.dataSize->DataFlowUsedForSizing = DesCoilAirFlow;
    2134          355 :                 state.dataSize->DataDesOutletAirTemp = DesCoilExitTemp;
    2135          355 :                 state.dataSize->DataDesOutletAirHumRat = DesCoilExitHumRat; // need to test for dry coil but inlet conditions not yet known
    2136              :             }
    2137              : 
    2138              :             // calculate pre-sizing data needed for specific functions (e.g., CoolingWaterDesAirInletTempSizing needs HRin and air flow)
    2139              :             // these will be calculated again after other parameters are known
    2140          493 :             if (waterCoil.WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
    2141           81 :                 TempSize = DataSizing::AutoSize;                          // coil report
    2142              :             } else {
    2143          412 :                 TempSize = waterCoil.DesInletAirHumRat; // preserve input if entered
    2144              :             }
    2145          493 :             CoolingWaterDesAirInletHumRatSizer sizerCWDesInHumRat;
    2146          493 :             sizerCWDesInHumRat.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2147          493 :             state.dataSize->DataDesInletAirHumRat = sizerCWDesInHumRat.size(state, TempSize, ErrorsFound);
    2148              : 
    2149          493 :             TempSize = DataSizing::AutoSize;
    2150          493 :             CoolingCapacitySizer sizerCoolingCapacity;
    2151          493 :             sizerCoolingCapacity.overrideSizingString(SizingString);
    2152          493 :             sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2153          493 :             state.dataSize->DataCapacityUsedForSizing = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
    2154          493 :             TempSize = waterCoil.MaxWaterVolFlowRate;
    2155          493 :             CoolingWaterflowSizer sizerCWWaterflow;
    2156          493 :             sizerCWWaterflow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2157          493 :             Real64 autoSizedCWFlow = sizerCWWaterflow.size(state, TempSize, ErrorsFound);
    2158              :             // Check if the water flow rate is defined in parent HVAC equipment and set water coil design water flow rate accordingly
    2159          493 :             if (state.dataSize->CurZoneEqNum > 0) {
    2160          107 :                 auto const &ZoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
    2161          107 :                 if (ZoneEqSizing.DesignSizeFromParent) {
    2162           81 :                     state.dataSize->DataWaterFlowUsedForSizing = ZoneEqSizing.MaxCWVolFlow;
    2163              :                 } else {
    2164           26 :                     state.dataSize->DataWaterFlowUsedForSizing = autoSizedCWFlow;
    2165              :                 }
    2166              :             } else {
    2167          386 :                 state.dataSize->DataWaterFlowUsedForSizing = autoSizedCWFlow;
    2168              :             }
    2169              :             // end pre-sizing data calculations
    2170              : 
    2171          493 :             if (waterCoil.WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
    2172           81 :                 bPRINT = false; // do not print this sizing request since this coil does not have a design inlet air temp input field (we
    2173              :                                 // should print this!)
    2174           81 :                 TempSize = DataSizing::AutoSize; // not an input for this model
    2175              :             } else {
    2176          412 :                 bPRINT = true;
    2177          412 :                 TempSize = waterCoil.DesInletAirTemp; // preserve input if entered
    2178              :             }
    2179              : 
    2180          493 :             CoolingWaterDesAirInletTempSizer sizerCWDesInletAirTemp;
    2181          493 :             sizerCWDesInletAirTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2182          493 :             waterCoil.DesInletAirTemp = sizerCWDesInletAirTemp.size(state, TempSize, ErrorsFound);
    2183          493 :             state.dataSize->DataDesInletAirTemp = waterCoil.DesInletAirTemp;
    2184              : 
    2185          493 :             if (waterCoil.WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
    2186           81 :                 bPRINT = false;                                           // no field for detailed water coil, should print to eio anyway
    2187           81 :                 TempSize = DataSizing::AutoSize;                          // coil report
    2188              :             } else {
    2189          412 :                 bPRINT = true;
    2190          412 :                 TempSize = waterCoil.DesInletWaterTemp; // preserve input if entered
    2191              :             }
    2192          493 :             CoolingWaterDesWaterInletTempSizer sizerCWDesWaterInTemp;
    2193          493 :             sizerCWDesWaterInTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2194          493 :             waterCoil.DesInletWaterTemp = sizerCWDesWaterInTemp.size(state, TempSize, ErrorsFound);
    2195              : 
    2196          493 :             if ((waterCoil.DesInletWaterTemp > state.dataSize->DataDesOutletAirTemp) && state.dataSize->DataDesOutletAirTemp > 0.0) {
    2197            0 :                 ShowWarningError(state, format("Invalid design inlet water temperature for {} = {}", CompType, CompName));
    2198            0 :                 ShowContinueError(state, format("...design inlet water temperature = {:.3R} C", waterCoil.DesInletWaterTemp));
    2199            0 :                 ShowContinueError(state, format("...design outlet air temperature = {:.3R} C", state.dataSize->DataDesOutletAirTemp));
    2200            0 :                 ShowContinueError(state, "...design inlet water temperature should be less than the design outlet air temperature");
    2201            0 :                 ShowContinueError(state, "...design inlet water temperature is set to the design outlet air temperature minus 5.0C");
    2202            0 :                 waterCoil.DesInletWaterTemp = state.dataSize->DataDesOutletAirTemp - 5.0;
    2203              :             }
    2204              : 
    2205          493 :             if (state.dataSize->CurZoneEqNum > 0) { // zone equipment use air inlet humrat to calculate design outlet air temperature
    2206          107 :                 if (waterCoil.WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
    2207            0 :                     bPRINT = false;                                           // no field for detailed water coil, should print to eio anyway
    2208            0 :                     TempSize = DataSizing::AutoSize;                          // coil report
    2209              :                 } else {
    2210          107 :                     bPRINT = true;
    2211          107 :                     TempSize = waterCoil.DesInletAirHumRat; // preserve input if entered
    2212              :                 }
    2213          107 :                 sizerCWDesInHumRat.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2214          107 :                 waterCoil.DesInletAirHumRat = sizerCWDesInHumRat.size(state, TempSize, ErrorsFound);
    2215              :             }
    2216              : 
    2217          493 :             if (waterCoil.WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
    2218           81 :                 bPRINT = false;                                           // no field for detailed water coil, should print to eio anyway
    2219           81 :                 TempSize = DataSizing::AutoSize;                          // coil report
    2220              :             } else {
    2221          412 :                 bPRINT = true;
    2222          412 :                 TempSize = waterCoil.DesOutletAirTemp; // preserve input if entered
    2223              :             }
    2224              : 
    2225          493 :             state.dataSize->DataDesInletWaterTemp = waterCoil.DesInletWaterTemp; // used for warning messages
    2226          493 :             CoolingWaterDesAirOutletTempSizer sizerCWDesAirOutTemp;
    2227          493 :             sizerCWDesAirOutTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2228          493 :             waterCoil.DesOutletAirTemp = sizerCWDesAirOutTemp.size(state, TempSize, ErrorsFound);
    2229          493 :             state.dataSize->DataDesOutletAirTemp = waterCoil.DesOutletAirTemp;
    2230              : 
    2231          493 :             if (state.dataSize->CurSysNum > 0) { // This call can be deleted at a future time and remove the if ( CurZoneEqNum > 0 ) check above. This
    2232              :                                                  // will change the order of the eio file.
    2233          386 :                 if (waterCoil.WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
    2234           81 :                     bPRINT = false;                                           // no field for detailed water coil, should print this to eio anyway
    2235           81 :                     TempSize = DataSizing::AutoSize;                          // coil report
    2236              :                 } else {
    2237          305 :                     bPRINT = true;
    2238          305 :                     TempSize = waterCoil.DesInletAirHumRat;
    2239              :                 }
    2240          386 :                 sizerCWDesInHumRat.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2241          386 :                 waterCoil.DesInletAirHumRat = sizerCWDesInHumRat.size(state, TempSize, ErrorsFound);
    2242              :             }
    2243              : 
    2244          493 :             if (waterCoil.WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
    2245           81 :                 bPRINT = false;                                           // no field for detailed water coil, should print this to eio anyway
    2246           81 :                 TempSize = DataSizing::AutoSize;                          // coil report
    2247              :             } else {
    2248          412 :                 bPRINT = true;
    2249          412 :                 TempSize = waterCoil.DesOutletAirHumRat; // preserve input if entered
    2250              :             }
    2251          493 :             CoolingWaterDesAirOutletHumRatSizer sizerCWDesOutHumRat;
    2252          493 :             sizerCWDesOutHumRat.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2253          493 :             waterCoil.DesOutletAirHumRat = sizerCWDesOutHumRat.size(state, TempSize, ErrorsFound);
    2254          493 :             state.dataSize->DataDesOutletAirHumRat = waterCoil.DesOutletAirHumRat;
    2255              : 
    2256          493 :             TempSize = DataSizing::AutoSize;
    2257          493 :             bPRINT = true;
    2258          493 :             if (waterCoil.MaxWaterVolFlowRate != DataSizing::AutoSize) {
    2259            0 :                 bPRINT = false;
    2260              :             }
    2261          493 :             if (state.dataSize->CurSysNum == 0) {
    2262          107 :                 bPRINT = false;
    2263              :             }
    2264          493 :             SizingString = "Design Coil Load [W]"; // there is no input field for this value and this is not the rated capacity (we should
    2265              :                                                    // always print this!)
    2266              :             // air inlet/outlet conditions should be known. Don't include fan heat in capacity calculation.
    2267          493 :             state.dataSize->DataDesAccountForFanHeat = false;
    2268          493 :             CoolingCapacitySizer sizerCoolingCapacity2;
    2269          493 :             sizerCoolingCapacity2.overrideSizingString(SizingString);
    2270          493 :             sizerCoolingCapacity2.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2271          493 :             waterCoil.DesWaterCoolingCoilRate = sizerCoolingCapacity2.size(state, TempSize, ErrorsFound);
    2272          493 :             waterCoil.InletAirMassFlowRate =
    2273          493 :                 state.dataEnvrn->StdRhoAir * state.dataSize->DataFlowUsedForSizing; // inlet air mass flow rate is the autosized value
    2274          493 :             state.dataSize->DataCapacityUsedForSizing = waterCoil.DesWaterCoolingCoilRate;
    2275              : 
    2276              :             // Why isn't the water volume flow rate based on the user inputs for inlet/outlet air/water temps? Water volume flow rate is
    2277              :             // always based on autosized inputs.
    2278          493 :             bPRINT = true;
    2279          493 :             TempSize = waterCoil.MaxWaterVolFlowRate;
    2280          493 :             sizerCWWaterflow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2281          493 :             waterCoil.MaxWaterVolFlowRate = sizerCWWaterflow.size(state, TempSize, ErrorsFound);
    2282          493 :             state.dataSize->DataWaterFlowUsedForSizing = waterCoil.MaxWaterVolFlowRate;
    2283              : 
    2284          493 :             if (waterCoil.WaterCoilModel == CoilModel::CoolingDetailed) { // 'DETAILED FLAT FIN'
    2285           81 :                 bPRINT = false; // do not print this sizing request since this coil does not have a design air flow rate input field (we
    2286              :                                 // should print this!)
    2287              :             } else {
    2288          412 :                 bPRINT = true;
    2289              :             }
    2290          493 :             TempSize = waterCoil.DesAirVolFlowRate;
    2291          493 :             CoolingAirFlowSizer sizingCoolingAirFlow2;
    2292          493 :             std::string stringOverride = "Design Air Flow Rate [m3/s]";
    2293          493 :             if (state.dataGlobal->isEpJSON) {
    2294            0 :                 stringOverride = "design_air_flow_rate [m3/s]";
    2295              :             }
    2296          493 :             sizingCoolingAirFlow2.overrideSizingString(stringOverride);
    2297              :             // sizingCoolingAirFlow2.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
    2298          493 :             sizingCoolingAirFlow2.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2299          493 :             waterCoil.DesAirVolFlowRate = sizingCoolingAirFlow2.size(state, TempSize, ErrorsFound);
    2300          493 :             waterCoil.DesAirMassFlowRate = waterCoil.DesAirVolFlowRate * state.dataEnvrn->StdRhoAir;
    2301              : 
    2302          493 :             if (waterCoil.DesAirVolFlowRate <= 0.0) {
    2303            0 :                 waterCoil.DesAirVolFlowRate = 0.0;
    2304            0 :                 ShowWarningError(state, format("The design air flow rate is zero for {} = {}", CompType, CompName));
    2305            0 :                 ShowContinueError(state, "The autosize value for max air volume flow rate is zero");
    2306              :             }
    2307              : 
    2308          493 :             if (waterCoil.WaterCoilModel == CoilModel::CoolingDetailed) {
    2309              : 
    2310           81 :                 int FieldNum = 16; //  N16, \field Number of Tubes per Row
    2311           81 :                 bPRINT = true;
    2312           81 :                 SizingString = state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames(FieldNum);
    2313              :                 // Auto size detailed cooling coil number of tubes per row = int( 13750.0 * WaterCoil( CoilNum ).MaxWaterVolFlowRate ) + 1
    2314           81 :                 state.dataSize->DataFlowUsedForSizing = waterCoil.MaxWaterVolFlowRate;
    2315           81 :                 TempSize = float(waterCoil.NumOfTubesPerRow);
    2316           81 :                 CoolingWaterNumofTubesPerRowSizer sizerCWNumofTubesPerRow;
    2317           81 :                 sizerCWNumofTubesPerRow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2318           81 :                 waterCoil.NumOfTubesPerRow = sizerCWNumofTubesPerRow.size(state, TempSize, ErrorsFound);
    2319              : 
    2320              :                 // Auto size water coil fin diameter = 0.335 * WaterCoil( CoilNum ).InletAirMassFlowRate
    2321           81 :                 state.dataSize->DataConstantUsedForSizing = waterCoil.InletAirMassFlowRate;
    2322           81 :                 state.dataSize->DataFractionUsedForSizing = 0.335;
    2323           81 :                 TempSize = waterCoil.FinDiam;
    2324              : 
    2325           81 :                 AutoCalculateSizer sizerFinDiameter;
    2326           81 :                 stringOverride = "Fin Diameter [m]";
    2327           81 :                 if (state.dataGlobal->isEpJSON) {
    2328            0 :                     stringOverride = "fin_diameter [m]";
    2329              :                 }
    2330           81 :                 sizerFinDiameter.overrideSizingString(stringOverride);
    2331           81 :                 sizerFinDiameter.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2332           81 :                 waterCoil.FinDiam = sizerFinDiameter.size(state, TempSize, ErrorsFound);
    2333              : 
    2334              :                 // Auto size water coil minimum airflow area = 0.44 * WaterCoil( CoilNum ).InletAirMassFlowRate
    2335           81 :                 state.dataSize->DataConstantUsedForSizing = waterCoil.InletAirMassFlowRate;
    2336           81 :                 state.dataSize->DataFractionUsedForSizing = 0.44;
    2337           81 :                 TempSize = waterCoil.MinAirFlowArea;
    2338              : 
    2339           81 :                 AutoCalculateSizer sizerMinAirFlowArea;
    2340           81 :                 stringOverride = "Minimum Airflow Area [m2]";
    2341           81 :                 if (state.dataGlobal->isEpJSON) {
    2342            0 :                     stringOverride = "minimum_airflow_area [m2]";
    2343              :                 }
    2344           81 :                 sizerMinAirFlowArea.overrideSizingString(stringOverride);
    2345           81 :                 sizerMinAirFlowArea.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2346           81 :                 waterCoil.MinAirFlowArea = sizerMinAirFlowArea.size(state, TempSize, ErrorsFound);
    2347              : 
    2348           81 :                 if (waterCoil.MinAirFlowArea <= 0.0) {
    2349            0 :                     ShowSevereError(state, format("Coil:Cooling:Water:DetailedGeometry: \"{}\"", waterCoil.Name));
    2350            0 :                     ShowContinueError(state,
    2351            0 :                                       format("Coil Minimum Airflow Area must be greater than 0. Coil area = {:.6T}", waterCoil.MinAirFlowArea));
    2352            0 :                     ErrorsFound = true;
    2353              :                 }
    2354              : 
    2355              :                 // Auto size water coil finned surface area = 78.5 * WaterCoil( CoilNum ).InletAirMassFlowRate
    2356          162 :                 state.dataSize->DataConstantUsedForSizing =
    2357           81 :                     waterCoil.InletAirMassFlowRate; // actual autosized air mass flow rate, not calculated from user input
    2358           81 :                 state.dataSize->DataFractionUsedForSizing = 78.5;
    2359           81 :                 TempSize = waterCoil.FinSurfArea;
    2360              : 
    2361           81 :                 AutoCalculateSizer sizerFinSurfaceArea;
    2362           81 :                 stringOverride = "Fin Surface Area [m2]";
    2363           81 :                 if (state.dataGlobal->isEpJSON) {
    2364            0 :                     stringOverride = "fin_surface_area [m2]";
    2365              :                 }
    2366           81 :                 sizerFinSurfaceArea.overrideSizingString(stringOverride);
    2367           81 :                 sizerFinSurfaceArea.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2368           81 :                 waterCoil.FinSurfArea = sizerFinSurfaceArea.size(state, TempSize, ErrorsFound);
    2369              : 
    2370              :                 // Auto size water coil total tube inside surface area = 4.4 * WaterCoil( CoilNum ).TubeInsideDiam * WaterCoil( CoilNum
    2371              :                 // ).NumOfTubeRows * WaterCoil( CoilNum ).NumOfTubesPerRow
    2372           81 :                 state.dataSize->DataConstantUsedForSizing = waterCoil.TubeInsideDiam * waterCoil.NumOfTubeRows * waterCoil.NumOfTubesPerRow;
    2373           81 :                 state.dataSize->DataFractionUsedForSizing = 4.4;
    2374           81 :                 TempSize = waterCoil.TotTubeInsideArea;
    2375              : 
    2376           81 :                 AutoCalculateSizer sizerTubeInsideArea;
    2377           81 :                 stringOverride = "Total Tube Inside Area [m2]";
    2378           81 :                 if (state.dataGlobal->isEpJSON) {
    2379            0 :                     stringOverride = "total_tube_inside_area [m2]";
    2380              :                 }
    2381           81 :                 sizerTubeInsideArea.overrideSizingString(stringOverride);
    2382           81 :                 sizerTubeInsideArea.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2383           81 :                 waterCoil.TotTubeInsideArea = sizerTubeInsideArea.size(state, TempSize, ErrorsFound);
    2384              : 
    2385              :                 // Auto size water coil total tube outside surface area = 4.1 * WaterCoil( CoilNum ).TubeOutsideDiam * WaterCoil( CoilNum
    2386              :                 // ).NumOfTubeRows * WaterCoil( CoilNum ).NumOfTubesPerRow
    2387           81 :                 state.dataSize->DataConstantUsedForSizing = waterCoil.TubeOutsideDiam * waterCoil.NumOfTubeRows * waterCoil.NumOfTubesPerRow;
    2388           81 :                 state.dataSize->DataFractionUsedForSizing = 4.1;
    2389           81 :                 TempSize = waterCoil.TubeOutsideSurfArea;
    2390              : 
    2391           81 :                 AutoCalculateSizer sizerTubeOutsideArea;
    2392           81 :                 stringOverride = "Tube Outside Surface Area [m2]";
    2393           81 :                 if (state.dataGlobal->isEpJSON) {
    2394            0 :                     stringOverride = "tube_outside_surface_area [m2]";
    2395              :                 }
    2396           81 :                 sizerTubeOutsideArea.overrideSizingString(stringOverride);
    2397           81 :                 sizerTubeOutsideArea.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2398           81 :                 waterCoil.TubeOutsideSurfArea = sizerTubeOutsideArea.size(state, TempSize, ErrorsFound);
    2399              : 
    2400           81 :                 if ((waterCoil.FinSurfArea + waterCoil.TubeOutsideSurfArea) <= 0.0) {
    2401            0 :                     ShowSevereError(state, format("Coil:Cooling:Water:DetailedGeometry: \"{}\"", waterCoil.Name));
    2402            0 :                     ShowContinueError(
    2403              :                         state,
    2404            0 :                         format("Coil Fin Surface Area plus Coil Tube Outside Surface Area must be greater than 0. Total surface area = {:.6T}",
    2405            0 :                                (waterCoil.FinSurfArea + waterCoil.TubeOutsideSurfArea)));
    2406            0 :                     ErrorsFound = true;
    2407              :                 }
    2408              : 
    2409              :                 // Auto size water coil coil depth = WaterCoil( CoilNum ).TubeDepthSpacing * WaterCoil( CoilNum ).NumOfTubeRows
    2410           81 :                 state.dataSize->DataConstantUsedForSizing = waterCoil.TubeDepthSpacing;
    2411           81 :                 state.dataSize->DataFractionUsedForSizing = waterCoil.NumOfTubeRows;
    2412           81 :                 TempSize = waterCoil.CoilDepth;
    2413              : 
    2414           81 :                 AutoCalculateSizer sizerCoilDepth;
    2415           81 :                 stringOverride = "Coil Depth [m]";
    2416           81 :                 if (state.dataGlobal->isEpJSON) {
    2417            0 :                     stringOverride = "coil_depth [m]";
    2418              :                 }
    2419           81 :                 sizerCoilDepth.overrideSizingString(stringOverride);
    2420           81 :                 sizerCoilDepth.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2421           81 :                 waterCoil.CoilDepth = sizerCoilDepth.size(state, TempSize, ErrorsFound);
    2422           81 :             }
    2423          493 :             state.dataSize->DataPltSizCoolNum = 0; // reset all globals to 0 to ensure correct sizing for other child components
    2424          493 :             state.dataSize->DataWaterLoopNum = 0;
    2425          493 :             state.dataSize->DataConstantUsedForSizing = 0.0;
    2426          493 :             state.dataSize->DataFractionUsedForSizing = 0.0;
    2427          493 :             state.dataSize->DataAirFlowUsedForSizing = 0.0;
    2428          493 :             state.dataSize->DataFlowUsedForSizing = 0.0;
    2429          493 :             state.dataSize->DataWaterFlowUsedForSizing = 0.0;
    2430          493 :             state.dataSize->DataCapacityUsedForSizing = 0.0;
    2431          493 :             state.dataSize->DataDesInletAirTemp = 0.0;
    2432          493 :             state.dataSize->DataDesOutletAirTemp = 0.0;
    2433          493 :             state.dataSize->DataDesOutletAirHumRat = 0.0;
    2434          493 :             state.dataSize->DataDesInletAirHumRat = 0.0;
    2435          493 :             state.dataSize->DataDesInletWaterTemp = 0.0;
    2436          493 :             state.dataSize->DataWaterCoilSizCoolDeltaT = 0.0;
    2437          493 :             state.dataSize->DataDesAccountForFanHeat = true;
    2438          493 :         } else {
    2439              :             // If there is no cooling Plant Sizing object and autosizing was requested, issue fatal error message
    2440          103 :             if (waterCoil.RequestingAutoSize) {
    2441            0 :                 ShowSevereError(state, "Autosizing of water coil requires a cooling loop Sizing:Plant object");
    2442            0 :                 ShowContinueError(state, format("Occurs in water coil object= {}", waterCoil.Name));
    2443            0 :                 ErrorsFound = true;
    2444              :             }
    2445              :         }
    2446              :         //} // end of cooling Plant Sizing existence IF - ELSE
    2447              :     } // end cooling coil IF
    2448              : 
    2449              :     // if this is a heating coil
    2450         3351 :     if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating && waterCoil.RequestingAutoSize) {
    2451              :         // find the appropriate heating Plant Sizing object
    2452         2449 :         PltSizHeatNum = PlantUtilities::MyPlantSizingIndex(
    2453              :             state, "hot water coil", waterCoil.Name, waterCoil.WaterInletNodeNum, waterCoil.WaterOutletNodeNum, LoopErrorsFound);
    2454              :     }
    2455              : 
    2456         3351 :     if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
    2457              : 
    2458         2755 :         if (waterCoil.UseDesignWaterDeltaTemp) {
    2459              :             // use water design deltaT specified in the heating water coils
    2460          114 :             state.dataSize->DataWaterCoilSizHeatDeltaT = waterCoil.DesignWaterDeltaTemp;
    2461              :         } else {
    2462         2641 :             if (PltSizHeatNum > 0) {
    2463         2335 :                 state.dataSize->DataWaterCoilSizHeatDeltaT = state.dataSize->PlantSizData(PltSizHeatNum).DeltaT;
    2464              :             }
    2465              :         }
    2466              : 
    2467         2755 :         if (PltSizHeatNum > 0) {
    2468              : 
    2469         2449 :             int FieldNum = 0;
    2470         2449 :             bool NomCapUserInp = false; // flag for whether user has onput a nominal heating capacity
    2471              : 
    2472         2449 :             state.dataSize->DataPltSizHeatNum = PltSizHeatNum;
    2473         2449 :             state.dataSize->DataWaterLoopNum = waterCoil.WaterPlantLoc.loopNum;
    2474         2449 :             rho = state.dataPlnt->PlantLoop(waterCoil.WaterPlantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    2475         2449 :             Cp = state.dataPlnt->PlantLoop(state.dataSize->DataWaterLoopNum).glycol->getSpecificHeat(state, Constant::HWInitConvTemp, RoutineName);
    2476         2449 :             if (waterCoil.DesTotWaterCoilLoad > 0.0) {
    2477           35 :                 NomCapUserInp = true;
    2478         2414 :             } else if (state.dataSize->CurSysNum > 0 && state.dataSize->CurSysNum <= state.dataHVACGlobal->NumPrimaryAirSys) {
    2479          415 :                 if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatingCapMethod == DataSizing::CapacityPerFloorArea) {
    2480            0 :                     NomCapUserInp = true;
    2481          829 :                 } else if (state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatingCapMethod == DataSizing::HeatingDesignCapacity &&
    2482          414 :                            state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatingTotalCapacity > 0.0) {
    2483            0 :                     NomCapUserInp = true;
    2484              :                 }
    2485              :             } else {
    2486         1999 :                 NomCapUserInp = false;
    2487              :             }
    2488         2449 :             bool bPRINT = false;                                     // do not print this sizing request
    2489         2449 :             TempSize = DataSizing::AutoSize;                         // get the autosized air volume flow rate for use in other calculations
    2490         2449 :             SizingString.clear();                                    // doesn't matter
    2491         2449 :             CompType = HVAC::cAllCoilTypes(HVAC::Coil_HeatingWater); // "Coil:Heating:Water"
    2492         2449 :             std::string const &CompName = waterCoil.Name;
    2493         2449 :             if (waterCoil.DesiccantRegenerationCoil) {
    2494            0 :                 state.dataSize->DataDesicRegCoil = true;
    2495            0 :                 state.dataSize->DataDesicDehumNum = waterCoil.DesiccantDehumNum;
    2496            0 :                 HeatingCoilDesAirInletTempSizer sizerHeatingDesInletTemp;
    2497            0 :                 ErrorsFound = false;
    2498            0 :                 sizerHeatingDesInletTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2499            0 :                 state.dataSize->DataDesInletAirTemp = sizerHeatingDesInletTemp.size(state, DataSizing::AutoSize, ErrorsFound);
    2500              : 
    2501            0 :                 HeatingCoilDesAirOutletTempSizer sizerHeatingDesOutletTemp;
    2502            0 :                 ErrorsFound = false;
    2503            0 :                 sizerHeatingDesOutletTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2504            0 :                 state.dataSize->DataDesOutletAirTemp = sizerHeatingDesOutletTemp.size(state, DataSizing::AutoSize, ErrorsFound);
    2505              : 
    2506            0 :                 if (state.dataSize->CurOASysNum > 0) {
    2507            0 :                     auto &OASysEqSizing = state.dataSize->OASysEqSizing(state.dataSize->CurOASysNum);
    2508            0 :                     OASysEqSizing.AirFlow = true;
    2509            0 :                     OASysEqSizing.AirVolFlow = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesOutAirVolFlow;
    2510              :                 }
    2511            0 :                 TempSize = DataSizing::AutoSize; // reset back
    2512            0 :             }
    2513         2449 :             ErrorsFound = false;
    2514         2449 :             HeatingAirFlowSizer sizingHeatingAirFlow;
    2515         2449 :             sizingHeatingAirFlow.overrideSizingString(SizingString);
    2516              :             // sizingHeatingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
    2517         2449 :             sizingHeatingAirFlow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2518         2449 :             TempSize = sizingHeatingAirFlow.size(state, TempSize, ErrorsFound);
    2519              :             // reset the design air volume flow rate for air loop coils only
    2520         2449 :             if (state.dataSize->CurSysNum > 0) {
    2521          416 :                 waterCoil.DesAirVolFlowRate = TempSize;
    2522              :             }
    2523         2449 :             waterCoil.InletAirMassFlowRate = state.dataEnvrn->StdRhoAir * TempSize; // inlet air mass flow rate is not the autosized value
    2524         2449 :             state.dataSize->DataAirFlowUsedForSizing = TempSize;
    2525         2449 :             state.dataSize->DataFlowUsedForSizing = TempSize; // many autosized inputs use the design (autosized) air flow rate, save this value
    2526              : 
    2527         2449 :             bPRINT = true;
    2528         2449 :             if (waterCoil.CoilPerfInpMeth == state.dataWaterCoils->NomCap && NomCapUserInp) {
    2529           35 :                 TempSize = waterCoil.DesTotWaterCoilLoad;
    2530           35 :                 state.dataSize->DataNomCapInpMeth = true;
    2531              :             } else {
    2532         2414 :                 TempSize = DataSizing::AutoSize;
    2533              :             }
    2534         2449 :             if (state.dataSize->CurSysNum > 0) {
    2535          416 :                 FieldNum = 3; //  N3 , \field Rated Capacity
    2536          416 :                 SizingString = state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames(FieldNum) + " [W]";
    2537          416 :                 ErrorsFound = false;
    2538          416 :                 HeatingCapacitySizer sizerHeatingCapacity;
    2539          416 :                 sizerHeatingCapacity.overrideSizingString(SizingString);
    2540          416 :                 sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2541          416 :                 TempSize = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
    2542          416 :                 waterCoil.DesWaterHeatingCoilRate = TempSize;
    2543          416 :                 waterCoil.DesTotWaterCoilLoad = TempSize;
    2544          416 :                 state.dataSize->DataCapacityUsedForSizing = waterCoil.DesWaterHeatingCoilRate;
    2545          416 :             } else {
    2546         2033 :                 WaterHeatingCapacitySizer sizerWaterHeatingCapacity;
    2547         2033 :                 ErrorsFound = false;
    2548         2033 :                 sizerWaterHeatingCapacity.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2549         2033 :                 waterCoil.DesWaterHeatingCoilRate = sizerWaterHeatingCapacity.size(state, TempSize, ErrorsFound);
    2550         2033 :                 waterCoil.DesTotWaterCoilLoad = waterCoil.DesWaterHeatingCoilRate;
    2551         2033 :                 state.dataSize->DataCapacityUsedForSizing = waterCoil.DesWaterHeatingCoilRate;
    2552         2033 :             }
    2553              : 
    2554              :             // We now have the design load if it was autosized. For the case of CoilPerfInpMeth == NomCap, calculate the air flow rate
    2555              :             // specified by the NomCap inputs. This overrides all previous values
    2556         2449 :             if (waterCoil.CoilPerfInpMeth == state.dataWaterCoils->NomCap && NomCapUserInp) {
    2557           35 :                 waterCoil.InletAirMassFlowRate =
    2558           35 :                     waterCoil.DesTotWaterCoilLoad / (CpAirStd * (waterCoil.DesOutletAirTemp - waterCoil.DesInletAirTemp));
    2559           35 :                 waterCoil.DesAirVolFlowRate = waterCoil.InletAirMassFlowRate / state.dataEnvrn->StdRhoAir;
    2560           35 :                 state.dataSize->DataAirFlowUsedForSizing = waterCoil.DesAirVolFlowRate;
    2561           35 :                 state.dataSize->DataFlowUsedForSizing = waterCoil.DesAirVolFlowRate;
    2562              :             }
    2563              : 
    2564         2449 :             TempSize = waterCoil.MaxWaterVolFlowRate;
    2565              : 
    2566         2449 :             if (waterCoil.CoilPerfInpMeth == state.dataWaterCoils->NomCap && NomCapUserInp) {
    2567           35 :                 if (waterCoil.DesTotWaterCoilLoad > HVAC::SmallLoad) {
    2568           35 :                     waterCoil.MaxWaterVolFlowRate =
    2569           35 :                         state.dataSize->DataCapacityUsedForSizing / (Cp * rho * (waterCoil.DesInletWaterTemp - waterCoil.DesOutletWaterTemp));
    2570              :                 } else {
    2571            0 :                     waterCoil.MaxWaterVolFlowRate = 0.0;
    2572              :                 }
    2573           35 :                 state.dataSize->DataConstantUsedForSizing = waterCoil.MaxWaterVolFlowRate;
    2574           35 :                 state.dataSize->DataFractionUsedForSizing = 1.0;
    2575              :             }
    2576         2449 :             HeatingWaterflowSizer sizerHWWaterflow;
    2577         2449 :             sizerHWWaterflow.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2578         2449 :             Real64 sizedMaxWaterVolFlowRate = sizerHWWaterflow.size(state, TempSize, ErrorsFound);
    2579              :             // Check if the water flow rate is defined in parent HVAC equipment and set water coil design water flow rate accordingly
    2580         2449 :             if (state.dataSize->CurZoneEqNum > 0) {
    2581         2033 :                 auto const &ZoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
    2582         2033 :                 if (ZoneEqSizing.DesignSizeFromParent) {
    2583           80 :                     state.dataSize->DataWaterFlowUsedForSizing = ZoneEqSizing.MaxHWVolFlow;
    2584           80 :                     waterCoil.MaxWaterVolFlowRate = ZoneEqSizing.MaxHWVolFlow;
    2585              :                 } else {
    2586         1953 :                     state.dataSize->DataWaterFlowUsedForSizing = sizedMaxWaterVolFlowRate;
    2587         1953 :                     waterCoil.MaxWaterVolFlowRate = sizedMaxWaterVolFlowRate;
    2588              :                 }
    2589              :             } else {
    2590          416 :                 state.dataSize->DataWaterFlowUsedForSizing = sizedMaxWaterVolFlowRate;
    2591          416 :                 waterCoil.MaxWaterVolFlowRate = sizedMaxWaterVolFlowRate;
    2592              :             }
    2593         2449 :             state.dataSize->DataConstantUsedForSizing = 0.0; // reset these in case NomCapUserInp was true
    2594         2449 :             state.dataSize->DataFractionUsedForSizing = 0.0;
    2595         2449 :             if (waterCoil.MaxWaterVolFlowRate <= 0.0) {
    2596              :                 //                    MaxWaterVolFlowRateDes = 0.0;
    2597           31 :                 ShowWarningError(state, format("The design coil load is zero for Coil:Heating:Water {}", waterCoil.Name));
    2598           62 :                 ShowContinueError(state, "The autosize value for maximum water flow rate is zero");
    2599           62 :                 ShowContinueError(state, "To change this, input a value for UA, change the heating design day, or raise the");
    2600           62 :                 ShowContinueError(state, "  system heating design supply air temperature. Also check to make sure the Preheat");
    2601           93 :                 ShowContinueError(state, "  Design Temperature is not the same as the Central Heating Design Supply Air Temperature. ");
    2602              :             }
    2603              : 
    2604              :             // initialize the water coil inlet conditions
    2605         2449 :             bPRINT = false; // no need to print to eio since we only need the values
    2606         2449 :             state.dataSize->DataFlowUsedForSizing = state.dataSize->DataAirFlowUsedForSizing;
    2607         2449 :             if (waterCoil.CoilPerfInpMeth == state.dataWaterCoils->NomCap && NomCapUserInp) {
    2608           35 :                 waterCoil.InletAirTemp = waterCoil.DesInletAirTemp;
    2609           35 :                 waterCoil.InletAirHumRat = PsyWFnTdbRhPb(state, waterCoil.DesInletAirTemp, 0.5, state.dataEnvrn->StdBaroPress, RoutineName);
    2610           35 :                 waterCoil.InletAirMassFlowRate = state.dataSize->DataAirFlowUsedForSizing * state.dataEnvrn->StdRhoAir; // don't need this
    2611           35 :                 state.dataSize->DataDesOutletAirTemp = waterCoil.DesOutletAirTemp;                                      // for error messages
    2612           70 :                 state.dataSize->DataDesOutletAirHumRat =
    2613           35 :                     PsyWFnTdbRhPb(state, state.dataSize->DataDesOutletAirTemp, 0.5, state.dataEnvrn->StdBaroPress, RoutineName); // for error messages
    2614           35 :                 waterCoil.InletWaterMassFlowRate = rho * state.dataSize->DataWaterFlowUsedForSizing;
    2615           35 :                 waterCoil.MaxWaterMassFlowRate = rho * state.dataSize->DataWaterFlowUsedForSizing;
    2616           35 :                 waterCoil.InletWaterTemp = waterCoil.DesInletWaterTemp;
    2617         2414 :             } else if (waterCoil.DesiccantRegenerationCoil) {
    2618            0 :                 waterCoil.InletAirTemp = state.dataSize->DataDesInletAirTemp;
    2619            0 :                 HeatingCoilDesAirInletHumRatSizer sizerHeatingDesInletHumRat;
    2620            0 :                 ErrorsFound = false;
    2621            0 :                 sizerHeatingDesInletHumRat.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2622            0 :                 waterCoil.DesInletAirHumRat = sizerHeatingDesInletHumRat.size(state, DataSizing::AutoSize, ErrorsFound);
    2623            0 :                 waterCoil.InletAirHumRat = waterCoil.DesInletAirHumRat;
    2624              : 
    2625            0 :                 waterCoil.DesAirVolFlowRate = state.dataSize->DataAirFlowUsedForSizing;                                 // coil report
    2626            0 :                 waterCoil.InletAirMassFlowRate = state.dataSize->DataAirFlowUsedForSizing * state.dataEnvrn->StdRhoAir; // this is stiil volume flow!
    2627            0 :             } else {
    2628         2414 :                 HeatingWaterDesAirInletTempSizer sizerHWDesInletTemp;
    2629         2414 :                 sizerHWDesInletTemp.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2630         2414 :                 waterCoil.InletAirTemp = sizerHWDesInletTemp.size(state, DataSizing::AutoSize, ErrorsFound);
    2631              : 
    2632         2414 :                 HeatingWaterDesAirInletHumRatSizer sizerHWAirInletHumRat;
    2633         2414 :                 sizerHWAirInletHumRat.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2634         2414 :                 waterCoil.DesInletAirHumRat = sizerHWAirInletHumRat.size(state, DataSizing::AutoSize, ErrorsFound);
    2635         2414 :                 waterCoil.InletAirHumRat = waterCoil.DesInletAirHumRat;
    2636              : 
    2637         2414 :                 HeatingAirflowUASizer sizerHWAirFlowUA;
    2638         2414 :                 sizerHWAirFlowUA.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2639         2414 :                 waterCoil.DesAirMassFlowRate = sizerHWAirFlowUA.size(state, DataSizing::AutoSize, ErrorsFound);
    2640         2414 :                 waterCoil.InletAirMassFlowRate = waterCoil.DesAirMassFlowRate;
    2641         2414 :             }
    2642              : 
    2643              :             // zone and air loop coils use different design coil load calculations, air loop coils use air side capacity,
    2644              :             // zone coils use water side capacity
    2645         2449 :             state.dataSize->DataDesInletAirTemp = waterCoil.InletAirTemp;                                                  // used in error mesages
    2646         2449 :             state.dataSize->DataDesInletAirHumRat = waterCoil.InletAirHumRat;                                              // used in error mesages
    2647         2449 :             state.dataSize->DataFlowUsedForSizing = state.dataSize->DataAirFlowUsedForSizing * state.dataEnvrn->StdRhoAir; // used in error mesages
    2648         2449 :             waterCoil.MaxWaterVolFlowRate = state.dataSize->DataWaterFlowUsedForSizing;                                    // why is this here?
    2649         2449 :             if (!(waterCoil.CoilPerfInpMeth == state.dataWaterCoils->NomCap && NomCapUserInp)) {
    2650              :                 // get the design coil load used to size UA
    2651         2414 :                 HeatingWaterDesCoilLoadUsedForUASizer sizerHWDesCoilLoadForUA;
    2652         2414 :                 sizerHWDesCoilLoadForUA.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2653         2414 :                 state.dataSize->DataCapacityUsedForSizing = sizerHWDesCoilLoadForUA.size(state, DataSizing::AutoSize, ErrorsFound);
    2654              :                 // get the water volume flow rate used to size UA
    2655         2414 :                 HeatingWaterDesCoilWaterVolFlowUsedForUASizer sizerHWWaterVolFlowUA;
    2656         2414 :                 sizerHWWaterVolFlowUA.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2657         2414 :                 state.dataSize->DataWaterFlowUsedForSizing = sizerHWWaterVolFlowUA.size(state, DataSizing::AutoSize, ErrorsFound);
    2658         2414 :                 waterCoil.InletWaterTemp = state.dataSize->PlantSizData(PltSizHeatNum).ExitTemp;
    2659         2414 :                 waterCoil.InletWaterMassFlowRate = rho * state.dataSize->DataWaterFlowUsedForSizing;
    2660         2414 :                 waterCoil.MaxWaterMassFlowRate = rho * state.dataSize->DataWaterFlowUsedForSizing;
    2661         2414 :                 waterCoil.DesWaterHeatingCoilRate = state.dataSize->DataCapacityUsedForSizing;
    2662         2414 :             }
    2663              :             // calculate UA
    2664         2449 :             if (state.dataSize->CurSysNum > 0) {
    2665          416 :                 waterCoil.DesTotWaterCoilLoad = state.dataSize->DataCapacityUsedForSizing;
    2666              :             }
    2667         2449 :             FieldNum = 1;  // N1 , \field U-Factor Times Area Value
    2668         2449 :             bPRINT = true; // report to eio the UA value
    2669         2449 :             SizingString = state.dataWaterCoils->WaterCoilNumericFields(CoilNum).FieldNames(FieldNum) + " [W/K]";
    2670         2449 :             state.dataSize->DataCoilNum = CoilNum;
    2671         2449 :             state.dataSize->DataFanOp = HVAC::FanOp::Continuous;
    2672         2449 :             if (waterCoil.CoilPerfInpMeth == state.dataWaterCoils->NomCap && NomCapUserInp) {
    2673           35 :                 TempSize = DataSizing::AutoSize;
    2674              :             } else {
    2675         2414 :                 TempSize = waterCoil.UACoil;
    2676              :             }
    2677              : 
    2678         2449 :             state.dataSize->DataFlowUsedForSizing = waterCoil.InletAirMassFlowRate;
    2679         2449 :             DesCoilWaterInTempSaved = state.dataWaterCoils->WaterCoil(state.dataSize->DataCoilNum).InletWaterTemp;
    2680         2449 :             if (DesCoilWaterInTempSaved < HVAC::DesCoilHWInletTempMin) {
    2681              :                 // at low coil design water inlet temp, sizing has convergence issue hence slightly higher water inlet temperature
    2682              :                 // is estimated in "EstimateCoilInletWaterTemp" and used for UA autosizing only
    2683            0 :                 EstimateCoilInletWaterTemp(state,
    2684            0 :                                            state.dataSize->DataCoilNum,
    2685            0 :                                            state.dataSize->DataFanOp,
    2686              :                                            1.0,
    2687            0 :                                            state.dataSize->DataCapacityUsedForSizing,
    2688              :                                            DesCoilInletWaterTempUsed);
    2689            0 :                 state.dataWaterCoils->WaterCoil(state.dataSize->DataCoilNum).InletWaterTemp = DesCoilInletWaterTempUsed;
    2690              :             }
    2691              :             // must set DataCapacityUsedForSizing, DataWaterFlowUsedForSizing and DataFlowUsedForSizing to size UA. Any value of 0 will result
    2692              :             // in UA = 1.
    2693         2449 :             WaterHeatingCoilUASizer sizerHWCoilUA;
    2694         2449 :             sizerHWCoilUA.initializeWithinEP(state, CompType, CompName, bPRINT, RoutineName);
    2695         2449 :             waterCoil.UACoil = sizerHWCoilUA.size(state, TempSize, ErrorsFound);
    2696         2449 :             if (DesCoilWaterInTempSaved < HVAC::DesCoilHWInletTempMin) {
    2697            0 :                 ShowWarningError(state, format("Autosizing of heating coil UA for Coil:Heating:Water \"{}\"", CompName));
    2698            0 :                 ShowContinueError(state,
    2699            0 :                                   format(" Plant design loop exit temperature = {:.2T} C",
    2700            0 :                                          state.dataSize->PlantSizData(state.dataSize->DataPltSizHeatNum).ExitTemp));
    2701            0 :                 ShowContinueError(state, " Plant design loop exit temperature is low for design load and leaving air temperature anticipated.");
    2702            0 :                 ShowContinueError(state,
    2703            0 :                                   format(" Heating coil UA-value is sized using coil water inlet temperature = {:.2T} C", DesCoilInletWaterTempUsed));
    2704            0 :                 state.dataWaterCoils->WaterCoil(state.dataSize->DataCoilNum).InletWaterTemp =
    2705              :                     DesCoilWaterInTempSaved; // reset the Design Coil Inlet Water Temperature
    2706              :             }
    2707              :             // if coil UA did not size due to one of these variables being 0, must set UACoilVariable to avoid crash later on
    2708         4867 :             if (state.dataSize->DataCapacityUsedForSizing == 0.0 || state.dataSize->DataWaterFlowUsedForSizing == 0.0 ||
    2709         2418 :                 state.dataSize->DataFlowUsedForSizing == 0.0) {
    2710           31 :                 if (waterCoil.UACoilVariable == DataSizing::AutoSize) {
    2711           31 :                     waterCoil.UACoilVariable = waterCoil.UACoil;
    2712              :                 }
    2713              :             }
    2714              :             // WaterCoil(CoilNum).UACoilVariable = WaterCoil(CoilNum).UACoil;
    2715         2449 :             waterCoil.DesWaterHeatingCoilRate = state.dataSize->DataCapacityUsedForSizing;
    2716         2449 :             state.dataWaterCoils->WaterCoil(state.dataSize->DataCoilNum).InletWaterTemp =
    2717              :                 DesCoilWaterInTempSaved; // reset the Design Coil Inlet Water Temperature
    2718              : 
    2719         2449 :             state.dataSize->DataWaterLoopNum = 0; // reset all globals to 0 to ensure correct sizing for other child components
    2720         2449 :             state.dataSize->DataPltSizHeatNum = 0;
    2721         2449 :             state.dataSize->DataCoilNum = 0;
    2722         2449 :             state.dataSize->DataFanOp = HVAC::FanOp::Invalid;
    2723         2449 :             state.dataSize->DataCapacityUsedForSizing = 0.0;
    2724         2449 :             state.dataSize->DataWaterFlowUsedForSizing = 0.0;
    2725         2449 :             state.dataSize->DataDesInletAirTemp = 0.0;
    2726         2449 :             state.dataSize->DataDesInletAirHumRat = 0.0;
    2727         2449 :             state.dataSize->DataDesOutletAirTemp = 0.0;
    2728         2449 :             state.dataSize->DataDesOutletAirHumRat = 0.0;
    2729         2449 :             state.dataSize->DataAirFlowUsedForSizing = 0.0;
    2730         2449 :             state.dataSize->DataFlowUsedForSizing = 0.0;
    2731         2449 :             state.dataSize->DataDesicDehumNum = 0;
    2732         2449 :             state.dataSize->DataDesicRegCoil = false;
    2733         2449 :             state.dataSize->DataWaterCoilSizHeatDeltaT = 0.0;
    2734         2449 :             state.dataSize->DataNomCapInpMeth = false;
    2735              : 
    2736         2449 :         } else {
    2737              :             // if there is no heating Plant Sizing object and autosizng was requested, issue an error message
    2738          306 :             if (waterCoil.RequestingAutoSize) {
    2739            0 :                 ShowSevereError(state, "Autosizing of water coil requires a heating loop Sizing:Plant object");
    2740            0 :                 ShowContinueError(state, format("Occurs in water coil object= {}", waterCoil.Name));
    2741            0 :                 ErrorsFound = true;
    2742              :             }
    2743              :         }
    2744              :         //} // end of heating Plant Sizing existence IF - ELSE
    2745              :     } // end heating coil IF
    2746              : 
    2747              :     // save the design water volumetric flow rate for use by the water loop sizing algorithms
    2748         3351 :     if (waterCoil.MaxWaterVolFlowRate > 0.0) {
    2749         3318 :         PlantUtilities::RegisterPlantCompDesignFlow(state, waterCoil.WaterInletNodeNum, waterCoil.MaxWaterVolFlowRate);
    2750              :     }
    2751              : 
    2752         3351 :     if (ErrorsFound || state.dataSize->DataErrorsFound) {
    2753            0 :         ShowFatalError(state, "Preceding water coil sizing errors cause program termination");
    2754              :     }
    2755         3351 : }
    2756              : 
    2757              : // End Initialization Section of the Module
    2758              : //******************************************************************************
    2759              : 
    2760              : // Begin Algorithm Section of the Module
    2761              : //******************************************************************************
    2762              : 
    2763    122023874 : void CalcSimpleHeatingCoil(EnergyPlusData &state,
    2764              :                            int const CoilNum,          // index to heating coil
    2765              :                            HVAC::FanOp const fanOp,    // fan operating mode
    2766              :                            Real64 const PartLoadRatio, // part-load ratio of heating coil
    2767              :                            int const CalcMode          // 1 = design calc; 2 = simulation calculation
    2768              : )
    2769              : {
    2770              :     // SUBROUTINE INFORMATION:
    2771              :     //       AUTHOR         Rich Liesen
    2772              :     //       DATE WRITTEN
    2773              :     //       MODIFIED       Aug. 2007 - R. Raustad, added fan operating mode and part-load ratio to
    2774              :     //                                  calculate the outlet conditions when fan and coil cycle.
    2775              :     //                                  Air and water outlet temperature are full output with average
    2776              :     //                                  air and water mass flow rate when fan and coil cycle.
    2777              :     //       RE-ENGINEERED  na
    2778              : 
    2779              :     // PURPOSE OF THIS SUBROUTINE:
    2780              :     // Simulates a simple NTU effectiveness model heating coil
    2781              : 
    2782              :     // METHODOLOGY EMPLOYED:
    2783              :     // (1) outlet conditions are calculated from the effectiveness and the inlet conditions.
    2784              :     // (2) Effectiveness is calculated from the NTU formula for a cross flow heat exchanger
    2785              :     //     with both streams unmixed.
    2786              :     // Note: UA is input by user and is fixed.
    2787              : 
    2788              :     // REFERENCES:
    2789              :     // See for instance ASHRAE HVAC 2 Toolkit, page 4-4, formula (4-7)
    2790              : 
    2791              :     // Using/Aliasing
    2792              : 
    2793              :     // Locals
    2794              :     // SUBROUTINE ARGUMENT DEFINITIONS:
    2795              : 
    2796              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2797              :     static constexpr std::string_view RoutineName("CalcSimpleHeatingCoil");
    2798              : 
    2799              :     // INTERFACE BLOCK SPECIFICATIONS
    2800              :     // na
    2801              : 
    2802              :     // DERIVED TYPE DEFINITIONS
    2803              :     // na
    2804              : 
    2805              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2806              :     Real64 WaterMassFlowRate;
    2807              :     Real64 AirMassFlow; // [kg/sec]
    2808              :     Real64 TempAirIn;   // [C]
    2809              :     Real64 TempAirOut;  // [C]
    2810              :     Real64 Win;
    2811              :     Real64 TempWaterIn;
    2812              :     Real64 TempWaterOut;
    2813              :     Real64 UA;
    2814              :     Real64 CapacitanceAir;
    2815              :     Real64 CapacitanceWater;
    2816              :     Real64 CapacitanceMin;
    2817              :     Real64 CapacitanceMax;
    2818              :     Real64 HeatingCoilLoad;
    2819              :     Real64 NTU;
    2820              :     Real64 ETA;
    2821              :     Real64 A;
    2822              :     Real64 CapRatio;
    2823              :     Real64 E1;
    2824              :     Real64 E2;
    2825              :     Real64 Effec;
    2826              :     Real64 Cp;
    2827              : 
    2828    122023874 :     auto &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    2829    122023874 :     UA = waterCoil.UACoilVariable;
    2830    122023874 :     TempAirIn = waterCoil.InletAirTemp;
    2831    122023874 :     Win = waterCoil.InletAirHumRat;
    2832    122023874 :     TempWaterIn = waterCoil.InletWaterTemp;
    2833              : 
    2834              :     // adjust mass flow rates for cycling fan cycling coil operation
    2835    122023874 :     if (fanOp == HVAC::FanOp::Cycling) {
    2836      2223372 :         if (PartLoadRatio > 0.0) {
    2837      1637750 :             AirMassFlow = waterCoil.InletAirMassFlowRate / PartLoadRatio;
    2838      1637750 :             WaterMassFlowRate = min(waterCoil.InletWaterMassFlowRate / PartLoadRatio, waterCoil.MaxWaterMassFlowRate);
    2839              :         } else {
    2840       585622 :             AirMassFlow = 0.0;
    2841       585622 :             WaterMassFlowRate = 0.0;
    2842              :         }
    2843              :     } else {
    2844    119800502 :         AirMassFlow = waterCoil.InletAirMassFlowRate;
    2845    119800502 :         WaterMassFlowRate = waterCoil.InletWaterMassFlowRate;
    2846              :     }
    2847              : 
    2848    122023874 :     if (WaterMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) { // If the coil is operating
    2849     77360012 :         CapacitanceAir = PsyCpAirFnW(Win) * AirMassFlow;
    2850     77360012 :         Cp = state.dataPlnt->PlantLoop(waterCoil.WaterPlantLoc.loopNum).glycol->getSpecificHeat(state, TempWaterIn, RoutineName);
    2851     77360012 :         CapacitanceWater = Cp * WaterMassFlowRate;
    2852     77360012 :         CapacitanceMin = min(CapacitanceAir, CapacitanceWater);
    2853     77360012 :         CapacitanceMax = max(CapacitanceAir, CapacitanceWater);
    2854              :     } else {
    2855     44663862 :         CapacitanceAir = 0.0;
    2856     44663862 :         CapacitanceWater = 0.0;
    2857              :     }
    2858              : 
    2859              :     // If the coil is operating there should be some heating capacitance
    2860              :     //  across the coil, so do the simulation. If not set outlet to inlet and no load.
    2861              :     //  Also the coil has to be scheduled to be available
    2862    199375588 :     if (((CapacitanceAir > 0.0) && (CapacitanceWater > 0.0)) &&
    2863     77351714 :         (CalcMode == state.dataWaterCoils->DesignCalc || state.dataWaterCoils->MySizeFlag(CoilNum) ||
    2864     77302276 :          state.dataWaterCoils->MyUAAndFlowCalcFlag(CoilNum) || waterCoil.availSched->getCurrentVal() > 0.0)) {
    2865              : 
    2866     77285158 :         if (UA <= 0.0) {
    2867            0 :             ShowFatalError(state, format("UA is zero for COIL:Heating:Water {}", waterCoil.Name));
    2868              :         }
    2869     77285158 :         NTU = UA / CapacitanceMin;
    2870     77285158 :         ETA = std::pow(NTU, 0.22);
    2871     77285158 :         CapRatio = CapacitanceMin / CapacitanceMax;
    2872     77285158 :         A = CapRatio * NTU / ETA;
    2873              : 
    2874     77285158 :         if (A > 20.0) {
    2875            0 :             A = ETA * 1.0 / CapRatio;
    2876              :         } else {
    2877     77285158 :             E1 = std::exp(-A);
    2878     77285158 :             A = ETA * (1.0 - E1) / CapRatio;
    2879              :         }
    2880              : 
    2881     77285158 :         if (A > 20.0) {
    2882       216670 :             Effec = 1.0;
    2883              :         } else {
    2884     77068488 :             E2 = std::exp(-A);
    2885     77068488 :             Effec = 1.0 - E2;
    2886              :         }
    2887              : 
    2888     77285158 :         TempAirOut = TempAirIn + Effec * CapacitanceMin * (TempWaterIn - TempAirIn) / CapacitanceAir;
    2889     77285158 :         TempWaterOut = TempWaterIn - CapacitanceAir * (TempAirOut - TempAirIn) / CapacitanceWater;
    2890     77285158 :         HeatingCoilLoad = CapacitanceWater * (TempWaterIn - TempWaterOut);
    2891              :         // The HeatingCoilLoad is the change in the enthalpy of the water
    2892     77285158 :         waterCoil.OutletWaterEnthalpy = waterCoil.InletWaterEnthalpy - HeatingCoilLoad / waterCoil.InletWaterMassFlowRate;
    2893     77285158 :         waterCoil.OutletWaterMassFlowRate = waterCoil.InletWaterMassFlowRate;
    2894              : 
    2895              :     } else { // If not running Conditions do not change across coil from inlet to outlet
    2896              : 
    2897     44738716 :         TempAirOut = TempAirIn;
    2898     44738716 :         TempWaterOut = TempWaterIn;
    2899     44738716 :         HeatingCoilLoad = 0.0;
    2900     44738716 :         waterCoil.OutletWaterEnthalpy = waterCoil.InletWaterEnthalpy;
    2901     44738716 :         waterCoil.OutletWaterMassFlowRate = 0.0;
    2902              :     }
    2903              : 
    2904    122023874 :     if (fanOp == HVAC::FanOp::Cycling) {
    2905      2223372 :         HeatingCoilLoad *= PartLoadRatio;
    2906              :     }
    2907              : 
    2908              :     // Set the outlet conditions
    2909    122023874 :     waterCoil.TotWaterHeatingCoilRate = HeatingCoilLoad;
    2910    122023874 :     waterCoil.OutletAirTemp = TempAirOut;
    2911    122023874 :     waterCoil.OutletWaterTemp = TempWaterOut;
    2912              : 
    2913              :     // This WaterCoil does not change the moisture or Mass Flow across the component
    2914    122023874 :     waterCoil.OutletAirHumRat = waterCoil.InletAirHumRat;
    2915    122023874 :     waterCoil.OutletAirMassFlowRate = waterCoil.InletAirMassFlowRate;
    2916              :     // Set the outlet enthalpys for air and water
    2917    122023874 :     waterCoil.OutletAirEnthalpy = PsyHFnTdbW(waterCoil.OutletAirTemp, waterCoil.OutletAirHumRat);
    2918    122023874 : }
    2919              : 
    2920      4921265 : void CalcDetailFlatFinCoolingCoil(EnergyPlusData &state,
    2921              :                                   int const CoilNum,
    2922              :                                   int const CalcMode,
    2923              :                                   HVAC::FanOp const fanOp,   // fan operating mode
    2924              :                                   Real64 const PartLoadRatio // part-load ratio of heating coil
    2925              : )
    2926              : {
    2927              : 
    2928              :     // SUBROUTINE INFORMATION:
    2929              :     //       AUTHOR(S)      Russell Taylor / Richard Liesen
    2930              :     //       DATE WRITTEN   Mar 1997
    2931              :     //       MODIFIED       Feb 2010, B. Nigusse, FSEC, corrected units inconsistency for tube and fins
    2932              :     //                      materials thermal conductivties. Now input values in the idf are in {W/(m.K)}
    2933              :     //       RE-ENGINEERED  Sept 1998
    2934              : 
    2935              :     // PURPOSE OF THIS SUBROUTINE:
    2936              :     // This subroutine simulates a chilled water cooling coil.  Provided with
    2937              :     // the coil geometry and the flow (i.e. air and water) inlet conditions,
    2938              :     // it will calculate the flow outlet conditions and the total and latent
    2939              :     // heat extraction rates from the air.  The coil model has some limitations
    2940              :     // as noted in the code.
    2941              : 
    2942              :     // METHODOLOGY EMPLOYED:
    2943              :     // successive substitution, solve coil as if all wet, then
    2944              :     // again if partly or entirely dry
    2945              : 
    2946              :     // REFERENCES:
    2947              :     // First found in Type 12 from MODSIM, but now
    2948              :     // programmed directly from Elmahdy, A.H. and Mitalas, G.P.  "A
    2949              :     // Simple Model for Cooling and Dehumidifying Coils for Use in
    2950              :     // Calculating Energy Requirements for Buildings"  _ASHRAE
    2951              :     // Transactions_ Vol. 83, Part 2, pp. 103-117 (1977).
    2952              : 
    2953              :     // OTHER NOTES:
    2954              :     // Routine was originally adapted for use in IBLAST by R.D. Taylor in l993.
    2955              :     // Subsequently rewritten and improved by J.C. Vanderzee in 1994
    2956              :     // Revised and further enhanced by R.D. Taylor in Jan 1996
    2957              :     // Re-engineered for EnergyPlus by Richard Liesen PhD in 1998
    2958              : 
    2959              :     // Using/Aliasing
    2960              : 
    2961              :     // Locals
    2962              :     // SUBROUTINE ARGUMENT DEFINITIONS:
    2963              : 
    2964              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2965              :     static Real64 const exp_47(std::exp(-0.41718));
    2966              :     static Real64 const exp_35(std::exp(-0.3574));
    2967              :     static constexpr std::string_view RoutineName("CalcDetailFlatFinCoolingCoil");
    2968              : 
    2969      4921265 :     constexpr Real64 AirViscosity(1.846e-5); // Dynamic Viscosity of Air in kg/(m.s)
    2970      4921265 :     constexpr Real64 ConvK(1.0e-3);          // Unit conversion factor
    2971      4921265 :     constexpr Real64 unity(1.0);
    2972      4921265 :     constexpr Real64 zero(0.0);
    2973      4921265 :     constexpr Real64 TubeFoulFactor(5.0e-2); // Inside tube fouling factor for water, in m2K/kW
    2974              :     // Changed from m2K/W to m2K/kW for consistency with the
    2975              :     // other parameters in "TubeFoulThermResis" calculation
    2976              : 
    2977              :     // INTERFACE BLOCK SPECIFICATIONS
    2978              :     // na
    2979              : 
    2980              :     // DERIVED TYPE DEFINITIONS
    2981              :     // na
    2982              : 
    2983              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2984              :     //    INTEGER :: CoolCoilErrs = 0
    2985              : 
    2986              :     Real64 AirEnthAtRsdInletWaterTemp;
    2987              :     Real64 AirExitEnthlAtCoilSurfTemp;
    2988              :     Real64 AirExitCoilSurfTemp;
    2989              :     Real64 AirReynoldsNo;
    2990              :     Real64 AirEnthAtWetDryIntrfcSurfTemp;
    2991              :     Real64 AirSideDrySurfFilmCoef;
    2992              :     Real64 AirSideWetSurfFilmCoef;
    2993              :     Real64 AirWetDryInterfcTemp;
    2994              :     Real64 CoilToAirThermResistDrySurf;
    2995              :     Real64 CoilToAirThermResistWetSurf;
    2996              :     Real64 DryAirSpecHeat;
    2997              :     Real64 DryCoilCoeff1;
    2998              :     Real64 DryCoilCoeff;
    2999              :     Real64 DryCoilEfficiency;
    3000              :     Real64 DryFinEfficncy;
    3001              :     Real64 DryCoilInThermResist;
    3002              :     Real64 DrySideEffectiveWaterTemp;
    3003              :     Real64 EnterAirDewPoint;
    3004              :     Real64 EnterAirHumRatDiff;
    3005              :     Real64 WetDryInterSurfTempErrorLast;
    3006              :     Real64 WetDryInterSurfTempError;
    3007              :     Real64 expon;
    3008              :     Real64 FilmCoefEqnFactor;
    3009              :     Real64 FilmCoefReynldsCorrelatnFact;
    3010              :     Real64 FinToTotSurfAreaRatio;
    3011              :     Real64 InCoilSurfTemp;
    3012              :     Real64 InsdToOutsdThermResistRatio;
    3013              :     Real64 InSurfTempSatAirEnthl;
    3014              :     Real64 K1;
    3015              :     Real64 MeanWaterTemp;
    3016              :     Real64 MoistAirSpecificHeat;
    3017              :     Real64 OutCoilSurfTemp;
    3018              :     Real64 OutSurfTempSatAirEnthl;
    3019              :     Real64 RaisedInletWaterTemp;
    3020              :     Real64 RsdInletWaterTempSatAirHumRat;
    3021              :     Real64 ScaledAirMassFlowRate;
    3022              :     Real64 ScaledCoilAirThermResistWetSurf;
    3023              :     Real64 ScaledWaterSpecHeat;
    3024              :     Real64 ScaledWaterToTubeThermResist;
    3025              :     Real64 SensToTotEnthDiffRatio;
    3026              :     Real64 SurfAreaWet;
    3027              :     Real64 TubeFoulThermResist;
    3028              :     Real64 TubeWaterVel;
    3029              :     Real64 UACoilAllWet;
    3030              :     Real64 UACoilPartWet;
    3031              :     Real64 UADryCoil;
    3032              :     Real64 WaterToTubeThermResist;
    3033              :     Real64 WetAreaChange;
    3034              :     Real64 WetAreaLast;
    3035              :     Real64 WetCoilCoeff;
    3036              :     Real64 WetCoilFinEfficncy;
    3037              :     Real64 WetDryInterfcAirEnthl;
    3038              :     Real64 WetDryInterfcSurfTemp;
    3039              :     Real64 WetDryInterfcWaterTemp;
    3040              :     Real64 WetFinEfficncy;
    3041              :     Real64 WetSideEffctvWaterTemp;
    3042              :     Real64 y;
    3043              :     Real64 TempAirIn;
    3044              :     Real64 TempAirOut;
    3045              :     Real64 InletAirHumRat;
    3046              :     Real64 OutletAirHumRat;
    3047              :     Real64 InletAirEnthalpy;
    3048              :     Real64 OutletAirEnthalpy;
    3049              :     Real64 WaterMassFlowRate;
    3050              :     Real64 AirMassFlow;
    3051              :     Real64 TempWaterIn;
    3052              :     Real64 TempWaterOut;
    3053              :     Real64 TotWaterCoilLoad;
    3054              :     Real64 SenWaterCoilLoad;
    3055              :     Real64 AirDensity;
    3056              :     Real64 AirVelocity;
    3057              :     Real64 denom;
    3058              :     Real64 rho;
    3059              :     Real64 Cp;
    3060              : 
    3061              :     // Set derived type variables to shorter local variables
    3062      4921265 :     auto &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    3063      4921265 :     TempAirIn = waterCoil.InletAirTemp;
    3064      4921265 :     InletAirHumRat = waterCoil.InletAirHumRat;
    3065      4921265 :     TempWaterIn = waterCoil.InletWaterTemp;
    3066              : 
    3067              :     //  adjust mass flow rates for cycling fan cycling coil operation
    3068      4921265 :     if (fanOp == HVAC::FanOp::Cycling) {
    3069            0 :         if (PartLoadRatio > 0.0) {
    3070            0 :             AirMassFlow = waterCoil.InletAirMassFlowRate / PartLoadRatio;
    3071            0 :             WaterMassFlowRate = min(waterCoil.InletWaterMassFlowRate / PartLoadRatio, waterCoil.MaxWaterMassFlowRate);
    3072              :         } else {
    3073            0 :             AirMassFlow = 0.0;
    3074            0 :             WaterMassFlowRate = 0.0;
    3075              :         }
    3076              :     } else {
    3077      4921265 :         AirMassFlow = waterCoil.InletAirMassFlowRate;
    3078      4921265 :         WaterMassFlowRate = waterCoil.InletWaterMassFlowRate;
    3079              :     }
    3080              : 
    3081      4921265 :     if (WaterMassFlowRate < waterCoil.MaxWaterMassFlowRate * WaterCoils::MinWaterMassFlowFrac) {
    3082      2605393 :         WaterMassFlowRate = 0.0;
    3083              :     }
    3084      4921265 :     if (TempAirIn <= TempWaterIn) {
    3085       532192 :         WaterMassFlowRate = 0.0;
    3086              :     }
    3087      4921265 :     WetDryInterfcAirEnthl = 0.0;
    3088      4921265 :     OutletAirEnthalpy = 0.0;
    3089      4921265 :     InletAirEnthalpy = 0.0;
    3090              : 
    3091              :     // Warning and error messages for large flow rates for the given user input geometry
    3092      4921265 :     AirDensity = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, TempAirIn, InletAirHumRat, RoutineName);
    3093      4921265 :     if (AirMassFlow > (5.0 * waterCoil.MinAirFlowArea / AirDensity) && state.dataWaterCoils->CoilWarningOnceFlag(CoilNum)) {
    3094            2 :         ShowWarningError(state, format("Coil:Cooling:Water:DetailedGeometry in Coil ={}", waterCoil.Name));
    3095            4 :         ShowContinueError(state, "Air Flow Rate Velocity has greatly exceeded upper design guidelines of ~2.5 m/s");
    3096            2 :         ShowContinueError(state, format("Air Mass Flow Rate[kg/s]={:.6T}", AirMassFlow));
    3097              :         // [m/s] = [kg/s] / ([m2] * [kg/m3])
    3098            2 :         AirVelocity = AirMassFlow / (waterCoil.MinAirFlowArea * AirDensity);
    3099            2 :         ShowContinueError(state, format("Air Face Velocity[m/s]={:.6T}", AirVelocity));
    3100            2 :         ShowContinueError(state, format("Approximate Mass Flow Rate limit for Face Area[kg/s]={:.6T}", 2.5 * waterCoil.MinAirFlowArea * AirDensity));
    3101            4 :         ShowContinueError(state, "Coil:Cooling:Water:DetailedGeometry could be resized/autosized to handle capacity");
    3102            2 :         state.dataWaterCoils->CoilWarningOnceFlag(CoilNum) = false;
    3103      4921263 :     } else if (AirMassFlow > (44.7 * waterCoil.MinAirFlowArea * AirDensity)) {
    3104            0 :         ShowSevereError(state, format("Coil:Cooling:Water:DetailedGeometry in Coil ={}", waterCoil.Name));
    3105            0 :         ShowContinueError(state, "Air Flow Rate Velocity is > 100MPH (44.7m/s) and simulation cannot continue");
    3106            0 :         ShowContinueError(state, format("Air Mass Flow Rate[kg/s]={:.6T}", AirMassFlow));
    3107            0 :         AirVelocity = AirMassFlow / (waterCoil.MinAirFlowArea * AirDensity);
    3108            0 :         ShowContinueError(state, format("Air Face Velocity[m/s]={:.6T}", AirVelocity));
    3109            0 :         ShowContinueError(state, format("Approximate Mass Flow Rate limit for Face Area[kg/s]={:.6T}", 44.7 * waterCoil.MinAirFlowArea * AirDensity));
    3110            0 :         ShowFatalError(state, "Coil:Cooling:Water:DetailedGeometry needs to be resized/autosized to handle capacity");
    3111              :     }
    3112              : 
    3113              :     // If Coil is Scheduled ON then do the simulation
    3114      7630858 :     if (((waterCoil.availSched->getCurrentVal() > 0.0) && (WaterMassFlowRate > 0.0) && (AirMassFlow >= WaterCoils::MinAirMassFlow)) ||
    3115      2709593 :         (CalcMode == state.dataWaterCoils->DesignCalc)) {
    3116              :         //        transfer inputs to simulation variables and calculate
    3117              :         //        known thermodynamic functions
    3118              :         // All coil calcs are done in KJoules.  Convert to KJ here and then convert
    3119              :         //  back to Joules at the end of the Subroutine.
    3120      2212179 :         DryAirSpecHeat = PsyCpAirFnW(zero) * ConvK;
    3121      2212179 :         MoistAirSpecificHeat = PsyCpAirFnW(InletAirHumRat) * ConvK;
    3122      2212179 :         InletAirEnthalpy = waterCoil.InletAirEnthalpy * ConvK;
    3123              : 
    3124      2212179 :         EnterAirDewPoint = PsyTdpFnWPb(state, InletAirHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
    3125              :         //       Ratio of secondary (fin) to total (secondary plus primary) surface areas
    3126      2212179 :         FinToTotSurfAreaRatio = waterCoil.FinSurfArea / waterCoil.TotCoilOutsideSurfArea;
    3127              :         //      known water and air flow parameters:
    3128      2212179 :         rho = state.dataPlnt->PlantLoop(waterCoil.WaterPlantLoc.loopNum).glycol->getDensity(state, TempWaterIn, RoutineName);
    3129              :         //      water flow velocity - assuming number of water circuits = NumOfTubesPerRow
    3130      2212179 :         TubeWaterVel =
    3131      2212179 :             WaterMassFlowRate * 4.0 / (waterCoil.NumOfTubesPerRow * rho * Constant::Pi * waterCoil.TubeInsideDiam * waterCoil.TubeInsideDiam);
    3132              :         //      air mass flow rate per unit area
    3133      2212179 :         ScaledAirMassFlowRate = (1.0 + InletAirHumRat) * AirMassFlow / waterCoil.MinAirFlowArea;
    3134              :         //      air flow Reynold's Number
    3135      2212179 :         AirReynoldsNo = waterCoil.CoilEffectiveInsideDiam * ScaledAirMassFlowRate / AirViscosity;
    3136              :         //       heat transfer coefficients and resistance components:
    3137              :         //              inside (water)
    3138      2212179 :         WaterToTubeThermResist = std::pow(waterCoil.TubeInsideDiam, 0.2) / (waterCoil.TotTubeInsideArea * 1.429 * std::pow(TubeWaterVel, 0.8));
    3139              :         //              metal and fouling
    3140      2212179 :         TubeFoulThermResist =
    3141      2212179 :             (0.5 * (waterCoil.TubeOutsideDiam - waterCoil.TubeInsideDiam) / (ConvK * waterCoil.TubeThermConductivity) + TubeFoulFactor) /
    3142      2212179 :             waterCoil.TotTubeInsideArea;
    3143              :         //              outside (wet and dry coil)
    3144      2212179 :         FilmCoefEqnFactor = waterCoil.GeometryCoef1 * std::pow(AirReynoldsNo, waterCoil.GeometryCoef2);
    3145              :         //       (1.23 is 1/Prandt(air)**(2/3))
    3146      2212179 :         AirSideDrySurfFilmCoef = 1.23 * FilmCoefEqnFactor * MoistAirSpecificHeat * ScaledAirMassFlowRate;
    3147      2212179 :         FilmCoefReynldsCorrelatnFact = 1.425 + AirReynoldsNo * (-0.51e-3 + AirReynoldsNo * 0.263e-6);
    3148              :         //       NOTE: the equation for FilmCoefReynldsCorrelatnFact generates valid results over
    3149              :         //             a limited range of Air Reynolds Numbers as indicated by
    3150              :         //             deleted code below.  Reynolds Numbers outside this range
    3151              :         //             may result in inaccurate results or failure of the coil
    3152              :         //             simulation to obtain a solution
    3153              :         //             Deleted code by J.C. Vanderzee
    3154              : 
    3155      2212179 :         AirSideWetSurfFilmCoef = FilmCoefReynldsCorrelatnFact * AirSideDrySurfFilmCoef;
    3156              :         //--                     need wet fin efficiency for outside
    3157      2212179 :         RaisedInletWaterTemp = TempWaterIn + 0.5;
    3158              : 
    3159              :         // By this statement the Inlet Air enthalpy will never be equal to AirEnthAtRsdInletWaterTemp
    3160      2212179 :         if ((RaisedInletWaterTemp - TempAirIn) < 0.000001) {
    3161      2212178 :             RaisedInletWaterTemp = TempWaterIn + 0.3;
    3162              :         }
    3163      2212179 :         if (TempAirIn < RaisedInletWaterTemp) {
    3164            1 :             RaisedInletWaterTemp = TempAirIn - 0.3;
    3165              :         }
    3166              : 
    3167      2212179 :         RsdInletWaterTempSatAirHumRat = PsyWFnTdbRhPb(state, RaisedInletWaterTemp, unity, state.dataEnvrn->OutBaroPress, RoutineName);
    3168      2212179 :         AirEnthAtRsdInletWaterTemp = PsyHFnTdbW(RaisedInletWaterTemp, RsdInletWaterTempSatAirHumRat) * ConvK;
    3169              : 
    3170      2212179 :         SensToTotEnthDiffRatio = DryAirSpecHeat * (TempAirIn - RaisedInletWaterTemp) / (InletAirEnthalpy - AirEnthAtRsdInletWaterTemp);
    3171              : 
    3172      2212179 :         EnterAirHumRatDiff = InletAirHumRat - RsdInletWaterTempSatAirHumRat;
    3173      2212179 :         DryFinEfficncy = 0.5 * (waterCoil.EffectiveFinDiam - waterCoil.TubeOutsideDiam) *
    3174      2212179 :                          std::sqrt(2.0 * AirSideWetSurfFilmCoef / (ConvK * waterCoil.FinThermConductivity * waterCoil.FinThickness));
    3175      2212179 :         if (EnterAirHumRatDiff < 0) {
    3176              :             //       note that this condition indicates dry coil
    3177        73375 :             EnterAirHumRatDiff = -EnterAirHumRatDiff;
    3178        73375 :             SensToTotEnthDiffRatio = std::abs(SensToTotEnthDiffRatio);
    3179              :         }
    3180              : 
    3181      2212179 :         if (EnterAirHumRatDiff > 1.0) {
    3182            0 :             EnterAirHumRatDiff = 1.0;
    3183      2212179 :         } else if (EnterAirHumRatDiff < 0.00001) {
    3184           57 :             EnterAirHumRatDiff = 0.00001;
    3185              :         }
    3186              : 
    3187      2212179 :         if (DryFinEfficncy > 1.0) {
    3188            0 :             DryFinEfficncy = 1.0;
    3189      2212179 :         } else if (DryFinEfficncy < 0.00001) {
    3190            0 :             DryFinEfficncy = 0.00001;
    3191              :         }
    3192              : 
    3193      2212179 :         if (TempAirIn > 48.0 / 1.8) {
    3194       274279 :             WetFinEfficncy =
    3195       274279 :                 exp_47 * std::pow(SensToTotEnthDiffRatio, 0.09471) * std::pow(EnterAirHumRatDiff, 0.0108) * std::pow(DryFinEfficncy, -0.50303);
    3196              :         } else {
    3197      1937900 :             WetFinEfficncy =
    3198      1937900 :                 exp_35 * std::pow(SensToTotEnthDiffRatio, 0.16081) * std::pow(EnterAirHumRatDiff, 0.01995) * std::pow(DryFinEfficncy, -0.52951);
    3199              :         }
    3200              : 
    3201      2212179 :         if (WetFinEfficncy > 1.0) {
    3202      2212059 :             WetFinEfficncy = 0.99;
    3203              :         }
    3204      2212179 :         if (WetFinEfficncy < 0.0) {
    3205            0 :             WetFinEfficncy = 0.001;
    3206              :         }
    3207              :         //       wet coil fin efficiency
    3208              : 
    3209      2212179 :         WetCoilFinEfficncy = 1.0 + FinToTotSurfAreaRatio * (WetFinEfficncy - 1.0);
    3210              :         //       wet coil outside thermal resistance = [1/UA] (wet coil)
    3211      2212179 :         CoilToAirThermResistWetSurf = MoistAirSpecificHeat / (waterCoil.TotCoilOutsideSurfArea * AirSideWetSurfFilmCoef * WetCoilFinEfficncy);
    3212              :         //--                     and dry fin efficiency
    3213      2212179 :         DryFinEfficncy = 0.5 * (waterCoil.EffectiveFinDiam - waterCoil.TubeOutsideDiam) *
    3214      2212179 :                          std::sqrt(2.0 * AirSideDrySurfFilmCoef / (ConvK * waterCoil.FinThermConductivity * waterCoil.FinThickness));
    3215              :         //      NOTE: The same caveats on the validity of the FilmCoefReynldsCorrelatnFact equation
    3216              :         //            hold for the DryFinEfficncy equation.  Values of DryFinEfficncy outside the
    3217              :         //            specified range of validity are not guaranteed to
    3218              :         //            produce results
    3219              :         //             Deleted code by J.C. Vanderzee
    3220              :         //       dry coil fin efficiency
    3221      2212179 :         DryCoilEfficiency = 0.0;
    3222              :         // Tuned Replaced by below to eliminate pow calls
    3223              :         //            for ( CoefPointer = 1; CoefPointer <= 5; ++CoefPointer ) {
    3224              :         //                DryCoilEfficiency += WaterCoil( CoilNum ).DryFinEfficncyCoef( CoefPointer ) * std::pow(
    3225              :         // DryFinEfficncy,
    3226              :         // CoefPointer
    3227              :         //-
    3228              :         // 1
    3229              :         //);             } // CoefPointer
    3230      2212179 :         auto const &dry_fin_eff_coef = waterCoil.DryFinEfficncyCoef;
    3231      2212179 :         Real64 DryFinEfficncy_pow = 1.0;
    3232     13273074 :         for (int CoefPointer = 1; CoefPointer <= 5; ++CoefPointer) {
    3233     11060895 :             DryCoilEfficiency += dry_fin_eff_coef(CoefPointer) * DryFinEfficncy_pow;
    3234     11060895 :             DryFinEfficncy_pow *= DryFinEfficncy;
    3235              :         } // CoefPointer
    3236      2212179 :         DryCoilEfficiency = 1.0 + FinToTotSurfAreaRatio * (DryCoilEfficiency - 1.0);
    3237              :         //       dry coil outside thermal resistance = [1/UA] (dry coil)
    3238      2212179 :         CoilToAirThermResistDrySurf = 1.0 / (waterCoil.TotCoilOutsideSurfArea * AirSideDrySurfFilmCoef * DryCoilEfficiency);
    3239              :         //       definitions made to simplify some of the expressions used below
    3240      2212179 :         Cp = state.dataPlnt->PlantLoop(waterCoil.WaterPlantLoc.loopNum).glycol->getSpecificHeat(state, TempWaterIn, RoutineName);
    3241      2212179 :         ScaledWaterSpecHeat = WaterMassFlowRate * Cp * ConvK / AirMassFlow;
    3242      2212179 :         DryCoilCoeff1 = 1.0 / (AirMassFlow * MoistAirSpecificHeat) - 1.0 / (WaterMassFlowRate * Cp * ConvK);
    3243              :         //       perform initialisations for all wet solution
    3244      2212179 :         WetSideEffctvWaterTemp = waterCoil.MeanWaterTempSaved + (TempWaterIn - waterCoil.InWaterTempSaved);
    3245      2212179 :         int WaterTempConvgLoop = 0;
    3246      2212179 :         bool WaterTempConvg = false;
    3247              :         //       Loop to solve coil as if all wet, converges on MeanWaterTemp eq WetSideEffctvWaterTemp
    3248              :         //       if conv=.TRUE. at any time program exits loop and proceeds
    3249              :         //       to part wet / part dry solution
    3250      5556579 :         while (WaterTempConvgLoop < 8 && !WaterTempConvg) {
    3251      3344400 :             ++WaterTempConvgLoop;
    3252      3344400 :             ScaledWaterToTubeThermResist = WaterToTubeThermResist / (1.0 + 0.0146 * WetSideEffctvWaterTemp);
    3253      3344400 :             ScaledCoilAirThermResistWetSurf = CoilToAirThermResistWetSurf / waterCoil.SatEnthlCurveSlope;
    3254      3344400 :             UACoilAllWet =
    3255      3344400 :                 1.0 / (waterCoil.SatEnthlCurveSlope * (TubeFoulThermResist + ScaledWaterToTubeThermResist + ScaledCoilAirThermResistWetSurf));
    3256              :             //       prevents floating point error when taking exponential
    3257              :             //       of a very large number
    3258      3344400 :             expon = UACoilAllWet * (1.0 / AirMassFlow - waterCoil.SatEnthlCurveSlope / (WaterMassFlowRate * Cp * ConvK));
    3259      3344400 :             if (expon < 20.0) { // CR7189 changed from ABS(expon) < 20
    3260              :                 //       negative expon can happen, but lead to tiny WetCoilCoef that aren't a problem
    3261      3344296 :                 WetCoilCoeff = std::exp(expon);
    3262              :                 // following appears similar to eq. 320 in Eng Ref but neglects K1 term
    3263      3344296 :                 TempWaterOut = ((1.0 - WetCoilCoeff) * (InletAirEnthalpy - waterCoil.SatEnthlCurveConstCoef) +
    3264      3344296 :                                 WetCoilCoeff * TempWaterIn * (waterCoil.SatEnthlCurveSlope - ScaledWaterSpecHeat)) /
    3265      3344296 :                                (waterCoil.SatEnthlCurveSlope - WetCoilCoeff * ScaledWaterSpecHeat);
    3266              :             } else {
    3267              :                 // following appears to be same as above with equation simplified to use only significant terms when WetCoilCoeff very large
    3268          104 :                 TempWaterOut =
    3269          104 :                     ((InletAirEnthalpy - waterCoil.SatEnthlCurveConstCoef) - TempWaterIn * (waterCoil.SatEnthlCurveSlope - ScaledWaterSpecHeat)) /
    3270              :                     ScaledWaterSpecHeat;
    3271              :             }
    3272              :             //      above is inverted form of WaterMassFlowRate*cpw*(TempWaterOut-TempWaterIn) = UA(LMHD)
    3273              :             //      note simplification that hsat = WaterCoil(CoilNum)%SatEnthlCurveConstCoef +  &
    3274              :             //                                      WaterCoil(CoilNum)%SatEnthlCurveSlope*WetSideEffctvWaterTemp
    3275      3344400 :             MeanWaterTemp = 0.5 * (TempWaterIn + TempWaterOut);
    3276      3344400 :             OutletAirEnthalpy = InletAirEnthalpy - (TempWaterOut - TempWaterIn) * ScaledWaterSpecHeat;
    3277              : 
    3278      3344400 :             InsdToOutsdThermResistRatio = (TubeFoulThermResist + ScaledWaterToTubeThermResist) / ScaledCoilAirThermResistWetSurf;
    3279      3344400 :             InCoilSurfTemp =
    3280      3344400 :                 UACoilAllWet * ScaledCoilAirThermResistWetSurf *
    3281      3344400 :                 (waterCoil.SatEnthlCurveSlope * TempWaterIn + (OutletAirEnthalpy - waterCoil.SatEnthlCurveConstCoef) * InsdToOutsdThermResistRatio);
    3282      3344400 :             OutCoilSurfTemp =
    3283      3344400 :                 UACoilAllWet * ScaledCoilAirThermResistWetSurf *
    3284      3344400 :                 (waterCoil.SatEnthlCurveSlope * TempWaterOut + (InletAirEnthalpy - waterCoil.SatEnthlCurveConstCoef) * InsdToOutsdThermResistRatio);
    3285              : 
    3286      3344400 :             if (std::abs(MeanWaterTemp - WetSideEffctvWaterTemp) > 0.01) {
    3287      1132221 :                 WetSideEffctvWaterTemp = MeanWaterTemp;
    3288      1132221 :                 InSurfTempSatAirEnthl = PsyHFnTdbRhPb(state, InCoilSurfTemp, unity, state.dataEnvrn->OutBaroPress, RoutineName) * ConvK;
    3289      1132221 :                 OutSurfTempSatAirEnthl = PsyHFnTdbRhPb(state, OutCoilSurfTemp, unity, state.dataEnvrn->OutBaroPress, RoutineName) * ConvK;
    3290              : 
    3291      1132221 :                 waterCoil.SatEnthlCurveSlope = (OutSurfTempSatAirEnthl - InSurfTempSatAirEnthl) / (OutCoilSurfTemp - InCoilSurfTemp);
    3292      1132221 :                 waterCoil.SatEnthlCurveConstCoef = InSurfTempSatAirEnthl - waterCoil.SatEnthlCurveSlope * InCoilSurfTemp;
    3293              :             } else {
    3294      2212179 :                 WaterTempConvg = true;
    3295              :             }
    3296              :         } // End of iteration loop to get MeanWaterTemp=WetSideEffctvWaterTemp
    3297              :         //      if 8 CoolCoilErrs are reached without convergence and the
    3298              :         //      predicted coil surface temperature at the outlet is less than
    3299              :         //      the dew point coil is apparently all wet but a solution
    3300              :         //      cannot be obtained
    3301      2212179 :         if (!WaterTempConvg && !state.dataGlobal->WarmupFlag && (OutCoilSurfTemp < EnterAirDewPoint)) {
    3302            0 :             ShowRecurringWarningErrorAtEnd(state,
    3303            0 :                                            waterCoil.Name + " not converged (8 iterations) due to \"Wet Convergence\" conditions.",
    3304            0 :                                            state.dataWaterCoils->WaterTempCoolCoilErrs(CoilNum),
    3305            0 :                                            std::abs(MeanWaterTemp - WetSideEffctvWaterTemp),
    3306            0 :                                            std::abs(MeanWaterTemp - WetSideEffctvWaterTemp));
    3307              :             //       CoolCoilErrs = CoolCoilErrs + 1
    3308              :             //       IF (CoolCoilErrs .LE. MaxCoolCoilErrs) THEN
    3309              :             //          CALL ShowWarningError(state, 'tp12c0:  not converged in 8 CoolCoilErrs')
    3310              :             //       END IF
    3311              :         }
    3312      2212179 :         waterCoil.MeanWaterTempSaved = MeanWaterTemp;
    3313              :         //      now simulate wet dry coil - test outlet condition from all
    3314              :         //      wet case to give an idea of the expected solution
    3315      2212179 :         int PartWetIterations = 0;
    3316      2212179 :         WetDryInterSurfTempError = 0.0;
    3317      2212179 :         bool CoilPartWetConvg = false;
    3318              :         //      Surface temp at coil water outlet (air inlet) is less than
    3319              :         //      the dew point - Coil must be completely wet so no need to
    3320              :         //      simulate wet/dry case
    3321      2212179 :         if (OutCoilSurfTemp < EnterAirDewPoint) {
    3322       642155 :             CoilPartWetConvg = true;
    3323       642155 :             waterCoil.SurfAreaWetFraction = 1.0;
    3324       642155 :             TotWaterCoilLoad = AirMassFlow * (InletAirEnthalpy - OutletAirEnthalpy);
    3325       642155 :             AirWetDryInterfcTemp = TempAirIn;
    3326       642155 :             WetDryInterfcAirEnthl = InletAirEnthalpy;
    3327              :             //      Surface temperature at coil water inlet is greater than the
    3328              :             //      dewpoint - coil cannot be all wet but may be all dry -
    3329              :             //      initialise with all dry solution
    3330      1570024 :         } else if (InCoilSurfTemp > EnterAirDewPoint) {
    3331       277867 :             SurfAreaWet = 0.0;
    3332       277867 :             waterCoil.SurfAreaWetFraction = 0.0;
    3333       277867 :             WetDryInterfcWaterTemp = TempWaterIn;
    3334       277867 :             TempWaterOut = waterCoil.OutWaterTempSaved + (TempWaterIn - waterCoil.InWaterTempSaved);
    3335       277867 :             WetAreaLast = 0.05 * waterCoil.TotCoilOutsideSurfArea;
    3336              :             //      General case - must be part-wet/part-dry - initialise
    3337              :             //      accordingly with some non-zero wet area
    3338              :         } else {
    3339      1292157 :             if (waterCoil.SurfAreaWetSaved != 0.0) {
    3340      1291171 :                 SurfAreaWet = waterCoil.SurfAreaWetSaved;
    3341              :             } else {
    3342          986 :                 SurfAreaWet = 0.8 * waterCoil.TotCoilOutsideSurfArea * (EnterAirDewPoint - InCoilSurfTemp) / (OutCoilSurfTemp - InCoilSurfTemp);
    3343              :             }
    3344      1292157 :             WetDryInterfcWaterTemp = TempWaterIn + EnterAirDewPoint - InCoilSurfTemp;
    3345      1292157 :             WetAreaLast = 0.0;
    3346              :         }
    3347              :         //       Loop to solve partly wet coil, converges on wet area and
    3348              :         //       boundary temperature at dew point
    3349              :         //       Dry coil is special case with zero wet area, converges on
    3350              :         //       mean water temperature
    3351     13474777 :         while (PartWetIterations < 40 && !CoilPartWetConvg) {
    3352     11262598 :             ++PartWetIterations;
    3353              :             //      effective water temp on dry side of coil
    3354     11262598 :             DrySideEffectiveWaterTemp = 0.5 * (TempWaterOut + WetDryInterfcWaterTemp);
    3355              :             //      tube inside thermal resistance
    3356     11262598 :             DryCoilInThermResist = WaterToTubeThermResist / (1.0 + 0.0146 * DrySideEffectiveWaterTemp);
    3357              :             //      overall UA, from water to air, of dry portion of coil
    3358              : 
    3359     11262598 :             UADryCoil = (waterCoil.TotCoilOutsideSurfArea - SurfAreaWet) /
    3360     11262598 :                         (waterCoil.TotCoilOutsideSurfArea * (TubeFoulThermResist + DryCoilInThermResist + CoilToAirThermResistDrySurf));
    3361              : 
    3362              :             // This is a numerical trap for a very small number in the EXP function that is approaching zero
    3363     11262598 :             if (UADryCoil * DryCoilCoeff1 < -60.0) {
    3364            0 :                 DryCoilCoeff = 0.0;
    3365              :             } else {
    3366     11262598 :                 DryCoilCoeff = std::exp(UADryCoil * DryCoilCoeff1);
    3367              :             }
    3368              : 
    3369     11262598 :             K1 = WaterMassFlowRate * Cp * ConvK * (DryCoilCoeff - 1.0) /
    3370     11262598 :                  (WaterMassFlowRate * Cp * ConvK * DryCoilCoeff - AirMassFlow * MoistAirSpecificHeat);
    3371     11262598 :             if (SurfAreaWet != 0) {
    3372     10695927 :                 waterCoil.SurfAreaWetFraction = SurfAreaWet / waterCoil.TotCoilOutsideSurfArea;
    3373              :                 //      effective water temp on wet side of coil
    3374     10695927 :                 WetSideEffctvWaterTemp = 0.5 * (TempWaterIn + WetDryInterfcWaterTemp);
    3375              :                 //      tube inside thermal resistance
    3376     10695927 :                 ScaledWaterToTubeThermResist = WaterToTubeThermResist / (1.0 + 0.0146 * WetSideEffctvWaterTemp);
    3377     10695927 :                 ScaledCoilAirThermResistWetSurf = CoilToAirThermResistWetSurf / waterCoil.EnthVsTempCurveAppxSlope;
    3378              :                 //      overall UA, from water to air, of wet portion of coil
    3379     10695927 :                 UACoilAllWet = 1.0 / (waterCoil.EnthVsTempCurveAppxSlope *
    3380     10695927 :                                       (TubeFoulThermResist + ScaledWaterToTubeThermResist + ScaledCoilAirThermResistWetSurf));
    3381     10695927 :                 UACoilPartWet = waterCoil.SurfAreaWetFraction * UACoilAllWet;
    3382     10695927 :                 expon = UACoilPartWet * (1.0 / AirMassFlow - waterCoil.EnthVsTempCurveAppxSlope / (WaterMassFlowRate * Cp * ConvK));
    3383              :                 //        prevents floating point error when taking exponential
    3384              :                 //        of a very large number
    3385     10695927 :                 if (expon < 20.0) {
    3386     10695927 :                     WetCoilCoeff = std::exp(expon);
    3387              :                     //          write(outputfiledebug,*) ' wcc=',wetcoilcoeff
    3388     10695927 :                     denom =
    3389     10695927 :                         (waterCoil.EnthVsTempCurveAppxSlope - WetCoilCoeff * ScaledWaterSpecHeat - (1.0 - WetCoilCoeff) * K1 * MoistAirSpecificHeat);
    3390              :                     //          write(outputfiledebug,*) ' denom=',denom
    3391              :                     //          WetDryInterfcWaterTemp = ((1.0 - WetCoilCoeff) * (InletAirEnthalpy - WaterCoil(CoilNum)%EnthVsTempCurveConst -
    3392              :                     //          K1
    3393              :                     //          *  &
    3394              :                     //                                     MoistAirSpecificHeat * TempAirIn) + WetCoilCoeff * &
    3395              :                     //                                     TempWaterIn * (WaterCoil(CoilNum)%EnthVsTempCurveAppxSlope -  &
    3396              :                     //                                     ScaledWaterSpecHeat)) / (WaterCoil(CoilNum)%EnthVsTempCurveAppxSlope -  &
    3397              :                     //                                      WetCoilCoeff * ScaledWaterSpecHeat - (1.0 - WetCoilCoeff) * K1 * &
    3398              :                     //                                     MoistAirSpecificHeat)
    3399     10695927 :                     WetDryInterfcWaterTemp =
    3400     10695927 :                         ((1.0 - WetCoilCoeff) * (InletAirEnthalpy - waterCoil.EnthVsTempCurveConst - K1 * MoistAirSpecificHeat * TempAirIn) +
    3401     10695927 :                          WetCoilCoeff * TempWaterIn * (waterCoil.EnthVsTempCurveAppxSlope - ScaledWaterSpecHeat)) /
    3402              :                         denom;
    3403              :                 } else {
    3404              :                     //         approximation to equation for WetDryInterfcWaterTemp when WetCoilCoeff-->inf.
    3405            0 :                     WetDryInterfcWaterTemp = (TempWaterIn * (waterCoil.EnthVsTempCurveAppxSlope - ScaledWaterSpecHeat) -
    3406            0 :                                               (InletAirEnthalpy - waterCoil.EnthVsTempCurveConst - K1 * MoistAirSpecificHeat * TempAirIn)) /
    3407            0 :                                              (K1 * MoistAirSpecificHeat - ScaledWaterSpecHeat);
    3408              :                 }
    3409              :             }
    3410              :             //        air temperature at wet-dry interface
    3411     11262598 :             AirWetDryInterfcTemp = TempAirIn - (TempAirIn - WetDryInterfcWaterTemp) * K1;
    3412              :             //        coil surface temperature at wet-dry interface
    3413     11262598 :             WetDryInterfcSurfTemp = WetDryInterfcWaterTemp + (AirWetDryInterfcTemp - WetDryInterfcWaterTemp) *
    3414     11262598 :                                                                  (TubeFoulThermResist + DryCoilInThermResist) /
    3415     11262598 :                                                                  (TubeFoulThermResist + DryCoilInThermResist + CoilToAirThermResistDrySurf);
    3416     11262598 :             if (SurfAreaWet != 0) {
    3417     10695927 :                 WetDryInterfcAirEnthl = InletAirEnthalpy - MoistAirSpecificHeat * (TempAirIn - AirWetDryInterfcTemp);
    3418              :                 //        conservation of energy - wet portion of coil
    3419     10695927 :                 OutletAirEnthalpy = WetDryInterfcAirEnthl - WaterMassFlowRate * Cp * ConvK * (WetDryInterfcWaterTemp - TempWaterIn) / AirMassFlow;
    3420              :                 //        ratio of inside to outside thermal resistance
    3421     10695927 :                 InsdToOutsdThermResistRatio = (TubeFoulThermResist + ScaledWaterToTubeThermResist) / ScaledCoilAirThermResistWetSurf;
    3422              :                 //        coil surface temperature at water inlet (air outlet)
    3423     10695927 :                 InCoilSurfTemp = UACoilAllWet * ScaledCoilAirThermResistWetSurf *
    3424     10695927 :                                  (waterCoil.EnthVsTempCurveAppxSlope * TempWaterIn +
    3425     10695927 :                                   (OutletAirEnthalpy - waterCoil.EnthVsTempCurveConst) * InsdToOutsdThermResistRatio);
    3426     10695927 :                 WetDryInterSurfTempErrorLast = WetDryInterSurfTempError;
    3427              :                 //        in part-wet/part-dry solution EnterAirDewPoint=WetDryInterfcSurfTemp drives WetDryInterSurfTempError->0
    3428     10695927 :                 WetDryInterSurfTempError = EnterAirDewPoint - WetDryInterfcSurfTemp;
    3429              :             } else {
    3430              :                 //        dry coil solution
    3431       566671 :                 WetDryInterfcAirEnthl = 0.0;
    3432       566671 :                 OutletAirEnthalpy = InletAirEnthalpy - MoistAirSpecificHeat * (TempAirIn - AirWetDryInterfcTemp);
    3433              :             }
    3434              :             //        total cooling = change in air enthalpy across coil
    3435     11262598 :             TotWaterCoilLoad = AirMassFlow * (InletAirEnthalpy - OutletAirEnthalpy);
    3436              :             //        conservation of energy on water stream gives water outlet
    3437              :             //        temperature
    3438     11262598 :             TempWaterOut = WaterMassFlowRate * Cp * ConvK; // Temp for next calc
    3439     11262598 :             TempWaterOut = min(TempWaterIn + TotWaterCoilLoad / TempWaterOut, TempAirIn);
    3440              :             //        update estimate of coil wet area
    3441              : 
    3442     11262598 :             if (SurfAreaWet == 0) {
    3443       566671 :                 MeanWaterTemp = 0.5 * (TempWaterOut + WetDryInterfcWaterTemp);
    3444       566671 :                 if (EnterAirDewPoint > WetDryInterfcSurfTemp) {
    3445       142667 :                     SurfAreaWet = 0.5 * WetAreaLast;
    3446       424004 :                 } else if (std::abs(MeanWaterTemp - DrySideEffectiveWaterTemp) <= 0.00002) {
    3447       141724 :                     CoilPartWetConvg = true;
    3448              :                 }
    3449     12207331 :             } else if (std::abs(WetDryInterSurfTempError) > 0.00002 ||
    3450      1511404 :                        std::abs(SurfAreaWet - WetAreaLast) / waterCoil.TotCoilOutsideSurfArea > 0.00001) {
    3451      9299148 :                 if (WetAreaLast == 0) {
    3452      1292157 :                     WetAreaLast = SurfAreaWet;
    3453      1292157 :                     SurfAreaWet += 0.4 * waterCoil.TotCoilOutsideSurfArea * WetDryInterSurfTempError / (OutCoilSurfTemp - InCoilSurfTemp);
    3454      8006991 :                 } else if (WetDryInterSurfTempError != WetDryInterSurfTempErrorLast) {
    3455      8006991 :                     WetAreaChange = SurfAreaWet - WetAreaLast;
    3456      8006991 :                     WetAreaLast = SurfAreaWet;
    3457      8006991 :                     SurfAreaWet -= 0.8 * WetDryInterSurfTempError * WetAreaChange / (WetDryInterSurfTempError - WetDryInterSurfTempErrorLast);
    3458              :                 }
    3459      9299148 :                 if (SurfAreaWet >= waterCoil.TotCoilOutsideSurfArea) {
    3460       155960 :                     SurfAreaWet = waterCoil.TotCoilOutsideSurfArea;
    3461       155960 :                     MeanWaterTemp = 0.5 * (TempWaterIn + WetDryInterfcWaterTemp);
    3462       155960 :                     if (WetAreaLast == waterCoil.TotCoilOutsideSurfArea && std::abs(MeanWaterTemp - WetSideEffctvWaterTemp) <= 0.00002) {
    3463        31521 :                         CoilPartWetConvg = true;
    3464              :                     }
    3465              :                 }
    3466      9299148 :                 if (SurfAreaWet <= 0) {
    3467         6524 :                     SurfAreaWet = 0.0;
    3468         6524 :                     waterCoil.SurfAreaWetFraction = 0.0;
    3469         6524 :                     WetDryInterfcWaterTemp = TempWaterIn;
    3470              :                 }
    3471      9299148 :                 InSurfTempSatAirEnthl = PsyHFnTdbRhPb(state, InCoilSurfTemp, unity, state.dataEnvrn->OutBaroPress, RoutineName) * ConvK;
    3472      9299148 :                 if ((EnterAirDewPoint - InCoilSurfTemp) >= 0.0001) {
    3473      9195901 :                     AirEnthAtWetDryIntrfcSurfTemp = PsyHFnTdbRhPb(state, EnterAirDewPoint, unity, state.dataEnvrn->OutBaroPress, RoutineName) * ConvK;
    3474      9195901 :                     waterCoil.EnthVsTempCurveAppxSlope =
    3475      9195901 :                         (AirEnthAtWetDryIntrfcSurfTemp - InSurfTempSatAirEnthl) / (EnterAirDewPoint - InCoilSurfTemp);
    3476              :                 } else {
    3477       103247 :                     AirEnthAtWetDryIntrfcSurfTemp =
    3478       103247 :                         PsyHFnTdbRhPb(state, InCoilSurfTemp + 0.0001, unity, state.dataEnvrn->OutBaroPress, RoutineName) * ConvK;
    3479       103247 :                     waterCoil.EnthVsTempCurveAppxSlope = (AirEnthAtWetDryIntrfcSurfTemp - InSurfTempSatAirEnthl) / 0.0001;
    3480              :                 }
    3481      9299148 :                 waterCoil.EnthVsTempCurveConst = InSurfTempSatAirEnthl - waterCoil.EnthVsTempCurveAppxSlope * InCoilSurfTemp;
    3482              :             } else {
    3483      1396779 :                 CoilPartWetConvg = true;
    3484              :             }
    3485              :         }
    3486              :         //      error checking to see if convergence has been achieved
    3487      2212179 :         if (!CoilPartWetConvg && !state.dataGlobal->WarmupFlag) {
    3488            0 :             ShowRecurringWarningErrorAtEnd(state,
    3489            0 :                                            waterCoil.Name + " not converged (40 iterations) due to \"Partial Wet Convergence\" conditions.",
    3490            0 :                                            state.dataWaterCoils->PartWetCoolCoilErrs(CoilNum));
    3491              :             //      CoolCoilErrs = CoolCoilErrs + 1
    3492              :             //      IF (CoolCoilErrs .LE. MaxCoolCoilErrs) THEN
    3493              :             //        CALL ShowWarningError(state, 'tp12c0:  not converged in 20 CoolCoilErrs')
    3494              :             //      END IF
    3495              :         }
    3496      2212179 :         if (waterCoil.SurfAreaWetFraction > 0 && waterCoil.SurfAreaWetFraction < 1) {
    3497      1396764 :             waterCoil.SurfAreaWetSaved = SurfAreaWet;
    3498              :         }
    3499              :         //       calculate TempAirOut, OutletAirHumRat, and SensCoolRate based on equations from
    3500              :         //       TYPE12 and the ASHRAE toolkit
    3501      2212179 :         if (waterCoil.SurfAreaWetFraction == 0) {
    3502              :             //       dry coil
    3503       141724 :             TempAirOut = TempAirIn - TotWaterCoilLoad / (AirMassFlow * MoistAirSpecificHeat);
    3504       141724 :             OutletAirHumRat = InletAirHumRat;
    3505       141724 :             SenWaterCoilLoad = TotWaterCoilLoad;
    3506              :         } else {
    3507              :             //       coil effectiveness
    3508      2070455 :             expon = waterCoil.SurfAreaWetFraction / (CoilToAirThermResistWetSurf * AirMassFlow);
    3509      2070455 :             y = 0.0;
    3510      2070455 :             if (expon < 20.0) {
    3511      2070291 :                 y = std::exp(-expon);
    3512              :             }
    3513      2070455 :             AirExitEnthlAtCoilSurfTemp = WetDryInterfcAirEnthl - (WetDryInterfcAirEnthl - OutletAirEnthalpy) / (1.0 - y);
    3514      2070455 :             AirExitCoilSurfTemp = AirExitEnthlAtCoilSurfTemp / ConvK; // TEmporary calc
    3515      2070455 :             AirExitCoilSurfTemp = PsyTsatFnHPb(state, AirExitCoilSurfTemp, state.dataEnvrn->OutBaroPress);
    3516              :             //       Implementation of epsilon*NTU method
    3517      2070455 :             TempAirOut = AirExitCoilSurfTemp + (AirWetDryInterfcTemp - AirExitCoilSurfTemp) * y;
    3518      2070455 :             OutletAirHumRat = PsyWFnTdbH(state, TempAirOut, 1000.0 * OutletAirEnthalpy, RoutineName);
    3519      2070455 :             SenWaterCoilLoad = AirMassFlow * (PsyCpAirFnW(InletAirHumRat) * TempAirIn - PsyCpAirFnW(OutletAirHumRat) * TempAirOut) * ConvK;
    3520              :         }
    3521              : 
    3522      2212179 :         if (fanOp == HVAC::FanOp::Cycling) {
    3523            0 :             TotWaterCoilLoad *= PartLoadRatio;
    3524            0 :             SenWaterCoilLoad *= PartLoadRatio;
    3525              :         }
    3526              : 
    3527              :         // Set the outlet conditions
    3528      2212179 :         waterCoil.TotWaterCoolingCoilRate = TotWaterCoilLoad * 1000.0;
    3529      2212179 :         waterCoil.SenWaterCoolingCoilRate = SenWaterCoilLoad * 1000.0;
    3530      2212179 :         waterCoil.OutletAirTemp = TempAirOut;
    3531      2212179 :         waterCoil.OutletWaterTemp = TempWaterOut;
    3532      2212179 :         waterCoil.OutletAirEnthalpy = OutletAirEnthalpy * 1000.0;
    3533      2212179 :         waterCoil.OutletAirHumRat = OutletAirHumRat;
    3534              :         // The CoolingCoilLoad is the change in the enthalpy of the water
    3535      2212179 :         waterCoil.OutletWaterEnthalpy = waterCoil.InletWaterEnthalpy + waterCoil.TotWaterCoolingCoilRate / waterCoil.InletWaterMassFlowRate;
    3536              : 
    3537              :         // This WaterCoil does not change the Mass Flow across the component
    3538      2212179 :         waterCoil.OutletAirMassFlowRate = waterCoil.InletAirMassFlowRate;
    3539      2212179 :         waterCoil.OutletWaterMassFlowRate = waterCoil.InletWaterMassFlowRate;
    3540              :     } else {
    3541              :         // If Coil is scheduled OFF then Outlet conditions are set to Inlet Conditions
    3542      2709086 :         waterCoil.TotWaterCoolingCoilRate = 0.0;
    3543      2709086 :         waterCoil.SenWaterCoolingCoilRate = 0.0;
    3544      2709086 :         TempAirOut = TempAirIn;
    3545      2709086 :         TempWaterOut = TempWaterIn;
    3546              :         // set the outlet conditions to the coil derived type
    3547      2709086 :         waterCoil.OutletAirTemp = TempAirOut;
    3548      2709086 :         waterCoil.OutletWaterTemp = TempWaterOut;
    3549      2709086 :         waterCoil.OutletAirEnthalpy = waterCoil.InletAirEnthalpy;
    3550      2709086 :         waterCoil.OutletAirHumRat = waterCoil.InletAirHumRat;
    3551              :         // The CoolingCoilLoad is the change in the enthalpy of the water
    3552      2709086 :         waterCoil.OutletWaterEnthalpy = waterCoil.InletWaterEnthalpy;
    3553              : 
    3554              :         // This WaterCoil does not change the Mass Flow across the component
    3555      2709086 :         waterCoil.OutletAirMassFlowRate = waterCoil.InletAirMassFlowRate;
    3556      2709086 :         waterCoil.OutletWaterMassFlowRate = 0.0;
    3557              :     }
    3558              : 
    3559              :     // Save some of the Values for next Time step
    3560      4921265 :     waterCoil.InWaterTempSaved = TempWaterIn;
    3561      4921265 :     waterCoil.OutWaterTempSaved = TempWaterOut;
    3562      4921265 : }
    3563              : 
    3564     23088334 : void CoolingCoil(EnergyPlusData &state,
    3565              :                  int const CoilNum,
    3566              :                  bool const FirstHVACIteration,
    3567              :                  int const CalcMode,
    3568              :                  HVAC::FanOp const fanOp,   // fan operating mode
    3569              :                  Real64 const PartLoadRatio // part-load ratio of heating coil
    3570              : )
    3571              : {
    3572              : 
    3573              :     // FUNCTION INFORMATION:
    3574              :     // AUTHOR         Rahul Chillar
    3575              :     // DATE WRITTEN   Mar 2004
    3576              : 
    3577              :     // PURPOSE OF THIS FUNCTION:
    3578              :     // The subroutine has the coil logic. Three types of Cooling Coils exist:
    3579              :     // They are 1.CoilDry , 2.CoilWet, 3. CoilPartDryPartWet. The logic for
    3580              :     // the three individual cases is in this subroutine.
    3581              : 
    3582              :     // METHODOLOGY EMPLOYED:
    3583              :     // Simulates a Coil Model from Design conditions and subsequently uses
    3584              :     // configuration values (example: UA)calculated from those design conditions
    3585              :     // to calculate new performance of coil from operating inputs.The values are
    3586              :     // calculated in the Subroutine InitWaterCoil
    3587              : 
    3588              :     // REFERENCES:
    3589              :     // ASHRAE Secondary HVAC Toolkit TRNSYS.  1990.  A Transient System
    3590              :     // Simulation Program: Reference Manual. Solar Energy Laboratory, Univ. Wisconsin-
    3591              :     // Madison, pp. 4.6.8-1 - 4.6.8-12.
    3592              :     // Threlkeld, J.L.  1970.  Thermal Environmental Engineering, 2nd Edition,
    3593              :     // Englewood Cliffs: Prentice-Hall,Inc. pp. 254-270.
    3594              : 
    3595              :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    3596              :     Real64 AirInletCoilSurfTemp; // Coil surface temperature at air entrance(C)
    3597              :     Real64 AirDewPointTemp;      // Temperature dew point at operating condition
    3598              :     Real64 OutletAirTemp;        // Outlet air temperature at operating condition
    3599              :     Real64 OutletAirHumRat;      // Outlet air humidity ratio at operating condition
    3600              :     Real64 OutletWaterTemp;      // Outlet water temperature at operating condtitons
    3601              :     Real64 TotWaterCoilLoad;     // Total heat transfer rate(W)
    3602              :     Real64 SenWaterCoilLoad;     // Sensible heat transfer rate
    3603              :     Real64 SurfAreaWetFraction;  // Fraction of surface area wet
    3604              :     Real64 AirMassFlowRate;      // Air mass flow rate for the calculation
    3605              : 
    3606     23088334 :     AirInletCoilSurfTemp = 0.0; // Coil surface temperature at air entrance(C)
    3607     23088334 :     AirDewPointTemp = 0.0;      // Temperature dew point at operating condition
    3608     23088334 :     OutletAirTemp = 0.0;        // Outlet air temperature at operating condition
    3609     23088334 :     OutletAirHumRat = 0.0;      // Outlet air humidity ratio at operating condition
    3610     23088334 :     OutletWaterTemp = 0.0;      // Outlet water temperature at operating condtitons
    3611     23088334 :     TotWaterCoilLoad = 0.0;     // Total heat transfer rate(W)
    3612     23088334 :     SenWaterCoilLoad = 0.0;     // Sensible heat transfer rate
    3613     23088334 :     SurfAreaWetFraction = 0.0;  // Fraction of surface area wet
    3614              : 
    3615     23088334 :     auto &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    3616     23088334 :     if (fanOp == HVAC::FanOp::Cycling && PartLoadRatio > 0.0) { // FB Start
    3617      1346418 :         AirMassFlowRate = waterCoil.InletAirMassFlowRate / PartLoadRatio;
    3618              :     } else {
    3619     21741916 :         AirMassFlowRate = waterCoil.InletAirMassFlowRate;
    3620              :     }
    3621              : 
    3622              :     // If Coil is Scheduled ON then do the simulation
    3623     45091781 :     if (((waterCoil.availSched->getCurrentVal() > 0.0) && (waterCoil.InletWaterMassFlowRate > 0.0) &&
    3624     46176668 :          (AirMassFlowRate >= WaterCoils::MinAirMassFlow) && (waterCoil.DesAirVolFlowRate > 0.0) && (waterCoil.MaxWaterMassFlowRate > 0.0)) ||
    3625     10546178 :         (CalcMode == state.dataWaterCoils->DesignCalc)) {
    3626              : 
    3627              :         // Calculate Temperature Dew Point at operating conditions.
    3628     12543576 :         AirDewPointTemp = PsyTdpFnWPb(state, waterCoil.InletAirHumRat, state.dataEnvrn->OutBaroPress);
    3629              : 
    3630     12543576 :         if (waterCoil.CoolingCoilAnalysisMode == state.dataWaterCoils->DetailedAnalysis) {
    3631              :             // Coil is completely dry if AirDewPointTemp is less than InletWaterTemp,hence Call CoilCompletelyDry
    3632       890832 :             if (AirDewPointTemp <= waterCoil.InletWaterTemp) {
    3633              : 
    3634              :                 // Calculate the leaving conditions and performance of dry coil
    3635         1483 :                 CoilCompletelyDry(state,
    3636              :                                   CoilNum,
    3637              :                                   waterCoil.InletWaterTemp,
    3638              :                                   waterCoil.InletAirTemp,
    3639              :                                   waterCoil.UACoilTotal,
    3640              :                                   OutletWaterTemp,
    3641              :                                   OutletAirTemp,
    3642              :                                   OutletAirHumRat,
    3643              :                                   TotWaterCoilLoad,
    3644              :                                   fanOp,
    3645              :                                   PartLoadRatio);
    3646              : 
    3647         1483 :                 SenWaterCoilLoad = TotWaterCoilLoad;
    3648         1483 :                 SurfAreaWetFraction = 0.0;
    3649              : 
    3650              :             } else {
    3651              :                 // Else If AirDewPointTemp is greater than InletWaterTemp then assume the
    3652              :                 // external surface of coil is completely wet,hence Call CoilCompletelyWet
    3653              :                 // Calculate the leaving conditions and performance of wet coil
    3654       889349 :                 CoilCompletelyWet(state,
    3655              :                                   CoilNum,
    3656              :                                   waterCoil.InletWaterTemp,
    3657              :                                   waterCoil.InletAirTemp,
    3658              :                                   waterCoil.InletAirHumRat,
    3659              :                                   waterCoil.UACoilInternal,
    3660              :                                   waterCoil.UACoilExternal,
    3661              :                                   OutletWaterTemp,
    3662              :                                   OutletAirTemp,
    3663              :                                   OutletAirHumRat,
    3664              :                                   TotWaterCoilLoad,
    3665              :                                   SenWaterCoilLoad,
    3666              :                                   SurfAreaWetFraction,
    3667              :                                   AirInletCoilSurfTemp,
    3668              :                                   fanOp,
    3669              :                                   PartLoadRatio);
    3670              : 
    3671              :                 // If AirDewPointTemp is less than temp of coil surface at entry of air
    3672       889349 :                 if (AirDewPointTemp < AirInletCoilSurfTemp) {
    3673              : 
    3674              :                     // Then coil is partially wet and dry hence call CoilPartWetPartDry
    3675              :                     // Calculate the leaving conditions and performance of dry coil
    3676       709695 :                     CoilPartWetPartDry(state,
    3677              :                                        CoilNum,
    3678              :                                        FirstHVACIteration,
    3679              :                                        waterCoil.InletWaterTemp,
    3680              :                                        waterCoil.InletAirTemp,
    3681              :                                        AirDewPointTemp,
    3682              :                                        OutletWaterTemp,
    3683              :                                        OutletAirTemp,
    3684              :                                        OutletAirHumRat,
    3685              :                                        TotWaterCoilLoad,
    3686              :                                        SenWaterCoilLoad,
    3687              :                                        SurfAreaWetFraction,
    3688              :                                        fanOp,
    3689              :                                        PartLoadRatio);
    3690              : 
    3691              :                 } // End if for part wet part dry coil
    3692              :             } // End if for dry coil
    3693              : 
    3694     11652744 :         } else if (waterCoil.CoolingCoilAnalysisMode == state.dataWaterCoils->SimpleAnalysis) {
    3695              :             // Coil is completely dry if AirDewPointTemp is less than InletWaterTemp,hence Call CoilCompletelyDry
    3696     11652744 :             if (AirDewPointTemp <= waterCoil.InletWaterTemp) {
    3697              : 
    3698              :                 // Calculate the leaving conditions and performance of dry coil
    3699      1868939 :                 CoilCompletelyDry(state,
    3700              :                                   CoilNum,
    3701              :                                   waterCoil.InletWaterTemp,
    3702              :                                   waterCoil.InletAirTemp,
    3703              :                                   waterCoil.UACoilTotal,
    3704              :                                   OutletWaterTemp,
    3705              :                                   OutletAirTemp,
    3706              :                                   OutletAirHumRat,
    3707              :                                   TotWaterCoilLoad,
    3708              :                                   fanOp,
    3709              :                                   PartLoadRatio);
    3710              : 
    3711      1868939 :                 SenWaterCoilLoad = TotWaterCoilLoad;
    3712      1868939 :                 SurfAreaWetFraction = 0.0;
    3713              : 
    3714              :             } else {
    3715              :                 // Else If AirDewPointTemp is greater than InletWaterTemp then assume the
    3716              :                 // external surface of coil is completely wet,hence Call CoilCompletelyWet
    3717              :                 // Calculate the leaving conditions and performance of wet coil
    3718      9783805 :                 CoilCompletelyWet(state,
    3719              :                                   CoilNum,
    3720              :                                   waterCoil.InletWaterTemp,
    3721              :                                   waterCoil.InletAirTemp,
    3722              :                                   waterCoil.InletAirHumRat,
    3723              :                                   waterCoil.UACoilInternal,
    3724              :                                   waterCoil.UACoilExternal,
    3725              :                                   OutletWaterTemp,
    3726              :                                   OutletAirTemp,
    3727              :                                   OutletAirHumRat,
    3728              :                                   TotWaterCoilLoad,
    3729              :                                   SenWaterCoilLoad,
    3730              :                                   SurfAreaWetFraction,
    3731              :                                   AirInletCoilSurfTemp,
    3732              :                                   fanOp,
    3733              :                                   PartLoadRatio);
    3734              : 
    3735              :             } // End if for dry coil
    3736              :         }
    3737              : 
    3738              :         // Report outlet variables at nodes
    3739     12543576 :         waterCoil.OutletAirTemp = OutletAirTemp;
    3740     12543576 :         waterCoil.OutletAirHumRat = OutletAirHumRat;
    3741     12543576 :         waterCoil.OutletWaterTemp = OutletWaterTemp;
    3742              :         // Report output results if the coil was operating
    3743              : 
    3744     12543576 :         if (fanOp == HVAC::FanOp::Cycling) {
    3745       711300 :             TotWaterCoilLoad *= PartLoadRatio;
    3746       711300 :             SenWaterCoilLoad *= PartLoadRatio;
    3747              :         }
    3748              : 
    3749     12543576 :         waterCoil.TotWaterCoolingCoilRate = TotWaterCoilLoad;
    3750     12543576 :         waterCoil.SenWaterCoolingCoilRate = SenWaterCoilLoad;
    3751     12543576 :         waterCoil.SurfAreaWetFraction = SurfAreaWetFraction;
    3752              :         //       WaterCoil(CoilNum)%OutletWaterEnthalpy = WaterCoil(CoilNum)%InletWaterEnthalpy+ &
    3753              :         //                                WaterCoil(CoilNum)%TotWaterCoolingCoilRate/WaterCoil(CoilNum)%InletWaterMassFlowRate
    3754     12543576 :         waterCoil.OutletWaterEnthalpy =
    3755     12543576 :             waterCoil.InletWaterEnthalpy + General::SafeDivide(waterCoil.TotWaterCoolingCoilRate, waterCoil.InletWaterMassFlowRate);
    3756              : 
    3757              :     } else {
    3758              :         // If both mass flow rates are zero, set outputs to inputs and return
    3759     10544758 :         waterCoil.OutletWaterTemp = waterCoil.InletWaterTemp;
    3760     10544758 :         waterCoil.OutletAirTemp = waterCoil.InletAirTemp;
    3761     10544758 :         waterCoil.OutletAirHumRat = waterCoil.InletAirHumRat;
    3762     10544758 :         waterCoil.OutletWaterEnthalpy = waterCoil.InletWaterEnthalpy;
    3763     10544758 :         waterCoil.TotWaterCoolingCoilEnergy = 0.0;
    3764     10544758 :         waterCoil.SenWaterCoolingCoilEnergy = 0.0;
    3765     10544758 :         waterCoil.SurfAreaWetFraction = 0.0;
    3766              : 
    3767              :     } // End of the Flow or No flow If block
    3768     23088334 :     waterCoil.OutletWaterMassFlowRate = waterCoil.InletWaterMassFlowRate;
    3769     23088334 :     waterCoil.OutletAirMassFlowRate = waterCoil.InletAirMassFlowRate;
    3770     23088334 :     waterCoil.OutletAirEnthalpy = PsyHFnTdbW(waterCoil.OutletAirTemp, waterCoil.OutletAirHumRat);
    3771     23088334 : }
    3772              : 
    3773              : // End Algorithm Section of the Module
    3774              : 
    3775              : // Coil Completely Dry Subroutine for Cooling Coil
    3776              : 
    3777     18042056 : void CoilCompletelyDry(EnergyPlusData &state,
    3778              :                        int const CoilNum,
    3779              :                        Real64 const WaterTempIn,  // Entering water temperature
    3780              :                        Real64 const AirTempIn,    // Entering air dry bulb temperature
    3781              :                        Real64 const CoilUA,       // Overall heat transfer coefficient
    3782              :                        Real64 &OutletWaterTemp,   // Leaving water temperature
    3783              :                        Real64 &OutletAirTemp,     // Leaving air dry bulb temperature
    3784              :                        Real64 &OutletAirHumRat,   // Leaving air humidity ratio
    3785              :                        Real64 &Q,                 // Heat transfer rate
    3786              :                        HVAC::FanOp const fanOp,   // fan operating mode
    3787              :                        Real64 const PartLoadRatio // part-load ratio of heating coil
    3788              : )
    3789              : {
    3790              : 
    3791              :     // FUNCTION INFORMATION:
    3792              :     // AUTHOR         Rahul Chillar
    3793              :     // DATE WRITTEN   March 2004
    3794              : 
    3795              :     // PURPOSE OF THIS FUNCTION:
    3796              :     // Calculate the performance of a sensible air-liquid heat exchanger.  Calculated
    3797              :     // results include outlet air temperature and humidity, outlet water temperature,
    3798              :     // and heat transfer rate.
    3799              : 
    3800              :     // METHODOLOGY EMPLOYED:
    3801              :     // Models coil using effectiveness-NTU model.
    3802              : 
    3803              :     // REFERENCES:
    3804              :     // Kays, W.M. and A.L. London.  1964,Compact Heat Exchangers, 2nd Edition,
    3805              :     // New York: McGraw-Hill.
    3806              : 
    3807              :     // FUNCTION PARAMETER DEFINITIONS:
    3808              :     static constexpr std::string_view RoutineName("CoilCompletelyDry");
    3809              : 
    3810              :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    3811              :     Real64 CapacitanceAir;   // Air-side capacity rate(W/C)
    3812              :     Real64 CapacitanceWater; // Water-side capacity rate(W/C)
    3813              :     Real64 AirMassFlow;
    3814              :     Real64 WaterMassFlowRate;
    3815              :     Real64 Cp;
    3816              : 
    3817     18042056 :     auto const &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    3818              :     //  adjust mass flow rates for cycling fan cycling coil operation
    3819     18042056 :     if (fanOp == HVAC::FanOp::Cycling) {
    3820      2125206 :         if (PartLoadRatio > 0.0) {
    3821      2125206 :             AirMassFlow = waterCoil.InletAirMassFlowRate / PartLoadRatio;
    3822      2125206 :             WaterMassFlowRate = min(waterCoil.InletWaterMassFlowRate / PartLoadRatio, waterCoil.MaxWaterMassFlowRate);
    3823              :         } else {
    3824            0 :             AirMassFlow = 0.0;
    3825            0 :             WaterMassFlowRate = 0.0;
    3826              :         }
    3827              :     } else {
    3828     15916850 :         AirMassFlow = waterCoil.InletAirMassFlowRate;
    3829     15916850 :         WaterMassFlowRate = waterCoil.InletWaterMassFlowRate;
    3830              :     }
    3831              : 
    3832              :     // Calculate air and water capacity rates
    3833     18042056 :     CapacitanceAir = AirMassFlow * PsyCpAirFnW(waterCoil.InletAirHumRat);
    3834              :     // Water Capacity Rate
    3835     18042056 :     Cp = state.dataPlnt->PlantLoop(waterCoil.WaterPlantLoc.loopNum).glycol->getSpecificHeat(state, WaterTempIn, RoutineName);
    3836              : 
    3837     18042056 :     CapacitanceWater = WaterMassFlowRate * Cp;
    3838              : 
    3839              :     // Determine the air and water outlet conditions
    3840     18042056 :     CoilOutletStreamCondition(state, CoilNum, CapacitanceWater, WaterTempIn, CapacitanceAir, AirTempIn, CoilUA, OutletWaterTemp, OutletAirTemp);
    3841              : 
    3842              :     // Calculate the total and sensible heat transfer rate both are equal in case of Dry Coil
    3843     18042056 :     Q = CapacitanceAir * (AirTempIn - OutletAirTemp);
    3844              : 
    3845              :     // Outlet humidity is equal to Inlet Humidity because its a dry coil
    3846     18042056 :     OutletAirHumRat = waterCoil.InletAirHumRat;
    3847     18042056 : }
    3848              : 
    3849              : // Coil Completely Wet Subroutine for Cooling Coil
    3850              : 
    3851     26844788 : void CoilCompletelyWet(EnergyPlusData &state,
    3852              :                        int const CoilNum,            // Number of Coil
    3853              :                        Real64 const WaterTempIn,     // Water temperature IN to this function (C)
    3854              :                        Real64 const AirTempIn,       // Air dry bulb temperature IN to this function(C)
    3855              :                        Real64 const AirHumRat,       // Air Humidity Ratio IN to this funcation (C)
    3856              :                        Real64 const UAInternalTotal, // Internal overall heat transfer coefficient(W/m2 C)
    3857              :                        Real64 const UAExternalTotal, // External overall heat transfer coefficient(W/m2 C)
    3858              :                        Real64 &OutletWaterTemp,      // Leaving water temperature (C)
    3859              :                        Real64 &OutletAirTemp,        // Leaving air dry bulb temperature(C)
    3860              :                        Real64 &OutletAirHumRat,      // Leaving air humidity ratio
    3861              :                        Real64 &TotWaterCoilLoad,     // Total heat transfer rate(W)
    3862              :                        Real64 &SenWaterCoilLoad,     // Sensible heat transfer rate(W)
    3863              :                        Real64 &SurfAreaWetFraction,  // Fraction of surface area wet
    3864              :                        Real64 &AirInletCoilSurfTemp, // Surface temperature at air entrance(C)
    3865              :                        HVAC::FanOp const fanOp,      // fan operating mode
    3866              :                        Real64 const PartLoadRatio    // part-load ratio of heating coil
    3867              : )
    3868              : {
    3869              : 
    3870              :     // FUNCTION INFORMATION:
    3871              :     // AUTHOR         Rahul Chillar
    3872              :     // DATE WRITTEN   Mar 2004
    3873              : 
    3874              :     // PURPOSE OF THIS FUNCTION:
    3875              :     // Calculate the performance of a cooling coil when the external fin surface is
    3876              :     // complete wet.  Results include outlet air temperature and humidity,
    3877              :     // outlet water temperature, sensible and total cooling capacities, and the wet
    3878              :     // fraction of the air-side surface area.
    3879              : 
    3880              :     // METHODOLOGY EMPLOYED:
    3881              :     // Models coil as counterflow heat exchanger. Approximates saturated air enthalpy as
    3882              :     // a linear function of temperature
    3883              :     // TRNSYS.  1990.  A Transient System Simulation Program: Reference Manual.
    3884              :     // Solar Energy Laboratory, Univ. Wisconsin Madison, pp. 4.6.8-1 - 4.6.8-12.
    3885              :     // Threlkeld, J.L.  1970.  Thermal Environmental Engineering, 2nd Edition,
    3886              :     // Englewood Cliffs: Prentice-Hall,Inc. pp. 254-270.
    3887              :     // Coil Uses Enthalpy Based Heat Transfer Coefficents and converts them to
    3888              :     // convential UA values. Intermediate value of fictitious Cp is defined. This follow
    3889              :     // the same procedure followed in the Design Calculation of the Coil. See the node in
    3890              :     // the one time calculation for design condition.
    3891              : 
    3892              :     // REFERENCES:
    3893              :     // Elmahdy, A.H. and Mitalas, G.P.  1977."A Simple Model for Cooling and
    3894              :     // Dehumidifying Coils for Use In Calculating Energy Requirements for Buildings,"
    3895              :     // ASHRAE Transactions,Vol.83 Part 2, pp. 103-117.
    3896              : 
    3897              :     // FUNCTION PARAMETER DEFINITIONS:
    3898              :     static constexpr std::string_view RoutineName("CoilCompletelyWet");
    3899              : 
    3900              :     // INTERFACE BLOCK SPECIFICATIONS
    3901              :     // na
    3902              : 
    3903              :     // DERIVED TYPE DEFINITIONS
    3904              :     // na
    3905              : 
    3906              :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    3907              :     Real64 AirSideResist;                  // Air-side resistance to heat transfer(m2 C/W)
    3908              :     Real64 WaterSideResist;                // Liquid-side resistance to heat transfer(m2 C/W)
    3909              :     Real64 EnteringAirDewPt;               // Entering air dew point(C)
    3910              :     Real64 UACoilTotalEnth;                // Overall enthalpy heat transfer coefficient(kg/s)
    3911              :     Real64 CapacityRateAirWet;             // Air-side capacity rate(kg/s)
    3912              :     Real64 CapacityRateWaterWet;           // Liquid-side capacity rate(kg/s)
    3913              :     Real64 ResistRatio;                    // Ratio of resistances
    3914              :     Real64 EnthAirOutlet;                  // Outlet air enthalpy
    3915              :     Real64 EnthSatAirInletWaterTemp;       // Saturated enthalpy of air at entering water temperature(J/kg)
    3916              :     Real64 EnthSatAirOutletWaterTemp;      // Saturated enthalpy of air at exit water temperature(J/kg)
    3917              :     Real64 EnthSatAirCoilSurfaceEntryTemp; // Saturated enthalpy of air at entering surface temperature(J/kg)
    3918              :     Real64 EnthSatAirCoilSurfaceExitTemp;  // Saturated enthalpy of air at exit surface temperature(J/kg)
    3919              :     Real64 EnthAirInlet;                   // Enthalpy of air at inlet
    3920              :     Real64 IntermediateCpSat;              // Coefficient for equation below(J/kg C)
    3921              :     // EnthSat1-EnthSat2 = IntermediateCpSat*(TSat1-TSat2)
    3922              :     // (all water and surface temperatures are
    3923              :     // related to saturated air enthalpies for
    3924              :     // wet surface heat transfer calculations)
    3925     26844788 :     Real64 constexpr SmallNo(1.e-9); // smallNo used in place of 0
    3926              :     Real64 AirMassFlow;
    3927              :     Real64 WaterMassFlowRate;
    3928              :     Real64 Cp;
    3929              : 
    3930     26844788 :     SurfAreaWetFraction = 1.0;
    3931     26844788 :     AirSideResist = 1.0 / max(UAExternalTotal, SmallNo);
    3932     26844788 :     WaterSideResist = 1.0 / max(UAInternalTotal, SmallNo);
    3933              : 
    3934     26844788 :     auto const &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    3935              :     //  adjust mass flow rates for cycling fan cycling coil operation
    3936     26844788 :     if (fanOp == HVAC::FanOp::Cycling) {
    3937      2515716 :         if (PartLoadRatio > 0.0) {
    3938      2515716 :             AirMassFlow = waterCoil.InletAirMassFlowRate / PartLoadRatio;
    3939      2515716 :             WaterMassFlowRate = min(waterCoil.InletWaterMassFlowRate / PartLoadRatio, waterCoil.MaxWaterMassFlowRate);
    3940              :         } else {
    3941            0 :             AirMassFlow = 0.0;
    3942            0 :             WaterMassFlowRate = 0.0;
    3943              :         }
    3944              :     } else {
    3945     24329072 :         AirMassFlow = waterCoil.InletAirMassFlowRate;
    3946     24329072 :         WaterMassFlowRate = waterCoil.InletWaterMassFlowRate;
    3947              :     }
    3948              : 
    3949              :     // Calculate enthalpies of entering air and water
    3950              : 
    3951              :     // Enthalpy of air at inlet to the coil
    3952     26844788 :     EnthAirInlet = PsyHFnTdbW(AirTempIn, AirHumRat);
    3953              : 
    3954              :     // Saturation Enthalpy of Air at inlet water temperature
    3955     26844788 :     EnthSatAirInletWaterTemp = PsyHFnTdbW(WaterTempIn, PsyWFnTdpPb(state, WaterTempIn, state.dataEnvrn->OutBaroPress));
    3956              : 
    3957              :     // Estimate IntermediateCpSat using entering air dewpoint and water temperature
    3958     26844788 :     EnteringAirDewPt = PsyTdpFnWPb(state, AirHumRat, state.dataEnvrn->OutBaroPress);
    3959              : 
    3960              :     // An intermediate value of Specific heat . EnthSat1-EnthSat2 = IntermediateCpSat*(TSat1-TSat2)
    3961     26844788 :     IntermediateCpSat =
    3962     26844788 :         (PsyHFnTdbW(EnteringAirDewPt, PsyWFnTdpPb(state, EnteringAirDewPt, state.dataEnvrn->OutBaroPress)) - EnthSatAirInletWaterTemp) /
    3963     26844788 :         (EnteringAirDewPt - WaterTempIn);
    3964              : 
    3965              :     // Determine air and water enthalpy outlet conditions by modeling
    3966              :     // coil as counterflow enthalpy heat exchanger
    3967     26844788 :     UACoilTotalEnth = 1.0 / (IntermediateCpSat * WaterSideResist + AirSideResist * PsyCpAirFnW(0.0));
    3968     26844788 :     CapacityRateAirWet = AirMassFlow;
    3969     26844788 :     Cp = state.dataPlnt->PlantLoop(waterCoil.WaterPlantLoc.loopNum).glycol->getSpecificHeat(state, WaterTempIn, RoutineName);
    3970     26844788 :     CapacityRateWaterWet = WaterMassFlowRate * (Cp / IntermediateCpSat);
    3971     26844788 :     CoilOutletStreamCondition(state,
    3972              :                               CoilNum,
    3973              :                               CapacityRateAirWet,
    3974              :                               EnthAirInlet,
    3975              :                               CapacityRateWaterWet,
    3976              :                               EnthSatAirInletWaterTemp,
    3977              :                               UACoilTotalEnth,
    3978              :                               EnthAirOutlet,
    3979              :                               EnthSatAirOutletWaterTemp);
    3980              : 
    3981              :     // Calculate entering and leaving external surface conditions from
    3982              :     // air and water conditions and the ratio of resistances
    3983     26844788 :     ResistRatio = (WaterSideResist) / (WaterSideResist + PsyCpAirFnW(0.0) / IntermediateCpSat * AirSideResist);
    3984     26844788 :     EnthSatAirCoilSurfaceEntryTemp = EnthSatAirOutletWaterTemp + ResistRatio * (EnthAirInlet - EnthSatAirOutletWaterTemp);
    3985     26844788 :     EnthSatAirCoilSurfaceExitTemp = EnthSatAirInletWaterTemp + ResistRatio * (EnthAirOutlet - EnthSatAirInletWaterTemp);
    3986              : 
    3987              :     // Calculate Coil Surface Temperature at air entry to the coil
    3988     26844788 :     AirInletCoilSurfTemp = PsyTsatFnHPb(state, EnthSatAirCoilSurfaceEntryTemp, state.dataEnvrn->OutBaroPress);
    3989              : 
    3990              :     // Calculate outlet air temperature and humidity from enthalpies and surface conditions.
    3991     26844788 :     TotWaterCoilLoad = AirMassFlow * (EnthAirInlet - EnthAirOutlet);
    3992     26844788 :     OutletWaterTemp = WaterTempIn + TotWaterCoilLoad / max(WaterMassFlowRate, SmallNo) / Cp;
    3993              : 
    3994              :     // Calculates out put variable for  the completely wet coil
    3995     26844788 :     WetCoilOutletCondition(state, CoilNum, AirTempIn, EnthAirInlet, EnthAirOutlet, UAExternalTotal, OutletAirTemp, OutletAirHumRat, SenWaterCoilLoad);
    3996     26844788 : }
    3997              : 
    3998              : // Coil Part Wet Part Dry Subroutine for Cooling Coil
    3999              : 
    4000       709695 : void CoilPartWetPartDry(EnergyPlusData &state,
    4001              :                         int const CoilNum,             // Number of Coil
    4002              :                         bool const FirstHVACIteration, // Saving Old values
    4003              :                         Real64 const InletWaterTemp,   // Entering liquid temperature(C)
    4004              :                         Real64 const InletAirTemp,     // Entering air dry bulb temperature(C)
    4005              :                         Real64 const AirDewPointTemp,  // Entering air dew point(C)
    4006              :                         Real64 &OutletWaterTemp,       // Leaving liquid temperature(C)
    4007              :                         Real64 &OutletAirTemp,         // Leaving air dry bulb temperature(C)
    4008              :                         Real64 &OutletAirHumRat,       // Leaving air humidity ratio
    4009              :                         Real64 &TotWaterCoilLoad,      // Total heat transfer rate (W)
    4010              :                         Real64 &SenWaterCoilLoad,      // Sensible heat transfer rate (W)
    4011              :                         Real64 &SurfAreaWetFraction,   // Fraction of surface area wet
    4012              :                         HVAC::FanOp const fanOp,       // fan operating mode
    4013              :                         Real64 const PartLoadRatio     // part-load ratio of heating coil
    4014              : )
    4015              : {
    4016              : 
    4017              :     // FUNCTION INFORMATION:
    4018              :     // AUTHOR         Rahul Chillar
    4019              :     // DATE WRITTEN   March 2004
    4020              : 
    4021              :     // PURPOSE OF THIS FUNCTION:
    4022              :     // Calculate the performance of a cooling  coil when the external fin surface is
    4023              :     // part wet and part dry.  Results include outlet air temperature and humidity,
    4024              :     // outlet liquid temperature, sensible and total cooling capacities, and the wet
    4025              :     // fraction of the air-side surface area.
    4026              : 
    4027              :     // METHODOLOGY EMPLOYED:
    4028              :     // Models coil using effectiveness NTU model
    4029              : 
    4030              :     // REFERENCES:
    4031              :     // Elmahdy, A.H. and Mitalas, G.P.  1977. "A Simple Model for Cooling and
    4032              :     // Dehumidifying Coils for Use In Calculating Energy Requirements for Buildings,"
    4033              :     // ASHRAE Transactions,Vol.83 Part 2, pp. 103-117.
    4034              :     // TRNSYS.  1990.  A Transient System Simulation Program: Reference Manual.
    4035              :     // Solar Energy Laboratory, Univ. Wisconsin- Madison, pp. 4.6.8-1 - 4.6.8-12.
    4036              :     // Threlkeld, J.L.  1970.  Thermal Environmental Engineering, 2nd Edition,
    4037              :     // Englewood Cliffs: Prentice-Hall,Inc. pp. 254-270.
    4038              : 
    4039              :     // FUNCTION PARAMETER DEFINITIONS:
    4040       709695 :     int constexpr itmax(60);
    4041       709695 :     Real64 constexpr smalltempdiff(1.0e-9);
    4042              : 
    4043              :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    4044              :     Real64 DryCoilHeatTranfer;             // Heat transfer rate for dry coil(W)
    4045              :     Real64 WetCoilTotalHeatTransfer;       // Total heat transfer rate for wet coil(W)
    4046              :     Real64 WetCoilSensibleHeatTransfer;    // Sensible heat transfer rate for wet coil(W)
    4047              :     Real64 SurfAreaWet;                    // Air-side area of wet coil(m2)
    4048              :     Real64 SurfAreaDry;                    // Air-side area of dry coil(m2)
    4049              :     Real64 DryCoilUA;                      // Overall heat transfer coefficient for dry coil(W/C)
    4050              :     Real64 WetDryInterfcWaterTemp;         // Liquid temperature at wet/dry boundary(C)
    4051              :     Real64 WetDryInterfcAirTemp;           // Air temperature at wet/dry boundary(C)
    4052              :     Real64 WetDryInterfcSurfTemp;          // Surface temperature at wet/dry boundary(C)
    4053              :     Real64 EstimateWetDryInterfcWaterTemp; // Estimated liquid temperature at wet/dry boundary(C)
    4054              :     Real64 EstimateSurfAreaWetFraction;    // Initial Estimate for Fraction of Surface Wet with condensation
    4055              :     Real64 WetPartUAInternal;              // UA of Wet Coil Internal
    4056              :     Real64 WetPartUAExternal;              // UA of Dry Coil External
    4057              :     Real64 WetDryInterfcHumRat;            // Humidity Ratio at interface of the wet dry transition
    4058              :     Real64 X1T;                            // Variables used in the two iteration in this subroutine.
    4059              :     Real64 NewSurfAreaWetFrac;             // Variables used in the two iteration in this subroutine.
    4060              :     Real64 ResultXT;                       // Variables used in the two iteration in this subroutine.
    4061              :     Real64 Y1T;                            // Variables used in the two iterations in this subroutine.
    4062              :     Real64 errorT;                         // Error in interation for First If loop
    4063              :     Real64 error;                          // Deviation of dependent variable in iteration
    4064              :     Real64 SurfAreaFracPrevious;
    4065              :     Real64 ErrorPrevious;
    4066              :     Real64 SurfAreaFracLast;
    4067              :     Real64 ErrorLast;
    4068              :     int iter;  // Iteration counter
    4069              :     int icvg;  // Iteration convergence flag
    4070              :     int icvgT; // Iteration Convergence Flag for First If loop
    4071              :     int itT;   // Iteration Counter for First If Loop
    4072              : 
    4073              :     // Iterates on SurfAreaWetFraction to converge on surface temperature equal to
    4074              :     // entering air dewpoint at wet/dry boundary.
    4075              : 
    4076              :     // Preliminary estimates of coil performance to begin iteration
    4077       709695 :     OutletWaterTemp = InletAirTemp;
    4078       709695 :     DryCoilHeatTranfer = 0.0;
    4079       709695 :     WetCoilTotalHeatTransfer = 0.0;
    4080       709695 :     WetCoilSensibleHeatTransfer = 0.0;
    4081              : 
    4082       709695 :     auto &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    4083       709695 :     if (FirstHVACIteration) {
    4084              :         // Estimate liquid temperature at boundary as entering air dew point
    4085       314814 :         WetDryInterfcWaterTemp = AirDewPointTemp;
    4086              : 
    4087              :         // Estimate fraction wet surface area based on liquid temperatures
    4088       314814 :         if (std::abs(OutletWaterTemp - InletWaterTemp) > smalltempdiff) {
    4089       314814 :             SurfAreaWetFraction = (WetDryInterfcWaterTemp - InletWaterTemp) / (OutletWaterTemp - InletWaterTemp);
    4090              :         } else {
    4091            0 :             SurfAreaWetFraction = 0.0;
    4092              :         }
    4093              : 
    4094              :     } else {
    4095       394881 :         SurfAreaWetFraction = waterCoil.SurfAreaWetFractionSaved;
    4096              :     }
    4097              :     // BEGIN LOOP to converge on SurfAreaWetFraction
    4098              :     // The method employed in this loop is as follows: The coil is partially wet and partially dry,
    4099              :     // we calculate the temperature of the coil at the interface, (the point at which the moisture begins
    4100              :     // to condense) temperature of the  water  at interface and air temp is dew point at that location.
    4101              :     // This is done by Iterating between the Completely Dry and Completely Wet Coil until the outlet
    4102              :     // water temperature of one coil equals the inlet water temperature of another.
    4103              :     // Using this value of interface temperature we now iterate to calculate Surface Fraction Wet, Iterate
    4104              :     // function perturbs the value of Surface Fraction Wet and based on this new value the entire loop is
    4105              :     // repeated to get a new interface water temperature and then surface fraction wet is again calculated.
    4106              :     // This process continues till the error between the Wet Dry Interface Temp and Air Dew Point becomes
    4107              :     // very negligible and in 95% of the cases its is a complete convergence to give the exact surface Wet
    4108              :     // fraction.
    4109       709695 :     NewSurfAreaWetFrac = SurfAreaWetFraction;
    4110       709695 :     error = 0.0;
    4111       709695 :     SurfAreaFracPrevious = SurfAreaWetFraction;
    4112       709695 :     ErrorPrevious = 0.0;
    4113       709695 :     SurfAreaFracLast = SurfAreaWetFraction;
    4114       709695 :     ErrorLast = 0.0;
    4115              : 
    4116      4052106 :     for (iter = 1; iter <= itmax; ++iter) {
    4117              : 
    4118              :         // Calculating Surface Area Wet and Surface Area Dry
    4119      4052106 :         SurfAreaWet = SurfAreaWetFraction * waterCoil.TotCoilOutsideSurfArea;
    4120      4052106 :         SurfAreaDry = waterCoil.TotCoilOutsideSurfArea - SurfAreaWet;
    4121              : 
    4122              :         // Calculating UA values for the Dry Part of the Coil
    4123      4052106 :         DryCoilUA = SurfAreaDry / (1.0 / waterCoil.UACoilInternalPerUnitArea + 1.0 / waterCoil.UADryExtPerUnitArea);
    4124              : 
    4125              :         // Calculating UA Value for the Wet part of the Coil
    4126      4052106 :         WetPartUAExternal = waterCoil.UAWetExtPerUnitArea * SurfAreaWet;
    4127      4052106 :         WetPartUAInternal = waterCoil.UACoilInternalPerUnitArea * SurfAreaWet;
    4128              : 
    4129              :         // Calculating Water Temperature at Wet Dry Interface of the coil
    4130      4052106 :         WetDryInterfcWaterTemp = InletWaterTemp + SurfAreaWetFraction * (OutletWaterTemp - InletWaterTemp);
    4131              : 
    4132              :         // BEGIN LOOP to converge on liquid temperature at wet/dry boundary
    4133     16171634 :         for (itT = 1; itT <= itmax; ++itT) {
    4134              : 
    4135              :             // Calculate dry coil performance with estimated liquid temperature at the boundary.
    4136     16171634 :             CoilCompletelyDry(state,
    4137              :                               CoilNum,
    4138              :                               WetDryInterfcWaterTemp,
    4139              :                               InletAirTemp,
    4140              :                               DryCoilUA,
    4141              :                               OutletWaterTemp,
    4142              :                               WetDryInterfcAirTemp,
    4143              :                               WetDryInterfcHumRat,
    4144              :                               DryCoilHeatTranfer,
    4145              :                               fanOp,
    4146              :                               PartLoadRatio);
    4147              : 
    4148              :             // Calculate wet coil performance with calculated air temperature at the boundary.
    4149     16171634 :             CoilCompletelyWet(state,
    4150              :                               CoilNum,
    4151              :                               InletWaterTemp,
    4152              :                               WetDryInterfcAirTemp,
    4153              :                               WetDryInterfcHumRat,
    4154              :                               WetPartUAInternal,
    4155              :                               WetPartUAExternal,
    4156              :                               EstimateWetDryInterfcWaterTemp,
    4157              :                               OutletAirTemp,
    4158              :                               OutletAirHumRat,
    4159              :                               WetCoilTotalHeatTransfer,
    4160              :                               WetCoilSensibleHeatTransfer,
    4161              :                               EstimateSurfAreaWetFraction,
    4162              :                               WetDryInterfcSurfTemp,
    4163              :                               fanOp,
    4164              :                               PartLoadRatio);
    4165              : 
    4166              :             // Iterating to calculate the actual wet dry interface water temperature.
    4167     16171634 :             errorT = EstimateWetDryInterfcWaterTemp - WetDryInterfcWaterTemp;
    4168     16171634 :             General::Iterate(ResultXT, 0.001, WetDryInterfcWaterTemp, errorT, X1T, Y1T, itT, icvgT);
    4169     16171634 :             WetDryInterfcWaterTemp = ResultXT;
    4170              : 
    4171              :             // IF convergence is achieved then exit the itT to itmax Do loop.
    4172     16171634 :             if (icvgT == 1) {
    4173      4052106 :                 break;
    4174              :             }
    4175              : 
    4176              :         } // End Do for Liq Boundary temp Convergence
    4177              : 
    4178              :         // Wet Dry Interface temperature not converged after maximum specified iterations.
    4179              :         // Print error message, set return error flag
    4180      4052106 :         if ((itT > itmax) && (!state.dataGlobal->WarmupFlag)) {
    4181            0 :             ShowWarningError(state, format("For Coil:Cooling:Water {}", waterCoil.Name));
    4182            0 :             ShowContinueError(state, "CoilPartWetPartDry: Maximum iterations exceeded for Liq Temp, at Interface");
    4183              :         }
    4184              : 
    4185              :         // If Following condition prevails then surface is dry, calculate dry coil performance and return
    4186      4052106 :         if (SurfAreaWetFraction <= 0.0 && WetDryInterfcSurfTemp >= AirDewPointTemp) {
    4187              : 
    4188              :             // Calculating Value of Dry UA for the coil
    4189            0 :             DryCoilUA = waterCoil.TotCoilOutsideSurfArea / (1.0 / waterCoil.UACoilInternalPerUnitArea + 1.0 / waterCoil.UADryExtPerUnitArea);
    4190              : 
    4191              :             // Calling the Completely Dry Coil for outputs
    4192            0 :             CoilCompletelyDry(state,
    4193              :                               CoilNum,
    4194              :                               InletWaterTemp,
    4195              :                               InletAirTemp,
    4196              :                               DryCoilUA,
    4197              :                               OutletWaterTemp,
    4198              :                               OutletAirTemp,
    4199              :                               OutletAirHumRat,
    4200              :                               TotWaterCoilLoad,
    4201              :                               fanOp,
    4202              :                               PartLoadRatio);
    4203              : 
    4204              :             // Sensible load = Total load in a Completely Dry Coil
    4205            0 :             SenWaterCoilLoad = TotWaterCoilLoad;
    4206              : 
    4207              :             // All coil is Dry so fraction wet is ofcourse =0
    4208            0 :             SurfAreaWetFraction = 0.0;
    4209            0 :             return;
    4210              :         }
    4211              : 
    4212              :         // IF the coil is not Dry then iterate to calculate Fraction of surface area that is wet.
    4213      4052106 :         error = WetDryInterfcSurfTemp - AirDewPointTemp;
    4214      4052106 :         CoilAreaFracIter(
    4215              :             NewSurfAreaWetFrac, SurfAreaWetFraction, error, SurfAreaFracPrevious, ErrorPrevious, SurfAreaFracLast, ErrorLast, iter, icvg);
    4216      4052106 :         SurfAreaWetFraction = NewSurfAreaWetFrac;
    4217              : 
    4218              :         // If converged, leave iteration loop
    4219      4052106 :         if (icvg == 1) {
    4220       709695 :             break;
    4221              :         }
    4222              : 
    4223              :         // Surface temperature not converged.  Repeat calculations with new
    4224              :         // estimate of fraction wet surface area.
    4225      3342411 :         if (SurfAreaWetFraction > 1.0) {
    4226        50980 :             SurfAreaWetFraction = 1.0;
    4227              :         }
    4228      3342411 :         if (SurfAreaWetFraction <= 0.0) {
    4229       191838 :             SurfAreaWetFraction = 0.0098;
    4230              :         }
    4231              : 
    4232              :     } // End do for the overall iteration
    4233              : 
    4234              :     // Calculate sum of total and sensible heat transfer from dry and wet parts.
    4235       709695 :     TotWaterCoilLoad = DryCoilHeatTranfer + WetCoilTotalHeatTransfer;
    4236       709695 :     SenWaterCoilLoad = DryCoilHeatTranfer + WetCoilSensibleHeatTransfer;
    4237              : 
    4238              :     // Save last iterations values for this current time step
    4239       709695 :     waterCoil.SurfAreaWetFractionSaved = SurfAreaWetFraction;
    4240              : }
    4241              : 
    4242              : // Calculating coil UA for Cooling Coil
    4243              : 
    4244            0 : Real64 CalcCoilUAbyEffectNTU(EnergyPlusData &state,
    4245              :                              int const CoilNum,
    4246              :                              Real64 const CapacityStream1,     // Capacity rate of stream1.(W/C)
    4247              :                              Real64 const EnergyInStreamOne,   // Inlet state of stream1.(C)
    4248              :                              Real64 const CapacityStream2,     // Capacity rate of stream2.(W/C)
    4249              :                              Real64 const EnergyInStreamTwo,   // Inlet state of stream2.(C)
    4250              :                              Real64 const DesTotalHeatTransfer // Heat transfer rate(W)
    4251              : )
    4252              : {
    4253              : 
    4254              :     // FUNCTION INFORMATION:
    4255              :     // AUTHOR         Rahul Chillar
    4256              :     // DATE WRITTEN   March 2004
    4257              : 
    4258              :     // PURPOSE OF THIS FUNCTION:
    4259              :     // Calculate the UA of a heat exchanger using the effectiveness-NTU relationships
    4260              :     // given the entering capacity rate and temperature of each flow stream, the
    4261              :     // heat transfer rate under these conditions and the heat exchanger configuration.
    4262              : 
    4263              :     // METHODOLOGY EMPLOYED:
    4264              :     // Models coil using effectiveness NTU model
    4265              : 
    4266              :     // Enforce explicit typing of all variables in this routine
    4267              : 
    4268              :     // Return value
    4269              :     Real64 CalcCoilUAbyEffectNTU; // Overall heat transfer coefficient(W/C)
    4270              : 
    4271              :     // FUNCTION PARAMETER DEFINITIONS:
    4272            0 :     Real64 constexpr SmallNo(1.e-9);
    4273            0 :     int constexpr itmax(12);
    4274              : 
    4275              :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    4276              :     Real64 MaxHeatTransfer;       // Maximum heat transfer from inlet conditions (W)
    4277              :     Real64 EstimatedHeatTransfer; // Estimated heat transfer in iteration(W)
    4278              :     Real64 CoilUA;                // Estimated heat transfer coefficient(W/C)
    4279              :     Real64 error;                 // Deviation of dependent variable in iteration
    4280              :     Real64 X1;                    // Previous values of independent variable in iteration
    4281              :     Real64 Y1;
    4282              :     Real64 ResultX;
    4283              :     Real64 EnergyOutStreamOne;        // Intermediate Variable used
    4284              :     Real64 EnergyOutStreamTwo;        // Intermediate variable used
    4285              :     Real64 DesTotalHeatTransferCheck; // Check value to keep design total heat transfer in range
    4286              :     int iter;                         // Iteration index
    4287              :     int icvg;                         // Iteration convergence flag
    4288              : 
    4289              :     // Check for Q out of range (effectiveness > 1)
    4290            0 :     MaxHeatTransfer = std::abs(min(CapacityStream1, CapacityStream2) * (EnergyInStreamOne - EnergyInStreamTwo));
    4291              : 
    4292            0 :     auto const &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    4293              :     // Error Message
    4294            0 :     if ((std::abs(DesTotalHeatTransfer) - MaxHeatTransfer) / max(MaxHeatTransfer, SmallNo) > SmallNo) {
    4295            0 :         ShowWarningError(state, format("For Coil:Cooling:Water {}", waterCoil.Name));
    4296            0 :         ShowContinueError(state, "CalcCoilUAbyEffectNTU:Given Q impossible for given inlet states, proceeding with MaxHeat Transfer");
    4297            0 :         ShowContinueError(state, "Check the Sizing:System and Sizing:Zone cooling design supply air temperature and ");
    4298            0 :         ShowContinueError(state,
    4299              :                           "the Sizing:Plant design Loop exit temperature.  There must be sufficient difference between these two temperatures.");
    4300              :     }
    4301              : 
    4302              :     // Design Heat Transfer cannot exceed Max heat Transfer , setting it value such that effectiveness<1.0
    4303            0 :     if ((DesTotalHeatTransfer) > (MaxHeatTransfer)) {
    4304              :         // Pegging value so that effectiveness is less than 1.
    4305            0 :         DesTotalHeatTransferCheck = 0.9 * MaxHeatTransfer;
    4306              : 
    4307              :         // Estimate CalcCoilUAbyEffectNTU
    4308            0 :         CoilUA = std::abs(DesTotalHeatTransferCheck / (EnergyInStreamOne - EnergyInStreamTwo));
    4309              : 
    4310              :     } else {
    4311              : 
    4312              :         // Estimate CalcCoilUAbyEffectNTU
    4313            0 :         CoilUA = std::abs(DesTotalHeatTransfer / (EnergyInStreamOne - EnergyInStreamTwo));
    4314              :     }
    4315              : 
    4316              :     // BEGIN LOOP to iteratively calculate CalcCoilUAbyEffectNTU
    4317            0 :     for (iter = 1; iter <= itmax; ++iter) {
    4318              : 
    4319              :         // Calculate heat transfer rate for estimated CalcCoilUAbyEffectNTU
    4320            0 :         CoilOutletStreamCondition(
    4321              :             state, CoilNum, CapacityStream1, EnergyInStreamOne, CapacityStream2, EnergyInStreamTwo, CoilUA, EnergyOutStreamOne, EnergyOutStreamTwo);
    4322              : 
    4323              :         // Initial Guess for a value of heat transfer
    4324            0 :         EstimatedHeatTransfer = CapacityStream1 * (EnergyInStreamOne - EnergyOutStreamOne);
    4325              : 
    4326              :         // Calculate new estimate for CalcCoilUAbyEffectNTU by iteration
    4327            0 :         if (DesTotalHeatTransfer > MaxHeatTransfer) {
    4328            0 :             error = std::abs(EstimatedHeatTransfer) - std::abs(DesTotalHeatTransferCheck);
    4329              :         } else {
    4330            0 :             error = std::abs(EstimatedHeatTransfer) - std::abs(DesTotalHeatTransfer);
    4331              :         }
    4332            0 :         General::Iterate(ResultX, 0.01, CoilUA, error, X1, Y1, iter, icvg);
    4333            0 :         CoilUA = ResultX;
    4334              :         // If converged, leave loop
    4335            0 :         if (icvg == 1) {
    4336            0 :             break;
    4337              :         }
    4338              :     }
    4339              : 
    4340              :     // If not converged after itmax iterations, return error code
    4341            0 :     if ((iter > itmax) && (!state.dataGlobal->WarmupFlag)) {
    4342            0 :         ShowWarningError(state, format("For Coil:Cooling:Water {}", waterCoil.Name));
    4343            0 :         ShowContinueError(state, "CalcCoilUAbyEffectNTU: Maximum iterations exceeded:Coil UA calculation");
    4344            0 :         CalcCoilUAbyEffectNTU = 0.0; // Autodesk:Return Line added to set return value: Using non-converged CoilUA value may be preferred but
    4345              :                                      // that was not happening
    4346              :     } else {
    4347              : 
    4348              :         // Assign value to CalcCoilUAbyEffectNTU
    4349            0 :         CalcCoilUAbyEffectNTU = CoilUA;
    4350              :     }
    4351              : 
    4352            0 :     return CalcCoilUAbyEffectNTU;
    4353              : }
    4354              : 
    4355              : // Calculating coil outlet stream conditions and coil UA for Cooling Coil
    4356              : 
    4357     44886844 : void CoilOutletStreamCondition(EnergyPlusData &state,
    4358              :                                int const CoilNum,
    4359              :                                Real64 const CapacityStream1,   // Capacity rate of stream1(W/C)
    4360              :                                Real64 const EnergyInStreamOne, // Inlet state of stream1 (C)
    4361              :                                Real64 const CapacityStream2,   // Capacity rate of stream2 (W/C)
    4362              :                                Real64 const EnergyInStreamTwo, // Inlet state of stream2 (C)
    4363              :                                Real64 const CoilUA,            // Heat transfer rateW)
    4364              :                                Real64 &EnergyOutStreamOne,     // Outlet state of stream1 (C)
    4365              :                                Real64 &EnergyOutStreamTwo      // Outlet state of stream2 (C)
    4366              : )
    4367              : {
    4368              : 
    4369              :     // FUNCTION INFORMATION:
    4370              :     // AUTHOR         Rahul Chillar
    4371              :     // DATE WRITTEN   March 2004
    4372              : 
    4373              :     // PURPOSE OF THIS FUNCTION:
    4374              :     // Calculate the outlet states of a simple heat exchanger using the effectiveness-Ntu
    4375              :     // method of analysis.
    4376              : 
    4377              :     // REFERENCES:
    4378              :     // Kays, W.M. and A.L. London.  1964.Compact Heat Exchangers, 2nd Ed.McGraw-Hill:New York.
    4379              : 
    4380              :     // FUNCTION PARAMETER DEFINITIONS:
    4381     44886844 :     Real64 constexpr LargeNo(1.e10);  // value used in place of infinity
    4382     44886844 :     Real64 constexpr SmallNo(1.e-15); // value used in place of zero
    4383              : 
    4384              :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    4385              :     Real64 MinimumCapacityStream; // Minimum capacity rate of the streams(W/C)
    4386              :     Real64 MaximumCapacityStream; // Maximum capacity rate of the streams(W/C)
    4387              :     Real64 RatioStreamCapacity;   // Ratio of minimum to maximum capacity rate
    4388              :     Real64 NTU;                   // Number of transfer units
    4389     44886844 :     Real64 effectiveness(0.0);    // Heat exchanger effectiveness
    4390              :     Real64 MaxHeatTransfer;       // Maximum heat transfer possible(W)
    4391              :     Real64 e;                     // Intermediate variables in effectiveness equation
    4392              :     Real64 eta;
    4393              :     Real64 b;
    4394              :     Real64 d;
    4395              : 
    4396              :     // NTU and MinimumCapacityStream/MaximumCapacityStream (RatioStreamCapacity) calculations
    4397     44886844 :     MinimumCapacityStream = min(CapacityStream1, CapacityStream2);
    4398     44886844 :     MaximumCapacityStream = max(CapacityStream1, CapacityStream2);
    4399              : 
    4400     44886844 :     if (std::abs(MaximumCapacityStream) <= 1.e-6) { // .EQ. 0.0d0) THEN
    4401            0 :         RatioStreamCapacity = 1.0;
    4402              :     } else {
    4403     44886844 :         RatioStreamCapacity = MinimumCapacityStream / MaximumCapacityStream;
    4404              :     }
    4405              : 
    4406     44886844 :     if (std::abs(MinimumCapacityStream) <= 1.e-6) { // .EQ. 0.0d0) THEN
    4407            0 :         NTU = LargeNo;
    4408              :     } else {
    4409     44886844 :         NTU = CoilUA / MinimumCapacityStream;
    4410              :     }
    4411              : 
    4412     44886844 :     auto const &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    4413              :     // Calculate effectiveness for special limiting cases
    4414     44886844 :     if (NTU <= 0.0) {
    4415       168829 :         effectiveness = 0.0;
    4416              : 
    4417     44718015 :     } else if (RatioStreamCapacity < SmallNo) {
    4418              :         // MinimumCapacityStream/MaximumCapacityStream = 0 and effectiveness is independent of configuration
    4419              :         // 20 is the Limit Chosen for Exponential Function, beyond which there is float point error.
    4420            0 :         if (NTU > 20.0) {
    4421            0 :             effectiveness = 1.0;
    4422              :         } else {
    4423            0 :             effectiveness = 1.0 - std::exp(-NTU);
    4424              :         }
    4425              :         // Calculate effectiveness depending on heat exchanger configuration
    4426     44718015 :     } else if (waterCoil.HeatExchType == state.dataWaterCoils->CounterFlow) {
    4427              : 
    4428              :         // Counterflow Heat Exchanger Configuration
    4429        12198 :         if (std::abs(RatioStreamCapacity - 1.0) < SmallNo) {
    4430            0 :             effectiveness = NTU / (NTU + 1.0);
    4431              :         } else {
    4432        12198 :             if (NTU * (1.0 - RatioStreamCapacity) > 20.0) {
    4433            0 :                 e = 0.0;
    4434              :             } else {
    4435        12198 :                 e = std::exp(-NTU * (1.0 - RatioStreamCapacity));
    4436              :             }
    4437        12198 :             effectiveness = (1.0 - e) / (1.0 - RatioStreamCapacity * e);
    4438              :         }
    4439              : 
    4440     44705817 :     } else if (waterCoil.HeatExchType == state.dataWaterCoils->CrossFlow) {
    4441              :         // Cross flow, both streams unmixed
    4442     44705817 :         eta = std::pow(NTU, -0.22);
    4443     44705817 :         if ((NTU * RatioStreamCapacity * eta) > 20.0) {
    4444            0 :             b = 1.0 / (RatioStreamCapacity * eta);
    4445            0 :             if (b > 20.0) {
    4446            0 :                 effectiveness = 1.0;
    4447              :             } else {
    4448            0 :                 effectiveness = 1.0 - std::exp(-b);
    4449            0 :                 if (effectiveness < 0.0) {
    4450            0 :                     effectiveness = 0.0;
    4451              :                 }
    4452              :             }
    4453              :         } else {
    4454     44705817 :             d = ((std::exp(-NTU * RatioStreamCapacity * eta) - 1.0) / (RatioStreamCapacity * eta));
    4455     44705817 :             if (d < -20.0 || d > 0.0) {
    4456        13615 :                 effectiveness = 1.0;
    4457              :             } else {
    4458     44692202 :                 effectiveness = 1.0 - std::exp((std::exp(-NTU * RatioStreamCapacity * eta) - 1.0) / (RatioStreamCapacity * eta));
    4459     44692202 :                 if (effectiveness < 0.0) {
    4460            0 :                     effectiveness = 0.0;
    4461              :                 }
    4462              :             }
    4463              :         }
    4464              :     }
    4465              : 
    4466              :     // Determine leaving conditions for the two streams
    4467     44886844 :     MaxHeatTransfer = max(MinimumCapacityStream, SmallNo) * (EnergyInStreamOne - EnergyInStreamTwo);
    4468     44886844 :     EnergyOutStreamOne = EnergyInStreamOne - effectiveness * MaxHeatTransfer / max(CapacityStream1, SmallNo);
    4469     44886844 :     EnergyOutStreamTwo = EnergyInStreamTwo + effectiveness * MaxHeatTransfer / max(CapacityStream2, SmallNo);
    4470     44886844 : }
    4471              : 
    4472              : // Subroutine for caculating outlet condition if coil is wet , for Cooling Coil
    4473              : 
    4474     26844788 : void WetCoilOutletCondition(EnergyPlusData &state,
    4475              :                             int const CoilNum,
    4476              :                             Real64 const AirTempIn,      // Entering air dry bulb temperature(C)
    4477              :                             Real64 const EnthAirInlet,   // Entering air enthalpy(J/kg)
    4478              :                             Real64 const EnthAirOutlet,  // Leaving air enthalpy(J/kg)
    4479              :                             Real64 const UACoilExternal, // Heat transfer coefficient for external surface (W/C)
    4480              :                             Real64 &OutletAirTemp,       // Leaving air dry bulb temperature(C)
    4481              :                             Real64 &OutletAirHumRat,     // Leaving air humidity ratio
    4482              :                             Real64 &SenWaterCoilLoad     // Sensible heat transfer rate(W)
    4483              : )
    4484              : {
    4485              : 
    4486              :     // FUNCTION INFORMATION:
    4487              :     // AUTHOR         Rahul Chillar
    4488              :     // DATE WRITTEN   Mar 2004
    4489              : 
    4490              :     // PURPOSE OF THIS FUNCTION:
    4491              :     // Calculate the leaving air temperature,the leaving air humidity ratio and the
    4492              :     // sensible cooling capacity of wet cooling coil.
    4493              : 
    4494              :     // METHODOLOGY EMPLOYED:
    4495              :     // Assumes condensate at uniform temperature.
    4496              : 
    4497              :     // REFERENCES:
    4498              :     // Elmahdy, A.H. and Mitalas, G.P.  1977."A Simple Model for Cooling and
    4499              :     // Dehumidifying Coils for Use In Calculating Energy Requirements for Buildings,"
    4500              :     // ASHRAE Transactions,Vol.83 Part 2, pp. 103-117.
    4501              : 
    4502              :     // FUNCTION PARAMETER DEFINITIONS:
    4503     26844788 :     Real64 constexpr SmallNo(1.e-9); // SmallNo value used in place of zero
    4504              : 
    4505              :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    4506              :     Real64 CapacitanceAir;        // Air capacity rate(W/C)
    4507              :     Real64 NTU;                   // Number of heat transfer units
    4508              :     Real64 effectiveness;         // Heat exchanger effectiveness
    4509              :     Real64 EnthAirCondensateTemp; // Saturated air enthalpy at temperature of condensate(J/kg)
    4510              :     Real64 TempCondensation;      // Temperature of condensate(C)
    4511              :     Real64 TempAirDewPoint;       // Temperature air dew point
    4512              : 
    4513              :     // Determine the temperature effectiveness, assuming the temperature
    4514              :     // of the condensate is constant (MinimumCapacityStream/MaximumCapacityStream = 0) and the specific heat
    4515              :     // of moist air is constant
    4516              : 
    4517     26844788 :     auto const &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    4518     26844788 :     CapacitanceAir = waterCoil.InletAirMassFlowRate * PsyCpAirFnW(waterCoil.InletAirHumRat);
    4519              : 
    4520              :     // Calculating NTU from UA and Capacitance.
    4521              :     // del      NTU = UACoilExternal/MAX(CapacitanceAir,SmallNo)
    4522              :     // del      effectiveness = 1 - EXP(-MAX(0.0d0,NTU))
    4523              :     // Calculating NTU from UA and Capacitance.
    4524     26844788 :     if (UACoilExternal > 0.0) {
    4525     26844788 :         if (CapacitanceAir > 0.0) {
    4526     26844788 :             NTU = UACoilExternal / CapacitanceAir;
    4527              :         } else {
    4528            0 :             NTU = 0.0;
    4529              :         }
    4530     26844788 :         effectiveness = 1.0 - std::exp(-NTU);
    4531              :     } else {
    4532            0 :         effectiveness = 0.0;
    4533              :     }
    4534              : 
    4535              :     // Calculate coil surface enthalpy and temperature at the exit
    4536              :     // of the wet part of the coil using the effectiveness relation
    4537     26844788 :     effectiveness = max(effectiveness, SmallNo);
    4538     26844788 :     EnthAirCondensateTemp = EnthAirInlet - (EnthAirInlet - EnthAirOutlet) / effectiveness;
    4539              : 
    4540              :     // Calculate condensate temperature as the saturation temperature
    4541              :     // at given saturation enthalpy
    4542     26844788 :     TempCondensation = PsyTsatFnHPb(state, EnthAirCondensateTemp, state.dataEnvrn->OutBaroPress);
    4543              : 
    4544     26844788 :     TempAirDewPoint = PsyTdpFnWPb(state, waterCoil.InletAirHumRat, state.dataEnvrn->OutBaroPress);
    4545              : 
    4546     26844788 :     if ((TempAirDewPoint - TempCondensation) > 0.1) {
    4547              : 
    4548              :         // Calculate Outlet Air Temperature using effectivness
    4549     23470118 :         OutletAirTemp = AirTempIn - (AirTempIn - TempCondensation) * effectiveness;
    4550              :         // Calculate Outlet air humidity ratio from PsyWFnTdbH routine
    4551     23470118 :         OutletAirHumRat = PsyWFnTdbH(state, OutletAirTemp, EnthAirOutlet);
    4552              : 
    4553              :     } else {
    4554      3374670 :         OutletAirHumRat = waterCoil.InletAirHumRat;
    4555      3374670 :         OutletAirTemp = PsyTdbFnHW(EnthAirOutlet, OutletAirHumRat);
    4556              :     }
    4557              : 
    4558              :     // Calculate Sensible Coil Load
    4559     26844788 :     SenWaterCoilLoad = CapacitanceAir * (AirTempIn - OutletAirTemp);
    4560     26844788 : }
    4561              : 
    4562              : // Beginning of Update subroutines for the WaterCoil Module
    4563              : // *****************************************************************************
    4564              : 
    4565    149968186 : void UpdateWaterCoil(EnergyPlusData &state, int const CoilNum)
    4566              : {
    4567              :     // SUBROUTINE INFORMATION:
    4568              :     //       AUTHOR         Richard Liesen
    4569              :     //       DATE WRITTEN   1998
    4570              :     //       MODIFIED       April 2004: Rahul Chillar
    4571              :     //                      Feb 2010 B. Griffith, plant upgrades
    4572              :     //       RE-ENGINEERED  na
    4573              : 
    4574              :     // PURPOSE OF THIS SUBROUTINE:
    4575              :     // This subroutine updates the coil outlet nodes.
    4576              : 
    4577              :     // METHODOLOGY EMPLOYED:
    4578              :     // Data is moved from the coil data structure to the coil outlet nodes.
    4579              : 
    4580              :     // Locals
    4581              :     // SUBROUTINE ARGUMENT DEFINITIONS:
    4582              : 
    4583              :     // SUBROUTINE PARAMETER DEFINITIONS:
    4584              :     // na
    4585              : 
    4586              :     // INTERFACE BLOCK SPECIFICATIONS
    4587              :     // na
    4588              : 
    4589              :     // DERIVED TYPE DEFINITIONS
    4590              :     // na
    4591              : 
    4592              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4593    149968186 :     auto const &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    4594    149968186 :     int const AirInletNode = waterCoil.AirInletNodeNum;
    4595    149968186 :     int const AirOutletNode = waterCoil.AirOutletNodeNum;
    4596    149968186 :     int const WaterOutletNode = waterCoil.WaterOutletNodeNum;
    4597              : 
    4598              :     // Set the outlet air nodes of the WaterCoil
    4599    149968186 :     state.dataLoopNodes->Node(AirOutletNode).MassFlowRate = waterCoil.OutletAirMassFlowRate;
    4600    149968186 :     state.dataLoopNodes->Node(AirOutletNode).Temp = waterCoil.OutletAirTemp;
    4601    149968186 :     state.dataLoopNodes->Node(AirOutletNode).HumRat = waterCoil.OutletAirHumRat;
    4602    149968186 :     state.dataLoopNodes->Node(AirOutletNode).Enthalpy = waterCoil.OutletAirEnthalpy;
    4603              : 
    4604    149968186 :     state.dataLoopNodes->Node(WaterOutletNode).Temp = waterCoil.OutletWaterTemp;
    4605    149968186 :     state.dataLoopNodes->Node(WaterOutletNode).Enthalpy = waterCoil.OutletWaterEnthalpy;
    4606              : 
    4607              :     // Set the outlet nodes for properties that just pass through & not used
    4608    149968186 :     state.dataLoopNodes->Node(AirOutletNode).Quality = state.dataLoopNodes->Node(AirInletNode).Quality;
    4609    149968186 :     state.dataLoopNodes->Node(AirOutletNode).Press = state.dataLoopNodes->Node(AirInletNode).Press;
    4610    149968186 :     state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMin = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMin;
    4611    149968186 :     state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMax = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMax;
    4612    149968186 :     state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMinAvail;
    4613    149968186 :     state.dataLoopNodes->Node(AirOutletNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(AirInletNode).MassFlowRateMaxAvail;
    4614    149968186 :     if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    4615            0 :         state.dataLoopNodes->Node(AirOutletNode).CO2 = state.dataLoopNodes->Node(AirInletNode).CO2;
    4616              :     }
    4617    149968186 :     if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    4618            0 :         state.dataLoopNodes->Node(AirOutletNode).GenContam = state.dataLoopNodes->Node(AirInletNode).GenContam;
    4619              :     }
    4620    149968186 : }
    4621              : 
    4622              : //        End of Update subroutines for the WaterCoil Module
    4623              : // *****************************************************************************
    4624              : 
    4625              : // Beginning of Reporting subroutines for the WaterCoil Module
    4626              : // *****************************************************************************
    4627              : 
    4628    149968186 : void ReportWaterCoil(EnergyPlusData &state, int const CoilNum)
    4629              : {
    4630              : 
    4631              :     // SUBROUTINE INFORMATION:
    4632              :     //       AUTHOR         Richard Liesen
    4633              :     //       DATE WRITTEN   1998
    4634              : 
    4635              :     // PURPOSE OF THIS SUBROUTINE:
    4636              :     // This subroutine updates the report variable for the coils.
    4637              : 
    4638    149968186 :     auto &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    4639    149968186 :     if (waterCoil.reportCoilFinalSizes) {
    4640     20373029 :         if (!state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingHVACSizingSimulations && !state.dataGlobal->DoingSizing) {
    4641         3351 :             std::string coilObjClassName;
    4642         3351 :             if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
    4643         2755 :                 coilObjClassName = "Coil:Heating:Water";
    4644         2755 :                 state.dataRptCoilSelection->coilSelectionReportObj->setCoilFinalSizes(state,
    4645         2755 :                                                                                       waterCoil.Name,
    4646              :                                                                                       coilObjClassName,
    4647              :                                                                                       waterCoil.DesWaterHeatingCoilRate,
    4648              :                                                                                       waterCoil.DesWaterHeatingCoilRate,
    4649              :                                                                                       waterCoil.DesAirVolFlowRate,
    4650              :                                                                                       waterCoil.MaxWaterVolFlowRate);
    4651         2755 :                 waterCoil.reportCoilFinalSizes = false;
    4652          596 :             } else if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling) {
    4653          162 :                 coilObjClassName = "Coil:Cooling:Water:DetailedGeometry";
    4654          162 :                 state.dataRptCoilSelection->coilSelectionReportObj->setCoilFinalSizes(state,
    4655          162 :                                                                                       waterCoil.Name,
    4656              :                                                                                       coilObjClassName,
    4657              :                                                                                       waterCoil.DesWaterCoolingCoilRate,
    4658              :                                                                                       -999.0,
    4659              :                                                                                       waterCoil.DesAirVolFlowRate,
    4660              :                                                                                       waterCoil.MaxWaterVolFlowRate);
    4661          162 :                 waterCoil.reportCoilFinalSizes = false;
    4662          434 :             } else if (waterCoil.WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) {
    4663          434 :                 coilObjClassName = "Coil:Cooling:Water";
    4664          434 :                 state.dataRptCoilSelection->coilSelectionReportObj->setCoilFinalSizes(state,
    4665          434 :                                                                                       waterCoil.Name,
    4666              :                                                                                       coilObjClassName,
    4667              :                                                                                       waterCoil.DesWaterCoolingCoilRate,
    4668              :                                                                                       -999.0,
    4669              :                                                                                       waterCoil.DesAirVolFlowRate,
    4670              :                                                                                       waterCoil.MaxWaterVolFlowRate);
    4671          434 :                 waterCoil.reportCoilFinalSizes = false;
    4672              :             }
    4673         3351 :         }
    4674              :     }
    4675    149968186 :     Real64 ReportingConstant = state.dataHVACGlobal->TimeStepSysSec;
    4676              :     // report the WaterCoil energy from this component
    4677    149968186 :     waterCoil.TotWaterHeatingCoilEnergy = waterCoil.TotWaterHeatingCoilRate * ReportingConstant;
    4678    149968186 :     waterCoil.TotWaterCoolingCoilEnergy = waterCoil.TotWaterCoolingCoilRate * ReportingConstant;
    4679    149968186 :     waterCoil.SenWaterCoolingCoilEnergy = waterCoil.SenWaterCoolingCoilRate * ReportingConstant;
    4680              : 
    4681              :     // report the WaterCoil water collection to water storage tank (if needed)
    4682              : 
    4683    149968186 :     if (waterCoil.CondensateCollectMode == state.dataWaterCoils->CondensateToTank) {
    4684              :         // calculate and report condensation rates  (how much water extracted from the air stream)
    4685              :         // water volumetric flow of water in m3/s for water system interactions
    4686              :         //  put here to catch all types of DX coils
    4687            0 :         Real64 Tavg = (waterCoil.InletAirTemp + waterCoil.OutletAirTemp) / 2.0;
    4688              :         //   CR9155 Remove specific humidity calculations
    4689              :         //  mdot * del HumRat / rho water
    4690            0 :         waterCoil.CondensateVdot =
    4691            0 :             max(0.0, (waterCoil.InletAirMassFlowRate * (waterCoil.InletAirHumRat - waterCoil.OutletAirHumRat) / Psychrometrics::RhoH2O(Tavg)));
    4692            0 :         waterCoil.CondensateVol = waterCoil.CondensateVdot * ReportingConstant;
    4693              : 
    4694            0 :         state.dataWaterData->WaterStorage(waterCoil.CondensateTankID).VdotAvailSupply(waterCoil.CondensateTankSupplyARRID) = waterCoil.CondensateVdot;
    4695            0 :         state.dataWaterData->WaterStorage(waterCoil.CondensateTankID).TwaterSupply(waterCoil.CondensateTankSupplyARRID) = waterCoil.OutletAirTemp;
    4696              :     }
    4697    149968186 : }
    4698              : 
    4699              : //        End of Reporting subroutines for the WaterCoil Module
    4700              : // *****************************************************************************
    4701              : 
    4702              : // Beginning of Coil Utility subroutines for the Detailed Model
    4703              : // *****************************************************************************
    4704              : 
    4705         1005 : void CalcDryFinEffCoef(EnergyPlusData &state, Real64 const OutTubeEffFinDiamRatio, Array1D<Real64> &PolynomCoef)
    4706              : {
    4707              :     // SUBROUTINE INFORMATION:
    4708              :     //       AUTHOR   Unknown
    4709              :     //       DATE WRITTEN   Unknown
    4710              :     //       DATE REWRITTEN  April 1997 by Russell D. Taylor, Ph.D.
    4711              :     //       MODIFIED
    4712              :     //       RE-ENGINEERED
    4713              : 
    4714              :     // PURPOSE OF THIS SUBROUTINE:
    4715              :     // The following subroutines are used once per cooling coil
    4716              :     // simulation to obtain the coefficients of the dry fin
    4717              :     // efficiency equation.  CalcDryFinEffCoef is the main calling
    4718              :     // routine which manages calls to the Bessel funtion and polynomial
    4719              :     // fit routines.
    4720              : 
    4721              :     // REFERENCES:
    4722              :     // First found in MODSIM.
    4723              :     // USE STATEMENTS:
    4724              :     // na
    4725              : 
    4726              :     // Argument array dimensioning
    4727              : 
    4728              :     // Locals
    4729              :     // SUBROUTINE ARGUMENT DEFINITIONS:
    4730              : 
    4731              :     // SUBROUTINE PARAMETER DEFINITIONS:
    4732              :     // na
    4733              : 
    4734              :     // INTERFACE BLOCK SPECIFICATIONS
    4735              :     // na
    4736              : 
    4737              :     // DERIVED TYPE DEFINITIONS
    4738              :     // na
    4739              : 
    4740              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4741              :     Real64 FAI;
    4742              :     Real64 FED;
    4743              :     Real64 FEDnumerator;
    4744              :     int I;
    4745              :     int IE1;
    4746              :     int IE2;
    4747              :     int IE3;
    4748              :     int IE4;
    4749              :     int IE5;
    4750              :     int IE6;
    4751              :     Real64 R1;
    4752              :     Real64 R1I1;
    4753              :     Real64 R1K1;
    4754              :     Real64 R2;
    4755              :     Real64 R2I0;
    4756              :     Real64 R2I1;
    4757              :     Real64 R2K0;
    4758              :     Real64 R2K1;
    4759              :     Real64 RO;
    4760              : 
    4761         1005 :     FAI = 0.02;
    4762        61305 :     for (I = 1; I <= WaterCoils::MaxOrderedPairs; ++I) {
    4763        60300 :         FAI += 0.035;
    4764        60300 :         R1 = FAI / (1.0 - OutTubeEffFinDiamRatio);
    4765        60300 :         R2 = R1 * OutTubeEffFinDiamRatio;
    4766        60300 :         RO = 2.0 * OutTubeEffFinDiamRatio / (FAI * (1.0 + OutTubeEffFinDiamRatio));
    4767        60300 :         CalcIBesselFunc(R1, 1, R1I1, IE1);
    4768        60300 :         CalcKBesselFunc(R2, 1, R2K1, IE2);
    4769        60300 :         CalcIBesselFunc(R2, 1, R2I1, IE3);
    4770        60300 :         CalcKBesselFunc(R1, 1, R1K1, IE4);
    4771        60300 :         CalcIBesselFunc(R2, 0, R2I0, IE5);
    4772        60300 :         CalcKBesselFunc(R2, 0, R2K0, IE6);
    4773        60300 :         FEDnumerator = RO * (R1I1 * R2K1 - R2I1 * R1K1);
    4774        60300 :         if (FEDnumerator != 0.0) {
    4775        60300 :             FED = FEDnumerator / (R2I0 * R1K1 + R1I1 * R2K0);
    4776              :         } else {
    4777            0 :             FED = 0.0;
    4778              :         }
    4779              :         //      FED = RO * (R1I1 * R2K1 - R2I1 * R1K1) / (R2I0 * R1K1 + R1I1 * R2K0)
    4780        60300 :         state.dataWaterCoils->OrderedPair(I, 1) = FAI;
    4781        60300 :         state.dataWaterCoils->OrderedPair(I, 2) = FED;
    4782              :     }
    4783         1005 :     CalcPolynomCoef(state, state.dataWaterCoils->OrderedPair, PolynomCoef);
    4784         1005 : }
    4785              : 
    4786       180900 : void CalcIBesselFunc(Real64 const BessFuncArg, int const BessFuncOrd, Real64 &IBessFunc, int &ErrorCode)
    4787              : {
    4788              :     // SUBROUTINE INFORMATION:
    4789              :     //       AUTHOR   Unknown
    4790              :     //       DATE WRITTEN   Unknown
    4791              :     //       DATE REWRITTEN  April 1997 by Russell D. Taylor, Ph.D.
    4792              :     //       MODIFIED
    4793              :     //       RE-ENGINEERED
    4794              : 
    4795              :     // PURPOSE OF THIS SUBROUTINE:
    4796              :     // To calculate the modified Bessel Function from order 0 to BessFuncOrd
    4797              :     // BessFuncArg    ARGUMENT OF BESSEL FUNCTION
    4798              :     // BessFuncOrd    ORDER OF BESSEL FUNCTION, GREATER THAN OR EQUAL TO ZERO
    4799              :     // IBessFunc   RESULTANT VALUE OF I BESSEL FUNCTION
    4800              :     // ErrorCode  RESULTANT ERROR CODE:
    4801              :     //       ErrorCode = 0   NO ERROR
    4802              :     //       ErrorCode = 1   BessFuncOrd .LT. 0
    4803              :     //       ErrorCode = 2   BessFuncArg .LT. 0
    4804              :     //       ErrorCode = 3   IBessFunc .LT. 10**(-30),     IBessFunc IS SET TO 0
    4805              :     //       ErrorCode = 4   BessFuncArg .GT. BessFuncOrd & BessFuncArg .GT. 90,  IBessFunc IS SET TO 10**38
    4806              : 
    4807              :     // REFERENCES:
    4808              :     // First found in MODSIM.
    4809              : 
    4810              :     // USE STATEMENTS:
    4811              :     // na
    4812              : 
    4813              :     // Locals
    4814              :     // SUBROUTINE ARGUMENT DEFINITIONS:
    4815              : 
    4816              :     // SUBROUTINE PARAMETER DEFINITIONS:
    4817       180900 :     Real64 constexpr ErrorTol(1.0e-06);
    4818              : 
    4819              :     // INTERFACE BLOCK SPECIFICATIONS
    4820              :     // na
    4821              : 
    4822              :     // DERIVED TYPE DEFINITIONS
    4823              :     // na
    4824              : 
    4825              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4826              :     int LoopCount;
    4827              : 
    4828              :     Real64 FI;
    4829              :     Real64 FK;
    4830              :     Real64 TERM;
    4831              : 
    4832       180900 :     ErrorCode = 0;
    4833       180900 :     IBessFunc = 1.0;
    4834       180900 :     if (BessFuncArg == 0.0 && BessFuncOrd == 0) {
    4835            0 :         return;
    4836              :     }
    4837              : 
    4838       180900 :     if (BessFuncOrd < 0) {
    4839            0 :         ErrorCode = 1;
    4840            0 :         return;
    4841       180900 :     } else if (BessFuncArg < 0.0) {
    4842            0 :         ErrorCode = 2;
    4843            0 :         return;
    4844       180900 :     } else if (BessFuncArg > 12.0 && BessFuncArg > BessFuncOrd) {
    4845            0 :         if (BessFuncArg > 90.0) {
    4846            0 :             ErrorCode = 4;
    4847            0 :             IBessFunc = 1.0e30;
    4848            0 :             return;
    4849              :         }
    4850            0 :         TERM = 1.0;
    4851            0 :         IBessFunc = 1.0;
    4852            0 :         for (LoopCount = 1; LoopCount <= 30; ++LoopCount) { // Start of 1st LoopCount Loop
    4853            0 :             if (std::abs(TERM) <= std::abs(ErrorTol * IBessFunc)) {
    4854            0 :                 IBessFunc *= std::exp(BessFuncArg) / std::sqrt(2.0 * Constant::Pi * BessFuncArg);
    4855            0 :                 return;
    4856              :             }
    4857            0 :             TERM *= 0.125 / BessFuncArg * (pow_2(2 * LoopCount - 1) - 4 * BessFuncOrd * BessFuncOrd) / double(LoopCount);
    4858            0 :             IBessFunc += TERM;
    4859              :         } // End of 1st LoopCount loop
    4860              :     }
    4861              : 
    4862       180900 :     TERM = 1.0;
    4863       180900 :     if (BessFuncOrd > 0) {
    4864       241200 :         for (LoopCount = 1; LoopCount <= BessFuncOrd; ++LoopCount) { // Start of 2nd LoopCount Loop
    4865       120600 :             FI = LoopCount;
    4866       120600 :             if (std::abs(TERM) < 1.0e-30 * FI / (BessFuncArg * 2.0)) {
    4867            0 :                 ErrorCode = 3;
    4868            0 :                 IBessFunc = 0.0;
    4869            0 :                 return;
    4870              :             }
    4871       120600 :             TERM *= BessFuncArg / (2.0 * FI);
    4872              :         } // End of 2nd LoopCount loop
    4873              :     }
    4874              : 
    4875       180900 :     IBessFunc = TERM;
    4876      1132140 :     for (LoopCount = 1; LoopCount <= 1000; ++LoopCount) { // Start of 3rd LoopCount Loop
    4877      1132140 :         if (std::abs(TERM) <= std::abs(IBessFunc * ErrorTol)) {
    4878       180900 :             return;
    4879              :         }
    4880       951240 :         FK = LoopCount * (BessFuncOrd + LoopCount);
    4881       951240 :         TERM *= pow_2(BessFuncArg) / (4.0 * FK);
    4882       951240 :         IBessFunc += TERM;
    4883              :     } // End of  3rd LoopCount loop
    4884              : }
    4885              : 
    4886       180900 : void CalcKBesselFunc(Real64 const BessFuncArg, int const BessFuncOrd, Real64 &KBessFunc, int &ErrorCode)
    4887              : {
    4888              :     // SUBROUTINE INFORMATION:
    4889              :     //       AUTHOR   Unknown
    4890              :     //       DATE WRITTEN   Unknown
    4891              :     //       DATE REWRITTEN  April 1997 by Russell D. Taylor, Ph.D.
    4892              :     //       MODIFIED
    4893              :     //       RE-ENGINEERED
    4894              : 
    4895              :     // PURPOSE OF THIS SUBROUTINE:
    4896              :     // To calculate the K Bessel Function for a given argument and
    4897              :     // order
    4898              :     //  BessFuncArg    THE ARGUMENT OF THE K BESSEL FUNCTION DESIRED
    4899              :     //  BessFuncOrd    THE ORDER OF THE K BESSEL FUNCTION DESIRED
    4900              :     //  KBessFunc   THE RESULTANT K BESSEL FUNCTION
    4901              :     //  ErrorCode  RESULTANT ERROR CODE:
    4902              :     //        ErrorCode=0  NO ERROR
    4903              :     //        ErrorCode=1  BessFuncOrd IS NEGATIVE
    4904              :     //        ErrorCode=2  BessFuncArg IS ZERO OR NEGATIVE
    4905              :     //        ErrorCode=3  BessFuncArg .GT. 85, KBessFunc .LT. 10**-38; KBessFunc SET TO 0.
    4906              :     //        ErrorCode=4  KBessFunc .GT. 10**38; KBessFunc SET TO 10**38
    4907              :     // NOTE: BessFuncOrd MUST BE GREATER THAN OR EQUAL TO ZERO
    4908              :     // METHOD:
    4909              :     //  COMPUTES ZERO ORDER AND FIRST ORDER BESSEL FUNCTIONS USING
    4910              :     //  SERIES APPROXIMATIONS AND THEN COMPUTES BessFuncOrd TH ORDER FUNCTION
    4911              :     //  USING RECURRENCE RELATION.
    4912              :     //  RECURRENCE RELATION AND POLYNOMIAL APPROXIMATION TECHNIQUE
    4913              :     //  AS DESCRIBED BY A.J.M. HITCHCOCK, 'POLYNOMIAL APPROXIMATIONS
    4914              :     //  TO BESSEL FUNCTIONS OF ORDER ZERO AND ONE AND TO RELATED
    4915              :     //  FUNCTIONS,' M.T.A.C., V.11, 1957, PP. 86-88, AND G.BessFuncOrd. WATSON,
    4916              :     //  'A TREATISE ON THE THEORY OF BESSEL FUNCTIONS,' CAMBRIDGE
    4917              :     //  UNIVERSITY PRESS, 1958, P.62
    4918              : 
    4919              :     // USE STATEMENTS:
    4920              :     // na
    4921              : 
    4922              :     // Locals
    4923              :     // SUBROUTINE ARGUMENT DEFINITIONS:
    4924              : 
    4925              :     // SUBROUTINE PARAMETER DEFINITIONS:
    4926       180900 :     Real64 constexpr GJMAX(1.0e+38);
    4927              : 
    4928              :     // INTERFACE BLOCK SPECIFICATIONS
    4929              :     // na
    4930              : 
    4931              :     // DERIVED TYPE DEFINITIONS
    4932              :     // na
    4933              : 
    4934              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4935              :     int LoopCount;
    4936              :     bool StopLoop;
    4937              : 
    4938              :     Real64 FACT;
    4939              :     Real64 G0;
    4940              :     Real64 G1;
    4941              :     Real64 GJ;
    4942              :     Real64 HJ;
    4943       180900 :     Array1D<Real64> T(12);
    4944              :     Real64 X2J;
    4945              : 
    4946       180900 :     KBessFunc = 0.0;
    4947       180900 :     G0 = 0.0;
    4948       180900 :     GJ = 0.0;
    4949              : 
    4950       180900 :     if (BessFuncOrd < 0.0) {
    4951            0 :         ErrorCode = 1;
    4952            0 :         return;
    4953       180900 :     } else if (BessFuncArg <= 0.0) {
    4954            0 :         ErrorCode = 2;
    4955            0 :         return;
    4956       180900 :     } else if (BessFuncArg > 85.0) {
    4957            0 :         ErrorCode = 3;
    4958            0 :         KBessFunc = 0.0;
    4959            0 :         return;
    4960              :     }
    4961              : 
    4962       180900 :     ErrorCode = 0;
    4963              : 
    4964              :     //     Use polynomial approximation if BessFuncArg > 1.
    4965              : 
    4966       180900 :     if (BessFuncArg > 1.0) {
    4967       112439 :         T(1) = 1.0 / BessFuncArg;
    4968      1349268 :         for (LoopCount = 2; LoopCount <= 12; ++LoopCount) {
    4969      1236829 :             T(LoopCount) = T(LoopCount - 1) / BessFuncArg;
    4970              :         } // End of LoopCount Loop
    4971       112439 :         if (BessFuncOrd != 1) {
    4972              : 
    4973              :             //     Compute K0 using polynomial approximation
    4974              : 
    4975        65322 :             G0 = std::exp(-BessFuncArg) *
    4976        32661 :                  (1.2533141 - 0.1566642 * T(1) + 0.08811128 * T(2) - 0.09139095 * T(3) + 0.1344596 * T(4) - 0.2299850 * T(5) + 0.3792410 * T(6) -
    4977        32661 :                   0.5247277 * T(7) + 0.5575368 * T(8) - 0.4262633 * T(9) + 0.2184518 * T(10) - 0.06680977 * T(11) + 0.009189383 * T(12)) *
    4978        32661 :                  std::sqrt(1.0 / BessFuncArg);
    4979        32661 :             if (BessFuncOrd == 0) {
    4980        32661 :                 KBessFunc = G0;
    4981        32661 :                 return;
    4982              :             }
    4983              :         }
    4984              : 
    4985              :         //     Compute K1 using polynomial approximation
    4986              : 
    4987       159556 :         G1 = std::exp(-BessFuncArg) *
    4988        79778 :              (1.2533141 + 0.4699927 * T(1) - 0.1468583 * T(2) + 0.1280427 * T(3) - 0.1736432 * T(4) + 0.2847618 * T(5) - 0.4594342 * T(6) +
    4989        79778 :               0.6283381 * T(7) - 0.6632295 * T(8) + 0.5050239 * T(9) - 0.2581304 * T(10) + 0.07880001 * T(11) - 0.01082418 * T(12)) *
    4990        79778 :              std::sqrt(1.0 / BessFuncArg);
    4991        79778 :         if (BessFuncOrd == 1) {
    4992        79778 :             KBessFunc = G1;
    4993        79778 :             return;
    4994              :         }
    4995              :     } else {
    4996              : 
    4997              :         //     Use series expansion if BessFuncArg <= 1.
    4998              : 
    4999        68461 :         if (BessFuncOrd != 1) {
    5000              : 
    5001              :             //     Compute K0 using series expansion
    5002              : 
    5003        27639 :             G0 = -(0.5772157 + std::log(BessFuncArg / 2.0));
    5004        27639 :             X2J = 1.0;
    5005        27639 :             FACT = 1.0;
    5006        27639 :             HJ = 0.0;
    5007       193473 :             for (LoopCount = 1; LoopCount <= 6; ++LoopCount) {
    5008       165834 :                 X2J *= pow_2(BessFuncArg) / 4.0;
    5009       165834 :                 FACT *= pow_2(1.0 / double(LoopCount));
    5010       165834 :                 HJ += 1.0 / double(LoopCount);
    5011       165834 :                 G0 += X2J * FACT * (HJ - (0.5772157 + std::log(BessFuncArg / 2.0)));
    5012              :             } // End of LoopCount Loop
    5013        27639 :             if (BessFuncOrd == 0.0) {
    5014        27639 :                 KBessFunc = G0;
    5015        27639 :                 return;
    5016              :             }
    5017              :         }
    5018              : 
    5019              :         //     Compute K1 using series expansion
    5020              : 
    5021        40822 :         X2J = BessFuncArg / 2.0;
    5022        40822 :         FACT = 1.0;
    5023        40822 :         HJ = 1.0;
    5024        40822 :         G1 = 1.0 / BessFuncArg + X2J * (0.5 + (0.5772157 + std::log(BessFuncArg / 2.0)) - HJ);
    5025       326576 :         for (LoopCount = 2; LoopCount <= 8; ++LoopCount) {
    5026       285754 :             X2J *= pow_2(BessFuncArg) / 4.0;
    5027       285754 :             FACT *= pow_2(1.0 / double(LoopCount));
    5028       285754 :             HJ += 1.0 / double(LoopCount);
    5029       285754 :             G1 += X2J * FACT * (0.5 + ((0.5772157 + std::log(BessFuncArg / 2.0)) - HJ) * double(LoopCount));
    5030              :         } // End of LoopCount Loop
    5031        40822 :         if (BessFuncOrd == 1) {
    5032        40822 :             KBessFunc = G1;
    5033        40822 :             return;
    5034              :         }
    5035              :     }
    5036              : 
    5037              :     //     From K0 and K1 compute KN using recurrence relation
    5038              : 
    5039            0 :     LoopCount = 2;
    5040            0 :     StopLoop = false;
    5041            0 :     while (LoopCount <= BessFuncOrd && !StopLoop) {
    5042            0 :         GJ = 2.0 * (double(LoopCount) - 1.0) * G1 / BessFuncArg + G0;
    5043            0 :         if (GJ - GJMAX > 0.0) {
    5044            0 :             ErrorCode = 4;
    5045            0 :             GJ = GJMAX;
    5046            0 :             StopLoop = true;
    5047              :         } else {
    5048            0 :             G0 = G1;
    5049            0 :             G1 = GJ;
    5050            0 :             ++LoopCount;
    5051              :         }
    5052              :     } // End of LoopCount Loop
    5053            0 :     KBessFunc = GJ;
    5054       180900 : }
    5055              : 
    5056         1005 : void CalcPolynomCoef(EnergyPlusData &state, Array2<Real64> const &OrderedPair, Array1D<Real64> &PolynomCoef)
    5057              : {
    5058              :     // SUBROUTINE INFORMATION:
    5059              :     //       AUTHOR   Unknown
    5060              :     //       DATE WRITTEN   Unknown
    5061              :     //       DATE REWRITTEN  April 1997 by Russell D. Taylor, Ph.D.
    5062              :     //       MODIFIED
    5063              :     //       RE-ENGINEERED
    5064              : 
    5065              :     // PURPOSE OF THIS SUBROUTINE:
    5066              :     // Fits polynomial of order from 1 to MaxPolynomOrder to the
    5067              :     // ordered pairs of data points X,Y
    5068              : 
    5069              :     // USE STATEMENTS:
    5070              :     // na
    5071              : 
    5072              :     // Locals
    5073              :     // SUBROUTINE ARGUMENT DEFINITIONS:
    5074              : 
    5075              :     // SUBROUTINE PARAMETER DEFINITIONS:
    5076              :     // na
    5077              : 
    5078              :     // INTERFACE BLOCK SPECIFICATIONS
    5079              :     // na
    5080              : 
    5081              :     // DERIVED TYPE DEFINITIONS
    5082              :     // na
    5083              : 
    5084              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5085              :     bool Converged;
    5086              :     Real64 B;
    5087              :     int I;
    5088              :     int II;
    5089              :     int J;
    5090              :     int PolynomOrder;
    5091              :     int CurrentOrder;
    5092              :     int CurrentOrdPair;
    5093              :     Real64 S1;
    5094              :     Real64 S2;
    5095              : 
    5096         1005 :     auto &OrdPairSum = state.dataWaterCoils->OrdPairSum;
    5097              : 
    5098         1005 :     OrdPairSum = 0.0;
    5099         1005 :     OrdPairSum(1, 1) = WaterCoils::MaxOrderedPairs;
    5100         1005 :     PolynomCoef = 0.0;
    5101        61305 :     for (CurrentOrdPair = 1; CurrentOrdPair <= WaterCoils::MaxOrderedPairs; ++CurrentOrdPair) {
    5102        60300 :         OrdPairSum(2, 1) += OrderedPair(CurrentOrdPair, 1);
    5103        60300 :         OrdPairSum(3, 1) += OrderedPair(CurrentOrdPair, 1) * OrderedPair(CurrentOrdPair, 1);
    5104        60300 :         OrdPairSum(1, 2) += OrderedPair(CurrentOrdPair, 2);
    5105        60300 :         OrdPairSum(2, 2) += OrderedPair(CurrentOrdPair, 1) * OrderedPair(CurrentOrdPair, 2);
    5106              :     }
    5107         1005 :     PolynomOrder = 1;
    5108         1005 :     Converged = false;
    5109         5025 :     while (!Converged) {
    5110        18090 :         for (CurrentOrder = 1; CurrentOrder <= PolynomOrder + 1; ++CurrentOrder) {
    5111        68340 :             for (J = 1; J <= PolynomOrder + 1; ++J) {
    5112        54270 :                 state.dataWaterCoils->OrdPairSumMatrix(J, CurrentOrder) = OrdPairSum(J - 1 + CurrentOrder, 1);
    5113              :             } // End of J loop
    5114        14070 :             state.dataWaterCoils->OrdPairSumMatrix(PolynomOrder + 2, CurrentOrder) = OrdPairSum(CurrentOrder, 2);
    5115              :         } // End of CurrentOrder loop
    5116              : 
    5117        18090 :         for (CurrentOrder = 1; CurrentOrder <= PolynomOrder + 1; ++CurrentOrder) {
    5118        14070 :             state.dataWaterCoils->OrdPairSumMatrix(CurrentOrder, PolynomOrder + 2) = -1.0;
    5119        48240 :             for (J = CurrentOrder + 1; J <= PolynomOrder + 2; ++J) {
    5120        34170 :                 state.dataWaterCoils->OrdPairSumMatrix(J, PolynomOrder + 2) = 0.0;
    5121              :             } // End of J loop
    5122              : 
    5123        68340 :             for (II = 2; II <= PolynomOrder + 2; ++II) {
    5124       193965 :                 for (J = CurrentOrder + 1; J <= PolynomOrder + 2; ++J) {
    5125       279390 :                     state.dataWaterCoils->OrdPairSumMatrix(J, II) -= state.dataWaterCoils->OrdPairSumMatrix(J, 1) *
    5126       139695 :                                                                      state.dataWaterCoils->OrdPairSumMatrix(CurrentOrder, II) /
    5127       139695 :                                                                      state.dataWaterCoils->OrdPairSumMatrix(CurrentOrder, 1);
    5128              :                 } // End of J loop
    5129              :             } // End of II loop
    5130        68340 :             for (II = 1; II <= PolynomOrder + 1; ++II) {
    5131       193965 :                 for (J = CurrentOrder + 1; J <= PolynomOrder + 2; ++J) {
    5132       139695 :                     state.dataWaterCoils->OrdPairSumMatrix(J, II) = state.dataWaterCoils->OrdPairSumMatrix(J, II + 1);
    5133              :                 } // End of J loop
    5134              :             } // End of II loop
    5135              :         } // End of CurrentOrder loop
    5136              : 
    5137         4020 :         S2 = 0.0;
    5138       245220 :         for (CurrentOrdPair = 1; CurrentOrdPair <= WaterCoils::MaxOrderedPairs; ++CurrentOrdPair) {
    5139       241200 :             S1 = state.dataWaterCoils->OrdPairSumMatrix(PolynomOrder + 2, 1);
    5140       241200 :             auto const OrderedPair1C = OrderedPair(CurrentOrdPair, 1); // (AUTO_OK_OBJ)
    5141       241200 :             Real64 OrderedPair1C_pow = 1.0;
    5142       844200 :             for (CurrentOrder = 1; CurrentOrder <= PolynomOrder; ++CurrentOrder) {
    5143       603000 :                 OrderedPair1C_pow *= OrderedPair1C;
    5144       603000 :                 S1 += state.dataWaterCoils->OrdPairSumMatrix(PolynomOrder + 2, CurrentOrder + 1) * OrderedPair1C_pow;
    5145              :             } // End of CurrentOrder loop
    5146       241200 :             S2 += (S1 - OrderedPair(CurrentOrdPair, 2)) * (S1 - OrderedPair(CurrentOrdPair, 2));
    5147              :         } // End of CurrentOrdPair loop
    5148         4020 :         B = WaterCoils::MaxOrderedPairs - (PolynomOrder + 1);
    5149         4020 :         if (S2 > 0.0001) {
    5150         3029 :             S2 = std::sqrt(S2 / B);
    5151              :         }
    5152        18090 :         for (CurrentOrder = 1; CurrentOrder <= PolynomOrder + 1; ++CurrentOrder) {
    5153        14070 :             PolynomCoef(CurrentOrder) = state.dataWaterCoils->OrdPairSumMatrix(PolynomOrder + 2, CurrentOrder);
    5154              :         } // End of CurrentOrder loop
    5155              : 
    5156         4020 :         if ((PolynomOrder - WaterCoils::MaxPolynomOrder < 0) && (S2 - WaterCoils::PolyConvgTol > 0.0)) {
    5157         3015 :             ++PolynomOrder;
    5158         3015 :             J = 2 * PolynomOrder;
    5159         3015 :             OrdPairSum(J, 1) = OrdPairSum(J + 1, 1) = 0.0;
    5160         3015 :             auto OrdPairSum2P = OrdPairSum(PolynomOrder + 1, 2) = 0.0; // (AUTO_OK_OBJ)
    5161       183915 :             for (I = 1; I <= WaterCoils::MaxOrderedPairs; ++I) {
    5162       180900 :                 auto const OrderedPair1I = OrderedPair(I, 1); // (AUTO_OK_OBJ)
    5163       180900 :                 Real64 OrderedPair_pow = std::pow(OrderedPair1I, J - 1);
    5164       180900 :                 OrdPairSum(J, 1) += OrderedPair_pow;
    5165       180900 :                 OrderedPair_pow *= OrderedPair1I;
    5166       180900 :                 OrdPairSum(J + 1, 1) += OrderedPair_pow;
    5167       180900 :                 OrdPairSum2P += OrderedPair(I, 2) * std::pow(OrderedPair1I, PolynomOrder);
    5168              :             }
    5169         3015 :             OrdPairSum(PolynomOrder + 1, 2) = OrdPairSum2P;
    5170         3015 :         } else {
    5171         1005 :             Converged = true;
    5172              :         }
    5173              :     }
    5174         1005 : }
    5175              : 
    5176              : // Iterate Routine for Cooling Coil
    5177              : 
    5178      4052106 : void CoilAreaFracIter(Real64 &NewSurfAreaWetFrac,       // Out Value of variable
    5179              :                       Real64 const SurfAreaFracCurrent, // Driver Value
    5180              :                       Real64 const ErrorCurrent,        // Objective Function
    5181              :                       Real64 &SurfAreaFracPrevious,     // First Previous value of Surf Area Fraction
    5182              :                       Real64 &ErrorPrevious,            // First Previous value of error
    5183              :                       Real64 &SurfAreaFracLast,         // Second Previous value of Surf Area Fraction
    5184              :                       Real64 &ErrorLast,                // Second Previous value of error
    5185              :                       int const IterNum,                // Number of Iterations
    5186              :                       int &icvg                         // Iteration convergence flag
    5187              : )
    5188              : {
    5189              :     // FUNCTION INFORMATION:
    5190              :     // AUTHOR         Rahul Chillar
    5191              :     // DATE WRITTEN   June 2004
    5192              : 
    5193              :     // PURPOSE OF THIS FUNCTION:
    5194              :     // Iterately solves for the value of SurfAreaWetFraction for the Cooling Coil.
    5195              : 
    5196              :     // METHODOLOGY EMPLOYED:
    5197              :     // First function generates 2 sets of guess points by perturbation and subsequently
    5198              :     // by Linear Fit and using the generated points calculates coeffecients for Quadratic
    5199              :     // fit to predict the next value of surface area wet fraction.
    5200              : 
    5201              :     // REFERENCES:
    5202              :     // ME 423 Design of Thermal Systems Class Notes.UIUC. W.F.Stoecker
    5203              : 
    5204              :     // FUNCTION PARAMETER DEFINITIONS:
    5205      4052106 :     Real64 constexpr Tolerance(1.e-5);         // Relative error tolerance
    5206      4052106 :     Real64 constexpr PerturbSurfAreaFrac(0.1); // Perturbation applied to Surf Fraction to initialize iteration
    5207      4052106 :     Real64 constexpr SmallNum(1.e-9);          // Small Number
    5208              : 
    5209              :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5210              :     Real64 check;             // Validity Check for moving to Quad Solution
    5211              :     Real64 QuadCoefThree;     // Term under radical in quadratic solution
    5212              :     Real64 QuadCoefOne;       // Term under radical in quadratic solution
    5213              :     Real64 QuadCoefTwo;       // Term under radical in quadratic solution
    5214              :     Real64 Slope;             // Slope for linear fit
    5215              :     Real64 SurfAreaFracOther; // Intermediate Value of Surf Area
    5216              :     int mode;                 // Linear/ perturbation option
    5217              : 
    5218              :     // Convergence Check  by comparing previous and current value of surf area fraction
    5219      4052106 :     if ((std::abs(SurfAreaFracCurrent - SurfAreaFracPrevious) < Tolerance * max(std::abs(SurfAreaFracCurrent), SmallNum) && IterNum != 1) ||
    5220              :         ErrorCurrent == 0.0) {
    5221              :         // Setting value for surface area fraction for coil
    5222       709695 :         NewSurfAreaWetFrac = SurfAreaFracCurrent;
    5223       709695 :         icvg = 1; // Convergance Flag
    5224       709695 :         return;
    5225              :     }
    5226              : 
    5227              :     // If Icvg = 0 , it has not converged.By perturbation for getting second set of
    5228              :     // data (mode=1), Getting Third set of data by performing a  linear fit(Mode=2).
    5229              :     // Now using the above 3 points generated by perturbation and Linear Fit to perform
    5230              :     // a quadratic fit.This will happen after second iteration only.
    5231      3342411 :     icvg = 0; // Convergance flag = false
    5232              :     // For First Iteration Start with perturbation, For second iteration start with linear fit
    5233              :     // from the previous two values
    5234      3342411 :     mode = IterNum;
    5235              : 
    5236        41988 : Label10:;
    5237      3384399 :     if (mode == 1) {
    5238              : 
    5239              :         // FirstGuess Set of Points provided by perturbation
    5240       709695 :         if (std::abs(SurfAreaFracCurrent) > SmallNum) {
    5241       709695 :             NewSurfAreaWetFrac = SurfAreaFracCurrent * (1.0 + PerturbSurfAreaFrac);
    5242              :         } else {
    5243            0 :             NewSurfAreaWetFrac = PerturbSurfAreaFrac;
    5244              :         }
    5245              : 
    5246              :         // Second set of values being calculated from the first set of values (incoming & perturb)
    5247      2674704 :     } else if (mode == 2) {
    5248              : 
    5249              :         // Calculating Slope for interpolating to the New Point (Simple Linear Extrapolation)
    5250       751683 :         Slope = (ErrorPrevious - ErrorCurrent) / (SurfAreaFracPrevious - SurfAreaFracCurrent);
    5251              :         // Error Check for value or Slope
    5252       751683 :         if (Slope == 0.0) {
    5253            0 :             mode = 1; // Go back to Perturbation
    5254            0 :             goto Label10;
    5255              :         }
    5256              :         // Guessing New Value for Surface Area Fraction
    5257       751683 :         NewSurfAreaWetFrac = SurfAreaFracCurrent - ErrorCurrent / Slope;
    5258              :     } else {
    5259              : 
    5260              :         // Check for Quadratic Fit possible here ,Previous value of surf area fraction
    5261              :         // equals current value then Try linear fit for another point.
    5262      1923021 :         if (SurfAreaFracCurrent == SurfAreaFracPrevious) {
    5263              :             // Assign Value of previous point to Last Variable for storing
    5264              :             // Go back and calculate new value for Previous.
    5265            0 :             SurfAreaFracPrevious = SurfAreaFracLast;
    5266            0 :             ErrorPrevious = ErrorLast;
    5267            0 :             mode = 2;
    5268            0 :             goto Label10;
    5269      1923021 :         } else if (SurfAreaFracCurrent == SurfAreaFracLast) {
    5270              :             // Calculate another value using Linear Fit.
    5271        25727 :             mode = 2;
    5272        25727 :             goto Label10;
    5273              :         }
    5274              : 
    5275              :         // Now We have enough previous points to calculate coefficients and
    5276              :         // perform a quadratic fit for new guess value of surface area fraction
    5277              : 
    5278              :         // Calculating First Coefficients for Quadratic Curve Fit
    5279      1897294 :         QuadCoefThree = ((ErrorLast - ErrorCurrent) / (SurfAreaFracLast - SurfAreaFracCurrent) -
    5280      1897294 :                          (ErrorPrevious - ErrorCurrent) / (SurfAreaFracPrevious - SurfAreaFracCurrent)) /
    5281      1897294 :                         (SurfAreaFracLast - SurfAreaFracPrevious);
    5282              :         // Calculating Second Coefficients for Quadratic Curve Fit
    5283      1897294 :         QuadCoefTwo = (ErrorPrevious - ErrorCurrent) / (SurfAreaFracPrevious - SurfAreaFracCurrent) -
    5284      1897294 :                       (SurfAreaFracPrevious + SurfAreaFracCurrent) * QuadCoefThree;
    5285              : 
    5286              :         // Calculating Third Coefficients for Quadratic Curve Fit
    5287      1897294 :         QuadCoefOne = ErrorCurrent - (QuadCoefTwo + QuadCoefThree * SurfAreaFracCurrent) * SurfAreaFracCurrent;
    5288              : 
    5289              :         // Check for validity of coefficients , if not REAL(r64) ,Then fit is linear
    5290      1897294 :         if (std::abs(QuadCoefThree) < 1.E-10) {
    5291            0 :             mode = 2; // going to Linear mode, due to colinear points.
    5292            0 :             goto Label10;
    5293              :         }
    5294              : 
    5295              :         // If value of Quadratic coefficients not suitable enought due to round off errors
    5296              :         // to predict new point go to linear fit and acertain new values for the coefficients.
    5297      1897294 :         if (std::abs((QuadCoefOne + (QuadCoefTwo + QuadCoefThree * SurfAreaFracPrevious) * SurfAreaFracPrevious - ErrorPrevious) / ErrorPrevious) >
    5298              :             1.E-4) {
    5299            3 :             mode = 2; // go to linear mode
    5300            3 :             goto Label10;
    5301              :         }
    5302              : 
    5303              :         // Validity Check for Imaginary roots, In this case go back to linear fit.
    5304      1897291 :         check = pow_2(QuadCoefTwo) - 4.0 * QuadCoefOne * QuadCoefThree;
    5305              :         // Imaginary Root Exist
    5306      1897291 :         if (check < 0) {
    5307        16258 :             mode = 2;
    5308        16258 :             goto Label10;
    5309      1881033 :         } else if (check > 0) {
    5310              :             // real unequal roots exist, Determine the roots nearest to most recent guess
    5311      1881016 :             NewSurfAreaWetFrac = (-QuadCoefTwo + std::sqrt(check)) / QuadCoefThree / 2.0;
    5312      1881016 :             SurfAreaFracOther = -NewSurfAreaWetFrac - QuadCoefTwo / QuadCoefThree;
    5313              :             // Assigning value to Surface Area Fraction with recent
    5314      1881016 :             if (std::abs(NewSurfAreaWetFrac - SurfAreaFracCurrent) > std::abs(SurfAreaFracOther - SurfAreaFracCurrent)) {
    5315         3279 :                 NewSurfAreaWetFrac = SurfAreaFracOther;
    5316              :             }
    5317              :         } else {
    5318              :             // The roots are real, one solution exists.
    5319           17 :             NewSurfAreaWetFrac = -QuadCoefTwo / QuadCoefThree / 2;
    5320              :         }
    5321              :     }
    5322              : 
    5323      3342411 :     if (mode < 3) {
    5324              :         // No valid previous points to eliminate, since it just has 2 points.
    5325              :         // Loading previous values into last
    5326      1461378 :         SurfAreaFracLast = SurfAreaFracPrevious;
    5327      1461378 :         ErrorLast = ErrorPrevious;
    5328              :         // Loading Current Values into previous
    5329      1461378 :         SurfAreaFracPrevious = SurfAreaFracCurrent;
    5330      1461378 :         ErrorPrevious = ErrorCurrent;
    5331              :     } else {
    5332              : 
    5333              :         // Elimination the most distance previous point from the answer based on sign and
    5334              :         // magnitute of the error. Keeping Current Point
    5335      1881033 :         if (ErrorPrevious * ErrorCurrent > 0 && ErrorLast * ErrorCurrent > 0) {
    5336              :             // If sign are same , simply eliminate the one with biggest error value.
    5337       333858 :             if (std::abs(ErrorLast) > std::abs(ErrorPrevious)) {
    5338              :                 // Eliminating Last Value
    5339        97898 :                 SurfAreaFracLast = SurfAreaFracPrevious;
    5340        97898 :                 ErrorLast = ErrorPrevious;
    5341              :             }
    5342              :         } else {
    5343              :             // If signs are different eliminate previous error with same sign as current error
    5344      1645073 :             if (ErrorLast * ErrorCurrent > 0) {
    5345              :                 // Previous Loaded to Last
    5346       516297 :                 SurfAreaFracLast = SurfAreaFracPrevious;
    5347       516297 :                 ErrorLast = ErrorPrevious;
    5348              :             }
    5349              :         }
    5350              :         // Current Loaded into previous.
    5351      1881033 :         SurfAreaFracPrevious = SurfAreaFracCurrent;
    5352      1881033 :         ErrorPrevious = ErrorCurrent;
    5353              :     }
    5354              : }
    5355              : 
    5356       274435 : void CheckWaterCoilSchedule(EnergyPlusData &state, std::string_view CompName, Real64 &Value, int &CompIndex)
    5357              : {
    5358              : 
    5359              :     // SUBROUTINE INFORMATION:
    5360              :     //       AUTHOR         Linda Lawrie
    5361              :     //       DATE WRITTEN   October 2005
    5362              : 
    5363              :     // Obtains and Allocates WaterCoil related parameters from input file
    5364       274435 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) { // First time subroutine has been entered
    5365            0 :         GetWaterCoilInput(state);
    5366            0 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    5367              :     }
    5368              : 
    5369       274435 :     int CoilNum = 0;
    5370              :     // Find the correct Coil number
    5371       274435 :     if (CompIndex == 0) {
    5372            8 :         CoilNum = Util::FindItemInList(CompName, state.dataWaterCoils->WaterCoil);
    5373            8 :         if (CoilNum == 0) {
    5374            0 :             ShowFatalError(state, format("CheckWaterCoilSchedule: Coil not found={}", CompName));
    5375              :         }
    5376            8 :         CompIndex = CoilNum;
    5377            8 :         Value = state.dataWaterCoils->WaterCoil(CoilNum).availSched->getCurrentVal(); // not scheduled?
    5378              :     } else {
    5379       274427 :         CoilNum = CompIndex;
    5380       274427 :         if (CoilNum > state.dataWaterCoils->NumWaterCoils || CoilNum < 1) {
    5381            0 :             ShowFatalError(state,
    5382            0 :                            format("CheckWaterCoilSchedule: Invalid CompIndex passed={}, Number of Heating Coils={}, Coil name={}",
    5383              :                                   CoilNum,
    5384            0 :                                   state.dataWaterCoils->NumWaterCoils,
    5385              :                                   CompName));
    5386              :         }
    5387       274427 :         auto const &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    5388       274427 :         if (CompName != waterCoil.Name) {
    5389            0 :             ShowFatalError(state,
    5390            0 :                            format("CheckWaterCoilSchedule: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
    5391              :                                   CoilNum,
    5392              :                                   CompName,
    5393            0 :                                   waterCoil.Name));
    5394              :         }
    5395       274427 :         Value = waterCoil.availSched->getCurrentVal(); // not scheduled?
    5396              :     }
    5397       274435 : }
    5398              : 
    5399          167 : Real64 GetCoilMaxWaterFlowRate(EnergyPlusData &state,
    5400              :                                std::string_view CoilType,   // must match coil types in this module
    5401              :                                std::string const &CoilName, // must match coil names for the coil type
    5402              :                                bool &ErrorsFound            // set to true if problem
    5403              : )
    5404              : {
    5405              : 
    5406              :     // FUNCTION INFORMATION:
    5407              :     //       AUTHOR         Linda Lawrie
    5408              :     //       DATE WRITTEN   November 2006
    5409              : 
    5410              :     // PURPOSE OF THIS FUNCTION:
    5411              :     // This function looks up the max water flow rate for the given coil and returns it.  If
    5412              :     // incorrect coil type or name is given, ErrorsFound is returned as true and capacity is returned
    5413              :     // as negative.
    5414              : 
    5415              :     // Return value
    5416              :     Real64 MaxWaterFlowRate; // returned max water flow rate of matched coil
    5417              : 
    5418              :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5419              : 
    5420              :     // Obtains and Allocates WaterCoil related parameters from input file
    5421          167 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) { // First time subroutine has been entered
    5422            2 :         GetWaterCoilInput(state);
    5423            2 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    5424              :     }
    5425              : 
    5426          167 :     int WhichCoil = 0;
    5427          253 :     if (Util::SameString(CoilType, "Coil:Heating:Water") || Util::SameString(CoilType, "Coil:Cooling:Water:DetailedGeometry") ||
    5428          253 :         Util::SameString(CoilType, "Coil:Cooling:Water")) {
    5429          167 :         WhichCoil = Util::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
    5430          167 :         if (WhichCoil != 0) {
    5431              :             // coil does not specify MaxWaterFlowRate
    5432          167 :             MaxWaterFlowRate = state.dataWaterCoils->WaterCoil(WhichCoil).MaxWaterVolFlowRate;
    5433              :         }
    5434              :     } else {
    5435            0 :         WhichCoil = 0;
    5436              :     }
    5437              : 
    5438          167 :     if (WhichCoil == 0) {
    5439            0 :         ShowSevereError(state, format("GetCoilMaxWaterFlowRate: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    5440            0 :         ShowContinueError(state, "... Max Water Flow rate returned as -1000.");
    5441            0 :         ErrorsFound = true;
    5442            0 :         MaxWaterFlowRate = -1000.0;
    5443              :     }
    5444              : 
    5445          167 :     return MaxWaterFlowRate;
    5446              : }
    5447              : 
    5448           24 : int GetCoilInletNode(EnergyPlusData &state,
    5449              :                      std::string_view CoilType,   // must match coil types in this module
    5450              :                      std::string const &CoilName, // must match coil names for the coil type
    5451              :                      bool &ErrorsFound            // set to true if problem
    5452              : )
    5453              : {
    5454              : 
    5455              :     // FUNCTION INFORMATION:
    5456              :     //       AUTHOR         R. Raustad
    5457              :     //       DATE WRITTEN   March 2007
    5458              : 
    5459              :     // PURPOSE OF THIS FUNCTION:
    5460              :     // This function looks up the given coil and returns the inlet node number.  If
    5461              :     // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    5462              :     // as zero.
    5463              : 
    5464              :     // Obtains and Allocates DXCoils
    5465           24 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
    5466            0 :         GetWaterCoilInput(state);
    5467            0 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    5468              :     }
    5469              : 
    5470           24 :     int NodeNumber = 0;
    5471           24 :     int WhichCoil = 0;
    5472           33 :     if (Util::SameString(CoilType, "Coil:Heating:Water") || Util::SameString(CoilType, "Coil:Cooling:Water:DetailedGeometry") ||
    5473           33 :         Util::SameString(CoilType, "Coil:Cooling:Water")) {
    5474           24 :         WhichCoil = Util::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
    5475           24 :         if (WhichCoil != 0) {
    5476           24 :             NodeNumber = state.dataWaterCoils->WaterCoil(WhichCoil).AirInletNodeNum;
    5477              :         }
    5478              :     } else {
    5479            0 :         WhichCoil = 0;
    5480              :     }
    5481              : 
    5482           24 :     if (WhichCoil == 0) {
    5483            0 :         ShowSevereError(state, format("GetCoilInletNode: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    5484            0 :         ErrorsFound = true;
    5485            0 :         NodeNumber = 0;
    5486              :     }
    5487              : 
    5488           24 :     return NodeNumber;
    5489              : }
    5490              : 
    5491           30 : int GetCoilOutletNode(EnergyPlusData &state,
    5492              :                       std::string_view CoilType,   // must match coil types in this module
    5493              :                       std::string const &CoilName, // must match coil names for the coil type
    5494              :                       bool &ErrorsFound            // set to true if problem
    5495              : )
    5496              : {
    5497              : 
    5498              :     // FUNCTION INFORMATION:
    5499              :     //       AUTHOR         R. Raustad
    5500              :     //       DATE WRITTEN   March 2007
    5501              : 
    5502              :     // PURPOSE OF THIS FUNCTION:
    5503              :     // This function looks up the given coil and returns the inlet node number.  If
    5504              :     // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    5505              :     // as zero.
    5506              : 
    5507              :     // Obtains and Allocates DXCoils
    5508           30 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
    5509            0 :         GetWaterCoilInput(state);
    5510            0 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    5511              :     }
    5512              : 
    5513           30 :     int WhichCoil = 0;
    5514           30 :     int NodeNumber = 0; // returned node number of matched coil
    5515           37 :     if (Util::SameString(CoilType, "Coil:Heating:Water") || Util::SameString(CoilType, "Coil:Cooling:Water:DetailedGeometry") ||
    5516           37 :         Util::SameString(CoilType, "Coil:Cooling:Water")) {
    5517           30 :         WhichCoil = Util::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
    5518           30 :         if (WhichCoil != 0) {
    5519           30 :             NodeNumber = state.dataWaterCoils->WaterCoil(WhichCoil).AirOutletNodeNum;
    5520              :         }
    5521              :     } else {
    5522            0 :         WhichCoil = 0;
    5523              :     }
    5524              : 
    5525           30 :     if (WhichCoil == 0) {
    5526            0 :         ShowSevereError(
    5527              :             state,
    5528            0 :             format("GetCoilOutletNode: Could not find Coil, Type=\"{}\" Name=\"{}\" when accessing coil outlet node number.", CoilType, CoilName));
    5529            0 :         ErrorsFound = true;
    5530            0 :         NodeNumber = 0;
    5531              :     }
    5532              : 
    5533           30 :     return NodeNumber;
    5534              : }
    5535              : 
    5536         5402 : int GetCoilWaterInletNode(EnergyPlusData &state,
    5537              :                           std::string_view CoilType,   // must match coil types in this module
    5538              :                           std::string const &CoilName, // must match coil names for the coil type
    5539              :                           bool &ErrorsFound            // set to true if problem
    5540              : )
    5541              : {
    5542              : 
    5543              :     // FUNCTION INFORMATION:
    5544              :     //       AUTHOR         R. Raustad
    5545              :     //       DATE WRITTEN   July 2007
    5546              : 
    5547              :     // PURPOSE OF THIS FUNCTION:
    5548              :     // This function looks up the given coil and returns the inlet water control node number.  If
    5549              :     // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    5550              :     // as zero.
    5551              : 
    5552              :     // Obtains and Allocates DXCoils
    5553         5402 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
    5554           39 :         GetWaterCoilInput(state);
    5555           39 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    5556              :     }
    5557              : 
    5558         5402 :     int NodeNumber = 0; // returned node number of matched coil
    5559         5402 :     int WhichCoil = 0;
    5560         5838 :     if (Util::SameString(CoilType, "Coil:Heating:Water") || Util::SameString(CoilType, "Coil:Cooling:Water:DetailedGeometry") ||
    5561         5838 :         Util::SameString(CoilType, "Coil:Cooling:Water")) {
    5562         5402 :         WhichCoil = Util::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
    5563         5402 :         if (WhichCoil != 0) {
    5564         5402 :             NodeNumber = state.dataWaterCoils->WaterCoil(WhichCoil).WaterInletNodeNum;
    5565              :         }
    5566              :     } else {
    5567            0 :         WhichCoil = 0;
    5568              :     }
    5569              : 
    5570         5402 :     if (WhichCoil == 0) {
    5571            0 :         ShowSevereError(state, format("GetCoilWaterInletNode: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    5572            0 :         ErrorsFound = true;
    5573            0 :         NodeNumber = 0;
    5574              :     }
    5575              : 
    5576         5402 :     return NodeNumber;
    5577              : }
    5578              : 
    5579         2182 : int GetCoilWaterOutletNode(EnergyPlusData &state,
    5580              :                            std::string_view CoilType,   // must match coil types in this module
    5581              :                            std::string const &CoilName, // must match coil names for the coil type
    5582              :                            bool &ErrorsFound            // set to true if problem
    5583              : )
    5584              : {
    5585              : 
    5586              :     // FUNCTION INFORMATION:
    5587              :     //       AUTHOR         R. Raustad
    5588              :     //       DATE WRITTEN   July 2007
    5589              : 
    5590              :     // PURPOSE OF THIS FUNCTION:
    5591              :     // This function looks up the given coil and returns the outlet water node number.  If
    5592              :     // incorrect coil type or name is given, ErrorsFound is returned as true and node number is returned
    5593              :     // as zero.
    5594              : 
    5595              :     // Obtains and Allocates DXCoils
    5596         2182 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
    5597            0 :         GetWaterCoilInput(state);
    5598            0 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    5599              :     }
    5600              : 
    5601         2182 :     int NodeNumber = 0; // returned node number of matched coil
    5602         2182 :     int WhichCoil = 0;
    5603         2279 :     if (Util::SameString(CoilType, "Coil:Heating:Water") || Util::SameString(CoilType, "Coil:Cooling:Water:DetailedGeometry") ||
    5604         2279 :         Util::SameString(CoilType, "Coil:Cooling:Water")) {
    5605         2182 :         WhichCoil = Util::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
    5606         2182 :         if (WhichCoil != 0) {
    5607         2182 :             NodeNumber = state.dataWaterCoils->WaterCoil(WhichCoil).WaterOutletNodeNum;
    5608              :         }
    5609              :     } else {
    5610            0 :         WhichCoil = 0;
    5611              :     }
    5612              : 
    5613         2182 :     if (WhichCoil == 0) {
    5614            0 :         ShowSevereError(state, format("GetCoilWaterOutletNode: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    5615            0 :         ErrorsFound = true;
    5616            0 :         NodeNumber = 0;
    5617              :     }
    5618              : 
    5619         2182 :     return NodeNumber;
    5620              : }
    5621              : 
    5622         3102 : void SetCoilDesFlow(EnergyPlusData &state,
    5623              :                     std::string_view CoilType,   // must match coil types in this module
    5624              :                     std::string const &CoilName, // must match coil names for the coil type
    5625              :                     Real64 const CoilDesFlow,    // coil volumetric air flow rate [m3/s]
    5626              :                     bool &ErrorsFound            // set to true if problem
    5627              : )
    5628              : {
    5629              : 
    5630              :     // SUBROUTINE INFORMATION:
    5631              :     //       AUTHOR         Fred Buhl
    5632              :     //       DATE WRITTEN   May 2009
    5633              : 
    5634              :     // PURPOSE OF THIS SUBROUTINE:
    5635              :     // This routine is designed to set the design air volume flow rate in the
    5636              :     // water coil data structure. Some of the coil types do not have this datum as
    5637              :     // an input parameter and it is needed for calculating capacity for output reporting.
    5638              : 
    5639         3102 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) { // First time subroutine has been entered
    5640           11 :         GetWaterCoilInput(state);
    5641           11 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    5642              :     }
    5643              : 
    5644         3286 :     if (Util::SameString(CoilType, "Coil:Heating:Water") || Util::SameString(CoilType, "Coil:Cooling:Water:DetailedGeometry") ||
    5645         3286 :         Util::SameString(CoilType, "Coil:Cooling:Water")) {
    5646         3012 :         int WhichCoil = Util::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
    5647         3012 :         if (WhichCoil != 0) {
    5648         3012 :             if (state.dataWaterCoils->WaterCoil(WhichCoil).DesAirVolFlowRate <= 0.0) {
    5649         3003 :                 state.dataWaterCoils->WaterCoil(WhichCoil).DesAirVolFlowRate = CoilDesFlow;
    5650              :             } else {
    5651              :                 // WaterCoil(WhichCoil).DesAirVolFlowRate = CoilDesFlow;
    5652              :             }
    5653              :         } else {
    5654            0 :             ShowSevereError(state, format("GetCoilMaxWaterFlowRate: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    5655            0 :             ErrorsFound = true;
    5656              :         }
    5657              :     }
    5658         3102 : }
    5659              : 
    5660            0 : Real64 GetWaterCoilDesAirFlow(EnergyPlusData &state,
    5661              :                               std::string const &CoilType, // must match coil types in this module
    5662              :                               std::string const &CoilName, // must match coil names for the coil type
    5663              :                               bool &ErrorsFound            // set to true if problem
    5664              : )
    5665              : {
    5666              : 
    5667              :     // SUBROUTINE INFORMATION:
    5668              :     //       AUTHOR         Fred Buhl
    5669              :     //       DATE WRITTEN   May 2009
    5670              : 
    5671              :     // PURPOSE OF THIS SUBROUTINE:
    5672              :     // This routine is designed to set the design air volume flow rate in the
    5673              :     // water coil data structure. Some of the coil types do not have this datum as
    5674              :     // an input parameter and it is needed for calculating capacity for output reporting.
    5675              : 
    5676            0 :     Real64 CoilDesAirFlow = 0.0;
    5677              : 
    5678            0 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) { // First time subroutine has been entered
    5679            0 :         GetWaterCoilInput(state);
    5680            0 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    5681              :     }
    5682              : 
    5683            0 :     if (Util::SameString(CoilType, "Coil:Cooling:Water")) {
    5684            0 :         int WhichCoil = Util::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
    5685            0 :         if (WhichCoil != 0) {
    5686            0 :             CoilDesAirFlow = state.dataWaterCoils->WaterCoil(WhichCoil).DesAirVolFlowRate;
    5687              :         } else {
    5688            0 :             ShowSevereError(state, format("GetWaterCoilDesAirFlowRate: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    5689            0 :             ErrorsFound = true;
    5690              :         }
    5691              :     } else {
    5692            0 :         ShowSevereError(state, format("GetWaterCoilDesAirFlowRate: Funciton not valid for Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    5693            0 :         ErrorsFound = true;
    5694              :     }
    5695              : 
    5696            0 :     return CoilDesAirFlow;
    5697              : }
    5698              : 
    5699          902 : void CheckActuatorNode(EnergyPlusData &state,
    5700              :                        int const ActuatorNodeNum,                    // input actuator node number
    5701              :                        DataPlant::PlantEquipmentType &WaterCoilType, // Cooling or Heating or 0
    5702              :                        bool &NodeNotFound                            // true if matching water inlet node not found
    5703              : )
    5704              : {
    5705              : 
    5706              :     // SUBROUTINE INFORMATION:
    5707              :     //       AUTHOR         Fred Buhl
    5708              :     //       DATE WRITTEN   January 2009
    5709              : 
    5710              :     // PURPOSE OF THIS FUNCTION:
    5711              :     // This subroutine checks that the input actuator node number is matched by
    5712              :     // the water inlet node number of some water coil
    5713              : 
    5714              :     // Obtains and Allocates DXCoils
    5715          902 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
    5716            0 :         GetWaterCoilInput(state);
    5717            0 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    5718              :     }
    5719              : 
    5720          902 :     WaterCoilType = DataPlant::PlantEquipmentType::Invalid;
    5721          902 :     NodeNotFound = true;
    5722        22548 :     for (int CoilNum = 1; CoilNum <= state.dataWaterCoils->NumWaterCoils; ++CoilNum) {
    5723        22548 :         auto const &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    5724        22548 :         if (waterCoil.WaterInletNodeNum == ActuatorNodeNum) {
    5725          902 :             WaterCoilType = waterCoil.WaterCoilType;
    5726          902 :             NodeNotFound = false;
    5727          902 :             break;
    5728              :         }
    5729              :     }
    5730          902 : }
    5731              : 
    5732          902 : void CheckForSensorAndSetPointNode(EnergyPlusData &state,
    5733              :                                    int const SensorNodeNum,                          // controller sensor node number
    5734              :                                    HVACControllers::CtrlVarType const ControlledVar, // controlled variable type
    5735              :                                    bool &NodeNotFound                                // true if matching air outlet node not found
    5736              : )
    5737              : {
    5738              : 
    5739              :     // SUBROUTINE INFORMATION:
    5740              :     //       AUTHOR         Bereket Nigusse
    5741              :     //       DATE WRITTEN   March 2013
    5742              : 
    5743              :     // PURPOSE OF THIS SUBROUTINE:
    5744              :     // This subroutine checks that the sensor node number matches the air outlet node number
    5745              :     // of some water coils
    5746              : 
    5747              :     // SUBROUTINE PARAMETER DEFINITIONS:
    5748              :     static constexpr std::string_view RoutineName("CheckForSensorAndSetpointNode: ");
    5749              : 
    5750              :     // Obtains and Allocates DXCoils
    5751          902 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
    5752            2 :         GetWaterCoilInput(state);
    5753            2 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    5754              :     }
    5755              : 
    5756          902 :     int WhichCoil = 0;
    5757          902 :     NodeNotFound = true;
    5758              : 
    5759        22548 :     for (int CoilNum = 1; CoilNum <= state.dataWaterCoils->NumWaterCoils; ++CoilNum) {
    5760        22548 :         auto const &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    5761        22548 :         if (SensorNodeNum != waterCoil.AirOutletNodeNum) {
    5762        21646 :             continue;
    5763              :         }
    5764          902 :         NodeNotFound = false;
    5765          902 :         WhichCoil = CoilNum;
    5766          902 :         break;
    5767              :     }
    5768              :     // now if the sensor node is on the water coil air outlet node then check that
    5769              :     // a setpoint is also specified on the water coil outlet node
    5770          902 :     if (!NodeNotFound) {
    5771          902 :         if (WhichCoil > 0) {
    5772          902 :             bool EMSSetPointErrorFlag = false;
    5773          902 :             switch (ControlledVar) {
    5774          847 :             case HVACControllers::CtrlVarType::Temperature: {
    5775          847 :                 EMSManager::CheckIfNodeSetPointManagedByEMS(state, SensorNodeNum, HVAC::CtrlVarType::Temp, EMSSetPointErrorFlag);
    5776          847 :                 state.dataLoopNodes->NodeSetpointCheck(SensorNodeNum).needsSetpointChecking = false;
    5777          847 :                 if (EMSSetPointErrorFlag) {
    5778          638 :                     if (!SetPointManager::NodeHasSPMCtrlVarType(state, SensorNodeNum, HVAC::CtrlVarType::Temp)) {
    5779              :                         std::string_view WaterCoilType =
    5780            0 :                             DataPlant::PlantEquipTypeNames[static_cast<int>(state.dataWaterCoils->WaterCoil(WhichCoil).WaterCoilType)];
    5781            0 :                         ShowWarningError(state, format("{}{}=\"{}\". ", RoutineName, WaterCoilType, state.dataWaterCoils->WaterCoil(WhichCoil).Name));
    5782            0 :                         ShowContinueError(state, " ..Temperature setpoint not found on coil air outlet node.");
    5783            0 :                         ShowContinueError(state,
    5784              :                                           " ..The setpoint may have been placed on a node downstream of the coil or on an airloop outlet node.");
    5785            0 :                         ShowContinueError(state, " ..Specify the setpoint and the sensor on the coil air outlet node when possible.");
    5786              :                     }
    5787              :                 }
    5788          847 :                 break;
    5789              :             }
    5790            0 :             case HVACControllers::CtrlVarType::HumidityRatio: {
    5791            0 :                 EMSManager::CheckIfNodeSetPointManagedByEMS(state, SensorNodeNum, HVAC::CtrlVarType::MaxHumRat, EMSSetPointErrorFlag);
    5792            0 :                 state.dataLoopNodes->NodeSetpointCheck(SensorNodeNum).needsSetpointChecking = false;
    5793            0 :                 if (EMSSetPointErrorFlag) {
    5794            0 :                     if (!SetPointManager::NodeHasSPMCtrlVarType(state, SensorNodeNum, HVAC::CtrlVarType::MaxHumRat)) {
    5795              :                         std::string_view WaterCoilType =
    5796            0 :                             DataPlant::PlantEquipTypeNames[static_cast<int>(state.dataWaterCoils->WaterCoil(WhichCoil).WaterCoilType)];
    5797            0 :                         ShowWarningError(state, format("{}{}=\"{}\". ", RoutineName, WaterCoilType, state.dataWaterCoils->WaterCoil(WhichCoil).Name));
    5798            0 :                         ShowContinueError(state, " ..Humidity ratio setpoint not found on coil air outlet node.");
    5799            0 :                         ShowContinueError(state,
    5800              :                                           " ..The setpoint may have been placed on a node downstream of the coil or on an airloop outlet node.");
    5801            0 :                         ShowContinueError(state, " ..Specify the setpoint and the sensor on the coil air outlet node when possible.");
    5802              :                     }
    5803              :                 }
    5804            0 :                 break;
    5805              :             }
    5806           55 :             case HVACControllers::CtrlVarType::TemperatureAndHumidityRatio: {
    5807           55 :                 EMSManager::CheckIfNodeSetPointManagedByEMS(state, SensorNodeNum, HVAC::CtrlVarType::Temp, EMSSetPointErrorFlag);
    5808           55 :                 state.dataLoopNodes->NodeSetpointCheck(SensorNodeNum).needsSetpointChecking = false;
    5809           55 :                 if (EMSSetPointErrorFlag) {
    5810           30 :                     if (!SetPointManager::NodeHasSPMCtrlVarType(state, SensorNodeNum, HVAC::CtrlVarType::Temp)) {
    5811              :                         std::string_view WaterCoilType =
    5812            0 :                             DataPlant::PlantEquipTypeNames[static_cast<int>(state.dataWaterCoils->WaterCoil(WhichCoil).WaterCoilType)];
    5813            0 :                         ShowWarningError(state, format("{}{}=\"{}\". ", RoutineName, WaterCoilType, state.dataWaterCoils->WaterCoil(WhichCoil).Name));
    5814            0 :                         ShowContinueError(state, " ..Temperature setpoint not found on coil air outlet node.");
    5815            0 :                         ShowContinueError(state,
    5816              :                                           " ..The setpoint may have been placed on a node downstream of the coil or on an airloop outlet node.");
    5817            0 :                         ShowContinueError(state, " ..Specify the setpoint and the sensor on the coil air outlet node when possible.");
    5818              :                     }
    5819              :                 }
    5820           55 :                 EMSSetPointErrorFlag = false;
    5821           55 :                 EMSManager::CheckIfNodeSetPointManagedByEMS(state, SensorNodeNum, HVAC::CtrlVarType::MaxHumRat, EMSSetPointErrorFlag);
    5822           55 :                 state.dataLoopNodes->NodeSetpointCheck(SensorNodeNum).needsSetpointChecking = false;
    5823           55 :                 if (EMSSetPointErrorFlag) {
    5824           30 :                     if (!SetPointManager::NodeHasSPMCtrlVarType(state, SensorNodeNum, HVAC::CtrlVarType::MaxHumRat)) {
    5825              :                         std::string_view WaterCoilType =
    5826            0 :                             DataPlant::PlantEquipTypeNames[static_cast<int>(state.dataWaterCoils->WaterCoil(WhichCoil).WaterCoilType)];
    5827            0 :                         ShowWarningError(state, format("{}{}=\"{}\". ", RoutineName, WaterCoilType, state.dataWaterCoils->WaterCoil(WhichCoil).Name));
    5828            0 :                         ShowContinueError(state, " ..Humidity ratio setpoint not found on coil air outlet node.");
    5829            0 :                         ShowContinueError(state,
    5830              :                                           " ..The setpoint may have been placed on a node downstream of the coil or on an airloop outlet node.");
    5831            0 :                         ShowContinueError(state, " ..Specify the setpoint and the sensor on the coil air outlet node when possible.");
    5832              :                     }
    5833              :                 }
    5834           55 :                 break;
    5835              :             }
    5836            0 :             default:
    5837            0 :                 break;
    5838              :             }
    5839              :         }
    5840              :     }
    5841          902 : }
    5842              : 
    5843           80 : Real64 TdbFnHRhPb(EnergyPlusData &state,
    5844              :                   Real64 const H,  // specific enthalpy {J/kg}
    5845              :                   Real64 const RH, // relative humidity value (0.0-1.0)
    5846              :                   Real64 const PB  // barometric pressure {Pascals}
    5847              : )
    5848              : {
    5849              : 
    5850              :     // FUNCTION INFORMATION:
    5851              :     //       AUTHOR         Fred Buhl
    5852              :     //       DATE WRITTEN   April 1, 2009
    5853              : 
    5854              :     // PURPOSE OF THIS FUNCTION:
    5855              :     // Given the specific enthalpy, relative humidity, and the
    5856              :     // barometric pressure, the function returns the dry bulb temperature.
    5857              : 
    5858              :     // Return value
    5859              :     Real64 T; // result=> humidity ratio
    5860              : 
    5861              :     // Locals
    5862              :     // FUNCTION ARGUMENT DEFINITIONS:
    5863              : 
    5864              :     // FUNCTION PARAMETER DEFINITIONS:
    5865           80 :     int constexpr MaxIte(500); // Maximum number of iterations
    5866           80 :     Real64 constexpr Acc(1.0); // Accuracy of result
    5867              : 
    5868              :     // INTERFACE BLOCK SPECIFICATIONS
    5869              :     // na
    5870              : 
    5871              :     // DERIVED TYPE DEFINITIONS
    5872              :     // na
    5873              : 
    5874              :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5875              :     int SolFla;        // Flag of solver
    5876              :     Real64 T0;         // lower bound for Tprov [C]
    5877              :     Real64 T1;         // upper bound for Tprov [C]
    5878           80 :     Real64 Tprov(0.0); // provisional value of drybulb temperature [C]
    5879              : 
    5880           80 :     T0 = 1.0;
    5881           80 :     T1 = 50.0;
    5882              : 
    5883         1765 :     auto f = [&state, H, RH, PB](Real64 const Tprov) { return H - Psychrometrics::PsyHFnTdbRhPb(state, Tprov, RH, PB); };
    5884              : 
    5885           80 :     General::SolveRoot(state, Acc, MaxIte, SolFla, Tprov, f, T0, T1);
    5886              :     // if the numerical inversion failed, issue error messages.
    5887           80 :     if (SolFla == -1) {
    5888            0 :         ShowSevereError(state, "Calculation of drybulb temperature failed in TdbFnHRhPb(H,RH,PB)");
    5889            0 :         ShowContinueError(state, "   Iteration limit exceeded");
    5890            0 :         ShowContinueError(state, format("   H=[{:.6R}], RH=[{:.4R}], PB=[{:.5R}].", H, RH, PB));
    5891           80 :     } else if (SolFla == -2) {
    5892            0 :         ShowSevereError(state, "Calculation of drybulb temperature failed in TdbFnHRhPb(H,RH,PB)");
    5893            0 :         ShowContinueError(state, "  Bad starting values for Tdb");
    5894            0 :         ShowContinueError(state, format("   H=[{:.6R}], RH=[{:.4R}], PB=[{:.5R}].", H, RH, PB));
    5895              :     }
    5896           80 :     if (SolFla < 0) {
    5897            0 :         T = 0.0;
    5898              :     } else {
    5899           80 :         T = Tprov;
    5900              :     }
    5901              : 
    5902           80 :     return T;
    5903              : }
    5904              : 
    5905         9085 : Real64 EstimateHEXSurfaceArea(EnergyPlusData &state, int const CoilNum) // coil number, [-]
    5906              : {
    5907              : 
    5908              :     // FUNCTION INFORMATION:
    5909              :     //       AUTHOR         Bereket A Nigusse, FSEC
    5910              :     //       DATE WRITTEN   July 2010
    5911              : 
    5912              :     // PURPOSE OF THIS FUNCTION:
    5913              :     // Splits the UA value of a simple coil:cooling:water heat exchanger model into
    5914              :     // "A" and U" values.
    5915              : 
    5916              :     // METHODOLOGY EMPLOYED:
    5917              :     // A typical design U overall heat transfer coefficient is used to split the "UA" into "A"
    5918              :     // and "U" values. Currently a constant U value calculated for a typical cooling coil is
    5919              :     // used. The assumptions used to calculate a typical U value are:
    5920              :     //     (1) tube side water velocity of 2.0 [m/s]
    5921              :     //     (2) inside to outside total surface area ratio (Ai/Ao) =  0.07 [-]
    5922              :     //     (3) fins overall efficiency = 0.92 based on aluminum fin, 12 fins per inch, and
    5923              :     //         fins area to total outside surafce area ratio of about 90%.
    5924              :     //     (4) air side convection coefficient of 140.0 [W/m2C].  Assumes sensible convection
    5925              :     //         of 58.0 [W/m2C] and 82.0 [W/m2C] sensible convection equivalent of the mass
    5926              :     //         transfer coefficient converted using the approximate relation:
    5927              :     //         hequivalent = hmasstransfer/CpAir.
    5928              : 
    5929              :     // FUNCTION PARAMETER DEFINITIONS:
    5930         9085 :     constexpr Real64 OverallFinEfficiency(0.92); // Assumes aluminum fins, 12 fins per inch, fins
    5931              :     // area of about 90% of external surface area Ao.
    5932              : 
    5933         9085 :     constexpr Real64 AreaRatio(0.07); // Heat exchanger Inside to Outside surface area ratio
    5934              :     // design values range from (Ai/Ao) = 0.06 to 0.08
    5935              : 
    5936              :     // Constant value air side heat transfer coefficient is assumed. This coefficient has sensible
    5937              :     // (58.d0 [W/m2C]) and latent (82.d0 [W/m2C]) heat transfer coefficient components.
    5938         9085 :     constexpr Real64 hAirTubeOutside(58.0 + 82.0); // Air side heat transfer coefficient [W/m2C]
    5939              : 
    5940              :     // Tube side water convection heat transfer coefficient of the cooling coil is calculated for
    5941              :     // inside tube diameter of 0.0122m (~0.5 inch nominal diameter) and water velocity 2.0 m/s:
    5942              :     static Real64 const hWaterTubeInside(1429.0 * std::pow(2.0, 0.8) * std::pow(0.0122, -0.2)); // water (tube) side heat transfer coefficient [W/m2C]
    5943              : 
    5944              :     // Estimate the overall heat transfer coefficient, UOverallHeatTransferCoef in [W/(m2C)].
    5945              :     // Neglecting tube wall and fouling resistance, the overall U value can be estimated as:
    5946              :     // 1/UOverallHeatTransferCoef = 1/(hi*AreaRatio) + 1/(ho*OverallFinEfficiency)
    5947              :     static Real64 const UOverallHeatTransferCoef_inv(
    5948              :         1.0 / (hWaterTubeInside * AreaRatio) +
    5949              :         1.0 / (hAirTubeOutside * OverallFinEfficiency)); // Inverse of overall heat transfer coefficient for coil [W/m2C]
    5950              : 
    5951              :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
    5952         9085 :     auto &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    5953         9085 :     waterCoil.UACoilTotal = 1.0 / (1.0 / waterCoil.UACoilExternal + 1.0 / waterCoil.UACoilInternal);
    5954              : 
    5955              :     // the heat exchanger surface area is calculated as follows:
    5956         9085 :     return waterCoil.UACoilTotal * UOverallHeatTransferCoef_inv; // Heat exchanger surface area [m2]
    5957              : }
    5958              : 
    5959         2509 : int GetWaterCoilIndex(EnergyPlusData &state,
    5960              :                       std::string_view CoilType,   // must match coil types in this module
    5961              :                       std::string const &CoilName, // must match coil names for the coil type
    5962              :                       bool &ErrorsFound            // set to true if problem
    5963              : )
    5964              : {
    5965              : 
    5966              :     // FUNCTION INFORMATION:
    5967              :     //       AUTHOR         B. Nigusse, FSEC
    5968              :     //       DATE WRITTEN   Feb 2012
    5969              : 
    5970              :     // PURPOSE OF THIS FUNCTION:
    5971              :     // This function looks up the index for the given coil and returns it.  If incorrect coil
    5972              :     // type or name is given, ErrorsFound is returned as true and node number is returned
    5973              :     // as zero.
    5974              : 
    5975              :     // Return value
    5976              :     int IndexNum; // returned coil index if matched coil
    5977              : 
    5978              :     // Obtains and allocates WaterCoil related parameters from input file
    5979         2509 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
    5980          278 :         GetWaterCoilInput(state);
    5981          278 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    5982              :     }
    5983              : 
    5984         2509 :     IndexNum = 0;
    5985         2509 :     if (CoilType == "COIL:HEATING:WATER") {
    5986         2319 :         IndexNum = Util::FindItemInList(CoilName, state.dataWaterCoils->WaterCoil);
    5987          190 :     } else if (CoilType == "COIL:COOLING:WATER") {
    5988          190 :         IndexNum = Util::FindItemInList(CoilName, state.dataWaterCoils->WaterCoil);
    5989            0 :     } else if (CoilType == "COIL:COOLING:WATER:DETAILEDGEOMETRY") {
    5990            0 :         IndexNum = Util::FindItemInList(CoilName, state.dataWaterCoils->WaterCoil);
    5991              :     } else {
    5992            0 :         IndexNum = 0;
    5993              :     }
    5994              : 
    5995         2509 :     if (IndexNum == 0) {
    5996            0 :         ShowSevereError(state, format("GetWaterCoilIndex: Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
    5997            0 :         ErrorsFound = true;
    5998              :     }
    5999              : 
    6000         2509 :     return IndexNum;
    6001              : }
    6002           24 : int GetCompIndex(EnergyPlusData &state, CoilModel compType, std::string_view const coilName)
    6003              : {
    6004              :     static constexpr std::array<std::string_view, (int)WaterCoils::CoilModel::Num> CoilModelNamesUC = {
    6005              :         "COIL:HEATING:WATER", "COIL:COOLING:WATER", "COIL:COOLING:WATER:DETAILED"};
    6006              : 
    6007           24 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
    6008            5 :         GetWaterCoilInput(state);
    6009            5 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    6010              :     }
    6011              : 
    6012           24 :     int index = Util::FindItemInList(coilName, state.dataWaterCoils->WaterCoil);
    6013              : 
    6014           24 :     if (index == 0) { // may not find coil name
    6015            0 :         ShowSevereError(state,
    6016            0 :                         format("GetWaterCoilIndex: Could not find CoilType = \"{}\" with Name = \"{}\"", CoilModelNamesUC[(int)compType], coilName));
    6017              :     }
    6018           24 :     return index;
    6019              : }
    6020              : 
    6021           29 : Real64 GetWaterCoilCapacity(EnergyPlusData &state,
    6022              :                             std::string const &CoilType, // must match coil types in this module
    6023              :                             std::string const &CoilName, // must match coil names for the coil type
    6024              :                             bool &ErrorsFound            // set to true if problem
    6025              : )
    6026              : {
    6027              : 
    6028              :     // FUNCTION INFORMATION:
    6029              :     //       AUTHOR         R. Raustad, FSEC
    6030              :     //       DATE WRITTEN   Sep 2013
    6031              : 
    6032              :     // PURPOSE OF THIS FUNCTION:
    6033              :     // This function looks up the capacity for the given coil and returns it.  If incorrect coil
    6034              :     // type or name is given, ErrorsFound is returned as true and capacity is returned
    6035              :     // as zero.
    6036              : 
    6037              :     // Obtains and allocates WaterCoil related parameters from input file
    6038           29 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
    6039            0 :         GetWaterCoilInput(state);
    6040            0 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    6041              :     }
    6042              : 
    6043              :     int IndexNum;           // index to water coil
    6044           29 :     Real64 Capacity = -1.0; // returned coil capacity if matched coil
    6045              : 
    6046           29 :     if (CoilType == "COIL:HEATING:WATER") {
    6047            9 :         IndexNum = Util::FindItemInList(CoilName, state.dataWaterCoils->WaterCoil);
    6048            9 :         Capacity = state.dataWaterCoils->WaterCoil(IndexNum).DesWaterHeatingCoilRate;
    6049           20 :     } else if (CoilType == "COIL:COOLING:WATER") {
    6050           20 :         IndexNum = Util::FindItemInList(CoilName, state.dataWaterCoils->WaterCoil);
    6051           20 :         Capacity = state.dataWaterCoils->WaterCoil(IndexNum).DesWaterCoolingCoilRate;
    6052            0 :     } else if (CoilType == "COIL:COOLING:WATER:DETAILEDGEOMETRY") {
    6053            0 :         IndexNum = Util::FindItemInList(CoilName, state.dataWaterCoils->WaterCoil);
    6054            0 :         Capacity = state.dataWaterCoils->WaterCoil(IndexNum).DesWaterCoolingCoilRate;
    6055              :     } else {
    6056            0 :         IndexNum = 0;
    6057              :     }
    6058              : 
    6059           29 :     if (IndexNum == 0) {
    6060            0 :         ShowSevereError(state, format("GetWaterCoilCapacity: Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
    6061            0 :         ErrorsFound = true;
    6062              :     }
    6063              : 
    6064           29 :     return Capacity;
    6065              : }
    6066              : 
    6067            0 : void UpdateWaterToAirCoilPlantConnection(EnergyPlusData &state,
    6068              :                                          DataPlant::PlantEquipmentType const CoilType,
    6069              :                                          std::string const &CoilName,
    6070              :                                          [[maybe_unused]] int const EquipFlowCtrl,   // Flow control mode for the equipment
    6071              :                                          int const LoopNum,                          // Plant loop index for where called from
    6072              :                                          const DataPlant::LoopSideLocation LoopSide, // Plant loop side index for where called from
    6073              :                                          int &CompIndex,                             // Chiller number pointer
    6074              :                                          [[maybe_unused]] bool const FirstHVACIteration,
    6075              :                                          bool &InitLoopEquip // If not zero, calculate the max load for operating conditions
    6076              : )
    6077              : {
    6078              : 
    6079              :     // SUBROUTINE INFORMATION:
    6080              :     //       AUTHOR         B. Griffith
    6081              :     //       DATE WRITTEN   February 2010
    6082              : 
    6083              :     // PURPOSE OF THIS SUBROUTINE:
    6084              :     // update sim routine called from plant
    6085              : 
    6086              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6087              : 
    6088              :     int CoilNum;
    6089            0 :     bool DidAnythingChange(false); // set to true if conditions changed
    6090              :     int InletNodeNum;
    6091              :     int OutletNodeNum;
    6092              : 
    6093              :     // Find the correct water coil
    6094            0 :     if (CompIndex == 0) {
    6095            0 :         CoilNum = Util::FindItemInList(CoilName, state.dataWaterCoils->WaterCoil);
    6096            0 :         if (CoilNum == 0) {
    6097            0 :             ShowFatalError(state, format("UpdateWaterToAirCoilPlantConnection: Specified Coil not one of Valid water coils={}", CoilName));
    6098              :         }
    6099            0 :         CompIndex = CoilNum;
    6100              :     } else {
    6101            0 :         CoilNum = CompIndex;
    6102            0 :         if (CoilNum > state.dataWaterCoils->NumWaterCoils || CoilNum < 1) {
    6103            0 :             ShowFatalError(state,
    6104            0 :                            format("UpdateWaterToAirCoilPlantConnection:  Invalid CompIndex passed={}, Number of Coils={}, Entered Coil name={}",
    6105              :                                   CoilNum,
    6106            0 :                                   state.dataWaterCoils->NumWaterCoils,
    6107              :                                   CoilName));
    6108              :         }
    6109            0 :         auto const &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    6110            0 :         if (state.dataGlobal->KickOffSimulation) {
    6111            0 :             if (CoilName != waterCoil.Name) {
    6112            0 :                 ShowFatalError(
    6113              :                     state,
    6114            0 :                     format("UpdateWaterToAirCoilPlantConnection: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
    6115              :                            CoilNum,
    6116              :                            CoilName,
    6117            0 :                            waterCoil.Name));
    6118              :             }
    6119            0 :             if (CoilType != waterCoil.WaterCoilType) {
    6120            0 :                 ShowFatalError(
    6121              :                     state,
    6122            0 :                     format("UpdateWaterToAirCoilPlantConnection: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
    6123              :                            CoilNum,
    6124              :                            CoilName,
    6125            0 :                            DataPlant::PlantEquipTypeNames[static_cast<int>(CoilType)]));
    6126              :             }
    6127              :         }
    6128              :     }
    6129              : 
    6130            0 :     if (InitLoopEquip) {
    6131            0 :         return;
    6132              :     }
    6133              : 
    6134            0 :     DidAnythingChange = false;
    6135              : 
    6136            0 :     auto const &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    6137            0 :     InletNodeNum = waterCoil.WaterInletNodeNum;
    6138            0 :     OutletNodeNum = waterCoil.WaterOutletNodeNum;
    6139              : 
    6140            0 :     if (state.dataLoopNodes->Node(InletNodeNum).Temp != waterCoil.InletWaterTemp) {
    6141            0 :         DidAnythingChange = true;
    6142              :     }
    6143              : 
    6144            0 :     if (state.dataLoopNodes->Node(OutletNodeNum).Temp != waterCoil.OutletWaterTemp) {
    6145            0 :         DidAnythingChange = true;
    6146              :     }
    6147              : 
    6148            0 :     if (state.dataLoopNodes->Node(InletNodeNum).MassFlowRate != waterCoil.OutletWaterMassFlowRate) {
    6149            0 :         DidAnythingChange = true;
    6150            0 :         state.dataLoopNodes->Node(OutletNodeNum).MassFlowRate =
    6151            0 :             state.dataLoopNodes->Node(InletNodeNum).MassFlowRate; // make sure flows are consistent
    6152              :     }
    6153              : 
    6154            0 :     if (state.dataLoopNodes->Node(OutletNodeNum).MassFlowRate != waterCoil.OutletWaterMassFlowRate) {
    6155            0 :         DidAnythingChange = true;
    6156              :     }
    6157              : 
    6158            0 :     if (DidAnythingChange) {
    6159              :         // set sim flag for this loop
    6160            0 :         state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSide).SimLoopSideNeeded = true;
    6161              :         // set sim flags for air side users of coils
    6162              : 
    6163            0 :         state.dataHVACGlobal->SimAirLoopsFlag = true;
    6164            0 :         state.dataHVACGlobal->SimZoneEquipmentFlag = true;
    6165              :     } else { // nothing changed so turn off sim flag
    6166            0 :         state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSide).SimLoopSideNeeded = false;
    6167              :     }
    6168              : }
    6169              : 
    6170            0 : Sched::Schedule *GetWaterCoilAvailSched(EnergyPlusData &state,
    6171              :                                         std::string const &CoilType, // must match coil types in this module
    6172              :                                         std::string const &CoilName, // must match coil names for the coil type
    6173              :                                         bool &ErrorsFound            // set to true if problem
    6174              : )
    6175              : {
    6176              : 
    6177              :     // FUNCTION INFORMATION:
    6178              :     //       AUTHOR         Chandan Sharma, FSEC
    6179              :     //       DATE WRITTEN   February 2013
    6180              : 
    6181              :     // PURPOSE OF THIS FUNCTION:
    6182              :     // This function looks up the given coil and returns the availability schedule index.  If
    6183              :     // incorrect coil type or name is given, ErrorsFound is returned as true and index is returned
    6184              :     // as zero.
    6185              : 
    6186              :     // Obtains and Allocates HeatingCoil related parameters from input file
    6187              :     // Obtains and Allocates DXCoils
    6188            0 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
    6189            0 :         GetWaterCoilInput(state);
    6190            0 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    6191              :     }
    6192              : 
    6193            0 :     int WhichCoil = 0;
    6194              : 
    6195            0 :     if (Util::SameString(CoilType, "Coil:Heating:Water") || Util::SameString(CoilType, "Coil:Cooling:Water") ||
    6196            0 :         Util::SameString(CoilType, "Coil:Cooling:Water:DetailedGeometry")) {
    6197            0 :         WhichCoil = Util::FindItem(CoilName, state.dataWaterCoils->WaterCoil);
    6198            0 :         if (WhichCoil != 0) {
    6199            0 :             return state.dataWaterCoils->WaterCoil(WhichCoil).availSched;
    6200              :         }
    6201              :     } else {
    6202            0 :         WhichCoil = 0;
    6203              :     }
    6204              : 
    6205            0 :     if (WhichCoil == 0) {
    6206            0 :         ShowSevereError(state, format("GetCoilAvailScheduleIndex: Could not find Coil, Type=\"{}\" Name=\"{}\"", CoilType, CoilName));
    6207            0 :         ErrorsFound = true;
    6208            0 :         return nullptr;
    6209              :     }
    6210              : 
    6211            0 :     return nullptr;
    6212              : }
    6213              : 
    6214            2 : void SetWaterCoilData(EnergyPlusData &state,
    6215              :                       int const CoilNum,                                  // Number of hot water heating Coil
    6216              :                       bool &ErrorsFound,                                  // Set to true if certain errors found
    6217              :                       ObjexxFCL::Optional_bool DesiccantRegenerationCoil, // Flag that this coil is used as regeneration air heating coil
    6218              :                       ObjexxFCL::Optional_int DesiccantDehumIndex,        // Index for the desiccant dehum system where this caoil is used
    6219              :                       ObjexxFCL::Optional_bool heatRecoveryCoil)          // true if water coil is connected to heat recovery loop
    6220              : {
    6221              : 
    6222              :     // FUNCTION INFORMATION:
    6223              :     //       AUTHOR         Bereket Nigusse
    6224              :     //       DATE WRITTEN   February 2016
    6225              : 
    6226              :     // PURPOSE OF THIS FUNCTION:
    6227              :     // This function sets data to water Heating Coil using the coil index and arguments passed
    6228              : 
    6229            2 :     if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
    6230            0 :         GetWaterCoilInput(state);
    6231            0 :         state.dataWaterCoils->GetWaterCoilsInputFlag = false;
    6232              :     }
    6233              : 
    6234            2 :     if (CoilNum <= 0 || CoilNum > state.dataWaterCoils->NumWaterCoils) {
    6235            0 :         ShowSevereError(state,
    6236            0 :                         format("SetHeatingCoilData: called with heating coil Number out of range={} should be >0 and <{}",
    6237              :                                CoilNum,
    6238            0 :                                state.dataWaterCoils->NumWaterCoils));
    6239            0 :         ErrorsFound = true;
    6240            0 :         return;
    6241              :     }
    6242              : 
    6243            2 :     auto &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    6244            2 :     if (present(DesiccantRegenerationCoil)) {
    6245            0 :         waterCoil.DesiccantRegenerationCoil = DesiccantRegenerationCoil;
    6246              :     }
    6247              : 
    6248            2 :     if (present(DesiccantDehumIndex)) {
    6249            0 :         waterCoil.DesiccantDehumNum = DesiccantDehumIndex;
    6250              :     }
    6251              : 
    6252            2 :     if (present(heatRecoveryCoil)) {
    6253            2 :         waterCoil.heatRecoveryCoil = heatRecoveryCoil;
    6254              :     }
    6255              : }
    6256              : 
    6257            0 : void EstimateCoilInletWaterTemp(EnergyPlusData &state,
    6258              :                                 int const CoilNum,                // index to heating coil
    6259              :                                 HVAC::FanOp const fanOp,          // fan operating mode
    6260              :                                 Real64 const PartLoadRatio,       // part-load ratio of heating coil
    6261              :                                 Real64 const UAMax,               // maximum UA-Value = design heating capacity
    6262              :                                 Real64 &DesCoilInletWaterTempUsed // estimated coil design inlet water temperature
    6263              : )
    6264              : {
    6265              :     // SUBROUTINE INFORMATION:
    6266              : 
    6267              :     // PURPOSE OF THIS SUBROUTINE:
    6268              :     // returns estimated coil inlet water temperature given UA value for assumed
    6269              :     // maximum effectiveness value for heating coil
    6270              : 
    6271              :     // METHODOLOGY EMPLOYED:
    6272              :     // applies energy balance around the water coil and estimates coil water inlet temperature
    6273              :     // assuming coil effectiveness of 0.8
    6274              : 
    6275              :     // SUBROUTINE PARAMETER DEFINITIONS:
    6276              :     static constexpr std::string_view RoutineName("EstimateCoilInletWaterTemp");
    6277            0 :     constexpr Real64 EffectivenessMaxAssumed(0.80);
    6278              : 
    6279              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6280              :     Real64 WaterMassFlowRate;
    6281              :     Real64 AirMassFlow;
    6282              :     Real64 TempAirIn;
    6283              :     Real64 TempAirOut; // [C]
    6284              :     Real64 Win;
    6285              :     Real64 TempWaterIn;
    6286              :     Real64 UA;
    6287              :     Real64 CapacitanceAir;
    6288              :     Real64 CapacitanceWater;
    6289              :     Real64 CapacitanceMin;
    6290              :     Real64 CapacitanceMax;
    6291              :     Real64 NTU;
    6292              :     Real64 ETA;
    6293              :     Real64 A;
    6294              :     Real64 CapRatio;
    6295              :     Real64 E1;
    6296              :     Real64 E2;
    6297              :     Real64 Effec;
    6298              :     Real64 Cp;
    6299              : 
    6300            0 :     UA = UAMax;
    6301            0 :     DesCoilInletWaterTempUsed = HVAC::DesCoilHWInletTempMin;
    6302            0 :     auto const &waterCoil = state.dataWaterCoils->WaterCoil(CoilNum);
    6303            0 :     TempAirIn = waterCoil.InletAirTemp;
    6304            0 :     Win = waterCoil.InletAirHumRat;
    6305            0 :     TempWaterIn = waterCoil.InletWaterTemp;
    6306              :     // adjust mass flow rates for cycling fan cycling coil operation
    6307            0 :     if (fanOp == HVAC::FanOp::Cycling) {
    6308            0 :         if (PartLoadRatio > 0.0) {
    6309            0 :             AirMassFlow = waterCoil.InletAirMassFlowRate / PartLoadRatio;
    6310            0 :             WaterMassFlowRate = min(waterCoil.InletWaterMassFlowRate / PartLoadRatio, waterCoil.MaxWaterMassFlowRate);
    6311              :         } else {
    6312            0 :             AirMassFlow = 0.0;
    6313            0 :             WaterMassFlowRate = 0.0;
    6314            0 :             return;
    6315              :         }
    6316              :     } else {
    6317            0 :         AirMassFlow = waterCoil.InletAirMassFlowRate;
    6318            0 :         WaterMassFlowRate = waterCoil.InletWaterMassFlowRate;
    6319              :     }
    6320            0 :     if (WaterMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) { // if the coil is operating
    6321            0 :         CapacitanceAir = PsyCpAirFnW(Win) * AirMassFlow;
    6322            0 :         Cp = state.dataPlnt->PlantLoop(waterCoil.WaterPlantLoc.loopNum).glycol->getSpecificHeat(state, TempWaterIn, RoutineName);
    6323            0 :         CapacitanceWater = Cp * WaterMassFlowRate;
    6324            0 :         CapacitanceMin = min(CapacitanceAir, CapacitanceWater);
    6325            0 :         CapacitanceMax = max(CapacitanceAir, CapacitanceWater);
    6326              :     } else {
    6327            0 :         CapacitanceAir = 0.0;
    6328            0 :         CapacitanceWater = 0.0;
    6329            0 :         return;
    6330              :     }
    6331              :     // calculate DesCoilInletWaterTempUsed
    6332            0 :     if (((CapacitanceAir > 0.0) && (CapacitanceWater > 0.0))) {
    6333              : 
    6334            0 :         if (UA <= 0.0) {
    6335            0 :             ShowWarningError(state, format("UA is zero for COIL:Heating:Water {}", waterCoil.Name));
    6336            0 :             return;
    6337              :         }
    6338            0 :         NTU = UA / CapacitanceMin;
    6339            0 :         ETA = std::pow(NTU, 0.22);
    6340            0 :         CapRatio = CapacitanceMin / CapacitanceMax;
    6341            0 :         A = CapRatio * NTU / ETA;
    6342              : 
    6343            0 :         if (A > 20.0) {
    6344            0 :             A = ETA * 1.0 / CapRatio;
    6345              :         } else {
    6346            0 :             E1 = std::exp(-A);
    6347            0 :             A = ETA * (1.0 - E1) / CapRatio;
    6348              :         }
    6349              : 
    6350            0 :         if (A > 20.0) {
    6351            0 :             Effec = 1.0;
    6352              :         } else {
    6353            0 :             E2 = std::exp(-A);
    6354            0 :             Effec = 1.0 - E2;
    6355              :         }
    6356            0 :         TempAirOut = TempAirIn + Effec * CapacitanceMin * (TempWaterIn - TempAirIn) / CapacitanceAir;
    6357              :         // this formulation assumes coil effectiveness of 0.80 to increase the estimated coil water inlet temperatures
    6358            0 :         DesCoilInletWaterTempUsed = CapacitanceAir * (TempAirOut - TempAirIn) / (CapacitanceMin * EffectivenessMaxAssumed) + TempAirIn;
    6359              :         // water coil should not be sized at coil water inlet temperature lower than 46.0C (for convergence problem in Regulafalsi)
    6360            0 :         DesCoilInletWaterTempUsed = max(DesCoilInletWaterTempUsed, HVAC::DesCoilHWInletTempMin);
    6361              :     }
    6362              : }
    6363              : 
    6364              : // End of Coil Utility subroutines
    6365              : // *****************************************************************************
    6366              : 
    6367              : } // namespace EnergyPlus::WaterCoils
        

Generated by: LCOV version 2.0-1