LCOV - code coverage report
Current view: top level - EnergyPlus - WaterCoils.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 2249 2811 80.0 %
Date: 2024-08-23 23:50:59 Functions: 37 42 88.1 %

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

Generated by: LCOV version 1.14