LCOV - code coverage report
Current view: top level - EnergyPlus - CoolTower.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 63.6 % 371 236
Test Date: 2025-05-22 16:09:37 Functions: 100.0 % 5 5

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

Generated by: LCOV version 2.0-1