LCOV - code coverage report
Current view: top level - EnergyPlus - CondenserLoopTowers.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 56.0 % 3380 1894
Test Date: 2025-05-22 16:09:37 Functions: 84.6 % 39 33

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <cassert>
      50              : #include <cmath>
      51              : 
      52              : // ObjexxFCL Headers
      53              : #include <ObjexxFCL/Array.functions.hh>
      54              : #include <ObjexxFCL/Fmath.hh>
      55              : // #include <ObjexxFCL/string.functions.hh>
      56              : 
      57              : // EnergyPlus Headers
      58              : #include <EnergyPlus/Autosizing/Base.hh>
      59              : #include <EnergyPlus/BranchNodeConnections.hh>
      60              : #include <EnergyPlus/CondenserLoopTowers.hh>
      61              : #include <EnergyPlus/CurveManager.hh>
      62              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      63              : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
      64              : #include <EnergyPlus/DataEnvironment.hh>
      65              : #include <EnergyPlus/DataHVACGlobals.hh>
      66              : #include <EnergyPlus/DataIPShortCuts.hh>
      67              : #include <EnergyPlus/DataLoopNode.hh>
      68              : #include <EnergyPlus/DataPrecisionGlobals.hh>
      69              : #include <EnergyPlus/DataSizing.hh>
      70              : #include <EnergyPlus/DataWater.hh>
      71              : #include <EnergyPlus/FaultsManager.hh>
      72              : #include <EnergyPlus/FluidProperties.hh>
      73              : #include <EnergyPlus/General.hh>
      74              : #include <EnergyPlus/GeneralRoutines.hh>
      75              : #include <EnergyPlus/GlobalNames.hh>
      76              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      77              : #include <EnergyPlus/NodeInputManager.hh>
      78              : #include <EnergyPlus/OutAirNodeManager.hh>
      79              : #include <EnergyPlus/OutputProcessor.hh>
      80              : #include <EnergyPlus/OutputReportPredefined.hh>
      81              : #include <EnergyPlus/Plant/DataPlant.hh>
      82              : #include <EnergyPlus/PlantUtilities.hh>
      83              : #include <EnergyPlus/Psychrometrics.hh>
      84              : #include <EnergyPlus/ScheduleManager.hh>
      85              : #include <EnergyPlus/UtilityRoutines.hh>
      86              : #include <EnergyPlus/WaterManager.hh>
      87              : 
      88              : namespace EnergyPlus {
      89              : 
      90              : namespace CondenserLoopTowers {
      91              : 
      92              :     // Module containing the routines dealing with the objects COOLING TOWER:SINGLE SPEED,
      93              :     // COOLING TOWER:TWO SPEED, and COOLING TOWER:VARIABLE SPEED
      94              : 
      95              :     // MODULE INFORMATION:
      96              :     //       AUTHOR         Dan Fisher
      97              :     //       DATE WRITTEN   April 1998
      98              :     //       MODIFIED       Shirey, Raustad: Dec 2000; Shirey, Sept 2002, Raustad Mar 2005
      99              :     //                      B Griffith Aug 2006, added water consumption and water system interactions
     100              :     //                      T Hong, Aug 2008. Added fluid bypass for single speed cooling tower
     101              :     //                      Chandan Sharma, FSEC, February 2010, Added basin heater
     102              :     //                      A Flament, July 2010, added multi-cell capability for the 3 types of cooling tower
     103              :     //       RE-ENGINEERED  na
     104              : 
     105              :     // PURPOSE OF THIS MODULE:
     106              :     // Model the performance of cooling towers
     107              : 
     108              :     std::string const cCoolingTower_SingleSpeed("CoolingTower:SingleSpeed");
     109              :     std::string const cCoolingTower_TwoSpeed("CoolingTower:TwoSpeed");
     110              :     std::string const cCoolingTower_VariableSpeed("CoolingTower:VariableSpeed");
     111              :     std::string const cCoolingTower_VariableSpeedMerkel("CoolingTower:VariableSpeed:Merkel");
     112              : 
     113           12 :     CoolingTower *CoolingTower::factory(EnergyPlusData &state, std::string_view objectName)
     114              :     {
     115              :         // Process the input data for towers if it hasn't been done already
     116           12 :         if (state.dataCondenserLoopTowers->GetInput) {
     117           12 :             GetTowerInput(state);
     118           12 :             state.dataCondenserLoopTowers->GetInput = false;
     119              :         }
     120              :         // Now look for this particular tower in the list
     121           12 :         auto thisObj = std::find_if(state.dataCondenserLoopTowers->towers.begin(),
     122           12 :                                     state.dataCondenserLoopTowers->towers.end(),
     123           12 :                                     [&objectName](const CoolingTower &myObj) { return myObj.Name == objectName; });
     124           12 :         if (thisObj != state.dataCondenserLoopTowers->towers.end()) return thisObj;
     125              :         // If we didn't find it, fatal
     126              :         ShowFatalError(state, format("CoolingTowerFactory: Error getting inputs for tower named: {}", objectName)); // LCOV_EXCL_LINE
     127              :         // Shut up the compiler
     128              :         return nullptr; // LCOV_EXCL_LINE
     129              :     }
     130              : 
     131        14199 :     void CoolingTower::simulate(EnergyPlusData &state,
     132              :                                 [[maybe_unused]] const PlantLocation &calledFromLocation,
     133              :                                 [[maybe_unused]] bool const FirstHVACIteration,
     134              :                                 Real64 &CurLoad,
     135              :                                 bool const RunFlag)
     136              :     {
     137        14199 :         this->initialize(state);
     138        14199 :         switch (this->TowerType) {
     139        13984 :         case DataPlant::PlantEquipmentType::CoolingTower_SingleSpd:
     140        13984 :             this->calculateSingleSpeedTower(state, CurLoad, RunFlag);
     141        13984 :             break;
     142          106 :         case DataPlant::PlantEquipmentType::CoolingTower_TwoSpd:
     143          106 :             this->calculateTwoSpeedTower(state, CurLoad, RunFlag);
     144          106 :             break;
     145            2 :         case DataPlant::PlantEquipmentType::CoolingTower_VarSpd:
     146            2 :             this->calculateVariableSpeedTower(state, CurLoad, RunFlag);
     147            2 :             break;
     148          107 :         case DataPlant::PlantEquipmentType::CoolingTower_VarSpdMerkel:
     149          107 :             this->calculateMerkelVariableSpeedTower(state, CurLoad, RunFlag);
     150          107 :             break;
     151            0 :         default:
     152            0 :             ShowFatalError(state, format("Plant Equipment Type specified for {} is not a Cooling Tower.", this->Name));
     153              :         }
     154        14199 :         this->calculateWaterUsage(state);
     155        14199 :         this->update(state);
     156        14199 :         this->report(state, RunFlag);
     157        14199 :     }
     158              : 
     159           35 :     void CoolingTower::getDesignCapacities([[maybe_unused]] EnergyPlusData &state,
     160              :                                            [[maybe_unused]] const PlantLocation &calledFromLocation,
     161              :                                            Real64 &MaxLoad,
     162              :                                            Real64 &MinLoad,
     163              :                                            Real64 &OptLoad)
     164              :     {
     165           35 :         MinLoad = 0.0;
     166           35 :         MaxLoad = this->TowerNominalCapacity * this->HeatRejectCapNomCapSizingRatio;
     167           35 :         OptLoad = this->TowerNominalCapacity;
     168           35 :     }
     169              : 
     170            7 :     void CoolingTower::getSizingFactor(Real64 &SizFactor)
     171              :     {
     172            7 :         SizFactor = this->SizFac;
     173            7 :     }
     174              : 
     175           35 :     void CoolingTower::onInitLoopEquip(EnergyPlusData &state, [[maybe_unused]] const PlantLocation &calledFromLocation)
     176              :     {
     177           35 :         this->initialize(state);
     178           35 :         if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_VarSpdMerkel) {
     179           10 :             this->SizeVSMerkelTower(state);
     180              :         } else {
     181           25 :             this->SizeTower(state);
     182              :         }
     183           35 :     }
     184              : 
     185           25 :     void GetTowerInput(EnergyPlusData &state)
     186              :     {
     187              : 
     188              :         // SUBROUTINE INFORMATION:
     189              :         //       AUTHOR:          Dan Fisher
     190              :         //       DATE WRITTEN:    April 1998
     191              :         //       MODIFIED         Don Shirey, Jan 2001 and Sept/Oct 2002; Richard Raustad, FSEC, Feb 2005 (added VS tower)
     192              :         //                        B. Griffith, Aug. 2006 water consumption modeling and water system connections
     193              :         //                        T Hong, Aug. 2008: added fluid bypass for single speed tower
     194              :         //                        A Flament, July 2010, added multi-cell capability for the 3 types of cooling tower
     195              : 
     196              :         // PURPOSE OF THIS SUBROUTINE:
     197              :         // Obtains input data for cooling towers and stores it in towers data structure. Additional structure
     198              :         // (VSTower) stores the coefficients for each VS tower.
     199              : 
     200              :         // METHODOLOGY EMPLOYED:
     201              :         // Uses "Get" routines to read in the data.
     202              : 
     203              :         static constexpr std::string_view routineName = "GetTowerInput";
     204              : 
     205              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     206              :         int TowerNum;                      // Tower number, reference counter for towers data array
     207           25 :         int NumVSCoolToolsModelCoeffs = 0; // Number of CoolTools VS cooling tower coefficient objects
     208           25 :         int NumVSYorkCalcModelCoeffs = 0;  // Number of YorkCalc VS cooling tower coefficient objects
     209              :         int VSModelCoeffNum;               // Specific variable-speed tower coefficient object of interest
     210              :         int NumAlphas;                     // Number of elements in the alpha array
     211              :         int NumNums;                       // Number of elements in the numeric array
     212              :         int NumAlphas2;                    // Number of elements in the alpha2 array
     213              :         int NumNums2;                      // Number of elements in the numeric2 array
     214              :         int IOStat;                        // IO Status when calling get input subroutine
     215              :         int CoeffNum;                      // Index for reading user defined VS tower coefficients
     216           25 :         bool ErrorsFound(false);           // Logical flag set .TRUE. if errors found while getting input data
     217           25 :         Array1D<Real64> NumArray(33);      // Numeric input data array
     218           25 :         Array1D<Real64> NumArray2(43);     // Numeric input data array for VS tower coefficients
     219           25 :         Array1D_string AlphArray(16);      // Character string input data array
     220           25 :         Array1D_string AlphArray2(1);      // Character string input data array for VS tower coefficients
     221              : 
     222           25 :         std::unordered_map<std::string, std::string> UniqueSimpleTowerNames;
     223              : 
     224           25 :         constexpr std::array<std::string_view, static_cast<int>(EvapLoss::Num)> EvapLossNamesUC{"LOSSFACTOR", "SATURATEDEXIT"};
     225           25 :         constexpr std::array<std::string_view, static_cast<int>(PIM::Num)> PIMNamesUC{"NOMINALCAPACITY", "UFACTORTIMESAREAANDDESIGNWATERFLOWRATE"};
     226           25 :         constexpr std::array<std::string_view, static_cast<int>(Blowdown::Num)> BlowDownNamesUC = {"CONCENTRATIONRATIO", "SCHEDULEDRATE"};
     227           25 :         constexpr std::array<std::string_view, static_cast<int>(CellCtrl::Num)> CellCtrlNamesUC = {"MINIMALCELL", "MAXIMALCELL"};
     228              : 
     229           25 :         auto const &s_ip = state.dataInputProcessing->inputProcessor;
     230           25 :         auto &s_ipsc = state.dataIPShortCut;
     231              : 
     232              :         // Get number of all cooling towers specified in the input data file (idf)
     233           25 :         int NumSingleSpeedTowers = s_ip->getNumObjectsFound(state, cCoolingTower_SingleSpeed);
     234           25 :         int NumTwoSpeedTowers = s_ip->getNumObjectsFound(state, cCoolingTower_TwoSpeed);
     235           25 :         int NumVariableSpeedTowers = s_ip->getNumObjectsFound(state, cCoolingTower_VariableSpeed);
     236           25 :         int NumVSMerkelTowers = s_ip->getNumObjectsFound(state, cCoolingTower_VariableSpeedMerkel);
     237           25 :         int NumSimpleTowers = NumSingleSpeedTowers + NumTwoSpeedTowers + NumVariableSpeedTowers + NumVSMerkelTowers;
     238              : 
     239           25 :         if (NumSimpleTowers <= 0)
     240            0 :             ShowFatalError(state,
     241              :                            "No Cooling Tower objects found in input, however, a branch object has specified a cooling tower. Search the input for "
     242              :                            "CoolingTower to determine the cause for this error.");
     243              : 
     244           25 :         state.dataCondenserLoopTowers->GetInput = false;
     245              :         // See if load distribution manager has already gotten the input
     246           25 :         if (allocated(state.dataCondenserLoopTowers->towers)) return;
     247              : 
     248              :         // Allocate data structures to hold tower input data, report data and tower inlet conditions
     249           15 :         state.dataCondenserLoopTowers->towers.allocate(NumSimpleTowers);
     250           15 :         UniqueSimpleTowerNames.reserve(NumSimpleTowers);
     251              :         // Allocate variable-speed tower structure with data specific to this type
     252           15 :         if (NumVariableSpeedTowers > 0) {
     253              :             // Allow users to input model coefficients other than default
     254            5 :             NumVSCoolToolsModelCoeffs = s_ip->getNumObjectsFound(state, "CoolingTowerPerformance:CoolTools");
     255            5 :             NumVSYorkCalcModelCoeffs = s_ip->getNumObjectsFound(state, "CoolingTowerPerformance:YorkCalc");
     256              :         }
     257              : 
     258              :         // Load data structures with cooling tower input data
     259           15 :         s_ipsc->cCurrentModuleObject = cCoolingTower_SingleSpeed;
     260           21 :         for (int SingleSpeedTowerNumber = 1; SingleSpeedTowerNumber <= NumSingleSpeedTowers; ++SingleSpeedTowerNumber) {
     261            6 :             TowerNum = SingleSpeedTowerNumber;
     262           18 :             s_ip->getObjectItem(state,
     263            6 :                                 s_ipsc->cCurrentModuleObject,
     264              :                                 SingleSpeedTowerNumber,
     265              :                                 AlphArray,
     266              :                                 NumAlphas,
     267              :                                 NumArray,
     268              :                                 NumNums,
     269              :                                 IOStat,
     270              :                                 _,
     271            6 :                                 s_ipsc->lAlphaFieldBlanks,
     272            6 :                                 s_ipsc->cAlphaFieldNames,
     273            6 :                                 s_ipsc->cNumericFieldNames);
     274              : 
     275            6 :             ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, AlphArray(1)};
     276              : 
     277            6 :             GlobalNames::VerifyUniqueInterObjectName(
     278           12 :                 state, UniqueSimpleTowerNames, AlphArray(1), s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaFieldNames(1), ErrorsFound);
     279            6 :             auto &tower = state.dataCondenserLoopTowers->towers(TowerNum);
     280            6 :             tower.Name = AlphArray(1);
     281            6 :             tower.TowerType = DataPlant::PlantEquipmentType::CoolingTower_SingleSpd;
     282            6 :             tower.TowerMassFlowRateMultiplier = 2.5;
     283            6 :             tower.WaterInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     284            6 :                                                                           AlphArray(2),
     285              :                                                                           ErrorsFound,
     286              :                                                                           DataLoopNode::ConnectionObjectType::CoolingTowerSingleSpeed,
     287            6 :                                                                           tower.Name,
     288              :                                                                           DataLoopNode::NodeFluidType::Water,
     289              :                                                                           DataLoopNode::ConnectionType::Inlet,
     290              :                                                                           NodeInputManager::CompFluidStream::Primary,
     291              :                                                                           DataLoopNode::ObjectIsNotParent);
     292           12 :             tower.WaterOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     293            6 :                                                                            AlphArray(3),
     294              :                                                                            ErrorsFound,
     295              :                                                                            DataLoopNode::ConnectionObjectType::CoolingTowerSingleSpeed,
     296            6 :                                                                            tower.Name,
     297              :                                                                            DataLoopNode::NodeFluidType::Water,
     298              :                                                                            DataLoopNode::ConnectionType::Outlet,
     299              :                                                                            NodeInputManager::CompFluidStream::Primary,
     300              :                                                                            DataLoopNode::ObjectIsNotParent);
     301            6 :             BranchNodeConnections::TestCompSet(state, s_ipsc->cCurrentModuleObject, tower.Name, AlphArray(2), AlphArray(3), "Chilled Water Nodes");
     302            6 :             tower.DesignWaterFlowRate = NumArray(1);
     303            6 :             if (tower.DesignWaterFlowRate == DataSizing::AutoSize) {
     304            3 :                 tower.DesignWaterFlowRateWasAutoSized = true;
     305              :             }
     306            6 :             tower.HighSpeedAirFlowRate = NumArray(2);
     307            6 :             if (tower.HighSpeedAirFlowRate == DataSizing::AutoSize) {
     308            5 :                 tower.HighSpeedAirFlowRateWasAutoSized = true;
     309              :             }
     310            6 :             tower.HighSpeedFanPower = NumArray(3);
     311            6 :             if (tower.HighSpeedFanPower == DataSizing::AutoSize) {
     312            5 :                 tower.HighSpeedFanPowerWasAutoSized = true;
     313              :             }
     314            6 :             tower.HighSpeedTowerUA = NumArray(4);
     315            6 :             if (tower.HighSpeedTowerUA == DataSizing::AutoSize) {
     316            3 :                 tower.HighSpeedTowerUAWasAutoSized = true;
     317              :             }
     318            6 :             tower.FreeConvAirFlowRate = NumArray(5);
     319            6 :             if (tower.FreeConvAirFlowRate == DataSizing::AutoSize) {
     320            4 :                 tower.FreeConvAirFlowRateWasAutoSized = true;
     321              :             }
     322            6 :             tower.FreeConvAirFlowRateSizingFactor = NumArray(6);
     323            6 :             tower.FreeConvTowerUA = NumArray(7);
     324            6 :             if (tower.FreeConvTowerUA == DataSizing::AutoSize) {
     325            2 :                 tower.FreeConvTowerUAWasAutoSized = true;
     326              :             }
     327            6 :             tower.FreeConvTowerUASizingFactor = NumArray(8);
     328            6 :             tower.HeatRejectCapNomCapSizingRatio = NumArray(9);
     329            6 :             tower.TowerNominalCapacity = NumArray(10);
     330            6 :             if (tower.TowerNominalCapacity == DataSizing::AutoSize) {
     331            0 :                 tower.TowerNominalCapacityWasAutoSized = true;
     332              :             }
     333            6 :             tower.TowerFreeConvNomCap = NumArray(11);
     334            6 :             if (tower.TowerFreeConvNomCap == DataSizing::AutoSize) {
     335            0 :                 tower.TowerFreeConvNomCapWasAutoSized = true;
     336              :             }
     337            6 :             tower.TowerFreeConvNomCapSizingFactor = NumArray(12);
     338            6 :             if (NumAlphas >= 4) {
     339            6 :                 tower.PerformanceInputMethod_Num = static_cast<PIM>(getEnumValue(PIMNamesUC, Util::makeUPPER(AlphArray(4))));
     340            6 :                 if (tower.PerformanceInputMethod_Num == PIM::Invalid) {
     341            0 :                     ShowSevereInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(4), AlphArray(4));
     342            0 :                     ErrorsFound = true;
     343              :                 }
     344              :             } else {
     345              :                 // Since Performance Input Method has been omitted then assume it to be UA and DESIGN WATER FLOW RATE
     346            0 :                 tower.PerformanceInputMethod_Num = PIM::UFactor;
     347              :             }
     348              :             // cooling tower design inlet conditions
     349            6 :             tower.DesInletAirDBTemp = NumArray(13);
     350            6 :             if (tower.DesInletAirDBTemp == 0) {
     351            0 :                 tower.DesInletAirDBTemp = 35.0;
     352            0 :                 tower.TowerInletCondsAutoSize = true;
     353              :             }
     354            6 :             tower.DesignInletWB = NumArray(14);
     355            6 :             if (tower.DesignInletWB == 0) {
     356            0 :                 tower.DesignInletWB = 25.6;
     357            0 :                 tower.TowerInletCondsAutoSize = true;
     358              :             }
     359            6 :             tower.DesignApproach = NumArray(15);
     360            6 :             if (tower.DesignApproach == DataSizing::AutoSize || tower.DesignApproach == 0) {
     361            5 :                 tower.DesignApproach = 3.9;
     362            5 :                 tower.TowerInletCondsAutoSize = true;
     363              :             }
     364            6 :             tower.DesignRange = NumArray(16);
     365            6 :             if (tower.DesignRange == DataSizing::AutoSize || tower.DesignRange == 0) {
     366            5 :                 tower.DesignRange = 5.5;
     367            5 :                 tower.TowerInletCondsAutoSize = true;
     368              :             }
     369              :             // set tower design water outlet and inlet temperatures
     370            6 :             tower.DesOutletWaterTemp = tower.DesignInletWB + tower.DesignApproach;
     371            6 :             tower.DesInletWaterTemp = tower.DesOutletWaterTemp + tower.DesignRange;
     372              :             //   Basin heater power as a function of temperature must be greater than or equal to 0
     373            6 :             tower.BasinHeaterPowerFTempDiff = NumArray(17);
     374            6 :             if (NumArray(17) < 0.0) {
     375            0 :                 ShowSevereCustom(state, eoh, "Basin heater power as a function of temperature difference must be >= 0");
     376            0 :                 ErrorsFound = true;
     377              :             }
     378              : 
     379            6 :             tower.BasinHeaterSetPointTemp = NumArray(18);
     380              : 
     381            6 :             if (tower.BasinHeaterPowerFTempDiff > 0.0) {
     382            0 :                 if (NumNums < 18) {
     383            0 :                     tower.BasinHeaterSetPointTemp = 2.0;
     384              :                 }
     385            0 :                 if (tower.BasinHeaterSetPointTemp < 2.0) {
     386            0 :                     ShowWarningCustom(state, eoh, format("{} is less than 2 deg C. Freezing could occur.", s_ipsc->cNumericFieldNames(18)));
     387              :                 }
     388              :             }
     389              : 
     390            6 :             if (!AlphArray(5).empty()) {
     391            0 :                 if ((tower.basinHeaterSched = Sched::GetSchedule(state, AlphArray(5))) == nullptr) {
     392            0 :                     ShowWarningItemNotFound(state,
     393              :                                             eoh,
     394            0 :                                             s_ipsc->cAlphaFieldNames(5),
     395            0 :                                             AlphArray(5),
     396              :                                             "Basin heater operation will not be modeled and the simulation continues");
     397              :                 }
     398              :             }
     399              : 
     400              :             // begin water use and systems get input
     401            6 :             tower.EvapLossMode = static_cast<EvapLoss>(getEnumValue(EvapLossNamesUC, Util::makeUPPER(AlphArray(6))));
     402              : 
     403            6 :             tower.UserEvapLossFactor = NumArray(19);        //  N11 , \field Evaporation Loss Factor
     404            6 :             tower.DriftLossFraction = NumArray(20) / 100.0; //  N12, \field Drift Loss Percent
     405            6 :             tower.ConcentrationRatio = NumArray(21);        //  N13, \field Blowdown Concentration Ratio
     406            6 :             tower.SizFac = NumArray(25);                    //  N17  \field Sizing Factor
     407            6 :             if (tower.SizFac <= 0.0) tower.SizFac = 1.0;
     408              : 
     409            6 :             tower.BlowdownMode = static_cast<Blowdown>(getEnumValue(BlowDownNamesUC, Util::makeUPPER(AlphArray(7))));
     410            6 :             if (tower.BlowdownMode == Blowdown::Schedule) {
     411            0 :                 if ((tower.blowdownSched = Sched::GetSchedule(state, AlphArray(8))) == nullptr) {
     412            0 :                     ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(8), AlphArray(8));
     413            0 :                     ErrorsFound = true;
     414              :                 }
     415              :             }
     416              : 
     417            6 :             if (AlphArray(9).empty()) {
     418            6 :                 tower.SuppliedByWaterSystem = false;
     419              :             } else { // water from storage tank
     420            0 :                 WaterManager::SetupTankDemandComponent(
     421            0 :                     state, AlphArray(1), s_ipsc->cCurrentModuleObject, AlphArray(9), ErrorsFound, tower.WaterTankID, tower.WaterTankDemandARRID);
     422            0 :                 tower.SuppliedByWaterSystem = true;
     423              :             }
     424              : 
     425              :             //   outdoor air inlet node
     426              : 
     427            6 :             if (s_ipsc->lAlphaFieldBlanks(10)) {
     428            6 :                 tower.OutdoorAirInletNodeNum = 0;
     429              :             } else {
     430            0 :                 tower.OutdoorAirInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     431            0 :                                                                                    AlphArray(10),
     432              :                                                                                    ErrorsFound,
     433              :                                                                                    DataLoopNode::ConnectionObjectType::CoolingTowerSingleSpeed,
     434            0 :                                                                                    tower.Name,
     435              :                                                                                    DataLoopNode::NodeFluidType::Air,
     436              :                                                                                    DataLoopNode::ConnectionType::OutsideAirReference,
     437              :                                                                                    NodeInputManager::CompFluidStream::Primary,
     438              :                                                                                    DataLoopNode::ObjectIsNotParent);
     439            0 :                 if (!OutAirNodeManager::CheckOutAirNodeNumber(state, tower.OutdoorAirInletNodeNum)) {
     440            0 :                     ShowSevereCustom(state,
     441              :                                      eoh,
     442            0 :                                      format("Outdoor Air Inlet Node Name not valid Outdoor Air Node= {}"
     443              :                                             "does not appear in an OutdoorAir:NodeList or as an OutdoorAir:Node.",
     444              :                                             AlphArray(10)));
     445            0 :                     ErrorsFound = true;
     446              :                 }
     447              :             }
     448              : 
     449              :             //   fluid bypass for single speed tower
     450            6 :             if (s_ipsc->lAlphaFieldBlanks(11) || AlphArray(11).empty()) {
     451            2 :                 tower.CapacityControl = CapacityCtrl::FanCycling; // FanCycling
     452            4 :             } else if ((tower.CapacityControl = static_cast<CapacityCtrl>(getEnumValue(CapacityCtrlNamesUC, AlphArray(11)))) ==
     453              :                        CapacityCtrl::Invalid) {
     454            0 :                 tower.CapacityControl = CapacityCtrl::FanCycling;
     455            0 :                 ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(11), AlphArray(11), "The default Fan Cycling is used.");
     456              :             }
     457              : 
     458              :             // added for multi-cell
     459            6 :             tower.NumCell = NumArray(22);
     460            6 :             if ((NumNums < 22) && (tower.NumCell == 0)) {
     461              :                 // assume Number of Cells not entered and should be defaulted
     462            0 :                 tower.NumCell = 1;
     463              :             }
     464            6 :             tower.MinFracFlowRate = NumArray(23);
     465            6 :             if ((NumNums < 23) && (tower.MinFracFlowRate == 0.0)) {
     466              :                 // assume Cell Minimum Water Flow Rate Fraction not entered and should be defaulted
     467            0 :                 tower.MinFracFlowRate = 0.33;
     468              :             }
     469            6 :             tower.MaxFracFlowRate = NumArray(24);
     470            6 :             if ((NumNums < 24) && (tower.MaxFracFlowRate == 0.0)) {
     471              :                 // assume Cell Maximum Water Flow Rate Fraction not entered and should be defaulted
     472            0 :                 tower.MaxFracFlowRate = 2.5;
     473              :             }
     474              : 
     475              :             //   cell control for single speed tower
     476            6 :             if (!s_ipsc->lAlphaFieldBlanks(12)) {
     477            2 :                 tower.cellCtrl = static_cast<CellCtrl>(getEnumValue(CellCtrlNamesUC, Util::makeUPPER(AlphArray(12))));
     478              :             }
     479              : 
     480              :             //   High speed air flow rate must be greater than free convection air flow rate.
     481              :             //   Can't tell yet if autosized, check later in initialize.
     482            6 :             if (tower.HighSpeedAirFlowRate <= tower.FreeConvAirFlowRate && tower.HighSpeedAirFlowRate != DataSizing::AutoSize) {
     483            0 :                 ShowSevereCustom(state, eoh, "Free convection air flow rate must be less than the design air flow rate.");
     484            0 :                 ErrorsFound = true;
     485              :             }
     486              : 
     487              :             //   Check various inputs if Performance Input Method = "UA and Design Water Flow Rate"
     488            6 :             if (tower.PerformanceInputMethod_Num == PIM::UFactor) {
     489            4 :                 if (tower.DesignWaterFlowRate == 0.0) {
     490            0 :                     ShowSevereCustom(state, eoh, "Tower performance input method requires a design water flow rate greater than zero.");
     491            0 :                     ErrorsFound = true;
     492              :                 }
     493            4 :                 if (tower.HighSpeedTowerUA <= tower.FreeConvTowerUA && tower.HighSpeedTowerUA != DataSizing::AutoSize) {
     494            0 :                     ShowSevereCustom(state, eoh, "Free convection UA must be less than the design tower UA.");
     495            0 :                     ErrorsFound = true;
     496              :                 }
     497            4 :                 if (tower.FreeConvTowerUA > 0.0 && tower.FreeConvAirFlowRate == 0.0) {
     498            0 :                     ShowSevereCustom(
     499              :                         state, eoh, "Free convection air flow rate must be greater than zero when free convection UA is greater than zero.");
     500            0 :                     ErrorsFound = true;
     501              :                 }
     502            2 :             } else if (tower.PerformanceInputMethod_Num == PIM::NominalCapacity) {
     503            2 :                 if (tower.TowerNominalCapacity == 0.0) {
     504            0 :                     ShowSevereCustom(state, eoh, "Tower performance input method requires valid nominal capacity.");
     505            0 :                     ErrorsFound = true;
     506              :                 }
     507            2 :                 if (tower.DesignWaterFlowRate != 0.0) {
     508            0 :                     if (tower.DesignWaterFlowRate > 0.0) {
     509            0 :                         ShowWarningCustom(state, eoh, "Nominal capacity input method and design water flow rate have been specified.");
     510              :                     } else {
     511            0 :                         ShowSevereCustom(
     512              :                             state, eoh, "Nominal capacity input method has been specified and design water flow rate is being autosized.");
     513              :                     }
     514            0 :                     ShowContinueError(state, "Design water flow rate will be set according to nominal tower capacity.");
     515              :                 }
     516            2 :                 if (tower.HighSpeedTowerUA != 0.0) {
     517            0 :                     if (tower.HighSpeedTowerUA > 0.0) {
     518            0 :                         ShowWarningCustom(state, eoh, "Nominal tower capacity and design tower UA have been specified.");
     519              :                     } else {
     520            0 :                         ShowSevereCustom(state, eoh, "Nominal tower capacity has been specified and design tower UA is being autosized.");
     521              :                     }
     522            0 :                     ShowContinueError(state, "Design tower UA will be set according to nominal tower capacity.");
     523              :                 }
     524            2 :                 if (tower.FreeConvTowerUA != 0.0) {
     525            0 :                     if (tower.FreeConvTowerUA > 0.0) {
     526            0 :                         ShowWarningCustom(state, eoh, "Nominal capacity input method and free convection UA have been specified.");
     527              :                     } else {
     528            0 :                         ShowSevereCustom(state, eoh, "Nominal capacity input method has been specified and free convection UA is being autosized.");
     529              :                     }
     530            0 :                     ShowContinueError(state, "Free convection UA will be set according to nominal tower capacity.");
     531              :                 }
     532            2 :                 if (tower.TowerFreeConvNomCap >= tower.TowerNominalCapacity) {
     533            0 :                     ShowSevereCustom(state, eoh, "Free convection nominal capacity must be less than the nominal (design) tower capacity.");
     534            0 :                     ErrorsFound = true;
     535              :                 }
     536            2 :                 if (tower.TowerFreeConvNomCap > 0.0 && tower.FreeConvAirFlowRate == 0.0) {
     537            0 :                     ShowSevereCustom(
     538              :                         state, eoh, "Free convection air flow must be greater than zero when tower free convection capacity is specified.");
     539            0 :                     ErrorsFound = true;
     540              :                 }
     541              :             } else { // Tower performance input method is not specified as a valid "choice"
     542            0 :                 ShowSevereInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(4), AlphArray(4));
     543            0 :                 ErrorsFound = true;
     544              :             }
     545              : 
     546            6 :             if (NumAlphas > 12) {
     547            3 :                 tower.EndUseSubcategory = AlphArray(13);
     548              :             } else {
     549            3 :                 tower.EndUseSubcategory = "General";
     550              :             }
     551              :         } // End Single-Speed Tower Loop
     552              : 
     553           15 :         s_ipsc->cCurrentModuleObject = cCoolingTower_TwoSpeed;
     554           19 :         for (int TwoSpeedTowerNumber = 1; TwoSpeedTowerNumber <= NumTwoSpeedTowers; ++TwoSpeedTowerNumber) {
     555            4 :             TowerNum = NumSingleSpeedTowers + TwoSpeedTowerNumber;
     556           12 :             s_ip->getObjectItem(state,
     557            4 :                                 s_ipsc->cCurrentModuleObject,
     558              :                                 TwoSpeedTowerNumber,
     559              :                                 AlphArray,
     560              :                                 NumAlphas,
     561              :                                 NumArray,
     562              :                                 NumNums,
     563              :                                 IOStat,
     564              :                                 _,
     565            4 :                                 s_ipsc->lAlphaFieldBlanks,
     566            4 :                                 s_ipsc->cAlphaFieldNames,
     567            4 :                                 s_ipsc->cNumericFieldNames);
     568              : 
     569            4 :             ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, AlphArray(1)};
     570              : 
     571            4 :             GlobalNames::VerifyUniqueInterObjectName(
     572            8 :                 state, UniqueSimpleTowerNames, AlphArray(1), s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaFieldNames(1), ErrorsFound);
     573              : 
     574            4 :             auto &tower = state.dataCondenserLoopTowers->towers(TowerNum);
     575            4 :             tower.Name = AlphArray(1);
     576            4 :             tower.TowerType = DataPlant::PlantEquipmentType::CoolingTower_TwoSpd;
     577            4 :             tower.TowerMassFlowRateMultiplier = 2.5;
     578            4 :             tower.WaterInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     579            4 :                                                                           AlphArray(2),
     580              :                                                                           ErrorsFound,
     581              :                                                                           DataLoopNode::ConnectionObjectType::CoolingTowerTwoSpeed,
     582            4 :                                                                           tower.Name,
     583              :                                                                           DataLoopNode::NodeFluidType::Water,
     584              :                                                                           DataLoopNode::ConnectionType::Inlet,
     585              :                                                                           NodeInputManager::CompFluidStream::Primary,
     586              :                                                                           DataLoopNode::ObjectIsNotParent);
     587            8 :             tower.WaterOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     588            4 :                                                                            AlphArray(3),
     589              :                                                                            ErrorsFound,
     590              :                                                                            DataLoopNode::ConnectionObjectType::CoolingTowerTwoSpeed,
     591            4 :                                                                            tower.Name,
     592              :                                                                            DataLoopNode::NodeFluidType::Water,
     593              :                                                                            DataLoopNode::ConnectionType::Outlet,
     594              :                                                                            NodeInputManager::CompFluidStream::Primary,
     595              :                                                                            DataLoopNode::ObjectIsNotParent);
     596            4 :             BranchNodeConnections::TestCompSet(state, s_ipsc->cCurrentModuleObject, AlphArray(1), AlphArray(2), AlphArray(3), "Chilled Water Nodes");
     597              : 
     598            4 :             if (NumAlphas >= 4) {
     599            4 :                 tower.PerformanceInputMethod_Num = static_cast<PIM>(getEnumValue(PIMNamesUC, Util::makeUPPER(AlphArray(4))));
     600              :             } else {
     601              :                 // Since Performance Input Method has been omitted then assume it to be UA and DESIGN WATER FLOW RATE
     602            0 :                 tower.PerformanceInputMethod_Num = PIM::UFactor;
     603              :             }
     604            4 :             tower.DesignWaterFlowRate = NumArray(1);
     605            4 :             if (tower.DesignWaterFlowRate == DataSizing::AutoSize) {
     606            0 :                 tower.DesignWaterFlowRateWasAutoSized = true;
     607              :             }
     608            4 :             tower.HighSpeedAirFlowRate = NumArray(2);
     609            4 :             if (tower.HighSpeedAirFlowRate == DataSizing::AutoSize) {
     610            4 :                 tower.HighSpeedAirFlowRateWasAutoSized = true;
     611              :             }
     612            4 :             tower.HighSpeedFanPower = NumArray(3);
     613            4 :             if (tower.HighSpeedFanPower == DataSizing::AutoSize) {
     614            4 :                 tower.HighSpeedFanPowerWasAutoSized = true;
     615              :             }
     616            4 :             tower.HighSpeedTowerUA = NumArray(4);
     617            4 :             if (tower.HighSpeedTowerUA == DataSizing::AutoSize) {
     618            0 :                 tower.HighSpeedTowerUAWasAutoSized = true;
     619              :             }
     620            4 :             tower.LowSpeedAirFlowRate = NumArray(5);
     621            4 :             if (tower.LowSpeedAirFlowRate == DataSizing::AutoSize) {
     622            4 :                 tower.LowSpeedAirFlowRateWasAutoSized = true;
     623              :             }
     624              : 
     625            4 :             tower.LowSpeedAirFlowRateSizingFactor = NumArray(6);
     626            4 :             tower.LowSpeedFanPower = NumArray(7);
     627            4 :             if (tower.LowSpeedFanPower == DataSizing::AutoSize) {
     628            4 :                 tower.LowSpeedFanPowerWasAutoSized = true;
     629              :             }
     630            4 :             tower.LowSpeedFanPowerSizingFactor = NumArray(8);
     631            4 :             tower.LowSpeedTowerUA = NumArray(9);
     632            4 :             if (tower.LowSpeedTowerUA == DataSizing::AutoSize) {
     633            3 :                 tower.LowSpeedTowerUAWasAutoSized = true;
     634              :             }
     635            4 :             tower.LowSpeedTowerUASizingFactor = NumArray(10);
     636            4 :             tower.FreeConvAirFlowRate = NumArray(11);
     637            4 :             if (tower.FreeConvAirFlowRate == DataSizing::AutoSize) {
     638            1 :                 tower.FreeConvAirFlowRateWasAutoSized = true;
     639              :             }
     640            4 :             tower.FreeConvAirFlowRateSizingFactor = NumArray(12);
     641            4 :             tower.FreeConvTowerUA = NumArray(13);
     642            4 :             if (tower.FreeConvTowerUA == DataSizing::AutoSize) {
     643            3 :                 tower.FreeConvTowerUAWasAutoSized = true;
     644              :             }
     645            4 :             tower.FreeConvTowerUASizingFactor = NumArray(14);
     646            4 :             tower.HeatRejectCapNomCapSizingRatio = NumArray(15);
     647            4 :             tower.TowerNominalCapacity = NumArray(16);
     648              : 
     649            4 :             tower.TowerLowSpeedNomCap = NumArray(17);
     650            4 :             if (tower.TowerLowSpeedNomCap == DataSizing::AutoSize) {
     651            1 :                 tower.TowerLowSpeedNomCapWasAutoSized = true;
     652              :             }
     653            4 :             tower.TowerLowSpeedNomCapSizingFactor = NumArray(18);
     654            4 :             tower.TowerFreeConvNomCap = NumArray(19);
     655            4 :             if (tower.TowerFreeConvNomCap == DataSizing::AutoSize) {
     656            0 :                 tower.TowerFreeConvNomCapWasAutoSized = true;
     657              :             }
     658            4 :             tower.TowerFreeConvNomCapSizingFactor = NumArray(20);
     659              :             // cooling tower design inlet conditions
     660            4 :             tower.DesInletAirDBTemp = NumArray(21);
     661            4 :             if (tower.DesInletAirDBTemp == 0) {
     662            0 :                 tower.DesInletAirDBTemp = 35.0;
     663            0 :                 tower.TowerInletCondsAutoSize = true;
     664              :             }
     665            4 :             tower.DesignInletWB = NumArray(22);
     666            4 :             if (tower.DesignInletWB == 0) {
     667            0 :                 tower.DesignInletWB = 25.6;
     668            0 :                 tower.TowerInletCondsAutoSize = true;
     669              :             }
     670            4 :             tower.DesignApproach = NumArray(23);
     671            4 :             if (tower.DesignApproach == DataSizing::AutoSize || tower.DesignApproach == 0) {
     672            2 :                 tower.DesignApproach = 3.9;
     673            2 :                 tower.TowerInletCondsAutoSize = true;
     674              :             }
     675            4 :             tower.DesignRange = NumArray(24);
     676            4 :             if (tower.DesignRange == DataSizing::AutoSize || tower.DesignRange == 0) {
     677            2 :                 tower.DesignRange = 5.5;
     678            2 :                 tower.TowerInletCondsAutoSize = true;
     679              :             }
     680              :             // set tower design water outlet and inlet temperatures
     681            4 :             tower.DesOutletWaterTemp = tower.DesignInletWB + tower.DesignApproach;
     682            4 :             tower.DesInletWaterTemp = tower.DesOutletWaterTemp + tower.DesignRange;
     683              :             //   Basin heater power as a function of temperature must be greater than or equal to 0
     684            4 :             tower.BasinHeaterPowerFTempDiff = NumArray(25);
     685            4 :             if (NumArray(25) < 0.0) {
     686            0 :                 ShowSevereCustom(state, eoh, "Basin heater power as a function of temperature difference must be >= 0");
     687            0 :                 ErrorsFound = true;
     688              :             }
     689              : 
     690            4 :             tower.BasinHeaterSetPointTemp = NumArray(26);
     691            4 :             if (tower.BasinHeaterPowerFTempDiff > 0.0) {
     692            0 :                 if (NumNums < 26) {
     693            0 :                     tower.BasinHeaterSetPointTemp = 2.0;
     694              :                 }
     695            0 :                 if (tower.BasinHeaterSetPointTemp < 2.0) {
     696            0 :                     ShowWarningCustom(state, eoh, format("{} is less than 2 deg C. Freezing could occur.", s_ipsc->cNumericFieldNames(26)));
     697              :                 }
     698              :             }
     699              : 
     700            4 :             if (!AlphArray(5).empty()) {
     701            1 :                 if ((tower.basinHeaterSched = Sched::GetSchedule(state, AlphArray(5))) == nullptr) {
     702            2 :                     ShowWarningItemNotFound(state,
     703              :                                             eoh,
     704            1 :                                             s_ipsc->cAlphaFieldNames(5),
     705            1 :                                             AlphArray(5),
     706              :                                             "Basin heater operation will not be modeled and the simulation continues");
     707              :                 }
     708              :             }
     709              : 
     710              :             // begin water use and systems get input
     711            4 :             tower.EvapLossMode = static_cast<EvapLoss>(getEnumValue(EvapLossNamesUC, Util::makeUPPER(AlphArray(6))));
     712            4 :             tower.UserEvapLossFactor = NumArray(27);        //  N23 , \field Evaporation Loss Factor
     713            4 :             tower.DriftLossFraction = NumArray(28) / 100.0; //  N24, \field Drift Loss Percent
     714            4 :             tower.ConcentrationRatio = NumArray(29);        //  N17, \field Blowdown Concentration Ratio
     715            4 :             tower.SizFac = NumArray(33);                    //  N21  \field Sizing Factor
     716            4 :             if (tower.SizFac <= 0.0) tower.SizFac = 1.0;
     717              : 
     718            4 :             tower.BlowdownMode = static_cast<Blowdown>(getEnumValue(BlowDownNamesUC, Util::makeUPPER(AlphArray(7))));
     719            4 :             if (tower.BlowdownMode == Blowdown::Schedule) {
     720            0 :                 if ((tower.blowdownSched = Sched::GetSchedule(state, AlphArray(8))) == nullptr) {
     721            0 :                     ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(8), AlphArray(8));
     722            0 :                     ErrorsFound = true;
     723              :                 }
     724              :             }
     725              : 
     726              :             // added for multi-cell
     727            4 :             tower.NumCell = NumArray(30);
     728            4 :             if ((NumNums < 30) && (tower.NumCell == 0)) {
     729              :                 // assume Number of Cells not entered and should be defaulted
     730            0 :                 tower.NumCell = 1;
     731              :             }
     732            4 :             tower.MinFracFlowRate = NumArray(31);
     733            4 :             if ((NumNums < 31) && (tower.MinFracFlowRate == 0.0)) {
     734              :                 // assume Cell Minimum Water Flow Rate Fraction not entered and should be defaulted
     735            0 :                 tower.MinFracFlowRate = 0.33;
     736              :             }
     737            4 :             tower.MaxFracFlowRate = NumArray(32);
     738            4 :             if ((NumNums < 32) && (tower.MaxFracFlowRate == 0.0)) {
     739              :                 // assume Cell Maximum Water Flow Rate Fraction not entered and should be defaulted
     740            0 :                 tower.MaxFracFlowRate = 2.5;
     741              :             }
     742              : 
     743              :             //   cell control for two speed tower
     744            4 :             if (!s_ipsc->lAlphaFieldBlanks(11)) {
     745            1 :                 tower.cellCtrl = static_cast<CellCtrl>(getEnumValue(CellCtrlNamesUC, Util::makeUPPER(AlphArray(11))));
     746              :             }
     747              : 
     748            4 :             if (s_ipsc->lAlphaFieldBlanks(9)) {
     749            4 :                 tower.SuppliedByWaterSystem = false;
     750              :             } else { // water from storage tank
     751            0 :                 WaterManager::SetupTankDemandComponent(
     752            0 :                     state, AlphArray(1), s_ipsc->cCurrentModuleObject, AlphArray(9), ErrorsFound, tower.WaterTankID, tower.WaterTankDemandARRID);
     753            0 :                 tower.SuppliedByWaterSystem = true;
     754              :             }
     755              : 
     756              :             //   outdoor air inlet node
     757            4 :             if (s_ipsc->lAlphaFieldBlanks(10)) {
     758            4 :                 tower.OutdoorAirInletNodeNum = 0;
     759              :             } else {
     760            0 :                 tower.OutdoorAirInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     761            0 :                                                                                    AlphArray(10),
     762              :                                                                                    ErrorsFound,
     763              :                                                                                    DataLoopNode::ConnectionObjectType::CoolingTowerTwoSpeed,
     764            0 :                                                                                    tower.Name,
     765              :                                                                                    DataLoopNode::NodeFluidType::Air,
     766              :                                                                                    DataLoopNode::ConnectionType::OutsideAirReference,
     767              :                                                                                    NodeInputManager::CompFluidStream::Primary,
     768              :                                                                                    DataLoopNode::ObjectIsNotParent);
     769            0 :                 if (!OutAirNodeManager::CheckOutAirNodeNumber(state, tower.OutdoorAirInletNodeNum)) {
     770            0 :                     ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(10), AlphArray(10));
     771            0 :                     ErrorsFound = true;
     772              :                 }
     773              :             }
     774              : 
     775              :             //   High speed air flow rate must be greater than low speed air flow rate.
     776              :             //   Can't tell yet if autosized, check later in initialize.
     777            4 :             if (tower.HighSpeedAirFlowRate <= tower.LowSpeedAirFlowRate && tower.HighSpeedAirFlowRate != DataSizing::AutoSize) {
     778            0 :                 ShowSevereError(state,
     779            0 :                                 format("{} \"{}\". Low speed air flow rate must be less than the high speed air flow rate.",
     780            0 :                                        s_ipsc->cCurrentModuleObject,
     781            0 :                                        tower.Name));
     782            0 :                 ErrorsFound = true;
     783              :             }
     784              :             //   Low speed air flow rate must be greater than free convection air flow rate.
     785              :             //   Can't tell yet if autosized, check later in initialize.
     786            4 :             if (tower.LowSpeedAirFlowRate <= tower.FreeConvAirFlowRate && tower.LowSpeedAirFlowRate != DataSizing::AutoSize) {
     787            0 :                 ShowSevereError(state,
     788            0 :                                 format("{} \"{}\". Free convection air flow rate must be less than the low speed air flow rate.",
     789            0 :                                        s_ipsc->cCurrentModuleObject,
     790            0 :                                        tower.Name));
     791            0 :                 ErrorsFound = true;
     792              :             }
     793              : 
     794              :             //   Check various inputs if Performance Input Method = "UA and Design Water Flow Rate"
     795            4 :             if (tower.PerformanceInputMethod_Num == PIM::UFactor) {
     796            0 :                 if (tower.DesignWaterFlowRate == 0.0) {
     797            0 :                     ShowSevereError(state,
     798            0 :                                     format("{} \"{}\". Tower performance input method requires a design water flow rate greater than zero.",
     799            0 :                                            s_ipsc->cCurrentModuleObject,
     800            0 :                                            tower.Name));
     801            0 :                     ErrorsFound = true;
     802              :                 }
     803            0 :                 if (tower.HighSpeedTowerUA <= tower.LowSpeedTowerUA && tower.HighSpeedTowerUA != DataSizing::AutoSize) {
     804            0 :                     ShowSevereError(state,
     805            0 :                                     format("{} \"{}\". Tower UA at low fan speed must be less than the tower UA at high fan speed.",
     806            0 :                                            s_ipsc->cCurrentModuleObject,
     807            0 :                                            tower.Name));
     808            0 :                     ErrorsFound = true;
     809              :                 }
     810            0 :                 if (tower.LowSpeedTowerUA <= tower.FreeConvTowerUA && tower.LowSpeedTowerUA != DataSizing::AutoSize) {
     811            0 :                     ShowSevereError(state,
     812            0 :                                     format("{} \"{}\". Tower UA at free convection air flow rate must be less than the tower UA at low fan speed.",
     813            0 :                                            s_ipsc->cCurrentModuleObject,
     814            0 :                                            tower.Name));
     815            0 :                     ErrorsFound = true;
     816              :                 }
     817            0 :                 if (tower.FreeConvTowerUA > 0.0 && tower.FreeConvAirFlowRate == 0.0) {
     818            0 :                     ShowSevereError(
     819              :                         state,
     820            0 :                         format("{} \"{}\". Free convection air flow rate must be greater than zero when free convection UA is greater than zero.",
     821            0 :                                s_ipsc->cCurrentModuleObject,
     822            0 :                                tower.Name));
     823            0 :                     ErrorsFound = true;
     824              :                 }
     825            4 :             } else if (tower.PerformanceInputMethod_Num == PIM::NominalCapacity) {
     826            4 :                 if (tower.TowerNominalCapacity == 0.0) {
     827            0 :                     ShowSevereError(state,
     828            0 :                                     format("{} \"{}\". Tower performance input method requires valid high-speed nominal capacity.",
     829            0 :                                            s_ipsc->cCurrentModuleObject,
     830            0 :                                            tower.Name));
     831            0 :                     ErrorsFound = true;
     832              :                 }
     833            4 :                 if (tower.TowerLowSpeedNomCap == 0.0) {
     834            0 :                     ShowSevereError(state,
     835            0 :                                     format("{} \"{}\". Tower performance input method requires valid low-speed nominal capacity.",
     836            0 :                                            s_ipsc->cCurrentModuleObject,
     837            0 :                                            tower.Name));
     838            0 :                     ErrorsFound = true;
     839              :                 }
     840            4 :                 if (tower.DesignWaterFlowRate != 0.0) {
     841            0 :                     if (tower.DesignWaterFlowRate > 0.0) {
     842            0 :                         ShowWarningError(state,
     843            0 :                                          format("{} \"{}\". Nominal capacity input method and design water flow rate have been specified.",
     844            0 :                                                 s_ipsc->cCurrentModuleObject,
     845            0 :                                                 tower.Name));
     846              :                     } else {
     847            0 :                         ShowSevereError(
     848              :                             state,
     849            0 :                             format("{} \"{}\". Nominal capacity input method has been specified and design water flow rate is being autosized.",
     850            0 :                                    s_ipsc->cCurrentModuleObject,
     851            0 :                                    tower.Name));
     852              :                     }
     853            0 :                     ShowContinueError(state, "Design water flow rate will be set according to nominal tower capacity.");
     854              :                 }
     855            4 :                 if (tower.HighSpeedTowerUA != 0.0) {
     856            0 :                     if (tower.HighSpeedTowerUA > 0.0) {
     857            0 :                         ShowWarningError(state,
     858            0 :                                          format("{} \"{}\". Nominal capacity input method and tower UA at high fan speed have been specified.",
     859            0 :                                                 s_ipsc->cCurrentModuleObject,
     860            0 :                                                 tower.Name));
     861              :                     } else {
     862            0 :                         ShowSevereError(
     863              :                             state,
     864            0 :                             format("{} \"{}\". Nominal capacity input method has been specified and tower UA at high fan speed is being autosized.",
     865            0 :                                    s_ipsc->cCurrentModuleObject,
     866            0 :                                    tower.Name));
     867              :                     }
     868            0 :                     ShowContinueError(state, "Tower UA at high fan speed will be set according to nominal tower capacity.");
     869              :                 }
     870            4 :                 if (tower.LowSpeedTowerUA != 0.0) {
     871            3 :                     if (tower.LowSpeedTowerUA > 0.0) {
     872            0 :                         ShowWarningError(state,
     873            0 :                                          format("{} \"{}\". Nominal capacity input method and tower UA at low fan speed have been specified.",
     874            0 :                                                 s_ipsc->cCurrentModuleObject,
     875            0 :                                                 tower.Name));
     876              :                     } else {
     877            6 :                         ShowSevereError(
     878              :                             state,
     879            6 :                             format("{} \"{}\". Nominal capacity input method has been specified and tower UA at low fan speed is being autosized.",
     880            3 :                                    s_ipsc->cCurrentModuleObject,
     881            3 :                                    tower.Name));
     882              :                     }
     883            9 :                     ShowContinueError(state, "Tower UA at low fan speed will be set according to nominal tower capacity.");
     884              :                 }
     885            4 :                 if (tower.FreeConvTowerUA != 0.0) {
     886            3 :                     if (tower.FreeConvTowerUA > 0.0) {
     887            0 :                         ShowWarningError(state,
     888            0 :                                          format("{} \"{}\". Nominal capacity input method and free convection UA have been specified.",
     889            0 :                                                 s_ipsc->cCurrentModuleObject,
     890            0 :                                                 tower.Name));
     891              :                     } else {
     892            6 :                         ShowSevereError(
     893              :                             state,
     894            6 :                             format("{} \"{}\". Nominal capacity input method has been specified and free convection UA is being autosized.",
     895            3 :                                    s_ipsc->cCurrentModuleObject,
     896            3 :                                    tower.Name));
     897              :                     }
     898            9 :                     ShowContinueError(state, "Free convection UA will be set according to nominal tower capacity.");
     899              :                 }
     900            4 :                 if (tower.TowerLowSpeedNomCap >= tower.TowerNominalCapacity) {
     901            0 :                     ShowSevereError(state,
     902            0 :                                     format("{} \"{}\". Low-speed nominal capacity must be less than the high-speed nominal capacity.",
     903            0 :                                            s_ipsc->cCurrentModuleObject,
     904            0 :                                            tower.Name));
     905            0 :                     ErrorsFound = true;
     906              :                 }
     907            4 :                 if (!tower.TowerLowSpeedNomCapWasAutoSized) {
     908            3 :                     if (tower.TowerFreeConvNomCap >= tower.TowerLowSpeedNomCap) {
     909            0 :                         ShowSevereError(state,
     910            0 :                                         format("{} \"{}\". Free convection nominal capacity must be less than the low-speed nominal capacity.",
     911            0 :                                                s_ipsc->cCurrentModuleObject,
     912            0 :                                                tower.Name));
     913            0 :                         ErrorsFound = true;
     914              :                     }
     915              :                 }
     916            4 :                 if (tower.TowerFreeConvNomCap > 0.0 && tower.FreeConvAirFlowRate == 0.0) {
     917            0 :                     ShowSevereCustom(
     918              :                         state, eoh, "Free convection air flow must be greater than zero when tower free convection capacity is specified.");
     919            0 :                     ErrorsFound = true;
     920              :                 }
     921              :             } else { // Tower performance input method is not specified as a valid "choice"
     922            0 :                 ShowSevereInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(4), AlphArray(4));
     923            0 :                 ErrorsFound = true;
     924              :             }
     925              : 
     926            4 :             if (NumAlphas > 11) {
     927            1 :                 tower.EndUseSubcategory = AlphArray(12);
     928              :             } else {
     929            3 :                 tower.EndUseSubcategory = "General";
     930              :             }
     931              :         } // End Two-Speed Tower Loop
     932              : 
     933           15 :         s_ipsc->cCurrentModuleObject = cCoolingTower_VariableSpeed;
     934           20 :         for (int VariableSpeedTowerNumber = 1; VariableSpeedTowerNumber <= NumVariableSpeedTowers; ++VariableSpeedTowerNumber) {
     935            5 :             TowerNum = NumSingleSpeedTowers + NumTwoSpeedTowers + VariableSpeedTowerNumber;
     936           15 :             s_ip->getObjectItem(state,
     937            5 :                                 s_ipsc->cCurrentModuleObject,
     938              :                                 VariableSpeedTowerNumber,
     939              :                                 AlphArray,
     940              :                                 NumAlphas,
     941              :                                 NumArray,
     942              :                                 NumNums,
     943              :                                 IOStat,
     944              :                                 _,
     945            5 :                                 s_ipsc->lAlphaFieldBlanks,
     946            5 :                                 s_ipsc->cAlphaFieldNames,
     947            5 :                                 s_ipsc->cNumericFieldNames);
     948            5 :             ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, AlphArray(1)};
     949            5 :             GlobalNames::VerifyUniqueInterObjectName(
     950           10 :                 state, UniqueSimpleTowerNames, AlphArray(1), s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaFieldNames(1), ErrorsFound);
     951              : 
     952            5 :             auto &tower = state.dataCondenserLoopTowers->towers(TowerNum);
     953            5 :             tower.Name = AlphArray(1);
     954            5 :             tower.TowerType = DataPlant::PlantEquipmentType::CoolingTower_VarSpd;
     955            5 :             tower.WaterInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     956            5 :                                                                           AlphArray(2),
     957              :                                                                           ErrorsFound,
     958              :                                                                           DataLoopNode::ConnectionObjectType::CoolingTowerVariableSpeed,
     959            5 :                                                                           AlphArray(1),
     960              :                                                                           DataLoopNode::NodeFluidType::Water,
     961              :                                                                           DataLoopNode::ConnectionType::Inlet,
     962              :                                                                           NodeInputManager::CompFluidStream::Primary,
     963              :                                                                           DataLoopNode::ObjectIsNotParent);
     964           10 :             tower.WaterOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     965            5 :                                                                            AlphArray(3),
     966              :                                                                            ErrorsFound,
     967              :                                                                            DataLoopNode::ConnectionObjectType::CoolingTowerVariableSpeed,
     968            5 :                                                                            AlphArray(1),
     969              :                                                                            DataLoopNode::NodeFluidType::Water,
     970              :                                                                            DataLoopNode::ConnectionType::Outlet,
     971              :                                                                            NodeInputManager::CompFluidStream::Primary,
     972              :                                                                            DataLoopNode::ObjectIsNotParent);
     973            5 :             BranchNodeConnections::TestCompSet(state, s_ipsc->cCurrentModuleObject, AlphArray(1), AlphArray(2), AlphArray(3), "Chilled Water Nodes");
     974              : 
     975            5 :             if ((Util::SameString(AlphArray(4), "CoolToolsUserDefined") || Util::SameString(AlphArray(4), "YorkCalcUserDefined")) &&
     976            0 :                 s_ipsc->lAlphaFieldBlanks(5)) {
     977            0 :                 ShowSevereCustom(state,
     978              :                                  eoh,
     979            0 :                                  format("A {} must be specified when {} is specified as CoolToolsUserDefined or YorkCalcUserDefined",
     980            0 :                                         s_ipsc->cAlphaFieldNames(5),
     981            0 :                                         s_ipsc->cAlphaFieldNames(4)));
     982            0 :                 ErrorsFound = true;
     983           10 :             } else if ((Util::SameString(AlphArray(4), "CoolToolsCrossFlow") || Util::SameString(AlphArray(4), "YorkCalc")) &&
     984            5 :                        !s_ipsc->lAlphaFieldBlanks(5)) {
     985            0 :                 ShowWarningCustom(state,
     986              :                                   eoh,
     987              :                                   "A Tower Model Coefficient Name is specified and the Tower Model Type is not specified as "
     988              :                                   "CoolToolsUserDefined or YorkCalcUserDefined. The CoolingTowerPerformance:CoolTools "
     989              :                                   "(orCoolingTowerPerformance:YorkCalc) data object will not be used.");
     990              :             } else {
     991            5 :                 tower.ModelCoeffObjectName = AlphArray(5);
     992              :             }
     993              : 
     994            5 :             if (!s_ipsc->lAlphaFieldBlanks(6)) {
     995            5 :                 tower.FanPowerfAirFlowCurve = Curve::GetCurveIndex(state, AlphArray(6));
     996            5 :                 if (tower.FanPowerfAirFlowCurve == 0) {
     997            2 :                     ShowWarningCustom(state,
     998              :                                       eoh,
     999            4 :                                       format("The Fan Power Ratio as a function of Air Flow Rate Ratio Curve Name specified as {} was not found."
    1000              :                                              "Fan Power as a function of Air Flow Rate Ratio will default to Fan Power = (Air Flow Rate Ratio)^3."
    1001              :                                              "The simulation continues.",
    1002              :                                              AlphArray(6)));
    1003              :                 }
    1004              :             }
    1005              : 
    1006            5 :             auto &vstower = state.dataCondenserLoopTowers->towers(TowerNum);
    1007              : 
    1008            5 :             if (Util::SameString(AlphArray(4), "CoolToolsCrossFlow")) {
    1009            3 :                 tower.TowerModelType = ModelType::CoolToolsXFModel;
    1010              :                 //     set cross-flow model coefficients
    1011              :                 //       Outputs approach in C
    1012            3 :                 vstower.Coeff[0] = 0.52049709836241;
    1013            3 :                 vstower.Coeff[1] = -10.617046395344;
    1014            3 :                 vstower.Coeff[2] = 10.7292974722538;
    1015            3 :                 vstower.Coeff[3] = -2.74988377158227;
    1016            3 :                 vstower.Coeff[4] = 4.73629943913743;
    1017            3 :                 vstower.Coeff[5] = -8.25759700874711;
    1018            3 :                 vstower.Coeff[6] = 1.57640938114136;
    1019            3 :                 vstower.Coeff[7] = 6.51119643791324;
    1020            3 :                 vstower.Coeff[8] = 1.50433525206692;
    1021            3 :                 vstower.Coeff[9] = -3.2888529287801;
    1022            3 :                 vstower.Coeff[10] = 0.0257786145353773;
    1023            3 :                 vstower.Coeff[11] = 0.182464289315254;
    1024            3 :                 vstower.Coeff[12] = -0.0818947291400898;
    1025            3 :                 vstower.Coeff[13] = -0.215010003996285;
    1026            3 :                 vstower.Coeff[14] = 0.0186741309635284;
    1027            3 :                 vstower.Coeff[15] = 0.0536824177590012;
    1028            3 :                 vstower.Coeff[16] = -0.00270968955115031;
    1029            3 :                 vstower.Coeff[17] = 0.00112277498589279;
    1030            3 :                 vstower.Coeff[18] = -0.00127758497497718;
    1031            3 :                 vstower.Coeff[19] = 0.0000760420796601607;
    1032            3 :                 vstower.Coeff[20] = 1.43600088336017;
    1033            3 :                 vstower.Coeff[21] = -0.5198695909109;
    1034            3 :                 vstower.Coeff[22] = 0.117339576910507;
    1035            3 :                 vstower.Coeff[23] = 1.50492810819924;
    1036            3 :                 vstower.Coeff[24] = -0.135898905926974;
    1037            3 :                 vstower.Coeff[25] = -0.152577581866506;
    1038            3 :                 vstower.Coeff[26] = -0.0533843828114562;
    1039            3 :                 vstower.Coeff[27] = 0.00493294869565511;
    1040            3 :                 vstower.Coeff[28] = -0.00796260394174197;
    1041            3 :                 vstower.Coeff[29] = 0.000222619828621544;
    1042            3 :                 vstower.Coeff[30] = -0.0543952001568055;
    1043            3 :                 vstower.Coeff[31] = 0.00474266879161693;
    1044            3 :                 vstower.Coeff[32] = -0.0185854671815598;
    1045            3 :                 vstower.Coeff[33] = 0.00115667701293848;
    1046            3 :                 vstower.Coeff[34] = 0.000807370664460284;
    1047              : 
    1048              :                 //       set minimum and maximum boundaries for CoolTools crossflow model input variables
    1049            3 :                 vstower.MinInletAirWBTemp = -1.0;
    1050            3 :                 vstower.MaxInletAirWBTemp = 26.6667;
    1051            3 :                 vstower.MinRangeTemp = 1.1111;
    1052            3 :                 vstower.MaxRangeTemp = 11.1111;
    1053            3 :                 vstower.MinApproachTemp = 1.1111;
    1054            3 :                 vstower.MaxApproachTemp = 11.1111;
    1055            3 :                 vstower.MinWaterFlowRatio = 0.75;
    1056            3 :                 vstower.MaxWaterFlowRatio = 1.25;
    1057              : 
    1058            2 :             } else if (Util::SameString(AlphArray(4), "YorkCalc")) {
    1059            2 :                 tower.TowerModelType = ModelType::YorkCalcModel;
    1060              :                 //     set counter-flow model coefficients
    1061              :                 //       Outputs approach in C
    1062            2 :                 vstower.Coeff[0] = -0.359741205;
    1063            2 :                 vstower.Coeff[1] = -0.055053608;
    1064            2 :                 vstower.Coeff[2] = 0.0023850432;
    1065            2 :                 vstower.Coeff[3] = 0.173926877;
    1066            2 :                 vstower.Coeff[4] = -0.0248473764;
    1067            2 :                 vstower.Coeff[5] = 0.00048430224;
    1068            2 :                 vstower.Coeff[6] = -0.005589849456;
    1069            2 :                 vstower.Coeff[7] = 0.0005770079712;
    1070            2 :                 vstower.Coeff[8] = -0.00001342427256;
    1071            2 :                 vstower.Coeff[9] = 2.84765801111111;
    1072            2 :                 vstower.Coeff[10] = -0.121765149;
    1073            2 :                 vstower.Coeff[11] = 0.0014599242;
    1074            2 :                 vstower.Coeff[12] = 1.680428651;
    1075            2 :                 vstower.Coeff[13] = -0.0166920786;
    1076            2 :                 vstower.Coeff[14] = -0.0007190532;
    1077            2 :                 vstower.Coeff[15] = -0.025485194448;
    1078            2 :                 vstower.Coeff[16] = 0.0000487491696;
    1079            2 :                 vstower.Coeff[17] = 0.00002719234152;
    1080            2 :                 vstower.Coeff[18] = -0.0653766255555556;
    1081            2 :                 vstower.Coeff[19] = -0.002278167;
    1082            2 :                 vstower.Coeff[20] = 0.0002500254;
    1083            2 :                 vstower.Coeff[21] = -0.0910565458;
    1084            2 :                 vstower.Coeff[22] = 0.00318176316;
    1085            2 :                 vstower.Coeff[23] = 0.000038621772;
    1086            2 :                 vstower.Coeff[24] = -0.0034285382352;
    1087            2 :                 vstower.Coeff[25] = 0.00000856589904;
    1088            2 :                 vstower.Coeff[26] = -0.000001516821552;
    1089              : 
    1090              :                 //       set minimum and maximum boundaries for YorkCalc model input variables
    1091            2 :                 vstower.MinInletAirWBTemp = -34.4;
    1092            2 :                 vstower.MaxInletAirWBTemp = 29.4444;
    1093            2 :                 vstower.MinRangeTemp = 1.1111;
    1094            2 :                 vstower.MaxRangeTemp = 22.2222;
    1095            2 :                 vstower.MinApproachTemp = 1.1111;
    1096            2 :                 vstower.MaxApproachTemp = 40.0;
    1097            2 :                 vstower.MinWaterFlowRatio = 0.75;
    1098            2 :                 vstower.MaxWaterFlowRatio = 1.25;
    1099            2 :                 vstower.MaxLiquidToGasRatio = 8.0;
    1100              : 
    1101            0 :             } else if (Util::SameString(AlphArray(4), "CoolToolsUserDefined")) {
    1102            0 :                 tower.TowerModelType = ModelType::CoolToolsUserDefined;
    1103              :                 // Nested Get-input routines below.  Should pull out of here and read in beforehand.
    1104            0 :                 for (VSModelCoeffNum = 1; VSModelCoeffNum <= NumVSCoolToolsModelCoeffs; ++VSModelCoeffNum) {
    1105            0 :                     s_ip->getObjectItem(
    1106              :                         state, "CoolingTowerPerformance:CoolTools", VSModelCoeffNum, AlphArray2, NumAlphas2, NumArray2, NumNums2, IOStat);
    1107              : 
    1108            0 :                     if (!Util::SameString(AlphArray2(1), tower.ModelCoeffObjectName)) continue;
    1109            0 :                     vstower.FoundModelCoeff = true;
    1110              :                     // verify the correct number of coefficients for the CoolTools model
    1111            0 :                     if (NumNums2 != 43) {
    1112            0 :                         ShowSevereError(state,
    1113            0 :                                         format("CoolingTower:VariableSpeed \"{}\". The number of numeric inputs for object "
    1114              :                                                "CoolingTowerPerformance:CoolTools \"{}\" must equal 43.",
    1115            0 :                                                tower.Name,
    1116            0 :                                                tower.ModelCoeffObjectName));
    1117            0 :                         ErrorsFound = true;
    1118              :                     } else {
    1119              : 
    1120            0 :                         vstower.MinInletAirWBTemp = NumArray2(1);
    1121            0 :                         vstower.MaxInletAirWBTemp = NumArray2(2);
    1122            0 :                         vstower.MinRangeTemp = NumArray2(3);
    1123            0 :                         vstower.MaxRangeTemp = NumArray2(4);
    1124            0 :                         vstower.MinApproachTemp = NumArray2(5);
    1125            0 :                         vstower.MaxApproachTemp = NumArray2(6);
    1126            0 :                         vstower.MinWaterFlowRatio = NumArray2(7);
    1127            0 :                         vstower.MaxWaterFlowRatio = NumArray2(8);
    1128              : 
    1129            0 :                         for (CoeffNum = 9; CoeffNum <= NumNums2; ++CoeffNum) {
    1130            0 :                             vstower.Coeff[CoeffNum - 9] = NumArray2(CoeffNum);
    1131              :                         }
    1132              :                     }
    1133            0 :                     break;
    1134              :                 }
    1135            0 :                 if (!vstower.FoundModelCoeff) {
    1136            0 :                     ShowSevereError(state,
    1137            0 :                                     format("CoolingTower:VariableSpeed \"{}\". User defined name for variable speed cooling tower model coefficients "
    1138              :                                            "object not found = {}",
    1139            0 :                                            tower.Name,
    1140            0 :                                            tower.ModelCoeffObjectName));
    1141            0 :                     ErrorsFound = true;
    1142              :                 }
    1143            0 :             } else if (Util::SameString(AlphArray(4), "YorkCalcUserDefined")) {
    1144            0 :                 tower.TowerModelType = ModelType::YorkCalcUserDefined;
    1145              :                 // Nested Get-input routines below.  Should pull out of here and read in beforehand.
    1146            0 :                 for (VSModelCoeffNum = 1; VSModelCoeffNum <= NumVSYorkCalcModelCoeffs; ++VSModelCoeffNum) {
    1147            0 :                     s_ip->getObjectItem(
    1148              :                         state, "CoolingTowerPerformance:YorkCalc", VSModelCoeffNum, AlphArray2, NumAlphas2, NumArray2, NumNums2, IOStat);
    1149            0 :                     if (!Util::SameString(AlphArray2(1), tower.ModelCoeffObjectName)) continue;
    1150            0 :                     vstower.FoundModelCoeff = true;
    1151              :                     // verify the correct number of coefficients for the YorkCalc model
    1152            0 :                     if (NumNums2 != 36) {
    1153            0 :                         ShowSevereError(state,
    1154            0 :                                         format("CoolingTower:VariableSpeed \"{}\". The number of numeric inputs for object "
    1155              :                                                "CoolingTowerPerformance:YorkCalc \"{}\" must equal 36.",
    1156            0 :                                                tower.Name,
    1157            0 :                                                tower.ModelCoeffObjectName));
    1158            0 :                         ErrorsFound = true;
    1159              :                     } else {
    1160              : 
    1161            0 :                         vstower.MinInletAirWBTemp = NumArray2(1);
    1162            0 :                         vstower.MaxInletAirWBTemp = NumArray2(2);
    1163            0 :                         vstower.MinRangeTemp = NumArray2(3);
    1164            0 :                         vstower.MaxRangeTemp = NumArray2(4);
    1165            0 :                         vstower.MinApproachTemp = NumArray2(5);
    1166            0 :                         vstower.MaxApproachTemp = NumArray2(6);
    1167            0 :                         vstower.MinWaterFlowRatio = NumArray2(7);
    1168            0 :                         vstower.MaxWaterFlowRatio = NumArray2(8);
    1169            0 :                         vstower.MaxLiquidToGasRatio = NumArray2(9);
    1170              : 
    1171            0 :                         for (CoeffNum = 10; CoeffNum <= NumNums2; ++CoeffNum) {
    1172            0 :                             vstower.Coeff[CoeffNum - 10] = NumArray2(CoeffNum);
    1173              :                         }
    1174              :                     }
    1175            0 :                     break;
    1176              :                 }
    1177              : 
    1178            0 :                 if (!vstower.FoundModelCoeff) {
    1179            0 :                     ShowSevereError(state,
    1180            0 :                                     format("{} \"{}\". User defined name for variable speed cooling tower model coefficients object not found = {}",
    1181            0 :                                            s_ipsc->cCurrentModuleObject,
    1182            0 :                                            tower.Name,
    1183            0 :                                            tower.ModelCoeffObjectName));
    1184            0 :                     ErrorsFound = true;
    1185              :                 }
    1186              :             } else {
    1187            0 :                 ShowSevereInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(5), AlphArray(5));
    1188            0 :                 ErrorsFound = true;
    1189              :             }
    1190              : 
    1191            5 :             tower.TowerMassFlowRateMultiplier = vstower.MaxWaterFlowRatio;
    1192              : 
    1193              :             //   check user defined minimums to be greater than 0
    1194            5 :             if (vstower.MinApproachTemp < 0.0) {
    1195            0 :                 ShowSevereCustom(state, eoh, "User defined minimum approach temperature must be > 0");
    1196            0 :                 ErrorsFound = true;
    1197              :             }
    1198            5 :             if (vstower.MinRangeTemp < 0.0) {
    1199            0 :                 ShowSevereCustom(state, eoh, "User defined minimum range temperature must be > 0");
    1200            0 :                 ErrorsFound = true;
    1201              :             }
    1202            5 :             if (vstower.MinWaterFlowRatio < 0.0) {
    1203            0 :                 ShowSevereCustom(state, eoh, "User defined minimum water flow rate ratio must be > 0");
    1204            0 :                 ErrorsFound = true;
    1205              :             }
    1206              : 
    1207              :             //   check that the user defined maximums are greater than the minimums
    1208            5 :             if (vstower.MaxApproachTemp < vstower.MinApproachTemp) {
    1209            0 :                 ShowSevereCustom(state, eoh, "User defined maximum approach temperature must be > the minimum approach temperature");
    1210            0 :                 ErrorsFound = true;
    1211              :             }
    1212            5 :             if (vstower.MaxRangeTemp < vstower.MinRangeTemp) {
    1213            0 :                 ShowSevereCustom(state, eoh, "User defined maximum range temperature must be > the minimum range temperature");
    1214            0 :                 ErrorsFound = true;
    1215              :             }
    1216            5 :             if (vstower.MaxWaterFlowRatio < vstower.MinWaterFlowRatio) {
    1217            0 :                 ShowSevereCustom(state, eoh, "User defined maximum water flow rate ratio must be > the minimum water flow rate ratio");
    1218            0 :                 ErrorsFound = true;
    1219              :             }
    1220              : 
    1221            5 :             tower.DesignInletWB = NumArray(1);
    1222            5 :             if (NumArray(1) < vstower.MinInletAirWBTemp || NumArray(1) > vstower.MaxInletAirWBTemp) {
    1223            0 :                 ShowSevereCustom(state,
    1224              :                                  eoh,
    1225            0 :                                  format("The design inlet air wet-bulb temperature of {:5.2F}"
    1226              :                                         "must be within the model limits of {:5.2F} and {:5.2F} degrees C",
    1227            0 :                                         tower.DesignInletWB,
    1228            0 :                                         vstower.MinInletAirWBTemp,
    1229            0 :                                         vstower.MaxInletAirWBTemp));
    1230            0 :                 ErrorsFound = true;
    1231              :             }
    1232              : 
    1233            5 :             tower.DesignApproach = NumArray(2);
    1234            5 :             if (NumArray(2) < vstower.MinApproachTemp || NumArray(2) > vstower.MaxApproachTemp) {
    1235            0 :                 ShowSevereCustom(state,
    1236              :                                  eoh,
    1237            0 :                                  format("The design approach temperature of {:5.2F}"
    1238              :                                         "must be within the model limits of {:5.2F} and {:5.2F} degrees C",
    1239            0 :                                         tower.DesignApproach,
    1240            0 :                                         vstower.MinApproachTemp,
    1241            0 :                                         vstower.MaxApproachTemp));
    1242            0 :                 ErrorsFound = true;
    1243              :             }
    1244              : 
    1245            5 :             tower.DesignRange = NumArray(3);
    1246            5 :             if (NumArray(3) < vstower.MinRangeTemp || NumArray(3) > vstower.MaxRangeTemp) {
    1247            0 :                 ShowSevereCustom(state,
    1248              :                                  eoh,
    1249            0 :                                  format("The design range temperature of {:5.2F}"
    1250              :                                         "must be within the model limits of {:5.2F} and {:5.2F} degrees C",
    1251            0 :                                         tower.DesignRange,
    1252            0 :                                         vstower.MinRangeTemp,
    1253            0 :                                         vstower.MaxRangeTemp));
    1254            0 :                 ErrorsFound = true;
    1255              :             }
    1256              : 
    1257              :             // set tower design water outlet and inlet temperatures
    1258            5 :             tower.DesOutletWaterTemp = tower.DesignInletWB + tower.DesignApproach;
    1259            5 :             tower.DesInletWaterTemp = tower.DesOutletWaterTemp + tower.DesignRange;
    1260              : 
    1261            5 :             tower.DesignWaterFlowRate = NumArray(4);
    1262            5 :             if (tower.DesignWaterFlowRate == DataSizing::AutoSize) {
    1263            2 :                 tower.DesignWaterFlowRateWasAutoSized = true;
    1264              :             }
    1265            5 :             if (NumArray(4) <= 0.0 && NumArray(4) != DataSizing::AutoSize) {
    1266            0 :                 ShowSevereCustom(state, eoh, "Design water flow rate must be > 0");
    1267            0 :                 ErrorsFound = true;
    1268              :             }
    1269              : 
    1270            5 :             tower.HighSpeedAirFlowRate = NumArray(5);
    1271            5 :             if (tower.HighSpeedAirFlowRate == DataSizing::AutoSize) {
    1272            2 :                 tower.HighSpeedAirFlowRateWasAutoSized = true;
    1273              :             }
    1274            5 :             if (NumArray(5) <= 0.0 && NumArray(5) != DataSizing::AutoSize) {
    1275            0 :                 ShowSevereCustom(state, eoh, "Design air flow rate must be > 0");
    1276            0 :                 ErrorsFound = true;
    1277              :             }
    1278              : 
    1279            5 :             tower.HighSpeedFanPower = NumArray(6);
    1280            5 :             if (tower.HighSpeedFanPower == DataSizing::AutoSize) {
    1281            0 :                 tower.HighSpeedFanPowerWasAutoSized = true;
    1282              :             }
    1283            5 :             if (NumArray(6) <= 0.0 && NumArray(6) != DataSizing::AutoSize) {
    1284            0 :                 ShowSevereCustom(state, eoh, "Design fan power must be > 0");
    1285            0 :                 ErrorsFound = true;
    1286              :             }
    1287              : 
    1288              :             //   minimum air flow rate fraction must be >= 0.2 and <= 0.5, below this value the tower fan cycles to maintain the setpoint
    1289            5 :             tower.MinimumVSAirFlowFrac = NumArray(7);
    1290            5 :             tower.MinimumVSAirFlowFrac = NumArray(7);
    1291            5 :             if (NumArray(7) < 0.2 || NumArray(7) > 0.5) {
    1292            0 :                 ShowSevereCustom(state, eoh, "Minimum VS air flow rate ratio must be >= 0.2 and <= 0.5");
    1293            0 :                 ErrorsFound = true;
    1294              :             }
    1295              : 
    1296              :             //   fraction of tower capacity in free convection regime must be >= to 0 and <= 0.2
    1297            5 :             tower.FreeConvectionCapacityFraction = NumArray(8);
    1298            5 :             if (NumArray(8) < 0.0 || NumArray(8) > 0.2) {
    1299            0 :                 ShowSevereCustom(state, eoh, "Fraction of tower capacity in free convection regime must be >= 0 and <= 0.2");
    1300            0 :                 ErrorsFound = true;
    1301              :             }
    1302              : 
    1303              :             //   Basin heater power as a function of temperature must be greater than or equal to 0
    1304            5 :             tower.BasinHeaterPowerFTempDiff = NumArray(9);
    1305            5 :             if (NumArray(9) < 0.0) {
    1306            0 :                 ShowSevereCustom(state, eoh, "Basin heater power as a function of temperature difference must be >= 0");
    1307            0 :                 ErrorsFound = true;
    1308              :             }
    1309              : 
    1310            5 :             tower.BasinHeaterSetPointTemp = NumArray(10);
    1311            5 :             if (tower.BasinHeaterPowerFTempDiff > 0.0) {
    1312            0 :                 if (NumNums < 10) {
    1313            0 :                     tower.BasinHeaterSetPointTemp = 2.0;
    1314              :                 }
    1315            0 :                 if (tower.BasinHeaterSetPointTemp < 2.0) {
    1316            0 :                     ShowWarningCustom(state, eoh, format("{} is less than 2 deg C. Freezing could occur.", s_ipsc->cNumericFieldNames(10)));
    1317              :                 }
    1318              :             }
    1319              : 
    1320              :             // Performance Input Method for Variable Speed Towers is assigned to be UA AND DESIGN WATER FLOW RATE
    1321              :             // for autosizing calculations (see SizeTower)
    1322            5 :             tower.PerformanceInputMethod_Num = PIM::UFactor;
    1323              : 
    1324            5 :             if (!AlphArray(7).empty()) {
    1325            0 :                 if ((tower.basinHeaterSched = Sched::GetSchedule(state, AlphArray(7))) == nullptr) {
    1326            0 :                     ShowWarningItemNotFound(state,
    1327              :                                             eoh,
    1328            0 :                                             s_ipsc->cAlphaFieldNames(7),
    1329            0 :                                             AlphArray(7),
    1330              :                                             "Basin heater operation will not be modeled and the simulation continues.");
    1331              :                 }
    1332              :             }
    1333              : 
    1334              :             // begin water use and systems get input
    1335            5 :             tower.EvapLossMode = static_cast<EvapLoss>(getEnumValue(EvapLossNamesUC, Util::makeUPPER(AlphArray(8))));
    1336            5 :             tower.UserEvapLossFactor = NumArray(11);        //  N11 , \field Evaporation Loss Factor
    1337            5 :             tower.DriftLossFraction = NumArray(12) / 100.0; //  N12, \field Drift Loss Percent
    1338            5 :             tower.ConcentrationRatio = NumArray(13);        //  N13, \field Blowdown Concentration Ratio
    1339            5 :             tower.SizFac = NumArray(17);                    //  N14  \field Sizing Factor
    1340            5 :             if (tower.SizFac <= 0.0) tower.SizFac = 1.0;
    1341              : 
    1342            5 :             tower.BlowdownMode = static_cast<Blowdown>(getEnumValue(BlowDownNamesUC, Util::makeUPPER(AlphArray(9))));
    1343            5 :             if (tower.BlowdownMode == Blowdown::Schedule) {
    1344            0 :                 if ((tower.blowdownSched = Sched::GetSchedule(state, AlphArray(10))) == nullptr) {
    1345            0 :                     ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(10), AlphArray(10));
    1346            0 :                     ErrorsFound = true;
    1347              :                 }
    1348              :             }
    1349              : 
    1350              :             // added for multi-cell
    1351            5 :             tower.NumCell = NumArray(14);
    1352            5 :             if ((NumNums < 14) && (tower.NumCell == 0)) {
    1353              :                 // assume Number of Cells not entered and should be defaulted
    1354            0 :                 tower.NumCell = 1;
    1355              :             }
    1356            5 :             tower.MinFracFlowRate = NumArray(15);
    1357            5 :             if ((NumNums < 15) && (tower.MinFracFlowRate == 0.0)) {
    1358              :                 // assume Cell Minimum Water Flow Rate Fraction not entered and should be defaulted
    1359            0 :                 tower.MinFracFlowRate = 0.33;
    1360              :             }
    1361            5 :             tower.MaxFracFlowRate = NumArray(16);
    1362            5 :             if ((NumNums < 16) && (tower.MaxFracFlowRate == 0.0)) {
    1363              :                 // assume Cell Maximum Water Flow Rate Fraction not entered and should be defaulted
    1364            0 :                 tower.MaxFracFlowRate = 2.5;
    1365              :             }
    1366              : 
    1367              :             //   cell control for variable speed tower
    1368            5 :             if (!s_ipsc->lAlphaFieldBlanks(13)) {
    1369            2 :                 tower.cellCtrl = static_cast<CellCtrl>(getEnumValue(CellCtrlNamesUC, Util::makeUPPER(AlphArray(13))));
    1370              :             }
    1371              : 
    1372            5 :             if (s_ipsc->lAlphaFieldBlanks(11)) {
    1373            5 :                 tower.SuppliedByWaterSystem = false;
    1374              :             } else { // water from storage tank
    1375            0 :                 WaterManager::SetupTankDemandComponent(
    1376            0 :                     state, AlphArray(1), s_ipsc->cCurrentModuleObject, AlphArray(11), ErrorsFound, tower.WaterTankID, tower.WaterTankDemandARRID);
    1377            0 :                 tower.SuppliedByWaterSystem = true;
    1378              :             }
    1379              : 
    1380              :             //   outdoor air inlet node
    1381            5 :             if (s_ipsc->lAlphaFieldBlanks(12)) {
    1382            5 :                 tower.OutdoorAirInletNodeNum = 0;
    1383              :             } else {
    1384            0 :                 tower.OutdoorAirInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
    1385            0 :                                                                                    AlphArray(12),
    1386              :                                                                                    ErrorsFound,
    1387              :                                                                                    DataLoopNode::ConnectionObjectType::CoolingTowerVariableSpeed,
    1388            0 :                                                                                    tower.Name,
    1389              :                                                                                    DataLoopNode::NodeFluidType::Air,
    1390              :                                                                                    DataLoopNode::ConnectionType::OutsideAirReference,
    1391              :                                                                                    NodeInputManager::CompFluidStream::Primary,
    1392              :                                                                                    DataLoopNode::ObjectIsNotParent);
    1393            0 :                 if (!OutAirNodeManager::CheckOutAirNodeNumber(state, tower.OutdoorAirInletNodeNum)) {
    1394            0 :                     ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(12), AlphArray(12));
    1395            0 :                     ErrorsFound = true;
    1396              :                 }
    1397              :             }
    1398            5 :             if (NumAlphas > 13) {
    1399            5 :                 tower.EndUseSubcategory = AlphArray(14);
    1400              :             } else {
    1401            0 :                 tower.EndUseSubcategory = "General";
    1402              :             }
    1403              : 
    1404              :         } // End Variable-Speed Tower Loop
    1405              : 
    1406           15 :         s_ipsc->cCurrentModuleObject = cCoolingTower_VariableSpeedMerkel;
    1407           19 :         for (int MerkelVSTowerNum = 1; MerkelVSTowerNum <= NumVSMerkelTowers; ++MerkelVSTowerNum) {
    1408            4 :             TowerNum = NumSingleSpeedTowers + NumTwoSpeedTowers + NumVariableSpeedTowers + MerkelVSTowerNum;
    1409           12 :             s_ip->getObjectItem(state,
    1410            4 :                                 s_ipsc->cCurrentModuleObject,
    1411              :                                 MerkelVSTowerNum,
    1412              :                                 AlphArray,
    1413              :                                 NumAlphas,
    1414              :                                 NumArray,
    1415              :                                 NumNums,
    1416              :                                 IOStat,
    1417            4 :                                 s_ipsc->lNumericFieldBlanks,
    1418            4 :                                 s_ipsc->lAlphaFieldBlanks,
    1419            4 :                                 s_ipsc->cAlphaFieldNames,
    1420            4 :                                 s_ipsc->cNumericFieldNames);
    1421              : 
    1422            4 :             ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, AlphArray(1)};
    1423            4 :             GlobalNames::VerifyUniqueInterObjectName(
    1424            8 :                 state, UniqueSimpleTowerNames, AlphArray(1), s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaFieldNames(1), ErrorsFound);
    1425            4 :             auto &tower = state.dataCondenserLoopTowers->towers(TowerNum);
    1426            4 :             tower.Name = AlphArray(1);
    1427            4 :             tower.TowerType = DataPlant::PlantEquipmentType::CoolingTower_VarSpdMerkel;
    1428            4 :             tower.WaterInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
    1429            4 :                                                                           AlphArray(2),
    1430              :                                                                           ErrorsFound,
    1431              :                                                                           DataLoopNode::ConnectionObjectType::CoolingTowerVariableSpeedMerkel,
    1432            4 :                                                                           AlphArray(1),
    1433              :                                                                           DataLoopNode::NodeFluidType::Water,
    1434              :                                                                           DataLoopNode::ConnectionType::Inlet,
    1435              :                                                                           NodeInputManager::CompFluidStream::Primary,
    1436              :                                                                           DataLoopNode::ObjectIsNotParent);
    1437            8 :             tower.WaterOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
    1438            4 :                                                                            AlphArray(3),
    1439              :                                                                            ErrorsFound,
    1440              :                                                                            DataLoopNode::ConnectionObjectType::CoolingTowerVariableSpeedMerkel,
    1441            4 :                                                                            AlphArray(1),
    1442              :                                                                            DataLoopNode::NodeFluidType::Water,
    1443              :                                                                            DataLoopNode::ConnectionType::Outlet,
    1444              :                                                                            NodeInputManager::CompFluidStream::Primary,
    1445              :                                                                            DataLoopNode::ObjectIsNotParent);
    1446            4 :             BranchNodeConnections::TestCompSet(state, s_ipsc->cCurrentModuleObject, AlphArray(1), AlphArray(2), AlphArray(3), "Chilled Water Nodes");
    1447              : 
    1448            4 :             if (Util::SameString(AlphArray(4), "UFactorTimesAreaAndDesignWaterFlowRate")) {
    1449            0 :                 tower.PerformanceInputMethod_Num = PIM::UFactor;
    1450            4 :             } else if (Util::SameString(AlphArray(4), "NominalCapacity")) {
    1451            4 :                 tower.PerformanceInputMethod_Num = PIM::NominalCapacity;
    1452              :             } else {
    1453            0 :                 ShowSevereInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(4), AlphArray(4));
    1454            0 :                 ErrorsFound = true;
    1455              :             }
    1456              : 
    1457            4 :             tower.FanPowerfAirFlowCurve = Curve::GetCurveIndex(state, AlphArray(5));
    1458            4 :             if (tower.FanPowerfAirFlowCurve == 0) {
    1459            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(5), AlphArray(5));
    1460            0 :                 ErrorsFound = true;
    1461              :             }
    1462              : 
    1463            4 :             tower.HeatRejectCapNomCapSizingRatio = NumArray(1);
    1464            4 :             tower.TowerNominalCapacity = NumArray(2);
    1465            4 :             if (tower.TowerNominalCapacity == DataSizing::AutoSize) {
    1466            1 :                 tower.TowerNominalCapacityWasAutoSized = true;
    1467              :             }
    1468            4 :             tower.TowerFreeConvNomCap = NumArray(3);
    1469            4 :             if (tower.TowerFreeConvNomCap == DataSizing::AutoSize) {
    1470            4 :                 tower.TowerFreeConvNomCapWasAutoSized = true;
    1471              :             }
    1472            4 :             tower.TowerFreeConvNomCapSizingFactor = NumArray(4);
    1473            4 :             tower.DesignWaterFlowRate = NumArray(5);
    1474            4 :             if (tower.DesignWaterFlowRate == DataSizing::AutoSize) {
    1475            3 :                 tower.DesignWaterFlowRateWasAutoSized = true;
    1476              :             }
    1477            4 :             tower.DesignWaterFlowPerUnitNomCap = NumArray(6);
    1478            4 :             tower.HighSpeedAirFlowRate = NumArray(7);
    1479            4 :             if (tower.HighSpeedAirFlowRate == DataSizing::AutoSize) {
    1480            4 :                 tower.HighSpeedAirFlowRateWasAutoSized = true;
    1481              :             }
    1482            4 :             tower.DefaultedDesignAirFlowScalingFactor = s_ipsc->lNumericFieldBlanks(8);
    1483            4 :             tower.DesignAirFlowPerUnitNomCap = NumArray(8);
    1484            4 :             tower.MinimumVSAirFlowFrac = NumArray(9);
    1485            4 :             tower.HighSpeedFanPower = NumArray(10);
    1486            4 :             if (tower.HighSpeedFanPower == DataSizing::AutoSize) {
    1487            3 :                 tower.HighSpeedFanPowerWasAutoSized = true;
    1488              :             }
    1489            4 :             tower.DesignFanPowerPerUnitNomCap = NumArray(11);
    1490            4 :             tower.FreeConvAirFlowRate = NumArray(12);
    1491            4 :             if (tower.FreeConvAirFlowRate == DataSizing::AutoSize) {
    1492            4 :                 tower.FreeConvAirFlowRateWasAutoSized = true;
    1493              :             }
    1494            4 :             tower.FreeConvAirFlowRateSizingFactor = NumArray(13);
    1495            4 :             tower.HighSpeedTowerUA = NumArray(14);
    1496            4 :             if (tower.HighSpeedTowerUA == DataSizing::AutoSize) {
    1497            0 :                 tower.HighSpeedTowerUAWasAutoSized = true;
    1498              :             }
    1499            4 :             tower.FreeConvTowerUA = NumArray(15);
    1500            4 :             if (tower.FreeConvTowerUA == DataSizing::AutoSize) {
    1501            0 :                 tower.FreeConvTowerUAWasAutoSized = true;
    1502              :             }
    1503            4 :             tower.FreeConvTowerUASizingFactor = NumArray(16);
    1504              : 
    1505            4 :             tower.UAModFuncAirFlowRatioCurvePtr = Curve::GetCurveIndex(state, AlphArray(6));
    1506            4 :             if (tower.UAModFuncAirFlowRatioCurvePtr == 0) {
    1507            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(6), AlphArray(6));
    1508            0 :                 ErrorsFound = true;
    1509              :             }
    1510              : 
    1511            4 :             tower.UAModFuncWetBulbDiffCurvePtr = Curve::GetCurveIndex(state, AlphArray(7));
    1512            4 :             if (tower.UAModFuncWetBulbDiffCurvePtr == 0) {
    1513            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(7), AlphArray(7));
    1514            0 :                 ErrorsFound = true;
    1515              :             }
    1516              : 
    1517            4 :             tower.UAModFuncWaterFlowRatioCurvePtr = Curve::GetCurveIndex(state, AlphArray(8));
    1518            4 :             if (tower.UAModFuncWaterFlowRatioCurvePtr == 0) {
    1519            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(8), AlphArray(8));
    1520            0 :                 ErrorsFound = true;
    1521              :             }
    1522              :             // cooling tower design inlet conditions
    1523            4 :             tower.DesInletAirDBTemp = NumArray(17);
    1524            4 :             if (tower.DesInletAirDBTemp == 0) {
    1525            0 :                 tower.DesInletAirDBTemp = 35.0;
    1526            0 :                 tower.TowerInletCondsAutoSize = true;
    1527              :             }
    1528            4 :             tower.DesignInletWB = NumArray(18);
    1529            4 :             if (tower.DesignInletWB == 0) {
    1530            0 :                 tower.DesignInletWB = 25.6;
    1531            0 :                 tower.TowerInletCondsAutoSize = true;
    1532              :             }
    1533            4 :             tower.DesignApproach = NumArray(19);
    1534            4 :             if (tower.DesignApproach == DataSizing::AutoSize || tower.DesignApproach == 0) {
    1535            2 :                 tower.DesignApproach = 3.9;
    1536            2 :                 tower.TowerInletCondsAutoSize = true;
    1537              :             }
    1538            4 :             tower.DesignRange = NumArray(20);
    1539            4 :             if (tower.DesignRange == DataSizing::AutoSize || tower.DesignRange == 0) {
    1540            2 :                 tower.DesignRange = 5.5;
    1541            2 :                 tower.TowerInletCondsAutoSize = true;
    1542              :             }
    1543              :             // set tower design water outlet and inlet temperatures
    1544            4 :             tower.DesOutletWaterTemp = tower.DesignInletWB + tower.DesignApproach;
    1545            4 :             tower.DesInletWaterTemp = tower.DesOutletWaterTemp + tower.DesignRange;
    1546              :             //   Basin heater power as a function of temperature must be greater than or equal to 0
    1547            4 :             tower.BasinHeaterPowerFTempDiff = NumArray(21);
    1548            4 :             if (NumArray(21) < 0.0) {
    1549            0 :                 ShowSevereCustom(state, eoh, "Basin heater power as a function of temperature difference must be >= 0");
    1550            0 :                 ErrorsFound = true;
    1551              :             }
    1552              : 
    1553            4 :             tower.BasinHeaterSetPointTemp = NumArray(22);
    1554            4 :             if (tower.BasinHeaterPowerFTempDiff > 0.0) {
    1555            0 :                 if (NumNums < 22) {
    1556            0 :                     tower.BasinHeaterSetPointTemp = 2.0;
    1557              :                 }
    1558            0 :                 if (tower.BasinHeaterSetPointTemp < 2.0) {
    1559            0 :                     ShowWarningCustom(state, eoh, format("{} is less than 2 deg C. Freezing could occur.", s_ipsc->cNumericFieldNames(22)));
    1560              :                 }
    1561              :             }
    1562              : 
    1563            4 :             if (!AlphArray(9).empty()) {
    1564            0 :                 if ((tower.basinHeaterSched = Sched::GetSchedule(state, AlphArray(9))) == nullptr) {
    1565            0 :                     ShowWarningItemNotFound(state,
    1566              :                                             eoh,
    1567            0 :                                             s_ipsc->cAlphaFieldNames(9),
    1568            0 :                                             AlphArray(9),
    1569              :                                             "Basin heater operation will not be modeled and the simulation continues");
    1570              :                 }
    1571              :             }
    1572              : 
    1573              :             // begin water use and systems get input
    1574            4 :             tower.EvapLossMode = static_cast<EvapLoss>(getEnumValue(EvapLossNamesUC, Util::makeUPPER(AlphArray(10))));
    1575            4 :             tower.UserEvapLossFactor = NumArray(23);        //  N23 , \field Evaporation Loss Factor
    1576            4 :             tower.DriftLossFraction = NumArray(24) / 100.0; //  N24, \field Drift Loss Percent
    1577            4 :             tower.ConcentrationRatio = NumArray(25);        //  N25, \field Blowdown Concentration Ratio
    1578            4 :             tower.SizFac = NumArray(29);                    //  N29  \field Sizing Factor
    1579            4 :             if (tower.SizFac <= 0.0) tower.SizFac = 1.0;
    1580              : 
    1581            4 :             tower.BlowdownMode = static_cast<Blowdown>(getEnumValue(BlowDownNamesUC, Util::makeUPPER(AlphArray(11))));
    1582            4 :             if (tower.BlowdownMode == Blowdown::Schedule) {
    1583            0 :                 if ((tower.blowdownSched = Sched::GetSchedule(state, AlphArray(12))) == nullptr) {
    1584            0 :                     ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(12), AlphArray(12));
    1585            0 :                     ErrorsFound = true;
    1586              :                 }
    1587              :             }
    1588              : 
    1589              :             // added for multi-cell
    1590            4 :             tower.NumCell = NumArray(26);
    1591            4 :             if ((NumNums < 26) && (tower.NumCell == 0)) {
    1592              :                 // assume Number of Cells not entered and should be defaulted
    1593            0 :                 tower.NumCell = 1;
    1594              :             }
    1595            4 :             tower.MinFracFlowRate = NumArray(27);
    1596            4 :             if ((NumNums < 27) && (tower.MinFracFlowRate == 0.0)) {
    1597              :                 // assume Cell Minimum Water Flow Rate Fraction not entered and should be defaulted
    1598            0 :                 tower.MinFracFlowRate = 0.33;
    1599              :             }
    1600            4 :             tower.MaxFracFlowRate = NumArray(28);
    1601            4 :             if ((NumNums < 28) && (tower.MaxFracFlowRate == 0.0)) {
    1602              :                 // assume Cell Maximum Water Flow Rate Fraction not entered and should be defaulted
    1603            0 :                 tower.MaxFracFlowRate = 2.5;
    1604              :             }
    1605            4 :             tower.TowerMassFlowRateMultiplier = tower.MaxFracFlowRate;
    1606              :             //   cell control for variable speed Merkel tower
    1607            4 :             if (!s_ipsc->lAlphaFieldBlanks(15)) {
    1608            1 :                 tower.cellCtrl = static_cast<CellCtrl>(getEnumValue(CellCtrlNamesUC, Util::makeUPPER(AlphArray(15))));
    1609              :             }
    1610              : 
    1611            4 :             if (s_ipsc->lAlphaFieldBlanks(13)) {
    1612            4 :                 tower.SuppliedByWaterSystem = false;
    1613              :             } else { // water from storage tank
    1614            0 :                 WaterManager::SetupTankDemandComponent(
    1615            0 :                     state, AlphArray(1), s_ipsc->cCurrentModuleObject, AlphArray(13), ErrorsFound, tower.WaterTankID, tower.WaterTankDemandARRID);
    1616            0 :                 tower.SuppliedByWaterSystem = true;
    1617              :             }
    1618              : 
    1619              :             //   outdoor air inlet node
    1620            4 :             if (s_ipsc->lAlphaFieldBlanks(14)) {
    1621            4 :                 tower.OutdoorAirInletNodeNum = 0;
    1622              :             } else {
    1623            0 :                 tower.OutdoorAirInletNodeNum =
    1624            0 :                     NodeInputManager::GetOnlySingleNode(state,
    1625            0 :                                                         AlphArray(14),
    1626              :                                                         ErrorsFound,
    1627              :                                                         DataLoopNode::ConnectionObjectType::CoolingTowerVariableSpeedMerkel,
    1628            0 :                                                         tower.Name,
    1629              :                                                         DataLoopNode::NodeFluidType::Air,
    1630              :                                                         DataLoopNode::ConnectionType::OutsideAirReference,
    1631              :                                                         NodeInputManager::CompFluidStream::Primary,
    1632              :                                                         DataLoopNode::ObjectIsNotParent);
    1633            0 :                 if (!OutAirNodeManager::CheckOutAirNodeNumber(state, tower.OutdoorAirInletNodeNum)) {
    1634            0 :                     ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(14), AlphArray(14));
    1635            0 :                     ErrorsFound = true;
    1636              :                 }
    1637              :             }
    1638            4 :             if (NumAlphas > 15) {
    1639            2 :                 tower.EndUseSubcategory = AlphArray(16);
    1640              :             } else {
    1641            2 :                 tower.EndUseSubcategory = "General";
    1642              :             }
    1643              : 
    1644              :         } // end merkel vs tower loop
    1645              : 
    1646           15 :         if (ErrorsFound) {
    1647            0 :             ShowFatalError(state, "Errors found in getting cooling tower input.");
    1648              :         }
    1649           65 :     }
    1650              : 
    1651           12 :     void CoolingTower::oneTimeInit(EnergyPlusData &state)
    1652              :     {
    1653              :         // Locate the tower on the plant loops for later usage
    1654           12 :         bool ErrorsFound = false;
    1655           12 :         PlantUtilities::ScanPlantLoopsForObject(state, this->Name, this->TowerType, this->plantLoc, ErrorsFound, _, _, _, _, _);
    1656           12 :         if (ErrorsFound) {
    1657            0 :             ShowFatalError(state, "initialize: Program terminated due to previous condition(s).");
    1658              :         }
    1659              : 
    1660              :         // check if setpoint on outlet node
    1661           24 :         this->SetpointIsOnOutlet = !((state.dataLoopNodes->Node(this->WaterOutletNodeNum).TempSetPoint == DataLoopNode::SensedNodeFlagValue) &&
    1662           12 :                                      (state.dataLoopNodes->Node(this->WaterOutletNodeNum).TempSetPointHi == DataLoopNode::SensedNodeFlagValue));
    1663           12 :     }
    1664              : 
    1665           19 :     void CoolingTower::initEachEnvironment(EnergyPlusData &state)
    1666              :     {
    1667              :         static constexpr std::string_view RoutineName("CoolingTower::initEachEnvironment");
    1668           19 :         Real64 const rho = this->plantLoc.loop->glycol->getDensity(state, Constant::InitConvTemp, RoutineName);
    1669           19 :         this->DesWaterMassFlowRate = this->DesignWaterFlowRate * rho;
    1670           19 :         this->DesWaterMassFlowRatePerCell = this->DesWaterMassFlowRate / this->NumCell;
    1671           19 :         PlantUtilities::InitComponentNodes(state, 0.0, this->DesWaterMassFlowRate, this->WaterInletNodeNum, this->WaterOutletNodeNum);
    1672           19 :     }
    1673              : 
    1674        14243 :     void CoolingTower::initialize(EnergyPlusData &state)
    1675              :     {
    1676              : 
    1677              :         // SUBROUTINE INFORMATION:
    1678              :         //       AUTHOR         Fred Buhl
    1679              :         //       DATE WRITTEN   May 2002
    1680              :         //       MODIFIED       Don Shirey Sept/Oct 2002, F Buhl Oct 2002
    1681              :         //       RE-ENGINEERED  R. Raustad, Oct 2005, moved Max/MinAvail to Init and allowed more than design
    1682              :         //                      water flow rate to pass through towers (up to 2.5 and 1.25 times the design flow
    1683              :         //                      for 1 or 2-speed and variable speed towers, respectively). Flow multiplier for
    1684              :         //                      VS Tower is defaulted to 1.25 and can be reassigned by user.
    1685              : 
    1686              :         // PURPOSE OF THIS SUBROUTINE:
    1687              :         // This subroutine is for initializations of the Cooling Tower components and for
    1688              :         // final checking of tower inputs (post autosizing)
    1689              : 
    1690              :         // METHODOLOGY EMPLOYED:
    1691              :         // Uses the status flags to trigger initializations.
    1692              : 
    1693        14243 :         if (this->oneTimeFlag) {
    1694           12 :             this->setupOutputVariables(state);
    1695           12 :             this->oneTimeInit(state);
    1696           12 :             this->oneTimeFlag = false;
    1697              :         }
    1698              : 
    1699              :         // Begin environment initializations
    1700        14243 :         if (this->envrnFlag && state.dataGlobal->BeginEnvrnFlag && (state.dataPlnt->PlantFirstSizesOkayToFinalize)) {
    1701           19 :             this->initEachEnvironment(state);
    1702           19 :             this->envrnFlag = false;
    1703              :         }
    1704              : 
    1705        14243 :         if (!state.dataGlobal->BeginEnvrnFlag) {
    1706        13818 :             this->envrnFlag = true;
    1707              :         }
    1708              : 
    1709              :         // Each time initializations
    1710        14243 :         this->WaterTemp = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp;
    1711              : 
    1712        14243 :         if (this->OutdoorAirInletNodeNum != 0) {
    1713            0 :             this->AirTemp = state.dataLoopNodes->Node(this->OutdoorAirInletNodeNum).Temp;
    1714            0 :             this->AirHumRat = state.dataLoopNodes->Node(this->OutdoorAirInletNodeNum).HumRat;
    1715            0 :             this->AirPress = state.dataLoopNodes->Node(this->OutdoorAirInletNodeNum).Press;
    1716            0 :             this->AirWetBulb = state.dataLoopNodes->Node(this->OutdoorAirInletNodeNum).OutAirWetBulb;
    1717              :         } else {
    1718        14243 :             this->AirTemp = state.dataEnvrn->OutDryBulbTemp;
    1719        14243 :             this->AirHumRat = state.dataEnvrn->OutHumRat;
    1720        14243 :             this->AirPress = state.dataEnvrn->OutBaroPress;
    1721        14243 :             this->AirWetBulb = state.dataEnvrn->OutWetBulbTemp;
    1722              :         }
    1723              : 
    1724        14243 :         this->WaterMassFlowRate =
    1725        14243 :             PlantUtilities::RegulateCondenserCompFlowReqOp(state, this->plantLoc, this->DesWaterMassFlowRate * this->TowerMassFlowRateMultiplier);
    1726              : 
    1727        14243 :         PlantUtilities::SetComponentFlowRate(state, this->WaterMassFlowRate, this->WaterInletNodeNum, this->WaterOutletNodeNum, this->plantLoc);
    1728              : 
    1729              :         // Added for fluid bypass. 8/2008
    1730        14243 :         this->BypassFraction = 0.0;
    1731        14243 :         this->BasinHeaterPower = 0.0;
    1732        14243 :         this->airFlowRateRatio = 0.0;
    1733        14243 :     }
    1734              : 
    1735           12 :     void CoolingTower::setupOutputVariables(EnergyPlusData &state)
    1736              :     {
    1737              :         // Set up output variables CurrentModuleObject='CoolingTower:SingleSpeed'
    1738           12 :         if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_SingleSpd) {
    1739           10 :             SetupOutputVariable(state,
    1740              :                                 "Cooling Tower Inlet Temperature",
    1741              :                                 Constant::Units::C,
    1742            5 :                                 this->InletWaterTemp,
    1743              :                                 OutputProcessor::TimeStepType::System,
    1744              :                                 OutputProcessor::StoreType::Average,
    1745            5 :                                 this->Name);
    1746           10 :             SetupOutputVariable(state,
    1747              :                                 "Cooling Tower Outlet Temperature",
    1748              :                                 Constant::Units::C,
    1749            5 :                                 this->OutletWaterTemp,
    1750              :                                 OutputProcessor::TimeStepType::System,
    1751              :                                 OutputProcessor::StoreType::Average,
    1752            5 :                                 this->Name);
    1753           10 :             SetupOutputVariable(state,
    1754              :                                 "Cooling Tower Mass Flow Rate",
    1755              :                                 Constant::Units::kg_s,
    1756            5 :                                 this->WaterMassFlowRate,
    1757              :                                 OutputProcessor::TimeStepType::System,
    1758              :                                 OutputProcessor::StoreType::Average,
    1759            5 :                                 this->Name);
    1760           10 :             SetupOutputVariable(state,
    1761              :                                 "Cooling Tower Heat Transfer Rate",
    1762              :                                 Constant::Units::W,
    1763            5 :                                 this->Qactual,
    1764              :                                 OutputProcessor::TimeStepType::System,
    1765              :                                 OutputProcessor::StoreType::Average,
    1766            5 :                                 this->Name);
    1767           10 :             SetupOutputVariable(state,
    1768              :                                 "Cooling Tower Fan Electricity Rate",
    1769              :                                 Constant::Units::W,
    1770            5 :                                 this->FanPower,
    1771              :                                 OutputProcessor::TimeStepType::System,
    1772              :                                 OutputProcessor::StoreType::Average,
    1773            5 :                                 this->Name);
    1774           10 :             SetupOutputVariable(state,
    1775              :                                 "Cooling Tower Fan Electricity Energy",
    1776              :                                 Constant::Units::J,
    1777            5 :                                 this->FanEnergy,
    1778              :                                 OutputProcessor::TimeStepType::System,
    1779              :                                 OutputProcessor::StoreType::Sum,
    1780            5 :                                 this->Name,
    1781              :                                 Constant::eResource::Electricity,
    1782              :                                 OutputProcessor::Group::Plant,
    1783              :                                 OutputProcessor::EndUseCat::HeatRejection,
    1784              :                                 this->EndUseSubcategory);
    1785              :             // Added for fluid bypass
    1786           10 :             SetupOutputVariable(state,
    1787              :                                 "Cooling Tower Bypass Fraction",
    1788              :                                 Constant::Units::None,
    1789            5 :                                 this->BypassFraction,
    1790              :                                 OutputProcessor::TimeStepType::System,
    1791              :                                 OutputProcessor::StoreType::Average,
    1792            5 :                                 this->Name);
    1793            5 :             SetupOutputVariable(state,
    1794              :                                 "Cooling Tower Operating Cells Count",
    1795              :                                 Constant::Units::None,
    1796            5 :                                 this->NumCellOn,
    1797              :                                 OutputProcessor::TimeStepType::System,
    1798              :                                 OutputProcessor::StoreType::Average,
    1799            5 :                                 this->Name);
    1800           10 :             SetupOutputVariable(state,
    1801              :                                 "Cooling Tower Fan Cycling Ratio",
    1802              :                                 Constant::Units::None,
    1803            5 :                                 this->FanCyclingRatio,
    1804              :                                 OutputProcessor::TimeStepType::System,
    1805              :                                 OutputProcessor::StoreType::Average,
    1806            5 :                                 this->Name);
    1807            5 :             if (this->BasinHeaterPowerFTempDiff > 0.0) {
    1808            0 :                 SetupOutputVariable(state,
    1809              :                                     "Cooling Tower Basin Heater Electricity Rate",
    1810              :                                     Constant::Units::W,
    1811            0 :                                     this->BasinHeaterPower,
    1812              :                                     OutputProcessor::TimeStepType::System,
    1813              :                                     OutputProcessor::StoreType::Average,
    1814            0 :                                     this->Name);
    1815            0 :                 SetupOutputVariable(state,
    1816              :                                     "Cooling Tower Basin Heater Electricity Energy",
    1817              :                                     Constant::Units::J,
    1818            0 :                                     this->BasinHeaterConsumption,
    1819              :                                     OutputProcessor::TimeStepType::System,
    1820              :                                     OutputProcessor::StoreType::Sum,
    1821            0 :                                     this->Name,
    1822              :                                     Constant::eResource::Electricity,
    1823              :                                     OutputProcessor::Group::Plant,
    1824              :                                     OutputProcessor::EndUseCat::HeatRejection,
    1825              :                                     "BasinHeater");
    1826              :             }
    1827              :         }
    1828              : 
    1829              :         // CurrentModuleObject='CoolingTower:TwoSpeed'
    1830           12 :         if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_TwoSpd) {
    1831            4 :             SetupOutputVariable(state,
    1832              :                                 "Cooling Tower Inlet Temperature",
    1833              :                                 Constant::Units::C,
    1834            2 :                                 this->InletWaterTemp,
    1835              :                                 OutputProcessor::TimeStepType::System,
    1836              :                                 OutputProcessor::StoreType::Average,
    1837            2 :                                 this->Name);
    1838            4 :             SetupOutputVariable(state,
    1839              :                                 "Cooling Tower Outlet Temperature",
    1840              :                                 Constant::Units::C,
    1841            2 :                                 this->OutletWaterTemp,
    1842              :                                 OutputProcessor::TimeStepType::System,
    1843              :                                 OutputProcessor::StoreType::Average,
    1844            2 :                                 this->Name);
    1845            4 :             SetupOutputVariable(state,
    1846              :                                 "Cooling Tower Mass Flow Rate",
    1847              :                                 Constant::Units::kg_s,
    1848            2 :                                 this->WaterMassFlowRate,
    1849              :                                 OutputProcessor::TimeStepType::System,
    1850              :                                 OutputProcessor::StoreType::Average,
    1851            2 :                                 this->Name);
    1852            4 :             SetupOutputVariable(state,
    1853              :                                 "Cooling Tower Heat Transfer Rate",
    1854              :                                 Constant::Units::W,
    1855            2 :                                 this->Qactual,
    1856              :                                 OutputProcessor::TimeStepType::System,
    1857              :                                 OutputProcessor::StoreType::Average,
    1858            2 :                                 this->Name);
    1859            4 :             SetupOutputVariable(state,
    1860              :                                 "Cooling Tower Fan Electricity Rate",
    1861              :                                 Constant::Units::W,
    1862            2 :                                 this->FanPower,
    1863              :                                 OutputProcessor::TimeStepType::System,
    1864              :                                 OutputProcessor::StoreType::Average,
    1865            2 :                                 this->Name);
    1866            4 :             SetupOutputVariable(state,
    1867              :                                 "Cooling Tower Fan Electricity Energy",
    1868              :                                 Constant::Units::J,
    1869            2 :                                 this->FanEnergy,
    1870              :                                 OutputProcessor::TimeStepType::System,
    1871              :                                 OutputProcessor::StoreType::Sum,
    1872            2 :                                 this->Name,
    1873              :                                 Constant::eResource::Electricity,
    1874              :                                 OutputProcessor::Group::Plant,
    1875              :                                 OutputProcessor::EndUseCat::HeatRejection,
    1876              :                                 this->EndUseSubcategory);
    1877            4 :             SetupOutputVariable(state,
    1878              :                                 "Cooling Tower Fan Cycling Ratio",
    1879              :                                 Constant::Units::None,
    1880            2 :                                 this->FanCyclingRatio,
    1881              :                                 OutputProcessor::TimeStepType::System,
    1882              :                                 OutputProcessor::StoreType::Average,
    1883            2 :                                 this->Name);
    1884            2 :             SetupOutputVariable(state,
    1885              :                                 "Cooling Tower Fan Speed Level",
    1886              :                                 Constant::Units::None,
    1887            2 :                                 this->SpeedSelected,
    1888              :                                 OutputProcessor::TimeStepType::System,
    1889              :                                 OutputProcessor::StoreType::Average,
    1890            2 :                                 this->Name);
    1891            2 :             SetupOutputVariable(state,
    1892              :                                 "Cooling Tower Operating Cells Count",
    1893              :                                 Constant::Units::None,
    1894            2 :                                 this->NumCellOn,
    1895              :                                 OutputProcessor::TimeStepType::System,
    1896              :                                 OutputProcessor::StoreType::Average,
    1897            2 :                                 this->Name);
    1898            2 :             if (this->BasinHeaterPowerFTempDiff > 0.0) {
    1899            0 :                 SetupOutputVariable(state,
    1900              :                                     "Cooling Tower Basin Heater Electricity Rate",
    1901              :                                     Constant::Units::W,
    1902            0 :                                     this->BasinHeaterPower,
    1903              :                                     OutputProcessor::TimeStepType::System,
    1904              :                                     OutputProcessor::StoreType::Average,
    1905            0 :                                     this->Name);
    1906            0 :                 SetupOutputVariable(state,
    1907              :                                     "Cooling Tower Basin Heater Electricity Energy",
    1908              :                                     Constant::Units::J,
    1909            0 :                                     this->BasinHeaterConsumption,
    1910              :                                     OutputProcessor::TimeStepType::System,
    1911              :                                     OutputProcessor::StoreType::Sum,
    1912            0 :                                     this->Name,
    1913              :                                     Constant::eResource::Electricity,
    1914              :                                     OutputProcessor::Group::Plant,
    1915              :                                     OutputProcessor::EndUseCat::HeatRejection,
    1916              :                                     "BasinHeater");
    1917              :             }
    1918              :         }
    1919              : 
    1920              :         // CurrentModuleObject='CoolingTower:VariableSpeed'
    1921           12 :         if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_VarSpd) {
    1922            4 :             SetupOutputVariable(state,
    1923              :                                 "Cooling Tower Inlet Temperature",
    1924              :                                 Constant::Units::C,
    1925            2 :                                 this->InletWaterTemp,
    1926              :                                 OutputProcessor::TimeStepType::System,
    1927              :                                 OutputProcessor::StoreType::Average,
    1928            2 :                                 this->Name);
    1929            4 :             SetupOutputVariable(state,
    1930              :                                 "Cooling Tower Outlet Temperature",
    1931              :                                 Constant::Units::C,
    1932            2 :                                 this->OutletWaterTemp,
    1933              :                                 OutputProcessor::TimeStepType::System,
    1934              :                                 OutputProcessor::StoreType::Average,
    1935            2 :                                 this->Name);
    1936            4 :             SetupOutputVariable(state,
    1937              :                                 "Cooling Tower Mass Flow Rate",
    1938              :                                 Constant::Units::kg_s,
    1939            2 :                                 this->WaterMassFlowRate,
    1940              :                                 OutputProcessor::TimeStepType::System,
    1941              :                                 OutputProcessor::StoreType::Average,
    1942            2 :                                 this->Name);
    1943            4 :             SetupOutputVariable(state,
    1944              :                                 "Cooling Tower Heat Transfer Rate",
    1945              :                                 Constant::Units::W,
    1946            2 :                                 this->Qactual,
    1947              :                                 OutputProcessor::TimeStepType::System,
    1948              :                                 OutputProcessor::StoreType::Average,
    1949            2 :                                 this->Name);
    1950            4 :             SetupOutputVariable(state,
    1951              :                                 "Cooling Tower Fan Electricity Rate",
    1952              :                                 Constant::Units::W,
    1953            2 :                                 this->FanPower,
    1954              :                                 OutputProcessor::TimeStepType::System,
    1955              :                                 OutputProcessor::StoreType::Average,
    1956            2 :                                 this->Name);
    1957            4 :             SetupOutputVariable(state,
    1958              :                                 "Cooling Tower Fan Electricity Energy",
    1959              :                                 Constant::Units::J,
    1960            2 :                                 this->FanEnergy,
    1961              :                                 OutputProcessor::TimeStepType::System,
    1962              :                                 OutputProcessor::StoreType::Sum,
    1963            2 :                                 this->Name,
    1964              :                                 Constant::eResource::Electricity,
    1965              :                                 OutputProcessor::Group::Plant,
    1966              :                                 OutputProcessor::EndUseCat::HeatRejection,
    1967              :                                 this->EndUseSubcategory);
    1968            4 :             SetupOutputVariable(state,
    1969              :                                 "Cooling Tower Air Flow Rate Ratio",
    1970              :                                 Constant::Units::None,
    1971            2 :                                 this->AirFlowRatio,
    1972              :                                 OutputProcessor::TimeStepType::System,
    1973              :                                 OutputProcessor::StoreType::Average,
    1974            2 :                                 this->Name);
    1975            4 :             SetupOutputVariable(state,
    1976              :                                 "Cooling Tower Fan Part Load Ratio",
    1977              :                                 Constant::Units::None,
    1978            2 :                                 this->FanCyclingRatio,
    1979              :                                 OutputProcessor::TimeStepType::System,
    1980              :                                 OutputProcessor::StoreType::Average,
    1981            2 :                                 this->Name);
    1982            2 :             SetupOutputVariable(state,
    1983              :                                 "Cooling Tower Operating Cells Count",
    1984              :                                 Constant::Units::None,
    1985            2 :                                 this->NumCellOn,
    1986              :                                 OutputProcessor::TimeStepType::System,
    1987              :                                 OutputProcessor::StoreType::Average,
    1988            2 :                                 this->Name);
    1989            2 :             if (this->BasinHeaterPowerFTempDiff > 0.0) {
    1990            0 :                 SetupOutputVariable(state,
    1991              :                                     "Cooling Tower Basin Heater Electricity Rate",
    1992              :                                     Constant::Units::W,
    1993            0 :                                     this->BasinHeaterPower,
    1994              :                                     OutputProcessor::TimeStepType::System,
    1995              :                                     OutputProcessor::StoreType::Average,
    1996            0 :                                     this->Name);
    1997            0 :                 SetupOutputVariable(state,
    1998              :                                     "Cooling Tower Basin Heater Electricity Energy",
    1999              :                                     Constant::Units::J,
    2000            0 :                                     this->BasinHeaterConsumption,
    2001              :                                     OutputProcessor::TimeStepType::System,
    2002              :                                     OutputProcessor::StoreType::Sum,
    2003            0 :                                     this->Name,
    2004              :                                     Constant::eResource::Electricity,
    2005              :                                     OutputProcessor::Group::Plant,
    2006              :                                     OutputProcessor::EndUseCat::HeatRejection,
    2007              :                                     "BasinHeater");
    2008              :             }
    2009              :         }
    2010              : 
    2011              :         // CurrentModuleObject='CoolingTower:VariableSpeed:Merkel'
    2012           12 :         if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_VarSpdMerkel) {
    2013            6 :             SetupOutputVariable(state,
    2014              :                                 "Cooling Tower Inlet Temperature",
    2015              :                                 Constant::Units::C,
    2016            3 :                                 this->InletWaterTemp,
    2017              :                                 OutputProcessor::TimeStepType::System,
    2018              :                                 OutputProcessor::StoreType::Average,
    2019            3 :                                 this->Name);
    2020            6 :             SetupOutputVariable(state,
    2021              :                                 "Cooling Tower Outlet Temperature",
    2022              :                                 Constant::Units::C,
    2023            3 :                                 this->OutletWaterTemp,
    2024              :                                 OutputProcessor::TimeStepType::System,
    2025              :                                 OutputProcessor::StoreType::Average,
    2026            3 :                                 this->Name);
    2027            6 :             SetupOutputVariable(state,
    2028              :                                 "Cooling Tower Mass Flow Rate",
    2029              :                                 Constant::Units::kg_s,
    2030            3 :                                 this->WaterMassFlowRate,
    2031              :                                 OutputProcessor::TimeStepType::System,
    2032              :                                 OutputProcessor::StoreType::Average,
    2033            3 :                                 this->Name);
    2034            6 :             SetupOutputVariable(state,
    2035              :                                 "Cooling Tower Heat Transfer Rate",
    2036              :                                 Constant::Units::W,
    2037            3 :                                 this->Qactual,
    2038              :                                 OutputProcessor::TimeStepType::System,
    2039              :                                 OutputProcessor::StoreType::Average,
    2040            3 :                                 this->Name);
    2041            6 :             SetupOutputVariable(state,
    2042              :                                 "Cooling Tower Fan Electricity Rate",
    2043              :                                 Constant::Units::W,
    2044            3 :                                 this->FanPower,
    2045              :                                 OutputProcessor::TimeStepType::System,
    2046              :                                 OutputProcessor::StoreType::Average,
    2047            3 :                                 this->Name);
    2048            6 :             SetupOutputVariable(state,
    2049              :                                 "Cooling Tower Fan Electricity Energy",
    2050              :                                 Constant::Units::J,
    2051            3 :                                 this->FanEnergy,
    2052              :                                 OutputProcessor::TimeStepType::System,
    2053              :                                 OutputProcessor::StoreType::Sum,
    2054            3 :                                 this->Name,
    2055              :                                 Constant::eResource::Electricity,
    2056              :                                 OutputProcessor::Group::Plant,
    2057              :                                 OutputProcessor::EndUseCat::HeatRejection,
    2058              :                                 this->EndUseSubcategory);
    2059            6 :             SetupOutputVariable(state,
    2060              :                                 "Cooling Tower Fan Speed Ratio",
    2061              :                                 Constant::Units::None,
    2062            3 :                                 this->AirFlowRatio,
    2063              :                                 OutputProcessor::TimeStepType::System,
    2064              :                                 OutputProcessor::StoreType::Average,
    2065            3 :                                 this->Name);
    2066              : 
    2067            3 :             SetupOutputVariable(state,
    2068              :                                 "Cooling Tower Operating Cells Count",
    2069              :                                 Constant::Units::None,
    2070            3 :                                 this->NumCellOn,
    2071              :                                 OutputProcessor::TimeStepType::System,
    2072              :                                 OutputProcessor::StoreType::Average,
    2073            3 :                                 this->Name);
    2074            3 :             if (this->BasinHeaterPowerFTempDiff > 0.0) {
    2075            0 :                 SetupOutputVariable(state,
    2076              :                                     "Cooling Tower Basin Heater Electricity Rate",
    2077              :                                     Constant::Units::W,
    2078            0 :                                     this->BasinHeaterPower,
    2079              :                                     OutputProcessor::TimeStepType::System,
    2080              :                                     OutputProcessor::StoreType::Average,
    2081            0 :                                     this->Name);
    2082            0 :                 SetupOutputVariable(state,
    2083              :                                     "Cooling Tower Basin Heater Electricity Energy",
    2084              :                                     Constant::Units::J,
    2085            0 :                                     this->BasinHeaterConsumption,
    2086              :                                     OutputProcessor::TimeStepType::System,
    2087              :                                     OutputProcessor::StoreType::Sum,
    2088            0 :                                     this->Name,
    2089              :                                     Constant::eResource::Electricity,
    2090              :                                     OutputProcessor::Group::Plant,
    2091              :                                     OutputProcessor::EndUseCat::HeatRejection,
    2092              :                                     "BasinHeater");
    2093              :             }
    2094              :         }
    2095              :         // setup common water reporting for all types of towers.
    2096           12 :         if (this->SuppliedByWaterSystem) {
    2097            0 :             SetupOutputVariable(state,
    2098              :                                 "Cooling Tower Make Up Water Volume Flow Rate",
    2099              :                                 Constant::Units::m3_s,
    2100            0 :                                 this->MakeUpVdot,
    2101              :                                 OutputProcessor::TimeStepType::System,
    2102              :                                 OutputProcessor::StoreType::Average,
    2103            0 :                                 this->Name);
    2104            0 :             SetupOutputVariable(state,
    2105              :                                 "Cooling Tower Make Up Water Volume",
    2106              :                                 Constant::Units::m3,
    2107            0 :                                 this->MakeUpVol,
    2108              :                                 OutputProcessor::TimeStepType::System,
    2109              :                                 OutputProcessor::StoreType::Sum,
    2110            0 :                                 this->Name);
    2111            0 :             SetupOutputVariable(state,
    2112              :                                 "Cooling Tower Storage Tank Water Volume Flow Rate",
    2113              :                                 Constant::Units::m3_s,
    2114            0 :                                 this->TankSupplyVdot,
    2115              :                                 OutputProcessor::TimeStepType::System,
    2116              :                                 OutputProcessor::StoreType::Average,
    2117            0 :                                 this->Name);
    2118            0 :             SetupOutputVariable(state,
    2119              :                                 "Cooling Tower Storage Tank Water Volume",
    2120              :                                 Constant::Units::m3,
    2121            0 :                                 this->TankSupplyVol,
    2122              :                                 OutputProcessor::TimeStepType::System,
    2123              :                                 OutputProcessor::StoreType::Sum,
    2124            0 :                                 this->Name,
    2125              :                                 Constant::eResource::Water,
    2126              :                                 OutputProcessor::Group::Plant,
    2127              :                                 OutputProcessor::EndUseCat::HeatRejection);
    2128            0 :             SetupOutputVariable(state,
    2129              :                                 "Cooling Tower Starved Storage Tank Water Volume Flow Rate",
    2130              :                                 Constant::Units::m3_s,
    2131            0 :                                 this->StarvedMakeUpVdot,
    2132              :                                 OutputProcessor::TimeStepType::System,
    2133              :                                 OutputProcessor::StoreType::Average,
    2134            0 :                                 this->Name);
    2135            0 :             SetupOutputVariable(state,
    2136              :                                 "Cooling Tower Starved Storage Tank Water Volume",
    2137              :                                 Constant::Units::m3,
    2138            0 :                                 this->StarvedMakeUpVol,
    2139              :                                 OutputProcessor::TimeStepType::System,
    2140              :                                 OutputProcessor::StoreType::Sum,
    2141            0 :                                 this->Name);
    2142            0 :             SetupOutputVariable(state,
    2143              :                                 "Cooling Tower Make Up Mains Water Volume",
    2144              :                                 Constant::Units::m3,
    2145            0 :                                 this->StarvedMakeUpVol,
    2146              :                                 OutputProcessor::TimeStepType::System,
    2147              :                                 OutputProcessor::StoreType::Sum,
    2148            0 :                                 this->Name,
    2149              :                                 Constant::eResource::MainsWater,
    2150              :                                 OutputProcessor::Group::Plant,
    2151              :                                 OutputProcessor::EndUseCat::HeatRejection);
    2152              :         } else { // tower water from mains and gets metered
    2153           24 :             SetupOutputVariable(state,
    2154              :                                 "Cooling Tower Make Up Water Volume Flow Rate",
    2155              :                                 Constant::Units::m3_s,
    2156           12 :                                 this->MakeUpVdot,
    2157              :                                 OutputProcessor::TimeStepType::System,
    2158              :                                 OutputProcessor::StoreType::Average,
    2159           12 :                                 this->Name);
    2160           24 :             SetupOutputVariable(state,
    2161              :                                 "Cooling Tower Make Up Water Volume",
    2162              :                                 Constant::Units::m3,
    2163           12 :                                 this->MakeUpVol,
    2164              :                                 OutputProcessor::TimeStepType::System,
    2165              :                                 OutputProcessor::StoreType::Sum,
    2166           12 :                                 this->Name,
    2167              :                                 Constant::eResource::Water,
    2168              :                                 OutputProcessor::Group::Plant,
    2169              :                                 OutputProcessor::EndUseCat::HeatRejection);
    2170           24 :             SetupOutputVariable(state,
    2171              :                                 "Cooling Tower Make Up Mains Water Volume",
    2172              :                                 Constant::Units::m3,
    2173           12 :                                 this->MakeUpVol,
    2174              :                                 OutputProcessor::TimeStepType::System,
    2175              :                                 OutputProcessor::StoreType::Sum,
    2176           12 :                                 this->Name,
    2177              :                                 Constant::eResource::MainsWater,
    2178              :                                 OutputProcessor::Group::Plant,
    2179              :                                 OutputProcessor::EndUseCat::HeatRejection);
    2180              :         }
    2181              : 
    2182           24 :         SetupOutputVariable(state,
    2183              :                             "Cooling Tower Water Evaporation Volume Flow Rate",
    2184              :                             Constant::Units::m3_s,
    2185           12 :                             this->EvaporationVdot,
    2186              :                             OutputProcessor::TimeStepType::System,
    2187              :                             OutputProcessor::StoreType::Average,
    2188           12 :                             this->Name);
    2189           24 :         SetupOutputVariable(state,
    2190              :                             "Cooling Tower Water Evaporation Volume",
    2191              :                             Constant::Units::m3,
    2192           12 :                             this->EvaporationVol,
    2193              :                             OutputProcessor::TimeStepType::System,
    2194              :                             OutputProcessor::StoreType::Sum,
    2195           12 :                             this->Name);
    2196           24 :         SetupOutputVariable(state,
    2197              :                             "Cooling Tower Water Drift Volume Flow Rate",
    2198              :                             Constant::Units::m3_s,
    2199           12 :                             this->DriftVdot,
    2200              :                             OutputProcessor::TimeStepType::System,
    2201              :                             OutputProcessor::StoreType::Average,
    2202           12 :                             this->Name);
    2203           24 :         SetupOutputVariable(state,
    2204              :                             "Cooling Tower Water Drift Volume",
    2205              :                             Constant::Units::m3,
    2206           12 :                             this->DriftVol,
    2207              :                             OutputProcessor::TimeStepType::System,
    2208              :                             OutputProcessor::StoreType::Sum,
    2209           12 :                             this->Name);
    2210           24 :         SetupOutputVariable(state,
    2211              :                             "Cooling Tower Water Blowdown Volume Flow Rate",
    2212              :                             Constant::Units::m3_s,
    2213           12 :                             this->BlowdownVdot,
    2214              :                             OutputProcessor::TimeStepType::System,
    2215              :                             OutputProcessor::StoreType::Average,
    2216           12 :                             this->Name);
    2217           24 :         SetupOutputVariable(state,
    2218              :                             "Cooling Tower Water Blowdown Volume",
    2219              :                             Constant::Units::m3,
    2220           12 :                             this->BlowdownVol,
    2221              :                             OutputProcessor::TimeStepType::System,
    2222              :                             OutputProcessor::StoreType::Sum,
    2223           12 :                             this->Name);
    2224           24 :         SetupOutputVariable(state,
    2225              :                             "Cooling Tower Approach",
    2226              :                             Constant::Units::C,
    2227           12 :                             this->coolingTowerApproach,
    2228              :                             OutputProcessor::TimeStepType::System,
    2229              :                             OutputProcessor::StoreType::Average,
    2230           12 :                             this->Name);
    2231           24 :         SetupOutputVariable(state,
    2232              :                             "Cooling Tower Range",
    2233              :                             Constant::Units::C,
    2234           12 :                             this->coolingTowerRange,
    2235              :                             OutputProcessor::TimeStepType::System,
    2236              :                             OutputProcessor::StoreType::Average,
    2237           12 :                             this->Name);
    2238           12 :     }
    2239              : 
    2240           33 :     void CoolingTower::SizeTower(EnergyPlusData &state)
    2241              :     {
    2242              : 
    2243              :         // SUBROUTINE INFORMATION:
    2244              :         //       AUTHOR         Fred Buhl
    2245              :         //       DATE WRITTEN   May 2002
    2246              :         //       MODIFIED       Don Shirey, Sept/Oct 2002; Richard Raustad, Feb 2005
    2247              : 
    2248              :         // PURPOSE OF THIS SUBROUTINE:
    2249              :         // This subroutine is for sizing Cooling Tower Components for which capacities and flow rates
    2250              :         // have not been specified in the input. This subroutine also calculates tower UA if the user
    2251              :         // has specified tower performance via the "Nominal Capacity" method.
    2252              : 
    2253              :         // METHODOLOGY EMPLOYED:
    2254              :         // Obtains condenser flow rate from the plant sizing array. If tower performance is specified
    2255              :         // via the "Nominal Capacity" method, the water flow rate is directly proportional to capacity.
    2256              : 
    2257              :         // SUBROUTINE PARAMETER DEFINITIONS:
    2258              : 
    2259           33 :         int constexpr MaxIte(500);    // Maximum number of iterations
    2260           33 :         Real64 constexpr Acc(0.0001); // Accuracy of result
    2261              :         static constexpr std::string_view RoutineName("SizeTower");
    2262              : 
    2263              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2264              :         int SolFla;                       // Flag of solver
    2265           33 :         Real64 DesTowerLoad(0.0);         // Design tower load [W]
    2266              :         Real64 UA0;                       // Lower bound for UA [W/C]
    2267              :         Real64 UA1;                       // Upper bound for UA [W/C]
    2268              :         Real64 UA;                        // Calculated UA value
    2269              :         Real64 DesTowerInletWaterTemp;    // design tower inlet water temperature
    2270              :         Real64 DesTowerExitWaterTemp;     // design tower exit water temperature
    2271              :         Real64 DesTowerWaterDeltaT;       // design tower temperature range
    2272              :         Real64 DesTowerApproachFromPlant; // design tower approach temperature from plant sizing object
    2273           33 :         Real64 TolTemp(0.04);             // DeltaT and DesignApproach diffs tolerance between plant sizing data and user input in cooling tower
    2274              :         // for warning message reporting purpose only
    2275              : 
    2276           33 :         Real64 tmpDesignWaterFlowRate = this->DesignWaterFlowRate;
    2277           33 :         Real64 tmpHighSpeedFanPower = this->HighSpeedFanPower;
    2278           33 :         Real64 tmpHighSpeedAirFlowRate = this->HighSpeedAirFlowRate;
    2279           33 :         Real64 tmpLowSpeedAirFlowRate = this->LowSpeedAirFlowRate;
    2280              : 
    2281           33 :         auto &PlantSizData(state.dataSize->PlantSizData);
    2282              : 
    2283              :         // Find the appropriate Plant Sizing object
    2284           33 :         int PltSizCondNum = this->plantLoc.loop->PlantSizNum;
    2285              : 
    2286           33 :         if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_SingleSpd ||
    2287           14 :             this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_TwoSpd) {
    2288           31 :             if (this->TowerInletCondsAutoSize) {
    2289           19 :                 if (PltSizCondNum > 0) {
    2290              :                     // use plant sizing data
    2291            1 :                     DesTowerExitWaterTemp = PlantSizData(PltSizCondNum).ExitTemp;
    2292            1 :                     DesTowerInletWaterTemp = DesTowerExitWaterTemp + PlantSizData(PltSizCondNum).DeltaT;
    2293            1 :                     DesTowerWaterDeltaT = PlantSizData(PltSizCondNum).DeltaT;
    2294              :                 } else {
    2295              :                     // set hard wired input assumptions
    2296              :                     // AssumedDeltaT = 11.0;
    2297              :                     // AssumedExitTemp = 21.0;
    2298           18 :                     DesTowerWaterDeltaT = 11.0;
    2299           18 :                     DesTowerExitWaterTemp = 21.0;
    2300           18 :                     DesTowerInletWaterTemp = DesTowerExitWaterTemp + DesTowerWaterDeltaT;
    2301              :                 }
    2302              :             } else {
    2303              :                 // use tower sizing data
    2304           12 :                 DesTowerExitWaterTemp = this->DesOutletWaterTemp;
    2305           12 :                 DesTowerInletWaterTemp = this->DesInletWaterTemp;
    2306           12 :                 DesTowerWaterDeltaT = this->DesignRange;
    2307           12 :                 if (PltSizCondNum > 0) {
    2308              :                     // check the tower range against the plant sizing data
    2309            0 :                     if (std::abs(DesTowerWaterDeltaT - PlantSizData(PltSizCondNum).DeltaT) > TolTemp) {
    2310            0 :                         ShowWarningError(state,
    2311            0 :                                          format("Error when autosizing the load for cooling tower = {}. Tower Design Range Temperature is different "
    2312              :                                                 "from the Design Loop Delta Temperature.",
    2313            0 :                                                 this->Name));
    2314            0 :                         ShowContinueError(state, format("Tower Design Range Temperature specified in tower = {}", this->Name));
    2315            0 :                         ShowContinueError(state,
    2316            0 :                                           format("is inconsistent with Design Loop Delta Temperature specified in Sizing:Plant object = {}.",
    2317            0 :                                                  PlantSizData(PltSizCondNum).PlantLoopName));
    2318            0 :                         ShowContinueError(state, format("..The Design Range Temperature specified in tower is = {:.2T}", this->DesignRange));
    2319            0 :                         ShowContinueError(state,
    2320            0 :                                           format("..The Design Loop Delta Temperature specified in plant sizing data is = {:.2T}",
    2321            0 :                                                  PlantSizData(PltSizCondNum).DeltaT));
    2322              :                     }
    2323              :                     // check if the tower approach is different from plant sizing data
    2324            0 :                     DesTowerApproachFromPlant = PlantSizData(PltSizCondNum).ExitTemp - this->DesignInletWB;
    2325            0 :                     if (std::abs(DesTowerApproachFromPlant - this->DesignApproach) > TolTemp) {
    2326            0 :                         ShowWarningError(state,
    2327            0 :                                          format("Error when autosizing the UA for cooling tower = {}. Tower Design Approach Temperature is "
    2328              :                                                 "inconsistent with Approach from Plant Sizing Data.",
    2329            0 :                                                 this->Name));
    2330            0 :                         ShowContinueError(state,
    2331            0 :                                           format("The Design Approach Temperature from inputs specified in Sizing:Plant object = {}",
    2332            0 :                                                  PlantSizData(PltSizCondNum).PlantLoopName));
    2333            0 :                         ShowContinueError(state, format("is inconsistent with Design Approach Temperature specified in tower = {}.", this->Name));
    2334            0 :                         ShowContinueError(state,
    2335            0 :                                           format("..The Design Approach Temperature from inputs specified is = {:.2T}", DesTowerApproachFromPlant));
    2336            0 :                         ShowContinueError(state, format("..The Design Approach Temperature specified in tower is = {:.2T}", this->DesignApproach));
    2337              :                     }
    2338              :                 }
    2339              :             }
    2340              :         } else { // CoolingTower_VariableSpeed
    2341            2 :             if (PltSizCondNum > 0) {
    2342              :                 // use plant sizing data
    2343            2 :                 DesTowerExitWaterTemp = PlantSizData(PltSizCondNum).ExitTemp;
    2344            2 :                 DesTowerInletWaterTemp = DesTowerExitWaterTemp + PlantSizData(PltSizCondNum).DeltaT;
    2345            2 :                 DesTowerWaterDeltaT = PlantSizData(PltSizCondNum).DeltaT;
    2346              :             } else {
    2347              :                 // set hard wired input assumptions
    2348            0 :                 DesTowerWaterDeltaT = 11.0;
    2349            0 :                 DesTowerExitWaterTemp = 21.0;
    2350            0 :                 DesTowerInletWaterTemp = DesTowerExitWaterTemp + DesTowerWaterDeltaT;
    2351              :             }
    2352              :         }
    2353              : 
    2354           33 :         if (this->PerformanceInputMethod_Num == PIM::UFactor && (!this->HighSpeedTowerUAWasAutoSized)) {
    2355            7 :             if (PltSizCondNum > 0) {
    2356            2 :                 Real64 const rho = this->plantLoc.loop->glycol->getDensity(state, DesTowerExitWaterTemp, RoutineName);
    2357            2 :                 Real64 const Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, DesTowerExitWaterTemp, RoutineName);
    2358            2 :                 DesTowerLoad = rho * Cp * this->DesignWaterFlowRate * DesTowerWaterDeltaT;
    2359            2 :                 this->TowerNominalCapacity = DesTowerLoad / this->HeatRejectCapNomCapSizingRatio;
    2360              : 
    2361              :             } else {
    2362            5 :                 Real64 AssumedDeltaT = DesTowerWaterDeltaT;
    2363            5 :                 Real64 AssumedExitTemp = DesTowerExitWaterTemp;
    2364              : 
    2365            5 :                 Real64 const rho = this->plantLoc.loop->glycol->getDensity(state, AssumedExitTemp, RoutineName);
    2366            5 :                 Real64 const Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, AssumedExitTemp, RoutineName);
    2367              : 
    2368            5 :                 DesTowerLoad = rho * Cp * this->DesignWaterFlowRate * AssumedDeltaT;
    2369            5 :                 this->TowerNominalCapacity = DesTowerLoad / this->HeatRejectCapNomCapSizingRatio;
    2370              :             }
    2371              :         }
    2372              : 
    2373           33 :         if (this->DesignWaterFlowRateWasAutoSized) {
    2374            2 :             if (PltSizCondNum > 0) {
    2375            1 :                 if (PlantSizData(PltSizCondNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
    2376            1 :                     tmpDesignWaterFlowRate = PlantSizData(PltSizCondNum).DesVolFlowRate * this->SizFac;
    2377            1 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) this->DesignWaterFlowRate = tmpDesignWaterFlowRate;
    2378              :                 } else {
    2379            0 :                     tmpDesignWaterFlowRate = 0.0;
    2380            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) this->DesignWaterFlowRate = tmpDesignWaterFlowRate;
    2381              :                 }
    2382            1 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2383            0 :                     BaseSizer::reportSizerOutput(state,
    2384            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2385              :                                                  this->Name,
    2386              :                                                  "Design Water Flow Rate [m3/s]",
    2387              :                                                  this->DesignWaterFlowRate);
    2388              :                 }
    2389            1 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2390            0 :                     BaseSizer::reportSizerOutput(state,
    2391            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2392              :                                                  this->Name,
    2393              :                                                  "Initial Design Water Flow Rate [m3/s]",
    2394              :                                                  this->DesignWaterFlowRate);
    2395              :                 }
    2396              :             } else {
    2397            1 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2398            0 :                     ShowSevereError(state, format("Autosizing error for cooling tower object = {}", this->Name));
    2399            0 :                     ShowFatalError(state, "Autosizing of cooling tower condenser flow rate requires a loop Sizing:Plant object.");
    2400              :                 }
    2401              :             }
    2402              :         }
    2403              : 
    2404           33 :         if (this->PerformanceInputMethod_Num == PIM::NominalCapacity) {
    2405              :             // Design water flow rate is assumed to be 3 gpm per ton (SI equivalent 5.382E-8 m3/s per watt)
    2406           24 :             this->DesignWaterFlowRate = 5.382e-8 * this->TowerNominalCapacity;
    2407           24 :             tmpDesignWaterFlowRate = this->DesignWaterFlowRate;
    2408           24 :             if (Util::SameString(DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)], "CoolingTower:SingleSpeed")) {
    2409           12 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2410            8 :                     BaseSizer::reportSizerOutput(state,
    2411            4 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2412              :                                                  this->Name,
    2413              :                                                  "Design Water Flow Rate based on tower nominal capacity [m3/s]",
    2414              :                                                  this->DesignWaterFlowRate);
    2415              :                 }
    2416           12 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2417            0 :                     BaseSizer::reportSizerOutput(state,
    2418            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2419              :                                                  this->Name,
    2420              :                                                  "Initial Design Water Flow Rate based on tower nominal capacity [m3/s]",
    2421              :                                                  this->DesignWaterFlowRate);
    2422              :                 }
    2423           12 :             } else if (Util::SameString(DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)], "CoolingTower:TwoSpeed")) {
    2424           12 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2425            8 :                     BaseSizer::reportSizerOutput(state,
    2426            4 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2427              :                                                  this->Name,
    2428              :                                                  "Design Water Flow Rate based on tower high-speed nominal capacity [m3/s]",
    2429              :                                                  this->DesignWaterFlowRate);
    2430              :                 }
    2431           12 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2432            0 :                     BaseSizer::reportSizerOutput(state,
    2433            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2434              :                                                  this->Name,
    2435              :                                                  "Initial Design Water Flow Rate based on tower high-speed nominal capacity [m3/s]",
    2436              :                                                  this->DesignWaterFlowRate);
    2437              :                 }
    2438              :             }
    2439              :         }
    2440              : 
    2441           33 :         PlantUtilities::RegisterPlantCompDesignFlow(state, this->WaterInletNodeNum, tmpDesignWaterFlowRate);
    2442              : 
    2443           33 :         if (this->HighSpeedFanPowerWasAutoSized) {
    2444              :             // We assume the nominal fan power is 0.0105 times the design load
    2445           26 :             if (this->PerformanceInputMethod_Num == PIM::NominalCapacity) {
    2446           24 :                 this->HighSpeedFanPower = 0.0105 * this->TowerNominalCapacity;
    2447           24 :                 tmpHighSpeedFanPower = this->HighSpeedFanPower;
    2448              :             } else {
    2449            2 :                 if (PltSizCondNum > 0) {
    2450            1 :                     if (PlantSizData(PltSizCondNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
    2451            1 :                         Real64 const rho = this->plantLoc.loop->glycol->getDensity(state, Constant::InitConvTemp, RoutineName);
    2452            1 :                         Real64 const Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, DesTowerExitWaterTemp, RoutineName);
    2453            1 :                         DesTowerLoad = rho * Cp * tmpDesignWaterFlowRate * DesTowerWaterDeltaT;
    2454            1 :                         tmpHighSpeedFanPower = 0.0105 * DesTowerLoad;
    2455            1 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) this->HighSpeedFanPower = tmpHighSpeedFanPower;
    2456              :                     } else {
    2457            0 :                         tmpHighSpeedFanPower = 0.0;
    2458            0 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) this->HighSpeedFanPower = tmpHighSpeedFanPower;
    2459              :                     }
    2460              :                 } else {
    2461            1 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2462            0 :                         ShowSevereError(state, "Autosizing of cooling tower fan power requires a loop Sizing:Plant object.");
    2463            0 :                         ShowFatalError(state, format(" Occurs in cooling tower object= {}", this->Name));
    2464              :                     }
    2465              :                 }
    2466              :             }
    2467           26 :             if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_SingleSpd ||
    2468           12 :                 this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_VarSpd) {
    2469           14 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2470            8 :                     BaseSizer::reportSizerOutput(state,
    2471            4 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2472              :                                                  this->Name,
    2473              :                                                  "Fan Power at Design Air Flow Rate [W]",
    2474              :                                                  this->HighSpeedFanPower);
    2475              :                 }
    2476           14 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2477            0 :                     BaseSizer::reportSizerOutput(state,
    2478            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2479              :                                                  this->Name,
    2480              :                                                  "Initial Fan Power at Design Air Flow Rate [W]",
    2481              :                                                  this->HighSpeedFanPower);
    2482              :                 }
    2483           12 :             } else if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_TwoSpd) {
    2484           12 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2485            8 :                     BaseSizer::reportSizerOutput(state,
    2486            4 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2487              :                                                  this->Name,
    2488              :                                                  "Fan Power at High Fan Speed [W]",
    2489              :                                                  this->HighSpeedFanPower);
    2490              :                 }
    2491           12 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2492            0 :                     BaseSizer::reportSizerOutput(state,
    2493            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2494              :                                                  this->Name,
    2495              :                                                  "Initial Fan Power at High Fan Speed [W]",
    2496              :                                                  this->HighSpeedFanPower);
    2497              :                 }
    2498              :             }
    2499              :         }
    2500              : 
    2501           33 :         if (this->HighSpeedAirFlowRateWasAutoSized) {
    2502              :             // Plant Sizing Object is not required to AUTOSIZE this field since its simply a multiple of another field.
    2503           26 :             tmpHighSpeedAirFlowRate = tmpHighSpeedFanPower * 0.5 * (101325.0 / state.dataEnvrn->StdBaroPress) / 190.0;
    2504           26 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) this->HighSpeedAirFlowRate = tmpHighSpeedAirFlowRate;
    2505              : 
    2506           26 :             if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_SingleSpd ||
    2507           12 :                 this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_VarSpd) {
    2508           14 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2509            8 :                     BaseSizer::reportSizerOutput(state,
    2510            4 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2511              :                                                  this->Name,
    2512              :                                                  "Design Air Flow Rate [m3/s]",
    2513              :                                                  this->HighSpeedAirFlowRate);
    2514              :                 }
    2515           14 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2516            0 :                     BaseSizer::reportSizerOutput(state,
    2517            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2518              :                                                  this->Name,
    2519              :                                                  "Initial Design Air Flow Rate [m3/s]",
    2520              :                                                  this->HighSpeedAirFlowRate);
    2521              :                 }
    2522           12 :             } else if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_TwoSpd) {
    2523           12 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2524            8 :                     BaseSizer::reportSizerOutput(state,
    2525            4 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2526              :                                                  this->Name,
    2527              :                                                  "Air Flow Rate at High Fan Speed [m3/s]",
    2528              :                                                  this->HighSpeedAirFlowRate);
    2529              :                 }
    2530           12 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2531            0 :                     BaseSizer::reportSizerOutput(state,
    2532            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2533              :                                                  this->Name,
    2534              :                                                  "Initial Air Flow Rate at High Fan Speed [m3/s]",
    2535              :                                                  this->HighSpeedAirFlowRate);
    2536              :                 }
    2537              :             }
    2538              :         }
    2539              : 
    2540           33 :         if (this->HighSpeedTowerUAWasAutoSized) {
    2541            2 :             if (PltSizCondNum > 0) {
    2542            1 :                 if (PlantSizData(PltSizCondNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
    2543            1 :                     Real64 const rho = this->plantLoc.loop->glycol->getDensity(state, Constant::InitConvTemp, RoutineName);
    2544            1 :                     Real64 const Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, DesTowerExitWaterTemp, RoutineName);
    2545            1 :                     DesTowerLoad = rho * Cp * tmpDesignWaterFlowRate * DesTowerWaterDeltaT;
    2546              :                     // This conditional statement is to trap when the user specified condenser/tower water design setpoint
    2547              :                     //  temperature is less than design inlet air wet bulb temperature
    2548            1 :                     if (PlantSizData(PltSizCondNum).ExitTemp <= this->DesignInletWB) {
    2549            2 :                         ShowSevereError(state,
    2550            2 :                                         format("Error when autosizing the UA value for cooling tower = {}. Design Loop Exit Temperature must be "
    2551              :                                                "greater than {:.2T} C when autosizing the tower UA.",
    2552            1 :                                                this->Name,
    2553            1 :                                                this->DesignInletWB));
    2554            2 :                         ShowContinueError(state,
    2555            2 :                                           format("The Design Loop Exit Temperature specified in Sizing:Plant object = {} ({:.2T} C)",
    2556            1 :                                                  PlantSizData(PltSizCondNum).PlantLoopName,
    2557            1 :                                                  PlantSizData(PltSizCondNum).ExitTemp));
    2558            2 :                         ShowContinueError(
    2559            2 :                             state, format("is less than or equal to the design inlet air wet-bulb temperature of {:.2T} C.", this->DesignInletWB));
    2560            2 :                         ShowContinueError(state,
    2561            2 :                                           format("If using HVACTemplate:Plant:ChilledWaterLoop, then check that input field Condenser Water Design "
    2562              :                                                  "Setpoint must be > {:.2T} C if autosizing the cooling tower.",
    2563            1 :                                                  this->DesignInletWB));
    2564            2 :                         ShowFatalError(state, format("Autosizing of cooling tower fails for tower = {}.", this->Name));
    2565              :                     }
    2566              : 
    2567            0 :                     Real64 const solveDesignWaterMassFlow = rho * tmpDesignWaterFlowRate; // design water mass flow rate
    2568            0 :                     UA0 = 0.0001 * DesTowerLoad;                                          // Assume deltaT = 10000K (limit)
    2569            0 :                     UA1 = DesTowerLoad;                                                   // Assume deltaT = 1K
    2570            0 :                     this->WaterTemp = DesTowerInletWaterTemp;
    2571            0 :                     this->AirTemp = this->DesInletAirDBTemp; // 35.0;
    2572            0 :                     this->AirWetBulb = this->DesignInletWB;  // 25.6;
    2573            0 :                     this->AirPress = state.dataEnvrn->StdBaroPress;
    2574            0 :                     this->AirHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, this->AirTemp, this->AirWetBulb, this->AirPress);
    2575            0 :                     auto f1 = [&state, this, DesTowerLoad, solveDesignWaterMassFlow, tmpHighSpeedAirFlowRate, Cp](Real64 UA) {
    2576              :                         Real64 const OutWaterTemp =
    2577            0 :                             this->calculateSimpleTowerOutletTemp(state, solveDesignWaterMassFlow, tmpHighSpeedAirFlowRate, UA);
    2578            0 :                         Real64 const CoolingOutput = Cp * solveDesignWaterMassFlow * (this->WaterTemp - OutWaterTemp); // tower cooling output [W]
    2579            0 :                         return (DesTowerLoad - CoolingOutput) / DesTowerLoad;
    2580            0 :                     };
    2581            0 :                     General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f1, UA0, UA1);
    2582            0 :                     if (SolFla == -1) {
    2583            0 :                         ShowSevereError(state, "Iteration limit exceeded in calculating tower UA");
    2584            0 :                         ShowFatalError(state, format("Autosizing of cooling tower UA failed for tower {}", this->Name));
    2585            0 :                     } else if (SolFla == -2) {
    2586            0 :                         ShowSevereError(state, "Bad starting values for UA");
    2587            0 :                         ShowFatalError(state, format("Autosizing of cooling tower UA failed for tower {}", this->Name));
    2588              :                     }
    2589              : 
    2590            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    2591            0 :                         this->HighSpeedTowerUA = UA;
    2592              :                     }
    2593            0 :                     this->TowerNominalCapacity = DesTowerLoad / this->HeatRejectCapNomCapSizingRatio;
    2594              :                 } else {
    2595            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    2596            0 :                         this->HighSpeedTowerUA = 0.0;
    2597              :                     }
    2598              :                 }
    2599            0 :                 if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_SingleSpd) {
    2600            0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2601            0 :                         BaseSizer::reportSizerOutput(state,
    2602            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2603              :                                                      this->Name,
    2604              :                                                      "U-Factor Times Area Value at Design Air Flow Rate [W/C]",
    2605              :                                                      this->HighSpeedTowerUA);
    2606              :                     }
    2607            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2608            0 :                         BaseSizer::reportSizerOutput(state,
    2609            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2610              :                                                      this->Name,
    2611              :                                                      "Initial U-Factor Times Area Value at Design Air Flow Rate [W/C]",
    2612              :                                                      this->HighSpeedTowerUA);
    2613              :                     }
    2614            0 :                 } else if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_TwoSpd) {
    2615            0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2616            0 :                         BaseSizer::reportSizerOutput(state,
    2617            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2618              :                                                      this->Name,
    2619              :                                                      "U-Factor Times Area Value at High Fan Speed [W/C]",
    2620              :                                                      this->HighSpeedTowerUA);
    2621              :                     }
    2622            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2623            0 :                         BaseSizer::reportSizerOutput(state,
    2624            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2625              :                                                      this->Name,
    2626              :                                                      "Initial U-Factor Times Area Value at High Fan Speed [W/C]",
    2627              :                                                      this->HighSpeedTowerUA);
    2628              :                     }
    2629              :                 }
    2630              :             } else {
    2631            1 :                 if (this->DesignWaterFlowRate >= HVAC::SmallWaterVolFlow) {
    2632              : 
    2633            1 :                     Real64 const rho = this->plantLoc.loop->glycol->getDensity(state, Constant::InitConvTemp, RoutineName);
    2634            1 :                     Real64 const Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, DesTowerExitWaterTemp, RoutineName);
    2635            1 :                     DesTowerLoad = rho * Cp * tmpDesignWaterFlowRate * DesTowerWaterDeltaT;
    2636              :                     // This conditional statement is to trap when the user specified condenser/tower water design setpoint
    2637              :                     //  temperature is less than design inlet air wet bulb temperature
    2638              :                     // Note JM 2018-11-22
    2639              :                     // * If actually user-specified:
    2640              :                     //  this->DesOutletWaterTemp = this->DesignInletWB
    2641              :                     //                                           + this->DesignApproach;
    2642              :                     //  DesTowerExitWaterTemp = this->DesOutletWaterTemp;
    2643              :                     //  => This basically means that approach is negative, which is impossible (must be > 0 per IDD)
    2644              :                     // * If not, hardcoded above to 21C
    2645            1 :                     if (DesTowerExitWaterTemp <= this->DesignInletWB) {
    2646            2 :                         ShowSevereError(state,
    2647            2 :                                         format("Error when autosizing the UA value for cooling tower = {}. Design Tower Exit Temperature must be "
    2648              :                                                "greater than {:.2T} C when autosizing the tower UA.",
    2649            1 :                                                this->Name,
    2650            1 :                                                this->DesignInletWB));
    2651            1 :                         ShowContinueError(state, format("The User-specified Design Loop Exit Temperature={:.2T}", DesTowerExitWaterTemp));
    2652            2 :                         ShowContinueError(
    2653            2 :                             state, format("is less than or equal to the design inlet air wet-bulb temperature of {:.2T} C.", this->DesignInletWB));
    2654              : 
    2655            1 :                         if (this->TowerInletCondsAutoSize) {
    2656            2 :                             ShowContinueError(state,
    2657            2 :                                               format("Because you did not specify the Design Approach Temperature, and you do not have a "
    2658              :                                                      "Sizing:Plant object, it was defaulted to {:.2T} C.",
    2659              :                                                      DesTowerExitWaterTemp));
    2660              :                         } else {
    2661              :                             // Should never get there...
    2662            0 :                             ShowContinueError(state,
    2663            0 :                                               format("The Design Loop Exit Temperature is the sum of the design air inlet wet-bulb temperature= "
    2664              :                                                      "{:.2T} C plus the cooling tower design approach temperature = {:.2T}C.",
    2665            0 :                                                      this->DesignInletWB,
    2666            0 :                                                      this->DesignApproach));
    2667              :                         }
    2668            2 :                         ShowContinueError(state,
    2669            2 :                                           format("If using HVACTemplate:Plant:ChilledWaterLoop, then check that input field Condenser Water Design "
    2670              :                                                  "Setpoint must be > {:.2T} C if autosizing the cooling tower.",
    2671            1 :                                                  this->DesignInletWB));
    2672            2 :                         ShowFatalError(state, format("Autosizing of cooling tower fails for tower = {}.", this->Name));
    2673              :                     }
    2674              : 
    2675            0 :                     Real64 const solveWaterMassFlow = rho * tmpDesignWaterFlowRate; // design water mass flow rate
    2676            0 :                     UA0 = 0.0001 * DesTowerLoad;                                    // Assume deltaT = 10000K (limit)
    2677            0 :                     UA1 = DesTowerLoad;                                             // Assume deltaT = 1K
    2678            0 :                     this->WaterTemp = DesTowerInletWaterTemp;
    2679            0 :                     this->AirTemp = this->DesInletAirDBTemp; // 35.0;
    2680            0 :                     this->AirWetBulb = this->DesignInletWB;  // 25.6;
    2681            0 :                     this->AirPress = state.dataEnvrn->StdBaroPress;
    2682            0 :                     this->AirHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, this->AirTemp, this->AirWetBulb, this->AirPress);
    2683            0 :                     auto f = [&state, this, DesTowerLoad, solveWaterMassFlow, tmpHighSpeedAirFlowRate, Cp](Real64 UA) {
    2684            0 :                         Real64 const OutWaterTemp = this->calculateSimpleTowerOutletTemp(state, solveWaterMassFlow, tmpHighSpeedAirFlowRate, UA);
    2685            0 :                         Real64 const CoolingOutput = Cp * solveWaterMassFlow * (this->WaterTemp - OutWaterTemp); // tower cooling output [W]
    2686            0 :                         return (DesTowerLoad - CoolingOutput) / DesTowerLoad;
    2687            0 :                     };
    2688            0 :                     General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f, UA0, UA1);
    2689            0 :                     if (SolFla == -1) {
    2690            0 :                         ShowSevereError(state, "Iteration limit exceeded in calculating tower UA");
    2691            0 :                         ShowFatalError(state, format("Autosizing of cooling tower UA failed for tower {}", this->Name));
    2692            0 :                     } else if (SolFla == -2) {
    2693            0 :                         ShowSevereError(state, "Bad starting values for UA");
    2694            0 :                         ShowFatalError(state, format("Autosizing of cooling tower UA failed for tower {}", this->Name));
    2695              :                     }
    2696              : 
    2697            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    2698            0 :                         this->HighSpeedTowerUA = UA;
    2699              :                     }
    2700            0 :                     this->TowerNominalCapacity = DesTowerLoad / this->HeatRejectCapNomCapSizingRatio;
    2701              :                 } else {
    2702            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    2703            0 :                         this->HighSpeedTowerUA = 0.0;
    2704              :                     }
    2705              :                 }
    2706            0 :                 if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_SingleSpd) {
    2707            0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2708            0 :                         BaseSizer::reportSizerOutput(state,
    2709            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2710              :                                                      this->Name,
    2711              :                                                      "U-Factor Times Area Value at Design Air Flow Rate [W/C]",
    2712              :                                                      this->HighSpeedTowerUA);
    2713              :                     }
    2714            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2715            0 :                         BaseSizer::reportSizerOutput(state,
    2716            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2717              :                                                      this->Name,
    2718              :                                                      "Initial U-Factor Times Area Value at Design Air Flow Rate [W/C]",
    2719              :                                                      this->HighSpeedTowerUA);
    2720              :                     }
    2721            0 :                 } else if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_TwoSpd) {
    2722            0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2723            0 :                         BaseSizer::reportSizerOutput(state,
    2724            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2725              :                                                      this->Name,
    2726              :                                                      "U-Factor Times Area Value at High Fan Speed [W/C]",
    2727              :                                                      this->HighSpeedTowerUA);
    2728              :                     }
    2729            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2730            0 :                         BaseSizer::reportSizerOutput(state,
    2731            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2732              :                                                      this->Name,
    2733              :                                                      "Initial U-Factor Times Area Value at High Fan Speed [W/C]",
    2734              :                                                      this->HighSpeedTowerUA);
    2735              :                     }
    2736              :                 }
    2737              :             }
    2738              :         }
    2739              : 
    2740           31 :         if (this->PerformanceInputMethod_Num == PIM::NominalCapacity) {
    2741           24 :             if (this->DesignWaterFlowRate >= HVAC::SmallWaterVolFlow) {
    2742              :                 // nominal capacity doesn't include compressor heat; predefined factor was 1.25 W heat rejection per W of delivered cooling but now is
    2743              :                 // a user input
    2744           24 :                 Real64 const rho = this->plantLoc.loop->glycol->getDensity(state, 29.44, RoutineName);     // 85F design exiting water temp
    2745           24 :                 Real64 const Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, 29.44, RoutineName); // 85F design exiting water temp
    2746              : 
    2747           24 :                 DesTowerLoad = this->TowerNominalCapacity * this->HeatRejectCapNomCapSizingRatio;
    2748           24 :                 Real64 const solveWaterFlowRate = rho * tmpDesignWaterFlowRate; // design water mass flow rate
    2749           24 :                 UA0 = 0.0001 * DesTowerLoad;                                    // Assume deltaT = 10000K (limit)
    2750           24 :                 UA1 = DesTowerLoad;                                             // Assume deltaT = 1K
    2751           24 :                 this->WaterTemp = this->DesInletWaterTemp;                      // 35.0; // 95F design inlet water temperature
    2752           24 :                 this->AirTemp = this->DesInletAirDBTemp;                        // 95F design inlet air dry-bulb temp
    2753           24 :                 this->AirWetBulb = this->DesignInletWB;                         // 78F design inlet air wet-bulb temp
    2754           24 :                 this->AirPress = state.dataEnvrn->StdBaroPress;
    2755           24 :                 this->AirHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, this->AirTemp, this->AirWetBulb, this->AirPress);
    2756          816 :                 auto f = [&state, this, DesTowerLoad, solveWaterFlowRate, tmpHighSpeedAirFlowRate, Cp](Real64 UA) {
    2757          816 :                     Real64 const OutWaterTemp = this->calculateSimpleTowerOutletTemp(state, solveWaterFlowRate, tmpHighSpeedAirFlowRate, UA);
    2758          816 :                     Real64 const CoolingOutput = Cp * solveWaterFlowRate * (this->WaterTemp - OutWaterTemp); // tower cooling output [W]
    2759          816 :                     return (DesTowerLoad - CoolingOutput) / DesTowerLoad;
    2760           24 :                 };
    2761           24 :                 General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f, UA0, UA1);
    2762           24 :                 if (SolFla == -1) {
    2763            0 :                     ShowSevereError(state, "Iteration limit exceeded in calculating tower UA");
    2764            0 :                     ShowFatalError(state, format("Autosizing of cooling tower UA failed for tower {}", this->Name));
    2765           24 :                 } else if (SolFla == -2) {
    2766            0 :                     ShowSevereError(state, "Bad starting values for UA");
    2767            0 :                     ShowFatalError(state, format("Autosizing of cooling tower UA failed for tower {}", this->Name));
    2768              :                 }
    2769           24 :                 if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    2770            8 :                     this->HighSpeedTowerUA = UA;
    2771              :                 }
    2772              :             } else {
    2773            0 :                 if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    2774            0 :                     this->HighSpeedTowerUA = 0.0;
    2775              :                 }
    2776              :             }
    2777           24 :             if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_SingleSpd) {
    2778           12 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2779            8 :                     BaseSizer::reportSizerOutput(state,
    2780            4 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2781              :                                                  this->Name,
    2782              :                                                  "U-Factor Times Area Value at Design Air Flow Rate [W/C]",
    2783              :                                                  this->HighSpeedTowerUA);
    2784              :                 }
    2785           12 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2786            0 :                     BaseSizer::reportSizerOutput(state,
    2787            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2788              :                                                  this->Name,
    2789              :                                                  "Initial U-Factor Times Area Value at Design Air Flow Rate [W/C]",
    2790              :                                                  this->HighSpeedTowerUA);
    2791              :                 }
    2792           12 :             } else if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_TwoSpd) {
    2793           12 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2794            8 :                     BaseSizer::reportSizerOutput(state,
    2795            4 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2796              :                                                  this->Name,
    2797              :                                                  "U-Factor Times Area Value at High Fan Speed [W/C]",
    2798              :                                                  this->HighSpeedTowerUA);
    2799              :                 }
    2800           12 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2801            0 :                     BaseSizer::reportSizerOutput(state,
    2802            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2803              :                                                  this->Name,
    2804              :                                                  "Initial U-Factor Times Area Value at High Fan Speed [W/C]",
    2805              :                                                  this->HighSpeedTowerUA);
    2806              :                 }
    2807              :             }
    2808              :         }
    2809              : 
    2810           31 :         if (this->LowSpeedAirFlowRateWasAutoSized) {
    2811              : 
    2812           12 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    2813            4 :                 this->LowSpeedAirFlowRate = this->LowSpeedAirFlowRateSizingFactor * this->HighSpeedAirFlowRate;
    2814            4 :                 tmpLowSpeedAirFlowRate = this->LowSpeedAirFlowRate;
    2815            4 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2816            8 :                     BaseSizer::reportSizerOutput(state,
    2817            4 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2818              :                                                  this->Name,
    2819              :                                                  "Low Fan Speed Air Flow Rate [m3/s]",
    2820              :                                                  this->LowSpeedAirFlowRate);
    2821              :                 }
    2822            4 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2823            0 :                     BaseSizer::reportSizerOutput(state,
    2824            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2825              :                                                  this->Name,
    2826              :                                                  "Initial Low Fan Speed Air Flow Rate [m3/s]",
    2827              :                                                  this->LowSpeedAirFlowRate);
    2828              :                 }
    2829              :             } else {
    2830            8 :                 tmpLowSpeedAirFlowRate = this->LowSpeedAirFlowRateSizingFactor * tmpHighSpeedAirFlowRate;
    2831              :             }
    2832              :         }
    2833              : 
    2834           31 :         if (this->LowSpeedFanPowerWasAutoSized) {
    2835           12 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    2836            4 :                 this->LowSpeedFanPower = this->LowSpeedFanPowerSizingFactor * this->HighSpeedFanPower;
    2837            4 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2838            8 :                     BaseSizer::reportSizerOutput(state,
    2839            4 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2840              :                                                  this->Name,
    2841              :                                                  "Fan Power at Low Fan Speed [W]",
    2842              :                                                  this->LowSpeedFanPower);
    2843              :                 }
    2844            4 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2845            0 :                     BaseSizer::reportSizerOutput(state,
    2846            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2847              :                                                  this->Name,
    2848              :                                                  "Initial Fan Power at Low Fan Speed [W]",
    2849              :                                                  this->LowSpeedFanPower);
    2850              :                 }
    2851              :             }
    2852              :         }
    2853              : 
    2854           31 :         if (this->LowSpeedTowerUAWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    2855            2 :             this->LowSpeedTowerUA = this->LowSpeedTowerUASizingFactor * this->HighSpeedTowerUA;
    2856            2 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2857            4 :                 BaseSizer::reportSizerOutput(state,
    2858            2 :                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2859              :                                              this->Name,
    2860              :                                              "U-Factor Times Area Value at Low Fan Speed [W/K]",
    2861              :                                              this->LowSpeedTowerUA);
    2862              :             }
    2863            2 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2864            0 :                 BaseSizer::reportSizerOutput(state,
    2865            0 :                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2866              :                                              this->Name,
    2867              :                                              "Initial U-Factor Times Area Value at Low Fan Speed [W/K]",
    2868              :                                              this->LowSpeedTowerUA);
    2869              :             }
    2870              :         }
    2871              : 
    2872           31 :         if (this->PerformanceInputMethod_Num == PIM::NominalCapacity) {
    2873           24 :             if (this->TowerLowSpeedNomCapWasAutoSized) {
    2874            6 :                 if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    2875            2 :                     this->TowerLowSpeedNomCap = this->TowerLowSpeedNomCapSizingFactor * this->TowerNominalCapacity;
    2876            2 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2877            4 :                         BaseSizer::reportSizerOutput(state,
    2878            2 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2879              :                                                      this->Name,
    2880              :                                                      "Low Speed Nominal Capacity [W]",
    2881              :                                                      this->TowerLowSpeedNomCap);
    2882              :                     }
    2883            2 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2884            0 :                         BaseSizer::reportSizerOutput(state,
    2885            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2886              :                                                      this->Name,
    2887              :                                                      "Initial Low Speed Nominal Capacity [W]",
    2888              :                                                      this->TowerLowSpeedNomCap);
    2889              :                     }
    2890              :                 }
    2891              :             }
    2892           24 :             if (this->TowerFreeConvNomCapWasAutoSized) {
    2893            0 :                 if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    2894            0 :                     this->TowerFreeConvNomCap = this->TowerFreeConvNomCapSizingFactor * this->TowerNominalCapacity;
    2895            0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2896            0 :                         BaseSizer::reportSizerOutput(state,
    2897            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2898              :                                                      this->Name,
    2899              :                                                      "Free Convection Nominal Capacity [W]",
    2900              :                                                      this->TowerFreeConvNomCap);
    2901              :                     }
    2902            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2903            0 :                         BaseSizer::reportSizerOutput(state,
    2904            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2905              :                                                      this->Name,
    2906              :                                                      "Initial Free Convection Nominal Capacity [W]",
    2907              :                                                      this->TowerFreeConvNomCap);
    2908              :                     }
    2909              :                 }
    2910              :             }
    2911              :         }
    2912              : 
    2913           55 :         if (this->PerformanceInputMethod_Num == PIM::NominalCapacity &&
    2914           55 :             Util::SameString(DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)], "CoolingTower:TwoSpeed")) {
    2915           12 :             if (this->DesignWaterFlowRate >= HVAC::SmallWaterVolFlow && this->TowerLowSpeedNomCap > 0.0) {
    2916              : 
    2917              :                 // nominal capacity doesn't include compressor heat; predefined factor was 1.25 W heat rejection per W of evap cooling but now is a
    2918              :                 // user input
    2919            8 :                 Real64 const rho = this->plantLoc.loop->glycol->getDensity(state, 29.44, RoutineName);     // 85F design exiting water temp
    2920            8 :                 Real64 const Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, 29.44, RoutineName); // 85F design exiting water temp
    2921            8 :                 DesTowerLoad = this->TowerLowSpeedNomCap * this->HeatRejectCapNomCapSizingRatio;
    2922            8 :                 Real64 const solveWaterFlow = rho * tmpDesignWaterFlowRate; // design water mass flow rate
    2923            8 :                 UA0 = 0.0001 * DesTowerLoad;                                // Assume deltaT = 10000K (limit)
    2924            8 :                 UA1 = DesTowerLoad;                                         // Assume deltaT = 1K
    2925            8 :                 this->WaterTemp = this->DesInletWaterTemp;                  // 35.0; // 95F design inlet water temperature
    2926            8 :                 this->AirTemp = this->DesInletAirDBTemp;                    // 35.0; // 95F design inlet air dry-bulb temp
    2927            8 :                 this->AirWetBulb = this->DesignInletWB;                     // 25.6; // 78F design inlet air wet-bulb temp
    2928            8 :                 this->AirPress = state.dataEnvrn->StdBaroPress;
    2929            8 :                 this->AirHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, this->AirTemp, this->AirWetBulb, this->AirPress);
    2930          108 :                 auto f = [&state, this, DesTowerLoad, solveWaterFlow, tmpLowSpeedAirFlowRate, Cp](Real64 UA) {
    2931          108 :                     Real64 const OutWaterTemp = this->calculateSimpleTowerOutletTemp(state, solveWaterFlow, tmpLowSpeedAirFlowRate, UA);
    2932          108 :                     Real64 const CoolingOutput = Cp * solveWaterFlow * (this->WaterTemp - OutWaterTemp); // tower cooling output [W]
    2933          108 :                     return (DesTowerLoad - CoolingOutput) / DesTowerLoad;
    2934            8 :                 };
    2935            8 :                 General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f, UA0, UA1);
    2936            8 :                 if (SolFla == -1) {
    2937            0 :                     ShowSevereError(state, "Iteration limit exceeded in calculating tower UA");
    2938            0 :                     ShowFatalError(state, format("Autosizing of cooling tower UA failed for tower {}", this->Name));
    2939            8 :                 } else if (SolFla == -2) {
    2940            0 :                     ShowSevereError(state, "Bad starting values for UA");
    2941            0 :                     ShowFatalError(state, format("Autosizing of cooling tower UA failed for tower {}", this->Name));
    2942              :                 }
    2943            8 :                 if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    2944            4 :                     this->LowSpeedTowerUA = UA;
    2945              :                 }
    2946            8 :             } else {
    2947            4 :                 this->LowSpeedTowerUA = 0.0;
    2948              :             }
    2949           12 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2950            8 :                 BaseSizer::reportSizerOutput(state,
    2951            4 :                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2952              :                                              this->Name,
    2953              :                                              "Low Fan Speed U-Factor Times Area Value [W/K]",
    2954              :                                              this->LowSpeedTowerUA);
    2955              :             }
    2956           12 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2957            0 :                 BaseSizer::reportSizerOutput(state,
    2958            0 :                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2959              :                                              this->Name,
    2960              :                                              "Initial Low Fan Speed U-Factor Times Area Value [W/K]",
    2961              :                                              this->LowSpeedTowerUA);
    2962              :             }
    2963              :         }
    2964              : 
    2965           31 :         if (this->FreeConvAirFlowRateWasAutoSized) {
    2966           18 :             this->FreeConvAirFlowRate = this->FreeConvAirFlowRateSizingFactor * tmpHighSpeedAirFlowRate;
    2967           18 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    2968            6 :                 this->FreeConvAirFlowRate = this->FreeConvAirFlowRateSizingFactor * this->HighSpeedAirFlowRate;
    2969            6 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2970           12 :                     BaseSizer::reportSizerOutput(state,
    2971            6 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2972              :                                                  this->Name,
    2973              :                                                  "Free Convection Regime Air Flow Rate [m3/s]",
    2974              :                                                  this->FreeConvAirFlowRate);
    2975              :                 }
    2976            6 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2977            0 :                     BaseSizer::reportSizerOutput(state,
    2978            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2979              :                                                  this->Name,
    2980              :                                                  "Initial Free Convection Regime Air Flow Rate [m3/s]",
    2981              :                                                  this->FreeConvAirFlowRate);
    2982              :                 }
    2983              :             }
    2984              :         }
    2985              : 
    2986           31 :         if (this->FreeConvTowerUAWasAutoSized) {
    2987            6 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    2988            2 :                 this->FreeConvTowerUA = this->FreeConvTowerUASizingFactor * this->HighSpeedTowerUA;
    2989            2 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    2990            4 :                     BaseSizer::reportSizerOutput(state,
    2991            2 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2992              :                                                  this->Name,
    2993              :                                                  "Free Convection U-Factor Times Area Value [W/K]",
    2994              :                                                  this->FreeConvTowerUA);
    2995              :                 }
    2996            2 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    2997            0 :                     BaseSizer::reportSizerOutput(state,
    2998            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    2999              :                                                  this->Name,
    3000              :                                                  "Initial Free Convection U-Factor Times Area Value [W/K]",
    3001              :                                                  this->FreeConvTowerUA);
    3002              :                 }
    3003              :             }
    3004              :         }
    3005              : 
    3006           31 :         if (this->PerformanceInputMethod_Num == PIM::NominalCapacity) {
    3007           24 :             if (this->DesignWaterFlowRate >= HVAC::SmallWaterVolFlow && this->TowerFreeConvNomCap > 0.0) {
    3008              :                 // nominal capacity doesn't include compressor heat; predefined factor was 1.25 W heat rejection per W of evap cooling but now user
    3009              :                 // input
    3010           24 :                 Real64 const rho = this->plantLoc.loop->glycol->getDensity(state, 29.44, RoutineName);     // 85F design exiting water temp
    3011           24 :                 Real64 const Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, 29.44, RoutineName); // 85F design exiting water temp
    3012           24 :                 DesTowerLoad = this->TowerFreeConvNomCap * this->HeatRejectCapNomCapSizingRatio;
    3013           24 :                 Real64 const solveWaterFlow = rho * this->DesignWaterFlowRate; // design water mass flow rate
    3014           24 :                 UA0 = 0.0001 * DesTowerLoad;                                   // Assume deltaT = 10000K (limit)
    3015           24 :                 UA1 = DesTowerLoad;                                            // Assume deltaT = 1K
    3016           24 :                 this->WaterTemp = this->DesInletWaterTemp;                     // 35.0; // 95F design inlet water temperature
    3017           24 :                 this->AirTemp = this->DesInletAirDBTemp;                       // 35.0; // 95F design inlet air dry-bulb temp
    3018           24 :                 this->AirWetBulb = this->DesignInletWB;                        // 25.6; // 78F design inlet air wet-bulb temp
    3019           24 :                 this->AirPress = state.dataEnvrn->StdBaroPress;
    3020           24 :                 this->AirHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, this->AirTemp, this->AirWetBulb, this->AirPress);
    3021          264 :                 auto f = [&state, this, DesTowerLoad, solveWaterFlow, Cp](Real64 UA) {
    3022          264 :                     Real64 const OutWaterTemp = this->calculateSimpleTowerOutletTemp(state, solveWaterFlow, this->FreeConvAirFlowRate, UA);
    3023          264 :                     Real64 const CoolingOutput = Cp * solveWaterFlow * (this->WaterTemp - OutWaterTemp); // tower cooling output [W]
    3024          264 :                     return (DesTowerLoad - CoolingOutput) / DesTowerLoad;
    3025           24 :                 };
    3026           24 :                 General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f, UA0, UA1);
    3027           24 :                 if (SolFla == -1) {
    3028            0 :                     ShowSevereError(state, "Iteration limit exceeded in calculating tower UA");
    3029            0 :                     ShowFatalError(state, format("Autosizing of cooling tower UA failed for tower {}", this->Name));
    3030           24 :                 } else if (SolFla == -2) {
    3031            0 :                     ShowSevereError(state, "Bad starting values for UA calculations");
    3032            0 :                     ShowContinueError(state, "Tower inlet design water temperature assumed to be 35.0 C.");
    3033            0 :                     ShowContinueError(state, "Tower inlet design air dry-bulb temperature assumed to be 35.0 C.");
    3034            0 :                     ShowContinueError(state, "Tower inlet design air wet-bulb temperature assumed to be 25.6 C.");
    3035            0 :                     ShowContinueError(state,
    3036            0 :                                       format("Tower load assumed to be {:.3T} times free convection capacity of {:.0T} W.",
    3037            0 :                                              this->HeatRejectCapNomCapSizingRatio,
    3038            0 :                                              this->TowerFreeConvNomCap));
    3039              : 
    3040              :                     Real64 OutWaterTemp; // outlet water temperature during sizing [C]
    3041              : 
    3042            0 :                     OutWaterTemp = this->calculateSimpleTowerOutletTemp(state, solveWaterFlow, this->FreeConvAirFlowRate, UA0);
    3043            0 :                     Real64 CoolingOutput = Cp * solveWaterFlow * (this->WaterTemp - OutWaterTemp); // tower capacity during sizing [W]
    3044            0 :                     ShowContinueError(state, format("Tower capacity at lower UA guess ({:.4T}) = {:.0T} W.", UA0, CoolingOutput));
    3045              : 
    3046            0 :                     OutWaterTemp = this->calculateSimpleTowerOutletTemp(state, solveWaterFlow, this->FreeConvAirFlowRate, UA1);
    3047            0 :                     CoolingOutput = Cp * solveWaterFlow * (this->WaterTemp - OutWaterTemp);
    3048            0 :                     ShowContinueError(state, format("Tower capacity at upper UA guess ({:.4T}) = {:.0T} W.", UA1, CoolingOutput));
    3049              : 
    3050            0 :                     if (CoolingOutput < DesTowerLoad) {
    3051            0 :                         ShowContinueError(state, "Free convection capacity should be less than tower capacity at upper UA guess.");
    3052              :                     }
    3053            0 :                     ShowFatalError(state, format("Autosizing of cooling tower UA failed for tower {}", this->Name));
    3054              :                 }
    3055           24 :                 if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3056            8 :                     this->FreeConvTowerUA = UA;
    3057              :                 }
    3058           24 :             } else {
    3059            0 :                 this->FreeConvTowerUA = 0.0;
    3060              :             }
    3061           24 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3062           16 :                 BaseSizer::reportSizerOutput(state,
    3063            8 :                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3064              :                                              this->Name,
    3065              :                                              "U-Factor Times Area Value at Free Convection Air Flow Rate [W/C]",
    3066              :                                              this->FreeConvTowerUA);
    3067              :             }
    3068           24 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3069            0 :                 BaseSizer::reportSizerOutput(state,
    3070            0 :                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3071              :                                              this->Name,
    3072              :                                              "Initial U-Factor Times Area Value at Free Convection Air Flow Rate [W/C]",
    3073              :                                              this->FreeConvTowerUA);
    3074              :             }
    3075              :         }
    3076              : 
    3077              :         // calibrate variable speed tower model based on user input by finding calibration water flow rate ratio that
    3078              :         // yields an approach temperature that matches user input
    3079           31 :         if (Util::SameString(DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)], "CoolingTower:VariableSpeed")) {
    3080              : 
    3081              :             //   check range for water flow rate ratio (make sure RegulaFalsi converges)
    3082            2 :             Real64 MaxWaterFlowRateRatio = 0.5; // maximum water flow rate ratio which yields desired approach temp
    3083            2 :             Real64 Tapproach = 0.0;             // temporary tower approach temp variable [C]
    3084            2 :             Real64 const FlowRateRatioStep = (this->MaxWaterFlowRatio - this->MinWaterFlowRatio) / 10.0;
    3085            2 :             bool ModelCalibrated = true;
    3086            2 :             Real64 ModelWaterFlowRatioMax = this->MaxWaterFlowRatio * 4.0; // maximum water flow rate ratio used for model calibration
    3087              :             //   find a flow rate large enough to provide an approach temperature > than the user defined approach
    3088            2 :             Real64 WaterFlowRateRatio(0.0); // tower water flow rate ratio
    3089           23 :             while (Tapproach < this->DesignApproach && MaxWaterFlowRateRatio <= ModelWaterFlowRatioMax) {
    3090           21 :                 WaterFlowRateRatio = MaxWaterFlowRateRatio;
    3091           21 :                 Tapproach = this->calculateVariableSpeedApproach(state, WaterFlowRateRatio, 1.0, this->DesignInletWB, this->DesignRange);
    3092           21 :                 if (Tapproach < this->DesignApproach) {
    3093           19 :                     MaxWaterFlowRateRatio += FlowRateRatioStep;
    3094              :                 }
    3095              :                 // a water flow rate large enough to provide an approach temperature > than the user defined approach does not exist
    3096              :                 // within the tolerances specified by the user
    3097           21 :                 if ((MaxWaterFlowRateRatio == 0.5 && Tapproach > this->DesignApproach) || MaxWaterFlowRateRatio >= ModelWaterFlowRatioMax) {
    3098            0 :                     ModelCalibrated = false;
    3099            0 :                     break;
    3100              :                 }
    3101              :             }
    3102              : 
    3103            2 :             Real64 WaterFlowRatio(0.0); // tower water flow rate ratio found during model calibration
    3104              : 
    3105            2 :             if (ModelCalibrated) {
    3106            8 :                 auto f = [&state, this](Real64 FlowRatio) {
    3107            8 :                     Real64 Tact = this->calculateVariableSpeedApproach(state, FlowRatio, 1.0, this->DesignInletWB, this->DesignRange);
    3108            8 :                     return this->DesignApproach - Tact;
    3109            2 :                 };
    3110            2 :                 General::SolveRoot(state, Acc, MaxIte, SolFla, WaterFlowRatio, f, DataPrecisionGlobals::constant_pointfive, MaxWaterFlowRateRatio);
    3111              : 
    3112            2 :                 if (SolFla == -1) {
    3113            0 :                     ShowSevereError(state, "Iteration limit exceeded in calculating tower water flow ratio during calibration");
    3114            0 :                     ShowContinueError(state,
    3115              :                                       "Inlet air wet-bulb, range, and/or approach temperature does not allow calibration of water flow rate ratio "
    3116              :                                       "for this variable-speed cooling tower.");
    3117            0 :                     ShowFatalError(state, format("Cooling tower calibration failed for tower {}", this->Name));
    3118            2 :                 } else if (SolFla == -2) {
    3119            0 :                     ShowSevereError(state, "Bad starting values for cooling tower water flow rate ratio calibration.");
    3120            0 :                     ShowContinueError(state,
    3121              :                                       "Inlet air wet-bulb, range, and/or approach temperature does not allow calibration of water flow rate ratio "
    3122              :                                       "for this variable-speed cooling tower.");
    3123            0 :                     ShowFatalError(state, format("Cooling tower calibration failed for tower {}.", this->Name));
    3124              :                 }
    3125              :             } else {
    3126            0 :                 ShowSevereError(state, "Bad starting values for cooling tower water flow rate ratio calibration.");
    3127            0 :                 ShowContinueError(state, "Design inlet air wet-bulb or range temperature must be modified to achieve the design approach");
    3128            0 :                 ShowContinueError(state,
    3129            0 :                                   format("A water flow rate ratio of {:.6F} was calculated to yield an approach temperature of {:.2F}.",
    3130              :                                          WaterFlowRateRatio,
    3131              :                                          Tapproach));
    3132            0 :                 ShowFatalError(state, format("Cooling tower calibration failed for tower {}.", this->Name));
    3133              :             }
    3134              : 
    3135            2 :             this->CalibratedWaterFlowRate = this->DesignWaterFlowRate / WaterFlowRatio;
    3136              : 
    3137            2 :             if (WaterFlowRatio < this->MinWaterFlowRatio || WaterFlowRatio > this->MaxWaterFlowRatio) {
    3138            0 :                 ShowWarningError(state,
    3139            0 :                                  format("CoolingTower:VariableSpeed, \"{}\" the calibrated water flow rate ratio is determined to be {:9.6F}. This "
    3140              :                                         "is outside the valid range of {:.2F} to {:.2F}.",
    3141            0 :                                         this->Name,
    3142              :                                         WaterFlowRatio,
    3143            0 :                                         this->MinWaterFlowRatio,
    3144            0 :                                         this->MaxWaterFlowRatio));
    3145              :             }
    3146              : 
    3147              :             Real64 const rho =
    3148            2 :                 this->plantLoc.loop->glycol->getDensity(state, (this->DesignInletWB + this->DesignApproach + this->DesignRange), RoutineName);
    3149              :             Real64 const Cp =
    3150            2 :                 this->plantLoc.loop->glycol->getSpecificHeat(state, (this->DesignInletWB + this->DesignApproach + this->DesignRange), RoutineName);
    3151              : 
    3152            2 :             this->TowerNominalCapacity = ((rho * tmpDesignWaterFlowRate) * Cp * this->DesignRange);
    3153            2 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3154            2 :                 BaseSizer::reportSizerOutput(state,
    3155            1 :                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3156              :                                              this->Name,
    3157              :                                              "Nominal Capacity [W]",
    3158              :                                              this->TowerNominalCapacity);
    3159              :             }
    3160            2 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3161            0 :                 BaseSizer::reportSizerOutput(state,
    3162            0 :                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3163              :                                              this->Name,
    3164              :                                              "Initial Nominal Capacity [W]",
    3165              :                                              this->TowerNominalCapacity);
    3166              :             }
    3167            2 :             this->FreeConvAirFlowRate = this->MinimumVSAirFlowFrac * this->HighSpeedAirFlowRate;
    3168              : 
    3169            2 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3170            2 :                 BaseSizer::reportSizerOutput(state,
    3171            1 :                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3172              :                                              this->Name,
    3173              :                                              "Air Flow Rate in free convection regime [m3/s]",
    3174              :                                              this->FreeConvAirFlowRate);
    3175              :             }
    3176            2 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3177            0 :                 BaseSizer::reportSizerOutput(state,
    3178            0 :                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3179              :                                              this->Name,
    3180              :                                              "Initial Air Flow Rate in free convection regime [m3/s]",
    3181              :                                              this->FreeConvAirFlowRate);
    3182              :             }
    3183            2 :             this->TowerFreeConvNomCap = this->TowerNominalCapacity * this->FreeConvectionCapacityFraction;
    3184              : 
    3185            2 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3186            2 :                 BaseSizer::reportSizerOutput(state,
    3187            1 :                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3188              :                                              this->Name,
    3189              :                                              "Tower capacity in free convection regime at design conditions [W]",
    3190              :                                              this->TowerFreeConvNomCap);
    3191              :             }
    3192            2 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3193            0 :                 BaseSizer::reportSizerOutput(state,
    3194            0 :                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3195              :                                              this->Name,
    3196              :                                              "Initial Tower capacity in free convection regime at design conditions [W]",
    3197              :                                              this->TowerFreeConvNomCap);
    3198              :             }
    3199              :         }
    3200           31 :         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3201              :             // create predefined report
    3202           20 :             OutputReportPredefined::PreDefTableEntry(
    3203           20 :                 state, state.dataOutRptPredefined->pdchMechType, this->Name, DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)]);
    3204           10 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomCap, this->Name, this->TowerNominalCapacity);
    3205              : 
    3206              :             // create std 229 new table for cooling towers and fluid coolers
    3207           20 :             OutputReportPredefined::PreDefTableEntry(
    3208           20 :                 state, state.dataOutRptPredefined->pdchCTFCType, this->Name, DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)]);
    3209           20 :             OutputReportPredefined::PreDefTableEntry(state,
    3210           10 :                                                      state.dataOutRptPredefined->pdchCTFCCondLoopName,
    3211              :                                                      this->Name,
    3212           20 :                                                      (this->plantLoc.loop != nullptr) ? this->plantLoc.loop->Name : "N/A");
    3213           20 :             OutputReportPredefined::PreDefTableEntry(state,
    3214           10 :                                                      state.dataOutRptPredefined->pdchCTFCCondLoopBranchName,
    3215              :                                                      this->Name,
    3216           20 :                                                      (this->plantLoc.branch != nullptr) ? plantLoc.branch->Name : "N/A");
    3217           20 :             OutputReportPredefined::PreDefTableEntry(state,
    3218           10 :                                                      state.dataOutRptPredefined->pdchCTFCFluidType,
    3219              :                                                      this->Name,
    3220           10 :                                                      this->plantLoc.loop->glycol->Name); // Fluid Name more reasonable than FluidType
    3221           10 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCTFCRange, this->Name, this->DesignRange);
    3222           10 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCTFCApproach, this->Name, this->DesignApproach);
    3223           20 :             OutputReportPredefined::PreDefTableEntry(
    3224           10 :                 state, state.dataOutRptPredefined->pdchCTFCDesFanPwr, this->Name, this->HighSpeedFanPower); // equivalent to Design Fan Power?
    3225           10 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCTFCDesInletAirWBT, this->Name, this->DesignInletWB);
    3226           20 :             OutputReportPredefined::PreDefTableEntry(
    3227           20 :                 state, state.dataOutRptPredefined->pdchCTFCDesWaterFlowRate, this->Name, this->DesignWaterFlowRate, 6);
    3228           10 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCTFCLevWaterSPTemp, this->Name, this->DesOutletWaterTemp);
    3229              :         }
    3230              : 
    3231              :         // input error checking
    3232           31 :         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3233           10 :             bool ErrorsFound = false;
    3234           10 :             if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_SingleSpd) {
    3235            5 :                 if (this->DesignWaterFlowRate > 0.0) {
    3236            5 :                     if (this->FreeConvAirFlowRate >= this->HighSpeedAirFlowRate) {
    3237            0 :                         ShowSevereError(state,
    3238            0 :                                         format("{} \"{}\". Free convection air flow rate must be less than the design air flow rate.",
    3239              :                                                cCoolingTower_SingleSpeed,
    3240            0 :                                                this->Name));
    3241            0 :                         ErrorsFound = true;
    3242              :                     }
    3243            5 :                     if (this->FreeConvTowerUA >= this->HighSpeedTowerUA) {
    3244            0 :                         ShowSevereError(
    3245              :                             state,
    3246            0 :                             format("{} \"{}\". Free convection UA must be less than the design tower UA.", cCoolingTower_SingleSpeed, this->Name));
    3247            0 :                         ErrorsFound = true;
    3248              :                     }
    3249              :                 }
    3250              :             }
    3251              : 
    3252           10 :             if (this->TowerType == DataPlant::PlantEquipmentType::CoolingTower_TwoSpd) {
    3253            4 :                 if (this->DesignWaterFlowRate > 0.0) {
    3254            4 :                     if (this->HighSpeedAirFlowRate <= this->LowSpeedAirFlowRate) {
    3255            0 :                         ShowSevereError(state,
    3256            0 :                                         format("{} \"{}\". Low speed air flow rate must be less than the high speed air flow rate.",
    3257              :                                                cCoolingTower_TwoSpeed,
    3258            0 :                                                this->Name));
    3259            0 :                         ErrorsFound = true;
    3260              :                     }
    3261            4 :                     if (this->LowSpeedAirFlowRate <= this->FreeConvAirFlowRate) {
    3262            0 :                         ShowSevereError(state,
    3263            0 :                                         format("{} \"{}\". Free convection air flow rate must be less than the low speed air flow rate.",
    3264              :                                                cCoolingTower_TwoSpeed,
    3265            0 :                                                this->Name));
    3266            0 :                         ErrorsFound = true;
    3267              :                     }
    3268            4 :                     if (this->HighSpeedTowerUA <= this->LowSpeedTowerUA) {
    3269            0 :                         ShowSevereError(state,
    3270            0 :                                         format("{} \"{}\". Tower UA at low fan speed must be less than the tower UA at high fan speed.",
    3271              :                                                cCoolingTower_TwoSpeed,
    3272            0 :                                                this->Name));
    3273            0 :                         ErrorsFound = true;
    3274              :                     }
    3275            4 :                     if (this->LowSpeedTowerUA <= this->FreeConvTowerUA) {
    3276            0 :                         ShowSevereError(
    3277              :                             state,
    3278            0 :                             format("{} \"{}\". Tower UA at free convection air flow rate must be less than the tower UA at low fan speed.",
    3279              :                                    cCoolingTower_TwoSpeed,
    3280            0 :                                    this->Name));
    3281            0 :                         ErrorsFound = true;
    3282              :                     }
    3283              :                 }
    3284              :             }
    3285           10 :             if (ErrorsFound) {
    3286            0 :                 ShowFatalError(state, "initialize: Program terminated due to previous condition(s).");
    3287              :             }
    3288              :         }
    3289           31 :     }
    3290              : 
    3291           13 :     void CoolingTower::SizeVSMerkelTower(EnergyPlusData &state)
    3292              :     {
    3293              : 
    3294              :         // SUBROUTINE PARAMETER DEFINITIONS:
    3295           13 :         int constexpr MaxIte(500);    // Maximum number of iterations
    3296           13 :         Real64 constexpr Acc(0.0001); // Accuracy of result
    3297              :         static constexpr std::string_view RoutineName("SizeTower");
    3298              : 
    3299              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3300              :         int SolFla; // Flag of solver
    3301              :         Real64 tmpHighSpeedFanPower;
    3302              : 
    3303              :         Real64 UA0;                       // Lower bound for UA [W/C]
    3304              :         Real64 UA1;                       // Upper bound for UA [W/C]
    3305              :         Real64 DesTowerLoad;              // Design tower load [W]
    3306           13 :         Real64 Cp(0);                     // local specific heat for fluid
    3307           13 :         Real64 rho(0);                    // local density for fluid
    3308              :         Real64 UA;                        // Calculated UA value
    3309              :         Real64 DesTowerInletWaterTemp;    // design tower inlet water temperature
    3310              :         Real64 DesTowerExitWaterTemp;     // design tower exit water temperature
    3311              :         Real64 DesTowerWaterDeltaT;       // design tower temperature range
    3312              :         Real64 DesTowerApproachFromPlant; // design tower approach temperature from plant sizing object
    3313           13 :         Real64 TolTemp(0.04);             // DeltaT and DesignApproach diffs tolerance between plant sizing data and user input in cooling tower
    3314              :         // for warning message reporting purpose only
    3315              : 
    3316              :         // Find the appropriate Plant Sizing object
    3317           13 :         int PltSizCondNum = this->plantLoc.loop->PlantSizNum;
    3318              : 
    3319           13 :         Real64 tmpNomTowerCap = this->TowerNominalCapacity;
    3320           13 :         Real64 tmpDesignWaterFlowRate = this->DesignWaterFlowRate;
    3321           13 :         Real64 tmpTowerFreeConvNomCap = this->TowerFreeConvNomCap;
    3322           13 :         Real64 tmpDesignAirFlowRate = this->HighSpeedAirFlowRate;
    3323           13 :         Real64 tmpFreeConvAirFlowRate = this->FreeConvAirFlowRate;
    3324           13 :         Real64 DesTowerInletAirWBTemp = this->DesignInletWB;
    3325           13 :         Real64 DesTowerInletAirDBTemp = this->DesInletAirDBTemp;
    3326              : 
    3327           13 :         auto const &PlantSizData(state.dataSize->PlantSizData);
    3328              : 
    3329           13 :         if (this->TowerInletCondsAutoSize) {
    3330            6 :             if (PltSizCondNum > 0) {
    3331              :                 // use plant sizing data
    3332            0 :                 DesTowerExitWaterTemp = PlantSizData(PltSizCondNum).ExitTemp;
    3333            0 :                 DesTowerInletWaterTemp = DesTowerExitWaterTemp + PlantSizData(PltSizCondNum).DeltaT;
    3334            0 :                 DesTowerWaterDeltaT = PlantSizData(PltSizCondNum).DeltaT;
    3335              :             } else {
    3336              :                 // set default values to replace hard wired input assumptions
    3337            6 :                 DesTowerExitWaterTemp = this->DesOutletWaterTemp;
    3338            6 :                 DesTowerInletWaterTemp = this->DesInletWaterTemp;
    3339            6 :                 DesTowerWaterDeltaT = this->DesignRange;
    3340              :             }
    3341              :         } else {
    3342              :             // use tower sizing data
    3343            7 :             DesTowerExitWaterTemp = this->DesOutletWaterTemp;
    3344            7 :             DesTowerInletWaterTemp = this->DesInletWaterTemp;
    3345            7 :             DesTowerWaterDeltaT = this->DesignRange;
    3346            7 :             if (PltSizCondNum > 0) {
    3347              :                 // check the tower range against the plant sizing data
    3348            1 :                 if (std::abs(DesTowerWaterDeltaT - PlantSizData(PltSizCondNum).DeltaT) > TolTemp) {
    3349            0 :                     ShowWarningError(state,
    3350            0 :                                      format("Error when autosizing the load for cooling tower = {}. Tower Design Range Temperature is different from "
    3351              :                                             "the Design Loop Delta Temperature.",
    3352            0 :                                             this->Name));
    3353            0 :                     ShowContinueError(state, format("Tower Design Range Temperature specified in tower = {}", this->Name));
    3354            0 :                     ShowContinueError(state,
    3355            0 :                                       format("is inconsistent with Design Loop Delta Temperature specified in Sizing:Plant object = {}.",
    3356            0 :                                              PlantSizData(PltSizCondNum).PlantLoopName));
    3357            0 :                     ShowContinueError(state, format("..The Design Range Temperature specified in tower is = {:.2T}", this->DesignRange));
    3358            0 :                     ShowContinueError(
    3359              :                         state,
    3360            0 :                         format("..The Design Loop Delta Temperature specified in plant sizing data is = {:.2T}", PlantSizData(PltSizCondNum).DeltaT));
    3361              :                 }
    3362              :                 // check if the tower approach is different from plant sizing data
    3363            1 :                 DesTowerApproachFromPlant = PlantSizData(PltSizCondNum).ExitTemp - this->DesignInletWB;
    3364            1 :                 if (std::abs(DesTowerApproachFromPlant - this->DesignApproach) > TolTemp) {
    3365            0 :                     ShowWarningError(state,
    3366            0 :                                      format("Error when autosizing the UA for cooling tower = {}. Tower Design Approach Temperature is inconsistent "
    3367              :                                             "with Approach from Plant Sizing Data.",
    3368            0 :                                             this->Name));
    3369            0 :                     ShowContinueError(state,
    3370            0 :                                       format("The Design Approach Temperature from inputs specified in Sizing:Plant object = {}",
    3371            0 :                                              PlantSizData(PltSizCondNum).PlantLoopName));
    3372            0 :                     ShowContinueError(state, format("is inconsistent with Design Approach Temperature specified in tower = {}.", this->Name));
    3373            0 :                     ShowContinueError(state,
    3374            0 :                                       format("..The Design Approach Temperature from inputs specified is = {:.2T}", DesTowerApproachFromPlant));
    3375            0 :                     ShowContinueError(state, format("..The Design Approach Temperature specified in tower is = {:.2T}", this->DesignApproach));
    3376              :                 }
    3377              :             }
    3378              :         }
    3379              : 
    3380           13 :         if (this->PerformanceInputMethod_Num == PIM::NominalCapacity) {
    3381              : 
    3382           13 :             if (PltSizCondNum > 0) { // get nominal capacity from PlantSizData(PltSizCondNum)%DeltaT and PlantSizData(PltSizCondNum)%DesVolFlowRate
    3383            1 :                 if (PlantSizData(PltSizCondNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
    3384            1 :                     rho = this->plantLoc.loop->glycol->getDensity(state, DesTowerExitWaterTemp, RoutineName);
    3385            1 :                     Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, DesTowerExitWaterTemp, RoutineName);
    3386            1 :                     DesTowerLoad = rho * Cp * PlantSizData(PltSizCondNum).DesVolFlowRate * DesTowerWaterDeltaT * this->SizFac;
    3387            1 :                     tmpNomTowerCap = DesTowerLoad / this->HeatRejectCapNomCapSizingRatio;
    3388              :                 } else {
    3389            0 :                     if (this->TowerNominalCapacityWasAutoSized) tmpNomTowerCap = 0.0;
    3390              :                 }
    3391              :             } else {                                  // PltSizCondNum = 0
    3392           12 :                 if (!this->TowerInletCondsAutoSize) { // can use design data entered into tower object
    3393            6 :                     if (this->DesignWaterFlowRate >= HVAC::SmallWaterVolFlow) {
    3394            1 :                         rho = this->plantLoc.loop->glycol->getDensity(state, DesTowerExitWaterTemp, RoutineName);
    3395            1 :                         Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, DesTowerExitWaterTemp, RoutineName);
    3396            1 :                         DesTowerLoad = rho * Cp * this->DesignWaterFlowRate * DesTowerWaterDeltaT * this->SizFac;
    3397            1 :                         tmpNomTowerCap = DesTowerLoad / this->HeatRejectCapNomCapSizingRatio;
    3398              :                     } else {
    3399            5 :                         if (this->TowerNominalCapacityWasAutoSized) tmpNomTowerCap = 0.0;
    3400              :                     }
    3401              :                 } else { // do not have enough data to size.
    3402            6 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize && this->TowerNominalCapacityWasAutoSized) {
    3403            0 :                         ShowSevereError(state, format("Autosizing error for cooling tower object = {}", this->Name));
    3404            0 :                         ShowFatalError(state, "Autosizing of cooling tower nominal capacity requires a loop Sizing:Plant object.");
    3405              :                     }
    3406              :                 }
    3407              :             }
    3408           13 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3409            5 :                 if (this->TowerNominalCapacityWasAutoSized) {
    3410            1 :                     this->TowerNominalCapacity = tmpNomTowerCap;
    3411            1 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3412            2 :                         BaseSizer::reportSizerOutput(state,
    3413            1 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3414              :                                                      this->Name,
    3415              :                                                      "Design Nominal Capacity [W]",
    3416              :                                                      tmpNomTowerCap);
    3417              :                     }
    3418            1 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3419            0 :                         BaseSizer::reportSizerOutput(state,
    3420            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3421              :                                                      this->Name,
    3422              :                                                      "Initial Design Nominal Capacity [W]",
    3423              :                                                      this->TowerNominalCapacity);
    3424              :                     }
    3425              :                 } else { // Hard-sized with sizing data
    3426            4 :                     if (this->TowerNominalCapacity > 0.0 && tmpNomTowerCap > 0.0) {
    3427            4 :                         Real64 NomCapUser(0.0);
    3428            4 :                         NomCapUser = this->TowerNominalCapacity;
    3429            4 :                         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3430            8 :                             BaseSizer::reportSizerOutput(state,
    3431            4 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3432              :                                                          this->Name,
    3433              :                                                          "Design Nominal Capacity [W]",
    3434              :                                                          tmpNomTowerCap,
    3435              :                                                          "User-Specified Nominal Capacity [W]",
    3436              :                                                          NomCapUser);
    3437            4 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    3438            0 :                                 if ((std::abs(tmpNomTowerCap - NomCapUser) / NomCapUser) > state.dataSize->AutoVsHardSizingThreshold) {
    3439            0 :                                     ShowMessage(state, format("SizeVSMerkelTower: Potential issue with equipment sizing for {}", this->Name));
    3440            0 :                                     ShowContinueError(state, format("User-Specified Nominal Capacity of {:.2R} [W]", NomCapUser));
    3441            0 :                                     ShowContinueError(state, format("differs from Design Size Nominal Capacity of {:.2R} [W]", tmpNomTowerCap));
    3442            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    3443            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    3444              :                                 }
    3445              :                             }
    3446            4 :                             tmpNomTowerCap = NomCapUser;
    3447              :                         }
    3448              :                     }
    3449              :                 }
    3450              :             }
    3451              : 
    3452           13 :             tmpTowerFreeConvNomCap = tmpNomTowerCap * this->TowerFreeConvNomCapSizingFactor;
    3453           13 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3454            5 :                 if (this->TowerFreeConvNomCapWasAutoSized) {
    3455            5 :                     this->TowerFreeConvNomCap = tmpTowerFreeConvNomCap;
    3456            5 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3457           10 :                         BaseSizer::reportSizerOutput(state,
    3458            5 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3459              :                                                      this->Name,
    3460              :                                                      "Design Free Convection Nominal Capacity [W]",
    3461              :                                                      this->TowerFreeConvNomCap);
    3462              :                     }
    3463            5 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3464            0 :                         BaseSizer::reportSizerOutput(state,
    3465            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3466              :                                                      this->Name,
    3467              :                                                      "Initial Design Free Convection Nominal Capacity [W]",
    3468              :                                                      this->TowerFreeConvNomCap);
    3469              :                     }
    3470              :                 } else { // Hard-sized with sizing data
    3471            0 :                     if (this->TowerFreeConvNomCap > 0.0 && tmpTowerFreeConvNomCap > 0.0) {
    3472            0 :                         Real64 NomCapUser(0.0);
    3473            0 :                         NomCapUser = this->TowerFreeConvNomCap;
    3474            0 :                         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3475            0 :                             BaseSizer::reportSizerOutput(state,
    3476            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3477              :                                                          this->Name,
    3478              :                                                          "Design Free Convection Nominal Capacity [W]",
    3479              :                                                          tmpTowerFreeConvNomCap,
    3480              :                                                          "User-Specified Free Convection Nominal Capacity [W]",
    3481              :                                                          NomCapUser);
    3482            0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    3483            0 :                                 if ((std::abs(tmpTowerFreeConvNomCap - NomCapUser) / NomCapUser) > state.dataSize->AutoVsHardSizingThreshold) {
    3484            0 :                                     ShowMessage(state, format("SizeVSMerkelTower: Potential issue with equipment sizing for {}", this->Name));
    3485            0 :                                     ShowContinueError(state, format("User-Specified Free Convection Nominal Capacity of {:.2R} [W]", NomCapUser));
    3486            0 :                                     ShowContinueError(
    3487              :                                         state,
    3488            0 :                                         format("differs from Design Size Free Convection Nominal Capacity of {:.2R} [W]", tmpTowerFreeConvNomCap));
    3489            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    3490            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    3491              :                                 }
    3492              :                             }
    3493            0 :                             tmpTowerFreeConvNomCap = NomCapUser;
    3494              :                         }
    3495              :                     }
    3496              :                 }
    3497              :             }
    3498              : 
    3499           13 :             tmpDesignWaterFlowRate = tmpNomTowerCap * this->DesignWaterFlowPerUnitNomCap;
    3500           13 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3501            5 :                 if (this->DesignWaterFlowRateWasAutoSized) {
    3502              :                     // for nominal cap input method, get design water flow rate from nominal cap and scalable sizing factor
    3503              : 
    3504            4 :                     this->DesignWaterFlowRate = tmpDesignWaterFlowRate;
    3505            4 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3506            8 :                         BaseSizer::reportSizerOutput(state,
    3507            4 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3508              :                                                      this->Name,
    3509              :                                                      "Design Water Flow Rate [m3/s]",
    3510              :                                                      this->DesignWaterFlowRate);
    3511              :                     }
    3512            4 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3513            0 :                         BaseSizer::reportSizerOutput(state,
    3514            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3515              :                                                      this->Name,
    3516              :                                                      "Initial Design Water Flow Rate [m3/s]",
    3517              :                                                      this->DesignWaterFlowRate);
    3518              :                     }
    3519              : 
    3520              :                 } else { // Hard-sized with sizing data
    3521            1 :                     if (this->DesignWaterFlowRate > 0.0 && tmpDesignWaterFlowRate > 0.0) {
    3522            1 :                         Real64 NomDesWaterFlowUser(0.0);
    3523            1 :                         NomDesWaterFlowUser = this->DesignWaterFlowRate;
    3524            1 :                         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3525            2 :                             BaseSizer::reportSizerOutput(state,
    3526            1 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3527              :                                                          this->Name,
    3528              :                                                          "Design Water Flow Rate [m3/s]",
    3529              :                                                          this->DesignWaterFlowRate,
    3530              :                                                          "User-Specified Design Water Flow Rate [m3/s]",
    3531              :                                                          NomDesWaterFlowUser);
    3532            1 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    3533            0 :                                 if ((std::abs(tmpDesignWaterFlowRate - NomDesWaterFlowUser) / NomDesWaterFlowUser) >
    3534            0 :                                     state.dataSize->AutoVsHardSizingThreshold) {
    3535            0 :                                     ShowMessage(state, format("SizeVSMerkelTower: Potential issue with equipment sizing for {}", this->Name));
    3536            0 :                                     ShowContinueError(state, format("User-Specified Design Water Flow Rate of {:.2R} [m3/s]", NomDesWaterFlowUser));
    3537            0 :                                     ShowContinueError(state, format("differs from Design Water Flow Rate of {:.2R} [m3/s]", tmpDesignWaterFlowRate));
    3538            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    3539            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    3540              :                                 }
    3541              :                             }
    3542            1 :                             tmpDesignWaterFlowRate = NomDesWaterFlowUser;
    3543              :                         }
    3544              :                     }
    3545              :                 }
    3546              :             }
    3547              : 
    3548           13 :             PlantUtilities::RegisterPlantCompDesignFlow(state, this->WaterInletNodeNum, tmpDesignWaterFlowRate);
    3549              : 
    3550           13 :             if (this->DefaultedDesignAirFlowScalingFactor) {
    3551            0 :                 tmpDesignAirFlowRate = tmpNomTowerCap * this->DesignAirFlowPerUnitNomCap * (101325.0 / state.dataEnvrn->StdBaroPress);
    3552              :             } else {
    3553           13 :                 tmpDesignAirFlowRate = tmpNomTowerCap * this->DesignAirFlowPerUnitNomCap;
    3554              :             }
    3555           13 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3556            5 :                 if (this->HighSpeedAirFlowRateWasAutoSized) {
    3557            5 :                     this->HighSpeedAirFlowRate = tmpDesignAirFlowRate;
    3558            5 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3559           10 :                         BaseSizer::reportSizerOutput(state,
    3560            5 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3561              :                                                      this->Name,
    3562              :                                                      "Design Air Flow Rate [m3/s]",
    3563              :                                                      this->HighSpeedAirFlowRate);
    3564              :                     }
    3565            5 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3566            0 :                         BaseSizer::reportSizerOutput(state,
    3567            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3568              :                                                      this->Name,
    3569              :                                                      "Initial Design Air Flow Rate [m3/s]",
    3570              :                                                      this->HighSpeedAirFlowRate);
    3571              :                     }
    3572              :                 } else { // Hard-sized with sizing data
    3573            0 :                     Real64 DesignAirFlowRateUser(0.0);
    3574            0 :                     DesignAirFlowRateUser = this->HighSpeedAirFlowRate;
    3575            0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3576            0 :                         BaseSizer::reportSizerOutput(state,
    3577            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3578              :                                                      this->Name,
    3579              :                                                      "Design Air Flow Rate [m3/s]",
    3580              :                                                      tmpDesignAirFlowRate,
    3581              :                                                      "User-Specified Design Air Flow Rate [m3/s]",
    3582              :                                                      DesignAirFlowRateUser);
    3583            0 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    3584            0 :                             if ((std::abs(tmpDesignAirFlowRate - DesignAirFlowRateUser) / DesignAirFlowRateUser) >
    3585            0 :                                 state.dataSize->AutoVsHardSizingThreshold) {
    3586            0 :                                 ShowMessage(state, format("SizeVSMerkelTower: Potential issue with equipment sizing for {}", this->Name));
    3587            0 :                                 ShowContinueError(state, format("User-Specified Design Air Flow Rate of {:.2R} [m3/s]", DesignAirFlowRateUser));
    3588            0 :                                 ShowContinueError(state, format("differs from Design Air Flow Rate of {:.2R} [m3/s]", tmpDesignAirFlowRate));
    3589            0 :                                 ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    3590            0 :                                 ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    3591              :                             }
    3592              :                         }
    3593            0 :                         tmpDesignAirFlowRate = DesignAirFlowRateUser;
    3594              :                     }
    3595              :                 }
    3596              :             }
    3597           13 :             tmpFreeConvAirFlowRate = tmpDesignAirFlowRate * this->FreeConvAirFlowRateSizingFactor;
    3598              : 
    3599           13 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3600            5 :                 if (this->FreeConvAirFlowRateWasAutoSized) {
    3601            5 :                     this->FreeConvAirFlowRate = tmpFreeConvAirFlowRate;
    3602            5 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3603           10 :                         BaseSizer::reportSizerOutput(state,
    3604            5 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3605              :                                                      this->Name,
    3606              :                                                      "Design Free Convection Regime Air Flow Rate [m3/s]",
    3607              :                                                      this->FreeConvAirFlowRate);
    3608              :                     }
    3609            5 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3610            0 :                         BaseSizer::reportSizerOutput(state,
    3611            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3612              :                                                      this->Name,
    3613              :                                                      "Initial Design Free Convection Regime Air Flow Rate [m3/s]",
    3614              :                                                      this->FreeConvAirFlowRate);
    3615              :                     }
    3616              :                 } else { // Hard-sized with sizing data
    3617            0 :                     Real64 FreeConvAirFlowUser(0.0);
    3618            0 :                     FreeConvAirFlowUser = this->FreeConvAirFlowRate;
    3619            0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3620            0 :                         BaseSizer::reportSizerOutput(state,
    3621            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3622              :                                                      this->Name,
    3623              :                                                      "Design Free Convection Regime Air Flow Rate [m3/s]",
    3624              :                                                      tmpFreeConvAirFlowRate,
    3625              :                                                      "User-Specified Design Free Convection Regime Air Flow Rate [m3/s]",
    3626              :                                                      FreeConvAirFlowUser);
    3627            0 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    3628            0 :                             if ((std::abs(tmpFreeConvAirFlowRate - FreeConvAirFlowUser) / FreeConvAirFlowUser) >
    3629            0 :                                 state.dataSize->AutoVsHardSizingThreshold) {
    3630            0 :                                 ShowMessage(state, format("SizeVSMerkelTower: Potential issue with equipment sizing for {}", this->Name));
    3631            0 :                                 ShowContinueError(
    3632              :                                     state,
    3633            0 :                                     format("User-Specified Design Free Convection Regime Air Flow Rate of {:.2R} [m3/s]", FreeConvAirFlowUser));
    3634            0 :                                 ShowContinueError(
    3635              :                                     state,
    3636            0 :                                     format("differs from Design Free Convection Regime Air Flow Rate of {:.2R} [m3/s]", tmpFreeConvAirFlowRate));
    3637            0 :                                 ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    3638            0 :                                 ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    3639              :                             }
    3640              :                         }
    3641            0 :                         tmpFreeConvAirFlowRate = FreeConvAirFlowUser;
    3642              :                     }
    3643              :                 }
    3644              :             }
    3645              : 
    3646              :             // now calculate UA values from nominal capacities and flow rates
    3647           13 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3648            5 :                 if (PltSizCondNum > 0) { // user has a plant sizing object
    3649            1 :                     Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, DesTowerExitWaterTemp, RoutineName);
    3650            1 :                     this->WaterTemp = DesTowerInletWaterTemp;
    3651              :                 } else { // probably no plant sizing object
    3652            4 :                     Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, Constant::InitConvTemp, RoutineName);
    3653            4 :                     this->WaterTemp = DesTowerInletWaterTemp; // 35.0; // design condition
    3654              :                 }
    3655            5 :                 rho = this->plantLoc.loop->glycol->getDensity(state, Constant::InitConvTemp, RoutineName);
    3656              : 
    3657              :                 // full speed fan tower UA
    3658            5 :                 Real64 const solveLoad = tmpNomTowerCap * this->HeatRejectCapNomCapSizingRatio;
    3659            5 :                 Real64 const solveWaterFlow = rho * tmpDesignWaterFlowRate; // design water mass flow rate
    3660            5 :                 UA0 = 0.0001 * solveLoad;                                   // Assume deltaT = 10000K (limit)
    3661            5 :                 UA1 = solveLoad;                                            // Assume deltaT = 1K
    3662              : 
    3663            5 :                 this->AirTemp = this->DesInletAirDBTemp; // 35.0;
    3664            5 :                 this->AirWetBulb = this->DesignInletWB;  // 25.6;
    3665            5 :                 this->AirPress = state.dataEnvrn->StdBaroPress;
    3666            5 :                 this->AirHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, this->AirTemp, this->AirWetBulb, this->AirPress);
    3667          170 :                 auto f = [&state, this, solveLoad, solveWaterFlow, tmpDesignAirFlowRate, Cp](Real64 UA) {
    3668          170 :                     Real64 const OutWaterTemp = this->calculateSimpleTowerOutletTemp(state, solveWaterFlow, tmpDesignAirFlowRate, UA);
    3669          170 :                     Real64 const CoolingOutput = Cp * solveWaterFlow * (this->WaterTemp - OutWaterTemp); // tower cooling output [W]
    3670          170 :                     return (solveLoad - CoolingOutput) / solveLoad;
    3671            5 :                 };
    3672            5 :                 General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f, UA0, UA1);
    3673            5 :                 if (SolFla == -1) {
    3674            0 :                     ShowSevereError(state, "Iteration limit exceeded in calculating tower UA");
    3675            0 :                     ShowFatalError(state, format("calculating cooling tower UA failed for tower {}", this->Name));
    3676            5 :                 } else if (SolFla == -2) {
    3677            0 :                     ShowSevereError(state, "Bad starting values for UA");
    3678            0 :                     ShowFatalError(state, format("Autosizing of cooling tower UA failed for tower {}", this->Name));
    3679              :                 }
    3680            5 :                 this->HighSpeedTowerUA = UA;
    3681            5 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3682           10 :                     BaseSizer::reportSizerOutput(state,
    3683            5 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3684              :                                                  this->Name,
    3685              :                                                  "U-Factor Times Area Value at Full Speed Air Flow Rate [W/C]",
    3686              :                                                  this->HighSpeedTowerUA);
    3687              :                 }
    3688            5 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3689            0 :                     BaseSizer::reportSizerOutput(state,
    3690            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3691              :                                                  this->Name,
    3692              :                                                  "Initial U-Factor Times Area Value at Full Speed Air Flow Rate [W/C]",
    3693              :                                                  this->HighSpeedTowerUA);
    3694              :                 }
    3695              :                 // free convection tower UA
    3696            5 :                 Real64 const solveLoad1 = tmpTowerFreeConvNomCap * this->HeatRejectCapNomCapSizingRatio;
    3697            5 :                 Real64 solveWaterFlow1 = rho * tmpDesignWaterFlowRate; // design water mass flow rate
    3698            5 :                 UA0 = 0.0001 * solveLoad1;                             // Assume deltaT = 10000K (limit)
    3699            5 :                 UA0 = max(UA0, 1.0);                                   // limit to 1.0
    3700            5 :                 UA1 = solveLoad1;                                      // Assume deltaT = 1K
    3701            5 :                 this->AirTemp = this->DesInletAirDBTemp;               // 35.0;
    3702            5 :                 this->AirWetBulb = this->DesignInletWB;                // 25.6;
    3703            5 :                 this->AirPress = state.dataEnvrn->StdBaroPress;
    3704            5 :                 this->AirHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, this->AirTemp, this->AirWetBulb, this->AirPress);
    3705          141 :                 auto f2 = [&state, this, solveLoad1, solveWaterFlow1, tmpFreeConvAirFlowRate, Cp](Real64 UA) {
    3706          141 :                     Real64 const OutWaterTemp = this->calculateSimpleTowerOutletTemp(state, solveWaterFlow1, tmpFreeConvAirFlowRate, UA);
    3707          141 :                     Real64 const CoolingOutput = Cp * solveWaterFlow1 * (this->WaterTemp - OutWaterTemp); // tower cooling output [W]
    3708          141 :                     return (solveLoad1 - CoolingOutput) / solveLoad1;
    3709            5 :                 };
    3710            5 :                 General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f2, UA0, UA1);
    3711            5 :                 if (SolFla == -1) {
    3712            0 :                     ShowSevereError(state, "Iteration limit exceeded in calculating tower free convection UA");
    3713            0 :                     ShowFatalError(state, format("calculating cooling tower UA failed for tower {}", this->Name));
    3714            5 :                 } else if (SolFla == -2) {
    3715            0 :                     ShowSevereError(state, "Bad starting values for UA");
    3716            0 :                     ShowFatalError(state, format("Autosizing of cooling tower UA failed for free convection tower {}", this->Name));
    3717              :                 }
    3718            5 :                 this->FreeConvTowerUA = UA;
    3719            5 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3720           10 :                     BaseSizer::reportSizerOutput(state,
    3721            5 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3722              :                                                  this->Name,
    3723              :                                                  "U-Factor Times Area Value at Free Convection Air Flow Rate [W/C]",
    3724              :                                                  this->FreeConvTowerUA);
    3725              :                 }
    3726            5 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3727            0 :                     BaseSizer::reportSizerOutput(state,
    3728            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3729              :                                                  this->Name,
    3730              :                                                  "Initial U-Factor Times Area Value at Free Convection Air Flow Rate [W/C]",
    3731              :                                                  this->FreeConvTowerUA);
    3732              :                 }
    3733              :             }
    3734            0 :         } else if (this->PerformanceInputMethod_Num == PIM::UFactor) {
    3735              :             // UA input method
    3736              : 
    3737            0 :             if (this->DesignWaterFlowRateWasAutoSized) { // get from plant sizing
    3738              :                 // UA input method using plant sizing for flow rate, whereas Nominal capacity method uses scalable sizing factor per cap
    3739            0 :                 if (PltSizCondNum > 0) {
    3740            0 :                     if (PlantSizData(PltSizCondNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
    3741            0 :                         tmpDesignWaterFlowRate = PlantSizData(PltSizCondNum).DesVolFlowRate * this->SizFac;
    3742            0 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3743            0 :                             this->DesignWaterFlowRate = tmpDesignWaterFlowRate;
    3744            0 :                             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3745            0 :                                 BaseSizer::reportSizerOutput(state,
    3746            0 :                                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3747              :                                                              this->Name,
    3748              :                                                              "Design Water Flow Rate [m3/s]",
    3749              :                                                              this->DesignWaterFlowRate);
    3750              :                             }
    3751            0 :                             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3752            0 :                                 BaseSizer::reportSizerOutput(state,
    3753            0 :                                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3754              :                                                              this->Name,
    3755              :                                                              "Initial Design Water Flow Rate [m3/s]",
    3756              :                                                              this->DesignWaterFlowRate);
    3757              :                             }
    3758              :                         }
    3759              :                     } else {
    3760            0 :                         tmpDesignWaterFlowRate = 0.0;
    3761              :                     }
    3762              : 
    3763              :                 } else {
    3764            0 :                     if (!this->TowerInletCondsAutoSize) {
    3765            0 :                         if (this->DesignWaterFlowRate >= HVAC::SmallWaterVolFlow) {
    3766            0 :                             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3767            0 :                                 this->DesignWaterFlowRate = tmpDesignWaterFlowRate;
    3768            0 :                                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3769            0 :                                     BaseSizer::reportSizerOutput(state,
    3770            0 :                                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3771              :                                                                  this->Name,
    3772              :                                                                  "Design Water Flow Rate [m3/s]",
    3773              :                                                                  this->DesignWaterFlowRate);
    3774              :                                 }
    3775            0 :                                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3776            0 :                                     BaseSizer::reportSizerOutput(state,
    3777            0 :                                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3778              :                                                                  this->Name,
    3779              :                                                                  "Initial Design Water Flow Rate [m3/s]",
    3780              :                                                                  this->DesignWaterFlowRate);
    3781              :                                 }
    3782              :                             }
    3783              :                         } else {
    3784            0 :                             tmpDesignWaterFlowRate = 0.0;
    3785              :                         }
    3786              :                     } else {
    3787            0 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3788            0 :                             ShowSevereError(state, format("Autosizing error for cooling tower object = {}", this->Name));
    3789            0 :                             ShowFatalError(state, "Autosizing of cooling tower nominal capacity requires a loop Sizing:Plant object.");
    3790              :                         }
    3791              :                     }
    3792              :                 }
    3793              :             }
    3794            0 :             PlantUtilities::RegisterPlantCompDesignFlow(state, this->WaterInletNodeNum, tmpDesignWaterFlowRate);
    3795              : 
    3796            0 :             if (this->HighSpeedTowerUAWasAutoSized) {
    3797              :                 // get nominal capacity from PlantSizData(PltSizCondNum)%DeltaT and PlantSizData(PltSizCondNum)%DesVolFlowRate
    3798            0 :                 if (PltSizCondNum > 0) {
    3799            0 :                     if (PlantSizData(PltSizCondNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
    3800            0 :                         rho = this->plantLoc.loop->glycol->getDensity(state, DesTowerExitWaterTemp, RoutineName);
    3801            0 :                         Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, DesTowerExitWaterTemp, RoutineName);
    3802            0 :                         DesTowerLoad = rho * Cp * PlantSizData(PltSizCondNum).DesVolFlowRate * DesTowerWaterDeltaT * this->SizFac;
    3803            0 :                         tmpNomTowerCap = DesTowerLoad / this->HeatRejectCapNomCapSizingRatio;
    3804            0 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3805            0 :                             this->TowerNominalCapacity = tmpNomTowerCap;
    3806            0 :                             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3807            0 :                                 BaseSizer::reportSizerOutput(state,
    3808            0 :                                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3809              :                                                              this->Name,
    3810              :                                                              "Nominal Capacity [W]",
    3811              :                                                              this->TowerNominalCapacity);
    3812              :                             }
    3813            0 :                             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3814            0 :                                 BaseSizer::reportSizerOutput(state,
    3815            0 :                                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3816              :                                                              this->Name,
    3817              :                                                              "Initial Nominal Capacity [W]",
    3818              :                                                              this->TowerNominalCapacity);
    3819              :                             }
    3820              :                         }
    3821              :                     } else {
    3822            0 :                         tmpNomTowerCap = 0.0;
    3823            0 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3824            0 :                             this->TowerNominalCapacity = tmpNomTowerCap;
    3825            0 :                             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3826            0 :                                 BaseSizer::reportSizerOutput(state,
    3827            0 :                                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3828              :                                                              this->Name,
    3829              :                                                              "Nominal Capacity [W]",
    3830              :                                                              this->TowerNominalCapacity);
    3831              :                             }
    3832            0 :                             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3833            0 :                                 BaseSizer::reportSizerOutput(state,
    3834            0 :                                                              DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3835              :                                                              this->Name,
    3836              :                                                              "Initial Nominal Capacity [W]",
    3837              :                                                              this->TowerNominalCapacity);
    3838              :                             }
    3839              :                         }
    3840              :                     }
    3841              :                 } else {
    3842            0 :                     if (!this->TowerInletCondsAutoSize) {
    3843            0 :                         if (this->DesignWaterFlowRate >= HVAC::SmallWaterVolFlow) {
    3844            0 :                             rho = this->plantLoc.loop->glycol->getDensity(state, DesTowerExitWaterTemp, RoutineName);
    3845            0 :                             Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, DesTowerExitWaterTemp, RoutineName);
    3846            0 :                             DesTowerLoad = rho * Cp * this->DesignWaterFlowRate * DesTowerWaterDeltaT * this->SizFac;
    3847            0 :                             tmpNomTowerCap = DesTowerLoad / this->HeatRejectCapNomCapSizingRatio;
    3848            0 :                             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3849            0 :                                 this->TowerNominalCapacity = tmpNomTowerCap;
    3850            0 :                                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3851            0 :                                     BaseSizer::reportSizerOutput(state,
    3852            0 :                                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3853              :                                                                  this->Name,
    3854              :                                                                  "Nominal Capacity [W]",
    3855              :                                                                  this->TowerNominalCapacity);
    3856              :                                 }
    3857            0 :                                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3858            0 :                                     BaseSizer::reportSizerOutput(state,
    3859            0 :                                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3860              :                                                                  this->Name,
    3861              :                                                                  "Initial Nominal Capacity [W]",
    3862              :                                                                  this->TowerNominalCapacity);
    3863              :                                 }
    3864              :                             }
    3865              :                         } else {
    3866            0 :                             tmpNomTowerCap = 0.0;
    3867            0 :                             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3868            0 :                                 this->TowerNominalCapacity = tmpNomTowerCap;
    3869            0 :                                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3870            0 :                                     BaseSizer::reportSizerOutput(state,
    3871            0 :                                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3872              :                                                                  this->Name,
    3873              :                                                                  "Nominal Capacity [W]",
    3874              :                                                                  this->TowerNominalCapacity);
    3875              :                                 }
    3876            0 :                                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3877            0 :                                     BaseSizer::reportSizerOutput(state,
    3878            0 :                                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3879              :                                                                  this->Name,
    3880              :                                                                  "Initial Nominal Capacity [W]",
    3881              :                                                                  this->TowerNominalCapacity);
    3882              :                                 }
    3883              :                             }
    3884              :                         }
    3885              :                     } else {
    3886            0 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3887            0 :                             ShowSevereError(state, format("Autosizing error for cooling tower object = {}", this->Name));
    3888            0 :                             ShowFatalError(state, "Autosizing of cooling tower nominal capacity requires a loop Sizing:Plant object.");
    3889              :                         }
    3890              :                     }
    3891              :                 }
    3892            0 :                 if (this->TowerFreeConvNomCapWasAutoSized) {
    3893            0 :                     tmpTowerFreeConvNomCap = tmpNomTowerCap * this->TowerFreeConvNomCapSizingFactor;
    3894            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3895            0 :                         this->TowerFreeConvNomCap = tmpTowerFreeConvNomCap;
    3896            0 :                         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3897            0 :                             BaseSizer::reportSizerOutput(state,
    3898            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3899              :                                                          this->Name,
    3900              :                                                          "Free Convection Nominal Capacity [W]",
    3901              :                                                          this->TowerFreeConvNomCap);
    3902              :                         }
    3903            0 :                         if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3904            0 :                             BaseSizer::reportSizerOutput(state,
    3905            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3906              :                                                          this->Name,
    3907              :                                                          "Initial Free Convection Nominal Capacity [W]",
    3908              :                                                          this->TowerFreeConvNomCap);
    3909              :                         }
    3910              :                     }
    3911              :                 }
    3912            0 :                 if (this->HighSpeedAirFlowRateWasAutoSized) {
    3913            0 :                     if (this->DefaultedDesignAirFlowScalingFactor) {
    3914            0 :                         tmpDesignAirFlowRate = tmpNomTowerCap * this->DesignAirFlowPerUnitNomCap * (101325.0 / state.dataEnvrn->StdBaroPress);
    3915              :                     } else {
    3916            0 :                         tmpDesignAirFlowRate = tmpNomTowerCap * this->DesignAirFlowPerUnitNomCap;
    3917              :                     }
    3918            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3919            0 :                         this->HighSpeedAirFlowRate = tmpDesignAirFlowRate;
    3920            0 :                         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3921            0 :                             BaseSizer::reportSizerOutput(state,
    3922            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3923              :                                                          this->Name,
    3924              :                                                          "Design Air Flow Rate [m3/s]",
    3925              :                                                          this->HighSpeedAirFlowRate);
    3926              :                         }
    3927            0 :                         if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3928            0 :                             BaseSizer::reportSizerOutput(state,
    3929            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3930              :                                                          this->Name,
    3931              :                                                          "Initial Design Air Flow Rate [m3/s]",
    3932              :                                                          this->HighSpeedAirFlowRate);
    3933              :                         }
    3934              :                     }
    3935              :                 }
    3936            0 :                 if (this->FreeConvAirFlowRateWasAutoSized) {
    3937            0 :                     tmpFreeConvAirFlowRate = tmpDesignAirFlowRate * this->FreeConvAirFlowRateSizingFactor;
    3938            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3939            0 :                         this->FreeConvAirFlowRate = tmpFreeConvAirFlowRate;
    3940            0 :                         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3941            0 :                             BaseSizer::reportSizerOutput(state,
    3942            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3943              :                                                          this->Name,
    3944              :                                                          "Free Convection Regime Air Flow Rate [m3/s]",
    3945              :                                                          this->FreeConvAirFlowRate);
    3946              :                         }
    3947            0 :                         if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3948            0 :                             BaseSizer::reportSizerOutput(state,
    3949            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3950              :                                                          this->Name,
    3951              :                                                          "Initial Free Convection Regime Air Flow Rate [m3/s]",
    3952              :                                                          this->FreeConvAirFlowRate);
    3953              :                         }
    3954              :                     }
    3955              :                 }
    3956              :                 // now calculate UA values from nominal capacities and flow rates
    3957            0 :                 if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    3958            0 :                     rho = this->plantLoc.loop->glycol->getDensity(state, Constant::InitConvTemp, RoutineName);
    3959            0 :                     Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, DesTowerExitWaterTemp, RoutineName);
    3960              :                     // full speed fan tower UA
    3961            0 :                     Real64 const solveLoad = tmpNomTowerCap * this->HeatRejectCapNomCapSizingRatio;
    3962            0 :                     Real64 const solveWaterFlow = rho * tmpDesignWaterFlowRate; // design water mass flow rate
    3963            0 :                     UA0 = 0.0001 * solveLoad;                                   // Assume deltaT = 10000K (limit)
    3964            0 :                     UA1 = solveLoad;                                            // Assume deltaT = 1K
    3965            0 :                     this->WaterTemp = DesTowerInletWaterTemp;
    3966            0 :                     this->AirTemp = this->DesInletAirDBTemp; // 35.0;
    3967            0 :                     this->AirWetBulb = this->DesignInletWB;  // 25.6;
    3968            0 :                     this->AirPress = state.dataEnvrn->StdBaroPress;
    3969            0 :                     this->AirHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, this->AirTemp, this->AirWetBulb, this->AirPress);
    3970            0 :                     auto f = [&state, this, solveLoad, solveWaterFlow, tmpDesignAirFlowRate, Cp](Real64 UA) {
    3971            0 :                         Real64 const OutWaterTemp = this->calculateSimpleTowerOutletTemp(state, solveWaterFlow, tmpDesignAirFlowRate, UA);
    3972            0 :                         Real64 const CoolingOutput = Cp * solveWaterFlow * (this->WaterTemp - OutWaterTemp); // tower cooling output [W]
    3973            0 :                         return (solveLoad - CoolingOutput) / solveLoad;
    3974            0 :                     };
    3975            0 :                     General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f, UA0, UA1);
    3976            0 :                     if (SolFla == -1) {
    3977            0 :                         ShowSevereError(state, "Iteration limit exceeded in calculating tower UA");
    3978            0 :                         ShowFatalError(state, format("calculating cooling tower UA failed for tower {}", this->Name));
    3979            0 :                     } else if (SolFla == -2) {
    3980            0 :                         ShowSevereError(state, "Bad starting values for UA");
    3981            0 :                         ShowFatalError(state, format("Autosizing of cooling tower UA failed for tower {}", this->Name));
    3982              :                     }
    3983            0 :                     this->HighSpeedTowerUA = UA;
    3984            0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    3985            0 :                         BaseSizer::reportSizerOutput(state,
    3986            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3987              :                                                      this->Name,
    3988              :                                                      "U-Factor Times Area Value at Full Speed Air Flow Rate [W/C]",
    3989              :                                                      this->HighSpeedTowerUA);
    3990              :                     }
    3991            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    3992            0 :                         BaseSizer::reportSizerOutput(state,
    3993            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    3994              :                                                      this->Name,
    3995              :                                                      "Initial U-Factor Times Area Value at Full Speed Air Flow Rate [W/C]",
    3996              :                                                      this->HighSpeedTowerUA);
    3997              :                     }
    3998              :                     // free convection tower UA
    3999            0 :                     Real64 const solveLoad2 = tmpTowerFreeConvNomCap * this->HeatRejectCapNomCapSizingRatio;
    4000            0 :                     Real64 const solveWaterFlow2 = rho * tmpDesignWaterFlowRate; // design water mass flow rate
    4001            0 :                     UA0 = 0.0001 * solveLoad2;                                   // Assume deltaT = 10000K (limit)
    4002            0 :                     UA1 = solveLoad2;                                            // Assume deltaT = 1K
    4003            0 :                     this->WaterTemp = DesTowerInletWaterTemp;
    4004            0 :                     this->AirTemp = DesTowerInletAirDBTemp;    // 35.0;
    4005            0 :                     this->AirWetBulb = DesTowerInletAirWBTemp; // 25.6;
    4006            0 :                     this->AirPress = state.dataEnvrn->StdBaroPress;
    4007            0 :                     this->AirHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, this->AirTemp, this->AirWetBulb, this->AirPress);
    4008            0 :                     auto f3 = [&state, this, solveLoad2, solveWaterFlow2, tmpFreeConvAirFlowRate, Cp](Real64 UA) {
    4009            0 :                         Real64 const OutWaterTemp = this->calculateSimpleTowerOutletTemp(state, solveWaterFlow2, tmpFreeConvAirFlowRate, UA);
    4010            0 :                         Real64 const CoolingOutput = Cp * solveWaterFlow2 * (this->WaterTemp - OutWaterTemp); // tower cooling output [W]
    4011            0 :                         return (solveLoad2 - CoolingOutput) / solveLoad2;
    4012            0 :                     };
    4013            0 :                     General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f3, UA0, UA1);
    4014            0 :                     if (SolFla == -1) {
    4015            0 :                         ShowSevereError(state, "Iteration limit exceeded in calculating tower free convection UA");
    4016            0 :                         ShowFatalError(state, format("calculating cooling tower UA failed for tower {}", this->Name));
    4017            0 :                     } else if (SolFla == -2) {
    4018            0 :                         ShowSevereError(state, "Bad starting values for UA");
    4019            0 :                         ShowFatalError(state, format("Autosizing of cooling tower UA failed for free convection tower {}", this->Name));
    4020              :                     }
    4021            0 :                     this->LowSpeedTowerUA = UA;
    4022            0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    4023            0 :                         BaseSizer::reportSizerOutput(state,
    4024            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4025              :                                                      this->Name,
    4026              :                                                      "U-Factor Times Area Value at Free Convection Air Flow Rate [W/C]",
    4027              :                                                      this->FreeConvTowerUA);
    4028              :                     }
    4029            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    4030            0 :                         BaseSizer::reportSizerOutput(state,
    4031            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4032              :                                                      this->Name,
    4033              :                                                      "Initial U-Factor Times Area Value at Free Convection Air Flow Rate [W/C]",
    4034              :                                                      this->FreeConvTowerUA);
    4035              :                     }
    4036              :                 }
    4037              : 
    4038              :             } else { // full speed UA given
    4039              : 
    4040            0 :                 if (this->FreeConvTowerUAWasAutoSized) { // determine from scalable sizing factor
    4041            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    4042            0 :                         this->FreeConvTowerUA = this->HighSpeedTowerUA * this->FreeConvTowerUASizingFactor;
    4043            0 :                         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    4044            0 :                             BaseSizer::reportSizerOutput(state,
    4045            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4046              :                                                          this->Name,
    4047              :                                                          "U-Factor Times Area Value at Free Convection Air Flow Rate [W/C]",
    4048              :                                                          this->FreeConvTowerUA);
    4049              :                         }
    4050            0 :                         if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    4051            0 :                             BaseSizer::reportSizerOutput(state,
    4052            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4053              :                                                          this->Name,
    4054              :                                                          "Initial U-Factor Times Area Value at Free Convection Air Flow Rate [W/C]",
    4055              :                                                          this->FreeConvTowerUA);
    4056              :                         }
    4057              :                     }
    4058              :                 }
    4059              :                 Real64 OutWaterTemp;
    4060            0 :                 if (this->HighSpeedAirFlowRateWasAutoSized) { // given UA but not air flow rate
    4061              :                     // need an air flow rate to find capacity from UA but flow rate is scaled off capacity
    4062              :                     // get nominal capacity from PlantSizData(PltSizCondNum)%DeltaT and PlantSizData(PltSizCondNum)%DesVolFlowRate
    4063            0 :                     if (PltSizCondNum > 0) {
    4064            0 :                         if (PlantSizData(PltSizCondNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
    4065            0 :                             rho = this->plantLoc.loop->glycol->getDensity(state, DesTowerExitWaterTemp, RoutineName);
    4066            0 :                             Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, DesTowerExitWaterTemp, RoutineName);
    4067            0 :                             DesTowerLoad = rho * Cp * PlantSizData(PltSizCondNum).DesVolFlowRate * DesTowerWaterDeltaT;
    4068            0 :                             tmpNomTowerCap = DesTowerLoad / this->HeatRejectCapNomCapSizingRatio;
    4069            0 :                             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    4070            0 :                                 this->TowerNominalCapacity = tmpNomTowerCap;
    4071            0 :                                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    4072            0 :                                     BaseSizer::reportSizerOutput(state,
    4073            0 :                                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4074              :                                                                  this->Name,
    4075              :                                                                  "Nominal Capacity [W]",
    4076              :                                                                  this->TowerNominalCapacity);
    4077              :                                 }
    4078            0 :                                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    4079            0 :                                     BaseSizer::reportSizerOutput(state,
    4080            0 :                                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4081              :                                                                  this->Name,
    4082              :                                                                  "Initial Nominal Capacity [W]",
    4083              :                                                                  this->TowerNominalCapacity);
    4084              :                                 }
    4085              :                             }
    4086              :                         } else {
    4087            0 :                             tmpNomTowerCap = rho = Cp = 0.0; // rho and Cp added: Used below
    4088            0 :                             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    4089            0 :                                 this->TowerNominalCapacity = tmpNomTowerCap;
    4090            0 :                                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    4091            0 :                                     BaseSizer::reportSizerOutput(state,
    4092            0 :                                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4093              :                                                                  this->Name,
    4094              :                                                                  "Nominal Capacity [W]",
    4095              :                                                                  this->TowerNominalCapacity);
    4096              :                                 }
    4097            0 :                                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    4098            0 :                                     BaseSizer::reportSizerOutput(state,
    4099            0 :                                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4100              :                                                                  this->Name,
    4101              :                                                                  "Initial Nominal Capacity [W]",
    4102              :                                                                  this->TowerNominalCapacity);
    4103              :                                 }
    4104              :                             }
    4105              :                         }
    4106              : 
    4107              :                     } else {
    4108            0 :                         tmpNomTowerCap = 0.0; // Suppress uninitialized warnings
    4109            0 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    4110            0 :                             ShowSevereError(state, format("Autosizing error for cooling tower object = {}", this->Name));
    4111            0 :                             ShowFatalError(state, "Autosizing of cooling tower nominal capacity requires a loop Sizing:Plant object.");
    4112              :                         }
    4113              :                     }
    4114              : 
    4115            0 :                     if (this->DefaultedDesignAirFlowScalingFactor) {
    4116            0 :                         tmpDesignAirFlowRate = tmpNomTowerCap * this->DesignAirFlowPerUnitNomCap * (101325.0 / state.dataEnvrn->StdBaroPress);
    4117              :                     } else {
    4118            0 :                         tmpDesignAirFlowRate = tmpNomTowerCap * this->DesignAirFlowPerUnitNomCap;
    4119              :                     }
    4120            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    4121            0 :                         this->HighSpeedAirFlowRate = tmpDesignAirFlowRate;
    4122            0 :                         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    4123            0 :                             BaseSizer::reportSizerOutput(state,
    4124            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4125              :                                                          this->Name,
    4126              :                                                          "Design Air Flow Rate [m3/s]",
    4127              :                                                          this->HighSpeedAirFlowRate);
    4128              :                         }
    4129            0 :                         if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    4130            0 :                             BaseSizer::reportSizerOutput(state,
    4131            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4132              :                                                          this->Name,
    4133              :                                                          "Initial Design Air Flow Rate [m3/s]",
    4134              :                                                          this->HighSpeedAirFlowRate);
    4135              :                         }
    4136              :                     }
    4137              : 
    4138              :                 } else { // UA and Air flow rate given, so find Nominal Cap from running model
    4139              : 
    4140            0 :                     rho = this->plantLoc.loop->glycol->getDensity(state, DesTowerExitWaterTemp, RoutineName);
    4141            0 :                     Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, DesTowerExitWaterTemp, RoutineName);
    4142              : 
    4143            0 :                     this->WaterTemp = DesTowerInletWaterTemp;
    4144            0 :                     this->AirTemp = DesTowerInletAirDBTemp;    // 35.0;
    4145            0 :                     this->AirWetBulb = DesTowerInletAirWBTemp; // 25.6;
    4146            0 :                     this->AirPress = state.dataEnvrn->StdBaroPress;
    4147            0 :                     this->AirHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, this->AirTemp, this->AirWetBulb, this->AirPress);
    4148              :                     OutWaterTemp =
    4149            0 :                         this->calculateSimpleTowerOutletTemp(state, rho * tmpDesignWaterFlowRate, this->HighSpeedAirFlowRate, this->HighSpeedTowerUA);
    4150            0 :                     tmpNomTowerCap = Cp * rho * tmpDesignWaterFlowRate * (this->WaterTemp - OutWaterTemp);
    4151            0 :                     tmpNomTowerCap /= this->HeatRejectCapNomCapSizingRatio;
    4152            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    4153            0 :                         this->TowerNominalCapacity = tmpNomTowerCap;
    4154            0 :                         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    4155            0 :                             BaseSizer::reportSizerOutput(state,
    4156            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4157              :                                                          this->Name,
    4158              :                                                          "Nominal Capacity [W]",
    4159              :                                                          this->TowerNominalCapacity);
    4160              :                         }
    4161            0 :                         if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    4162            0 :                             BaseSizer::reportSizerOutput(state,
    4163            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4164              :                                                          this->Name,
    4165              :                                                          "Initial Nominal Capacity [W]",
    4166              :                                                          this->TowerNominalCapacity);
    4167              :                         }
    4168              :                     }
    4169              : 
    4170              :                 } // both UA and air flow rate given
    4171              : 
    4172            0 :                 if (this->FreeConvAirFlowRateWasAutoSized) {
    4173            0 :                     tmpFreeConvAirFlowRate = tmpDesignAirFlowRate * this->FreeConvAirFlowRateSizingFactor;
    4174            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    4175            0 :                         this->FreeConvAirFlowRate = tmpFreeConvAirFlowRate;
    4176            0 :                         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    4177            0 :                             BaseSizer::reportSizerOutput(state,
    4178            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4179              :                                                          this->Name,
    4180              :                                                          "Free Convection Regime Air Flow Rate [m3/s]",
    4181              :                                                          this->FreeConvAirFlowRate);
    4182              :                         }
    4183            0 :                         if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    4184            0 :                             BaseSizer::reportSizerOutput(state,
    4185            0 :                                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4186              :                                                          this->Name,
    4187              :                                                          "Initial Free Convection Regime Air Flow Rate [m3/s]",
    4188              :                                                          this->FreeConvAirFlowRate);
    4189              :                         }
    4190              :                     }
    4191              :                 }
    4192              : 
    4193              :                 OutWaterTemp =
    4194            0 :                     this->calculateSimpleTowerOutletTemp(state, rho * tmpDesignWaterFlowRate, tmpFreeConvAirFlowRate, this->FreeConvTowerUA);
    4195            0 :                 tmpTowerFreeConvNomCap = Cp * rho * tmpDesignWaterFlowRate * (this->WaterTemp - OutWaterTemp);
    4196            0 :                 tmpTowerFreeConvNomCap /= this->HeatRejectCapNomCapSizingRatio;
    4197            0 :                 if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    4198            0 :                     this->TowerFreeConvNomCap = tmpTowerFreeConvNomCap;
    4199            0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    4200            0 :                         BaseSizer::reportSizerOutput(state,
    4201            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4202              :                                                      this->Name,
    4203              :                                                      "Free Convection Nominal Capacity [W]",
    4204              :                                                      this->TowerFreeConvNomCap);
    4205              :                     }
    4206            0 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    4207            0 :                         BaseSizer::reportSizerOutput(state,
    4208            0 :                                                      DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4209              :                                                      this->Name,
    4210              :                                                      "Initial Free Convection Nominal Capacity [W]",
    4211              :                                                      this->TowerFreeConvNomCap);
    4212              :                     }
    4213              :                 }
    4214              :             }
    4215              :         }
    4216              : 
    4217           13 :         tmpHighSpeedFanPower = tmpNomTowerCap * this->DesignFanPowerPerUnitNomCap;
    4218           13 :         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    4219            5 :             if (this->HighSpeedFanPowerWasAutoSized) {
    4220              : 
    4221            4 :                 this->HighSpeedFanPower = tmpHighSpeedFanPower;
    4222            4 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    4223            8 :                     BaseSizer::reportSizerOutput(state,
    4224            4 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4225              :                                                  this->Name,
    4226              :                                                  "Design Fan Power [W]",
    4227              :                                                  this->HighSpeedFanPower);
    4228              :                 }
    4229            4 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    4230            0 :                     BaseSizer::reportSizerOutput(state,
    4231            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4232              :                                                  this->Name,
    4233              :                                                  "Initial Design Fan Power [W]",
    4234              :                                                  this->HighSpeedFanPower);
    4235              :                 }
    4236              :             } else { // Hard-sized with sizing data
    4237            1 :                 Real64 HighSpeedFanPowerUser(0.0);
    4238            1 :                 HighSpeedFanPowerUser = this->HighSpeedAirFlowRate;
    4239            1 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    4240            2 :                     BaseSizer::reportSizerOutput(state,
    4241            1 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    4242              :                                                  this->Name,
    4243              :                                                  "Design Fan Power [W]",
    4244              :                                                  tmpHighSpeedFanPower,
    4245              :                                                  "User-Specified Design Fan Power [W]",
    4246              :                                                  HighSpeedFanPowerUser);
    4247            1 :                     if (state.dataGlobal->DisplayExtraWarnings) {
    4248            0 :                         if ((std::abs(tmpHighSpeedFanPower - HighSpeedFanPowerUser) / HighSpeedFanPowerUser) >
    4249            0 :                             state.dataSize->AutoVsHardSizingThreshold) {
    4250            0 :                             ShowMessage(state, format("SizeVSMerkelTower: Potential issue with equipment sizing for {}", this->Name));
    4251            0 :                             ShowContinueError(state, format("User-Specified Design Fan Power of {:.2R} [W]", HighSpeedFanPowerUser));
    4252            0 :                             ShowContinueError(state, format("differs from Design Fan Power of {:.2R} [W]", tmpHighSpeedFanPower));
    4253            0 :                             ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    4254            0 :                             ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    4255              :                         }
    4256              :                     }
    4257              :                 }
    4258              :             }
    4259              :         }
    4260              : 
    4261           13 :         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    4262              :             // create predefined report
    4263           10 :             OutputReportPredefined::PreDefTableEntry(
    4264           10 :                 state, state.dataOutRptPredefined->pdchMechType, this->Name, DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)]);
    4265            5 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomCap, this->Name, this->TowerNominalCapacity);
    4266              : 
    4267              :             // create std 229 new table for cooling towers and fluid coolers
    4268           10 :             OutputReportPredefined::PreDefTableEntry(
    4269           10 :                 state, state.dataOutRptPredefined->pdchCTFCType, this->Name, DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)]);
    4270           10 :             OutputReportPredefined::PreDefTableEntry(state,
    4271            5 :                                                      state.dataOutRptPredefined->pdchCTFCCondLoopName,
    4272              :                                                      this->Name,
    4273           10 :                                                      (this->plantLoc.loop != nullptr) ? this->plantLoc.loop->Name : "N/A");
    4274           10 :             OutputReportPredefined::PreDefTableEntry(state,
    4275            5 :                                                      state.dataOutRptPredefined->pdchCTFCCondLoopBranchName,
    4276              :                                                      this->Name,
    4277           10 :                                                      (this->plantLoc.branch != nullptr) ? plantLoc.branch->Name : "N/A");
    4278           10 :             OutputReportPredefined::PreDefTableEntry(state,
    4279            5 :                                                      state.dataOutRptPredefined->pdchCTFCFluidType,
    4280              :                                                      this->Name,
    4281            5 :                                                      this->plantLoc.loop->glycol->Name); // Fluid Name more reasonable than FluidType
    4282            5 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCTFCRange, this->Name, this->DesignRange);
    4283            5 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCTFCApproach, this->Name, this->DesignApproach);
    4284           10 :             OutputReportPredefined::PreDefTableEntry(
    4285            5 :                 state, state.dataOutRptPredefined->pdchCTFCDesFanPwr, this->Name, this->HighSpeedFanPower); // equivalent to Design Fan Power?
    4286            5 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCTFCDesInletAirWBT, this->Name, this->DesignInletWB);
    4287           10 :             OutputReportPredefined::PreDefTableEntry(
    4288           10 :                 state, state.dataOutRptPredefined->pdchCTFCDesWaterFlowRate, this->Name, this->DesignWaterFlowRate, 6);
    4289            5 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCTFCLevWaterSPTemp, this->Name, this->DesOutletWaterTemp);
    4290              :         }
    4291           13 :     } // namespace CondenserLoopTowers
    4292              : 
    4293        13985 :     void CoolingTower::calculateSingleSpeedTower(EnergyPlusData &state, Real64 &MyLoad, bool RunFlag)
    4294              :     {
    4295              : 
    4296              :         // SUBROUTINE INFORMATION:
    4297              :         //       AUTHOR         Dan Fisher
    4298              :         //       DATE WRITTEN   Sept. 1998
    4299              :         //       MODIFIED       Aug. 2008, T Hong, Added fluid bypass for single speed cooling tower
    4300              :         //                      The OutletWaterTemp from calculateSimpleTowerOutletTemp can be lower than 0 degreeC
    4301              :         //                      which may not be allowed in practice if water is the tower fluid.
    4302              :         //                      Chandan Sharma, FSEC, February 2010, Added basin heater
    4303              :         //                      Jul. 2010, A Flament, added multi-cell capability for the 3 types of cooling tower
    4304              :         //                      Jun. 2016, R Zhang, Applied the condenser supply water temperature sensor fault model
    4305              :         //                      Jul. 2016, R Zhang, Applied the cooling tower fouling fault model
    4306              :         //       RE-ENGINEERED  Jan. 2001, Richard Raustad
    4307              : 
    4308              :         // PURPOSE OF THIS SUBROUTINE:
    4309              :         // To simulate the operation of a single-speed fan cooling tower.
    4310              : 
    4311              :         // METHODOLOGY EMPLOYED:
    4312              :         // The cooling tower is modeled using effectiveness-NTU relationships for
    4313              :         // counterflow heat exchangers based on Merkel's theory.
    4314              :         // The subroutine calculates the period of time required to meet a
    4315              :         // leaving water temperature setpoint. It assumes that part-load
    4316              :         // operation represents a linear interpolation of two steady-state regimes.
    4317              :         // Cyclic losses are neglected. The period of time required to meet the
    4318              :         // leaving water temperature setpoint is used to determine the required
    4319              :         // fan power and energy. Free convection regime is also modeled. This
    4320              :         // occurs when the pump is operating and the fan is off. If free convection
    4321              :         // regime cooling is all that is required for a given time step, the leaving
    4322              :         // water temperature is allowed to fall below the leaving water temperature
    4323              :         // setpoint (free cooling). At times when the cooling tower fan is required,
    4324              :         // the leaving water temperature is at or above the setpoint.
    4325              :         // A RunFlag is passed by the upper level manager to indicate the ON/OFF status,
    4326              :         // or schedule, of the cooling tower. If the tower is OFF, outlet water
    4327              :         // temperature and flow rate are passed through the model from inlet node to
    4328              :         // outlet node without intervention (with the exception of free convection
    4329              :         // where water temperature is allowed to float below the outlet water set
    4330              :         // point). Reports are also updated with fan power and energy being zero.
    4331              :         // When the RunFlag indicates an ON condition for the cooling tower, the
    4332              :         // mass flow rate and water temperature are read from the inlet node of the
    4333              :         // cooling tower (water-side). The outdoor air wet-bulb temperature is used
    4334              :         // as the entering condition to the cooling tower (air-side). Input deck
    4335              :         // parameters are read for the free convection regime (pump ON and fan OFF)
    4336              :         // and a leaving water temperature is calculated. If the leaving water temperature
    4337              :         // is at or below the setpoint, the calculated leaving water temperature is
    4338              :         // placed on the outlet node and no fan power is used. If the calculated leaving
    4339              :         // water temperature is above the setpoint, the cooling tower fan is turned on
    4340              :         // and design parameters are used to again calculate the leaving water temperature.
    4341              :         // If the calculated leaving water temperature is below the setpoint, a fan
    4342              :         // run-time fraction is calculated and used to determine fan power. The leaving
    4343              :         // water temperature setpoint is placed on the outlet node. If the calculated
    4344              :         // leaving water temperature is at or above the setpoint, the calculated
    4345              :         // leaving water temperature is placed on the outlet node and the fan runs at
    4346              :         // full power. Water mass flow rate is passed from inlet node to outlet node
    4347              :         // with no intervention.
    4348              :         // If a tower has multiple cells, the specified inputs of or the autosized capacity
    4349              :         //  and air/water flow rates are for the entire tower. The number of cells to operate
    4350              :         //  is first determined based on the user entered minimal and maximal water flow fractions
    4351              :         //  per cell. If the loads are not met, more cells (if available) will operate to meet
    4352              :         //  the loads. Inside each cell, the capacity controls still apply. Each cell operates
    4353              :         //  in the same way.
    4354              : 
    4355              :         // REFERENCES:
    4356              :         // ASHRAE HVAC1KIT: A Toolkit for Primary HVAC System Energy Calculation. 1999.
    4357              : 
    4358              :         // SUBROUTINE PARAMETER DEFINITIONS:
    4359              :         static constexpr std::string_view RoutineName("calculateSingleSpeedTower");
    4360        13985 :         int constexpr MaxIteration(100); // Maximum fluid bypass iteration calculations
    4361              :         static constexpr std::string_view MaxItChar("100");
    4362        13985 :         Real64 constexpr BypassFractionThreshold(0.01); // Threshold to stop bypass iteration
    4363        13985 :         Real64 constexpr OWTLowerLimit(0.0);            // The limit of tower exit fluid temperature used in the fluid bypass
    4364              :         //  calculation to avoid fluid freezing. For water, it is 0 degreeC,
    4365              :         //  for glycols, it can be much lower. The fluid type is stored at the loop.
    4366              :         //  Current choices are Water and Steam, needs to expand for glycols
    4367              : 
    4368              :         // set inlet and outlet nodes
    4369        13985 :         this->Qactual = 0.0;
    4370        13985 :         this->FanPower = 0.0;
    4371        13985 :         this->OutletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp;
    4372              : 
    4373        13985 :         Real64 freeConvTowerUA = this->FreeConvTowerUA;
    4374        13985 :         Real64 highSpeedTowerUA = this->HighSpeedTowerUA;
    4375              : 
    4376              :         // water temperature setpoint
    4377        13985 :         Real64 TempSetPoint = 0.0;
    4378        13985 :         switch (this->plantLoc.loop->LoopDemandCalcScheme) {
    4379        13985 :         case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
    4380        13985 :             if (this->SetpointIsOnOutlet) {
    4381            0 :                 TempSetPoint = state.dataLoopNodes->Node(this->WaterOutletNodeNum).TempSetPoint;
    4382              :             } else {
    4383        13985 :                 TempSetPoint = this->plantLoc.side->TempSetPoint;
    4384              :             }
    4385        13985 :         } break;
    4386            0 :         case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
    4387            0 :             if (this->SetpointIsOnOutlet) {
    4388            0 :                 TempSetPoint = state.dataLoopNodes->Node(this->WaterOutletNodeNum).TempSetPointHi;
    4389              :             } else {
    4390            0 :                 TempSetPoint = this->plantLoc.side->TempSetPointHi;
    4391              :             }
    4392            0 :         } break;
    4393            0 :         default:
    4394            0 :             break;
    4395              :         }
    4396              : 
    4397              :         // If there is a fault of condenser SWT Sensor
    4398        13985 :         if (this->FaultyCondenserSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    4399            0 :             (!state.dataGlobal->KickOffSimulation)) {
    4400            0 :             int FaultIndex = this->FaultyCondenserSWTIndex;
    4401            0 :             Real64 TowerOutletTemp_ff = TempSetPoint;
    4402              : 
    4403              :             // calculate the sensor offset using fault information
    4404            0 :             this->FaultyCondenserSWTOffset = state.dataFaultsMgr->FaultsCondenserSWTSensor(FaultIndex).CalFaultOffsetAct(state);
    4405              :             // update the TempSetPoint
    4406            0 :             TempSetPoint = TowerOutletTemp_ff - this->FaultyCondenserSWTOffset;
    4407              :         }
    4408              : 
    4409              :         // If there is a fault of cooling tower fouling
    4410        13985 :         if (this->FaultyTowerFoulingFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    4411            0 :             (!state.dataGlobal->KickOffSimulation)) {
    4412            0 :             int FaultIndex = this->FaultyTowerFoulingIndex;
    4413            0 :             Real64 FreeConvTowerUA_ff = this->FreeConvTowerUA;
    4414            0 :             Real64 HighSpeedTowerUA_ff = this->HighSpeedTowerUA;
    4415              : 
    4416              :             // calculate the Faulty Tower Fouling Factor using fault information
    4417            0 :             this->FaultyTowerFoulingFactor = state.dataFaultsMgr->FaultsTowerFouling(FaultIndex).CalFaultyTowerFoulingFactor(state);
    4418              : 
    4419              :             // update the tower UA values at faulty cases
    4420            0 :             freeConvTowerUA = FreeConvTowerUA_ff * this->FaultyTowerFoulingFactor;
    4421            0 :             highSpeedTowerUA = HighSpeedTowerUA_ff * this->FaultyTowerFoulingFactor;
    4422              :         }
    4423              : 
    4424              :         // Added for fluid bypass. First assume no fluid bypass
    4425        13985 :         int BypassFlag = 0; // Flag indicator for fluid bypass (0 - no bypass, 1 - bypass)
    4426        13985 :         Real64 BypassFraction2 = 0.0;
    4427        13985 :         this->BypassFraction = 0.0;
    4428              : 
    4429              :         // Added for multi-cell. Determine the number of cells operating
    4430        13985 :         int NumCellMin(0);
    4431        13985 :         int NumCellMax(0);
    4432        13985 :         Real64 WaterMassFlowRatePerCellMin = 0.0;
    4433        13985 :         if (this->DesWaterMassFlowRate > 0.0) {
    4434        13972 :             WaterMassFlowRatePerCellMin = this->DesWaterMassFlowRate * this->MinFracFlowRate / this->NumCell;
    4435        13972 :             Real64 WaterMassFlowRatePerCellMax = this->DesWaterMassFlowRate * this->MaxFracFlowRate / this->NumCell;
    4436              : 
    4437              :             // round it up to the nearest integer
    4438        13972 :             NumCellMin = min(int((this->WaterMassFlowRate / WaterMassFlowRatePerCellMax) + 0.9999), this->NumCell);
    4439        13972 :             NumCellMax = min(int((this->WaterMassFlowRate / WaterMassFlowRatePerCellMin) + 0.9999), this->NumCell);
    4440              :         }
    4441              :         // cap min at 1
    4442        13985 :         if (NumCellMin <= 0) NumCellMin = 1;
    4443        13985 :         if (NumCellMax <= 0) NumCellMax = 1;
    4444        13985 :         if (this->cellCtrl == CellCtrl::MinCell) {
    4445            1 :             this->NumCellOn = NumCellMin;
    4446              :         } else {
    4447        13984 :             this->NumCellOn = NumCellMax;
    4448              :         }
    4449        13985 :         Real64 WaterMassFlowRatePerCell = this->WaterMassFlowRate / this->NumCellOn;
    4450              : 
    4451              :         // Do not RETURN here if flow rate is less than SmallMassFlow. Check basin heater and then RETURN.
    4452              : 
    4453        13985 :         bool returnFlagSet = false;
    4454        13985 :         this->checkMassFlowAndLoad(state, MyLoad, RunFlag, returnFlagSet);
    4455        13985 :         if (returnFlagSet) return;
    4456              : 
    4457         8464 :         bool IncrNumCellFlag = true; // determine if yes or no we increase the number of cells // set value to true to enter in the loop
    4458              : 
    4459         8464 :         Real64 UAdesign = 0.0; // UA value at design conditions (entered by user or calculated)
    4460              :         Real64 OutletWaterTempOFF;
    4461         8464 :         Real64 FanModeFrac = 0.0;
    4462         8464 :         Real64 AirFlowRate = 0.0;
    4463        16928 :         while (IncrNumCellFlag) {
    4464         8464 :             IncrNumCellFlag = false;
    4465              : 
    4466              :             //   Initialize local variables to the free convection design values
    4467         8464 :             UAdesign = freeConvTowerUA / this->NumCell;
    4468         8464 :             AirFlowRate = this->FreeConvAirFlowRate / this->NumCell;
    4469         8464 :             OutletWaterTempOFF = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp;
    4470         8464 :             this->OutletWaterTemp = OutletWaterTempOFF;
    4471         8464 :             FanModeFrac = 0.0;
    4472              : 
    4473         8464 :             OutletWaterTempOFF = this->calculateSimpleTowerOutletTemp(state, WaterMassFlowRatePerCell, AirFlowRate, UAdesign);
    4474              : 
    4475              :             //   Assume Setpoint was met using free convection regime (pump ON and fan OFF)
    4476         8464 :             this->FanPower = 0.0;
    4477         8464 :             this->OutletWaterTemp = OutletWaterTempOFF;
    4478              : 
    4479         8464 :             if (OutletWaterTempOFF > TempSetPoint) {
    4480              :                 //     Setpoint was not met (or free conv. not used), turn on cooling tower fan
    4481         8424 :                 UAdesign = highSpeedTowerUA / this->NumCell;
    4482         8424 :                 AirFlowRate = this->HighSpeedAirFlowRate / this->NumCell;
    4483              : 
    4484              :                 // The fan power is for all cells operating
    4485         8424 :                 Real64 const FanPowerOn = this->HighSpeedFanPower * this->NumCellOn / this->NumCell;
    4486              : 
    4487         8424 :                 this->OutletWaterTemp = this->calculateSimpleTowerOutletTemp(state, WaterMassFlowRatePerCell, AirFlowRate, UAdesign);
    4488              : 
    4489         8424 :                 if (this->OutletWaterTemp <= TempSetPoint) {
    4490          168 :                     if (this->CapacityControl == CapacityCtrl::FanCycling || this->OutletWaterTemp <= OWTLowerLimit) {
    4491              :                         //           Setpoint was met with pump ON and fan ON, calculate run-time fraction
    4492          164 :                         FanModeFrac = (TempSetPoint - OutletWaterTempOFF) / (this->OutletWaterTemp - OutletWaterTempOFF);
    4493          164 :                         this->FanPower = FanModeFrac * FanPowerOn;
    4494          164 :                         this->OutletWaterTemp = TempSetPoint;
    4495              :                     } else {
    4496              :                         // FluidBypass, fan runs at full speed for the entire time step
    4497            4 :                         FanModeFrac = 1.0;
    4498            4 :                         this->FanPower = FanPowerOn;
    4499            4 :                         BypassFlag = 1;
    4500              :                     }
    4501              :                 } else {
    4502              :                     //         Setpoint was not met, cooling tower ran at full capacity
    4503         8256 :                     FanModeFrac = 1.0;
    4504         8256 :                     this->FanPower = FanPowerOn;
    4505              :                     // if possible increase the number of cells and do the calculations again with the new water mass flow rate per cell
    4506         8256 :                     if (this->NumCellOn < this->NumCell && (this->WaterMassFlowRate / (this->NumCellOn + 1)) >= WaterMassFlowRatePerCellMin) {
    4507            0 :                         ++this->NumCellOn;
    4508            0 :                         WaterMassFlowRatePerCell = this->WaterMassFlowRate / this->NumCellOn;
    4509            0 :                         IncrNumCellFlag = true;
    4510              :                     }
    4511              :                 }
    4512           40 :             } else if (OutletWaterTempOFF < TempSetPoint) {
    4513              :                 // Need to bypass in free convection cooling mode if bypass is allowed
    4514           40 :                 if (this->CapacityControl == CapacityCtrl::FluidBypass) {
    4515           40 :                     if (OutletWaterTempOFF > OWTLowerLimit) {
    4516           40 :                         BypassFlag = 1;
    4517              :                     }
    4518              :                 }
    4519              :             }
    4520              :         }
    4521              : 
    4522              :         // Calculate bypass fraction since OWTLowerLimit < OutletWaterTemp < TempSetPoint.
    4523              :         // The iteration ends when the number of iterations exceeds the limit or the difference
    4524              :         //  between the new and old bypass fractions is less than the threshold.
    4525         8464 :         if (BypassFlag == 1) {
    4526              :             // Inlet water temperature lower than setpoint, assume 100% bypass, tower fan off
    4527           44 :             if (this->InletWaterTemp <= TempSetPoint) {
    4528            0 :                 this->FanPower = 0.0;
    4529            0 :                 this->BypassFraction = 1.0;
    4530            0 :                 this->OutletWaterTemp = this->InletWaterTemp;
    4531              :             } else {
    4532           44 :                 if (std::abs(this->InletWaterTemp - this->OutletWaterTemp) <= 0.01) {
    4533              :                     // Outlet temp is close enough to inlet temp, assume 100% bypass, tower fan off
    4534            0 :                     this->BypassFraction = 1.0;
    4535            0 :                     this->FanPower = 0.0;
    4536              :                 } else {
    4537           44 :                     Real64 bypassFraction = (TempSetPoint - this->OutletWaterTemp) / (this->InletWaterTemp - this->OutletWaterTemp);
    4538           44 :                     if (bypassFraction > 1.0 || bypassFraction < 0.0) {
    4539              :                         // Bypass cannot meet setpoint, assume no bypass
    4540            0 :                         this->BypassFraction = 0.0;
    4541              :                     } else {
    4542           44 :                         int NumIteration = 0;
    4543           44 :                         Real64 BypassFractionPrev = bypassFraction;
    4544           44 :                         Real64 OutletWaterTempPrev = this->OutletWaterTemp;
    4545           80 :                         while (NumIteration < MaxIteration) {
    4546           80 :                             ++NumIteration;
    4547              :                             // need to iterate for the new OutletWaterTemp while bypassing tower water
    4548           80 :                             this->OutletWaterTemp =
    4549           80 :                                 this->calculateSimpleTowerOutletTemp(state, WaterMassFlowRatePerCell * (1.0 - bypassFraction), AirFlowRate, UAdesign);
    4550              :                             // Calc new BypassFraction based on the new OutletWaterTemp
    4551           80 :                             if (std::abs(this->OutletWaterTemp - OWTLowerLimit) <= 0.01) {
    4552            0 :                                 BypassFraction2 = bypassFraction;
    4553            0 :                                 break;
    4554           80 :                             } else if (this->OutletWaterTemp < OWTLowerLimit) {
    4555              :                                 // Set OutletWaterTemp = OWTLowerLimit, and use linear interpolation to calculate the bypassFraction
    4556            0 :                                 BypassFraction2 = BypassFractionPrev - (BypassFractionPrev - bypassFraction) * (OutletWaterTempPrev - OWTLowerLimit) /
    4557            0 :                                                                            (OutletWaterTempPrev - this->OutletWaterTemp);
    4558            0 :                                 this->OutletWaterTemp = this->calculateSimpleTowerOutletTemp(
    4559            0 :                                     state, WaterMassFlowRatePerCell * (1.0 - BypassFraction2), AirFlowRate, UAdesign);
    4560            0 :                                 if (this->OutletWaterTemp < OWTLowerLimit) {
    4561              :                                     // Use previous iteration values
    4562            0 :                                     BypassFraction2 = BypassFractionPrev;
    4563            0 :                                     this->OutletWaterTemp = OutletWaterTempPrev;
    4564              :                                 }
    4565            0 :                                 break;
    4566              :                             } else {
    4567           80 :                                 BypassFraction2 = (TempSetPoint - this->OutletWaterTemp) / (this->InletWaterTemp - this->OutletWaterTemp);
    4568              :                             }
    4569              : 
    4570              :                             // Compare two BypassFraction to determine when to stop
    4571           80 :                             if (std::abs(BypassFraction2 - bypassFraction) <= BypassFractionThreshold) break;
    4572           36 :                             BypassFractionPrev = bypassFraction;
    4573           36 :                             OutletWaterTempPrev = this->OutletWaterTemp;
    4574           36 :                             bypassFraction = BypassFraction2;
    4575              :                         }
    4576           44 :                         if (NumIteration > MaxIteration) {
    4577            0 :                             ShowWarningError(
    4578            0 :                                 state, format("Cooling tower fluid bypass iteration exceeds maximum limit of {} for {}", MaxItChar, this->Name));
    4579              :                         }
    4580           44 :                         this->BypassFraction = BypassFraction2;
    4581              :                         // may not meet TempSetPoint due to limit of tower outlet temp to OWTLowerLimit
    4582           44 :                         this->OutletWaterTemp = (1.0 - BypassFraction2) * this->OutletWaterTemp + BypassFraction2 * this->InletWaterTemp;
    4583              :                     }
    4584              :                 }
    4585              :             }
    4586              :         }
    4587              : 
    4588              :         // output the fraction of the time step the fan is ON
    4589         8464 :         this->FanCyclingRatio = FanModeFrac;
    4590              :         // Should this be water inlet node num?????
    4591              :         Real64 const CpWater =
    4592         8464 :             this->plantLoc.loop->glycol->getSpecificHeat(state, state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp, RoutineName);
    4593              : 
    4594         8464 :         this->Qactual = this->WaterMassFlowRate * CpWater * (state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp - this->OutletWaterTemp);
    4595         8464 :         this->airFlowRateRatio = (AirFlowRate * this->NumCell) / this->HighSpeedAirFlowRate;
    4596              :     }
    4597              : 
    4598          106 :     void CoolingTower::calculateTwoSpeedTower(EnergyPlusData &state, Real64 &MyLoad, bool RunFlag)
    4599              :     {
    4600              : 
    4601              :         // SUBROUTINE INFORMATION:
    4602              :         //       AUTHOR         Dan Fisher
    4603              :         //       DATE WRITTEN   Sept. 1998
    4604              :         //       MODIFIED       Feb. 2010, Chandan Sharma, FSEC, Added basin heater
    4605              :         //                      Jul. 2010, A Flament, added multi-cell capability for the 3 types of cooling tower
    4606              :         //                      Jun. 2016, R Zhang, Applied the condenser supply water temperature sensor fault model
    4607              :         //                      Jul. 2016, R Zhang, Applied the cooling tower fouling fault model
    4608              : 
    4609              :         // PURPOSE OF THIS SUBROUTINE:
    4610              :         // To simulate the operation of a cooling tower with a two-speed fan.
    4611              : 
    4612              :         // METHODOLOGY EMPLOYED:
    4613              :         // The cooling tower is modeled using effectiveness-NTU relationships for
    4614              :         // counterflow heat exchangers based on Merkel's theory.
    4615              :         // The subroutine calculates the period of time required to meet a
    4616              :         // leaving water temperature setpoint. It assumes that part-load
    4617              :         // operation represents a linear interpolation of three steady-state regimes
    4618              :         // (high-speed fan operation, low-speed fan operation and free convection regime).
    4619              :         // Cyclic losses are neglected. The period of time required to meet the
    4620              :         // leaving water temperature setpoint is used to determine the required
    4621              :         // fan power and energy. Free convection regime is also modeled. This
    4622              :         // occurs when the pump is operating and the fan is off. If free convection
    4623              :         // regime cooling is all that is required for a given time step, the leaving
    4624              :         // water temperature is allowed to fall below the leaving water temperature
    4625              :         // setpoint (free cooling). At times when the cooling tower fan is required,
    4626              :         // the leaving water temperature is at or above the setpoint.
    4627              :         // A RunFlag is passed by the upper level manager to indicate the ON/OFF status,
    4628              :         // or schedule, of the cooling tower. If the tower is OFF, outlet water
    4629              :         // temperature and flow rate are passed through the model from inlet node to
    4630              :         // outlet node without intervention (with the exception of free convection
    4631              :         // where water temperature is allowed to float below the outlet water set
    4632              :         // point). Reports are also updated with fan power and fan energy being zero.
    4633              :         // When the RunFlag indicates an ON condition for the cooling tower, the
    4634              :         // mass flow rate and water temperature are read from the inlet node of the
    4635              :         // cooling tower (water-side). The outdoor air wet-bulb temperature is used
    4636              :         // as the entering condition to the cooling tower (air-side). Input deck
    4637              :         // parameters are read for the free convection regime (pump ON and fan OFF)
    4638              :         // and a leaving water temperature is calculated. If the leaving water temperature
    4639              :         // is at or below the setpoint, the calculated leaving water temperature is
    4640              :         // placed on the outlet node and no fan power is used. If the calculated leaving
    4641              :         // water temperature is above the setpoint, the cooling tower fan is turned on
    4642              :         // and parameters for low fan speed are used to again calculate the leaving
    4643              :         // water temperature. If the calculated leaving water temperature is
    4644              :         // below the setpoint, a fan run-time fraction (FanModeFrac) is calculated and
    4645              :         // used to determine fan power. The leaving water temperature setpoint is placed
    4646              :         // on the outlet node. If the calculated leaving water temperature is at or above
    4647              :         // the setpoint, the cooling tower fan is turned on 'high speed' and the routine is
    4648              :         // repeated. If the calculated leaving water temperature is below the setpoint,
    4649              :         // a fan run-time fraction is calculated for the second stage fan and fan power
    4650              :         // is calculated as FanModeFrac*HighSpeedFanPower+(1-FanModeFrac)*LowSpeedFanPower.
    4651              :         // If the calculated leaving water temperature is above the leaving water temp.
    4652              :         // setpoint, the calculated leaving water temperature is placed on the outlet
    4653              :         // node and the fan runs at full power (High Speed Fan Power). Water mass flow
    4654              :         // rate is passed from inlet node to outlet node with no intervention.
    4655              :         // If a tower has multiple cells, the specified inputs of or the autosized capacity
    4656              :         //  and air/water flow rates are for the entire tower. The number of cells to operate
    4657              :         //  is first determined based on the user entered minimal and maximal water flow fractions
    4658              :         //  per cell. If the loads are not met, more cells (if available) will operate to meet
    4659              :         //  the loads. Each cell operates in same way - same fan speed etc.
    4660              :         // REFERENCES:
    4661              :         // ASHRAE HVAC1KIT: A Toolkit for Primary HVAC System Energy Calculation. 1999.
    4662              : 
    4663              :         // SUBROUTINE PARAMETER DEFINITIONS:
    4664              :         static constexpr std::string_view RoutineName("calculateTwoSpeedTower");
    4665              : 
    4666              :         // init
    4667          106 :         this->Qactual = 0.0;
    4668          106 :         this->FanPower = 0.0;
    4669          106 :         this->OutletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp;
    4670              : 
    4671          106 :         Real64 freeConvTowerUA = this->FreeConvTowerUA;
    4672          106 :         Real64 highSpeedTowerUA = this->HighSpeedTowerUA;
    4673              : 
    4674              :         // water temperature setpoint
    4675          106 :         Real64 TempSetPoint = 0.0;
    4676          106 :         switch (this->plantLoc.loop->LoopDemandCalcScheme) {
    4677          106 :         case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
    4678          106 :             if (this->SetpointIsOnOutlet) {
    4679            0 :                 TempSetPoint = state.dataLoopNodes->Node(this->WaterOutletNodeNum).TempSetPoint;
    4680              :             } else {
    4681          106 :                 TempSetPoint = this->plantLoc.side->TempSetPoint;
    4682              :             }
    4683          106 :         } break;
    4684            0 :         case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
    4685            0 :             if (this->SetpointIsOnOutlet) {
    4686            0 :                 TempSetPoint = state.dataLoopNodes->Node(this->WaterOutletNodeNum).TempSetPointHi;
    4687              :             } else {
    4688            0 :                 TempSetPoint = this->plantLoc.side->TempSetPointHi;
    4689              :             }
    4690            0 :         } break;
    4691            0 :         default:
    4692            0 :             break;
    4693              :         }
    4694              : 
    4695              :         // If there is a fault of condenser SWT Sensor
    4696          106 :         if (this->FaultyCondenserSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    4697            0 :             (!state.dataGlobal->KickOffSimulation)) {
    4698            0 :             int FaultIndex = this->FaultyCondenserSWTIndex;
    4699            0 :             Real64 TowerOutletTemp_ff = TempSetPoint;
    4700              : 
    4701              :             // calculate the sensor offset using fault information
    4702            0 :             this->FaultyCondenserSWTOffset = state.dataFaultsMgr->FaultsCondenserSWTSensor(FaultIndex).CalFaultOffsetAct(state);
    4703              :             // update the TempSetPoint
    4704            0 :             TempSetPoint = TowerOutletTemp_ff - this->FaultyCondenserSWTOffset;
    4705              :         }
    4706              : 
    4707              :         // If there is a fault of cooling tower fouling
    4708          106 :         if (this->FaultyTowerFoulingFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    4709            0 :             (!state.dataGlobal->KickOffSimulation)) {
    4710            0 :             int FaultIndex = this->FaultyTowerFoulingIndex;
    4711            0 :             Real64 FreeConvTowerUA_ff = this->FreeConvTowerUA;
    4712            0 :             Real64 HighSpeedTowerUA_ff = this->HighSpeedTowerUA;
    4713              : 
    4714              :             // calculate the Faulty Tower Fouling Factor using fault information
    4715            0 :             this->FaultyTowerFoulingFactor = state.dataFaultsMgr->FaultsTowerFouling(FaultIndex).CalFaultyTowerFoulingFactor(state);
    4716              : 
    4717              :             // update the tower UA values at faulty cases
    4718            0 :             freeConvTowerUA = FreeConvTowerUA_ff * this->FaultyTowerFoulingFactor;
    4719            0 :             highSpeedTowerUA = HighSpeedTowerUA_ff * this->FaultyTowerFoulingFactor;
    4720              :         }
    4721              : 
    4722              :         // Do not RETURN here if flow rate is less than SmallMassFlow. Check basin heater and then RETURN.
    4723          149 :         if (this->plantLoc.side->FlowLock == DataPlant::FlowLock::Unlocked) return; // TODO: WTF
    4724           48 :         bool returnFlagSet = false;
    4725           48 :         this->checkMassFlowAndLoad(state, MyLoad, RunFlag, returnFlagSet);
    4726           48 :         if (returnFlagSet) return;
    4727              : 
    4728              :         // Added for multi-cell. Determine the number of cells operating
    4729            5 :         Real64 WaterMassFlowRatePerCellMin = 0.0;
    4730              :         Real64 WaterMassFlowRatePerCellMax;
    4731            5 :         int NumCellMin(0);
    4732            5 :         int NumCellMax(0);
    4733              :         Real64 WaterMassFlowRatePerCell;
    4734            5 :         if (this->DesWaterMassFlowRate > 0.0) {
    4735            5 :             WaterMassFlowRatePerCellMin = this->DesWaterMassFlowRate * this->MinFracFlowRate / this->NumCell;
    4736            5 :             WaterMassFlowRatePerCellMax = this->DesWaterMassFlowRate * this->MaxFracFlowRate / this->NumCell;
    4737              : 
    4738              :             // round it up to the nearest integer
    4739            5 :             NumCellMin = min(int((this->WaterMassFlowRate / WaterMassFlowRatePerCellMax) + 0.9999), this->NumCell);
    4740            5 :             NumCellMax = min(int((this->WaterMassFlowRate / WaterMassFlowRatePerCellMin) + 0.9999), this->NumCell);
    4741              :         }
    4742              : 
    4743              :         // cap min at 1
    4744            5 :         if (NumCellMin <= 0) NumCellMin = 1;
    4745            5 :         if (NumCellMax <= 0) NumCellMax = 1;
    4746              : 
    4747            5 :         if (this->cellCtrl == CellCtrl::MinCell) {
    4748            2 :             this->NumCellOn = NumCellMin;
    4749              :         } else {
    4750            3 :             this->NumCellOn = NumCellMax;
    4751              :         }
    4752              : 
    4753            5 :         WaterMassFlowRatePerCell = this->WaterMassFlowRate / this->NumCellOn;
    4754              : 
    4755            5 :         bool IncrNumCellFlag = true;
    4756              : 
    4757            5 :         Real64 AirFlowRate = 0.0;
    4758            5 :         Real64 FanModeFrac = 0.0;
    4759            5 :         int SpeedSel = 0;
    4760           15 :         while (IncrNumCellFlag) {
    4761            5 :             IncrNumCellFlag = false;
    4762              : 
    4763              :             // set local variable for tower
    4764            5 :             Real64 UAdesign = freeConvTowerUA / this->NumCell; // where is NumCellOn?
    4765            5 :             AirFlowRate = this->FreeConvAirFlowRate / this->NumCell;
    4766            5 :             this->WaterMassFlowRate = state.dataLoopNodes->Node(this->WaterInletNodeNum).MassFlowRate;
    4767            5 :             Real64 OutletWaterTemp1stStage = this->OutletWaterTemp;
    4768            5 :             Real64 OutletWaterTemp2ndStage = this->OutletWaterTemp;
    4769            5 :             FanModeFrac = 0.0;
    4770              : 
    4771            5 :             Real64 OutletWaterTempOFF = this->calculateSimpleTowerOutletTemp(state, WaterMassFlowRatePerCell, AirFlowRate, UAdesign);
    4772              : 
    4773              :             //     Setpoint was met using free convection regime (pump ON and fan OFF)
    4774            5 :             this->FanPower = 0.0;
    4775            5 :             this->OutletWaterTemp = OutletWaterTempOFF;
    4776              : 
    4777            5 :             if (OutletWaterTempOFF > TempSetPoint) {
    4778              :                 //     Setpoint was not met (or free conv. not used),turn on cooling tower 1st stage fan
    4779            0 :                 UAdesign = this->LowSpeedTowerUA / this->NumCell;
    4780            0 :                 AirFlowRate = this->LowSpeedAirFlowRate / this->NumCell;
    4781            0 :                 Real64 const FanPowerLow = this->LowSpeedFanPower * this->NumCellOn / this->NumCell;
    4782              : 
    4783            0 :                 OutletWaterTemp1stStage = this->calculateSimpleTowerOutletTemp(state, WaterMassFlowRatePerCell, AirFlowRate, UAdesign);
    4784              : 
    4785            0 :                 if (OutletWaterTemp1stStage <= TempSetPoint) {
    4786              :                     //         Setpoint was met with pump ON and fan ON 1st stage, calculate fan mode fraction
    4787            0 :                     FanModeFrac = (TempSetPoint - OutletWaterTempOFF) / (OutletWaterTemp1stStage - OutletWaterTempOFF);
    4788            0 :                     this->FanPower = FanModeFrac * FanPowerLow;
    4789            0 :                     this->OutletWaterTemp = TempSetPoint;
    4790            0 :                     this->Qactual *= FanModeFrac;
    4791            0 :                     SpeedSel = 1;
    4792              :                 } else {
    4793              :                     //         Setpoint was not met, turn on cooling tower 2nd stage fan
    4794            0 :                     UAdesign = highSpeedTowerUA / this->NumCell;
    4795            0 :                     AirFlowRate = this->HighSpeedAirFlowRate / this->NumCell;
    4796            0 :                     Real64 const FanPowerHigh = this->HighSpeedFanPower * this->NumCellOn / this->NumCell;
    4797              : 
    4798            0 :                     OutletWaterTemp2ndStage = this->calculateSimpleTowerOutletTemp(state, WaterMassFlowRatePerCell, AirFlowRate, UAdesign);
    4799              : 
    4800            0 :                     if ((OutletWaterTemp2ndStage <= TempSetPoint) && UAdesign > 0.0) {
    4801              :                         //           Setpoint was met with pump ON and fan ON 2nd stage, calculate fan mode fraction
    4802            0 :                         FanModeFrac = (TempSetPoint - OutletWaterTemp1stStage) / (OutletWaterTemp2ndStage - OutletWaterTemp1stStage);
    4803            0 :                         this->FanPower = (FanModeFrac * FanPowerHigh) + (1.0 - FanModeFrac) * FanPowerLow;
    4804            0 :                         this->OutletWaterTemp = TempSetPoint;
    4805            0 :                         SpeedSel = 2;
    4806              :                     } else {
    4807              :                         //           Setpoint was not met, cooling tower ran at full capacity
    4808            0 :                         this->OutletWaterTemp = OutletWaterTemp2ndStage;
    4809            0 :                         this->FanPower = FanPowerHigh;
    4810            0 :                         SpeedSel = 2;
    4811            0 :                         FanModeFrac = 1.0;
    4812              :                         // if possible increase the number of cells and do the calculations again with the new water mass flow rate per cell
    4813            0 :                         if (this->NumCellOn < this->NumCell && (this->WaterMassFlowRate / (this->NumCellOn + 1)) >= WaterMassFlowRatePerCellMin) {
    4814            0 :                             ++this->NumCellOn;
    4815            0 :                             WaterMassFlowRatePerCell = this->WaterMassFlowRate / this->NumCellOn;
    4816            0 :                             IncrNumCellFlag = true;
    4817              :                         }
    4818              :                     }
    4819              :                 }
    4820              :             }
    4821              :         }
    4822              : 
    4823              :         // output the fraction of the time step the fan is ON
    4824            5 :         this->FanCyclingRatio = FanModeFrac;
    4825            5 :         this->SpeedSelected = SpeedSel;
    4826              : 
    4827              :         Real64 const CpWater =
    4828            5 :             this->plantLoc.loop->glycol->getSpecificHeat(state, state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp, RoutineName);
    4829            5 :         this->Qactual = this->WaterMassFlowRate * CpWater * (state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp - this->OutletWaterTemp);
    4830            5 :         this->airFlowRateRatio = (AirFlowRate * this->NumCell) / this->HighSpeedAirFlowRate;
    4831              :     }
    4832              : 
    4833            4 :     void CoolingTower::calculateVariableSpeedTower(EnergyPlusData &state, Real64 &MyLoad, bool RunFlag)
    4834              :     {
    4835              : 
    4836              :         // SUBROUTINE INFORMATION:
    4837              :         //       AUTHOR         Richard Raustad
    4838              :         //       DATE WRITTEN   Feb 2005
    4839              :         //       MODIFIED       Jul. 2010, A Flament, added multi-cell capability for the 3 types of cooling tower
    4840              :         //                      Jul. 2010, B Griffith, general fluid props
    4841              :         //                      Jun. 2016, R Zhang, Applied the condenser supply water temperature sensor fault model
    4842              :         //                      Jul. 2016, R Zhang, Applied the cooling tower fouling fault model
    4843              : 
    4844              :         // PURPOSE OF THIS SUBROUTINE:
    4845              :         // To simulate the operation of a variable-speed fan cooling tower.
    4846              : 
    4847              :         // METHODOLOGY EMPLOYED:
    4848              :         // For each simulation time step, a desired range temperature (Twater,inlet-Twater,setpoint) and desired approach
    4849              :         // temperature (Twater,setpoint-Tair,WB) is calculated which meets the outlet water temperature setpoint. This
    4850              :         // desired range and approach temperature also provides a balance point for the empirical model where:
    4851              :         // Tair,WB + Twater,range + Tapproach = Node(WaterInletNode)%Temp
    4852              :         // Calculation of water outlet temperature uses one of the following equations:
    4853              :         // Twater,outlet = Tair,WB + Tapproach          (1)  or
    4854              :         // Twater,outlet = Twater,inlet - Twater,range  (2)
    4855              :         // If a solution (or balance) is found, these 2 calculation methods are equal. Equation 2 is used to calculate
    4856              :         // the outlet water temperature in the free convection regime and at the minimum or maximum fan speed so that
    4857              :         // if a solution is not reached, the outlet water temperature is approximately equal to the inlet water temperature
    4858              :         // and the tower fan must be varied to meet the setpoint. Equation 1 is used when the fan speed is varied between
    4859              :         // the minimum and maximum fan speed to meet the outlet water temperature setpoint.
    4860              :         // The outlet water temperature in the free convection regime is first calculated to see if the setpoint is met.
    4861              :         // If the setpoint is met, the fan is OFF and the outlet water temperature is allowed to float below the set
    4862              :         // point temperature. If the setpoint is not met, the outlet water temperature is re-calculated at the minimum
    4863              :         // fan speed. If the setpoint is met, the fan is cycled to exactly meet the outlet water temperature setpoint.
    4864              :         // If the setpoint is not met at the minimum fan speed, the outlet water temperature is re-calculated at the
    4865              :         // maximum fan speed. If the setpoint at the maximum fan speed is not met, the fan runs at maximum speed the
    4866              :         // entire time step. If the setpoint is met at the maximum fan speed, the fan speed is varied to meet the setpoint.
    4867              :         // If a tower has multiple cells, the specified inputs of or the autosized capacity
    4868              :         //  and air/water flow rates are for the entire tower. The number of cells to operate
    4869              :         //  is first determined based on the user entered minimal and maximal water flow fractions
    4870              :         //  per cell. If the loads are not met, more cells (if available) will operate to meet
    4871              :         //  the loads. Inside each cell, the fan speed varies in the same way.
    4872              :         // REFERENCES:
    4873              :         // Benton, D.J., Bowmand, C.F., Hydeman, M., Miller, P.,
    4874              :         // "An Improved Cooling Tower Algorithm for the CoolToolsTM Simulation Model".
    4875              :         // ASHRAE Transactions 2002, V. 108, Pt. 1.
    4876              :         // York International Corporation, "YORKcalcTM Software, Chiller-Plant Energy-Estimating Program",
    4877              :         // Form 160.00-SG2 (0502). 2002.
    4878              : 
    4879              :         // SUBROUTINE PARAMETER DEFINITIONS:
    4880              : 
    4881            4 :         int constexpr MaxIte(500);    // Maximum number of iterations
    4882            4 :         Real64 constexpr Acc(0.0001); // Accuracy of result
    4883              :         static constexpr std::string_view RoutineName("calculateVariableSpeedTower");
    4884              : 
    4885              :         // Added for multi-cell. Determine the number of cells operating
    4886            4 :         Real64 WaterMassFlowRatePerCellMin = 0.0;
    4887              :         Real64 WaterMassFlowRatePerCellMax;
    4888            4 :         int NumCellMin(0);
    4889            4 :         int NumCellMax(0);
    4890              :         Real64 WaterMassFlowRatePerCell;
    4891            4 :         if (this->DesWaterMassFlowRate > 0.0) {
    4892            2 :             WaterMassFlowRatePerCellMin = this->DesWaterMassFlowRate * this->MinFracFlowRate / this->NumCell;
    4893            2 :             WaterMassFlowRatePerCellMax = this->DesWaterMassFlowRate * this->MaxFracFlowRate / this->NumCell;
    4894              : 
    4895              :             // round it up to the nearest integer
    4896            2 :             NumCellMin = min(int((this->WaterMassFlowRate / WaterMassFlowRatePerCellMax) + 0.9999), this->NumCell);
    4897            2 :             NumCellMax = min(int((this->WaterMassFlowRate / WaterMassFlowRatePerCellMin) + 0.9999), this->NumCell);
    4898              :         }
    4899              : 
    4900              :         // cap min at 1
    4901            4 :         if (NumCellMin <= 0) NumCellMin = 1;
    4902            4 :         if (NumCellMax <= 0) NumCellMax = 1;
    4903              : 
    4904            4 :         if (this->cellCtrl == CellCtrl::MinCell) {
    4905            0 :             this->NumCellOn = NumCellMin;
    4906              :         } else {
    4907            4 :             this->NumCellOn = NumCellMax;
    4908              :         }
    4909              : 
    4910            4 :         WaterMassFlowRatePerCell = this->WaterMassFlowRate / this->NumCellOn;
    4911              : 
    4912              :         // Initialize subroutine variables
    4913            4 :         this->Qactual = 0.0;
    4914            4 :         this->FanPower = 0.0;
    4915            4 :         this->OutletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp;
    4916              : 
    4917            4 :         this->WaterUsage = 0.0;
    4918            4 :         Real64 Twb = this->AirWetBulb;
    4919            4 :         Real64 TwbCapped = this->AirWetBulb;
    4920              : 
    4921              :         // water temperature setpoint
    4922            4 :         Real64 TempSetPoint(0.0); // Outlet water temperature setpoint (C)
    4923            4 :         switch (this->plantLoc.loop->LoopDemandCalcScheme) {
    4924            4 :         case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
    4925            4 :             TempSetPoint = this->plantLoc.side->TempSetPoint;
    4926            4 :         } break;
    4927            0 :         case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
    4928            0 :             TempSetPoint = this->plantLoc.side->TempSetPointHi;
    4929            0 :         } break;
    4930            0 :         default: {
    4931            0 :             assert(false);
    4932              :         } break;
    4933              :         }
    4934              : 
    4935              :         // If there is a fault of condenser SWT Sensor
    4936            4 :         if (this->FaultyCondenserSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    4937            0 :             (!state.dataGlobal->KickOffSimulation)) {
    4938            0 :             int FaultIndex = this->FaultyCondenserSWTIndex;
    4939            0 :             Real64 TowerOutletTemp_ff = TempSetPoint;
    4940              : 
    4941              :             // calculate the sensor offset using fault information
    4942            0 :             this->FaultyCondenserSWTOffset = state.dataFaultsMgr->FaultsCondenserSWTSensor(FaultIndex).CalFaultOffsetAct(state);
    4943              :             // update the TempSetPoint
    4944            0 :             TempSetPoint = TowerOutletTemp_ff - this->FaultyCondenserSWTOffset;
    4945              :         }
    4946              : 
    4947            4 :         Real64 Tr = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp - TempSetPoint;
    4948            4 :         Real64 Ta = TempSetPoint - this->AirWetBulb;
    4949              : 
    4950              :         // Do not RETURN here if flow rate is less than MassFlowTolerance. Check basin heater and then RETURN.
    4951            4 :         if (this->plantLoc.side->FlowLock == DataPlant::FlowLock::Unlocked) return; // TODO: WTF
    4952              : 
    4953            2 :         bool returnFlagSet = false;
    4954            2 :         this->checkMassFlowAndLoad(state, MyLoad, RunFlag, returnFlagSet);
    4955            2 :         if (returnFlagSet) return;
    4956              : 
    4957              :         // loop to increment NumCell if we cannot meet the setpoint with the actual number of cells calculated above
    4958            2 :         bool IncrNumCellFlag = true;
    4959              :         Real64 OutletWaterTempOFF;             // Outlet water temperature with fan OFF (C)
    4960            2 :         Real64 OutletWaterTempON = 0.0;        // Outlet water temperature with fan ON at maximum fan speed (C)
    4961            2 :         Real64 FreeConvectionCapFrac = 0.0;    // fraction of tower capacity in free convection
    4962            2 :         Real64 WaterFlowRateRatioCapped = 0.0; // Water flow rate ratio passed to VS tower model
    4963              :         Real64 TrCapped;                       // range temp passed to VS tower model
    4964              :         Real64 TaCapped;                       // approach temp passed to VS tower model
    4965            4 :         while (IncrNumCellFlag) {
    4966            2 :             IncrNumCellFlag = false;
    4967              :             // Initialize inlet node water properties
    4968              :             Real64 const WaterDensity =
    4969            2 :                 this->plantLoc.loop->glycol->getDensity(state, state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp, RoutineName);
    4970            2 :             Real64 const WaterFlowRateRatio = WaterMassFlowRatePerCell / (WaterDensity * this->CalibratedWaterFlowRate / this->NumCell);
    4971              : 
    4972              :             // check independent inputs with respect to model boundaries
    4973            2 :             this->checkModelBounds(state, Twb, Tr, Ta, WaterFlowRateRatio, TwbCapped, TrCapped, TaCapped, WaterFlowRateRatioCapped);
    4974              : 
    4975              :             //   determine the free convection capacity by finding the outlet temperature at full air flow and multiplying
    4976              :             //   the tower's full capacity temperature difference by the percentage of tower capacity in free convection
    4977              :             //   regime specified by the user
    4978              : 
    4979            2 :             this->airFlowRateRatio = 1.0;
    4980            2 :             OutletWaterTempOFF = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp;
    4981            2 :             this->OutletWaterTemp = OutletWaterTempOFF;
    4982            2 :             FreeConvectionCapFrac = this->FreeConvectionCapacityFraction;
    4983            2 :             OutletWaterTempON = this->calculateVariableTowerOutletTemp(state, WaterFlowRateRatioCapped, this->airFlowRateRatio, TwbCapped);
    4984              : 
    4985            2 :             if (OutletWaterTempON > TempSetPoint) {
    4986            0 :                 this->FanCyclingRatio = 1.0;
    4987            0 :                 this->airFlowRateRatio = 1.0;
    4988            0 :                 this->FanPower = this->HighSpeedFanPower * this->NumCellOn / this->NumCell;
    4989            0 :                 this->OutletWaterTemp = OutletWaterTempON;
    4990              :                 // if possible increase the number of cells and do the calculations again with the new water mass flow rate per cell
    4991            0 :                 if (this->NumCellOn < this->NumCell && (this->WaterMassFlowRate / (this->NumCellOn + 1)) > WaterMassFlowRatePerCellMin) {
    4992            0 :                     ++this->NumCellOn;
    4993            0 :                     WaterMassFlowRatePerCell = this->WaterMassFlowRate / this->NumCellOn;
    4994            0 :                     IncrNumCellFlag = true;
    4995              :                 }
    4996              :             }
    4997              :         }
    4998              : 
    4999              :         // find the correct air ratio only if full flow is  too much
    5000            2 :         if (OutletWaterTempON < TempSetPoint) {
    5001              :             //   outlet water temperature is calculated in the free convection regime
    5002            2 :             OutletWaterTempOFF = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp -
    5003            2 :                                  FreeConvectionCapFrac * (state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp - OutletWaterTempON);
    5004              :             //   fan is OFF
    5005            2 :             this->FanCyclingRatio = 0.0;
    5006              :             //   air flow ratio is assumed to be the fraction of tower capacity in the free convection regime (fan is OFF but air is flowing)
    5007            2 :             this->airFlowRateRatio = FreeConvectionCapFrac;
    5008              : 
    5009              :             // Assume setpoint was met using free convection regime (pump ON and fan OFF)
    5010            2 :             this->FanPower = 0.0;
    5011            2 :             this->OutletWaterTemp = OutletWaterTempOFF;
    5012              : 
    5013            2 :             if (OutletWaterTempOFF > TempSetPoint) {
    5014              :                 // Setpoint was not met, turn on cooling tower fan at minimum fan speed
    5015              : 
    5016            2 :                 this->airFlowRateRatio = this->MinimumVSAirFlowFrac;
    5017              :                 Real64 OutletWaterTempMIN; // Outlet water temperature with fan at minimum speed (C)
    5018            2 :                 OutletWaterTempMIN = this->calculateVariableTowerOutletTemp(state, WaterFlowRateRatioCapped, this->airFlowRateRatio, TwbCapped);
    5019              : 
    5020            2 :                 if (OutletWaterTempMIN < TempSetPoint) {
    5021              :                     //         if setpoint was exceeded, cycle the fan at minimum air flow to meet the setpoint temperature
    5022            1 :                     if (this->FanPowerfAirFlowCurve == 0) {
    5023            0 :                         this->FanPower = pow_3(this->airFlowRateRatio) * this->HighSpeedFanPower * this->NumCellOn / this->NumCell;
    5024              :                     } else {
    5025            1 :                         Real64 const FanCurveValue = Curve::CurveValue(state, this->FanPowerfAirFlowCurve, this->airFlowRateRatio);
    5026            1 :                         this->FanPower = max(0.0, (this->HighSpeedFanPower * FanCurveValue)) * this->NumCellOn / this->NumCell;
    5027              :                     }
    5028              :                     //       fan is cycling ON and OFF at the minimum fan speed. Adjust fan power and air flow rate ratio according to cycling rate
    5029            1 :                     this->FanCyclingRatio = ((OutletWaterTempOFF - TempSetPoint) / (OutletWaterTempOFF - OutletWaterTempMIN));
    5030            1 :                     this->FanPower *= this->FanCyclingRatio;
    5031            1 :                     this->OutletWaterTemp = TempSetPoint;
    5032            1 :                     this->airFlowRateRatio =
    5033            1 :                         (this->FanCyclingRatio * this->MinimumVSAirFlowFrac) + ((1 - this->FanCyclingRatio) * FreeConvectionCapFrac);
    5034              :                 } else {
    5035              :                     //       if setpoint was not met at minimum fan speed, set fan speed to maximum
    5036            1 :                     this->airFlowRateRatio = 1.0;
    5037              :                     //         fan will not cycle and runs the entire time step
    5038            1 :                     this->FanCyclingRatio = 1.0;
    5039              : 
    5040            1 :                     this->OutletWaterTemp =
    5041            1 :                         this->calculateVariableTowerOutletTemp(state, WaterFlowRateRatioCapped, this->airFlowRateRatio, TwbCapped);
    5042              : 
    5043              :                     // Setpoint was met with pump ON and fan ON at full flow
    5044              :                     // Calculate the fraction of full air flow to exactly meet the setpoint temperature
    5045            6 :                     auto f = [&state, this, WaterFlowRateRatioCapped, TwbCapped, Tr, Ta](Real64 FlowRatio) {
    5046            6 :                         Real64 TapproachActual = this->calculateVariableSpeedApproach(state, WaterFlowRateRatioCapped, FlowRatio, TwbCapped, Tr);
    5047            6 :                         return Ta - TapproachActual;
    5048            1 :                     };
    5049            1 :                     int SolFla = 0;
    5050            1 :                     General::SolveRoot(state, Acc, MaxIte, SolFla, this->airFlowRateRatio, f, this->MinimumVSAirFlowFrac, 1.0);
    5051            1 :                     if (SolFla == -1) {
    5052            0 :                         if (!state.dataGlobal->WarmupFlag)
    5053            0 :                             ShowWarningError(
    5054              :                                 state,
    5055            0 :                                 format("Cooling tower iteration limit exceeded when calculating air flow rate ratio for tower {}", this->Name));
    5056              :                         //           IF RegulaFalsi cannot find a solution then provide detailed output for debugging
    5057            1 :                     } else if (SolFla == -2) {
    5058            0 :                         if (!state.dataGlobal->WarmupFlag) {
    5059              : 
    5060            0 :                             if (this->CoolingTowerAFRRFailedCount < 1) {
    5061            0 :                                 ++this->CoolingTowerAFRRFailedCount;
    5062            0 :                                 ShowWarningError(
    5063              :                                     state,
    5064            0 :                                     format("CoolingTower:VariableSpeed \"{}\" - Cooling tower air flow rate ratio calculation failed ", this->Name));
    5065            0 :                                 ShowContinueError(state,
    5066            0 :                                                   format("...with conditions as Twb = {:5.2F}, Trange = {:5.2F}, Tapproach = {:5.2F}, and water flow "
    5067              :                                                          "rate ratio = {:5.2F}",
    5068              :                                                          TwbCapped,
    5069              :                                                          Tr,
    5070              :                                                          Ta,
    5071              :                                                          WaterFlowRateRatioCapped));
    5072            0 :                                 ShowContinueError(state, "...a solution could not be found within the valid range of air flow rate ratios");
    5073            0 :                                 ShowContinueErrorTimeStamp(
    5074            0 :                                     state, format(" ...Valid air flow rate ratio range = {:5.2F} to 1.0.", this->MinimumVSAirFlowFrac));
    5075            0 :                                 ShowContinueError(state, "...Consider modifying the design approach or design range temperature for this tower.");
    5076              :                             } else {
    5077            0 :                                 ShowRecurringWarningErrorAtEnd(state,
    5078            0 :                                                                "CoolingTower:VariableSpeed \"" + this->Name +
    5079              :                                                                    "\" - Cooling tower air flow rate ratio calculation failed error continues.",
    5080            0 :                                                                this->CoolingTowerAFRRFailedIndex);
    5081              :                             }
    5082              :                         }
    5083              :                     }
    5084              : 
    5085              :                     //         Use theoretical cubic for determination of fan power if user has not specified a fan power ratio curve
    5086            1 :                     if (this->FanPowerfAirFlowCurve == 0) {
    5087            0 :                         this->FanPower = pow_3(this->airFlowRateRatio) * this->HighSpeedFanPower * this->NumCellOn / this->NumCell;
    5088              :                     } else {
    5089            1 :                         Real64 const FanCurveValue = Curve::CurveValue(state, this->FanPowerfAirFlowCurve, this->airFlowRateRatio);
    5090            1 :                         this->FanPower = max(0.0, (this->HighSpeedFanPower * FanCurveValue)) * this->NumCellOn / this->NumCell;
    5091              :                     }
    5092              :                     //           outlet water temperature is calculated as the inlet air wet-bulb temperature plus tower approach temperature
    5093            1 :                     this->OutletWaterTemp = Twb + Ta;
    5094              :                 }
    5095              :             }
    5096              :         }
    5097              : 
    5098              :         Real64 const CpWater =
    5099            2 :             this->plantLoc.loop->glycol->getSpecificHeat(state, state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp, RoutineName);
    5100            2 :         this->Qactual = this->WaterMassFlowRate * CpWater * (state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp - this->OutletWaterTemp);
    5101              : 
    5102              :         //   calculate end time of current time step
    5103            2 :         Real64 const CurrentEndTime = state.dataGlobal->CurrentTime + state.dataHVACGlobal->SysTimeElapsed;
    5104              : 
    5105              :         //   Print warning messages only when valid and only for the first occurrence. Let summary provide statistics.
    5106              :         //   Wait for next time step to print warnings. If simulation iterates, print out
    5107              :         //   the warning for the last iteration only. Must wait for next time step to accomplish this.
    5108              :         //   If a warning occurs and the simulation down shifts, the warning is not valid.
    5109            2 :         if (CurrentEndTime > this->CurrentEndTimeLast && state.dataHVACGlobal->TimeStepSys >= this->TimeStepSysLast) {
    5110            0 :             if (this->PrintLGMessage) {
    5111            0 :                 ++this->VSErrorCountFlowFrac;
    5112              :                 //       Show single warning and pass additional info to ShowRecurringWarningErrorAtEnd
    5113            0 :                 if (this->VSErrorCountFlowFrac < 2) {
    5114            0 :                     ShowWarningError(state, this->LGBuffer1);
    5115            0 :                     ShowContinueError(state, this->LGBuffer2);
    5116              :                 } else {
    5117            0 :                     ShowRecurringWarningErrorAtEnd(state,
    5118            0 :                                                    format("{} \"{}\" - Liquid to gas ratio is out of range error continues...",
    5119            0 :                                                           DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    5120            0 :                                                           this->Name),
    5121            0 :                                                    this->ErrIndexLG,
    5122            0 :                                                    this->LGLast,
    5123            0 :                                                    this->LGLast);
    5124              :                 }
    5125              :             }
    5126              :         }
    5127              : 
    5128              :         //   save last system time step and last end time of current time step (used to determine if warning is valid)
    5129            2 :         this->TimeStepSysLast = state.dataHVACGlobal->TimeStepSys;
    5130            2 :         this->CurrentEndTimeLast = CurrentEndTime;
    5131              : 
    5132              :         //   warn user on first occurrence if flow fraction is greater than maximum for the YorkCalc model, use recurring warning stats
    5133            2 :         if (this->TowerModelType == ModelType::YorkCalcModel || this->TowerModelType == ModelType::YorkCalcUserDefined) {
    5134            0 :             this->PrintLGMessage = false;
    5135              :             //      Do not report error message in free convection regime
    5136            0 :             if (this->airFlowRateRatio > this->MinimumVSAirFlowFrac) {
    5137            0 :                 Real64 const FlowFraction = WaterFlowRateRatioCapped / this->airFlowRateRatio;
    5138              :                 //        Flow fractions greater than a MaxLiquidToGasRatio of 8 are not reliable using the YorkCalc model
    5139            0 :                 if (FlowFraction > this->MaxLiquidToGasRatio) {
    5140              :                     //          Report warnings only during actual simulation
    5141            0 :                     if (!state.dataGlobal->WarmupFlag) {
    5142            0 :                         this->PrintLGMessage = true;
    5143            0 :                         this->LGBuffer1 = format("{} \"{}\" - Liquid to gas ratio (L/G) is out of range at {:5.2F}.",
    5144            0 :                                                  DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    5145            0 :                                                  this->Name,
    5146            0 :                                                  FlowFraction);
    5147            0 :                         this->LGBuffer2 = format(" ...Valid maximum ratio = {:5.2F}. Occurrence info = {}, {} {}",
    5148            0 :                                                  this->MaxLiquidToGasRatio,
    5149            0 :                                                  state.dataEnvrn->EnvironmentName,
    5150            0 :                                                  state.dataEnvrn->CurMnDy,
    5151            0 :                                                  General::CreateSysTimeIntervalString(state));
    5152              : 
    5153            0 :                         this->LGLast = FlowFraction;
    5154              :                     }
    5155              :                 }
    5156              :             }
    5157              :         }
    5158              :     }
    5159              : 
    5160          108 :     void CoolingTower::calculateMerkelVariableSpeedTower(EnergyPlusData &state, Real64 &MyLoad, bool RunFlag)
    5161              :     {
    5162              : 
    5163              :         // SUBROUTINE INFORMATION:
    5164              :         //       AUTHOR         B.Griffith
    5165              :         //       DATE WRITTEN   August 2013
    5166              :         //       MODIFIED       Jun. 2016, R Zhang, Applied the condenser supply water temperature sensor fault model
    5167              :         //                      Jul. 2016, R Zhang, Applied the cooling tower fouling fault model
    5168              : 
    5169              :         // PURPOSE OF THIS SUBROUTINE:
    5170              :         // Calculate variable speed tower model using Merkel's theory with UA adjustments developed by Scheier
    5171              : 
    5172              :         // METHODOLOGY EMPLOYED:
    5173              :         // Find a fan speed that operates the tower to meet MyLoad
    5174              : 
    5175              :         // SUBROUTINE PARAMETER DEFINITIONS:
    5176          108 :         Real64 constexpr DesignWetBulb(25.56); // tower outdoor air entering wetbulb for design [C]
    5177          108 :         int constexpr MaxIte(500);             // Maximum number of iterations for solver
    5178          108 :         Real64 constexpr Acc(1.e-3);           // Accuracy of solver result
    5179              :         static constexpr std::string_view RoutineName("calculateMerkelVariableSpeedTower");
    5180              : 
    5181              :         Real64 const CpWater =
    5182          108 :             this->plantLoc.loop->glycol->getSpecificHeat(state, state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp, RoutineName);
    5183          108 :         this->Qactual = 0.0;
    5184          108 :         this->FanPower = 0.0;
    5185          108 :         this->OutletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp;
    5186              : 
    5187          108 :         Real64 freeConvTowerUA = this->FreeConvTowerUA;
    5188          108 :         Real64 highSpeedTowerUA = this->HighSpeedTowerUA;
    5189              : 
    5190              :         // If there is a fault of condenser SWT Sensor
    5191          108 :         if (this->FaultyCondenserSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    5192            0 :             (!state.dataGlobal->KickOffSimulation)) {
    5193            0 :             int FaultIndex = this->FaultyCondenserSWTIndex;
    5194              :             // calculate the sensor offset using fault information
    5195            0 :             this->FaultyCondenserSWTOffset = state.dataFaultsMgr->FaultsCondenserSWTSensor(FaultIndex).CalFaultOffsetAct(state);
    5196              :         }
    5197              : 
    5198              :         // If there is a fault of cooling tower fouling
    5199          108 :         if (this->FaultyTowerFoulingFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
    5200            0 :             (!state.dataGlobal->KickOffSimulation)) {
    5201            0 :             int FaultIndex = this->FaultyTowerFoulingIndex;
    5202            0 :             Real64 FreeConvTowerUA_ff = this->FreeConvTowerUA;
    5203            0 :             Real64 HighSpeedTowerUA_ff = this->HighSpeedTowerUA;
    5204              : 
    5205              :             // calculate the Faulty Tower Fouling Factor using fault information
    5206            0 :             this->FaultyTowerFoulingFactor = state.dataFaultsMgr->FaultsTowerFouling(FaultIndex).CalFaultyTowerFoulingFactor(state);
    5207              : 
    5208              :             // update the tower UA values at faulty cases
    5209            0 :             freeConvTowerUA = FreeConvTowerUA_ff * this->FaultyTowerFoulingFactor;
    5210            0 :             highSpeedTowerUA = HighSpeedTowerUA_ff * this->FaultyTowerFoulingFactor;
    5211              :         }
    5212              : 
    5213          108 :         Real64 WaterMassFlowRatePerCellMin = 0.0;
    5214              :         Real64 WaterMassFlowRatePerCellMax;
    5215              : 
    5216              :         // Added for multi-cell. Determine the number of cells operating
    5217          108 :         int NumCellMin = 0;
    5218          108 :         int NumCellMax = 0;
    5219              :         Real64 WaterMassFlowRatePerCell;
    5220              :         Real64 UAdesignPerCell;
    5221              :         Real64 AirFlowRatePerCell;
    5222          108 :         if (this->DesWaterMassFlowRate > 0.0) {
    5223           49 :             WaterMassFlowRatePerCellMin = this->DesWaterMassFlowRate * this->MinFracFlowRate / this->NumCell;
    5224           49 :             WaterMassFlowRatePerCellMax = this->DesWaterMassFlowRate * this->MaxFracFlowRate / this->NumCell;
    5225              : 
    5226              :             // round it up to the nearest integer
    5227           49 :             NumCellMin = min(int((this->WaterMassFlowRate / WaterMassFlowRatePerCellMax) + 0.9999), this->NumCell);
    5228           49 :             NumCellMax = min(int((this->WaterMassFlowRate / WaterMassFlowRatePerCellMin) + 0.9999), this->NumCell);
    5229              :         }
    5230              : 
    5231              :         // cap min at 1
    5232          108 :         if (NumCellMin <= 0) NumCellMin = 1;
    5233          108 :         if (NumCellMax <= 0) NumCellMax = 1;
    5234              : 
    5235          108 :         if (this->cellCtrl == CellCtrl::MinCell) {
    5236            0 :             this->NumCellOn = NumCellMin;
    5237              :         } else {
    5238          108 :             this->NumCellOn = NumCellMax;
    5239              :         }
    5240              : 
    5241          108 :         WaterMassFlowRatePerCell = this->WaterMassFlowRate / this->NumCellOn;
    5242              : 
    5243          108 :         if ((std::abs(MyLoad) <= HVAC::SmallLoad) || !RunFlag) {
    5244              :             // tower doesn't need to do anything
    5245           94 :             this->OutletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp;
    5246           94 :             this->FanPower = 0.0;
    5247           94 :             this->airFlowRateRatio = 0.0;
    5248           94 :             this->Qactual = 0.0;
    5249           94 :             CalcBasinHeaterPower(
    5250           94 :                 state, this->BasinHeaterPowerFTempDiff, this->basinHeaterSched, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
    5251           94 :             return;
    5252           14 :         } else if (this->WaterMassFlowRate <= DataBranchAirLoopPlant::MassFlowTolerance || (MyLoad > HVAC::SmallLoad)) {
    5253              :             // for multiple cells, we assume that it's a common basin
    5254            0 :             CalcBasinHeaterPower(
    5255            0 :                 state, this->BasinHeaterPowerFTempDiff, this->basinHeaterSched, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
    5256            0 :             return;
    5257              :         }
    5258              : 
    5259              :         // first find free convection cooling rate
    5260           14 :         UAdesignPerCell = freeConvTowerUA / this->NumCell;
    5261           14 :         AirFlowRatePerCell = this->FreeConvAirFlowRate / this->NumCell;
    5262           14 :         this->WaterMassFlowRate = state.dataLoopNodes->Node(this->WaterInletNodeNum).MassFlowRate;
    5263           14 :         Real64 OutletWaterTempOFF = this->calculateSimpleTowerOutletTemp(state, WaterMassFlowRatePerCell, AirFlowRatePerCell, UAdesignPerCell);
    5264              : 
    5265           14 :         Real64 FreeConvQdot = this->WaterMassFlowRate * CpWater * (state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp - OutletWaterTempOFF);
    5266           14 :         this->FanPower = 0.0;
    5267              : 
    5268           14 :         if (std::abs(MyLoad) <= FreeConvQdot) { // can meet load with free convection and fan off
    5269              : 
    5270           10 :             this->OutletWaterTemp = OutletWaterTempOFF;
    5271           10 :             this->airFlowRateRatio = 0.0;
    5272           10 :             this->Qactual = FreeConvQdot;
    5273           10 :             CalcBasinHeaterPower(
    5274           10 :                 state, this->BasinHeaterPowerFTempDiff, this->basinHeaterSched, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
    5275              : 
    5276           10 :             return;
    5277              :         }
    5278              : 
    5279              :         // next find full fan speed cooling rate
    5280            4 :         UAdesignPerCell = highSpeedTowerUA / this->NumCell;
    5281            4 :         AirFlowRatePerCell = this->HighSpeedAirFlowRate / this->NumCell;
    5282            4 :         this->airFlowRateRatio = 1.0;
    5283            4 :         Real64 WaterFlowRateRatio = WaterMassFlowRatePerCell / this->DesWaterMassFlowRatePerCell;
    5284            4 :         Real64 UAwetbulbAdjFac = Curve::CurveValue(state, this->UAModFuncWetBulbDiffCurvePtr, (DesignWetBulb - this->AirWetBulb));
    5285            4 :         Real64 UAairflowAdjFac = Curve::CurveValue(state, this->UAModFuncAirFlowRatioCurvePtr, this->airFlowRateRatio);
    5286            4 :         Real64 UAwaterflowAdjFac = Curve::CurveValue(state, this->UAModFuncWaterFlowRatioCurvePtr, WaterFlowRateRatio);
    5287            4 :         Real64 UAadjustedPerCell = UAdesignPerCell * UAwetbulbAdjFac * UAairflowAdjFac * UAwaterflowAdjFac;
    5288            4 :         this->OutletWaterTemp = this->calculateSimpleTowerOutletTemp(state, WaterMassFlowRatePerCell, AirFlowRatePerCell, UAadjustedPerCell);
    5289              :         Real64 FullSpeedFanQdot =
    5290            4 :             this->WaterMassFlowRate * CpWater * (state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp - this->OutletWaterTemp);
    5291            4 :         Real64 FanPowerAdjustFac = 0.0;
    5292            4 :         if (FullSpeedFanQdot <= std::abs(MyLoad)) { // full speed is what we want.
    5293              : 
    5294            0 :             if ((FullSpeedFanQdot + HVAC::SmallLoad) < std::abs(MyLoad) && (this->NumCellOn < this->NumCell) &&
    5295            0 :                 ((this->WaterMassFlowRate / (this->NumCellOn + 1)) >= WaterMassFlowRatePerCellMin)) {
    5296              :                 // If full fan and not meeting setpoint, then increase number of cells until all are used or load is satisfied
    5297            0 :                 bool IncrNumCellFlag = true; // set value to true to enter in the loop
    5298            0 :                 while (IncrNumCellFlag) {
    5299            0 :                     ++this->NumCellOn;
    5300            0 :                     WaterMassFlowRatePerCell = this->WaterMassFlowRate / this->NumCellOn;
    5301            0 :                     WaterFlowRateRatio = WaterMassFlowRatePerCell / this->DesWaterMassFlowRatePerCell;
    5302            0 :                     UAwaterflowAdjFac = Curve::CurveValue(state, this->UAModFuncWaterFlowRatioCurvePtr, WaterFlowRateRatio);
    5303            0 :                     UAadjustedPerCell = UAdesignPerCell * UAwetbulbAdjFac * UAairflowAdjFac * UAwaterflowAdjFac;
    5304            0 :                     this->OutletWaterTemp =
    5305            0 :                         this->calculateSimpleTowerOutletTemp(state, WaterMassFlowRatePerCell, AirFlowRatePerCell, UAadjustedPerCell);
    5306            0 :                     IncrNumCellFlag = (FullSpeedFanQdot + HVAC::SmallLoad) < std::abs(MyLoad) && (this->NumCellOn < this->NumCell) &&
    5307            0 :                                       ((this->WaterMassFlowRate / (this->NumCellOn + 1)) >= WaterMassFlowRatePerCellMin);
    5308              :                 }
    5309            0 :                 FullSpeedFanQdot =
    5310            0 :                     this->WaterMassFlowRate * CpWater * (state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp - this->OutletWaterTemp);
    5311              :             }
    5312            0 :             this->Qactual = FullSpeedFanQdot;
    5313            0 :             CalcBasinHeaterPower(
    5314            0 :                 state, this->BasinHeaterPowerFTempDiff, this->basinHeaterSched, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
    5315              :             // now calculate fan power
    5316            0 :             FanPowerAdjustFac = Curve::CurveValue(state, this->FanPowerfAirFlowCurve, this->airFlowRateRatio);
    5317            0 :             this->FanPower = this->HighSpeedFanPower * FanPowerAdjustFac * this->NumCellOn / this->NumCell;
    5318              : 
    5319            0 :             return;
    5320              :         }
    5321              : 
    5322              :         // next find minimum air flow ratio cooling rate
    5323            4 :         this->airFlowRateRatio = this->MinimumVSAirFlowFrac;
    5324            4 :         AirFlowRatePerCell = this->airFlowRateRatio * this->HighSpeedAirFlowRate / this->NumCell;
    5325            4 :         UAairflowAdjFac = Curve::CurveValue(state, this->UAModFuncAirFlowRatioCurvePtr, this->airFlowRateRatio);
    5326            4 :         UAadjustedPerCell = UAdesignPerCell * UAwetbulbAdjFac * UAairflowAdjFac * UAwaterflowAdjFac;
    5327            4 :         this->OutletWaterTemp = this->calculateSimpleTowerOutletTemp(state, WaterMassFlowRatePerCell, AirFlowRatePerCell, UAadjustedPerCell);
    5328              :         Real64 MinSpeedFanQdot =
    5329            4 :             this->WaterMassFlowRate * CpWater * (state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp - this->OutletWaterTemp);
    5330              : 
    5331            4 :         if (std::abs(MyLoad) <= MinSpeedFanQdot) { // min fan speed already exceeds load)
    5332            4 :             this->Qactual = MinSpeedFanQdot;
    5333            4 :             CalcBasinHeaterPower(
    5334            4 :                 state, this->BasinHeaterPowerFTempDiff, this->basinHeaterSched, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
    5335              :             // now calculate fan power
    5336            4 :             FanPowerAdjustFac = Curve::CurveValue(state, this->FanPowerfAirFlowCurve, this->airFlowRateRatio);
    5337            4 :             this->FanPower = this->HighSpeedFanPower * FanPowerAdjustFac * this->NumCellOn / this->NumCell;
    5338            4 :             return;
    5339              :         }
    5340              : 
    5341            0 :         if ((MinSpeedFanQdot < std::abs(MyLoad)) && (std::abs(MyLoad) < FullSpeedFanQdot)) {
    5342              :             // load can be refined by modulating fan speed, call regula-falsi
    5343            0 :             auto f = [&state, this, MyLoad, WaterMassFlowRatePerCell, UAdesignPerCell, UAwetbulbAdjFac, UAwaterflowAdjFac, CpWater](
    5344              :                          Real64 airFlowRateRatioLocal) {
    5345            0 :                 Real64 const AirFlowRatePerCell = airFlowRateRatioLocal * this->HighSpeedAirFlowRate / this->NumCell;
    5346            0 :                 Real64 const UAairflowAdjFac = Curve::CurveValue(state, this->UAModFuncAirFlowRatioCurvePtr, airFlowRateRatioLocal);
    5347            0 :                 Real64 const UAadjustedPerCell = UAdesignPerCell * UAwetbulbAdjFac * UAairflowAdjFac * UAwaterflowAdjFac;
    5348              :                 Real64 OutletWaterTempTrial =
    5349            0 :                     this->calculateSimpleTowerOutletTemp(state, WaterMassFlowRatePerCell, AirFlowRatePerCell, UAadjustedPerCell);
    5350              :                 Real64 const Qdot =
    5351            0 :                     this->WaterMassFlowRate * CpWater * (state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp - OutletWaterTempTrial);
    5352            0 :                 return std::abs(MyLoad) - Qdot;
    5353            0 :             };
    5354            0 :             int SolFla = 0;
    5355            0 :             General::SolveRoot(state, Acc, MaxIte, SolFla, this->airFlowRateRatio, f, this->MinimumVSAirFlowFrac, 1.0);
    5356              : 
    5357            0 :             if (SolFla == -1) {
    5358            0 :                 if (!state.dataGlobal->WarmupFlag) {
    5359            0 :                     if (this->VSMerkelAFRErrorIter < 1) {
    5360            0 :                         ++this->VSMerkelAFRErrorIter;
    5361            0 :                         ShowWarningError(state,
    5362            0 :                                          format("{} - Iteration limit exceeded calculating variable speed fan ratio for unit = {}",
    5363              :                                                 cCoolingTower_VariableSpeedMerkel,
    5364            0 :                                                 this->Name));
    5365            0 :                         ShowContinueError(state,
    5366            0 :                                           format("Estimated air flow ratio  = {:.4R}",
    5367            0 :                                                  (std::abs(MyLoad) - MinSpeedFanQdot) / (FullSpeedFanQdot - MinSpeedFanQdot)));
    5368            0 :                         ShowContinueError(state, format("Calculated air flow ratio = {:.4R}", this->airFlowRateRatio));
    5369            0 :                         ShowContinueErrorTimeStamp(state,
    5370              :                                                    "The calculated air flow ratio will be used and the simulation continues. Occurrence info:");
    5371              :                     }
    5372            0 :                     ShowRecurringWarningErrorAtEnd(
    5373              :                         state,
    5374            0 :                         cCoolingTower_VariableSpeedMerkel + " \"" + this->Name +
    5375              :                             "\" - Iteration limit exceeded calculating air flow ratio error continues. air flow ratio statistics follow.",
    5376            0 :                         this->VSMerkelAFRErrorIterIndex,
    5377            0 :                         this->airFlowRateRatio,
    5378            0 :                         this->airFlowRateRatio);
    5379              :                 }
    5380            0 :             } else if (SolFla == -2) {
    5381            0 :                 this->airFlowRateRatio = (std::abs(MyLoad) - MinSpeedFanQdot) / (FullSpeedFanQdot - MinSpeedFanQdot);
    5382            0 :                 if (!state.dataGlobal->WarmupFlag) {
    5383            0 :                     if (this->VSMerkelAFRErrorFail < 1) {
    5384            0 :                         ++this->VSMerkelAFRErrorFail;
    5385            0 :                         ShowWarningError(state,
    5386            0 :                                          format("{} - solver failed calculating variable speed fan ratio for unit = {}",
    5387              :                                                 cCoolingTower_VariableSpeedMerkel,
    5388            0 :                                                 this->Name));
    5389            0 :                         ShowContinueError(state, format("Estimated air flow ratio  = {:.4R}", this->airFlowRateRatio));
    5390            0 :                         ShowContinueErrorTimeStamp(state, "The estimated air flow ratio will be used and the simulation continues. Occurrence info:");
    5391              :                     }
    5392            0 :                     ShowRecurringWarningErrorAtEnd(
    5393              :                         state,
    5394            0 :                         cCoolingTower_VariableSpeedMerkel + " \"" + this->Name +
    5395              :                             "\" - solver failed calculating air flow ratio error continues. air flow ratio statistics follow.",
    5396            0 :                         this->VSMerkelAFRErrorFailIndex,
    5397            0 :                         this->airFlowRateRatio,
    5398            0 :                         this->airFlowRateRatio);
    5399              :                 }
    5400              :             }
    5401              : 
    5402              :             // now rerun to get performance with AirFlowRateRatio
    5403            0 :             AirFlowRatePerCell = this->airFlowRateRatio * this->HighSpeedAirFlowRate / this->NumCell;
    5404              : 
    5405            0 :             UAairflowAdjFac = Curve::CurveValue(state, this->UAModFuncAirFlowRatioCurvePtr, this->airFlowRateRatio);
    5406            0 :             UAadjustedPerCell = UAdesignPerCell * UAwetbulbAdjFac * UAairflowAdjFac * UAwaterflowAdjFac;
    5407              : 
    5408            0 :             this->OutletWaterTemp = this->calculateSimpleTowerOutletTemp(state, WaterMassFlowRatePerCell, AirFlowRatePerCell, UAadjustedPerCell);
    5409            0 :             this->Qactual = this->WaterMassFlowRate * CpWater * (state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp - this->OutletWaterTemp);
    5410            0 :             CalcBasinHeaterPower(
    5411            0 :                 state, this->BasinHeaterPowerFTempDiff, this->basinHeaterSched, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
    5412              : 
    5413              :             // now calculate fan power
    5414            0 :             FanPowerAdjustFac = Curve::CurveValue(state, this->FanPowerfAirFlowCurve, this->airFlowRateRatio);
    5415            0 :             this->FanPower = this->HighSpeedFanPower * FanPowerAdjustFac * this->NumCellOn / this->NumCell;
    5416              :         }
    5417              :     }
    5418              : 
    5419        18494 :     Real64 CoolingTower::calculateSimpleTowerOutletTemp(EnergyPlusData &state,
    5420              :                                                         Real64 const waterMassFlowRate,
    5421              :                                                         Real64 const AirFlowRate,
    5422              :                                                         Real64 const UAdesign)
    5423              :     {
    5424              : 
    5425              :         // SUBROUTINE INFORMATION:
    5426              :         //       AUTHOR         Dan Fisher
    5427              :         //       DATE WRITTEN   Sept. 1998
    5428              :         //       RE-ENGINEERED  Shirey, Raustad, Jan 2001
    5429              : 
    5430              :         // PURPOSE OF THIS SUBROUTINE:
    5431              :         // See purpose for Single Speed or Two Speed tower model
    5432              : 
    5433              :         // METHODOLOGY EMPLOYED:
    5434              :         // See methodology for Single Speed or Two Speed tower model
    5435              : 
    5436              :         // REFERENCES:
    5437              :         // Merkel, F. 1925.  Verduftungskuhlung. VDI Forschungsarbeiten, Nr 275, Berlin.
    5438              :         // ASHRAE     1999.  HVAC1KIT: A Toolkit for Primary HVAC System Energy Calculations.
    5439              : 
    5440              :         // SUBROUTINE PARAMETER DEFINITIONS:
    5441              :         static constexpr std::string_view RoutineName("calculateSimpleTowerOutletTemp");
    5442              : 
    5443              :         // initialize some local variables
    5444        18494 :         Real64 QactualLocal = 0.0; // Actual heat transfer rate between tower water and air [W]
    5445              : 
    5446              :         // set local tower inlet and outlet temperature variables
    5447        18494 :         this->InletWaterTemp = this->WaterTemp;
    5448        18494 :         Real64 OutletWaterTempLocal = this->InletWaterTemp;
    5449        18494 :         Real64 InletAirTemp = this->AirTemp;       // Dry-bulb temperature of air entering the tower [C]
    5450        18494 :         Real64 InletAirWetBulb = this->AirWetBulb; // Wetbulb temp of entering moist air [C]
    5451              : 
    5452        18494 :         if (UAdesign == 0.0) return OutletWaterTempLocal;
    5453              : 
    5454              :         // set water and air properties
    5455        10074 :         Real64 AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(state, this->AirPress, InletAirTemp, this->AirHumRat); // Density of air [kg/m3]
    5456        10074 :         Real64 AirMassFlowRate = AirFlowRate * AirDensity;                                                           // Mass flow rate of air [kg/s]
    5457        10074 :         Real64 CpAir = Psychrometrics::PsyCpAirFnW(this->AirHumRat);                                                 // Heat capacity of air [J/kg/K]
    5458        10074 :         Real64 CpWater = this->plantLoc.loop->glycol->getSpecificHeat(state, this->WaterTemp, RoutineName); // Heat capacity of water [J/kg/K]
    5459              :         Real64 InletAirEnthalpy =
    5460        10074 :             Psychrometrics::PsyHFnTdbRhPb(state, this->AirWetBulb, 1.0, this->AirPress); // Enthalpy of entering moist air [J/kg]
    5461              : 
    5462              :         // initialize exiting wet bulb temperature before iterating on final solution
    5463        10074 :         Real64 OutletAirWetBulb = InletAirWetBulb + 6.0; // Wetbulb temp of exiting moist air [C]
    5464              : 
    5465              :         // Calculate mass flow rates
    5466        10074 :         if (waterMassFlowRate <= 0.0) {
    5467            0 :             OutletWaterTempLocal = this->InletWaterTemp;
    5468            0 :             return OutletWaterTempLocal;
    5469              :         }
    5470              : 
    5471        10074 :         Real64 MdotCpWater = waterMassFlowRate * CpWater; // Water mass flow rate times the heat capacity [W/K]
    5472              : 
    5473        10074 :         int Iter = 0;
    5474              :         Real64 OutletAirEnthalpy;                   // Enthalpy of exiting moist air [J/kg]
    5475        10074 :         Real64 WetBulbError = 1.0;                  // Calculated error for exiting wet-bulb temperature between iterations [delta K/K]
    5476        10074 :         Real64 DeltaTwb = 1.0;                      // Absolute value of difference between inlet and outlet air wet-bulb temp [C]
    5477              :         Real64 OutletAirWetBulbLast;                // temporary Wetbulb temp of exiting moist air [C]
    5478        10074 :         int constexpr IterMax(50);                  // Maximum number of iterations allowed
    5479        10074 :         Real64 constexpr WetBulbTolerance(0.00001); // Maximum error for exiting wet-bulb temperature between iterations [delta K/K]
    5480        10074 :         Real64 constexpr DeltaTwbTolerance(0.001);  // Maximum error (tolerance) in DeltaTwb for iteration convergence [C]
    5481        40131 :         while ((WetBulbError > WetBulbTolerance) && (Iter <= IterMax) && (DeltaTwb > DeltaTwbTolerance)) {
    5482        30057 :             ++Iter;
    5483              :             //        OutletAirEnthalpy = PsyHFnTdbRhPb(OutletAirWetBulb,1.0,OutBaroPress)
    5484        30057 :             OutletAirEnthalpy = Psychrometrics::PsyHFnTdbRhPb(state, OutletAirWetBulb, 1.0, this->AirPress);
    5485              :             // calculate the airside specific heat and capacity
    5486        30057 :             Real64 const CpAirside =
    5487        30057 :                 (OutletAirEnthalpy - InletAirEnthalpy) /
    5488        30057 :                 (OutletAirWetBulb - InletAirWetBulb);               // Delta enthalpy of the tower air divides by delta air wet-bulb temp [J/kg/K]
    5489        30057 :             Real64 const AirCapacity = AirMassFlowRate * CpAirside; // MdotCp of air through the tower
    5490              :             // calculate the minimum to maximum capacity ratios of airside and waterside
    5491        30057 :             Real64 const CapacityRatioMin = min(AirCapacity, MdotCpWater);    // Minimum capacity of airside and waterside
    5492        30057 :             Real64 const CapacityRatioMax = max(AirCapacity, MdotCpWater);    // Maximum capacity of airside and waterside
    5493        30057 :             Real64 const CapacityRatio = CapacityRatioMin / CapacityRatioMax; // Ratio of minimum to maximum capacity
    5494              :             // Calculate heat transfer coefficient and number of transfer units (NTU)
    5495        30057 :             Real64 const UAactual = UAdesign * CpAirside / CpAir;        // UA value at actual conditions [W/C]
    5496        30057 :             Real64 const NumTransferUnits = UAactual / CapacityRatioMin; // Number of transfer Units [NTU]
    5497              :             // calculate heat exchanger effectiveness
    5498              :             Real64 effectiveness; // Effectiveness of the heat exchanger [-]
    5499        30057 :             if (CapacityRatio <= 0.995) {
    5500        30057 :                 Real64 Exponent = NumTransferUnits * (1.0 - CapacityRatio);
    5501        30057 :                 if (Exponent >= 700.0) {
    5502           44 :                     effectiveness = NumTransferUnits / (1.0 + NumTransferUnits);
    5503              :                 } else {
    5504        30013 :                     effectiveness = (1.0 - std::exp(-1.0 * NumTransferUnits * (1.0 - CapacityRatio))) /
    5505        30013 :                                     (1.0 - CapacityRatio * std::exp(-1.0 * NumTransferUnits * (1.0 - CapacityRatio)));
    5506              :                 }
    5507              :             } else {
    5508            0 :                 effectiveness = NumTransferUnits / (1.0 + NumTransferUnits);
    5509              :             }
    5510              :             // calculate water to air heat transfer and store last exiting WB temp of air
    5511        30057 :             QactualLocal = effectiveness * CapacityRatioMin * (this->InletWaterTemp - InletAirWetBulb);
    5512        30057 :             OutletAirWetBulbLast = OutletAirWetBulb;
    5513              :             // calculate new exiting wet bulb temperature of airstream
    5514        30057 :             OutletAirWetBulb = InletAirWetBulb + QactualLocal / AirCapacity;
    5515              :             // Check error tolerance and exit if satisfied
    5516        30057 :             DeltaTwb = std::abs(OutletAirWetBulb - InletAirWetBulb);
    5517              :             // Add KelvinConv to denominator below convert OutletAirWetBulbLast to Kelvin to avoid divide by zero.
    5518              :             // Wet bulb error units are delta K/K
    5519        30057 :             WetBulbError = std::abs((OutletAirWetBulb - OutletAirWetBulbLast) / (OutletAirWetBulbLast + Constant::Kelvin));
    5520              :         }
    5521              : 
    5522        10074 :         if (QactualLocal >= 0.0) {
    5523        10074 :             OutletWaterTempLocal = this->InletWaterTemp - QactualLocal / MdotCpWater;
    5524              :         } else {
    5525            0 :             OutletWaterTempLocal = this->InletWaterTemp;
    5526              :         }
    5527        10074 :         return OutletWaterTempLocal;
    5528              :     }
    5529              : 
    5530            8 :     Real64 CoolingTower::calculateVariableTowerOutletTemp(EnergyPlusData &state,
    5531              :                                                           Real64 const WaterFlowRateRatio,    // current water flow rate ratio (capped if applicable)
    5532              :                                                           Real64 const airFlowRateRatioLocal, // current air flow rate ratio
    5533              :                                                           Real64 const Twb // current inlet air wet-bulb temperature (C, capped if applicable)
    5534              :     )
    5535              :     {
    5536              : 
    5537              :         // SUBROUTINE INFORMATION:
    5538              :         //       AUTHOR         Richard Raustad, FSEC
    5539              :         //       DATE WRITTEN   Feb. 2005
    5540              : 
    5541              :         // PURPOSE OF THIS SUBROUTINE:
    5542              :         // To calculate the leaving water temperature of the variable speed cooling tower.
    5543              : 
    5544              :         // METHODOLOGY EMPLOYED:
    5545              :         // The range temperature is varied to determine balance point where model output (Tapproach),
    5546              :         // range temperature and inlet air wet-bulb temperature show a balance as:
    5547              :         // Twb + Tapproach + Trange = Node(WaterInletNode)%Temp
    5548              : 
    5549              :         // REFERENCES:
    5550              :         // Benton, D.J., Bowmand, C.F., Hydeman, M., Miller, P.,
    5551              :         // "An Improved Cooling Tower Algorithm for the CoolToolsTM Simulation Model".
    5552              :         // ASHRAE Transactions 2002, V. 108, Pt. 1.
    5553              :         // York International Corporation, "YORKcalcTM Software, Chiller-Plant Energy-Estimating Program",
    5554              :         // Form 160.00-SG2 (0502). 2002.
    5555              : 
    5556              :         // SUBROUTINE PARAMETER DEFINITIONS:
    5557            8 :         int constexpr MaxIte(500);    // Maximum number of iterations
    5558            8 :         Real64 constexpr Acc(0.0001); // Accuracy of result
    5559              : 
    5560              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5561            8 :         Real64 constexpr VSTowerMaxRangeTemp(22.2222); // set VS cooling tower range maximum value used for solver
    5562              : 
    5563              :         // determine tower outlet water temperature
    5564              :         Real64 Tr; // range temperature which results in an energy balance
    5565           58 :         auto f = [&state, this, WaterFlowRateRatio, airFlowRateRatioLocal, Twb](Real64 Trange) {
    5566              :             // call model to determine approach temperature given other independent variables (range temp is being varied to find balance)
    5567           58 :             Real64 Tapproach = this->calculateVariableSpeedApproach(state, WaterFlowRateRatio, airFlowRateRatioLocal, Twb, Trange);
    5568              :             // calculate residual based on a balance where Twb + Ta + Tr = Inlet Water Temp
    5569           58 :             return (Twb + Tapproach + Trange) - this->WaterTemp;
    5570            8 :         };
    5571            8 :         int SolFla = 0;
    5572            8 :         General::SolveRoot(state, Acc, MaxIte, SolFla, Tr, f, 0.001, max(this->MaxRangeTemp, VSTowerMaxRangeTemp));
    5573              : 
    5574              :         // calculate outlet temperature
    5575            8 :         Real64 outletWaterTempLocal = this->WaterTemp - min(Tr, this->MaxRangeTemp);
    5576              : 
    5577            8 :         if (SolFla == -1) {
    5578            0 :             ShowSevereError(state, "Iteration limit exceeded in calculating tower nominal capacity at minimum air flow ratio");
    5579            0 :             ShowContinueError(
    5580              :                 state,
    5581              :                 "Design inlet air wet-bulb or approach temperature must be modified to achieve an acceptable range at the minimum air flow rate");
    5582            0 :             ShowContinueError(state, format("Cooling tower simulation failed to converge for tower {}", this->Name));
    5583            8 :         } else if (SolFla == -2) {
    5584              :             // bad starting value means that solution corresponds to a range that is beyond
    5585              :             // the bounds of the model; The maximum range is used here
    5586            1 :             outletWaterTempLocal = this->WaterTemp - this->MaxRangeTemp;
    5587            1 :             ++this->VSErrorCountTRCalc;
    5588            1 :             if (this->VSErrorCountTRCalc < 2) {
    5589            2 :                 ShowWarningError(
    5590              :                     state,
    5591            2 :                     format("The range for the cooling tower {} likely exceeds the bounds of the model. The maximum range of the model is used {}.",
    5592            1 :                            this->Name,
    5593            1 :                            this->MaxRangeTemp));
    5594            2 :                 ShowContinueError(state,
    5595            2 :                                   format(" ... Occurrence info = {}, {} {}",
    5596            1 :                                          state.dataEnvrn->EnvironmentName,
    5597            1 :                                          state.dataEnvrn->CurMnDy,
    5598            2 :                                          General::CreateSysTimeIntervalString(state)));
    5599              :             } else {
    5600            0 :                 ShowRecurringWarningErrorAtEnd(
    5601              :                     state,
    5602            0 :                     format("The range for the cooling tower {} likely exceeds the bounds of the model. The maximum range of the model is used {}",
    5603            0 :                            this->Name,
    5604            0 :                            this->MaxRangeTemp),
    5605            0 :                     this->ErrIndexTRCalc);
    5606              :             }
    5607              :         }
    5608            8 :         return outletWaterTempLocal;
    5609              :     }
    5610              : 
    5611           93 :     Real64 CoolingTower::calculateVariableSpeedApproach(EnergyPlusData &state,
    5612              :                                                         Real64 const PctWaterFlow,      // Water flow ratio of cooling tower
    5613              :                                                         Real64 const airFlowRatioLocal, // Air flow ratio of cooling tower
    5614              :                                                         Real64 const Twb,               // Inlet air wet-bulb temperature [C]
    5615              :                                                         Real64 const Tr // Cooling tower range (outlet water temp minus inlet air wet-bulb temp) [C]
    5616              :     )
    5617              :     {
    5618              :         // FUNCTION INFORMATION:
    5619              :         //       AUTHOR         Richard Raustad, FSEC
    5620              :         //       DATE WRITTEN   Feb. 2005
    5621              : 
    5622              :         // PURPOSE OF THIS FUNCTION:
    5623              :         // Calculate tower approach temperature (e.g. outlet water temp minus inlet air wet-bulb temp)
    5624              :         // given air flow ratio, water flow ratio, inlet air wet-bulb temp, and tower range.
    5625              : 
    5626              :         // METHODOLOGY EMPLOYED:
    5627              :         // Calculation method used empirical models from CoolTools or York to determine performance
    5628              :         // of variable speed (variable air flow rate) cooling towers.
    5629              : 
    5630              :         // REFERENCES:
    5631              :         // Benton, D.J., Bowmand, C.F., Hydeman, M., Miller, P.,
    5632              :         // "An Improved Cooling Tower Algorithm for the CoolToolsTM Simulation Model".
    5633              :         // ASHRAE Transactions 2002, V. 108, Pt. 1.
    5634              :         // York International Corporation, "YORKcalcTM Software, Chiller-Plant Energy-Estimating Program",
    5635              :         // Form 160.00-SG2 (0502). 2002.
    5636              : 
    5637           93 :         if (this->TowerModelType == ModelType::YorkCalcModel || this->TowerModelType == ModelType::YorkCalcUserDefined) {
    5638            2 :             Real64 PctAirFlow = airFlowRatioLocal;
    5639            2 :             Real64 FlowFactor = PctWaterFlow / PctAirFlow;
    5640            2 :             return this->Coeff[0] + this->Coeff[1] * Twb + this->Coeff[2] * Twb * Twb + this->Coeff[3] * Tr + this->Coeff[4] * Twb * Tr +
    5641            2 :                    this->Coeff[5] * Twb * Twb * Tr + this->Coeff[6] * Tr * Tr + this->Coeff[7] * Twb * Tr * Tr +
    5642            2 :                    this->Coeff[8] * Twb * Twb * Tr * Tr + this->Coeff[9] * FlowFactor + this->Coeff[10] * Twb * FlowFactor +
    5643            2 :                    this->Coeff[11] * Twb * Twb * FlowFactor + this->Coeff[12] * Tr * FlowFactor + this->Coeff[13] * Twb * Tr * FlowFactor +
    5644            2 :                    this->Coeff[14] * Twb * Twb * Tr * FlowFactor + this->Coeff[15] * Tr * Tr * FlowFactor +
    5645            2 :                    this->Coeff[16] * Twb * Tr * Tr * FlowFactor + this->Coeff[17] * Twb * Twb * Tr * Tr * FlowFactor +
    5646            2 :                    this->Coeff[18] * FlowFactor * FlowFactor + this->Coeff[19] * Twb * FlowFactor * FlowFactor +
    5647            2 :                    this->Coeff[20] * Twb * Twb * FlowFactor * FlowFactor + this->Coeff[21] * Tr * FlowFactor * FlowFactor +
    5648            2 :                    this->Coeff[22] * Twb * Tr * FlowFactor * FlowFactor + this->Coeff[23] * Twb * Twb * Tr * FlowFactor * FlowFactor +
    5649            2 :                    this->Coeff[24] * Tr * Tr * FlowFactor * FlowFactor + this->Coeff[25] * Twb * Tr * Tr * FlowFactor * FlowFactor +
    5650            2 :                    this->Coeff[26] * Twb * Twb * Tr * Tr * FlowFactor * FlowFactor;
    5651              : 
    5652              :         } else { // empirical model is CoolTools format
    5653              :             //     the CoolTools model actually uses PctFanPower = AirFlowRatio^3 as an input to the model
    5654           91 :             Real64 PctAirFlow = pow_3(airFlowRatioLocal);
    5655           91 :             return this->Coeff[0] + this->Coeff[1] * PctAirFlow + this->Coeff[2] * PctAirFlow * PctAirFlow +
    5656           91 :                    this->Coeff[3] * PctAirFlow * PctAirFlow * PctAirFlow + this->Coeff[4] * PctWaterFlow +
    5657           91 :                    this->Coeff[5] * PctAirFlow * PctWaterFlow + this->Coeff[6] * PctAirFlow * PctAirFlow * PctWaterFlow +
    5658           91 :                    this->Coeff[7] * PctWaterFlow * PctWaterFlow + this->Coeff[8] * PctAirFlow * PctWaterFlow * PctWaterFlow +
    5659           91 :                    this->Coeff[9] * PctWaterFlow * PctWaterFlow * PctWaterFlow + this->Coeff[10] * Twb + this->Coeff[11] * PctAirFlow * Twb +
    5660           91 :                    this->Coeff[12] * PctAirFlow * PctAirFlow * Twb + this->Coeff[13] * PctWaterFlow * Twb +
    5661           91 :                    this->Coeff[14] * PctAirFlow * PctWaterFlow * Twb + this->Coeff[15] * PctWaterFlow * PctWaterFlow * Twb +
    5662           91 :                    this->Coeff[16] * Twb * Twb + this->Coeff[17] * PctAirFlow * Twb * Twb + this->Coeff[18] * PctWaterFlow * Twb * Twb +
    5663           91 :                    this->Coeff[19] * Twb * Twb * Twb + this->Coeff[20] * Tr + this->Coeff[21] * PctAirFlow * Tr +
    5664           91 :                    this->Coeff[22] * PctAirFlow * PctAirFlow * Tr + this->Coeff[23] * PctWaterFlow * Tr +
    5665           91 :                    this->Coeff[24] * PctAirFlow * PctWaterFlow * Tr + this->Coeff[25] * PctWaterFlow * PctWaterFlow * Tr +
    5666           91 :                    this->Coeff[26] * Twb * Tr + this->Coeff[27] * PctAirFlow * Twb * Tr + this->Coeff[28] * PctWaterFlow * Twb * Tr +
    5667           91 :                    this->Coeff[29] * Twb * Twb * Tr + this->Coeff[30] * Tr * Tr + this->Coeff[31] * PctAirFlow * Tr * Tr +
    5668           91 :                    this->Coeff[32] * PctWaterFlow * Tr * Tr + this->Coeff[33] * Twb * Tr * Tr + this->Coeff[34] * Tr * Tr * Tr;
    5669              :         }
    5670              :     }
    5671              : 
    5672            2 :     void CoolingTower::checkModelBounds(EnergyPlusData &state,
    5673              :                                         Real64 Twb,                      // current inlet air wet-bulb temperature (C)
    5674              :                                         Real64 Tr,                       // requested range temperature for current time step (C)
    5675              :                                         Real64 Ta,                       // requested approach temperature for current time step (C)
    5676              :                                         Real64 WaterFlowRateRatio,       // current water flow rate ratio at water inlet node
    5677              :                                         Real64 &TwbCapped,               // bounded value of inlet air wet-bulb temperature (C)
    5678              :                                         Real64 &TrCapped,                // bounded value of range temperature (C)
    5679              :                                         Real64 &TaCapped,                // bounded value of approach temperature (C)
    5680              :                                         Real64 &WaterFlowRateRatioCapped // bounded value of water flow rate ratio
    5681              :     )
    5682              :     {
    5683              : 
    5684              :         // SUBROUTINE INFORMATION:
    5685              :         //       AUTHOR         Richard Raustad
    5686              :         //       DATE WRITTEN   Feb 2005
    5687              : 
    5688              :         // PURPOSE OF THIS SUBROUTINE:
    5689              :         // To verify that the empirical model's independent variables are within the limits used during the
    5690              :         // development of the empirical model.
    5691              : 
    5692              :         // METHODOLOGY EMPLOYED:
    5693              :         // The empirical models used for simulating a variable speed cooling tower are based on a limited data set.
    5694              :         // Extrapolation of empirical models can cause instability and the independent variables may need to be limited.
    5695              :         // The range of each independent variable is provided either by the CoolTools or York model limits, or
    5696              :         // specified by the user if the model is User Defined (in either the CoolTools or York model format).
    5697              :         // These limits are tested in this subroutine each time step and returned for use by the calling routine.
    5698              :         // The independent variables capped here may or may not be passed to the empirical model in the calling
    5699              :         // routine depending on their use.
    5700              : 
    5701              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5702            2 :         std::string OutputChar;   // character string for warning messages
    5703            2 :         std::string OutputCharLo; // character string for warning messages
    5704            2 :         std::string OutputCharHi; // character string for warning messages
    5705            2 :         std::string TrimValue;    // character string for warning messages
    5706              :         // current end time is compared with last to see if time step changed
    5707              : 
    5708              :         //   initialize capped variables in case independent variables are in bounds
    5709            2 :         TwbCapped = Twb;
    5710            2 :         TrCapped = Tr;
    5711            2 :         TaCapped = Ta;
    5712            2 :         WaterFlowRateRatioCapped = WaterFlowRateRatio;
    5713              : 
    5714              :         //   calculate end time of current time step
    5715            2 :         Real64 CurrentEndTime = state.dataGlobal->CurrentTime + state.dataHVACGlobal->SysTimeElapsed;
    5716              : 
    5717              :         //   Print warning messages only when valid and only for the first occurrence. Let summary provide statistics.
    5718              :         //   Wait for next time step to print warnings. If simulation iterates, print out
    5719              :         //   the warning for the last iteration only. Must wait for next time step to accomplish this.
    5720              :         //   If a warning occurs and the simulation down shifts, the warning is not valid.
    5721            2 :         if (CurrentEndTime > this->CurrentEndTimeLast && state.dataHVACGlobal->TimeStepSys >= this->TimeStepSysLast) {
    5722            0 :             if (this->PrintTrMessage) {
    5723            0 :                 ++this->VSErrorCountTR;
    5724            0 :                 if (this->VSErrorCountTR < 2) {
    5725            0 :                     ShowWarningError(state, this->TrBuffer1);
    5726            0 :                     ShowContinueError(state, this->TrBuffer2);
    5727            0 :                     ShowContinueError(state, this->TrBuffer3);
    5728            0 :                     ShowContinueError(state, " ...Range temperatures outside model boundaries may not adversely affect tower performance.");
    5729            0 :                     ShowContinueError(state, " ...This is not an unexpected occurrence when simulating actual conditions.");
    5730              :                 } else {
    5731            0 :                     ShowRecurringWarningErrorAtEnd(state,
    5732            0 :                                                    format("{} \"{}\" - Tower range temperature is out of range error continues...",
    5733            0 :                                                           DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    5734            0 :                                                           this->Name),
    5735            0 :                                                    this->ErrIndexTR,
    5736            0 :                                                    this->TrLast,
    5737            0 :                                                    this->TrLast);
    5738              :                 }
    5739              :             }
    5740            0 :             if (this->PrintTwbMessage) {
    5741            0 :                 ++this->VSErrorCountIAWB;
    5742            0 :                 if (this->VSErrorCountIAWB < 6) {
    5743            0 :                     ShowWarningError(state, this->TwbBuffer1);
    5744            0 :                     ShowContinueError(state, this->TwbBuffer2);
    5745            0 :                     ShowContinueError(state, this->TwbBuffer3);
    5746            0 :                     ShowContinueError(state, " ...Wet-bulb temperatures outside model boundaries may not adversely affect tower performance.");
    5747              :                 } else {
    5748            0 :                     ShowRecurringWarningErrorAtEnd(state,
    5749            0 :                                                    format("{} \"{}\" - Inlet air wet-bulb temperature is out of range error continues...",
    5750            0 :                                                           DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    5751            0 :                                                           this->Name),
    5752            0 :                                                    this->ErrIndexIAWB,
    5753            0 :                                                    this->TwbLast,
    5754            0 :                                                    this->TwbLast);
    5755              :                 }
    5756              :             }
    5757            0 :             if (this->PrintTaMessage) {
    5758            0 :                 ++this->VSErrorCountTA;
    5759            0 :                 if (this->VSErrorCountTA < 2) {
    5760            0 :                     ShowWarningError(state, this->TaBuffer1);
    5761            0 :                     ShowContinueError(state, this->TaBuffer2);
    5762            0 :                     ShowContinueError(state, this->TaBuffer3);
    5763            0 :                     ShowContinueError(state, " ...Approach temperatures outside model boundaries may not adversely affect tower performance.");
    5764            0 :                     ShowContinueError(state, " ...This is not an unexpected occurrence when simulating actual conditions.");
    5765              :                 } else {
    5766            0 :                     ShowRecurringWarningErrorAtEnd(state,
    5767            0 :                                                    format("{} \"{}\" - Tower approach temperature is out of range error continues...",
    5768            0 :                                                           DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    5769            0 :                                                           this->Name),
    5770            0 :                                                    this->ErrIndexTA,
    5771            0 :                                                    this->TaLast,
    5772            0 :                                                    this->TaLast);
    5773              :                 }
    5774              :             }
    5775            0 :             if (this->PrintWFRRMessage) {
    5776            0 :                 ++this->VSErrorCountWFRR;
    5777            0 :                 if (this->VSErrorCountWFRR < 6) {
    5778            0 :                     ShowWarningError(state, this->WFRRBuffer1);
    5779            0 :                     ShowContinueError(state, this->WFRRBuffer2);
    5780            0 :                     ShowContinueError(state, this->WFRRBuffer3);
    5781            0 :                     ShowContinueError(state, " ...Water flow rate ratios outside model boundaries may not adversely affect tower performance.");
    5782              :                 } else {
    5783            0 :                     ShowRecurringWarningErrorAtEnd(state,
    5784            0 :                                                    format("{} \"{}\" - Water flow rate ratio is out of range error continues...",
    5785            0 :                                                           DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    5786            0 :                                                           this->Name),
    5787            0 :                                                    this->ErrIndexWFRR,
    5788            0 :                                                    this->WaterFlowRateRatioLast,
    5789            0 :                                                    this->WaterFlowRateRatioLast);
    5790              :                 }
    5791              :             }
    5792              :         }
    5793              : 
    5794              :         //   save last system time step and last end time of current time step (used to determine if warning is valid)
    5795            2 :         this->TimeStepSysLast = state.dataHVACGlobal->TimeStepSys;
    5796            2 :         this->CurrentEndTimeLast = CurrentEndTime;
    5797              : 
    5798              :         //   check boundaries of independent variables and post warnings to individual buffers to print at end of time step
    5799            2 :         if (Twb < this->MinInletAirWBTemp || Twb > this->MaxInletAirWBTemp) {
    5800            0 :             OutputChar = format("{:.2R}", Twb);
    5801            0 :             OutputCharLo = format("{:.2R}", this->MinInletAirWBTemp);
    5802            0 :             OutputCharHi = format("{:.2R}", this->MaxInletAirWBTemp);
    5803            0 :             if (Twb < this->MinInletAirWBTemp) {
    5804            0 :                 TwbCapped = this->MinInletAirWBTemp;
    5805              :             }
    5806            0 :             if (Twb > this->MaxInletAirWBTemp) {
    5807            0 :                 TwbCapped = this->MaxInletAirWBTemp;
    5808              :             }
    5809            0 :             if (!state.dataGlobal->WarmupFlag) {
    5810            0 :                 this->PrintTwbMessage = true;
    5811            0 :                 this->TwbBuffer1 = format("{} \"{}\" - Inlet air wet-bulb temperature is outside model boundaries at {}.",
    5812            0 :                                           DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    5813            0 :                                           this->Name,
    5814            0 :                                           OutputChar);
    5815            0 :                 this->TwbBuffer2 = " ...Valid range = " + OutputCharLo + " to " + OutputCharHi +
    5816            0 :                                    ". Occurrence info = " + state.dataEnvrn->EnvironmentName + ", " + state.dataEnvrn->CurMnDy + ' ' +
    5817            0 :                                    General::CreateSysTimeIntervalString(state);
    5818            0 :                 TrimValue = format("{:.6R}", TwbCapped);
    5819            0 :                 this->TwbBuffer3 = " ...Inlet air wet-bulb temperature passed to the model = " + TrimValue;
    5820            0 :                 this->TwbLast = Twb;
    5821              :             } else {
    5822            0 :                 this->PrintTwbMessage = false;
    5823              :             }
    5824              :         } else {
    5825            2 :             this->PrintTwbMessage = false;
    5826              :         }
    5827              : 
    5828            2 :         if (Tr < this->MinRangeTemp || Tr > this->MaxRangeTemp) {
    5829            0 :             OutputChar = format("{:.2R}", Tr);
    5830            0 :             OutputCharLo = format("{:.2R}", this->MinRangeTemp);
    5831            0 :             OutputCharHi = format("{:.2R}", this->MaxRangeTemp);
    5832            0 :             if (Tr < this->MinRangeTemp) {
    5833            0 :                 TrCapped = this->MinRangeTemp;
    5834              :             }
    5835            0 :             if (Tr > this->MaxRangeTemp) {
    5836            0 :                 TrCapped = this->MaxRangeTemp;
    5837              :             }
    5838            0 :             if (!state.dataGlobal->WarmupFlag) {
    5839            0 :                 this->PrintTrMessage = true;
    5840            0 :                 this->TrBuffer1 = format("{} \"{}\" - Tower range temperature is outside model boundaries at {}.",
    5841            0 :                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    5842            0 :                                          this->Name,
    5843            0 :                                          OutputChar);
    5844            0 :                 this->TrBuffer2 = " ...Valid range = " + OutputCharLo + " to " + OutputCharHi +
    5845            0 :                                   ". Occurrence info = " + state.dataEnvrn->EnvironmentName + ", " + state.dataEnvrn->CurMnDy + ' ' +
    5846            0 :                                   General::CreateSysTimeIntervalString(state);
    5847            0 :                 TrimValue = format("{:.5R}", Tr);
    5848            0 :                 this->TrBuffer3 = " ...Tower range temperature passed to the model = " + TrimValue;
    5849            0 :                 this->TrLast = Tr;
    5850              :             } else {
    5851            0 :                 this->PrintTrMessage = false;
    5852              :             }
    5853              :         } else {
    5854            2 :             this->PrintTrMessage = false;
    5855              :         }
    5856              : 
    5857            2 :         if (Ta < this->MinApproachTemp || Ta > this->MaxApproachTemp) {
    5858            1 :             OutputChar = format("{:.2R}", Ta);
    5859            1 :             OutputCharLo = format("{:.2R}", this->MinApproachTemp);
    5860            1 :             OutputCharHi = format("{:.2R}", this->MaxApproachTemp);
    5861            1 :             if (Ta < this->MinApproachTemp) {
    5862            0 :                 TaCapped = this->MinApproachTemp;
    5863              :             }
    5864            1 :             if (Ta > this->MaxApproachTemp) {
    5865            1 :                 TaCapped = this->MaxApproachTemp;
    5866              :             }
    5867            2 :             if (!state.dataGlobal->WarmupFlag) {
    5868            1 :                 this->PrintTaMessage = true;
    5869            2 :                 this->TaBuffer1 = format("{} \"{}\" - Tower approach temperature is outside model boundaries at {}.",
    5870            1 :                                          DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    5871            1 :                                          this->Name,
    5872            1 :                                          OutputChar);
    5873            2 :                 this->TaBuffer2 = " ...Valid range = " + OutputCharLo + " to " + OutputCharHi +
    5874            3 :                                   ". Occurrence info = " + state.dataEnvrn->EnvironmentName + ", " + state.dataEnvrn->CurMnDy + ' ' +
    5875            3 :                                   General::CreateSysTimeIntervalString(state);
    5876            1 :                 TrimValue = format("{:.5R}", Ta);
    5877            1 :                 this->TaBuffer3 = " ...Tower approach temperature passed to the model = " + TrimValue;
    5878            1 :                 this->TaLast = Ta;
    5879              :             } else {
    5880            0 :                 this->PrintTaMessage = false;
    5881              :             }
    5882              :         } else {
    5883            1 :             this->PrintTaMessage = false;
    5884              :         }
    5885              : 
    5886            2 :         if (this->TowerModelType == ModelType::YorkCalcModel || this->TowerModelType == ModelType::YorkCalcUserDefined) {
    5887              :             //     Water flow rate ratio warning not valid for YorkCalc model, print liquid to gas ratio
    5888              :             //     warning instead (bottom of Subroutine VariableSpeedTower)
    5889            0 :             this->PrintWFRRMessage = false;
    5890              :         } else {
    5891            2 :             if (WaterFlowRateRatio < this->MinWaterFlowRatio || WaterFlowRateRatio > this->MaxWaterFlowRatio) {
    5892            2 :                 OutputChar = format("{:.2R}", WaterFlowRateRatio);
    5893            2 :                 OutputCharLo = format("{:.2R}", this->MinWaterFlowRatio);
    5894            2 :                 OutputCharHi = format("{:.2R}", this->MaxWaterFlowRatio);
    5895            2 :                 if (WaterFlowRateRatio < this->MinWaterFlowRatio) {
    5896            2 :                     WaterFlowRateRatioCapped = this->MinWaterFlowRatio;
    5897              :                 }
    5898            2 :                 if (WaterFlowRateRatio > this->MaxWaterFlowRatio) {
    5899            0 :                     WaterFlowRateRatioCapped = this->MaxWaterFlowRatio;
    5900              :                 }
    5901            4 :                 if (!state.dataGlobal->WarmupFlag) {
    5902            2 :                     this->PrintWFRRMessage = true;
    5903            4 :                     this->WFRRBuffer1 = format("{} \"{}\" - Water flow rate ratio is outside model boundaries at {}.",
    5904            2 :                                                DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    5905            2 :                                                this->Name,
    5906            2 :                                                OutputChar);
    5907            4 :                     this->WFRRBuffer2 = " ...Valid range = " + OutputCharLo + " to " + OutputCharHi +
    5908            6 :                                         ". Occurrence info = " + state.dataEnvrn->EnvironmentName + ", " + state.dataEnvrn->CurMnDy + ' ' +
    5909            6 :                                         General::CreateSysTimeIntervalString(state);
    5910            2 :                     TrimValue = format("{:.5R}", WaterFlowRateRatioCapped);
    5911            2 :                     this->WFRRBuffer3 = " ...Water flow rate ratio passed to the model = " + TrimValue;
    5912            2 :                     this->WaterFlowRateRatioLast = WaterFlowRateRatio;
    5913              :                 } else {
    5914            0 :                     this->PrintWFRRMessage = false;
    5915              :                 }
    5916              :             } else {
    5917            0 :                 this->PrintWFRRMessage = false;
    5918              :             }
    5919              :         }
    5920            2 :     }
    5921              : 
    5922        14199 :     void CoolingTower::calculateWaterUsage(EnergyPlusData &state)
    5923              :     {
    5924              : 
    5925              :         // SUBROUTINE INFORMATION:
    5926              :         //       AUTHOR         B. Griffith
    5927              :         //       DATE WRITTEN   August 2006
    5928              :         //       MODIFIED       T Hong, Aug. 2008. Added fluid bypass for single speed cooling tower
    5929              :         //                      A Flament, July 2010. Added multi-cell capability
    5930              : 
    5931              :         // PURPOSE OF THIS SUBROUTINE:
    5932              :         // Collect tower water usage calculations for reuse by all the tower models.
    5933              : 
    5934              :         // REFERENCES:
    5935              :         // Code for this routine started from VariableSpeedTower
    5936              : 
    5937              :         // SUBROUTINE PARAMETER DEFINITIONS:
    5938              :         static constexpr std::string_view RoutineName("calculateWaterUsage");
    5939              : 
    5940        14199 :         Real64 EvapVdot = 0.0;
    5941        14199 :         Real64 AverageWaterTemp = (this->InletWaterTemp + this->OutletWaterTemp) / 2.0;
    5942              : 
    5943              :         // Set water and air properties
    5944        14199 :         if (this->EvapLossMode == EvapLoss::MoistTheory) {
    5945              : 
    5946        14198 :             Real64 const AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(state, this->AirPress, this->AirTemp, this->AirHumRat);
    5947        14198 :             Real64 const AirMassFlowRate = this->airFlowRateRatio * this->HighSpeedAirFlowRate * AirDensity * this->NumCellOn / this->NumCell;
    5948        14198 :             Real64 const InletAirEnthalpy = Psychrometrics::PsyHFnTdbRhPb(state, this->AirWetBulb, 1.0, this->AirPress);
    5949              : 
    5950        14198 :             if (AirMassFlowRate > 0.0) {
    5951              :                 // Calculate outlet air conditions for determining water usage
    5952              : 
    5953         8473 :                 Real64 const OutletAirEnthalpy = InletAirEnthalpy + this->Qactual / AirMassFlowRate;
    5954         8473 :                 Real64 const OutletAirTSat = Psychrometrics::PsyTsatFnHPb(state, OutletAirEnthalpy, this->AirPress);
    5955         8473 :                 Real64 const OutletAirHumRatSat = Psychrometrics::PsyWFnTdbH(state, OutletAirTSat, OutletAirEnthalpy);
    5956              : 
    5957              :                 // calculate specific humidity ratios (HUMRAT to mass of moist air not dry air)
    5958         8473 :                 Real64 const InSpecificHumRat = this->AirHumRat / (1 + this->AirHumRat);
    5959         8473 :                 Real64 const OutSpecificHumRat = OutletAirHumRatSat / (1 + OutletAirHumRatSat);
    5960              : 
    5961              :                 // calculate average air temp for density call
    5962         8473 :                 Real64 const TairAvg = (this->AirTemp + OutletAirTSat) / 2.0;
    5963              : 
    5964              :                 // Amount of water evaporated, get density water at air temp or 4 C if too cold
    5965         8473 :                 Real64 const rho = this->plantLoc.loop->glycol->getDensity(state, max(TairAvg, 4.0), RoutineName);
    5966              : 
    5967         8473 :                 EvapVdot = (AirMassFlowRate * (OutSpecificHumRat - InSpecificHumRat)) / rho; // [m3/s]
    5968         8473 :                 if (EvapVdot < 0.0) EvapVdot = 0.0;
    5969              :             } else {
    5970         5725 :                 EvapVdot = 0.0;
    5971              :             }
    5972              : 
    5973            1 :         } else if (this->EvapLossMode == EvapLoss::UserFactor) {
    5974            1 :             Real64 const rho = this->plantLoc.loop->glycol->getDensity(state, AverageWaterTemp, RoutineName);
    5975              : 
    5976            1 :             EvapVdot = this->UserEvapLossFactor * (this->InletWaterTemp - this->OutletWaterTemp) * (this->WaterMassFlowRate / rho);
    5977            1 :             if (EvapVdot < 0.0) EvapVdot = 0.0;
    5978              :         } else {
    5979              :             // should never come here
    5980              :         }
    5981              : 
    5982              :         //   amount of water lost due to drift
    5983        14199 :         Real64 driftVdot = this->DesignWaterFlowRate * this->NumCellOn / this->NumCell * this->DriftLossFraction * this->airFlowRateRatio;
    5984              : 
    5985        14199 :         Real64 BlowDownVdot(0.0);
    5986        14199 :         if (this->BlowdownMode == Blowdown::Schedule) {
    5987              :             // Amount of water lost due to blow down (purging contaminants from tower basin)
    5988            0 :             BlowDownVdot = (this->blowdownSched != nullptr) ? this->blowdownSched->getCurrentVal() : 0.0;
    5989        14199 :         } else if (this->BlowdownMode == Blowdown::Concentration) {
    5990        14199 :             if (this->ConcentrationRatio > 2.0) { // protect divide by zero
    5991        14199 :                 BlowDownVdot = EvapVdot / (this->ConcentrationRatio - 1) - driftVdot;
    5992              :             } else {
    5993            0 :                 BlowDownVdot = EvapVdot - driftVdot;
    5994              :             }
    5995        14199 :             if (BlowDownVdot < 0.0) BlowDownVdot = 0.0;
    5996              :         } else {
    5997              :             // should never come here
    5998              :         }
    5999              : 
    6000              :         // Added for fluid bypass
    6001        14199 :         if (this->CapacityControl == CapacityCtrl::FluidBypass) {
    6002          106 :             if (this->EvapLossMode == EvapLoss::UserFactor) EvapVdot *= (1 - this->BypassFraction);
    6003          106 :             driftVdot *= (1 - this->BypassFraction);
    6004          106 :             BlowDownVdot *= (1 - this->BypassFraction);
    6005              :         }
    6006              : 
    6007        14199 :         Real64 const makeUpVdot = EvapVdot + driftVdot + BlowDownVdot;
    6008              : 
    6009              :         // set demand request in Water Storage if needed
    6010        14199 :         Real64 StarvedVdot = 0.0;
    6011        14199 :         Real64 tankSupplyVdot = 0.0;
    6012        14199 :         if (this->SuppliedByWaterSystem) {
    6013              : 
    6014              :             // set demand request
    6015            0 :             state.dataWaterData->WaterStorage(this->WaterTankID).VdotRequestDemand(this->WaterTankDemandARRID) = makeUpVdot;
    6016              : 
    6017            0 :             Real64 const AvailTankVdot = state.dataWaterData->WaterStorage(this->WaterTankID)
    6018            0 :                                              .VdotAvailDemand(this->WaterTankDemandARRID); // check what tank can currently provide
    6019              : 
    6020            0 :             tankSupplyVdot = makeUpVdot;      // init
    6021            0 :             if (AvailTankVdot < makeUpVdot) { // calculate starved flow
    6022            0 :                 StarvedVdot = makeUpVdot - AvailTankVdot;
    6023            0 :                 tankSupplyVdot = AvailTankVdot;
    6024              :             }
    6025              :         } else { // supplied by mains
    6026              :         }
    6027              : 
    6028              :         //   total water usage
    6029              :         // update report variables
    6030        14199 :         this->EvaporationVdot = EvapVdot;
    6031        14199 :         this->EvaporationVol = EvapVdot * (state.dataHVACGlobal->TimeStepSysSec);
    6032        14199 :         this->DriftVdot = driftVdot;
    6033        14199 :         this->DriftVol = driftVdot * (state.dataHVACGlobal->TimeStepSysSec);
    6034        14199 :         this->BlowdownVdot = BlowDownVdot;
    6035        14199 :         this->BlowdownVol = BlowDownVdot * (state.dataHVACGlobal->TimeStepSysSec);
    6036        14199 :         this->MakeUpVdot = makeUpVdot;
    6037        14199 :         this->MakeUpVol = makeUpVdot * (state.dataHVACGlobal->TimeStepSysSec);
    6038        14199 :         this->TankSupplyVdot = tankSupplyVdot;
    6039        14199 :         this->TankSupplyVol = tankSupplyVdot * (state.dataHVACGlobal->TimeStepSysSec);
    6040        14199 :         this->StarvedMakeUpVdot = StarvedVdot;
    6041        14199 :         this->StarvedMakeUpVol = StarvedVdot * (state.dataHVACGlobal->TimeStepSysSec);
    6042        14199 :         this->coolingTowerApproach = this->OutletWaterTemp - this->AirWetBulb;
    6043        14199 :         this->coolingTowerRange = this->InletWaterTemp - this->OutletWaterTemp;
    6044        14199 :     }
    6045              : 
    6046        14201 :     void CoolingTower::update(EnergyPlusData &state)
    6047              :     {
    6048              : 
    6049              :         // SUBROUTINE INFORMATION:
    6050              :         //       AUTHOR:          Dan Fisher
    6051              :         //       DATE WRITTEN:    October 1998
    6052              : 
    6053              :         // PURPOSE OF THIS SUBROUTINE:
    6054              :         // This subroutine is for passing results to the outlet water node.
    6055              : 
    6056              :         // set node information
    6057        14201 :         PlantUtilities::SafeCopyPlantNode(state, this->WaterInletNodeNum, this->WaterOutletNodeNum);
    6058        14201 :         state.dataLoopNodes->Node(this->WaterOutletNodeNum).Temp = this->OutletWaterTemp;
    6059              : 
    6060        14201 :         if (this->plantLoc.side->FlowLock == DataPlant::FlowLock::Unlocked || state.dataGlobal->WarmupFlag) return;
    6061              : 
    6062              :         // Check flow rate through tower and compare to design flow rate, show warning if greater than Design * Multiplier
    6063          960 :         if (state.dataLoopNodes->Node(this->WaterOutletNodeNum).MassFlowRate > this->DesWaterMassFlowRate * this->TowerMassFlowRateMultiplier) {
    6064            0 :             ++this->HighMassFlowErrorCount;
    6065            0 :             if (this->HighMassFlowErrorCount < 2) {
    6066            0 :                 ShowWarningError(state, format("{} \"{}\"", DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)], this->Name));
    6067            0 :                 ShowContinueError(state, " Condenser Loop Mass Flow Rate is much greater than the towers design mass flow rate.");
    6068            0 :                 ShowContinueError(
    6069            0 :                     state, format(" Condenser Loop Mass Flow Rate = {:.6T}", state.dataLoopNodes->Node(this->WaterOutletNodeNum).MassFlowRate));
    6070            0 :                 ShowContinueError(state, format(" Tower Design Mass Flow Rate   = {:.6T}", this->DesWaterMassFlowRate));
    6071            0 :                 ShowContinueErrorTimeStamp(state, "");
    6072              :             } else {
    6073            0 :                 ShowRecurringWarningErrorAtEnd(
    6074              :                     state,
    6075            0 :                     format("{} \"{}\"  Condenser Loop Mass Flow Rate is much greater than the towers design mass flow rate error continues...",
    6076            0 :                            DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    6077            0 :                            this->Name),
    6078            0 :                     this->HighMassFlowErrorIndex,
    6079            0 :                     state.dataLoopNodes->Node(this->WaterOutletNodeNum).MassFlowRate,
    6080            0 :                     state.dataLoopNodes->Node(this->WaterOutletNodeNum).MassFlowRate);
    6081              :             }
    6082              :         }
    6083              : 
    6084              :         // Check if OutletWaterTemp is below the minimum condenser loop temp and warn user
    6085          960 :         Real64 const LoopMinTemp = this->plantLoc.loop->MinTemp;
    6086          960 :         bool const outletWaterTempTooLow = this->OutletWaterTemp < LoopMinTemp;
    6087          960 :         bool const flowIsOn = this->WaterMassFlowRate > 0.0;
    6088          960 :         if (outletWaterTempTooLow && flowIsOn) {
    6089            0 :             ++this->OutletWaterTempErrorCount;
    6090            0 :             if (this->OutletWaterTempErrorCount < 2) {
    6091            0 :                 ShowWarningError(state, format("{} \"{}\"", DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)], this->Name));
    6092            0 :                 ShowContinueError(
    6093              :                     state,
    6094            0 :                     format("Cooling tower water outlet temperature ({:.2F} C) is below the specified minimum condenser loop temp of {:.2F} C",
    6095            0 :                            this->OutletWaterTemp,
    6096              :                            LoopMinTemp));
    6097            0 :                 ShowContinueErrorTimeStamp(state, "");
    6098              :             } else {
    6099            0 :                 ShowRecurringWarningErrorAtEnd(
    6100              :                     state,
    6101            0 :                     format("{} \"{}\" Cooling tower water outlet temperature is below the specified minimum condenser loop temp error continues...",
    6102            0 :                            DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    6103            0 :                            this->Name),
    6104            0 :                     this->OutletWaterTempErrorIndex,
    6105            0 :                     this->OutletWaterTemp,
    6106            0 :                     this->OutletWaterTemp);
    6107              :             }
    6108              :         }
    6109              : 
    6110              :         // Check if water mass flow rate is small (e.g. no flow) and warn user
    6111          960 :         if (this->WaterMassFlowRate > 0.0 && this->WaterMassFlowRate <= DataBranchAirLoopPlant::MassFlowTolerance) {
    6112            0 :             ++this->SmallWaterMassFlowErrorCount;
    6113            0 :             if (this->SmallWaterMassFlowErrorCount < 2) {
    6114            0 :                 ShowWarningError(state, format("{} \"{}\"", DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)], this->Name));
    6115            0 :                 ShowContinueError(state, "Cooling tower water mass flow rate near zero.");
    6116            0 :                 ShowContinueErrorTimeStamp(state, "");
    6117            0 :                 ShowContinueError(state, format("Actual Mass flow = {:.2T}", this->WaterMassFlowRate));
    6118              :             } else {
    6119            0 :                 ShowRecurringWarningErrorAtEnd(state,
    6120            0 :                                                format("{} \"{}\"  Cooling tower water mass flow rate near zero error continues...",
    6121            0 :                                                       DataPlant::PlantEquipTypeNames[static_cast<int>(this->TowerType)],
    6122            0 :                                                       this->Name),
    6123            0 :                                                this->SmallWaterMassFlowErrorIndex,
    6124            0 :                                                this->WaterMassFlowRate,
    6125            0 :                                                this->WaterMassFlowRate);
    6126              :             }
    6127              :         }
    6128              :     }
    6129              : 
    6130        14201 :     void CoolingTower::report(EnergyPlusData &state, bool const RunFlag)
    6131              :     {
    6132              : 
    6133              :         // SUBROUTINE INFORMATION:
    6134              :         //       AUTHOR:          Dan Fisher
    6135              :         //       DATE WRITTEN:    October 1998
    6136              : 
    6137              :         // PURPOSE OF THIS SUBROUTINE:
    6138              :         // This subroutine updates the report variables for the tower.
    6139              : 
    6140        14201 :         Real64 const ReportingConstant = state.dataHVACGlobal->TimeStepSysSec;
    6141              : 
    6142        14201 :         if (!RunFlag) {
    6143         5711 :             this->InletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp;
    6144         5711 :             this->OutletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp;
    6145         5711 :             this->Qactual = 0.0;
    6146         5711 :             this->FanPower = 0.0;
    6147         5711 :             this->FanEnergy = 0.0;
    6148         5711 :             this->AirFlowRatio = 0.0;
    6149         5711 :             this->WaterAmountUsed = 0.0;
    6150         5711 :             this->BasinHeaterConsumption = this->BasinHeaterPower * ReportingConstant;
    6151         5711 :             this->FanCyclingRatio = 0.0;
    6152         5711 :             this->BypassFraction = 0.0; // added for fluid bypass
    6153         5711 :             this->NumCellOn = 0;
    6154         5711 :             this->SpeedSelected = 0;
    6155              :         } else {
    6156         8490 :             this->InletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp;
    6157         8490 :             this->FanEnergy = this->FanPower * ReportingConstant;
    6158         8490 :             this->AirFlowRatio = this->airFlowRateRatio;
    6159         8490 :             this->WaterAmountUsed = this->WaterUsage * ReportingConstant;
    6160         8490 :             this->BasinHeaterConsumption = this->BasinHeaterPower * ReportingConstant;
    6161              :         }
    6162        14201 :     }
    6163              : 
    6164        14038 :     void CoolingTower::checkMassFlowAndLoad(EnergyPlusData &state, Real64 const MyLoad, bool RunFlag, bool &returnFlagSet)
    6165              :     {
    6166        14038 :         if ((MyLoad > -HVAC::SmallLoad) || !RunFlag) {
    6167              :             // tower doesn't need to do anything
    6168         5565 :             this->OutletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp;
    6169         5565 :             this->FanPower = 0.0;
    6170         5565 :             this->airFlowRateRatio = 0.0;
    6171         5565 :             this->Qactual = 0.0;
    6172         5565 :             this->WaterMassFlowRate = 0.0;
    6173         5565 :             PlantUtilities::SetComponentFlowRate(state, this->WaterMassFlowRate, this->WaterInletNodeNum, this->WaterOutletNodeNum, this->plantLoc);
    6174         5565 :             CalcBasinHeaterPower(
    6175         5565 :                 state, this->BasinHeaterPowerFTempDiff, this->basinHeaterSched, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
    6176         5565 :             returnFlagSet = true;
    6177         8473 :         } else if (this->WaterMassFlowRate <= DataBranchAirLoopPlant::MassFlowTolerance) {
    6178              :             // for multiple cells, we assume that it's a common basin
    6179            1 :             CalcBasinHeaterPower(
    6180            1 :                 state, this->BasinHeaterPowerFTempDiff, this->basinHeaterSched, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
    6181            1 :             returnFlagSet = true;
    6182              :         }
    6183        14038 :     }
    6184              : 
    6185            0 :     Real64 CoolingTower::getDynamicMaxCapacity(EnergyPlusData &state)
    6186              :     {
    6187              :         // TODO: does not include faults object impact
    6188              :         static constexpr std::string_view routineName("getDynamicMaxCapacity");
    6189            0 :         Real64 outletWaterTemp = 0.0;
    6190            0 :         Real64 constexpr designWetBulb = 25.56;
    6191            0 :         Real64 constexpr airFlowRateRatio = 1.0;
    6192            0 :         Real64 constexpr waterFlowRateRatio = 1.0;
    6193              :         Real64 const CpWater =
    6194            0 :             this->plantLoc.loop->glycol->getSpecificHeat(state, state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp, routineName);
    6195              :         // use operating max (i.e., at current plant flow rates, could be 0 if plant is off) or max available capacity?
    6196              :         // Real64 waterMassFlowRate = state.dataLoopNodes->Node(this->WaterInletNodeNum).MassFlowRateMaxAvail;
    6197            0 :         Real64 waterMassFlowRate = this->DesWaterMassFlowRate;
    6198            0 :         this->AirWetBulb = (this->OutdoorAirInletNodeNum > 0) ? state.dataLoopNodes->Node(this->OutdoorAirInletNodeNum).OutAirWetBulb
    6199            0 :                                                               : state.dataEnvrn->OutWetBulbTemp;
    6200              : 
    6201            0 :         switch (this->TowerType) {
    6202            0 :         case DataPlant::PlantEquipmentType::CoolingTower_SingleSpd:
    6203              :         case DataPlant::PlantEquipmentType::CoolingTower_TwoSpd: {
    6204              :             // only needed for calculateSimpleTowerOutletTemp
    6205            0 :             this->AirTemp =
    6206            0 :                 (this->OutdoorAirInletNodeNum > 0) ? state.dataLoopNodes->Node(this->OutdoorAirInletNodeNum).Temp : state.dataEnvrn->OutDryBulbTemp;
    6207            0 :             Real64 WaterMassFlowRatePerCell = waterMassFlowRate / this->NumCell;
    6208            0 :             Real64 UAdesign = this->HighSpeedTowerUA / this->NumCell; // could save these calculations in e.g., this->DesUAPerCell
    6209            0 :             Real64 AirFlowRate = this->HighSpeedAirFlowRate / this->NumCell;
    6210            0 :             outletWaterTemp = this->calculateSimpleTowerOutletTemp(state, WaterMassFlowRatePerCell, AirFlowRate, UAdesign);
    6211            0 :         } break;
    6212            0 :         case DataPlant::PlantEquipmentType::CoolingTower_VarSpd: {
    6213              :             Real64 TrCapped; // range temp passed to VS tower model
    6214              :             Real64 TaCapped; // approach temp passed to VS tower model
    6215            0 :             Real64 Twb = this->AirWetBulb;
    6216            0 :             Real64 TwbCapped = this->AirWetBulb;
    6217              :             // water temperature setpoint
    6218            0 :             Real64 TempSetPoint(0.0); // Outlet water temperature setpoint (C)
    6219            0 :             switch (this->plantLoc.loop->LoopDemandCalcScheme) {
    6220            0 :             case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
    6221            0 :                 TempSetPoint = this->plantLoc.side->TempSetPoint;
    6222            0 :             } break;
    6223            0 :             case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
    6224            0 :                 TempSetPoint = this->plantLoc.side->TempSetPointHi;
    6225            0 :             } break;
    6226            0 :             default: {
    6227            0 :                 assert(false);
    6228              :             } break;
    6229              :             }
    6230            0 :             Real64 Tr = state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp - TempSetPoint;
    6231            0 :             Real64 Ta = TempSetPoint - this->AirWetBulb;
    6232            0 :             Real64 waterFlowRateRatioCapped = 0.0; // Water flow rate ratio passed to VS tower model
    6233              :             // check independent inputs with respect to model boundaries
    6234            0 :             this->checkModelBounds(state, Twb, Tr, Ta, waterFlowRateRatio, TwbCapped, TrCapped, TaCapped, waterFlowRateRatioCapped);
    6235            0 :             outletWaterTemp = this->calculateVariableTowerOutletTemp(state, waterFlowRateRatioCapped, airFlowRateRatio, TwbCapped);
    6236            0 :         } break;
    6237            0 :         case DataPlant::PlantEquipmentType::CoolingTower_VarSpdMerkel: {
    6238              :             // only needed for calculateSimpleTowerOutletTemp
    6239            0 :             this->AirTemp =
    6240            0 :                 (this->OutdoorAirInletNodeNum > 0) ? state.dataLoopNodes->Node(this->OutdoorAirInletNodeNum).Temp : state.dataEnvrn->OutDryBulbTemp;
    6241            0 :             Real64 const UAdesignPerCell = this->HighSpeedTowerUA / this->NumCell;
    6242            0 :             Real64 const airFlowRatePerCell = this->HighSpeedAirFlowRate / this->NumCell;
    6243            0 :             Real64 const waterMassFlowRatePerCell = waterMassFlowRate / this->NumCell;
    6244            0 :             Real64 const WaterFlowRateRatio = waterMassFlowRatePerCell / this->DesWaterMassFlowRatePerCell; // this should always be 1 ?
    6245            0 :             Real64 const UAwetbulbAdjFac = Curve::CurveValue(state, this->UAModFuncWetBulbDiffCurvePtr, (designWetBulb - this->AirWetBulb));
    6246            0 :             Real64 const UAairflowAdjFac = Curve::CurveValue(state, this->UAModFuncAirFlowRatioCurvePtr, airFlowRateRatio);
    6247            0 :             Real64 const UAwaterflowAdjFac = Curve::CurveValue(state, this->UAModFuncWaterFlowRatioCurvePtr, WaterFlowRateRatio);
    6248            0 :             Real64 const UAadjustedPerCell = UAdesignPerCell * UAwetbulbAdjFac * UAairflowAdjFac * UAwaterflowAdjFac;
    6249            0 :             outletWaterTemp = this->calculateSimpleTowerOutletTemp(state, waterMassFlowRatePerCell, airFlowRatePerCell, UAadjustedPerCell);
    6250            0 :         } break;
    6251            0 :         default:
    6252            0 :             assert(false);
    6253              :         }
    6254            0 :         return waterMassFlowRate * CpWater * (state.dataLoopNodes->Node(this->WaterInletNodeNum).Temp - outletWaterTemp);
    6255              :     }
    6256              : 
    6257              : } // namespace CondenserLoopTowers
    6258              : 
    6259              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1