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

Generated by: LCOV version 2.0-1