LCOV - code coverage report
Current view: top level - EnergyPlus - CondenserLoopTowers.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 2144 3471 61.8 %
Date: 2023-01-17 19:17:23 Functions: 35 38 92.1 %

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

Generated by: LCOV version 1.13