LCOV - code coverage report
Current view: top level - EnergyPlus - CoolTower.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 264 415 63.6 %
Date: 2024-08-23 23:50:59 Functions: 5 5 100.0 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // C++ Headers
      49             : #include <cmath>
      50             : 
      51             : // ObjexxFCL Headers
      52             : #include <ObjexxFCL/Fmath.hh>
      53             : 
      54             : // EnergyPlus Headers
      55             : #include <EnergyPlus/CoolTower.hh>
      56             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      57             : #include <EnergyPlus/DataEnvironment.hh>
      58             : #include <EnergyPlus/DataHVACGlobals.hh>
      59             : #include <EnergyPlus/DataHeatBalance.hh>
      60             : #include <EnergyPlus/DataIPShortCuts.hh>
      61             : #include <EnergyPlus/DataWater.hh>
      62             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      63             : #include <EnergyPlus/OutputProcessor.hh>
      64             : #include <EnergyPlus/Psychrometrics.hh>
      65             : #include <EnergyPlus/ScheduleManager.hh>
      66             : #include <EnergyPlus/UtilityRoutines.hh>
      67             : #include <EnergyPlus/WaterManager.hh>
      68             : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      69             : 
      70             : namespace EnergyPlus {
      71             : 
      72             : namespace CoolTower {
      73             :     // Module containing the data for cooltower system
      74             : 
      75             :     // MODULE INFORMATION:
      76             :     //       AUTHOR         Daeho Kang
      77             :     //       DATE WRITTEN   Aug 2008
      78             :     //       MODIFIED       na
      79             :     //       RE-ENGINEERED  na
      80             : 
      81             :     // PURPOSE OF THIS MODULE:
      82             :     // To encapsulate the data and algorithms required to manage the cooltower component.
      83             : 
      84             :     // REFERENCES:
      85             :     // Baruch Givoni. 1994. Passive and Low Energy Cooling of Buildings. Chapter 5: Evaporative Cooling Systems.
      86             :     //     John Wiley & Sons, Inc.
      87             :     // OTHER NOTES: none
      88             : 
      89             :     // Using/Aliasing
      90             :     using namespace DataHeatBalance;
      91             : 
      92             :     constexpr std::array<std::string_view, static_cast<int>(FlowCtrl::Num)> FlowCtrlNamesUC{"WATERFLOWSCHEDULE", "WINDDRIVENFLOW"};
      93             : 
      94     3728073 :     void ManageCoolTower(EnergyPlusData &state)
      95             :     {
      96             : 
      97             :         // SUBROUTINE INFORMATION:
      98             :         //       AUTHOR         Daeho Kang
      99             :         //       DATE WRITTEN   Aug 2008
     100             : 
     101             :         // PURPOSE OF THIS SUBROUTINE:
     102             :         // This subroutine manages the simulation of Cooltower component.
     103             :         // This driver manages the calls to all of the other drivers and simulation algorithms.
     104             : 
     105             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     106             : 
     107             :         // Obtains and allocates heat balance related parameters from input
     108     3728073 :         if (state.dataCoolTower->GetInputFlag) {
     109         763 :             GetCoolTower(state);
     110         763 :             state.dataCoolTower->GetInputFlag = false;
     111             :         }
     112             : 
     113     3728073 :         if ((int)state.dataCoolTower->CoolTowerSys.size() == 0) return;
     114             : 
     115        3580 :         CalcCoolTower(state);
     116             : 
     117        3580 :         UpdateCoolTower(state);
     118             : 
     119        3580 :         ReportCoolTower(state);
     120             :     }
     121             : 
     122         763 :     void GetCoolTower(EnergyPlusData &state)
     123             :     {
     124             : 
     125             :         // SUBROUTINE INFORMATION:
     126             :         //       AUTHOR         Daeho Kang
     127             :         //       DATE WRITTEN   Aug 2008
     128             : 
     129             :         // PURPOSE OF THIS SUBROUTINE:
     130             :         // This subroutine gets input data for cooltower components
     131             :         // and stores it in the Cooltower data structure.
     132             : 
     133             :         // SUBROUTINE PARAMETER DEFINITIONS:
     134         763 :         static std::string const CurrentModuleObject("ZoneCoolTower:Shower");
     135         763 :         Real64 constexpr MaximumWaterFlowRate(0.016667); // Maximum limit of water flow rate in m3/s (1000 l/min)
     136         763 :         Real64 constexpr MinimumWaterFlowRate(0.0);      // Minimum limit of water flow rate
     137         763 :         Real64 constexpr MaxHeight(30.0);                // Maximum effective tower height in m
     138         763 :         Real64 constexpr MinHeight(1.0);                 // Minimum effective tower height in m
     139         763 :         Real64 constexpr MaxValue(100.0);                // Maximum limit of outlet area, airflow, and temperature
     140         763 :         Real64 constexpr MinValue(0.0);                  // Minimum limit of outlet area, airflow, and temperature
     141         763 :         Real64 constexpr MaxFrac(1.0);                   // Maximum fraction
     142         763 :         Real64 constexpr MinFrac(0.0);                   // Minimum fraction
     143             : 
     144             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     145         763 :         bool ErrorsFound(false); // If errors detected in input
     146             :         int NumAlphas;           // Number of Alphas for each GetobjectItem call
     147             :         int NumNumbers;          // Number of Numbers for each GetobjectItem call
     148             :         int NumArgs;
     149             :         int IOStat;
     150         763 :         Array1D_string cAlphaArgs;     // Alpha input items for object
     151         763 :         Array1D_string cAlphaFields;   // Alpha field names
     152         763 :         Array1D_string cNumericFields; // Numeric field names
     153         763 :         Array1D<Real64> rNumericArgs;  // Numeric input items for object
     154         763 :         Array1D_bool lAlphaBlanks;     // Logical array, alpha field input BLANK = .TRUE.
     155         763 :         Array1D_bool lNumericBlanks;   // Logical array, numeric field input BLANK = .TRUE.
     156             : 
     157             :         // Initializations and allocations
     158         763 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumArgs, NumAlphas, NumNumbers);
     159         763 :         cAlphaArgs.allocate(NumAlphas);
     160         763 :         cAlphaFields.allocate(NumAlphas);
     161         763 :         cNumericFields.allocate(NumNumbers);
     162         763 :         rNumericArgs.dimension(NumNumbers, 0.0);
     163         763 :         lAlphaBlanks.dimension(NumAlphas, true);
     164         763 :         lNumericBlanks.dimension(NumNumbers, true);
     165             : 
     166         763 :         auto &Zone(state.dataHeatBal->Zone);
     167             : 
     168         763 :         int NumCoolTowers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     169             : 
     170         763 :         state.dataCoolTower->CoolTowerSys.allocate(NumCoolTowers);
     171             : 
     172             :         // Obtain inputs
     173         768 :         for (int CoolTowerNum = 1; CoolTowerNum <= NumCoolTowers; ++CoolTowerNum) {
     174             : 
     175          10 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     176             :                                                                      CurrentModuleObject,
     177             :                                                                      CoolTowerNum,
     178           5 :                                                                      state.dataIPShortCut->cAlphaArgs,
     179             :                                                                      NumAlphas,
     180           5 :                                                                      state.dataIPShortCut->rNumericArgs,
     181             :                                                                      NumNumbers,
     182             :                                                                      IOStat,
     183             :                                                                      lNumericBlanks,
     184             :                                                                      lAlphaBlanks,
     185             :                                                                      cAlphaFields,
     186             :                                                                      cNumericFields);
     187           5 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).Name = state.dataIPShortCut->cAlphaArgs(1);     // Name of cooltower
     188           5 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).Schedule = state.dataIPShortCut->cAlphaArgs(2); // Get schedule
     189           5 :             if (lAlphaBlanks(2)) {
     190           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).SchedPtr = ScheduleManager::ScheduleAlwaysOn;
     191             :             } else {
     192           5 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).SchedPtr =
     193           5 :                     ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
     194           5 :                 if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).SchedPtr == 0) {
     195           0 :                     ShowSevereError(state, format("{}=\"{}\" invalid data", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     196           0 :                     ShowContinueError(state, format("Invalid-Schedule not found {}=\"{}\".", cAlphaFields(2), state.dataIPShortCut->cAlphaArgs(2)));
     197           0 :                     ErrorsFound = true;
     198             :                 }
     199             :             }
     200             : 
     201           5 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), Zone);
     202           5 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr =
     203           5 :                 Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->space);
     204           5 :             if ((state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr == 0) && (state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr == 0)) {
     205           0 :                 if (lAlphaBlanks(3)) {
     206           0 :                     ShowSevereError(state,
     207           0 :                                     format("{}=\"{}\" invalid {} is required but input is blank.",
     208             :                                            CurrentModuleObject,
     209           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     210             :                                            cAlphaFields(3)));
     211             :                 } else {
     212           0 :                     ShowSevereError(state,
     213           0 :                                     format("{}=\"{}\" invalid {}=\"{}\" not found.",
     214             :                                            CurrentModuleObject,
     215           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     216             :                                            cAlphaFields(3),
     217           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
     218             :                 }
     219           0 :                 ErrorsFound = true;
     220           5 :             } else if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr == 0) {
     221           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr =
     222           0 :                     state.dataHeatBal->space(state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr).zoneNum;
     223             :             }
     224             : 
     225           5 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyName = state.dataIPShortCut->cAlphaArgs(4); // Name of water storage tank
     226           5 :             if (lAlphaBlanks(4)) {
     227           5 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode = WaterSupplyMode::FromMains;
     228           0 :             } else if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromTank) {
     229           0 :                 WaterManager::SetupTankDemandComponent(state,
     230           0 :                                                        state.dataCoolTower->CoolTowerSys(CoolTowerNum).Name,
     231             :                                                        CurrentModuleObject,
     232           0 :                                                        state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyName,
     233             :                                                        ErrorsFound,
     234           0 :                                                        state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupTankID,
     235           0 :                                                        state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterTankDemandARRID);
     236             :             }
     237             : 
     238             :             {
     239           5 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).FlowCtrlType =
     240           5 :                     static_cast<FlowCtrl>(getEnumValue(FlowCtrlNamesUC, state.dataIPShortCut->cAlphaArgs(5))); // Type of flow control
     241           5 :                 if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FlowCtrlType == FlowCtrl::Invalid) {
     242           0 :                     ShowSevereError(state,
     243           0 :                                     format("{}=\"{}\" invalid {}=\"{}\".",
     244             :                                            CurrentModuleObject,
     245           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     246             :                                            cAlphaFields(5),
     247           0 :                                            state.dataIPShortCut->cAlphaArgs(5)));
     248           0 :                     ErrorsFound = true;
     249             :                 }
     250             :             }
     251             : 
     252           5 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpSchedPtr =
     253           5 :                 ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(6));
     254           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpSchedPtr == 0) {
     255           0 :                 if (lAlphaBlanks(6)) {
     256           0 :                     ShowSevereError(state,
     257           0 :                                     format("{}=\"{}\" invalid {} is required but input is blank.",
     258             :                                            CurrentModuleObject,
     259           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     260             :                                            cAlphaFields(6)));
     261             :                 } else {
     262           0 :                     ShowSevereError(state,
     263           0 :                                     format("{}=\"{}\" invalid {}=\"{}\" not found.",
     264             :                                            CurrentModuleObject,
     265           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     266             :                                            cAlphaFields(6),
     267           0 :                                            state.dataIPShortCut->cAlphaArgs(6)));
     268             :                 }
     269           0 :                 ErrorsFound = true;
     270             :             }
     271             : 
     272           5 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate = state.dataIPShortCut->rNumericArgs(1); // Maximum limit of water supply
     273           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate > MaximumWaterFlowRate) {
     274           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate = MaximumWaterFlowRate;
     275           0 :                 ShowWarningError(state,
     276           0 :                                  format("{}=\"{}\" invalid {}=[{:.2R}].",
     277             :                                         CurrentModuleObject,
     278           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
     279             :                                         cNumericFields(1),
     280           0 :                                         state.dataIPShortCut->rNumericArgs(1)));
     281           0 :                 ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaximumWaterFlowRate));
     282             :             }
     283           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate < MinimumWaterFlowRate) {
     284           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate = MinimumWaterFlowRate;
     285           0 :                 ShowWarningError(state,
     286           0 :                                  format("{}=\"{}\" invalid {}=[{:.2R}].",
     287             :                                         CurrentModuleObject,
     288           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
     289             :                                         cNumericFields(1),
     290           0 :                                         state.dataIPShortCut->rNumericArgs(1)));
     291           0 :                 ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinimumWaterFlowRate));
     292             :             }
     293             : 
     294           5 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight = state.dataIPShortCut->rNumericArgs(2); // Get effctive tower height
     295           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight > MaxHeight) {
     296           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight = MaxHeight;
     297           0 :                 ShowWarningError(state,
     298           0 :                                  format("{}=\"{}\" invalid {}=[{:.2R}].",
     299             :                                         CurrentModuleObject,
     300           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
     301             :                                         cNumericFields(2),
     302           0 :                                         state.dataIPShortCut->rNumericArgs(2)));
     303           0 :                 ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxHeight));
     304             :             }
     305           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight < MinHeight) {
     306           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight = MinHeight;
     307           0 :                 ShowWarningError(state,
     308           0 :                                  format("{}=\"{}\" invalid {}=[{:.2R}].",
     309             :                                         CurrentModuleObject,
     310           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
     311             :                                         cNumericFields(2),
     312           0 :                                         state.dataIPShortCut->rNumericArgs(2)));
     313           0 :                 ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinHeight));
     314             :             }
     315             : 
     316           5 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea = state.dataIPShortCut->rNumericArgs(3); // Get outlet area
     317           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea > MaxValue) {
     318           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea = MaxValue;
     319           0 :                 ShowWarningError(state,
     320           0 :                                  format("{}=\"{}\" invalid {}=[{:.2R}].",
     321             :                                         CurrentModuleObject,
     322           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
     323             :                                         cNumericFields(3),
     324           0 :                                         state.dataIPShortCut->rNumericArgs(3)));
     325           0 :                 ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxValue));
     326             :             }
     327           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea < MinValue) {
     328           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea = MinValue;
     329           0 :                 ShowWarningError(state,
     330           0 :                                  format("{}=\"{}\" invalid {}=[{:.2R}].",
     331             :                                         CurrentModuleObject,
     332           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
     333             :                                         cNumericFields(3),
     334           0 :                                         state.dataIPShortCut->rNumericArgs(3)));
     335           0 :                 ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinValue));
     336             :             }
     337             : 
     338           5 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate =
     339           5 :                 state.dataIPShortCut->rNumericArgs(4); // Maximum limit of air flow to the space
     340           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate > MaxValue) {
     341           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate = MaxValue;
     342           0 :                 ShowWarningError(state,
     343           0 :                                  format("{}=\"{}\" invalid {}=[{:.2R}].",
     344             :                                         CurrentModuleObject,
     345           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
     346             :                                         cNumericFields(4),
     347           0 :                                         state.dataIPShortCut->rNumericArgs(4)));
     348           0 :                 ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxValue));
     349             :             }
     350           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate < MinValue) {
     351           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate = MinValue;
     352           0 :                 ShowWarningError(state,
     353           0 :                                  format("{}=\"{}\" invalid {}=[{:.2R}].",
     354             :                                         CurrentModuleObject,
     355           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
     356             :                                         cNumericFields(4),
     357           0 :                                         state.dataIPShortCut->rNumericArgs(4)));
     358           0 :                 ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinValue));
     359             :             }
     360             : 
     361           5 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp =
     362           5 :                 state.dataIPShortCut->rNumericArgs(5); // Get minimum temp limit which gets this cooltower off
     363           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp > MaxValue) {
     364           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp = MaxValue;
     365           0 :                 ShowWarningError(state,
     366           0 :                                  format("{}=\"{}\" invalid {}=[{:.2R}].",
     367             :                                         CurrentModuleObject,
     368           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
     369             :                                         cNumericFields(5),
     370           0 :                                         state.dataIPShortCut->rNumericArgs(5)));
     371           0 :                 ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxValue));
     372             :             }
     373           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp < MinValue) {
     374           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp = MinValue;
     375           0 :                 ShowWarningError(state,
     376           0 :                                  format("{}=\"{}\" invalid {}=[{:.2R}].",
     377             :                                         CurrentModuleObject,
     378           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
     379             :                                         cNumericFields(5),
     380           0 :                                         state.dataIPShortCut->rNumericArgs(5)));
     381           0 :                 ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinValue));
     382             :             }
     383             : 
     384           5 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss = state.dataIPShortCut->rNumericArgs(6); // Fraction of water loss
     385           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss > MaxFrac) {
     386           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss = MaxFrac;
     387           0 :                 ShowWarningError(state,
     388           0 :                                  format("{}=\"{}\" invalid {}=[{:.2R}].",
     389             :                                         CurrentModuleObject,
     390           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
     391             :                                         cNumericFields(6),
     392           0 :                                         state.dataIPShortCut->rNumericArgs(6)));
     393           0 :                 ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxFrac));
     394             :             }
     395           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss < MinFrac) {
     396           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss = MinFrac;
     397           0 :                 ShowWarningError(state,
     398           0 :                                  format("{}=\"{}\" invalid {}=[{:.2R}].",
     399             :                                         CurrentModuleObject,
     400           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
     401             :                                         cNumericFields(6),
     402           0 :                                         state.dataIPShortCut->rNumericArgs(6)));
     403           0 :                 ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinFrac));
     404             :             }
     405             : 
     406           5 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched = state.dataIPShortCut->rNumericArgs(7); // Fraction of loss of air flow
     407           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched > MaxFrac) {
     408           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched = MaxFrac;
     409           0 :                 ShowWarningError(state,
     410           0 :                                  format("{}=\"{}\" invalid {}=[{:.2R}].",
     411             :                                         CurrentModuleObject,
     412           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
     413             :                                         cNumericFields(7),
     414           0 :                                         state.dataIPShortCut->rNumericArgs(7)));
     415           0 :                 ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxFrac));
     416             :             }
     417           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched < MinFrac) {
     418           0 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched = MinFrac;
     419           0 :                 ShowWarningError(state,
     420           0 :                                  format("{}=\"{}\" invalid {}=[{:.5R}].",
     421             :                                         CurrentModuleObject,
     422           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
     423             :                                         cNumericFields(7),
     424           0 :                                         state.dataIPShortCut->rNumericArgs(7)));
     425           0 :                 ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinFrac));
     426             :             }
     427             : 
     428           5 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).RatedPumpPower = state.dataIPShortCut->rNumericArgs(8); // Get rated pump power
     429             :         }
     430             : 
     431         763 :         cAlphaArgs.deallocate();
     432         763 :         cAlphaFields.deallocate();
     433         763 :         cNumericFields.deallocate();
     434         763 :         rNumericArgs.deallocate();
     435         763 :         lAlphaBlanks.deallocate();
     436         763 :         lNumericBlanks.deallocate();
     437             : 
     438         763 :         if (ErrorsFound) ShowFatalError(state, format("{} errors occurred in input.  Program terminates.", CurrentModuleObject));
     439             : 
     440         768 :         for (int CoolTowerNum = 1; CoolTowerNum <= NumCoolTowers; ++CoolTowerNum) {
     441          10 :             SetupOutputVariable(state,
     442             :                                 "Zone Cooltower Sensible Heat Loss Energy",
     443             :                                 Constant::Units::J,
     444           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatLoss,
     445             :                                 OutputProcessor::TimeStepType::System,
     446             :                                 OutputProcessor::StoreType::Sum,
     447           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     448          10 :             SetupOutputVariable(state,
     449             :                                 "Zone Cooltower Sensible Heat Loss Rate",
     450             :                                 Constant::Units::W,
     451           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatPower,
     452             :                                 OutputProcessor::TimeStepType::System,
     453             :                                 OutputProcessor::StoreType::Average,
     454           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     455          10 :             SetupOutputVariable(state,
     456             :                                 "Zone Cooltower Latent Heat Loss Energy",
     457             :                                 Constant::Units::J,
     458           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatLoss,
     459             :                                 OutputProcessor::TimeStepType::System,
     460             :                                 OutputProcessor::StoreType::Sum,
     461           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     462          10 :             SetupOutputVariable(state,
     463             :                                 "Zone Cooltower Latent Heat Loss Rate",
     464             :                                 Constant::Units::W,
     465           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatPower,
     466             :                                 OutputProcessor::TimeStepType::System,
     467             :                                 OutputProcessor::StoreType::Average,
     468           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     469          10 :             SetupOutputVariable(state,
     470             :                                 "Zone Cooltower Air Volume",
     471             :                                 Constant::Units::m3,
     472           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTAirVol,
     473             :                                 OutputProcessor::TimeStepType::System,
     474             :                                 OutputProcessor::StoreType::Sum,
     475           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     476          10 :             SetupOutputVariable(state,
     477             :                                 "Zone Cooltower Current Density Air Volume Flow Rate",
     478             :                                 Constant::Units::m3_s,
     479           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRate,
     480             :                                 OutputProcessor::TimeStepType::System,
     481             :                                 OutputProcessor::StoreType::Average,
     482           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     483          10 :             SetupOutputVariable(state,
     484             :                                 "Zone Cooltower Standard Density Air Volume Flow Rate",
     485             :                                 Constant::Units::m3_s,
     486           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRateStd,
     487             :                                 OutputProcessor::TimeStepType::System,
     488             :                                 OutputProcessor::StoreType::Average,
     489           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     490          10 :             SetupOutputVariable(state,
     491             :                                 "Zone Cooltower Air Mass",
     492             :                                 Constant::Units::kg,
     493           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTAirMass,
     494             :                                 OutputProcessor::TimeStepType::System,
     495             :                                 OutputProcessor::StoreType::Sum,
     496           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     497          10 :             SetupOutputVariable(state,
     498             :                                 "Zone Cooltower Air Mass Flow Rate",
     499             :                                 Constant::Units::kg_s,
     500           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirMassFlowRate,
     501             :                                 OutputProcessor::TimeStepType::System,
     502             :                                 OutputProcessor::StoreType::Average,
     503           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     504          10 :             SetupOutputVariable(state,
     505             :                                 "Zone Cooltower Air Inlet Temperature",
     506             :                                 Constant::Units::C,
     507           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletDBTemp,
     508             :                                 OutputProcessor::TimeStepType::System,
     509             :                                 OutputProcessor::StoreType::Average,
     510           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     511          10 :             SetupOutputVariable(state,
     512             :                                 "Zone Cooltower Air Inlet Humidity Ratio",
     513             :                                 Constant::Units::kgWater_kgDryAir,
     514           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletHumRat,
     515             :                                 OutputProcessor::TimeStepType::System,
     516             :                                 OutputProcessor::StoreType::Average,
     517           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     518          10 :             SetupOutputVariable(state,
     519             :                                 "Zone Cooltower Air Outlet Temperature",
     520             :                                 Constant::Units::C,
     521           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletTemp,
     522             :                                 OutputProcessor::TimeStepType::System,
     523             :                                 OutputProcessor::StoreType::Average,
     524           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     525          10 :             SetupOutputVariable(state,
     526             :                                 "Zone Cooltower Air Outlet Humidity Ratio",
     527             :                                 Constant::Units::kgWater_kgDryAir,
     528           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletHumRat,
     529             :                                 OutputProcessor::TimeStepType::System,
     530             :                                 OutputProcessor::StoreType::Average,
     531           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     532          10 :             SetupOutputVariable(state,
     533             :                                 "Zone Cooltower Pump Electricity Rate",
     534             :                                 Constant::Units::W,
     535           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecPower,
     536             :                                 OutputProcessor::TimeStepType::System,
     537             :                                 OutputProcessor::StoreType::Average,
     538           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     539          10 :             SetupOutputVariable(state,
     540             :                                 "Zone Cooltower Pump Electricity Energy",
     541             :                                 Constant::Units::J,
     542           5 :                                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecConsump,
     543             :                                 OutputProcessor::TimeStepType::System,
     544             :                                 OutputProcessor::StoreType::Sum,
     545           5 :                                 Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name,
     546             :                                 Constant::eResource::Electricity,
     547             :                                 OutputProcessor::Group::HVAC, // System
     548             :                                 OutputProcessor::EndUseCat::Cooling);
     549           5 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromMains) {
     550          10 :                 SetupOutputVariable(state,
     551             :                                     "Zone Cooltower Water Volume",
     552             :                                     Constant::Units::m3,
     553           5 :                                     state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump,
     554             :                                     OutputProcessor::TimeStepType::System,
     555             :                                     OutputProcessor::StoreType::Sum,
     556           5 :                                     Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     557          10 :                 SetupOutputVariable(state,
     558             :                                     "Zone Cooltower Mains Water Volume",
     559             :                                     Constant::Units::m3,
     560           5 :                                     state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump,
     561             :                                     OutputProcessor::TimeStepType::System,
     562             :                                     OutputProcessor::StoreType::Sum,
     563           5 :                                     Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name,
     564             :                                     Constant::eResource::MainsWater,
     565             :                                     OutputProcessor::Group::HVAC, // System
     566             :                                     OutputProcessor::EndUseCat::Cooling);
     567           0 :             } else if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromTank) {
     568           0 :                 SetupOutputVariable(state,
     569             :                                     "Zone Cooltower Water Volume",
     570             :                                     Constant::Units::m3,
     571           0 :                                     state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump,
     572             :                                     OutputProcessor::TimeStepType::System,
     573             :                                     OutputProcessor::StoreType::Sum,
     574           0 :                                     Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     575           0 :                 SetupOutputVariable(state,
     576             :                                     "Zone Cooltower Storage Tank Water Volume",
     577             :                                     Constant::Units::m3,
     578           0 :                                     state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump,
     579             :                                     OutputProcessor::TimeStepType::System,
     580             :                                     OutputProcessor::StoreType::Sum,
     581           0 :                                     Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
     582           0 :                 SetupOutputVariable(state,
     583             :                                     "Zone Cooltower Starved Mains Water Volume",
     584             :                                     Constant::Units::m3,
     585           0 :                                     state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeup,
     586             :                                     OutputProcessor::TimeStepType::System,
     587             :                                     OutputProcessor::StoreType::Sum,
     588           0 :                                     Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name,
     589             :                                     Constant::eResource::MainsWater,
     590             :                                     OutputProcessor::Group::HVAC, // System
     591             :                                     OutputProcessor::EndUseCat::Cooling);
     592             :             }
     593             :         }
     594         763 :     }
     595             : 
     596        3580 :     void CalcCoolTower(EnergyPlusData &state)
     597             :     {
     598             : 
     599             :         // SUBROUTINE INFORMATION:
     600             :         //       AUTHOR         Daeho Kang
     601             :         //       DATE WRITTEN   Aug 2008
     602             : 
     603             :         // REFERENCES:
     604             :         // Baruch Givoni. 1994. Passive and Low Energy Cooling of Buildings. Chapter 5: Evaporative Cooling Systems.
     605             :         //     John Wiley & Sons, Inc.
     606             : 
     607             :         // SUBROUTINE PARAMETER DEFINITIONS:
     608        3580 :         Real64 constexpr MinWindSpeed(0.1);  // Minimum limit of outdoor air wind speed in m/s
     609        3580 :         Real64 constexpr MaxWindSpeed(30.0); // Maximum limit of outdoor air wind speed in m/s
     610        3580 :         Real64 constexpr UCFactor(60000.0);  // Unit conversion factor m3/s to l/min
     611             : 
     612             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     613             :         Real64 CVF_ZoneNum;          // Design flow rate in m3/s
     614             :         Real64 AirMassFlowRate;      // Actual air mass flow rate in kg/s
     615             :         Real64 AirSpecHeat;          // Specific heat of air
     616             :         Real64 AirDensity;           // Density of air
     617             :         Real64 RhoWater;             // Density of water
     618             :         Real64 PumpPartLoadRat;      // Pump part load ratio (based on user schedule, or 1.0 for no schedule)
     619        3580 :         Real64 WaterFlowRate = 0.0;  // Calculated water flow rate in m3/s
     620        3580 :         Real64 AirVolFlowRate = 0.0; // Calculated air volume flow rate in m3/s
     621             :         Real64 InletHumRat;          // Humidity ratio of outdoor air
     622             :         Real64 OutletHumRat;         // Humidity ratio of air at the cooltower outlet
     623        3580 :         Real64 OutletTemp = 0.0;     // Dry bulb temperature of air at the cooltower outlet
     624             :         Real64 IntHumRat;            // Humidity ratio of initialized air
     625             : 
     626        3580 :         auto &Zone(state.dataHeatBal->Zone);
     627             : 
     628       12501 :         for (int CoolTowerNum = 1; CoolTowerNum <= (int)state.dataCoolTower->CoolTowerSys.size(); ++CoolTowerNum) {
     629        8921 :             int const ZoneNum = state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr;
     630        8921 :             auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
     631        8921 :             thisZoneHB.MCPTC = 0.0;
     632        8921 :             thisZoneHB.MCPC = 0.0;
     633        8921 :             thisZoneHB.CTMFL = 0.0;
     634        8921 :             if ((state.dataHeatBal->doSpaceHeatBalance) && (state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr > 0)) {
     635           0 :                 auto &thisSpaceHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr);
     636           0 :                 thisSpaceHB.MCPTC = 0.0;
     637           0 :                 thisSpaceHB.MCPC = 0.0;
     638           0 :                 thisSpaceHB.CTMFL = 0.0;
     639             :             }
     640        8921 :             if (ScheduleManager::GetCurrentScheduleValue(state, state.dataCoolTower->CoolTowerSys(CoolTowerNum).SchedPtr) > 0.0) {
     641             :                 // check component operation
     642        6365 :                 if (state.dataEnvrn->WindSpeed < MinWindSpeed || state.dataEnvrn->WindSpeed > MaxWindSpeed) continue;
     643        6365 :                 if (state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT < state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp)
     644        2920 :                     continue;
     645             : 
     646             :                 // Unit is on and simulate this component
     647             :                 // Determine the temperature and air flow rate at the cooltower outlet
     648        3445 :                 if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FlowCtrlType == FlowCtrl::WindDriven) {
     649        2785 :                     Real64 const height_sqrt(std::sqrt(state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight));
     650        2785 :                     state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletVelocity = 0.7 * height_sqrt + 0.47 * (state.dataEnvrn->WindSpeed - 1.0);
     651        2785 :                     AirVolFlowRate =
     652        2785 :                         state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea * state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletVelocity;
     653        2785 :                     AirVolFlowRate = min(AirVolFlowRate, state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate);
     654        2785 :                     WaterFlowRate = (AirVolFlowRate / (0.0125 * height_sqrt));
     655        2785 :                     if (WaterFlowRate > state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate * UCFactor) {
     656        2049 :                         WaterFlowRate = state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate * UCFactor;
     657        2049 :                         AirVolFlowRate = 0.0125 * WaterFlowRate * height_sqrt;
     658        2049 :                         AirVolFlowRate = min(AirVolFlowRate, state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate);
     659             :                     }
     660        2785 :                     WaterFlowRate = min(WaterFlowRate, (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate * UCFactor));
     661        2785 :                     OutletTemp =
     662        2785 :                         state.dataEnvrn->OutDryBulbTemp - (state.dataEnvrn->OutDryBulbTemp - state.dataEnvrn->OutWetBulbTemp) *
     663        2785 :                                                               (1.0 - std::exp(-0.8 * state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight)) *
     664        2785 :                                                               (1.0 - std::exp(-0.15 * WaterFlowRate));
     665         660 :                 } else if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FlowCtrlType == FlowCtrl::FlowSchedule) {
     666         660 :                     WaterFlowRate = state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate * UCFactor;
     667         660 :                     AirVolFlowRate = 0.0125 * WaterFlowRate * std::sqrt(state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight);
     668         660 :                     AirVolFlowRate = min(AirVolFlowRate, state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate);
     669         660 :                     OutletTemp =
     670         660 :                         state.dataEnvrn->OutDryBulbTemp - (state.dataEnvrn->OutDryBulbTemp - state.dataEnvrn->OutWetBulbTemp) *
     671         660 :                                                               (1.0 - std::exp(-0.8 * state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight)) *
     672         660 :                                                               (1.0 - std::exp(-0.15 * WaterFlowRate));
     673             :                 }
     674             : 
     675        3445 :                 if (OutletTemp < state.dataEnvrn->OutWetBulbTemp) {
     676           0 :                     ShowSevereError(state, "Cooltower outlet temperature exceed the outdoor wet bulb temperature reset to input values");
     677           0 :                     ShowContinueError(state, format("Occurs in Cooltower ={}", state.dataCoolTower->CoolTowerSys(CoolTowerNum).Name));
     678             :                 }
     679             : 
     680        3445 :                 WaterFlowRate /= UCFactor;
     681             :                 // Determine actual water flow rate
     682        3445 :                 if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss > 0.0) {
     683        2782 :                     state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualWaterFlowRate =
     684        2782 :                         WaterFlowRate * (1.0 + state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss);
     685             :                 } else {
     686         663 :                     state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualWaterFlowRate = WaterFlowRate;
     687             :                 }
     688             : 
     689             :                 // Determine actual air flow rate
     690        3445 :                 if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched > 0.0) {
     691        2782 :                     state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualAirVolFlowRate =
     692        2782 :                         AirVolFlowRate * (1.0 - state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched);
     693             :                 } else {
     694         663 :                     state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualAirVolFlowRate = AirVolFlowRate;
     695             :                 }
     696             : 
     697             :                 // Determine pump power
     698        3445 :                 if (ScheduleManager::GetCurrentScheduleValue(state, state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpSchedPtr) > 0) {
     699        3445 :                     PumpPartLoadRat = ScheduleManager::GetCurrentScheduleValue(state, state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpSchedPtr);
     700             :                 } else {
     701           0 :                     PumpPartLoadRat = 1.0;
     702             :                 }
     703             : 
     704             :                 // Determine air mass flow rate and volume flow rate
     705        6890 :                 InletHumRat = Psychrometrics::PsyWFnTdbTwbPb(
     706        3445 :                     state, state.dataEnvrn->OutDryBulbTemp, state.dataEnvrn->OutWetBulbTemp, state.dataEnvrn->OutBaroPress);
     707             :                 // Assume no pressure drops and no changes in enthalpy between inlet and outlet air
     708        3445 :                 IntHumRat = Psychrometrics::PsyWFnTdbH(state, OutletTemp, state.dataEnvrn->OutEnthalpy); // Initialized humidity ratio
     709        3445 :                 AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, OutletTemp, IntHumRat);
     710        3445 :                 AirMassFlowRate = AirDensity * state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualAirVolFlowRate;
     711             :                 // From the mass balance W_in*(m_air + m_water) = W_out*m_air
     712        3445 :                 RhoWater = Psychrometrics::RhoH2O(OutletTemp); // Assume T_water = T_outlet
     713        3445 :                 OutletHumRat = (InletHumRat * (AirMassFlowRate + (state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualWaterFlowRate * RhoWater))) /
     714             :                                AirMassFlowRate;
     715        3445 :                 AirSpecHeat = Psychrometrics::PsyCpAirFnW(OutletHumRat);
     716        3445 :                 AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, OutletTemp, OutletHumRat); // Outlet air density
     717        3445 :                 CVF_ZoneNum = state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualAirVolFlowRate *
     718        3445 :                               ScheduleManager::GetCurrentScheduleValue(state, state.dataCoolTower->CoolTowerSys(CoolTowerNum).SchedPtr);
     719        3445 :                 Real64 thisMCPC = CVF_ZoneNum * AirDensity * AirSpecHeat;
     720        3445 :                 Real64 thisMCPTC = thisMCPC * OutletTemp;
     721        3445 :                 Real64 thisCTMFL = thisMCPC / AirSpecHeat;
     722        3445 :                 Real64 thisZT = thisZoneHB.ZT;
     723        3445 :                 Real64 thisAirHumRat = thisZoneHB.airHumRat;
     724        3445 :                 thisZoneHB.MCPC = thisMCPC;
     725        3445 :                 thisZoneHB.MCPTC = thisMCPTC;
     726        3445 :                 thisZoneHB.CTMFL = thisCTMFL;
     727        3445 :                 if ((state.dataHeatBal->doSpaceHeatBalance) && (state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr > 0)) {
     728             :                     auto &thisSpaceHB =
     729           0 :                         state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr);
     730           0 :                     thisSpaceHB.MCPC = thisMCPC;
     731           0 :                     thisSpaceHB.MCPTC = thisMCPTC;
     732           0 :                     thisSpaceHB.CTMFL = thisCTMFL;
     733           0 :                     thisZT = thisSpaceHB.ZT;
     734           0 :                     thisAirHumRat = thisSpaceHB.airHumRat;
     735             :                 }
     736             : 
     737        3445 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatPower = thisMCPC * std::abs(thisZT - OutletTemp);
     738        3445 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatPower = CVF_ZoneNum * std::abs(thisAirHumRat - OutletHumRat);
     739        3445 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletTemp = OutletTemp;
     740        3445 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletHumRat = OutletHumRat;
     741        3445 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRate = CVF_ZoneNum;
     742        3445 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirMassFlowRate = thisCTMFL;
     743        3445 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRateStd = thisCTMFL / state.dataEnvrn->StdRhoAir;
     744        3445 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletDBTemp = Zone(ZoneNum).OutDryBulbTemp;
     745        3445 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletWBTemp = Zone(ZoneNum).OutWetBulbTemp;
     746        3445 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletHumRat = state.dataEnvrn->OutHumRat;
     747        3445 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate = (std::abs(InletHumRat - OutletHumRat) * thisCTMFL) / RhoWater;
     748        3445 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeupRate = 0.0; // initialize -- calc in update
     749        3445 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecPower =
     750        3445 :                     state.dataCoolTower->CoolTowerSys(CoolTowerNum).RatedPumpPower * PumpPartLoadRat;
     751             :             } else { // Unit is off
     752        2556 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatPower = 0.0;
     753        2556 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatPower = 0.0;
     754        2556 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletTemp = 0.0;
     755        2556 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletHumRat = 0.0;
     756        2556 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRate = 0.0;
     757        2556 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirMassFlowRate = 0.0;
     758        2556 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRateStd = 0.0;
     759        2556 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletDBTemp = 0.0;
     760        2556 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletHumRat = 0.0;
     761        2556 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecPower = 0.0;
     762        2556 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate = 0.0;
     763        2556 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeupRate = 0.0;
     764             :             }
     765             :         }
     766        3580 :     }
     767             : 
     768        3580 :     void UpdateCoolTower(EnergyPlusData &state)
     769             :     {
     770             : 
     771             :         // SUBROUTINE INFORMATION:
     772             :         //       AUTHOR         Richard J. Liesen
     773             :         //       DATE WRITTEN   October 2000
     774             :         //       MODIFIED       Aug 2008 Daeho Kang
     775             : 
     776       12501 :         for (int CoolTowerNum = 1; CoolTowerNum <= (int)state.dataCoolTower->CoolTowerSys.size(); ++CoolTowerNum) {
     777             : 
     778             :             // Set the demand request for supply water from water storage tank (if needed)
     779        8921 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromTank) {
     780           0 :                 state.dataWaterData->WaterStorage(state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupTankID)
     781           0 :                     .VdotRequestDemand(state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterTankDemandARRID) =
     782           0 :                     state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate;
     783             :             }
     784             : 
     785             :             // check if should be starved by restricted flow from tank
     786        8921 :             if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromTank) {
     787           0 :                 Real64 AvailWaterRate = state.dataWaterData->WaterStorage(state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupTankID)
     788           0 :                                             .VdotAvailDemand(state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterTankDemandARRID);
     789           0 :                 if (AvailWaterRate < state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate) {
     790           0 :                     state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeupRate =
     791           0 :                         state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate - AvailWaterRate;
     792           0 :                     state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate = AvailWaterRate;
     793             :                 }
     794             :             }
     795             :         }
     796        3580 :     }
     797             : 
     798        3580 :     void ReportCoolTower(EnergyPlusData &state)
     799             :     {
     800             : 
     801             :         // SUBROUTINE INFORMATION:
     802             :         //       AUTHOR         Daeho Kang
     803             :         //       DATE WRITTEN   Aut 2008
     804             : 
     805        3580 :         Real64 const TSMult = state.dataHVACGlobal->TimeStepSysSec;
     806             : 
     807       12501 :         for (int CoolTowerNum = 1; CoolTowerNum <= (int)state.dataCoolTower->CoolTowerSys.size(); ++CoolTowerNum) {
     808             : 
     809        8921 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTAirVol = state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRate * TSMult;
     810        8921 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTAirMass = state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirMassFlowRate * TSMult;
     811        8921 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatLoss = state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatPower * TSMult;
     812        8921 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatLoss = state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatPower * TSMult;
     813        8921 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecConsump = state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecPower * TSMult;
     814        8921 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump =
     815        8921 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate * TSMult;
     816        8921 :             state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeup =
     817        8921 :                 state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeupRate * TSMult;
     818             :         }
     819        3580 :     }
     820             : 
     821             : } // namespace CoolTower
     822             : 
     823             : } // namespace EnergyPlus

Generated by: LCOV version 1.14