LCOV - code coverage report
Current view: top level - EnergyPlus - PackagedThermalStorageCoil.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 66.7 % 2377 1585
Test Date: 2025-06-02 07:23:51 Functions: 85.7 % 21 18

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <cassert>
      50              : #include <cmath>
      51              : 
      52              : // ObjexxFCL Headers
      53              : #include <ObjexxFCL/Fmath.hh>
      54              : 
      55              : // EnergyPlus Headers
      56              : #include <EnergyPlus/Autosizing/Base.hh>
      57              : #include <EnergyPlus/BranchNodeConnections.hh>
      58              : #include <EnergyPlus/CurveManager.hh>
      59              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      60              : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
      61              : #include <EnergyPlus/DataEnvironment.hh>
      62              : #include <EnergyPlus/DataHeatBalance.hh>
      63              : #include <EnergyPlus/DataIPShortCuts.hh>
      64              : #include <EnergyPlus/DataLoopNode.hh>
      65              : #include <EnergyPlus/DataSizing.hh>
      66              : #include <EnergyPlus/DataWater.hh>
      67              : #include <EnergyPlus/DataZoneEquipment.hh>
      68              : #include <EnergyPlus/EMSManager.hh>
      69              : #include <EnergyPlus/FluidProperties.hh>
      70              : #include <EnergyPlus/General.hh>
      71              : #include <EnergyPlus/GeneralRoutines.hh>
      72              : #include <EnergyPlus/GlobalNames.hh>
      73              : #include <EnergyPlus/HeatBalanceInternalHeatGains.hh>
      74              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      75              : #include <EnergyPlus/NodeInputManager.hh>
      76              : #include <EnergyPlus/OutputProcessor.hh>
      77              : #include <EnergyPlus/OutputReportPredefined.hh>
      78              : #include <EnergyPlus/PackagedThermalStorageCoil.hh>
      79              : #include <EnergyPlus/Plant/DataPlant.hh>
      80              : #include <EnergyPlus/PlantUtilities.hh>
      81              : #include <EnergyPlus/Psychrometrics.hh>
      82              : #include <EnergyPlus/ScheduleManager.hh>
      83              : #include <EnergyPlus/UtilityRoutines.hh>
      84              : #include <EnergyPlus/WaterManager.hh>
      85              : #include <EnergyPlus/WaterThermalTanks.hh>
      86              : 
      87              : namespace EnergyPlus::PackagedThermalStorageCoil {
      88              : 
      89              : // Module containing the routines dealing with the packaged thermal storage cooling
      90              : 
      91              : // MODULE INFORMATION:
      92              : //       AUTHOR         Brent Griffith
      93              : //       DATE WRITTEN   April 2013
      94              : //       MODIFIED       na
      95              : //       RE-ENGINEERED  na
      96              : 
      97              : // PURPOSE OF THIS MODULE:
      98              : // encapsulate the data and algorithms for modeling packaged thermals storage cooling coils
      99              : 
     100              : // Using/Aliasing
     101              : using namespace DataLoopNode;
     102              : using namespace Psychrometrics;
     103              : using namespace Curve;
     104              : 
     105              : constexpr std::array<std::string_view, static_cast<int>(PTSCCtrlType::Num)> modeControlStrings = {"SCHEDULEDMODES", "EMSCONTROLLED"};
     106              : constexpr std::array<std::string_view, static_cast<int>(MediaType::Num)> mediaStrings = {"WATER", "USERDEFINEDFLUIDTYPE", "ICE"};
     107              : constexpr std::array<std::string_view, static_cast<int>(TESCondenserType::Num)> condenserTypesUC = {"AIRCOOLED", "EVAPORATIVELYCOOLED"};
     108              : constexpr Real64 gigaJoulesToJoules = 1.e+09;
     109              : 
     110        63397 : void SimTESCoil(EnergyPlusData &state,
     111              :                 std::string_view CompName, // name of the fan coil unit
     112              :                 int &CompIndex,
     113              :                 HVAC::FanOp const fanOp, // allows parent object to control fan mode
     114              :                 PTSCOperatingMode &TESOpMode,
     115              :                 ObjexxFCL::Optional<Real64 const> PartLoadRatio // part load ratio (for single speed cycling unit)
     116              : )
     117              : {
     118              : 
     119              :     // SUBROUTINE INFORMATION:
     120              :     //       AUTHOR         <author>
     121              :     //       DATE WRITTEN   <date_written>
     122              :     //       MODIFIED       na
     123              :     //       RE-ENGINEERED  na
     124              : 
     125              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     126              : 
     127        63397 :     if (state.dataPackagedThermalStorageCoil->GetTESInputFlag) {
     128            0 :         GetTESCoilInput(state);
     129            0 :         state.dataPackagedThermalStorageCoil->GetTESInputFlag = false;
     130              :     }
     131              : 
     132        63397 :     int TESCoilNum = 0;
     133        63397 :     if (CompIndex == 0) {
     134            0 :         TESCoilNum = Util::FindItemInList(CompName, state.dataPackagedThermalStorageCoil->TESCoil);
     135            0 :         if (TESCoilNum == 0) {
     136            0 :             ShowFatalError(state, format("Thermal Energy Storage Cooling Coil not found={}", CompName));
     137              :         }
     138            0 :         CompIndex = TESCoilNum;
     139              :     } else {
     140        63397 :         TESCoilNum = CompIndex;
     141        63397 :         if (TESCoilNum > state.dataPackagedThermalStorageCoil->NumTESCoils || TESCoilNum < 1) {
     142            0 :             ShowFatalError(state,
     143            0 :                            format("SimTESCoil: Invalid CompIndex passed={}, Number of Thermal Energy Storage Cooling Coil Coils={}, Coil name={}",
     144              :                                   TESCoilNum,
     145            0 :                                   state.dataPackagedThermalStorageCoil->NumTESCoils,
     146              :                                   CompName));
     147              :         }
     148        63397 :         if (state.dataPackagedThermalStorageCoil->CheckEquipName(TESCoilNum)) {
     149            4 :             if (!CompName.empty() && CompName != state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).Name) {
     150            0 :                 ShowFatalError(state,
     151            0 :                                format("SimTESCoil: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
     152              :                                       TESCoilNum,
     153              :                                       CompName,
     154            0 :                                       state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).Name));
     155              :             }
     156            4 :             state.dataPackagedThermalStorageCoil->CheckEquipName(TESCoilNum) = false;
     157              :         }
     158              :     }
     159              : 
     160        63397 :     TESOpMode = PTSCOperatingMode::CoolingOnly;
     161              : 
     162        63397 :     InitTESCoil(state, TESCoilNum);
     163              : 
     164        63397 :     TESOpMode = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).CurControlMode;
     165        63397 :     switch (TESOpMode) {
     166           12 :     case PTSCOperatingMode::Off:
     167           12 :         CalcTESCoilOffMode(state, TESCoilNum);
     168           12 :         break;
     169        30543 :     case PTSCOperatingMode::CoolingOnly:
     170        30543 :         CalcTESCoilCoolingOnlyMode(state, TESCoilNum, fanOp, PartLoadRatio);
     171        30543 :         break;
     172        14200 :     case PTSCOperatingMode::CoolingAndCharge:
     173        14200 :         CalcTESCoilCoolingAndChargeMode(state, TESCoilNum, fanOp, PartLoadRatio);
     174        14200 :         break;
     175         2338 :     case PTSCOperatingMode::CoolingAndDischarge:
     176         2338 :         CalcTESCoilCoolingAndDischargeMode(state, TESCoilNum, fanOp, PartLoadRatio);
     177         2338 :         break;
     178         1349 :     case PTSCOperatingMode::ChargeOnly:
     179         1349 :         CalcTESCoilChargeOnlyMode(state, TESCoilNum);
     180         1349 :         break;
     181        14955 :     case PTSCOperatingMode::DischargeOnly:
     182        14955 :         CalcTESCoilDischargeOnlyMode(state, TESCoilNum, PartLoadRatio);
     183        14955 :         break;
     184            0 :     default:
     185            0 :         assert(false);
     186              :     }
     187        63397 : }
     188              : 
     189            1 : void GetTESCoilInput(EnergyPlusData &state)
     190              : {
     191              : 
     192              :     // SUBROUTINE INFORMATION:
     193              :     //       AUTHOR         <author>
     194              :     //       DATE WRITTEN   <date_written>
     195              :     //       MODIFIED       na
     196              :     //       RE-ENGINEERED  na
     197              : 
     198              :     // Using/Aliasing
     199              :     using BranchNodeConnections::TestCompSet;
     200              :     using DataZoneEquipment::FindControlledZoneIndexFromSystemNodeNumberForZone;
     201              :     using GlobalNames::VerifyUniqueCoilName;
     202              :     using NodeInputManager::GetOnlySingleNode;
     203              :     using WaterManager::SetupTankDemandComponent;
     204              :     using WaterManager::SetupTankSupplyComponent;
     205              : 
     206              :     // SUBROUTINE PARAMETER DEFINITIONS:
     207              :     static constexpr std::string_view RoutineName("GetTESCoilInput: "); // include trailing blank space
     208              :     static constexpr std::string_view routineName = "GetTESCoilInput";
     209              : 
     210              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     211            1 :     int NumAlphas = 0;       // Number of alphas in input
     212            1 :     int NumNumbers = 0;      // Number of numeric items in input
     213            1 :     int IOStatus = -1;       // Input status returned from GetObjectItem
     214            1 :     bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
     215              : 
     216            1 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     217            1 :     cCurrentModuleObject = "Coil:Cooling:DX:SingleSpeed:ThermalStorage";
     218            1 :     state.dataPackagedThermalStorageCoil->NumTESCoils = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     219              : 
     220            1 :     state.dataPackagedThermalStorageCoil->TESCoil.allocate(state.dataPackagedThermalStorageCoil->NumTESCoils);
     221            1 :     state.dataPackagedThermalStorageCoil->CheckEquipName.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, true);
     222              : 
     223            5 :     for (int item = 1; item <= state.dataPackagedThermalStorageCoil->NumTESCoils; ++item) {
     224              : 
     225            4 :         auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(item);
     226              : 
     227            8 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     228              :                                                                  cCurrentModuleObject,
     229              :                                                                  item,
     230            4 :                                                                  state.dataIPShortCut->cAlphaArgs,
     231              :                                                                  NumAlphas,
     232            4 :                                                                  state.dataIPShortCut->rNumericArgs,
     233              :                                                                  NumNumbers,
     234              :                                                                  IOStatus,
     235            4 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     236            4 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     237            4 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     238            4 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     239              : 
     240            4 :         ErrorObjectHeader eoh{routineName, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)};
     241              : 
     242            4 :         Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
     243              : 
     244              :         // ErrorsFound will be set to True if problem was found, left untouched otherwise
     245            4 :         VerifyUniqueCoilName(state, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, cCurrentModuleObject + " Name");
     246              : 
     247            4 :         thisTESCoil.Name = state.dataIPShortCut->cAlphaArgs(1);
     248            4 :         if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
     249            0 :             thisTESCoil.availSched = Sched::GetScheduleAlwaysOn(state);
     250            4 :         } else if ((thisTESCoil.availSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(2))) == nullptr) {
     251            0 :             ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2));
     252            0 :             ErrorsFound = true;
     253              :         }
     254              : 
     255            4 :         thisTESCoil.ModeControlType = static_cast<PTSCCtrlType>(getEnumValue(modeControlStrings, state.dataIPShortCut->cAlphaArgs(3)));
     256            4 :         if (thisTESCoil.ModeControlType == PTSCCtrlType::Invalid) {
     257            0 :             ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     258            0 :             ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3)));
     259            0 :             ShowContinueError(state, "Available choices are ScheduledModes or EMSControlled");
     260            0 :             ErrorsFound = true;
     261              :         }
     262              : 
     263            4 :         if (thisTESCoil.ModeControlType == PTSCCtrlType::ScheduledOpModes) {
     264            1 :             if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
     265            0 :                 ShowSevereEmptyField(state, eoh, state.dataIPShortCut->cAlphaFieldNames(4));
     266            0 :                 ErrorsFound = true;
     267            1 :             } else if ((thisTESCoil.controlModeSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(4))) == nullptr) {
     268            0 :                 ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(4), state.dataIPShortCut->cAlphaArgs(4));
     269            0 :                 ErrorsFound = true;
     270              :             }
     271              :         }
     272              : 
     273            4 :         thisTESCoil.StorageMedia = static_cast<MediaType>(getEnumValue(mediaStrings, state.dataIPShortCut->cAlphaArgs(5)));
     274            4 :         switch (thisTESCoil.StorageMedia) {
     275            3 :         case MediaType::Ice:
     276              :         case MediaType::UserDefindFluid:
     277              :             // nothing else to do for now
     278            3 :             break;
     279            1 :         case MediaType::Water:
     280            1 :             thisTESCoil.StorageFluidName = "WATER";
     281            1 :             thisTESCoil.glycol = Fluid::GetWater(state);
     282            1 :             break;
     283            0 :         default:
     284            0 :             ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     285            0 :             ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(5), state.dataIPShortCut->cAlphaArgs(5)));
     286            0 :             ShowContinueError(state, "Available choices are Ice, Water, or UserDefindedFluidType");
     287            0 :             ErrorsFound = true;
     288              :         }
     289              : 
     290            4 :         thisTESCoil.StorageFluidName = state.dataIPShortCut->cAlphaArgs(6);
     291            4 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(5), "USERDEFINEDFLUIDTYPE")) {
     292            0 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) {
     293            0 :                 ShowSevereEmptyField(state, eoh, state.dataIPShortCut->cAlphaFieldNames(6));
     294            0 :                 ErrorsFound = true;
     295            0 :             } else if ((thisTESCoil.glycol = Fluid::GetGlycol(state, state.dataIPShortCut->cAlphaArgs(6))) == nullptr) {
     296            0 :                 ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(6), state.dataIPShortCut->cAlphaArgs(6));
     297            0 :                 ErrorsFound = true;
     298              :             }
     299              :         }
     300              : 
     301            4 :         switch (thisTESCoil.StorageMedia) {
     302            1 :         case MediaType::Water:
     303              :         case MediaType::UserDefindFluid:
     304            1 :             if (!state.dataIPShortCut->lNumericFieldBlanks(1)) {
     305            1 :                 thisTESCoil.FluidStorageVolume = state.dataIPShortCut->rNumericArgs(1);
     306              :             } else {
     307            0 :                 ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     308            0 :                 ShowContinueError(state, format("{} cannot be blank for Water storage type", state.dataIPShortCut->cNumericFieldNames(1)));
     309            0 :                 ShowContinueError(state, "Enter fluid storage tank volume in m3/s.");
     310            0 :                 ErrorsFound = true;
     311              :             }
     312            1 :             break;
     313            3 :         case MediaType::Ice:
     314            3 :             if (!state.dataIPShortCut->lNumericFieldBlanks(2)) {
     315            3 :                 if (state.dataIPShortCut->rNumericArgs(2) == Constant::AutoCalculate) {
     316            3 :                     thisTESCoil.IceStorageCapacity = state.dataIPShortCut->rNumericArgs(2);
     317              :                 } else {
     318            0 :                     thisTESCoil.IceStorageCapacity =
     319            0 :                         state.dataIPShortCut->rNumericArgs(2) * gigaJoulesToJoules; // input in giga joules, used as joules internally
     320              :                 }
     321            0 :             } else if (state.dataIPShortCut->lNumericFieldBlanks(2)) {
     322            0 :                 ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     323            0 :                 ShowContinueError(state, format("{} cannot be blank for Ice storage type", state.dataIPShortCut->cNumericFieldNames(2)));
     324            0 :                 ShowContinueError(state, "Enter ice storage tank capacity in GJ.");
     325            0 :                 ErrorsFound = true;
     326              :             }
     327            3 :             break;
     328            0 :         default:
     329              :             // nothing
     330            0 :             break;
     331              :         }
     332              : 
     333            4 :         thisTESCoil.StorageCapacitySizingFactor = state.dataIPShortCut->rNumericArgs(3);
     334              : 
     335            4 :         thisTESCoil.StorageAmbientNodeNum = GetOnlySingleNode(state,
     336            4 :                                                               state.dataIPShortCut->cAlphaArgs(7),
     337              :                                                               ErrorsFound,
     338              :                                                               DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
     339            4 :                                                               state.dataIPShortCut->cAlphaArgs(1),
     340              :                                                               DataLoopNode::NodeFluidType::Air,
     341              :                                                               DataLoopNode::ConnectionType::Sensor,
     342              :                                                               NodeInputManager::CompFluidStream::Primary,
     343              :                                                               ObjectIsNotParent);
     344              : 
     345            4 :         int const ZoneIndexTrial = FindControlledZoneIndexFromSystemNodeNumberForZone(state, thisTESCoil.StorageAmbientNodeNum);
     346            4 :         if (ZoneIndexTrial > 0) { // tank is inside a zone so setup internal gains
     347            1 :             SetupZoneInternalGain(
     348              :                 state, ZoneIndexTrial, thisTESCoil.Name, DataHeatBalance::IntGainType::PackagedTESCoilTank, &thisTESCoil.QdotAmbient);
     349              :         }
     350              : 
     351            4 :         thisTESCoil.StorageUA = state.dataIPShortCut->rNumericArgs(4);
     352            4 :         thisTESCoil.RatedFluidTankTemp = state.dataIPShortCut->rNumericArgs(5);
     353            4 :         thisTESCoil.RatedEvapAirVolFlowRate = state.dataIPShortCut->rNumericArgs(6);
     354              : 
     355            4 :         thisTESCoil.EvapAirInletNodeNum = GetOnlySingleNode(state,
     356            4 :                                                             state.dataIPShortCut->cAlphaArgs(8),
     357              :                                                             ErrorsFound,
     358              :                                                             DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
     359            4 :                                                             state.dataIPShortCut->cAlphaArgs(1),
     360              :                                                             DataLoopNode::NodeFluidType::Air,
     361              :                                                             DataLoopNode::ConnectionType::Inlet,
     362              :                                                             NodeInputManager::CompFluidStream::Primary,
     363              :                                                             ObjectIsNotParent);
     364            8 :         thisTESCoil.EvapAirOutletNodeNum = GetOnlySingleNode(state,
     365            4 :                                                              state.dataIPShortCut->cAlphaArgs(9),
     366              :                                                              ErrorsFound,
     367              :                                                              DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
     368            4 :                                                              state.dataIPShortCut->cAlphaArgs(1),
     369              :                                                              DataLoopNode::NodeFluidType::Air,
     370              :                                                              DataLoopNode::ConnectionType::Outlet,
     371              :                                                              NodeInputManager::CompFluidStream::Primary,
     372              :                                                              ObjectIsNotParent);
     373            8 :         TestCompSet(state,
     374              :                     cCurrentModuleObject,
     375            4 :                     state.dataIPShortCut->cAlphaArgs(1),
     376            4 :                     state.dataIPShortCut->cAlphaArgs(8),
     377            4 :                     state.dataIPShortCut->cAlphaArgs(9),
     378              :                     "Air Nodes");
     379              : 
     380            4 :         BooleanSwitch const answer = getYesNoValue(state.dataIPShortCut->cAlphaArgs(10));
     381            4 :         switch (answer) {
     382            4 :         case BooleanSwitch::Yes:
     383              :         case BooleanSwitch::No:
     384            4 :             thisTESCoil.CoolingOnlyModeIsAvailable = static_cast<bool>(answer);
     385            4 :             break;
     386            0 :         default:
     387            0 :             thisTESCoil.CoolingOnlyModeIsAvailable = false;
     388            0 :             ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     389            0 :             ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(10), state.dataIPShortCut->cAlphaArgs(10)));
     390            0 :             ShowContinueError(state, "Available choices are Yes or No.");
     391            0 :             ErrorsFound = true;
     392              :         }
     393              : 
     394            4 :         thisTESCoil.CoolingOnlyRatedTotCap = state.dataIPShortCut->rNumericArgs(7);
     395            4 :         if (thisTESCoil.CoolingOnlyModeIsAvailable) { // get input data for this mode
     396              : 
     397            4 :             thisTESCoil.CoolingOnlyRatedSHR = state.dataIPShortCut->rNumericArgs(8);
     398            4 :             thisTESCoil.CoolingOnlyRatedCOP = state.dataIPShortCut->rNumericArgs(9);
     399              : 
     400            4 :             thisTESCoil.CoolingOnlyCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(11));
     401            4 :             if (thisTESCoil.CoolingOnlyCapFTempCurve == 0) {
     402            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(11)) {
     403            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     404            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(11)));
     405              :                 } else {
     406            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     407            0 :                     ShowContinueError(
     408            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(11), state.dataIPShortCut->cAlphaArgs(11)));
     409              :                 }
     410            0 :                 ErrorsFound = true;
     411              :             } else {
     412              :                 // Verify Curve Object
     413           12 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     414              :                                                                  thisTESCoil.CoolingOnlyCapFTempCurve,        // Curve index
     415              :                                                                  {2},                                         // Valid dimensions
     416              :                                                                  RoutineName,                                 // Routine name
     417              :                                                                  cCurrentModuleObject,                        // Object Type
     418              :                                                                  thisTESCoil.Name,                            // Object Name
     419            4 :                                                                  state.dataIPShortCut->cAlphaFieldNames(11)); // Field Name
     420              :             }
     421              : 
     422            4 :             thisTESCoil.CoolingOnlyCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(12));
     423            4 :             if (thisTESCoil.CoolingOnlyCapFFlowCurve == 0) {
     424            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(12)) {
     425            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     426            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(12)));
     427              :                 } else {
     428            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     429            0 :                     ShowContinueError(
     430            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(12), state.dataIPShortCut->cAlphaArgs(12)));
     431              :                 }
     432            0 :                 ErrorsFound = true;
     433              :             } else {
     434              :                 // Verify Curve Object, any curve with just x as single independent variable
     435           12 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     436              :                                                                  thisTESCoil.CoolingOnlyCapFFlowCurve,        // Curve index
     437              :                                                                  {1},                                         // Valid dimensions
     438              :                                                                  RoutineName,                                 // Routine name
     439              :                                                                  cCurrentModuleObject,                        // Object Type
     440              :                                                                  thisTESCoil.Name,                            // Object Name
     441            4 :                                                                  state.dataIPShortCut->cAlphaFieldNames(12)); // Field Name
     442              :             }
     443              : 
     444            4 :             thisTESCoil.CoolingOnlyEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(13));
     445            4 :             if (thisTESCoil.CoolingOnlyEIRFTempCurve == 0) {
     446            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(13)) {
     447            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     448            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(13)));
     449              :                 } else {
     450            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     451            0 :                     ShowContinueError(
     452            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(13), state.dataIPShortCut->cAlphaArgs(13)));
     453              :                 }
     454            0 :                 ErrorsFound = true;
     455              :             } else {
     456              :                 // Verify Curve Object
     457           12 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     458              :                                                                  thisTESCoil.CoolingOnlyEIRFTempCurve,        // Curve index
     459              :                                                                  {2},                                         // Valid dimensions
     460              :                                                                  RoutineName,                                 // Routine name
     461              :                                                                  cCurrentModuleObject,                        // Object Type
     462              :                                                                  thisTESCoil.Name,                            // Object Name
     463            4 :                                                                  state.dataIPShortCut->cAlphaFieldNames(13)); // Field Name
     464              :             }
     465              : 
     466            4 :             thisTESCoil.CoolingOnlyEIRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(14));
     467            4 :             if (thisTESCoil.CoolingOnlyEIRFFlowCurve == 0) {
     468            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(14)) {
     469            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     470            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(14)));
     471              :                 } else {
     472            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     473            0 :                     ShowContinueError(
     474            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(14), state.dataIPShortCut->cAlphaArgs(14)));
     475              :                 }
     476            0 :                 ErrorsFound = true;
     477              :             } else {
     478              :                 // Verify Curve Object, any curve with just x as single independent variable
     479           12 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     480              :                                                                  thisTESCoil.CoolingOnlyEIRFFlowCurve,        // Curve index
     481              :                                                                  {1},                                         // Valid dimensions
     482              :                                                                  RoutineName,                                 // Routine name
     483              :                                                                  cCurrentModuleObject,                        // Object Type
     484              :                                                                  thisTESCoil.Name,                            // Object Name
     485            4 :                                                                  state.dataIPShortCut->cAlphaFieldNames(14)); // Field Name
     486              :             }
     487              : 
     488            4 :             thisTESCoil.CoolingOnlyPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(15));
     489            4 :             if (thisTESCoil.CoolingOnlyPLFFPLRCurve == 0) {
     490            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(15)) {
     491            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     492            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(15)));
     493              :                 } else {
     494            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     495            0 :                     ShowContinueError(
     496            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(15), state.dataIPShortCut->cAlphaArgs(15)));
     497              :                 }
     498            0 :                 ErrorsFound = true;
     499              :             } else {
     500              :                 // Verify Curve Object, any curve with just x as single independent variable
     501           12 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     502              :                                                                  thisTESCoil.CoolingOnlyPLFFPLRCurve,         // Curve index
     503              :                                                                  {1},                                         // Valid dimensions
     504              :                                                                  RoutineName,                                 // Routine name
     505              :                                                                  cCurrentModuleObject,                        // Object Type
     506              :                                                                  thisTESCoil.Name,                            // Object Name
     507            4 :                                                                  state.dataIPShortCut->cAlphaFieldNames(15)); // Field Name
     508              :             }
     509              : 
     510            4 :             thisTESCoil.CoolingOnlySHRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(16));
     511            4 :             if (thisTESCoil.CoolingOnlySHRFTempCurve == 0) {
     512            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(16)) {
     513            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     514            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(16)));
     515              :                 } else {
     516            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     517            0 :                     ShowContinueError(
     518            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(16), state.dataIPShortCut->cAlphaArgs(16)));
     519              :                 }
     520            0 :                 ErrorsFound = true;
     521              :             } else {
     522              :                 // Verify Curve Object
     523           12 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     524              :                                                                  thisTESCoil.CoolingOnlySHRFTempCurve,        // Curve index
     525              :                                                                  {2},                                         // Valid dimensions
     526              :                                                                  RoutineName,                                 // Routine name
     527              :                                                                  cCurrentModuleObject,                        // Object Type
     528              :                                                                  thisTESCoil.Name,                            // Object Name
     529            4 :                                                                  state.dataIPShortCut->cAlphaFieldNames(16)); // Field Name
     530              :             }
     531              : 
     532            4 :             thisTESCoil.CoolingOnlySHRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(17));
     533            4 :             if (thisTESCoil.CoolingOnlySHRFFlowCurve == 0) {
     534            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(17)) {
     535            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     536            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(17)));
     537              :                 } else {
     538            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     539            0 :                     ShowContinueError(
     540            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(17), state.dataIPShortCut->cAlphaArgs(17)));
     541              :                 }
     542            0 :                 ErrorsFound = true;
     543              :             } else {
     544              :                 // Verify Curve Object, any curve with just x as single independent variable
     545           12 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     546              :                                                                  thisTESCoil.CoolingOnlySHRFFlowCurve,        // Curve index
     547              :                                                                  {1},                                         // Valid dimensions
     548              :                                                                  RoutineName,                                 // Routine name
     549              :                                                                  cCurrentModuleObject,                        // Object Type
     550              :                                                                  thisTESCoil.Name,                            // Object Name
     551            4 :                                                                  state.dataIPShortCut->cAlphaFieldNames(17)); // Field Name
     552              :             }
     553              :         }
     554              : 
     555            4 :         BooleanSwitch const answer2 = getYesNoValue(state.dataIPShortCut->cAlphaArgs(18));
     556            4 :         switch (answer2) {
     557            4 :         case BooleanSwitch::Yes:
     558              :         case BooleanSwitch::No:
     559            4 :             thisTESCoil.CoolingAndChargeModeAvailable = static_cast<bool>(answer2);
     560            4 :             break;
     561            0 :         default:
     562            0 :             thisTESCoil.CoolingAndChargeModeAvailable = false;
     563            0 :             ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     564            0 :             ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(18), state.dataIPShortCut->cAlphaArgs(18)));
     565            0 :             ShowContinueError(state, "Available choices are Yes or No.");
     566            0 :             ErrorsFound = true;
     567              :         }
     568              : 
     569            4 :         if (thisTESCoil.CoolingAndChargeModeAvailable) {
     570              : 
     571            3 :             thisTESCoil.CoolingAndChargeRatedTotCap = state.dataIPShortCut->rNumericArgs(10); // gross total evaporator cooling capacity [W]
     572            3 :             thisTESCoil.CoolingAndChargeRatedTotCapSizingFactor =
     573            3 :                 state.dataIPShortCut->rNumericArgs(11); // sizing factor for gross total evaporator [ ]
     574            3 :             thisTESCoil.CoolingAndChargeRatedChargeCap =
     575            3 :                 state.dataIPShortCut->rNumericArgs(12); // net storage charging capacity at rating conditions [W]
     576            3 :             thisTESCoil.CoolingAndChargeRatedChargeCapSizingFactor =
     577            3 :                 state.dataIPShortCut->rNumericArgs(13);                                            // sizing factor for charging capacity [ ]
     578            3 :             thisTESCoil.CoolingAndChargeRatedSHR = state.dataIPShortCut->rNumericArgs(14);         // Sensible heat ratio (sens cap/total cap)  [W/W]
     579            3 :             thisTESCoil.CoolingAndChargeCoolingRatedCOP = state.dataIPShortCut->rNumericArgs(15);  // Coefficient of performance , for cooling [W/W]
     580            3 :             thisTESCoil.CoolingAndChargeChargingRatedCOP = state.dataIPShortCut->rNumericArgs(16); // Coefficient of performance , for charging [W/W]
     581              : 
     582            3 :             thisTESCoil.CoolingAndChargeCoolingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(19));
     583            3 :             if (thisTESCoil.CoolingAndChargeCoolingCapFTempCurve == 0) {
     584            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(19)) {
     585            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     586            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(19)));
     587              :                 } else {
     588            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     589            0 :                     ShowContinueError(
     590            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(19), state.dataIPShortCut->cAlphaArgs(19)));
     591              :                 }
     592            0 :                 ErrorsFound = true;
     593              :             } else {
     594              :                 // Verify Curve Object
     595            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     596              :                                                                  thisTESCoil.CoolingAndChargeCoolingCapFTempCurve, // Curve index
     597              :                                                                  {3},                                              // Valid dimensions
     598              :                                                                  RoutineName,                                      // Routine name
     599              :                                                                  cCurrentModuleObject,                             // Object Type
     600              :                                                                  thisTESCoil.Name,                                 // Object Name
     601            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(19));      // Field Name
     602              :             }
     603              : 
     604            3 :             thisTESCoil.CoolingAndChargeCoolingCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(20));
     605            3 :             if (thisTESCoil.CoolingAndChargeCoolingCapFFlowCurve == 0) {
     606            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(20)) {
     607            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     608            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(20)));
     609              :                 } else {
     610            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     611            0 :                     ShowContinueError(
     612            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(20), state.dataIPShortCut->cAlphaArgs(20)));
     613              :                 }
     614            0 :                 ErrorsFound = true;
     615              :             } else {
     616              :                 // Verify Curve Object, any curve with just x as single independent variable
     617            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     618              :                                                                  thisTESCoil.CoolingAndChargeCoolingCapFFlowCurve, // Curve index
     619              :                                                                  {1},                                              // Valid dimensions
     620              :                                                                  RoutineName,                                      // Routine name
     621              :                                                                  cCurrentModuleObject,                             // Object Type
     622              :                                                                  thisTESCoil.Name,                                 // Object Name
     623            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(20));      // Field Name
     624              :             }
     625            3 :             thisTESCoil.CoolingAndChargeCoolingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(21));
     626            3 :             if (thisTESCoil.CoolingAndChargeCoolingEIRFTempCurve == 0) {
     627            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(21)) {
     628            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     629            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(21)));
     630              :                 } else {
     631            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     632            0 :                     ShowContinueError(
     633            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(21), state.dataIPShortCut->cAlphaArgs(21)));
     634              :                 }
     635            0 :                 ErrorsFound = true;
     636              :             } else {
     637              :                 // Verify Curve Object
     638            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     639              :                                                                  thisTESCoil.CoolingAndChargeCoolingEIRFTempCurve, // Curve index
     640              :                                                                  {3},                                              // Valid dimensions
     641              :                                                                  RoutineName,                                      // Routine name
     642              :                                                                  cCurrentModuleObject,                             // Object Type
     643              :                                                                  thisTESCoil.Name,                                 // Object Name
     644            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(21));      // Field Name
     645              :             }
     646              : 
     647            3 :             thisTESCoil.CoolingAndChargeCoolingEIRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(22));
     648            3 :             if (thisTESCoil.CoolingAndChargeCoolingEIRFFlowCurve == 0) {
     649            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(22)) {
     650            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     651            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(22)));
     652              :                 } else {
     653            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     654            0 :                     ShowContinueError(
     655            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(22), state.dataIPShortCut->cAlphaArgs(22)));
     656              :                 }
     657            0 :                 ErrorsFound = true;
     658              :             } else {
     659              :                 // Verify Curve Object, any curve with just x as single independent variable
     660            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     661              :                                                                  thisTESCoil.CoolingAndChargeCoolingEIRFFlowCurve, // Curve index
     662              :                                                                  {1},                                              // Valid dimensions
     663              :                                                                  RoutineName,                                      // Routine name
     664              :                                                                  cCurrentModuleObject,                             // Object Type
     665              :                                                                  thisTESCoil.Name,                                 // Object Name
     666            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(22));      // Field Name
     667              :             }
     668              : 
     669            3 :             thisTESCoil.CoolingAndChargeCoolingPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(23));
     670            3 :             if (thisTESCoil.CoolingAndChargeCoolingPLFFPLRCurve == 0) {
     671            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(23)) {
     672            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     673            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(23)));
     674              :                 } else {
     675            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     676            0 :                     ShowContinueError(
     677            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(23), state.dataIPShortCut->cAlphaArgs(23)));
     678              :                 }
     679            0 :                 ErrorsFound = true;
     680              :             } else {
     681              :                 // Verify Curve Object, any curve with just x as single independent variable
     682            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     683              :                                                                  thisTESCoil.CoolingAndChargeCoolingPLFFPLRCurve, // Curve index
     684              :                                                                  {1},                                             // Valid dimensions
     685              :                                                                  RoutineName,                                     // Routine name
     686              :                                                                  cCurrentModuleObject,                            // Object Type
     687              :                                                                  thisTESCoil.Name,                                // Object Name
     688            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(23));     // Field Name
     689              :             }
     690              : 
     691            3 :             thisTESCoil.CoolingAndChargeChargingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(24));
     692            3 :             if (thisTESCoil.CoolingAndChargeChargingCapFTempCurve == 0) {
     693            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(24)) {
     694            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     695            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(24)));
     696              :                 } else {
     697            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     698            0 :                     ShowContinueError(
     699            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(24), state.dataIPShortCut->cAlphaArgs(24)));
     700              :                 }
     701            0 :                 ErrorsFound = true;
     702              :             } else {
     703              :                 // Verify Curve Object
     704            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     705              :                                                                  thisTESCoil.CoolingAndChargeChargingCapFTempCurve, // Curve index
     706              :                                                                  {3},                                               // Valid dimensions
     707              :                                                                  RoutineName,                                       // Routine name
     708              :                                                                  cCurrentModuleObject,                              // Object Type
     709              :                                                                  thisTESCoil.Name,                                  // Object Name
     710            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(24));       // Field Name
     711              :             }
     712              : 
     713            3 :             thisTESCoil.CoolingAndChargeChargingCapFEvapPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(25));
     714            3 :             if (thisTESCoil.CoolingAndChargeChargingCapFEvapPLRCurve == 0) {
     715            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(25)) {
     716            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     717            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(25)));
     718              :                 } else {
     719            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     720            0 :                     ShowContinueError(
     721            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(25), state.dataIPShortCut->cAlphaArgs(25)));
     722              :                 }
     723            0 :                 ErrorsFound = true;
     724              :             } else {
     725              :                 // Verify Curve Object, any curve with just x as single independent variable
     726            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     727              :                                                                  thisTESCoil.CoolingAndChargeChargingCapFEvapPLRCurve, // Curve index
     728              :                                                                  {1},                                                  // Valid dimensions
     729              :                                                                  RoutineName,                                          // Routine name
     730              :                                                                  cCurrentModuleObject,                                 // Object Type
     731              :                                                                  thisTESCoil.Name,                                     // Object Name
     732            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(25));          // Field Name
     733              :             }
     734              : 
     735            3 :             thisTESCoil.CoolingAndChargeChargingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(26));
     736            3 :             if (thisTESCoil.CoolingAndChargeChargingEIRFTempCurve == 0) {
     737            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(26)) {
     738            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     739            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(26)));
     740              :                 } else {
     741            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     742            0 :                     ShowContinueError(
     743            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(26), state.dataIPShortCut->cAlphaArgs(26)));
     744              :                 }
     745            0 :                 ErrorsFound = true;
     746              :             } else {
     747              :                 // Verify Curve Object
     748            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     749              :                                                                  thisTESCoil.CoolingAndChargeChargingEIRFTempCurve, // Curve index
     750              :                                                                  {3},                                               // Valid dimensions
     751              :                                                                  RoutineName,                                       // Routine name
     752              :                                                                  cCurrentModuleObject,                              // Object Type
     753              :                                                                  thisTESCoil.Name,                                  // Object Name
     754            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(26));       // Field Name
     755              :             }
     756              : 
     757            3 :             thisTESCoil.CoolingAndChargeChargingEIRFFLowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(27));
     758            3 :             if (thisTESCoil.CoolingAndChargeChargingEIRFFLowCurve == 0) {
     759            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(27)) {
     760            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     761            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(27)));
     762              :                 } else {
     763            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     764            0 :                     ShowContinueError(
     765            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(27), state.dataIPShortCut->cAlphaArgs(27)));
     766              :                 }
     767            0 :                 ErrorsFound = true;
     768              :             } else {
     769              :                 // Verify Curve Object, any curve with just x as single independent variable
     770            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     771              :                                                                  thisTESCoil.CoolingAndChargeChargingEIRFFLowCurve, // Curve index
     772              :                                                                  {1},                                               // Valid dimensions
     773              :                                                                  RoutineName,                                       // Routine name
     774              :                                                                  cCurrentModuleObject,                              // Object Type
     775              :                                                                  thisTESCoil.Name,                                  // Object Name
     776            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(27));       // Field Name
     777              :             }
     778              : 
     779            3 :             thisTESCoil.CoolingAndChargeChargingPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(28));
     780            3 :             if (thisTESCoil.CoolingAndChargeChargingPLFFPLRCurve == 0) {
     781            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(28)) {
     782            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     783            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(28)));
     784              :                 } else {
     785            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     786            0 :                     ShowContinueError(
     787            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(28), state.dataIPShortCut->cAlphaArgs(28)));
     788              :                 }
     789            0 :                 ErrorsFound = true;
     790              :             } else {
     791              :                 // Verify Curve Object, any curve with just x as single independent variable
     792            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     793              :                                                                  thisTESCoil.CoolingAndChargeChargingPLFFPLRCurve, // Curve index
     794              :                                                                  {1},                                              // Valid dimensions
     795              :                                                                  RoutineName,                                      // Routine name
     796              :                                                                  cCurrentModuleObject,                             // Object Type
     797              :                                                                  thisTESCoil.Name,                                 // Object Name
     798            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(28));      // Field Name
     799              :             }
     800              : 
     801            3 :             thisTESCoil.CoolingAndChargeSHRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(29));
     802            3 :             if (thisTESCoil.CoolingAndChargeSHRFTempCurve == 0) {
     803            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(29)) {
     804            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     805            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(29)));
     806              :                 } else {
     807            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     808            0 :                     ShowContinueError(
     809            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(29), state.dataIPShortCut->cAlphaArgs(29)));
     810              :                 }
     811            0 :                 ErrorsFound = true;
     812              :             } else {
     813              :                 // Verify Curve Object
     814            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     815              :                                                                  thisTESCoil.CoolingAndChargeSHRFTempCurve, // Curve index
     816              :                                                                  {2, 3},                                    // Valid dimensions  // MULTIPLECURVEDIMS
     817              :                                                                  RoutineName,                               // Routine name
     818              :                                                                  cCurrentModuleObject,                      // Object Type
     819              :                                                                  thisTESCoil.Name,                          // Object Name
     820            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(29)); // Field Name
     821              :             }
     822              : 
     823            3 :             thisTESCoil.CoolingAndChargeSHRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(30));
     824            3 :             if (thisTESCoil.CoolingAndChargeSHRFFlowCurve == 0) {
     825            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(30)) {
     826            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     827            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(30)));
     828              :                 } else {
     829            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     830            0 :                     ShowContinueError(
     831            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(30), state.dataIPShortCut->cAlphaArgs(30)));
     832              :                 }
     833            0 :                 ErrorsFound = true;
     834              :             } else {
     835              :                 // Verify Curve Object, any curve with just x as single independent variable
     836            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     837              :                                                                  thisTESCoil.CoolingAndChargeSHRFFlowCurve,   // Curve index
     838              :                                                                  {1},                                         // Valid dimensions
     839              :                                                                  RoutineName,                                 // Routine name
     840              :                                                                  cCurrentModuleObject,                        // Object Type
     841              :                                                                  thisTESCoil.Name,                            // Object Name
     842            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(30)); // Field Name
     843              :             }
     844              : 
     845              :         } // Cooling and Charge Mode available
     846              : 
     847            4 :         BooleanSwitch answer3 = getYesNoValue(state.dataIPShortCut->cAlphaArgs(31));
     848            4 :         switch (answer3) {
     849            4 :         case BooleanSwitch::Yes:
     850              :         case BooleanSwitch::No:
     851            4 :             thisTESCoil.CoolingAndDischargeModeAvailable = static_cast<bool>(answer3);
     852            4 :             break;
     853            0 :         default:
     854            0 :             thisTESCoil.CoolingAndDischargeModeAvailable = false;
     855            0 :             ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     856            0 :             ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(31), state.dataIPShortCut->cAlphaArgs(31)));
     857            0 :             ShowContinueError(state, "Available choices are Yes or No.");
     858            0 :             ErrorsFound = true;
     859              :         }
     860              : 
     861            4 :         if (thisTESCoil.CoolingAndDischargeModeAvailable) {
     862              : 
     863            1 :             thisTESCoil.CoolingAndDischargeRatedTotCap = state.dataIPShortCut->rNumericArgs(17); // gross total evaporator cooling capacity  [W]
     864            1 :             thisTESCoil.CoolingAndDischargeRatedTotCapSizingFactor =
     865            1 :                 state.dataIPShortCut->rNumericArgs(18); // sizing factor gross total cooling capacity []
     866            1 :             thisTESCoil.CoolingAndDischargeRatedDischargeCap = state.dataIPShortCut->rNumericArgs(19); // net storage discharging capacity  [W]
     867            1 :             thisTESCoil.CoolingAndDischargeRatedDischargeCapSizingFactor =
     868            1 :                 state.dataIPShortCut->rNumericArgs(20);                                              // sizing factor discharging capacity []
     869            1 :             thisTESCoil.CoolingAndDischargeRatedSHR = state.dataIPShortCut->rNumericArgs(21);        // Sensible heat ratio (sens cap/total cap) [W/W]
     870            1 :             thisTESCoil.CoolingAndDischargeCoolingRatedCOP = state.dataIPShortCut->rNumericArgs(22); // Coefficient of performance , for cooling [W/W]
     871            1 :             thisTESCoil.CoolingAndDischargeDischargingRatedCOP =
     872            1 :                 state.dataIPShortCut->rNumericArgs(23); // Coefficient of performance , for charging [W/W]
     873              : 
     874            1 :             thisTESCoil.CoolingAndDischargeCoolingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(32));
     875            1 :             if (thisTESCoil.CoolingAndDischargeCoolingCapFTempCurve == 0) {
     876            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(32)) {
     877            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     878            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(32)));
     879              :                 } else {
     880            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     881            0 :                     ShowContinueError(
     882            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(32), state.dataIPShortCut->cAlphaArgs(32)));
     883              :                 }
     884            0 :                 ErrorsFound = true;
     885              :             } else {
     886              :                 // Verify Curve Object
     887            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     888              :                                                                  thisTESCoil.CoolingAndDischargeCoolingCapFTempCurve, // Curve index
     889              :                                                                  {3},                                                 // Valid dimensions
     890              :                                                                  RoutineName,                                         // Routine name
     891              :                                                                  cCurrentModuleObject,                                // Object Type
     892              :                                                                  thisTESCoil.Name,                                    // Object Name
     893            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(32));         // Field Name
     894              :             }
     895              : 
     896            1 :             thisTESCoil.CoolingAndDischargeCoolingCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(33));
     897            1 :             if (thisTESCoil.CoolingAndDischargeCoolingCapFFlowCurve == 0) {
     898            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(33)) {
     899            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     900            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(33)));
     901              :                 } else {
     902            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     903            0 :                     ShowContinueError(
     904            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(33), state.dataIPShortCut->cAlphaArgs(33)));
     905              :                 }
     906            0 :                 ErrorsFound = true;
     907              :             } else {
     908              :                 // Verify Curve Object, any curve with just x as single independent variable
     909            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     910              :                                                                  thisTESCoil.CoolingAndDischargeCoolingCapFFlowCurve, // Curve index
     911              :                                                                  {1},                                                 // Valid dimensions
     912              :                                                                  RoutineName,                                         // Routine name
     913              :                                                                  cCurrentModuleObject,                                // Object Type
     914              :                                                                  thisTESCoil.Name,                                    // Object Name
     915            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(33));         // Field Name
     916              :             }
     917              : 
     918            1 :             thisTESCoil.CoolingAndDischargeCoolingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(34));
     919            1 :             if (thisTESCoil.CoolingAndDischargeCoolingEIRFTempCurve == 0) {
     920            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(34)) {
     921            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     922            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(34)));
     923              :                 } else {
     924            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     925            0 :                     ShowContinueError(
     926            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(34), state.dataIPShortCut->cAlphaArgs(34)));
     927              :                 }
     928            0 :                 ErrorsFound = true;
     929              :             } else {
     930              :                 // Verify Curve Object
     931            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     932              :                                                                  thisTESCoil.CoolingAndDischargeCoolingEIRFTempCurve, // Curve index
     933              :                                                                  {3},                                                 // Valid dimensions
     934              :                                                                  RoutineName,                                         // Routine name
     935              :                                                                  cCurrentModuleObject,                                // Object Type
     936              :                                                                  thisTESCoil.Name,                                    // Object Name
     937            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(34));         // Field Name
     938              :             }
     939              : 
     940            1 :             thisTESCoil.CoolingAndDischargeCoolingEIRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(35));
     941            1 :             if (thisTESCoil.CoolingAndDischargeCoolingEIRFFlowCurve == 0) {
     942            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(35)) {
     943            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     944            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(35)));
     945              :                 } else {
     946            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     947            0 :                     ShowContinueError(
     948            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(35), state.dataIPShortCut->cAlphaArgs(35)));
     949              :                 }
     950            0 :                 ErrorsFound = true;
     951              :             } else {
     952              :                 // Verify Curve Object, any curve with just x as single independent variable
     953            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     954              :                                                                  thisTESCoil.CoolingAndDischargeCoolingEIRFFlowCurve, // Curve index
     955              :                                                                  {1},                                                 // Valid dimensions
     956              :                                                                  RoutineName,                                         // Routine name
     957              :                                                                  cCurrentModuleObject,                                // Object Type
     958              :                                                                  thisTESCoil.Name,                                    // Object Name
     959            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(35));         // Field Name
     960              :             }
     961              : 
     962            1 :             thisTESCoil.CoolingAndDischargeCoolingPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(36));
     963            1 :             if (thisTESCoil.CoolingAndDischargeCoolingPLFFPLRCurve == 0) {
     964            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(36)) {
     965            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     966            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(36)));
     967              :                 } else {
     968            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     969            0 :                     ShowContinueError(
     970            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(36), state.dataIPShortCut->cAlphaArgs(36)));
     971              :                 }
     972            0 :                 ErrorsFound = true;
     973              :             } else {
     974              :                 // Verify Curve Object, any curve with just x as single independent variable
     975            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     976              :                                                                  thisTESCoil.CoolingAndDischargeCoolingPLFFPLRCurve, // Curve index
     977              :                                                                  {1},                                                // Valid dimensions
     978              :                                                                  RoutineName,                                        // Routine name
     979              :                                                                  cCurrentModuleObject,                               // Object Type
     980              :                                                                  thisTESCoil.Name,                                   // Object Name
     981            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(36));        // Field Name
     982              :             }
     983              : 
     984            1 :             thisTESCoil.CoolingAndDischargeDischargingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(37));
     985            1 :             if (thisTESCoil.CoolingAndDischargeDischargingCapFTempCurve == 0) {
     986            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(37)) {
     987            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     988            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(37)));
     989              :                 } else {
     990            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
     991            0 :                     ShowContinueError(
     992            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(37), state.dataIPShortCut->cAlphaArgs(37)));
     993              :                 }
     994            0 :                 ErrorsFound = true;
     995              :             } else {
     996              :                 // Verify Curve Object
     997            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
     998              :                                                                  thisTESCoil.CoolingAndDischargeDischargingCapFTempCurve, // Curve index
     999              :                                                                  {3},                                                     // Valid dimensions
    1000              :                                                                  RoutineName,                                             // Routine name
    1001              :                                                                  cCurrentModuleObject,                                    // Object Type
    1002              :                                                                  thisTESCoil.Name,                                        // Object Name
    1003            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(37));             // Field Name
    1004              :             }
    1005              : 
    1006            1 :             thisTESCoil.CoolingAndDischargeDischargingCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(38));
    1007            1 :             if (thisTESCoil.CoolingAndDischargeDischargingCapFFlowCurve == 0) {
    1008            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(38)) {
    1009            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1010            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(38)));
    1011              :                 } else {
    1012            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1013            0 :                     ShowContinueError(
    1014            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(38), state.dataIPShortCut->cAlphaArgs(38)));
    1015              :                 }
    1016            0 :                 ErrorsFound = true;
    1017              :             } else {
    1018              :                 // Verify Curve Object, any curve with just x as single independent variable
    1019            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1020              :                                                                  thisTESCoil.CoolingAndDischargeDischargingCapFFlowCurve, // Curve index
    1021              :                                                                  {1},                                                     // Valid dimensions
    1022              :                                                                  RoutineName,                                             // Routine name
    1023              :                                                                  cCurrentModuleObject,                                    // Object Type
    1024              :                                                                  thisTESCoil.Name,                                        // Object Name
    1025            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(38));             // Field Name
    1026              :             }
    1027              : 
    1028            1 :             thisTESCoil.CoolingAndDischargeDischargingCapFEvapPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(39));
    1029            1 :             if (thisTESCoil.CoolingAndDischargeDischargingCapFEvapPLRCurve == 0) {
    1030            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(39)) {
    1031            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1032            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(39)));
    1033              :                 } else {
    1034            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1035            0 :                     ShowContinueError(
    1036            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(39), state.dataIPShortCut->cAlphaArgs(39)));
    1037              :                 }
    1038            0 :                 ErrorsFound = true;
    1039              :             } else {
    1040              :                 // Verify Curve Object, any curve with just x as single independent variable
    1041            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1042              :                                                                  thisTESCoil.CoolingAndDischargeDischargingCapFEvapPLRCurve, // Curve index
    1043              :                                                                  {1},                                                        // Valid dimensions
    1044              :                                                                  RoutineName,                                                // Routine name
    1045              :                                                                  cCurrentModuleObject,                                       // Object Type
    1046              :                                                                  thisTESCoil.Name,                                           // Object Name
    1047            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(39));                // Field Name
    1048              :             }
    1049              : 
    1050            1 :             thisTESCoil.CoolingAndDischargeDischargingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(40));
    1051            1 :             if (thisTESCoil.CoolingAndDischargeDischargingEIRFTempCurve == 0) {
    1052            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(40)) {
    1053            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1054            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(40)));
    1055              :                 } else {
    1056            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1057            0 :                     ShowContinueError(
    1058            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(40), state.dataIPShortCut->cAlphaArgs(40)));
    1059              :                 }
    1060            0 :                 ErrorsFound = true;
    1061              :             } else {
    1062              :                 // Verify Curve Object
    1063            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1064              :                                                                  thisTESCoil.CoolingAndDischargeDischargingEIRFTempCurve, // Curve index
    1065              :                                                                  {3},                                                     // Valid dimensions
    1066              :                                                                  RoutineName,                                             // Routine name
    1067              :                                                                  cCurrentModuleObject,                                    // Object Type
    1068              :                                                                  thisTESCoil.Name,                                        // Object Name
    1069            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(40));             // Field Name
    1070              :             }
    1071              : 
    1072            1 :             thisTESCoil.CoolingAndDischargeDischargingEIRFFLowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(41));
    1073            1 :             if (thisTESCoil.CoolingAndDischargeDischargingEIRFFLowCurve == 0) {
    1074            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(41)) {
    1075            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1076            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(41)));
    1077              :                 } else {
    1078            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1079            0 :                     ShowContinueError(
    1080            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(41), state.dataIPShortCut->cAlphaArgs(41)));
    1081              :                 }
    1082            0 :                 ErrorsFound = true;
    1083              :             } else {
    1084              :                 // Verify Curve Object, any curve with just x as single independent variable
    1085            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1086              :                                                                  thisTESCoil.CoolingAndDischargeDischargingEIRFFLowCurve, // Curve index
    1087              :                                                                  {1},                                                     // Valid dimensions
    1088              :                                                                  RoutineName,                                             // Routine name
    1089              :                                                                  cCurrentModuleObject,                                    // Object Type
    1090              :                                                                  thisTESCoil.Name,                                        // Object Name
    1091            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(41));             // Field Name
    1092              :             }
    1093              : 
    1094            1 :             thisTESCoil.CoolingAndDischargeDischargingPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(42));
    1095            1 :             if (thisTESCoil.CoolingAndDischargeDischargingPLFFPLRCurve == 0) {
    1096            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(42)) {
    1097            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1098            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(42)));
    1099              :                 } else {
    1100            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1101            0 :                     ShowContinueError(
    1102            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(42), state.dataIPShortCut->cAlphaArgs(42)));
    1103              :                 }
    1104            0 :                 ErrorsFound = true;
    1105              :             } else {
    1106              :                 // Verify Curve Object, any curve with just x as single independent variable
    1107            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1108              :                                                                  thisTESCoil.CoolingAndDischargeDischargingPLFFPLRCurve, // Curve index
    1109              :                                                                  {1},                                                    // Valid dimensions
    1110              :                                                                  RoutineName,                                            // Routine name
    1111              :                                                                  cCurrentModuleObject,                                   // Object Type
    1112              :                                                                  thisTESCoil.Name,                                       // Object Name
    1113            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(42));            // Field Name
    1114              :             }
    1115              : 
    1116            1 :             thisTESCoil.CoolingAndDischargeSHRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(43));
    1117            1 :             if (thisTESCoil.CoolingAndDischargeSHRFTempCurve == 0) {
    1118            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(43)) {
    1119            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1120            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(43)));
    1121              :                 } else {
    1122            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1123            0 :                     ShowContinueError(
    1124            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(43), state.dataIPShortCut->cAlphaArgs(43)));
    1125              :                 }
    1126            0 :                 ErrorsFound = true;
    1127              :             } else {
    1128              :                 // Verify Curve Object
    1129            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1130              :                                                                  thisTESCoil.CoolingAndDischargeSHRFTempCurve, // Curve index
    1131              :                                                                  {2, 3},               // Valid dimensions  // MULTIPLECURVEDIMS
    1132              :                                                                  RoutineName,          // Routine name
    1133              :                                                                  cCurrentModuleObject, // Object Type
    1134              :                                                                  thisTESCoil.Name,     // Object Name
    1135            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(43)); // Field Name
    1136              :             }
    1137              : 
    1138            1 :             thisTESCoil.CoolingAndDischargeSHRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(44));
    1139            1 :             if (thisTESCoil.CoolingAndDischargeSHRFFlowCurve == 0) {
    1140            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(44)) {
    1141            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1142            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(44)));
    1143              :                 } else {
    1144            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1145            0 :                     ShowContinueError(
    1146            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(44), state.dataIPShortCut->cAlphaArgs(44)));
    1147              :                 }
    1148            0 :                 ErrorsFound = true;
    1149              :             } else {
    1150              :                 // Verify Curve Object, any curve with just x as single independent variable
    1151            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1152              :                                                                  thisTESCoil.CoolingAndDischargeSHRFFlowCurve, // Curve index
    1153              :                                                                  {1},                                          // Valid dimensions
    1154              :                                                                  RoutineName,                                  // Routine name
    1155              :                                                                  cCurrentModuleObject,                         // Object Type
    1156              :                                                                  thisTESCoil.Name,                             // Object Name
    1157            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(44));  // Field Name
    1158              :             }
    1159              : 
    1160              :         } // cooling and discharge mode available
    1161              : 
    1162            4 :         BooleanSwitch answer4 = getYesNoValue(state.dataIPShortCut->cAlphaArgs(45));
    1163            4 :         switch (answer4) {
    1164            4 :         case BooleanSwitch::Yes:
    1165              :         case BooleanSwitch::No:
    1166            4 :             thisTESCoil.ChargeOnlyModeAvailable = static_cast<bool>(answer4);
    1167            4 :             break;
    1168            0 :         default:
    1169            0 :             thisTESCoil.ChargeOnlyModeAvailable = false;
    1170            0 :             ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1171            0 :             ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(45), state.dataIPShortCut->cAlphaArgs(45)));
    1172            0 :             ShowContinueError(state, "Available choices are Yes or No.");
    1173            0 :             ErrorsFound = true;
    1174              :         }
    1175              : 
    1176            4 :         if (thisTESCoil.ChargeOnlyModeAvailable) {
    1177              : 
    1178            1 :             thisTESCoil.ChargeOnlyRatedCapacity = state.dataIPShortCut->rNumericArgs(24); // net storage charging capacity at rating conditions [W]
    1179            1 :             thisTESCoil.ChargeOnlyRatedCapacitySizingFactor = state.dataIPShortCut->rNumericArgs(25); // sizing factor for charging capacity []
    1180            1 :             thisTESCoil.ChargeOnlyRatedCOP = state.dataIPShortCut->rNumericArgs(26); // coefficient of performance at rating conditions [W/W]
    1181              : 
    1182            1 :             thisTESCoil.ChargeOnlyChargingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(46));
    1183            1 :             if (thisTESCoil.ChargeOnlyChargingCapFTempCurve == 0) {
    1184            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(46)) {
    1185            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1186            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(46)));
    1187              :                 } else {
    1188            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1189            0 :                     ShowContinueError(
    1190            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(46), state.dataIPShortCut->cAlphaArgs(46)));
    1191              :                 }
    1192            0 :                 ErrorsFound = true;
    1193              :             } else {
    1194              :                 // Verify Curve Object
    1195            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1196              :                                                                  thisTESCoil.ChargeOnlyChargingCapFTempCurve, // Curve index
    1197              :                                                                  {2},                                         // Valid dimensions
    1198              :                                                                  RoutineName,                                 // Routine name
    1199              :                                                                  cCurrentModuleObject,                        // Object Type
    1200              :                                                                  thisTESCoil.Name,                            // Object Name
    1201            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(46)); // Field Name
    1202              :             }
    1203              : 
    1204            1 :             thisTESCoil.ChargeOnlyChargingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(47));
    1205            1 :             if (thisTESCoil.ChargeOnlyChargingEIRFTempCurve == 0) {
    1206            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(47)) {
    1207            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1208            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(47)));
    1209              :                 } else {
    1210            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1211            0 :                     ShowContinueError(
    1212            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(47), state.dataIPShortCut->cAlphaArgs(47)));
    1213              :                 }
    1214            0 :                 ErrorsFound = true;
    1215              :             } else {
    1216              :                 // Verify Curve Object
    1217            3 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1218              :                                                                  thisTESCoil.ChargeOnlyChargingEIRFTempCurve, // Curve index
    1219              :                                                                  {2},                                         // Valid dimensions
    1220              :                                                                  RoutineName,                                 // Routine name
    1221              :                                                                  cCurrentModuleObject,                        // Object Type
    1222              :                                                                  thisTESCoil.Name,                            // Object Name
    1223            1 :                                                                  state.dataIPShortCut->cAlphaFieldNames(47)); // Field Name
    1224              :             }
    1225              : 
    1226              :         } // Charge only mode available
    1227              : 
    1228            4 :         BooleanSwitch answer5 = getYesNoValue(state.dataIPShortCut->cAlphaArgs(48));
    1229            4 :         switch (answer5) {
    1230            4 :         case BooleanSwitch::Yes:
    1231              :         case BooleanSwitch::No:
    1232            4 :             thisTESCoil.DischargeOnlyModeAvailable = static_cast<bool>(answer5);
    1233            4 :             break;
    1234            0 :         default:
    1235            0 :             thisTESCoil.DischargeOnlyModeAvailable = false;
    1236            0 :             ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1237            0 :             ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(48), state.dataIPShortCut->cAlphaArgs(48)));
    1238            0 :             ShowContinueError(state, "Available choices are Yes or No.");
    1239            0 :             ErrorsFound = true;
    1240              :         }
    1241              : 
    1242            4 :         if (thisTESCoil.DischargeOnlyModeAvailable) {
    1243            3 :             thisTESCoil.DischargeOnlyRatedDischargeCap = state.dataIPShortCut->rNumericArgs(27); // gross total evaporator cooling capacity  [W]
    1244            3 :             thisTESCoil.DischargeOnlyRatedDischargeCapSizingFactor = state.dataIPShortCut->rNumericArgs(28); // sizing factor for cooling capacity []
    1245            3 :             thisTESCoil.DischargeOnlyRatedSHR = state.dataIPShortCut->rNumericArgs(29); // sensible heat ratio (sens cap/total cap)
    1246            3 :             thisTESCoil.DischargeOnlyRatedCOP = state.dataIPShortCut->rNumericArgs(30); // coefficient of performance  for discharging [W/W]
    1247              : 
    1248            3 :             thisTESCoil.DischargeOnlyCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(49));
    1249            3 :             if (thisTESCoil.DischargeOnlyCapFTempCurve == 0) {
    1250            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(49)) {
    1251            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1252            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(49)));
    1253              :                 } else {
    1254            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1255            0 :                     ShowContinueError(
    1256            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(49), state.dataIPShortCut->cAlphaArgs(49)));
    1257              :                 }
    1258            0 :                 ErrorsFound = true;
    1259              :             } else {
    1260              :                 // Verify Curve Object
    1261            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1262              :                                                                  thisTESCoil.DischargeOnlyCapFTempCurve,      // Curve index
    1263              :                                                                  {2},                                         // Valid dimensions
    1264              :                                                                  RoutineName,                                 // Routine name
    1265              :                                                                  cCurrentModuleObject,                        // Object Type
    1266              :                                                                  thisTESCoil.Name,                            // Object Name
    1267            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(49)); // Field Name
    1268              :             }
    1269              : 
    1270            3 :             thisTESCoil.DischargeOnlyCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(50));
    1271            3 :             if (thisTESCoil.DischargeOnlyCapFFlowCurve == 0) {
    1272            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(50)) {
    1273            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1274            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(50)));
    1275              :                 } else {
    1276            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1277            0 :                     ShowContinueError(
    1278            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(50), state.dataIPShortCut->cAlphaArgs(50)));
    1279              :                 }
    1280            0 :                 ErrorsFound = true;
    1281              :             } else {
    1282              :                 // Verify Curve Object, any curve with just x as single independent variable
    1283            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1284              :                                                                  thisTESCoil.DischargeOnlyCapFFlowCurve,      // Curve index
    1285              :                                                                  {1},                                         // Valid dimensions
    1286              :                                                                  RoutineName,                                 // Routine name
    1287              :                                                                  cCurrentModuleObject,                        // Object Type
    1288              :                                                                  thisTESCoil.Name,                            // Object Name
    1289            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(50)); // Field Name
    1290              :             }
    1291              : 
    1292            3 :             thisTESCoil.DischargeOnlyEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(51));
    1293            3 :             if (thisTESCoil.DischargeOnlyEIRFTempCurve == 0) {
    1294            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(51)) {
    1295            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1296            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(51)));
    1297              :                 } else {
    1298            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1299            0 :                     ShowContinueError(
    1300            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(51), state.dataIPShortCut->cAlphaArgs(51)));
    1301              :                 }
    1302            0 :                 ErrorsFound = true;
    1303              :             } else {
    1304              :                 // Verify Curve Object
    1305            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1306              :                                                                  thisTESCoil.DischargeOnlyEIRFTempCurve,      // Curve index
    1307              :                                                                  {2},                                         // Valid dimensions
    1308              :                                                                  RoutineName,                                 // Routine name
    1309              :                                                                  cCurrentModuleObject,                        // Object Type
    1310              :                                                                  thisTESCoil.Name,                            // Object Name
    1311            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(51)); // Field Name
    1312              :             }
    1313              : 
    1314            3 :             thisTESCoil.DischargeOnlyEIRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(52));
    1315            3 :             if (thisTESCoil.DischargeOnlyEIRFFlowCurve == 0) {
    1316            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(52)) {
    1317            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1318            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(52)));
    1319              :                 } else {
    1320            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1321            0 :                     ShowContinueError(
    1322            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(52), state.dataIPShortCut->cAlphaArgs(52)));
    1323              :                 }
    1324            0 :                 ErrorsFound = true;
    1325              :             } else {
    1326              :                 // Verify Curve Object, any curve with just x as single independent variable
    1327            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1328              :                                                                  thisTESCoil.DischargeOnlyEIRFFlowCurve,      // Curve index
    1329              :                                                                  {1},                                         // Valid dimensions
    1330              :                                                                  RoutineName,                                 // Routine name
    1331              :                                                                  cCurrentModuleObject,                        // Object Type
    1332              :                                                                  thisTESCoil.Name,                            // Object Name
    1333            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(52)); // Field Name
    1334              :             }
    1335              : 
    1336            3 :             thisTESCoil.DischargeOnlyPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(53));
    1337            3 :             if (thisTESCoil.DischargeOnlyPLFFPLRCurve == 0) {
    1338            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(53)) {
    1339            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1340            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(53)));
    1341              :                 } else {
    1342            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1343            0 :                     ShowContinueError(
    1344            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(53), state.dataIPShortCut->cAlphaArgs(53)));
    1345              :                 }
    1346            0 :                 ErrorsFound = true;
    1347              :             } else {
    1348              :                 // Verify Curve Object, any curve with just x as single independent variable
    1349            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1350              :                                                                  thisTESCoil.DischargeOnlyPLFFPLRCurve,       // Curve index
    1351              :                                                                  {1},                                         // Valid dimensions
    1352              :                                                                  RoutineName,                                 // Routine name
    1353              :                                                                  cCurrentModuleObject,                        // Object Type
    1354              :                                                                  thisTESCoil.Name,                            // Object Name
    1355            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(53)); // Field Name
    1356              :             }
    1357              : 
    1358            3 :             thisTESCoil.DischargeOnlySHRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(54));
    1359            3 :             if (thisTESCoil.DischargeOnlySHRFTempCurve == 0) {
    1360            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(54)) {
    1361            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1362            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(54)));
    1363              :                 } else {
    1364            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1365            0 :                     ShowContinueError(
    1366            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(54), state.dataIPShortCut->cAlphaArgs(54)));
    1367              :                 }
    1368            0 :                 ErrorsFound = true;
    1369              :             } else {
    1370              :                 // Verify Curve Object
    1371            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1372              :                                                                  thisTESCoil.DischargeOnlySHRFTempCurve, // Curve index
    1373              :                                                                  {2, 3},                                 // Valid dimensions  // MULTIPLECURVEDIMS
    1374              :                                                                  RoutineName,                            // Routine name
    1375              :                                                                  cCurrentModuleObject,                   // Object Type
    1376              :                                                                  thisTESCoil.Name,                       // Object Name
    1377            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(54)); // Field Name
    1378              :             }
    1379              : 
    1380            3 :             thisTESCoil.DischargeOnlySHRFFLowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(55));
    1381            3 :             if (thisTESCoil.DischargeOnlySHRFFLowCurve == 0) {
    1382            0 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(55)) {
    1383            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1384            0 :                     ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(55)));
    1385              :                 } else {
    1386            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1387            0 :                     ShowContinueError(
    1388            0 :                         state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(55), state.dataIPShortCut->cAlphaArgs(55)));
    1389              :                 }
    1390            0 :                 ErrorsFound = true;
    1391              :             } else {
    1392              :                 // Verify Curve Object, any curve with just x as single independent variable
    1393            9 :                 ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
    1394              :                                                                  thisTESCoil.DischargeOnlySHRFFLowCurve,      // Curve index
    1395              :                                                                  {1},                                         // Valid dimensions
    1396              :                                                                  RoutineName,                                 // Routine name
    1397              :                                                                  cCurrentModuleObject,                        // Object Type
    1398              :                                                                  thisTESCoil.Name,                            // Object Name
    1399            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames(55)); // Field Name
    1400              :             }
    1401              : 
    1402              :         } // Discharge Only mode available
    1403              : 
    1404            4 :         thisTESCoil.AncillaryControlsPower = state.dataIPShortCut->rNumericArgs(31);
    1405            4 :         thisTESCoil.ColdWeatherMinimumTempLimit = state.dataIPShortCut->rNumericArgs(32);
    1406            4 :         thisTESCoil.ColdWeatherAncillaryPower = state.dataIPShortCut->rNumericArgs(33);
    1407            4 :         thisTESCoil.CondAirInletNodeNum = GetOnlySingleNode(state,
    1408            4 :                                                             state.dataIPShortCut->cAlphaArgs(56),
    1409              :                                                             ErrorsFound,
    1410              :                                                             DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
    1411            4 :                                                             thisTESCoil.Name,
    1412              :                                                             DataLoopNode::NodeFluidType::Air,
    1413              :                                                             DataLoopNode::ConnectionType::OutsideAirReference,
    1414              :                                                             NodeInputManager::CompFluidStream::Primary,
    1415              :                                                             ObjectIsNotParent);
    1416            4 :         thisTESCoil.CondAirOutletNodeNum = GetOnlySingleNode(state,
    1417            4 :                                                              state.dataIPShortCut->cAlphaArgs(57),
    1418              :                                                              ErrorsFound,
    1419              :                                                              DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
    1420            4 :                                                              thisTESCoil.Name,
    1421              :                                                              DataLoopNode::NodeFluidType::Air,
    1422              :                                                              DataLoopNode::ConnectionType::ReliefAir,
    1423              :                                                              NodeInputManager::CompFluidStream::Primary,
    1424              :                                                              ObjectIsNotParent);
    1425              : 
    1426            4 :         thisTESCoil.CondenserAirVolumeFlow = state.dataIPShortCut->rNumericArgs(34);
    1427            4 :         thisTESCoil.CondenserAirFlowSizingFactor = state.dataIPShortCut->rNumericArgs(35);
    1428              : 
    1429            4 :         thisTESCoil.CondenserType = static_cast<TESCondenserType>(getEnumValue(condenserTypesUC, state.dataIPShortCut->cAlphaArgs(58)));
    1430            4 :         if (thisTESCoil.CondenserType == TESCondenserType::Invalid) {
    1431            0 :             ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1432            0 :             ShowContinueError(state, format("{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(58), state.dataIPShortCut->cAlphaArgs(58)));
    1433            0 :             ShowContinueError(state, "Available choices are AirCooled or EvaporativelyCooled.");
    1434            0 :             ErrorsFound = true;
    1435              :         }
    1436              : 
    1437            4 :         thisTESCoil.EvapCondEffect = state.dataIPShortCut->rNumericArgs(36);
    1438            4 :         thisTESCoil.EvapCondPumpElecNomPower = state.dataIPShortCut->rNumericArgs(37);
    1439            4 :         thisTESCoil.BasinHeaterPowerFTempDiff = state.dataIPShortCut->rNumericArgs(38);
    1440            4 :         thisTESCoil.BasinHeaterSetpointTemp = state.dataIPShortCut->rNumericArgs(39);
    1441              : 
    1442            4 :         if (state.dataIPShortCut->lAlphaFieldBlanks(59)) {
    1443            4 :             thisTESCoil.basinHeaterAvailSched = Sched::GetScheduleAlwaysOn(state);
    1444            0 :         } else if ((thisTESCoil.basinHeaterAvailSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(59))) == nullptr) {
    1445            0 :             ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(59), state.dataIPShortCut->cAlphaArgs(59));
    1446            0 :             ErrorsFound = true;
    1447              :         }
    1448              : 
    1449            4 :         if (state.dataIPShortCut->lAlphaFieldBlanks(60)) {
    1450            4 :             thisTESCoil.EvapWaterSupplyMode = EvapWaterSupply::WaterSupplyFromMains;
    1451              :         } else {
    1452            0 :             thisTESCoil.EvapWaterSupplyName = state.dataIPShortCut->cAlphaArgs(60);
    1453            0 :             thisTESCoil.EvapWaterSupplyMode = EvapWaterSupply::WaterSupplyFromTank;
    1454            0 :             SetupTankDemandComponent(state,
    1455              :                                      thisTESCoil.Name,
    1456              :                                      cCurrentModuleObject,
    1457              :                                      thisTESCoil.EvapWaterSupplyName,
    1458              :                                      ErrorsFound,
    1459            0 :                                      thisTESCoil.EvapWaterSupTankID,
    1460            0 :                                      thisTESCoil.EvapWaterTankDemandARRID);
    1461              :         }
    1462              : 
    1463            4 :         if (state.dataIPShortCut->lAlphaFieldBlanks(61)) {
    1464            4 :             thisTESCoil.CondensateCollectMode = CondensateAction::Discard;
    1465              :         } else {
    1466            0 :             thisTESCoil.CondensateCollectName = state.dataIPShortCut->cAlphaArgs(61);
    1467            0 :             thisTESCoil.CondensateCollectMode = CondensateAction::ToTank;
    1468            0 :             SetupTankSupplyComponent(state,
    1469              :                                      thisTESCoil.Name,
    1470              :                                      cCurrentModuleObject,
    1471              :                                      thisTESCoil.CondensateCollectName,
    1472              :                                      ErrorsFound,
    1473            0 :                                      thisTESCoil.CondensateTankID,
    1474            0 :                                      thisTESCoil.CondensateTankSupplyARRID);
    1475              :         }
    1476              : 
    1477            4 :         if (!state.dataIPShortCut->lAlphaFieldBlanks(62)) {
    1478            1 :             thisTESCoil.TESPlantInletNodeNum = GetOnlySingleNode(state,
    1479            1 :                                                                  state.dataIPShortCut->cAlphaArgs(62),
    1480              :                                                                  ErrorsFound,
    1481              :                                                                  DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
    1482            1 :                                                                  state.dataIPShortCut->cAlphaArgs(1),
    1483              :                                                                  DataLoopNode::NodeFluidType::Water,
    1484              :                                                                  DataLoopNode::ConnectionType::Inlet,
    1485              :                                                                  NodeInputManager::CompFluidStream::Secondary,
    1486              :                                                                  ObjectIsNotParent);
    1487              : 
    1488            1 :             thisTESCoil.TESPlantConnectionAvailable = true;
    1489              :         } else {
    1490            3 :             thisTESCoil.TESPlantConnectionAvailable = false;
    1491              :         }
    1492            4 :         if (!state.dataIPShortCut->lAlphaFieldBlanks(63)) {
    1493            2 :             thisTESCoil.TESPlantOutletNodeNum = GetOnlySingleNode(state,
    1494            1 :                                                                   state.dataIPShortCut->cAlphaArgs(63),
    1495              :                                                                   ErrorsFound,
    1496              :                                                                   DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
    1497            1 :                                                                   state.dataIPShortCut->cAlphaArgs(1),
    1498              :                                                                   DataLoopNode::NodeFluidType::Water,
    1499              :                                                                   DataLoopNode::ConnectionType::Outlet,
    1500              :                                                                   NodeInputManager::CompFluidStream::Secondary,
    1501              :                                                                   ObjectIsNotParent);
    1502              :         } else {
    1503            3 :             if (thisTESCoil.TESPlantConnectionAvailable) {
    1504            0 :                 ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
    1505            0 :                 ShowContinueError(state, format("...{} cannot be blank.", state.dataIPShortCut->cAlphaFieldNames(63)));
    1506            0 :                 ErrorsFound = true;
    1507              :             }
    1508              :         }
    1509            4 :         if (thisTESCoil.TESPlantConnectionAvailable) {
    1510            3 :             TestCompSet(state,
    1511              :                         cCurrentModuleObject,
    1512            1 :                         state.dataIPShortCut->cAlphaArgs(1),
    1513            1 :                         state.dataIPShortCut->cAlphaArgs(62),
    1514            1 :                         state.dataIPShortCut->cAlphaArgs(63),
    1515              :                         "Water Nodes");
    1516              :         }
    1517              : 
    1518            4 :         if (!state.dataIPShortCut->lNumericFieldBlanks(40)) {
    1519            1 :             thisTESCoil.TESPlantDesignVolumeFlowRate = state.dataIPShortCut->rNumericArgs(40);
    1520              :         }
    1521            4 :         if (!state.dataIPShortCut->lNumericFieldBlanks(41)) {
    1522            1 :             thisTESCoil.TESPlantEffectiveness = state.dataIPShortCut->rNumericArgs(41);
    1523              :         }
    1524              : 
    1525            4 :         switch (thisTESCoil.StorageMedia) {
    1526            1 :         case MediaType::UserDefindFluid:
    1527              :         case MediaType::Water: {
    1528            1 :             Real64 TminRho = -9999.0;
    1529            1 :             Real64 TmaxRho = 9999.0;
    1530            1 :             Real64 TminCp = -9999.0;
    1531            1 :             Real64 TmaxCp = 9999.0;
    1532            1 :             if (!state.dataIPShortCut->lNumericFieldBlanks(42)) {
    1533            1 :                 thisTESCoil.MinimumFluidTankTempLimit = state.dataIPShortCut->rNumericArgs(42);
    1534              :             } else {
    1535            0 :                 thisTESCoil.glycol->getDensityTemperatureLimits(state, TminRho, TmaxRho);
    1536            0 :                 thisTESCoil.glycol->getSpecificHeatTemperatureLimits(state, TminCp, TmaxCp);
    1537            0 :                 thisTESCoil.MinimumFluidTankTempLimit = max(TminRho, TminCp);
    1538              :             }
    1539            1 :             if (!state.dataIPShortCut->lNumericFieldBlanks(43)) {
    1540            1 :                 thisTESCoil.MaximumFluidTankTempLimit = state.dataIPShortCut->rNumericArgs(43);
    1541              :             } else {
    1542            0 :                 thisTESCoil.glycol->getDensityTemperatureLimits(state, TminRho, TmaxRho);
    1543            0 :                 thisTESCoil.glycol->getSpecificHeatTemperatureLimits(state, TminCp, TmaxCp);
    1544            0 :                 thisTESCoil.MaximumFluidTankTempLimit = min(TmaxRho, TmaxCp);
    1545              :             }
    1546              :         }
    1547            4 :         default:
    1548              :             // nothing
    1549            4 :             break;
    1550              :         }
    1551              :     }
    1552              : 
    1553            1 :     if (ErrorsFound) {
    1554            0 :         ShowFatalError(state,
    1555            0 :                        format("{}Errors found in getting {} input. Preceding condition(s) causes termination.", RoutineName, cCurrentModuleObject));
    1556              :     }
    1557              : 
    1558              :     // setup reporting
    1559            5 :     for (int item = 1; item <= state.dataPackagedThermalStorageCoil->NumTESCoils; ++item) {
    1560            4 :         auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(item);
    1561              : 
    1562            4 :         SetupOutputVariable(state,
    1563              :                             "Cooling Coil Operating Mode Index",
    1564              :                             Constant::Units::None,
    1565            4 :                             thisTESCoil.curControlModeReport,
    1566              :                             OutputProcessor::TimeStepType::System,
    1567              :                             OutputProcessor::StoreType::Average,
    1568            4 :                             thisTESCoil.Name);
    1569              : 
    1570              :         // cCurrentModuleObject = "Coil:Cooling:DX:SingleSpeed:ThermalStorage"
    1571            8 :         SetupOutputVariable(state,
    1572              :                             "Cooling Coil Total Cooling Rate",
    1573              :                             Constant::Units::W,
    1574            4 :                             thisTESCoil.EvapTotCoolingRate,
    1575              :                             OutputProcessor::TimeStepType::System,
    1576              :                             OutputProcessor::StoreType::Average,
    1577            4 :                             thisTESCoil.Name);
    1578            8 :         SetupOutputVariable(state,
    1579              :                             "Cooling Coil Total Cooling Energy",
    1580              :                             Constant::Units::J,
    1581            4 :                             thisTESCoil.EvapTotCoolingEnergy,
    1582              :                             OutputProcessor::TimeStepType::System,
    1583              :                             OutputProcessor::StoreType::Sum,
    1584            4 :                             thisTESCoil.Name,
    1585              :                             Constant::eResource::EnergyTransfer,
    1586              :                             OutputProcessor::Group::HVAC,
    1587              :                             OutputProcessor::EndUseCat::CoolingCoils);
    1588            8 :         SetupOutputVariable(state,
    1589              :                             "Cooling Coil Sensible Cooling Rate",
    1590              :                             Constant::Units::W,
    1591            4 :                             thisTESCoil.EvapSensCoolingRate,
    1592              :                             OutputProcessor::TimeStepType::System,
    1593              :                             OutputProcessor::StoreType::Average,
    1594            4 :                             thisTESCoil.Name);
    1595            8 :         SetupOutputVariable(state,
    1596              :                             "Cooling Coil Sensible Cooling Energy",
    1597              :                             Constant::Units::J,
    1598            4 :                             thisTESCoil.EvapSensCoolingEnergy,
    1599              :                             OutputProcessor::TimeStepType::System,
    1600              :                             OutputProcessor::StoreType::Sum,
    1601            4 :                             thisTESCoil.Name);
    1602            8 :         SetupOutputVariable(state,
    1603              :                             "Cooling Coil Latent Cooling Rate",
    1604              :                             Constant::Units::W,
    1605            4 :                             thisTESCoil.EvapLatCoolingRate,
    1606              :                             OutputProcessor::TimeStepType::System,
    1607              :                             OutputProcessor::StoreType::Average,
    1608            4 :                             thisTESCoil.Name);
    1609            8 :         SetupOutputVariable(state,
    1610              :                             "Cooling Coil Latent Cooling Energy",
    1611              :                             Constant::Units::J,
    1612            4 :                             thisTESCoil.EvapLatCoolingEnergy,
    1613              :                             OutputProcessor::TimeStepType::System,
    1614              :                             OutputProcessor::StoreType::Sum,
    1615            4 :                             thisTESCoil.Name);
    1616            8 :         SetupOutputVariable(state,
    1617              :                             "Cooling Coil Electricity Rate",
    1618              :                             Constant::Units::W,
    1619            4 :                             thisTESCoil.ElecCoolingPower,
    1620              :                             OutputProcessor::TimeStepType::System,
    1621              :                             OutputProcessor::StoreType::Average,
    1622            4 :                             thisTESCoil.Name);
    1623            8 :         SetupOutputVariable(state,
    1624              :                             "Cooling Coil Electricity Energy",
    1625              :                             Constant::Units::J,
    1626            4 :                             thisTESCoil.ElecCoolingEnergy,
    1627              :                             OutputProcessor::TimeStepType::System,
    1628              :                             OutputProcessor::StoreType::Sum,
    1629            4 :                             thisTESCoil.Name,
    1630              :                             Constant::eResource::Electricity,
    1631              :                             OutputProcessor::Group::HVAC,
    1632              :                             OutputProcessor::EndUseCat::Cooling);
    1633              : 
    1634            8 :         SetupOutputVariable(state,
    1635              :                             "Cooling Coil Runtime Fraction",
    1636              :                             Constant::Units::None,
    1637            4 :                             thisTESCoil.RuntimeFraction,
    1638              :                             OutputProcessor::TimeStepType::System,
    1639              :                             OutputProcessor::StoreType::Average,
    1640            4 :                             thisTESCoil.Name);
    1641            8 :         SetupOutputVariable(state,
    1642              :                             "Cooling Coil Cold Weather Protection Electricity Energy",
    1643              :                             Constant::Units::J,
    1644            4 :                             thisTESCoil.ElectColdWeatherEnergy,
    1645              :                             OutputProcessor::TimeStepType::System,
    1646              :                             OutputProcessor::StoreType::Sum,
    1647            4 :                             thisTESCoil.Name,
    1648              :                             Constant::eResource::Electricity,
    1649              :                             OutputProcessor::Group::HVAC,
    1650              :                             OutputProcessor::EndUseCat::Cooling,
    1651              :                             "Thermal Protection");
    1652            8 :         SetupOutputVariable(state,
    1653              :                             "Cooling Coil Cold Weather Protection Electricity Rate",
    1654              :                             Constant::Units::W,
    1655            4 :                             thisTESCoil.ElectColdWeatherPower,
    1656              :                             OutputProcessor::TimeStepType::System,
    1657              :                             OutputProcessor::StoreType::Average,
    1658            4 :                             thisTESCoil.Name);
    1659              : 
    1660            8 :         SetupOutputVariable(state,
    1661              :                             "Cooling Coil Thermal Storage Mechanical Heat Transfer Rate",
    1662              :                             Constant::Units::W,
    1663            4 :                             thisTESCoil.QdotTES,
    1664              :                             OutputProcessor::TimeStepType::System,
    1665              :                             OutputProcessor::StoreType::Average,
    1666            4 :                             thisTESCoil.Name);
    1667              : 
    1668            8 :         SetupOutputVariable(state,
    1669              :                             "Cooling Coil Thermal Storage Mechanical Heat Transfer Energy",
    1670              :                             Constant::Units::J,
    1671            4 :                             thisTESCoil.Q_TES,
    1672              :                             OutputProcessor::TimeStepType::System,
    1673              :                             OutputProcessor::StoreType::Sum,
    1674            4 :                             thisTESCoil.Name);
    1675              : 
    1676            8 :         SetupOutputVariable(state,
    1677              :                             "Cooling Coil Thermal Storage Ambient Heat Transfer Rate",
    1678              :                             Constant::Units::W,
    1679            4 :                             thisTESCoil.QdotAmbient,
    1680              :                             OutputProcessor::TimeStepType::System,
    1681              :                             OutputProcessor::StoreType::Average,
    1682            4 :                             thisTESCoil.Name);
    1683              : 
    1684            8 :         SetupOutputVariable(state,
    1685              :                             "Cooling Coil Thermal Storage Ambient Heat Transfer Energy",
    1686              :                             Constant::Units::J,
    1687            4 :                             thisTESCoil.Q_Ambient,
    1688              :                             OutputProcessor::TimeStepType::System,
    1689              :                             OutputProcessor::StoreType::Sum,
    1690            4 :                             thisTESCoil.Name);
    1691              : 
    1692            4 :         if (thisTESCoil.TESPlantConnectionAvailable) {
    1693            2 :             SetupOutputVariable(state,
    1694              :                                 "Cooling Coil Thermal Storage Plant Heat Transfer Rate",
    1695              :                                 Constant::Units::W,
    1696            1 :                                 thisTESCoil.QdotPlant,
    1697              :                                 OutputProcessor::TimeStepType::System,
    1698              :                                 OutputProcessor::StoreType::Average,
    1699            1 :                                 thisTESCoil.Name);
    1700            2 :             SetupOutputVariable(state,
    1701              :                                 "Cooling Coil Thermal Storage Plant Heat Transfer Energy",
    1702              :                                 Constant::Units::J,
    1703            1 :                                 thisTESCoil.Q_Plant,
    1704              :                                 OutputProcessor::TimeStepType::System,
    1705              :                                 OutputProcessor::StoreType::Sum,
    1706            1 :                                 thisTESCoil.Name);
    1707              :         }
    1708              : 
    1709            4 :         if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    1710            2 :             SetupOutputVariable(state,
    1711              :                                 "Cooling Coil Condenser Inlet Temperature",
    1712              :                                 Constant::Units::C,
    1713            1 :                                 thisTESCoil.CondInletTemp,
    1714              :                                 OutputProcessor::TimeStepType::System,
    1715              :                                 OutputProcessor::StoreType::Average,
    1716            1 :                                 thisTESCoil.Name);
    1717              : 
    1718            1 :             if (thisTESCoil.EvapWaterSupplyMode == EvapWaterSupply::WaterSupplyFromMains) {
    1719            2 :                 SetupOutputVariable(state,
    1720              :                                     "Cooling Coil Evaporative Condenser Water Volume",
    1721              :                                     Constant::Units::m3,
    1722            1 :                                     thisTESCoil.EvapWaterConsump,
    1723              :                                     OutputProcessor::TimeStepType::System,
    1724              :                                     OutputProcessor::StoreType::Sum,
    1725            1 :                                     thisTESCoil.Name,
    1726              :                                     Constant::eResource::Water,
    1727              :                                     OutputProcessor::Group::HVAC,
    1728              :                                     OutputProcessor::EndUseCat::Cooling);
    1729            2 :                 SetupOutputVariable(state,
    1730              :                                     "Cooling Coil Evaporative Condenser Mains Supply Water Volume",
    1731              :                                     Constant::Units::m3,
    1732            1 :                                     thisTESCoil.EvapWaterConsump,
    1733              :                                     OutputProcessor::TimeStepType::System,
    1734              :                                     OutputProcessor::StoreType::Sum,
    1735            1 :                                     thisTESCoil.Name,
    1736              :                                     Constant::eResource::MainsWater,
    1737              :                                     OutputProcessor::Group::HVAC,
    1738              :                                     OutputProcessor::EndUseCat::Cooling);
    1739            0 :             } else if (thisTESCoil.EvapWaterSupplyMode == EvapWaterSupply::WaterSupplyFromTank) {
    1740            0 :                 SetupOutputVariable(state,
    1741              :                                     "Cooling Coil Evaporative Condenser Storage Tank Water Volume",
    1742              :                                     Constant::Units::m3,
    1743            0 :                                     thisTESCoil.EvapWaterConsump,
    1744              :                                     OutputProcessor::TimeStepType::System,
    1745              :                                     OutputProcessor::StoreType::Sum,
    1746            0 :                                     thisTESCoil.Name,
    1747              :                                     Constant::eResource::Water,
    1748              :                                     OutputProcessor::Group::HVAC,
    1749              :                                     OutputProcessor::EndUseCat::Cooling);
    1750            0 :                 SetupOutputVariable(state,
    1751              :                                     "Cooling Coil Evaporative Condenser Starved Water Volume",
    1752              :                                     Constant::Units::m3,
    1753            0 :                                     thisTESCoil.EvapWaterStarvMakup,
    1754              :                                     OutputProcessor::TimeStepType::System,
    1755              :                                     OutputProcessor::StoreType::Sum,
    1756            0 :                                     thisTESCoil.Name,
    1757              :                                     Constant::eResource::Water,
    1758              :                                     OutputProcessor::Group::HVAC,
    1759              :                                     OutputProcessor::EndUseCat::Cooling);
    1760            0 :                 SetupOutputVariable(state,
    1761              :                                     "Cooling Coil Evaporative Condenser Starved Mains Water Volume",
    1762              :                                     Constant::Units::m3,
    1763            0 :                                     thisTESCoil.EvapWaterStarvMakup,
    1764              :                                     OutputProcessor::TimeStepType::System,
    1765              :                                     OutputProcessor::StoreType::Sum,
    1766            0 :                                     thisTESCoil.Name,
    1767              :                                     Constant::eResource::MainsWater,
    1768              :                                     OutputProcessor::Group::HVAC,
    1769              :                                     OutputProcessor::EndUseCat::Cooling);
    1770              :             }
    1771              : 
    1772            2 :             SetupOutputVariable(state,
    1773              :                                 "Cooling Coil Evaporative Condenser Pump Electricity Rate",
    1774              :                                 Constant::Units::W,
    1775            1 :                                 thisTESCoil.EvapCondPumpElecPower,
    1776              :                                 OutputProcessor::TimeStepType::System,
    1777              :                                 OutputProcessor::StoreType::Average,
    1778            1 :                                 thisTESCoil.Name);
    1779            2 :             SetupOutputVariable(state,
    1780              :                                 "Cooling Coil Evaporative Condenser Pump Electricity Energy",
    1781              :                                 Constant::Units::J,
    1782            1 :                                 thisTESCoil.EvapCondPumpElecConsumption,
    1783              :                                 OutputProcessor::TimeStepType::System,
    1784              :                                 OutputProcessor::StoreType::Sum,
    1785            1 :                                 thisTESCoil.Name,
    1786              :                                 Constant::eResource::Electricity,
    1787              :                                 OutputProcessor::Group::HVAC,
    1788              :                                 OutputProcessor::EndUseCat::Cooling);
    1789              : 
    1790            2 :             SetupOutputVariable(state,
    1791              :                                 "Cooling Coil Basin Heater Electricity Rate",
    1792              :                                 Constant::Units::W,
    1793            1 :                                 thisTESCoil.ElectEvapCondBasinHeaterPower,
    1794              :                                 OutputProcessor::TimeStepType::System,
    1795              :                                 OutputProcessor::StoreType::Average,
    1796            1 :                                 thisTESCoil.Name);
    1797            2 :             SetupOutputVariable(state,
    1798              :                                 "Cooling Coil Basin Heater Electricity Energy",
    1799              :                                 Constant::Units::J,
    1800            1 :                                 thisTESCoil.ElectEvapCondBasinHeaterEnergy,
    1801              :                                 OutputProcessor::TimeStepType::System,
    1802              :                                 OutputProcessor::StoreType::Sum,
    1803            1 :                                 thisTESCoil.Name,
    1804              :                                 Constant::eResource::Electricity,
    1805              :                                 OutputProcessor::Group::HVAC,
    1806              :                                 OutputProcessor::EndUseCat::Cooling,
    1807              :                                 "Thermal Protection");
    1808              :         }
    1809              : 
    1810            4 :         switch (thisTESCoil.StorageMedia) {
    1811            1 :         case MediaType::Water:
    1812              :         case MediaType::UserDefindFluid:
    1813            2 :             SetupOutputVariable(state,
    1814              :                                 "Cooling Coil Fluid Thermal Storage End Temperature",
    1815              :                                 Constant::Units::C,
    1816            1 :                                 thisTESCoil.FluidTankTempFinal,
    1817              :                                 OutputProcessor::TimeStepType::System,
    1818              :                                 OutputProcessor::StoreType::Average,
    1819            1 :                                 thisTESCoil.Name);
    1820            1 :             break;
    1821            3 :         case MediaType::Ice:
    1822            6 :             SetupOutputVariable(state,
    1823              :                                 "Cooling Coil Ice Thermal Storage End Fraction",
    1824              :                                 Constant::Units::None,
    1825            3 :                                 thisTESCoil.IceFracRemain,
    1826              :                                 OutputProcessor::TimeStepType::System,
    1827              :                                 OutputProcessor::StoreType::Average,
    1828            3 :                                 thisTESCoil.Name);
    1829            3 :             break;
    1830            0 :         default:
    1831              :             // nothing
    1832            0 :             break;
    1833              :         }
    1834              :     }
    1835              : 
    1836            1 :     if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    1837            5 :         for (int item = 1; item <= state.dataPackagedThermalStorageCoil->NumTESCoils; ++item) {
    1838            4 :             auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(item);
    1839              :             // setup EMS actuator for control mode
    1840            4 :             SetupEMSActuator(state,
    1841              :                              "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
    1842              :                              thisTESCoil.Name,
    1843              :                              "Operating Mode",
    1844              :                              "[ ]",
    1845            4 :                              thisTESCoil.EMSControlModeOn,
    1846            4 :                              thisTESCoil.EMSControlModeValue);
    1847              :         }
    1848              :     }
    1849            1 : }
    1850              : 
    1851        63397 : void InitTESCoil(EnergyPlusData &state, int &TESCoilNum)
    1852              : {
    1853              : 
    1854              :     // SUBROUTINE INFORMATION:
    1855              :     //       AUTHOR         B. Griffith
    1856              :     //       DATE WRITTEN   <date_written>
    1857              :     //       MODIFIED       na
    1858              :     //       RE-ENGINEERED  na
    1859              : 
    1860              :     // Using/Aliasing
    1861              : 
    1862              :     using PlantUtilities::ScanPlantLoopsForObject;
    1863              : 
    1864              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1865        63397 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    1866              : 
    1867        63397 :     if (state.dataPackagedThermalStorageCoil->MyOneTimeFlag) {
    1868              :         // initialize the environment and sizing flags
    1869            1 :         state.dataPackagedThermalStorageCoil->MyFlag.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, true);
    1870            1 :         state.dataPackagedThermalStorageCoil->MySizeFlag.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, true);
    1871            1 :         state.dataPackagedThermalStorageCoil->MyEnvrnFlag.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, true);
    1872            1 :         state.dataPackagedThermalStorageCoil->MyWarmupFlag.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, false);
    1873            1 :         state.dataPackagedThermalStorageCoil->MyOneTimeFlag = false;
    1874              :     }
    1875              : 
    1876        63397 :     if (state.dataPackagedThermalStorageCoil->MyFlag(TESCoilNum)) {
    1877              : 
    1878            4 :         if (thisTESCoil.TESPlantConnectionAvailable) {
    1879            1 :             bool errFlag = false;
    1880            1 :             PlantLocation plantLoc{};
    1881            1 :             ScanPlantLoopsForObject(state, thisTESCoil.Name, DataPlant::PlantEquipmentType::PackagedTESCoolingCoil, plantLoc, errFlag);
    1882              : 
    1883              :             // double check node names match
    1884            1 :             if (errFlag) {
    1885            0 :                 ShowFatalError(state, "InitTESCoil: Program terminated due to previous condition(s).");
    1886              :             }
    1887            1 :             thisTESCoil.TESPlantLoopNum = plantLoc.loopNum;
    1888            1 :             thisTESCoil.TESPlantLoopSideNum = plantLoc.loopSideNum;
    1889            1 :             thisTESCoil.TESPlantBranchNum = plantLoc.branchNum;
    1890            1 :             thisTESCoil.TESPlantCompNum = plantLoc.compNum;
    1891              : 
    1892            2 :             if ((DataPlant::CompData::getPlantComponent(state, plantLoc).NodeNumIn != thisTESCoil.TESPlantInletNodeNum) ||
    1893            1 :                 (DataPlant::CompData::getPlantComponent(state, plantLoc).NodeNumOut != thisTESCoil.TESPlantOutletNodeNum)) {
    1894            0 :                 ShowSevereError(
    1895            0 :                     state, format("InitTESCoil: Coil:Cooling:DX:SingleSpeed:ThermalStorage =\"{}\", non-matching plant nodes.", thisTESCoil.Name));
    1896            0 :                 ShowContinueError(state,
    1897            0 :                                   format("...in Branch=\"{}\", Component referenced with:",
    1898            0 :                                          state.dataPlnt->PlantLoop(thisTESCoil.TESPlantLoopNum)
    1899            0 :                                              .LoopSide(thisTESCoil.TESPlantLoopSideNum)
    1900            0 :                                              .Branch(thisTESCoil.TESPlantBranchNum)
    1901            0 :                                              .Name));
    1902            0 :                 ShowContinueError(
    1903              :                     state,
    1904            0 :                     format("...Inlet Node=\"{}", state.dataLoopNodes->NodeID(DataPlant::CompData::getPlantComponent(state, plantLoc).NodeNumIn)));
    1905            0 :                 ShowContinueError(
    1906              :                     state,
    1907            0 :                     format("...Outlet Node=\"{}", state.dataLoopNodes->NodeID(DataPlant::CompData::getPlantComponent(state, plantLoc).NodeNumOut)));
    1908            0 :                 ShowContinueError(state, format("...TES Inlet Node=\"{}", state.dataLoopNodes->NodeID(thisTESCoil.TESPlantInletNodeNum)));
    1909            0 :                 ShowContinueError(state, format("...TES Outlet Node=\"{}", state.dataLoopNodes->NodeID(thisTESCoil.TESPlantOutletNodeNum)));
    1910            0 :                 errFlag = true;
    1911              :             }
    1912            1 :             if (errFlag) {
    1913            0 :                 ShowFatalError(state, "InitTESCoil: Program terminated due to previous condition(s).");
    1914              :             }
    1915              : 
    1916              :         } // any plant connection to TES
    1917            4 :         state.dataPackagedThermalStorageCoil->MyFlag(TESCoilNum) = false;
    1918              :     }
    1919              : 
    1920        63397 :     if (state.dataPackagedThermalStorageCoil->MySizeFlag(TESCoilNum)) {
    1921              : 
    1922            4 :         SizeTESCoil(state, TESCoilNum);
    1923              : 
    1924            4 :         state.dataPackagedThermalStorageCoil->MySizeFlag(TESCoilNum) = false;
    1925              :     }
    1926              : 
    1927        63397 :     if (state.dataGlobal->BeginEnvrnFlag && state.dataPackagedThermalStorageCoil->MyEnvrnFlag(TESCoilNum)) {
    1928           20 :         thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
    1929           20 :         thisTESCoil.QdotPlant = 0.0;
    1930           20 :         thisTESCoil.Q_Plant = 0.0;
    1931           20 :         thisTESCoil.QdotAmbient = 0.0;
    1932           20 :         thisTESCoil.Q_Ambient = 0.0;
    1933           20 :         thisTESCoil.QdotTES = 0.0;
    1934           20 :         thisTESCoil.Q_TES = 0.0;
    1935           20 :         thisTESCoil.TimeElapsed = 0.0;
    1936           20 :         thisTESCoil.IceFracRemain = 0.0;
    1937           20 :         thisTESCoil.IceFracRemainLastTimestep = 0.0;
    1938           20 :         thisTESCoil.FluidTankTempFinal = thisTESCoil.RatedFluidTankTemp;
    1939           20 :         thisTESCoil.FluidTankTempFinalLastTimestep = thisTESCoil.RatedFluidTankTemp;
    1940           20 :         thisTESCoil.ElecCoolingPower = 0.0;     // electric power for cooling [W]
    1941           20 :         thisTESCoil.ElecCoolingEnergy = 0.0;    // electric energy for cooling [J], metered
    1942           20 :         thisTESCoil.EvapTotCoolingRate = 0.0;   // evaporator coil total cooling rate [W]
    1943           20 :         thisTESCoil.EvapTotCoolingEnergy = 0.0; // evaporatory coil total cooling energy [J], metered
    1944           20 :         thisTESCoil.EvapSensCoolingRate = 0.0;
    1945           20 :         thisTESCoil.EvapSensCoolingEnergy = 0.0;
    1946           20 :         thisTESCoil.EvapLatCoolingRate = 0.0;
    1947           20 :         thisTESCoil.EvapLatCoolingEnergy = 0.0;
    1948           20 :         thisTESCoil.RuntimeFraction = 0.0;
    1949           20 :         thisTESCoil.ElectColdWeatherPower = 0.0;  // electric power for cold weather protection [W]
    1950           20 :         thisTESCoil.ElectColdWeatherEnergy = 0.0; // electric energy for cold weather protection [J], metered
    1951           20 :         thisTESCoil.ElectEvapCondBasinHeaterPower = 0.0;
    1952           20 :         thisTESCoil.ElectEvapCondBasinHeaterEnergy = 0.0;
    1953              : 
    1954           20 :         state.dataPackagedThermalStorageCoil->MyEnvrnFlag(TESCoilNum) = false;
    1955              :     }
    1956              : 
    1957        63397 :     if (!state.dataGlobal->BeginEnvrnFlag) {
    1958        63138 :         state.dataPackagedThermalStorageCoil->MyEnvrnFlag(TESCoilNum) = true;
    1959              :     }
    1960              : 
    1961        63397 :     if (state.dataPackagedThermalStorageCoil->MyWarmupFlag(TESCoilNum) && (!state.dataGlobal->WarmupFlag)) {
    1962              :         // reset to initial condition once warm up is over.
    1963            8 :         thisTESCoil.IceFracRemain = 0.0;
    1964            8 :         thisTESCoil.IceFracRemainLastTimestep = 0.0;
    1965            8 :         thisTESCoil.FluidTankTempFinal = thisTESCoil.RatedFluidTankTemp;
    1966            8 :         thisTESCoil.FluidTankTempFinalLastTimestep = thisTESCoil.RatedFluidTankTemp;
    1967            8 :         state.dataPackagedThermalStorageCoil->MyWarmupFlag(TESCoilNum) = false;
    1968              :     }
    1969              : 
    1970        63397 :     if (state.dataGlobal->WarmupFlag) {
    1971        54380 :         state.dataPackagedThermalStorageCoil->MyWarmupFlag(TESCoilNum) = true;
    1972              :     }
    1973              : 
    1974              :     // determine control mode
    1975        63397 :     if (thisTESCoil.availSched->getCurrentVal() != 0.0) {
    1976        63397 :         if (thisTESCoil.ModeControlType == PTSCCtrlType::ScheduledOpModes) {
    1977        16775 :             Real64 const tmpSchedValue = thisTESCoil.controlModeSched->getCurrentVal();
    1978              :             // check if value is valid
    1979        16775 :             if (tmpSchedValue > static_cast<int>(PTSCOperatingMode::Invalid) && tmpSchedValue < static_cast<int>(PTSCOperatingMode::Num)) {
    1980        16775 :                 thisTESCoil.CurControlMode = static_cast<PTSCOperatingMode>(tmpSchedValue);
    1981              :             } else {
    1982            0 :                 thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
    1983            0 :                 if (thisTESCoil.ControlModeErrorIndex == 0) {
    1984            0 :                     ShowSevereMessage(state, "InitTESCoil: Invalid control schedule value for operating mode");
    1985            0 :                     ShowContinueError(state, format("Occurs for Coil:Cooling:DX:SingleSpeed:ThermalStorage name = {}", thisTESCoil.Name));
    1986            0 :                     ShowContinueError(state, format("Value returned from schedule ={:.8R}", tmpSchedValue));
    1987            0 :                     ShowContinueError(state, "Operating mode will be set to Off, and the simulation continues");
    1988              :                 }
    1989            0 :                 ShowRecurringSevereErrorAtEnd(state,
    1990              :                                               "InitTESCoil: Invalid control schedule value for TES operating mode, set to Off",
    1991            0 :                                               thisTESCoil.ControlModeErrorIndex,
    1992              :                                               tmpSchedValue,
    1993              :                                               tmpSchedValue);
    1994              :             }
    1995              : 
    1996        46622 :         } else if (thisTESCoil.ModeControlType == PTSCCtrlType::EMSActuatedOpModes) {
    1997        46622 :             if (thisTESCoil.EMSControlModeOn) {
    1998        46610 :                 int const tmpEMSValue = std::floor(thisTESCoil.EMSControlModeValue);
    1999              : 
    2000              :                 // check for invalid value first
    2001        46610 :                 if (tmpEMSValue <= static_cast<int>(PTSCOperatingMode::Invalid) || tmpEMSValue >= static_cast<int>(PTSCOperatingMode::Num)) {
    2002            0 :                     thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
    2003            0 :                     if (thisTESCoil.ControlModeErrorIndex == 0) {
    2004            0 :                         ShowSevereMessage(state, "InitTESCoil: Invalid control value for operating mode");
    2005            0 :                         ShowContinueError(state, format("Occurs for Coil:Cooling:DX:SingleSpeed:ThermalStorage name = {}", thisTESCoil.Name));
    2006            0 :                         ShowContinueError(state, format("Value returned from EMS ={:.8R}", thisTESCoil.EMSControlModeValue));
    2007            0 :                         ShowContinueError(state, "Operating mode will be set to Off, and the simulation continues");
    2008              :                     }
    2009            0 :                     ShowRecurringSevereErrorAtEnd(state,
    2010              :                                                   "InitTESCoil: Invalid control schedule value for TES operating mode, set to Off",
    2011            0 :                                                   thisTESCoil.ControlModeErrorIndex,
    2012            0 :                                                   thisTESCoil.EMSControlModeValue,
    2013            0 :                                                   thisTESCoil.EMSControlModeValue);
    2014              :                 } else {
    2015              :                     // at this point we have a valid value, we can cast it and assign it
    2016        46610 :                     thisTESCoil.CurControlMode = static_cast<PTSCOperatingMode>(tmpEMSValue);
    2017              :                     // but then we need to do some error handling for certain cases
    2018        46610 :                     switch (thisTESCoil.CurControlMode) {
    2019            0 :                     case PTSCOperatingMode::Off:
    2020            0 :                         break; // nothing to check
    2021              : 
    2022        26244 :                     case PTSCOperatingMode::CoolingOnly:
    2023        26244 :                         if (!(thisTESCoil.CoolingOnlyModeIsAvailable)) {
    2024            0 :                             ShowSevereMessage(state, "InitTESCoil: Invalid control value for operating mode");
    2025            0 :                             ShowContinueError(state, format("Occurs for Coil:Cooling:DX:SingleSpeed:ThermalStorage name = {}", thisTESCoil.Name));
    2026            0 :                             ShowContinueError(state, "Value returned from EMS indicates Cooling Only Mode but that mode is not available.");
    2027            0 :                             ShowContinueError(state, "Operating mode will be set to Off, and the simulation continues");
    2028            0 :                             thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
    2029              :                         }
    2030        26244 :                         break;
    2031         4062 :                     case PTSCOperatingMode::CoolingAndCharge:
    2032         4062 :                         if (!(thisTESCoil.CoolingAndChargeModeAvailable)) {
    2033            0 :                             ShowSevereMessage(state, "InitTESCoil: Invalid control value for operating mode");
    2034            0 :                             ShowContinueError(state, format("Occurs for Coil:Cooling:DX:SingleSpeed:ThermalStorage name = {}", thisTESCoil.Name));
    2035            0 :                             ShowContinueError(state, "Value returned from EMS indicates Cooling And Charge Mode but that mode is not available.");
    2036            0 :                             ShowContinueError(state, "Operating mode will be set to Off, and the simulation continues");
    2037            0 :                             thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
    2038              :                         }
    2039         4062 :                         break;
    2040            0 :                     case PTSCOperatingMode::CoolingAndDischarge:
    2041            0 :                         if (!(thisTESCoil.CoolingAndDischargeModeAvailable)) {
    2042            0 :                             ShowSevereMessage(state, "InitTESCoil: Invalid control value for operating mode");
    2043            0 :                             ShowContinueError(state, format("Occurs for Coil:Cooling:DX:SingleSpeed:ThermalStorage name = {}", thisTESCoil.Name));
    2044            0 :                             ShowContinueError(state, "Value returned from EMS indicates Cooling And Discharge Mode but that mode is not available.");
    2045            0 :                             ShowContinueError(state, "Operating mode will be set to Off, and the simulation continues");
    2046            0 :                             thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
    2047              :                         }
    2048            0 :                         break;
    2049         1349 :                     case PTSCOperatingMode::ChargeOnly:
    2050         1349 :                         if (!(thisTESCoil.ChargeOnlyModeAvailable)) {
    2051            0 :                             ShowSevereMessage(state, "InitTESCoil: Invalid control value for operating mode");
    2052            0 :                             ShowContinueError(state, format("Occurs for Coil:Cooling:DX:SingleSpeed:ThermalStorage name = {}", thisTESCoil.Name));
    2053            0 :                             ShowContinueError(state, "Value returned from EMS indicates Charge Only Mode but that mode is not available.");
    2054            0 :                             ShowContinueError(state, "Operating mode will be set to Off, and the simulation continues");
    2055            0 :                             thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
    2056              :                         }
    2057         1349 :                         break;
    2058        14955 :                     case PTSCOperatingMode::DischargeOnly:
    2059        14955 :                         if (!(thisTESCoil.DischargeOnlyModeAvailable)) {
    2060            0 :                             ShowSevereMessage(state, "InitTESCoil: Invalid control value for operating mode");
    2061            0 :                             ShowContinueError(state, format("Occurs for Coil:Cooling:DX:SingleSpeed:ThermalStorage name = {}", thisTESCoil.Name));
    2062            0 :                             ShowContinueError(state, "Value returned from EMS indicates Discharge Only Mode but that mode is not available.");
    2063            0 :                             ShowContinueError(state, "Operating mode will be set to Off, and the simulation continues");
    2064            0 :                             thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
    2065              :                         }
    2066        14955 :                         break;
    2067            0 :                     default:
    2068              :                         // no need to handle other cases
    2069            0 :                         break;
    2070              :                     }
    2071              :                 }
    2072              : 
    2073              :             } else {
    2074           12 :                 thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
    2075              :             }
    2076              :         }
    2077              :     } else {
    2078            0 :         thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
    2079              :     }
    2080              : 
    2081              :     // update the integer report variable
    2082        63397 :     thisTESCoil.curControlModeReport = static_cast<int>(thisTESCoil.CurControlMode);
    2083              : 
    2084        63397 :     thisTESCoil.QdotPlant = 0.0;   // heat exchange rate for plant connection to TES tank [W]
    2085        63397 :     thisTESCoil.Q_Plant = 0.0;     //  heat exchange energy for plant connection to TES tank [J]
    2086        63397 :     thisTESCoil.QdotAmbient = 0.0; // heat exchange rate for skin losses/gains for TES tank to surroundings [W]
    2087        63397 :     thisTESCoil.Q_Ambient = 0.0;   // heat exchange enegy for skin losses/gains for TES tank to surroundings [J]
    2088        63397 :     thisTESCoil.QdotTES = 0.0;     // heat exchange rate by mechanical systems to charge or discharge TES [W]
    2089        63397 :     thisTESCoil.Q_TES = 0.0;       // heat exchange energy by mechanical systems to charge or discharge TES [J]
    2090              : 
    2091              :     // dynamic calculated data
    2092        63397 :     thisTESCoil.ElecCoolingPower = 0.0;     // electric power for cooling [W]
    2093        63397 :     thisTESCoil.ElecCoolingEnergy = 0.0;    // electric energy for cooling [J], metered
    2094        63397 :     thisTESCoil.EvapTotCoolingRate = 0.0;   // evaporator coil total cooling rate [W]
    2095        63397 :     thisTESCoil.EvapTotCoolingEnergy = 0.0; // evaporatory coil total cooling energy [J], metered
    2096        63397 :     thisTESCoil.EvapSensCoolingRate = 0.0;
    2097        63397 :     thisTESCoil.EvapSensCoolingEnergy = 0.0;
    2098        63397 :     thisTESCoil.EvapLatCoolingRate = 0.0;
    2099        63397 :     thisTESCoil.EvapLatCoolingEnergy = 0.0;
    2100        63397 :     thisTESCoil.RuntimeFraction = 0.0;
    2101        63397 :     thisTESCoil.CondenserRuntimeFraction = 0.0;
    2102        63397 :     thisTESCoil.ElectColdWeatherPower = 0.0;  // electric power for cold weather protection [W]
    2103        63397 :     thisTESCoil.ElectColdWeatherEnergy = 0.0; // electric energy for cold weather protection [J], metered
    2104        63397 :     thisTESCoil.ElectEvapCondBasinHeaterPower = 0.0;
    2105        63397 :     thisTESCoil.ElectEvapCondBasinHeaterEnergy = 0.0;
    2106        63397 : }
    2107              : 
    2108            4 : void SizeTESCoil(EnergyPlusData &state, int &TESCoilNum)
    2109              : {
    2110              : 
    2111              :     // SUBROUTINE INFORMATION:
    2112              :     //       AUTHOR         B. Griffith
    2113              :     //       DATE WRITTEN   April 2013
    2114              :     //       MODIFIED       na
    2115              :     //       RE-ENGINEERED  na
    2116              : 
    2117              :     // Using/Aliasing
    2118              :     using namespace DataSizing;
    2119              :     using namespace OutputReportPredefined;
    2120              : 
    2121              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2122              :     static constexpr std::string_view RoutineName("SizeTESCoil ");
    2123              :     static constexpr std::string_view calcTESWaterStorageTank("CalcTESWaterStorageTank");
    2124            4 :     Real64 constexpr FluidTankSizingDeltaT(10.0);
    2125              : 
    2126              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2127              :     Real64 MixTemp;
    2128              :     Real64 MixHumRat;
    2129              :     Real64 MixEnth;
    2130              :     Real64 MixWetBulb;
    2131              :     Real64 SupTemp;
    2132              :     Real64 SupHumRat;
    2133              :     Real64 SupEnth;
    2134              :     Real64 OutTemp;
    2135              :     Real64 OutAirFrac;
    2136              :     Real64 VolFlowRate;
    2137              :     Real64 CoolCapAtPeak;
    2138              :     Real64 TotCapTempModFac;
    2139              :     Real64 rhoair;
    2140              :     Real64 rho;
    2141              :     Real64 deltaT;
    2142              :     Real64 Cp;
    2143              : 
    2144            4 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    2145              : 
    2146            4 :     if (thisTESCoil.RatedEvapAirVolFlowRate == AutoSize) {
    2147              : 
    2148            4 :         if (state.dataSize->CurSysNum > 0) {
    2149            4 :             CheckSysSizing(state, "Coil:Cooling:DX:SingleSpeed:ThermalStorage", thisTESCoil.Name);
    2150            4 :             if (state.dataSize->CurOASysNum > 0) {
    2151            0 :                 thisTESCoil.RatedEvapAirVolFlowRate = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesOutAirVolFlow;
    2152              :             } else {
    2153            4 :                 thisTESCoil.RatedEvapAirVolFlowRate = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    2154              :             }
    2155            0 :         } else if (state.dataSize->CurZoneEqNum > 0) {
    2156            0 :             CheckZoneSizing(state, "Coil:Cooling:DX:SingleSpeed:ThermalStorage", thisTESCoil.Name);
    2157            0 :             thisTESCoil.RatedEvapAirVolFlowRate = max(state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolVolFlow,
    2158            0 :                                                       state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatVolFlow);
    2159              :         }
    2160              : 
    2161            4 :         if (thisTESCoil.RatedEvapAirVolFlowRate < HVAC::SmallAirVolFlow) {
    2162            0 :             thisTESCoil.RatedEvapAirVolFlowRate = 0.0;
    2163              :         }
    2164            4 :         BaseSizer::reportSizerOutput(state,
    2165              :                                      "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
    2166              :                                      thisTESCoil.Name,
    2167              :                                      "Rated Evaporator Air Flow Rate [m3/s]",
    2168              :                                      thisTESCoil.RatedEvapAirVolFlowRate);
    2169              :     }
    2170              : 
    2171            4 :     thisTESCoil.RatedEvapAirMassFlowRate = state.dataEnvrn->StdRhoAir * thisTESCoil.RatedEvapAirVolFlowRate;
    2172              : 
    2173            4 :     if (thisTESCoil.CondenserAirVolumeFlow == Constant::AutoCalculate) {
    2174            4 :         thisTESCoil.CondenserAirVolumeFlow = thisTESCoil.RatedEvapAirVolFlowRate * thisTESCoil.CondenserAirFlowSizingFactor;
    2175            4 :         BaseSizer::reportSizerOutput(state,
    2176              :                                      "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
    2177              :                                      thisTESCoil.Name,
    2178              :                                      "Condenser Air Flow Rate [m3/s]",
    2179              :                                      thisTESCoil.CondenserAirVolumeFlow);
    2180              :     }
    2181              : 
    2182            4 :     thisTESCoil.CondenserAirMassFlow = state.dataEnvrn->StdRhoAir * thisTESCoil.CondenserAirVolumeFlow;
    2183              : 
    2184            4 :     if (thisTESCoil.CoolingOnlyRatedTotCap == AutoSize) {
    2185            4 :         if (state.dataSize->CurSysNum > 0) {
    2186            4 :             CheckSysSizing(state, "Coil:Cooling:DX:SingleSpeed:ThermalStorage", thisTESCoil.Name);
    2187            4 :             VolFlowRate = thisTESCoil.RatedEvapAirVolFlowRate;
    2188            4 :             if (VolFlowRate >= HVAC::SmallAirVolFlow) {
    2189            4 :                 if (state.dataSize->CurOASysNum > 0) { // coil is in the OA stream
    2190            0 :                     MixTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).OutTempAtCoolPeak;
    2191            0 :                     MixHumRat = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).OutHumRatAtCoolPeak;
    2192            0 :                     SupTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).PrecoolTemp;
    2193            0 :                     SupHumRat = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).PrecoolHumRat;
    2194              :                 } else { // coil is on the main air loop
    2195              :                     //     MixTemp = FinalSysSizing(CurSysNum)%MixTempAtCoolPeak
    2196              :                     //     MixHumRat = FinalSysSizing(CurSysNum)%MixHumRatAtCoolPeak
    2197            4 :                     SupTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).CoolSupTemp;
    2198            4 :                     SupHumRat = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).CoolSupHumRat;
    2199            4 :                     if (state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).NumOACoolCoils ==
    2200              :                         0) { // there is no precooling of the OA stream
    2201            4 :                         MixTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).MixTempAtCoolPeak;
    2202            4 :                         MixHumRat = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).MixHumRatAtCoolPeak;
    2203              :                     } else { // there is precooling of OA stream
    2204            0 :                         if (VolFlowRate > 0.0) {
    2205            0 :                             OutAirFrac = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesOutAirVolFlow / VolFlowRate;
    2206              :                         } else {
    2207            0 :                             OutAirFrac = 1.0;
    2208              :                         }
    2209            0 :                         OutAirFrac = min(1.0, max(0.0, OutAirFrac));
    2210            0 :                         MixTemp = OutAirFrac * state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).PrecoolTemp +
    2211            0 :                                   (1.0 - OutAirFrac) * state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).RetTempAtCoolPeak;
    2212            0 :                         MixHumRat = OutAirFrac * state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).PrecoolHumRat +
    2213            0 :                                     (1.0 - OutAirFrac) * state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).RetHumRatAtCoolPeak;
    2214              :                     }
    2215              :                 }
    2216            4 :                 OutTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).OutTempAtCoolPeak;
    2217            4 :                 rhoair = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, MixTemp, MixHumRat, RoutineName);
    2218            4 :                 MixEnth = PsyHFnTdbW(MixTemp, MixHumRat);
    2219            4 :                 MixWetBulb = PsyTwbFnTdbWPb(state, MixTemp, MixHumRat, state.dataEnvrn->StdBaroPress, RoutineName);
    2220            4 :                 SupEnth = PsyHFnTdbW(SupTemp, SupHumRat);
    2221            4 :                 TotCapTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFTempCurve, MixWetBulb, OutTemp);
    2222            4 :                 CoolCapAtPeak = max(0.0, (rhoair * VolFlowRate * (MixEnth - SupEnth)));
    2223            4 :                 if (TotCapTempModFac > 0.0) {
    2224            4 :                     thisTESCoil.CoolingOnlyRatedTotCap = CoolCapAtPeak / TotCapTempModFac;
    2225              :                 } else {
    2226            0 :                     thisTESCoil.CoolingOnlyRatedTotCap = CoolCapAtPeak;
    2227              :                 }
    2228              : 
    2229              :             } else {
    2230            0 :                 thisTESCoil.CoolingOnlyRatedTotCap = 0.0;
    2231              :             }
    2232            0 :         } else if (state.dataSize->CurZoneEqNum > 0) {
    2233            0 :             CheckZoneSizing(state, "Coil:Cooling:DX:SingleSpeed:ThermalStorage", thisTESCoil.Name);
    2234            0 :             VolFlowRate = thisTESCoil.RatedEvapAirVolFlowRate;
    2235            0 :             if (VolFlowRate >= HVAC::SmallAirVolFlow) {
    2236            0 :                 if (state.dataSize->ZoneEqDXCoil) {
    2237            0 :                     if (state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum).OAVolFlow > 0.0) {
    2238            0 :                         MixTemp = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolCoilInTemp;
    2239            0 :                         MixHumRat = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolCoilInHumRat;
    2240              :                     } else {
    2241            0 :                         MixTemp = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).ZoneRetTempAtCoolPeak;
    2242            0 :                         MixHumRat = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).ZoneHumRatAtCoolPeak;
    2243              :                     }
    2244              :                 } else {
    2245            0 :                     MixTemp = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolCoilInTemp;
    2246            0 :                     MixHumRat = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolCoilInHumRat;
    2247              :                 }
    2248            0 :                 SupTemp = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).CoolDesTemp;
    2249            0 :                 SupHumRat = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).CoolDesHumRat;
    2250            0 :                 int const TimeStepNumAtMax = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).TimeStepNumAtCoolMax;
    2251            0 :                 int const DDNum = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).CoolDDNum;
    2252            0 :                 if (DDNum > 0 && TimeStepNumAtMax > 0) {
    2253            0 :                     OutTemp = state.dataSize->DesDayWeath(DDNum).Temp(TimeStepNumAtMax);
    2254              :                 } else {
    2255            0 :                     OutTemp = 0.0;
    2256              :                 }
    2257            0 :                 rhoair = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, MixTemp, MixHumRat, RoutineName);
    2258            0 :                 MixEnth = PsyHFnTdbW(MixTemp, MixHumRat);
    2259            0 :                 MixWetBulb = PsyTwbFnTdbWPb(state, MixTemp, MixHumRat, state.dataEnvrn->StdBaroPress, RoutineName);
    2260            0 :                 SupEnth = PsyHFnTdbW(SupTemp, SupHumRat);
    2261            0 :                 TotCapTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFTempCurve, MixWetBulb, OutTemp);
    2262            0 :                 CoolCapAtPeak = max(0.0, (rhoair * VolFlowRate * (MixEnth - SupEnth)));
    2263            0 :                 if (TotCapTempModFac > 0.0) {
    2264            0 :                     thisTESCoil.CoolingOnlyRatedTotCap = CoolCapAtPeak / TotCapTempModFac;
    2265              :                 } else {
    2266            0 :                     thisTESCoil.CoolingOnlyRatedTotCap = CoolCapAtPeak;
    2267              :                 }
    2268              : 
    2269              :             } else {
    2270            0 :                 thisTESCoil.CoolingOnlyRatedTotCap = 0.0;
    2271              :             }
    2272              :         }
    2273              : 
    2274            4 :         BaseSizer::reportSizerOutput(state,
    2275              :                                      "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
    2276              :                                      thisTESCoil.Name,
    2277              :                                      "Cooling Only Mode Rated Total Evaporator Cooling Capacity [W]",
    2278              :                                      thisTESCoil.CoolingOnlyRatedTotCap);
    2279              :     }
    2280              : 
    2281            4 :     if (thisTESCoil.CoolingAndChargeModeAvailable && (thisTESCoil.CoolingAndChargeRatedTotCap == Constant::AutoCalculate)) {
    2282            3 :         thisTESCoil.CoolingAndChargeRatedTotCap = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingAndChargeRatedTotCapSizingFactor;
    2283            3 :         BaseSizer::reportSizerOutput(state,
    2284              :                                      "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
    2285              :                                      thisTESCoil.Name,
    2286              :                                      "Cooling And Charge Mode Rated Total Evaporator Cooling Capacity [W]",
    2287              :                                      thisTESCoil.CoolingAndChargeRatedTotCap);
    2288              :     }
    2289              : 
    2290            4 :     if (thisTESCoil.CoolingAndChargeModeAvailable && (thisTESCoil.CoolingAndChargeRatedChargeCap == Constant::AutoCalculate)) {
    2291            3 :         thisTESCoil.CoolingAndChargeRatedChargeCap = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingAndChargeRatedChargeCapSizingFactor;
    2292            3 :         BaseSizer::reportSizerOutput(state,
    2293              :                                      "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
    2294              :                                      thisTESCoil.Name,
    2295              :                                      "Cooling And Charge Mode Rated Storage Charging Capacity [W]",
    2296              :                                      thisTESCoil.CoolingAndChargeRatedChargeCap);
    2297              :     }
    2298              : 
    2299            4 :     if (thisTESCoil.CoolingAndDischargeModeAvailable && (thisTESCoil.CoolingAndDischargeRatedTotCap == Constant::AutoCalculate)) {
    2300            1 :         thisTESCoil.CoolingAndDischargeRatedTotCap = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingAndDischargeRatedTotCapSizingFactor;
    2301            1 :         BaseSizer::reportSizerOutput(state,
    2302              :                                      "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
    2303              :                                      thisTESCoil.Name,
    2304              :                                      "Cooling And Discharge Mode Rated Total Evaporator Cooling Capacity [W]",
    2305              :                                      thisTESCoil.CoolingAndDischargeRatedTotCap);
    2306              :     }
    2307              : 
    2308            4 :     if (thisTESCoil.CoolingAndDischargeModeAvailable && (thisTESCoil.CoolingAndDischargeRatedDischargeCap == Constant::AutoCalculate)) {
    2309            1 :         thisTESCoil.CoolingAndDischargeRatedDischargeCap =
    2310            1 :             thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingAndDischargeRatedDischargeCapSizingFactor;
    2311            1 :         BaseSizer::reportSizerOutput(state,
    2312              :                                      "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
    2313              :                                      thisTESCoil.Name,
    2314              :                                      "Cooling And Discharge Mode Rated Storage Discharging Capacity [W]",
    2315              :                                      thisTESCoil.CoolingAndDischargeRatedDischargeCap);
    2316              :     }
    2317              : 
    2318            4 :     if (thisTESCoil.ChargeOnlyModeAvailable && (thisTESCoil.ChargeOnlyRatedCapacity == Constant::AutoCalculate)) {
    2319            1 :         thisTESCoil.ChargeOnlyRatedCapacity = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.ChargeOnlyRatedCapacitySizingFactor;
    2320            1 :         BaseSizer::reportSizerOutput(state,
    2321              :                                      "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
    2322              :                                      thisTESCoil.Name,
    2323              :                                      "Charge Only Mode Rated Storage Charging Capacity [W]",
    2324              :                                      thisTESCoil.ChargeOnlyRatedCapacity);
    2325              :     }
    2326              : 
    2327            4 :     if (thisTESCoil.DischargeOnlyModeAvailable && (thisTESCoil.DischargeOnlyRatedDischargeCap == Constant::AutoCalculate)) {
    2328            3 :         thisTESCoil.DischargeOnlyRatedDischargeCap = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.DischargeOnlyRatedDischargeCapSizingFactor;
    2329            3 :         BaseSizer::reportSizerOutput(state,
    2330              :                                      "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
    2331              :                                      thisTESCoil.Name,
    2332              :                                      "Discharge Only Mode Rated Storage Discharging Capacity [W]",
    2333              :                                      thisTESCoil.DischargeOnlyRatedDischargeCap);
    2334              :     }
    2335              : 
    2336            4 :     switch (thisTESCoil.StorageMedia) {
    2337            1 :     case MediaType::UserDefindFluid:
    2338              :     case MediaType::Water:
    2339            1 :         if (thisTESCoil.FluidStorageVolume == Constant::AutoCalculate) {
    2340              : 
    2341              :             // for fluid tanks, assume a 10C deltaT or diff between max and min, whichever is smaller
    2342            1 :             deltaT = min(FluidTankSizingDeltaT, (thisTESCoil.MaximumFluidTankTempLimit - thisTESCoil.MinimumFluidTankTempLimit));
    2343            1 :             rho = thisTESCoil.glycol->getDensity(state, Constant::CWInitConvTemp, calcTESWaterStorageTank);
    2344            1 :             Cp = thisTESCoil.glycol->getSpecificHeat(state, Constant::CWInitConvTemp, calcTESWaterStorageTank);
    2345            1 :             if (thisTESCoil.DischargeOnlyRatedDischargeCap > 0.0 && thisTESCoil.DischargeOnlyModeAvailable) {
    2346            0 :                 thisTESCoil.FluidStorageVolume =
    2347            0 :                     (thisTESCoil.DischargeOnlyRatedDischargeCap * thisTESCoil.StorageCapacitySizingFactor * Constant::rSecsInHour) /
    2348            0 :                     (rho * Cp * deltaT);
    2349              :             } else {
    2350            1 :                 thisTESCoil.FluidStorageVolume =
    2351            1 :                     (thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.StorageCapacitySizingFactor * Constant::rSecsInHour) / (rho * Cp * deltaT);
    2352              :             }
    2353            1 :             BaseSizer::reportSizerOutput(
    2354              :                 state, "Coil:Cooling:DX:SingleSpeed:ThermalStorage", thisTESCoil.Name, "Fluid Storage Volume [m3]", thisTESCoil.FluidStorageVolume);
    2355              :         }
    2356            1 :         break;
    2357            3 :     case MediaType::Ice:
    2358            3 :         if (thisTESCoil.IceStorageCapacity == Constant::AutoCalculate) {
    2359            3 :             if (thisTESCoil.DischargeOnlyRatedDischargeCap > 0.0 && thisTESCoil.DischargeOnlyModeAvailable) {
    2360            3 :                 thisTESCoil.IceStorageCapacity =
    2361            3 :                     thisTESCoil.DischargeOnlyRatedDischargeCap * thisTESCoil.StorageCapacitySizingFactor * Constant::rSecsInHour;
    2362              :             } else {
    2363            0 :                 thisTESCoil.IceStorageCapacity = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.StorageCapacitySizingFactor * Constant::rSecsInHour;
    2364              :             }
    2365            6 :             BaseSizer::reportSizerOutput(state,
    2366              :                                          "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
    2367              :                                          thisTESCoil.Name,
    2368              :                                          "Ice Storage Capacity [GJ]",
    2369            3 :                                          thisTESCoil.IceStorageCapacity / gigaJoulesToJoules);
    2370              :         }
    2371              :     default:
    2372            3 :         break;
    2373              :     }
    2374              : 
    2375            4 :     if ((thisTESCoil.CondenserType == TESCondenserType::Evap) && (thisTESCoil.EvapCondPumpElecNomPower == AutoSize)) {
    2376            0 :         thisTESCoil.EvapCondPumpElecNomPower = thisTESCoil.CoolingOnlyRatedTotCap * 0.004266; // w/w (15 w/ton)
    2377            0 :         BaseSizer::reportSizerOutput(state,
    2378              :                                      "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
    2379              :                                      thisTESCoil.Name,
    2380              :                                      "Evaporative Condenser Pump Rated Power Consumption [W]",
    2381              :                                      thisTESCoil.EvapCondPumpElecNomPower);
    2382              :     }
    2383              : 
    2384            4 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilType, thisTESCoil.Name, "Coil:Cooling:DX:SingleSpeed:ThermalStorage");
    2385              : 
    2386            4 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilTotCap, thisTESCoil.Name, thisTESCoil.CoolingOnlyRatedTotCap);
    2387            8 :     PreDefTableEntry(state,
    2388            4 :                      state.dataOutRptPredefined->pdchCoolCoilSensCap,
    2389              :                      thisTESCoil.Name,
    2390            4 :                      thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingOnlyRatedSHR);
    2391            8 :     PreDefTableEntry(state,
    2392            4 :                      state.dataOutRptPredefined->pdchCoolCoilLatCap,
    2393              :                      thisTESCoil.Name,
    2394            4 :                      thisTESCoil.CoolingOnlyRatedTotCap - thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingOnlyRatedSHR);
    2395            4 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilSHR, thisTESCoil.Name, thisTESCoil.CoolingOnlyRatedSHR);
    2396            4 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilNomEff, thisTESCoil.Name, thisTESCoil.CoolingOnlyRatedCOP);
    2397            4 : }
    2398              : 
    2399           12 : void CalcTESCoilOffMode(EnergyPlusData &state, int const TESCoilNum)
    2400              : {
    2401              : 
    2402              :     // SUBROUTINE INFORMATION:
    2403              :     //       AUTHOR         Brent Griffith
    2404              :     //       DATE WRITTEN   April 2013
    2405              :     //       MODIFIED       na
    2406              :     //       RE-ENGINEERED  na
    2407              : 
    2408           12 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    2409              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2410              : 
    2411           12 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    2412              : 
    2413              :     // coil is off; just pass through conditions
    2414           12 :     Real64 StandbyAncillaryPower = 0.0;
    2415           12 :     if (thisTESCoil.availSched->getCurrentVal() != 0.0) {
    2416           12 :         StandbyAncillaryPower = thisTESCoil.AncillaryControlsPower;
    2417              :     }
    2418              : 
    2419           12 :     thisTESCoil.ElecCoolingPower = StandbyAncillaryPower;
    2420           12 :     thisTESCoil.ElecCoolingEnergy = StandbyAncillaryPower * TimeStepSysSec;
    2421              : 
    2422           12 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    2423           12 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    2424           12 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
    2425           12 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    2426           12 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    2427           12 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    2428           12 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    2429           12 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    2430           12 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    2431           12 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
    2432              : 
    2433           12 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    2434           12 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    2435           12 :     state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
    2436           12 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
    2437           12 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
    2438           12 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    2439           12 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
    2440           12 :     thisTESCoil.RuntimeFraction = 0.0;
    2441           12 :     thisTESCoil.EvapTotCoolingRate = 0.0;
    2442           12 :     thisTESCoil.EvapTotCoolingEnergy = 0.0;
    2443           12 :     thisTESCoil.EvapSensCoolingRate = 0.0;
    2444           12 :     thisTESCoil.EvapSensCoolingEnergy = 0.0;
    2445           12 :     thisTESCoil.EvapLatCoolingRate = 0.0;
    2446           12 :     thisTESCoil.EvapLatCoolingEnergy = 0.0;
    2447              : 
    2448           12 :     thisTESCoil.QdotTES = 0.0;
    2449           12 :     thisTESCoil.Q_TES = 0.0;
    2450              : 
    2451           12 :     UpdateTEStorage(state, TESCoilNum);
    2452              : 
    2453           12 :     thisTESCoil.CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    2454              : 
    2455           12 :     UpdateColdWeatherProtection(state, TESCoilNum);
    2456              : 
    2457           12 :     if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    2458            4 :         UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
    2459              :     }
    2460           12 : }
    2461              : 
    2462        30543 : void CalcTESCoilCoolingOnlyMode(EnergyPlusData &state, int const TESCoilNum, [[maybe_unused]] HVAC::FanOp const fanOp, Real64 const PartLoadRatio)
    2463              : {
    2464              : 
    2465              :     // SUBROUTINE INFORMATION:
    2466              :     //       AUTHOR         Brent Griffith
    2467              :     //       DATE WRITTEN   April 2013
    2468              :     //       MODIFIED       na
    2469              :     //       RE-ENGINEERED  na
    2470              : 
    2471              :     // Using/Aliasing
    2472        30543 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    2473              : 
    2474              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2475        30543 :     int constexpr MaxIter(30);
    2476        30543 :     Real64 constexpr RelaxationFactor(0.4);
    2477        30543 :     Real64 constexpr Tolerance(0.1);
    2478              :     static constexpr std::string_view RoutineName("CalcTESCoilCoolingOnlyMode");
    2479              : 
    2480              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2481              :     Real64 CondInletTemp; // Condenser inlet temperature (C). Outdoor dry-bulb temp for air-cooled condenser.
    2482              :     // Outdoor Wetbulb +(1 - effectiveness)*(outdoor drybulb - outdoor wetbulb) for evap condenser.
    2483              :     Real64 CondInletHumRat; // Condenser inlet humidity ratio (kg/kg). Zero for air-cooled condenser.
    2484              :                             // For evap condenser, its the humidity ratio of the air leaving the evap cooling pads.
    2485              : 
    2486        30543 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    2487              : 
    2488              :     // first deal with condenser
    2489        30543 :     if (thisTESCoil.CondenserType == TESCondenserType::Air) {
    2490        22920 :         Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
    2491        22920 :         if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
    2492            0 :             CondInletTemp = state.dataEnvrn->OutDryBulbTemp;
    2493            0 :             CondInletHumRat = state.dataEnvrn->OutHumRat;
    2494              :         } else {
    2495        22920 :             CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    2496        22920 :             CondInletHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    2497              :         }
    2498         7623 :     } else if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    2499         7623 :         Real64 CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
    2500         7623 :         Real64 OutdoorDryBulb = 0.0;
    2501         7623 :         Real64 OutdoorWetBulb = 0.0;
    2502         7623 :         if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
    2503            0 :             OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
    2504            0 :             CondAirSidePressure = state.dataEnvrn->OutBaroPress;
    2505            0 :             OutdoorWetBulb = state.dataEnvrn->OutWetBulbTemp;
    2506              :         } else {
    2507         7623 :             OutdoorDryBulb = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    2508         7623 :             Real64 const OutdoorHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    2509         7623 :             OutdoorWetBulb = PsyTwbFnTdbWPb(state, OutdoorDryBulb, OutdoorHumRat, CondAirSidePressure, RoutineName);
    2510              :         }
    2511              :         // direct evap cool model
    2512         7623 :         CondInletTemp = OutdoorWetBulb + (OutdoorDryBulb - OutdoorWetBulb) * (1.0 - thisTESCoil.EvapCondEffect);
    2513         7623 :         CondInletHumRat = PsyWFnTdbTwbPb(state, CondInletTemp, OutdoorWetBulb, CondAirSidePressure, RoutineName);
    2514              :     }
    2515              : 
    2516        30543 :     Real64 const EvapAirMassFlow = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    2517              : 
    2518        30543 :     if ((EvapAirMassFlow > HVAC::SmallMassFlow) && (PartLoadRatio > 0.0)) { // coil is running
    2519              : 
    2520        12270 :         Real64 const EvapInletDryBulb = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    2521        12270 :         Real64 const EvapInletHumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    2522        12270 :         Real64 const EvapInletWetBulb = PsyTwbFnTdbWPb(state, EvapInletDryBulb, EvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
    2523        12270 :         Real64 const EvapInletEnthalpy = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Enthalpy;
    2524              : 
    2525        12270 :         Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
    2526        12270 :         Real64 TotCapTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFTempCurve, EvapInletWetBulb, CondInletTemp);
    2527        12270 :         TotCapTempModFac = max(0.0, TotCapTempModFac); // could warn if negative, DXcoil does
    2528        12270 :         Real64 TotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFFlowCurve, AirMassFlowRatio);
    2529        12270 :         TotCapFlowModFac = max(0.0, TotCapFlowModFac); // could warn if negative, DXcoil does
    2530        12270 :         Real64 TotCap = thisTESCoil.CoolingOnlyRatedTotCap * TotCapTempModFac * TotCapFlowModFac;
    2531              : 
    2532              :         // now see if coil might be running dry
    2533        12270 :         Real64 const PartLoadOutAirEnth = EvapInletEnthalpy - (TotCap * PartLoadRatio) / EvapAirMassFlow;
    2534        12270 :         Real64 const PartLoadDryCoilOutAirTemp = PsyTdbFnHW(PartLoadOutAirEnth, EvapInletHumRat);
    2535              : 
    2536        12270 :         bool CoilMightBeDry = false;
    2537        12270 :         Real64 DryCoilTestEvapInletHumRat = 0.0;
    2538        12270 :         Real64 SHRadp = 0.0;
    2539        12270 :         if (PartLoadDryCoilOutAirTemp > PsyTsatFnHPb(state, PartLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    2540              : 
    2541          125 :             CoilMightBeDry = true;
    2542              :             // find wADP, humidity ratio at apparatus dewpoint and inlet hum rat that would have dry coil
    2543          125 :             DryCoilTestEvapInletHumRat = EvapInletHumRat;
    2544          125 :             Real64 DryCoilTestEvapInletWetBulb = EvapInletWetBulb;
    2545          125 :             int Counter = 0;
    2546          125 :             bool Converged = false;
    2547          250 :             while (!Converged) {
    2548              :                 TotCapTempModFac =
    2549          125 :                     EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFTempCurve, DryCoilTestEvapInletWetBulb, CondInletTemp);
    2550          125 :                 TotCapTempModFac = max(0.0, TotCapTempModFac); // could warn if negative, DXcoil does
    2551              : 
    2552          125 :                 TotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFFlowCurve, AirMassFlowRatio);
    2553          125 :                 TotCapFlowModFac = max(0.0, TotCapFlowModFac); // could warn if negative, DXcoil does
    2554          125 :                 TotCap = thisTESCoil.CoolingOnlyRatedTotCap * TotCapTempModFac * TotCapFlowModFac;
    2555              : 
    2556              :                 // coil bypass factor = 0.0
    2557          125 :                 Real64 const hADP = EvapInletEnthalpy - (TotCap / EvapAirMassFlow);
    2558          125 :                 Real64 const tADP = PsyTsatFnHPb(state, hADP, state.dataEnvrn->OutBaroPress, RoutineName);
    2559          125 :                 Real64 const wADP = min(EvapInletHumRat, PsyWFnTdbH(state, tADP, hADP, RoutineName));
    2560          125 :                 Real64 const hTinwADP = PsyHFnTdbW(EvapInletDryBulb, wADP);
    2561          125 :                 if ((EvapInletEnthalpy - hADP) > 1.e-10) {
    2562          125 :                     SHRadp = min((hTinwADP - hADP) / (EvapInletEnthalpy - hADP), 1.0);
    2563              :                 } else {
    2564            0 :                     SHRadp = 1.0;
    2565              :                 }
    2566              : 
    2567          125 :                 if ((wADP > DryCoilTestEvapInletHumRat) || (Counter >= 1 && Counter < MaxIter)) {
    2568            0 :                     if (DryCoilTestEvapInletHumRat <= 0.0) {
    2569            0 :                         DryCoilTestEvapInletHumRat = 0.00001;
    2570              :                     }
    2571            0 :                     Real64 const werror = (DryCoilTestEvapInletHumRat - wADP) / DryCoilTestEvapInletHumRat;
    2572              : 
    2573            0 :                     DryCoilTestEvapInletHumRat = RelaxationFactor * wADP + (1.0 - RelaxationFactor) * DryCoilTestEvapInletHumRat;
    2574              :                     DryCoilTestEvapInletWetBulb =
    2575            0 :                         PsyTwbFnTdbWPb(state, EvapInletDryBulb, DryCoilTestEvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
    2576              : 
    2577            0 :                     ++Counter;
    2578            0 :                     Converged = (std::abs(werror) <= Tolerance);
    2579            0 :                 } else {
    2580          125 :                     Converged = true;
    2581              :                 }
    2582              :             }
    2583              :         }
    2584              : 
    2585              :         // total cooling capacity modification factors
    2586        12270 :         Real64 const SHRTempFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlySHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb);
    2587        12270 :         Real64 const SHRFlowFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlySHRFFlowCurve, AirMassFlowRatio);
    2588              : 
    2589        12270 :         Real64 SHR = thisTESCoil.CoolingOnlyRatedSHR * SHRTempFac * SHRFlowFac;
    2590        12270 :         SHR = min(SHR, 1.0); // warn maybe
    2591        12270 :         SHR = max(SHR, 0.0); // warn maybe
    2592        12270 :         if (CoilMightBeDry) {
    2593          125 :             if ((EvapInletHumRat < DryCoilTestEvapInletHumRat) && (SHRadp > SHR)) { // coil is dry for sure
    2594            0 :                 SHR = 1.0;
    2595          125 :             } else if (SHRadp > SHR) {
    2596          125 :                 SHR = SHRadp;
    2597              :             }
    2598              :         }
    2599              : 
    2600              :         // part load factor
    2601        12270 :         Real64 const PLF = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyPLFFPLRCurve, PartLoadRatio);
    2602              :         // compressor running time divided by full time of timestep.
    2603        12270 :         Real64 RuntimeFraction = 1.0;
    2604        12270 :         if (PLF >= PartLoadRatio && PLF > 0.0) {
    2605         6998 :             RuntimeFraction = PartLoadRatio / PLF;
    2606              :         } else {
    2607         5272 :             RuntimeFraction = 1.0; // warn maybe
    2608              :         }
    2609              :         //  Calculate full load output conditions
    2610        12270 :         Real64 const FullLoadOutAirEnth = EvapInletEnthalpy - TotCap / EvapAirMassFlow;
    2611              : 
    2612              :         // Enthalpy at inlet dry-bulb and outlet humidity ratio [J/kg]
    2613        12270 :         Real64 const hTinwout = EvapInletEnthalpy - (1.0 - SHR) * (TotCap / EvapAirMassFlow);
    2614              :         // The following will often throw psych warnings for neg w, suppress warnings because error condition is handled in next IF
    2615        12270 :         Real64 FullLoadOutAirHumRat = PsyWFnTdbH(state, EvapInletDryBulb, hTinwout, RoutineName, true);
    2616        12270 :         Real64 FullLoadOutAirTemp = PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
    2617              :         // Check for saturation error and modify temperature at constant enthalpy
    2618        12270 :         if (FullLoadOutAirTemp < PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    2619        10627 :             FullLoadOutAirTemp = PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName);
    2620        10627 :             FullLoadOutAirHumRat = PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
    2621              :         }
    2622              : 
    2623              :         // Continuous fan, cycling compressor
    2624        12270 :         Real64 const EvapOutletAirEnthalpy = ((PartLoadRatio)*FullLoadOutAirEnth + (1.0 - (PartLoadRatio)) * EvapInletEnthalpy);
    2625        12270 :         Real64 EvapOutletAirHumRat = ((PartLoadRatio)*FullLoadOutAirHumRat + (1.0 - (PartLoadRatio)) * EvapInletHumRat);
    2626        12270 :         Real64 EvapOutletAirTemp = PsyTdbFnHW(EvapOutletAirEnthalpy, EvapOutletAirHumRat);
    2627        12270 :         if (EvapOutletAirTemp < PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName)) {
    2628         1911 :             EvapOutletAirTemp = PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName);
    2629         1911 :             EvapOutletAirHumRat = PsyWFnTdbH(state, EvapOutletAirTemp, EvapOutletAirEnthalpy, RoutineName);
    2630              :         }
    2631              :         // Calculate electricity consumed. First, get EIR modifying factors for off-rated conditions
    2632        12270 :         Real64 EIRTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyEIRFTempCurve, EvapInletWetBulb, CondInletTemp);
    2633        12270 :         EIRTempModFac = max(EIRTempModFac, 0.0);
    2634              : 
    2635        12270 :         Real64 EIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyEIRFFlowCurve, AirMassFlowRatio);
    2636        12270 :         EIRFlowModFac = max(EIRFlowModFac, 0.0);
    2637              : 
    2638        12270 :         Real64 const EIR = EIRTempModFac * EIRFlowModFac / thisTESCoil.CoolingOnlyRatedCOP;
    2639              : 
    2640        12270 :         Real64 const ElecCoolingPower = TotCap * EIR * RuntimeFraction;
    2641              : 
    2642        12270 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = EvapOutletAirTemp;
    2643        12270 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = EvapOutletAirHumRat;
    2644        12270 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = EvapOutletAirEnthalpy;
    2645        12270 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate = EvapAirMassFlow;
    2646        12270 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    2647        12270 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    2648        12270 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    2649        12270 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    2650              : 
    2651              :         // determine condenser leaving conditions
    2652        12270 :         Real64 const QdotCond = TotCap * RuntimeFraction + ElecCoolingPower;
    2653        12270 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    2654        12270 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    2655        12270 :         Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
    2656        12270 :         Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
    2657        12270 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
    2658        12270 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
    2659        12270 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
    2660              : 
    2661        12270 :         thisTESCoil.ElecCoolingPower = ElecCoolingPower + thisTESCoil.AncillaryControlsPower;
    2662        12270 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    2663              : 
    2664        12270 :         thisTESCoil.RuntimeFraction = RuntimeFraction;
    2665        12270 :         thisTESCoil.CondenserRuntimeFraction = RuntimeFraction;
    2666        12270 :         thisTESCoil.EvapTotCoolingRate = TotCap * RuntimeFraction; // double check this
    2667        12270 :         thisTESCoil.EvapTotCoolingEnergy = TotCap * RuntimeFraction * TimeStepSysSec;
    2668        12270 :         Real64 const MinAirHumRat = min(state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat,
    2669        12270 :                                         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat);
    2670        12270 :         thisTESCoil.EvapSensCoolingRate =
    2671        12270 :             EvapAirMassFlow * (PsyHFnTdbW(EvapInletDryBulb, MinAirHumRat) - PsyHFnTdbW(EvapOutletAirTemp, MinAirHumRat));
    2672        12270 :         if (thisTESCoil.EvapSensCoolingRate > thisTESCoil.EvapTotCoolingRate) {
    2673            0 :             thisTESCoil.EvapSensCoolingRate = thisTESCoil.EvapTotCoolingRate;
    2674              :         }
    2675        12270 :         thisTESCoil.EvapSensCoolingEnergy = thisTESCoil.EvapSensCoolingRate * TimeStepSysSec;
    2676        12270 :         thisTESCoil.EvapLatCoolingRate = thisTESCoil.EvapTotCoolingRate - thisTESCoil.EvapSensCoolingRate;
    2677        12270 :         thisTESCoil.EvapLatCoolingEnergy = thisTESCoil.EvapLatCoolingRate * TimeStepSysSec;
    2678              : 
    2679        12270 :     } else { // coil is off; just pass through conditions
    2680        18273 :         thisTESCoil.ElecCoolingPower = thisTESCoil.AncillaryControlsPower;
    2681        18273 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    2682        18273 :         thisTESCoil.RuntimeFraction = 0.0;
    2683        18273 :         thisTESCoil.CondenserRuntimeFraction = 0.0;
    2684        18273 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    2685        18273 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    2686        18273 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
    2687        18273 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    2688        18273 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    2689        18273 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    2690        18273 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    2691        18273 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    2692        18273 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    2693        18273 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
    2694              : 
    2695        18273 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    2696        18273 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    2697        18273 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
    2698        18273 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
    2699        18273 :             state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
    2700        18273 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    2701        18273 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
    2702        18273 :         thisTESCoil.EvapTotCoolingRate = 0.0;
    2703        18273 :         thisTESCoil.EvapTotCoolingEnergy = 0.0;
    2704        18273 :         thisTESCoil.EvapSensCoolingRate = 0.0;
    2705        18273 :         thisTESCoil.EvapSensCoolingEnergy = 0.0;
    2706        18273 :         thisTESCoil.EvapLatCoolingRate = 0.0;
    2707        18273 :         thisTESCoil.EvapLatCoolingEnergy = 0.0;
    2708              :     }
    2709              : 
    2710        30543 :     thisTESCoil.QdotTES = 0.0;
    2711        30543 :     thisTESCoil.Q_TES = 0.0;
    2712              : 
    2713        30543 :     UpdateTEStorage(state, TESCoilNum);
    2714              : 
    2715        30543 :     thisTESCoil.CondInletTemp = CondInletTemp;
    2716              : 
    2717        30543 :     UpdateColdWeatherProtection(state, TESCoilNum);
    2718              : 
    2719        30543 :     if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    2720         7623 :         UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
    2721         7623 :         UpdateEvaporativeCondenserWaterUse(state, TESCoilNum, CondInletHumRat, thisTESCoil.CondAirInletNodeNum);
    2722              :     }
    2723        30543 : }
    2724              : 
    2725        14200 : void CalcTESCoilCoolingAndChargeMode(EnergyPlusData &state,
    2726              :                                      int const TESCoilNum,
    2727              :                                      [[maybe_unused]] HVAC::FanOp const fanOp,
    2728              :                                      Real64 const PartLoadRatio)
    2729              : {
    2730              : 
    2731              :     // SUBROUTINE INFORMATION:
    2732              :     //       AUTHOR         Brent Griffith
    2733              :     //       DATE WRITTEN   April 2013
    2734              :     //       MODIFIED       na
    2735              :     //       RE-ENGINEERED  na
    2736              : 
    2737              :     // Using/Aliasing
    2738        14200 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    2739              : 
    2740              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2741        14200 :     int constexpr MaxIter(30);
    2742        14200 :     Real64 constexpr RelaxationFactor(0.4);
    2743        14200 :     Real64 constexpr Tolerance(0.1);
    2744              :     static constexpr std::string_view RoutineName("CalcTESCoilCoolingAndChargeMode");
    2745              : 
    2746              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2747              :     Real64 CondInletTemp;   // Condenser inlet temperature (C). Outdoor dry-bulb temp for air-cooled condenser.
    2748              :                             // Outdoor Wetbulb +(1 - effectiveness)*(outdoor drybulb - outdoor wetbulb) for evap condenser.
    2749              :     Real64 CondInletHumRat; // Condenser inlet humidity ratio (kg/kg). Zero for air-cooled condenser.
    2750              :                             // For evap condenser, its the humidity ratio of the air leaving the evap cooling pads.
    2751              : 
    2752        14200 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    2753              : 
    2754              :     // first deal with condenser
    2755        14200 :     if (thisTESCoil.CondenserType == TESCondenserType::Air) {
    2756        11879 :         Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
    2757        11879 :         if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
    2758            0 :             CondInletTemp = state.dataEnvrn->OutDryBulbTemp;
    2759            0 :             CondInletHumRat = state.dataEnvrn->OutHumRat;
    2760              :         } else {
    2761        11879 :             CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    2762        11879 :             CondInletHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    2763              :         }
    2764         2321 :     } else if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    2765         2321 :         Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
    2766         2321 :         Real64 OutdoorDryBulb = 0.0;
    2767         2321 :         Real64 OutdoorWetBulb = 0.0;
    2768         2321 :         if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
    2769            0 :             OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
    2770            0 :             OutdoorWetBulb = state.dataEnvrn->OutWetBulbTemp;
    2771              :         } else {
    2772         2321 :             OutdoorDryBulb = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    2773         2321 :             Real64 const OutdoorHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    2774         2321 :             OutdoorWetBulb = PsyTwbFnTdbWPb(state, OutdoorDryBulb, OutdoorHumRat, CondAirSidePressure, RoutineName);
    2775              :         }
    2776              :         // direct evap cool model
    2777         2321 :         CondInletTemp = OutdoorWetBulb + (OutdoorDryBulb - OutdoorWetBulb) * (1.0 - thisTESCoil.EvapCondEffect);
    2778         2321 :         CondInletHumRat = PsyWFnTdbTwbPb(state, CondInletTemp, OutdoorWetBulb, CondAirSidePressure, RoutineName);
    2779              :     }
    2780              : 
    2781              :     Real64 QdotChargeLimit; // limit for charge cooling power to hit limit of storage.
    2782              :     Real64 sTES;            // stat of Thermal energy storage [C or fraction of ice]
    2783              :     bool TESCanBeCharged;
    2784              : 
    2785        14200 :     switch (state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).StorageMedia) {
    2786        10138 :     case MediaType::Water:
    2787              :     case MediaType::UserDefindFluid:
    2788        10138 :         sTES = thisTESCoil.FluidTankTempFinalLastTimestep;
    2789        10138 :         if ((sTES > thisTESCoil.MinimumFluidTankTempLimit) && (sTES < thisTESCoil.MaximumFluidTankTempLimit)) {
    2790        10138 :             TESCanBeCharged = true;
    2791              :             // find charge limit to reach limits
    2792        10138 :             Real64 const rho = thisTESCoil.glycol->getDensity(state, sTES, RoutineName);
    2793        10138 :             Real64 const TankMass = rho * thisTESCoil.FluidStorageVolume;
    2794        10138 :             Real64 const CpTank = thisTESCoil.glycol->getSpecificHeat(state, sTES, RoutineName);
    2795              :             // simple linear approximation of DT/Dt term in McpDT/Dt
    2796        10138 :             QdotChargeLimit = TankMass * CpTank * (sTES - thisTESCoil.MinimumFluidTankTempLimit) / TimeStepSysSec;
    2797        10138 :         } else {
    2798            0 :             TESCanBeCharged = false;
    2799              :         }
    2800        10138 :         break;
    2801         4062 :     case MediaType::Ice:
    2802         4062 :         sTES = thisTESCoil.IceFracRemainLastTimestep;
    2803         4062 :         if (sTES < 1.0) {
    2804         4062 :             TESCanBeCharged = true;
    2805              :             // find charge limit to reach limit
    2806         4062 :             QdotChargeLimit = (1.0 - sTES) * thisTESCoil.IceStorageCapacity / TimeStepSysSec;
    2807              :         } else {
    2808            0 :             TESCanBeCharged = false;
    2809              :         }
    2810         4062 :         break;
    2811            0 :     default:
    2812            0 :         break;
    2813              :     }
    2814              : 
    2815              :     // local for evaporator air mass flow [kg/s]
    2816        14200 :     Real64 const EvapAirMassFlow = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    2817              :     // evaporator inlet air drybulb [C]
    2818        14200 :     Real64 const EvapInletDryBulb = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    2819              :     // evaporator inlet air humidity ratio [kg/kg]
    2820        14200 :     Real64 const EvapInletHumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    2821              :     // evaporator inlet air wetbulb [C]
    2822        14200 :     Real64 const EvapInletWetBulb = PsyTwbFnTdbWPb(state, EvapInletDryBulb, EvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
    2823              : 
    2824        14200 :     Real64 TotChargeCap = 0.0;
    2825              : 
    2826        14200 :     if ((EvapAirMassFlow > HVAC::SmallMassFlow) && (PartLoadRatio > 0.0)) { // coil is running
    2827              : 
    2828         5269 :         Real64 const EvapInletEnthalpy = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Enthalpy;
    2829              : 
    2830              :         // evaporator inlet air mass flow divided by design mass flow [ ]
    2831         5269 :         Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
    2832              : 
    2833              :         // total cooling capacity modification factor due to temps []
    2834              :         Real64 EvapTotCapTempModFac =
    2835         5269 :             EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    2836         5269 :         EvapTotCapTempModFac = max(0.0, EvapTotCapTempModFac); // could warn if negative, DXcoil does
    2837              : 
    2838              :         // total cooling capacity modification factor due to flow []
    2839         5269 :         Real64 EvapTotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingCapFFlowCurve, AirMassFlowRatio);
    2840         5269 :         EvapTotCapFlowModFac = max(0.0, EvapTotCapFlowModFac); // could warn if negative, DXcoil does
    2841              : 
    2842              :         // total cooling capacity
    2843         5269 :         Real64 EvapTotCap = thisTESCoil.CoolingAndChargeRatedTotCap * EvapTotCapTempModFac * EvapTotCapFlowModFac;
    2844              : 
    2845              :         // now see if coil is running dry
    2846         5269 :         Real64 const PartLoadOutAirEnth = EvapInletEnthalpy - (EvapTotCap * PartLoadRatio) / EvapAirMassFlow;
    2847         5269 :         Real64 const PartLoadDryCoilOutAirTemp = PsyTdbFnHW(PartLoadOutAirEnth, EvapInletHumRat);
    2848              : 
    2849         5269 :         bool CoilMightBeDry = false;
    2850         5269 :         Real64 DryCoilTestEvapInletHumRat = 0.0;
    2851         5269 :         Real64 SHRadp = 0.0;
    2852         5269 :         if (PartLoadDryCoilOutAirTemp > PsyTsatFnHPb(state, PartLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    2853            4 :             CoilMightBeDry = true;
    2854              :             // find wADP, humidity ratio at apparatus dewpoint and inlet hum rat that would have dry coil
    2855            4 :             DryCoilTestEvapInletHumRat = EvapInletHumRat;
    2856            4 :             Real64 DryCoilTestEvapInletWetBulb = EvapInletWetBulb;
    2857            4 :             int Counter = 0;
    2858            4 :             bool Converged = false;
    2859            8 :             while (!Converged) {
    2860            4 :                 EvapTotCapTempModFac = EnergyPlus::Curve::CurveValue(
    2861              :                     state, thisTESCoil.CoolingAndChargeCoolingCapFTempCurve, DryCoilTestEvapInletWetBulb, CondInletTemp, sTES);
    2862            4 :                 EvapTotCapTempModFac = max(0.0, EvapTotCapTempModFac); // could warn if negative, DXcoil does
    2863            4 :                 EvapTotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingCapFFlowCurve, AirMassFlowRatio);
    2864            4 :                 EvapTotCapFlowModFac = max(0.0, EvapTotCapFlowModFac); // could warn if negative, DXcoil does
    2865            4 :                 EvapTotCap = thisTESCoil.CoolingAndChargeRatedTotCap * EvapTotCapTempModFac * EvapTotCapFlowModFac;
    2866              :                 // coil bypass factor = 0.0
    2867            4 :                 Real64 const hADP = EvapInletEnthalpy - (EvapTotCap / EvapAirMassFlow);
    2868            4 :                 Real64 const tADP = PsyTsatFnHPb(state, hADP, state.dataEnvrn->OutBaroPress, RoutineName);
    2869            4 :                 Real64 const wADP = min(EvapInletHumRat, PsyWFnTdbH(state, tADP, hADP, RoutineName));
    2870            4 :                 Real64 const hTinwADP = PsyHFnTdbW(EvapInletDryBulb, wADP);
    2871            4 :                 if ((EvapInletEnthalpy - hADP) > 1.e-10) {
    2872            4 :                     SHRadp = min((hTinwADP - hADP) / (EvapInletEnthalpy - hADP), 1.0);
    2873              :                 } else {
    2874            0 :                     SHRadp = 1.0;
    2875              :                 }
    2876              : 
    2877            4 :                 if ((wADP > DryCoilTestEvapInletHumRat) || (Counter >= 1 && Counter < MaxIter)) {
    2878            0 :                     if (DryCoilTestEvapInletHumRat <= 0.0) {
    2879            0 :                         DryCoilTestEvapInletHumRat = 0.00001;
    2880              :                     }
    2881            0 :                     Real64 const werror = (DryCoilTestEvapInletHumRat - wADP) / DryCoilTestEvapInletHumRat;
    2882              : 
    2883            0 :                     DryCoilTestEvapInletHumRat = RelaxationFactor * wADP + (1.0 - RelaxationFactor) * DryCoilTestEvapInletHumRat;
    2884              :                     DryCoilTestEvapInletWetBulb =
    2885            0 :                         PsyTwbFnTdbWPb(state, EvapInletDryBulb, DryCoilTestEvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
    2886              : 
    2887            0 :                     ++Counter;
    2888            0 :                     Converged = (std::abs(werror) <= Tolerance);
    2889            0 :                 } else {
    2890            4 :                     Converged = true;
    2891              :                 }
    2892              :             }
    2893              :         }
    2894              : 
    2895              :         // total cooling capacity modification factors
    2896              :         Real64 const SHRTempFac =
    2897         5269 :             (state.dataCurveManager->curves(thisTESCoil.CoolingAndChargeSHRFTempCurve)->numDims == 2)
    2898         5269 :                 ? EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeSHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb)
    2899         4330 :                 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeSHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb, sTES);
    2900         5269 :         Real64 const SHRFlowFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeSHRFFlowCurve, AirMassFlowRatio);
    2901         5269 :         Real64 SHR = thisTESCoil.CoolingAndChargeRatedSHR * SHRTempFac * SHRFlowFac;
    2902         5269 :         SHR = min(SHR, 1.0); // warn maybe
    2903         5269 :         SHR = max(SHR, 0.0); // warn maybe
    2904         5269 :         if (CoilMightBeDry) {
    2905            4 :             if ((EvapInletHumRat < DryCoilTestEvapInletHumRat) && (SHRadp > SHR)) { // coil is dry for sure
    2906            0 :                 SHR = 1.0;
    2907            4 :             } else if (SHRadp > SHR) {
    2908            4 :                 SHR = SHRadp;
    2909              :             }
    2910              :         }
    2911              : 
    2912              :         // part load factor
    2913         5269 :         Real64 const PLF = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingPLFFPLRCurve, PartLoadRatio);
    2914              :         // compressor running time divided by full time of timestep.
    2915         5269 :         Real64 EvapRuntimeFraction = 1.0;
    2916         5269 :         if (PLF >= PartLoadRatio && PLF > 0.0) {
    2917         3061 :             EvapRuntimeFraction = PartLoadRatio / PLF;
    2918              :         } else {
    2919         2208 :             EvapRuntimeFraction = 1.0; // warn maybe
    2920              :         }
    2921              : 
    2922              :         // Calculate electricity consumed. First, get EIR modifying factors for off-rated conditions
    2923              :         Real64 EIRTempModFac =
    2924         5269 :             EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    2925         5269 :         EIRTempModFac = max(EIRTempModFac, 0.0);
    2926              : 
    2927         5269 :         Real64 EIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingEIRFFlowCurve, AirMassFlowRatio);
    2928         5269 :         EIRFlowModFac = max(EIRFlowModFac, 0.0);
    2929              : 
    2930         5269 :         Real64 const EIR = EIRTempModFac * EIRFlowModFac / thisTESCoil.CoolingAndChargeCoolingRatedCOP;
    2931              : 
    2932         5269 :         Real64 const EvapElecCoolingPower = EvapTotCap * EIR * EvapRuntimeFraction;
    2933              : 
    2934         5269 :         TotChargeCap = 0.0;
    2935         5269 :         Real64 ChargeRuntimeFraction = 0.0;
    2936         5269 :         Real64 ChargeElectricCoolingPower = 0.0;
    2937         5269 :         if (TESCanBeCharged) {
    2938              :             Real64 ChargeCapModFac =
    2939         5269 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    2940         5269 :             ChargeCapModFac = max(0.0, ChargeCapModFac);
    2941              : 
    2942         5269 :             Real64 ChargeCapPLRModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingCapFEvapPLRCurve, PartLoadRatio);
    2943         5269 :             ChargeCapPLRModFac = max(0.0, ChargeCapPLRModFac);
    2944              : 
    2945         5269 :             TotChargeCap = thisTESCoil.CoolingAndChargeRatedChargeCap * ChargeCapModFac * ChargeCapPLRModFac;
    2946         5269 :             if (TotChargeCap > QdotChargeLimit) {
    2947            0 :                 ChargeRuntimeFraction = QdotChargeLimit / TotChargeCap;
    2948            0 :                 TotChargeCap = min(TotChargeCap, QdotChargeLimit);
    2949              :             } else {
    2950         5269 :                 ChargeRuntimeFraction = 1.0;
    2951              :             }
    2952              :             Real64 ChargeEIRTempModFac =
    2953         5269 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    2954         5269 :             ChargeEIRTempModFac = max(0.0, ChargeEIRTempModFac);
    2955              : 
    2956         5269 :             Real64 ChargeEIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingEIRFFLowCurve, AirMassFlowRatio);
    2957         5269 :             ChargeEIRFlowModFac = max(0.0, ChargeEIRFlowModFac);
    2958              : 
    2959         5269 :             Real64 const ChargeEIR = (ChargeEIRTempModFac * ChargeEIRFlowModFac) / thisTESCoil.CoolingAndChargeChargingRatedCOP;
    2960         5269 :             ChargeElectricCoolingPower = TotChargeCap * ChargeEIR;
    2961         5269 :             thisTESCoil.QdotTES = -TotChargeCap;
    2962              :         } else {
    2963            0 :             TotChargeCap = 0.0;
    2964            0 :             ChargeElectricCoolingPower = 0.0;
    2965            0 :             thisTESCoil.QdotTES = 0.0;
    2966            0 :             ChargeRuntimeFraction = 0.0;
    2967              :         }
    2968              : 
    2969              :         //  Calculate full load output conditions
    2970         5269 :         Real64 const FullLoadOutAirEnth = EvapInletEnthalpy - EvapTotCap / EvapAirMassFlow;
    2971              : 
    2972         5269 :         Real64 const hTinwout = EvapInletEnthalpy - (1.0 - SHR) * (EvapTotCap / EvapAirMassFlow);
    2973              :         // The following will often throw psych warnings for neg w, suppress warnings because error condition is handled in next IF
    2974         5269 :         Real64 FullLoadOutAirHumRat = PsyWFnTdbH(state, EvapInletDryBulb, hTinwout, RoutineName, true);
    2975         5269 :         Real64 FullLoadOutAirTemp = PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
    2976              :         // Check for saturation error and modify temperature at constant enthalpy
    2977         5269 :         if (FullLoadOutAirTemp < PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    2978         5265 :             FullLoadOutAirTemp = PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName);
    2979         5265 :             FullLoadOutAirHumRat = PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
    2980              :         }
    2981              : 
    2982              :         // Continuous fan, cycling compressor
    2983         5269 :         Real64 const EvapOutletAirEnthalpy = ((PartLoadRatio)*FullLoadOutAirEnth + (1.0 - (PartLoadRatio)) * EvapInletEnthalpy);
    2984         5269 :         Real64 EvapOutletAirHumRat = ((PartLoadRatio)*FullLoadOutAirHumRat + (1.0 - (PartLoadRatio)) * EvapInletHumRat);
    2985         5269 :         Real64 EvapOutletAirTemp = PsyTdbFnHW(EvapOutletAirEnthalpy, EvapOutletAirHumRat);
    2986         5269 :         if (EvapOutletAirTemp < PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName)) {
    2987          904 :             EvapOutletAirTemp = PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName);
    2988          904 :             EvapOutletAirHumRat = PsyWFnTdbH(state, EvapOutletAirTemp, EvapOutletAirEnthalpy, RoutineName);
    2989              :         }
    2990              : 
    2991         5269 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = EvapOutletAirTemp;
    2992         5269 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = EvapOutletAirHumRat;
    2993         5269 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = EvapOutletAirEnthalpy;
    2994         5269 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate = EvapAirMassFlow;
    2995         5269 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    2996         5269 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    2997         5269 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    2998         5269 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    2999              : 
    3000              :         // determine condenser leaving conditions
    3001              :         // condenser total heat rejection rate [W]
    3002         5269 :         Real64 const QdotCond = EvapTotCap * EvapRuntimeFraction + EvapElecCoolingPower + TotChargeCap + ChargeElectricCoolingPower;
    3003         5269 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3004         5269 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3005              :         // condenser inlet enthalpy [J/kg]
    3006         5269 :         Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
    3007         5269 :         Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
    3008         5269 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
    3009         5269 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
    3010         5269 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
    3011              : 
    3012         5269 :         thisTESCoil.ElecCoolingPower = EvapElecCoolingPower + ChargeElectricCoolingPower + thisTESCoil.AncillaryControlsPower;
    3013         5269 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3014              : 
    3015         5269 :         thisTESCoil.RuntimeFraction = EvapRuntimeFraction;
    3016         5269 :         if (ChargeRuntimeFraction > 0.0) {
    3017         5269 :             thisTESCoil.CondenserRuntimeFraction = max(ChargeRuntimeFraction, EvapRuntimeFraction);
    3018              :         } else {
    3019            0 :             thisTESCoil.CondenserRuntimeFraction = EvapRuntimeFraction;
    3020              :         }
    3021              : 
    3022         5269 :         thisTESCoil.EvapTotCoolingRate = EvapTotCap * EvapRuntimeFraction; // double check this
    3023         5269 :         thisTESCoil.EvapTotCoolingEnergy = EvapTotCap * EvapRuntimeFraction * TimeStepSysSec;
    3024         5269 :         Real64 const MinAirHumRat = min(state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat,
    3025         5269 :                                         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat);
    3026         5269 :         thisTESCoil.EvapSensCoolingRate =
    3027         5269 :             EvapAirMassFlow * (PsyHFnTdbW(EvapInletDryBulb, MinAirHumRat) - PsyHFnTdbW(EvapOutletAirTemp, MinAirHumRat));
    3028         5269 :         if (thisTESCoil.EvapSensCoolingRate > thisTESCoil.EvapTotCoolingRate) {
    3029            0 :             thisTESCoil.EvapSensCoolingRate = thisTESCoil.EvapTotCoolingRate;
    3030              :         }
    3031         5269 :         thisTESCoil.EvapSensCoolingEnergy = thisTESCoil.EvapSensCoolingRate * TimeStepSysSec;
    3032         5269 :         thisTESCoil.EvapLatCoolingRate = thisTESCoil.EvapTotCoolingRate - thisTESCoil.EvapSensCoolingRate;
    3033         5269 :         thisTESCoil.EvapLatCoolingEnergy = thisTESCoil.EvapLatCoolingRate * TimeStepSysSec;
    3034              : 
    3035         5269 :     } else { // Evap off, but may still charge
    3036              : 
    3037         8931 :         TotChargeCap = 0.0;
    3038         8931 :         Real64 ChargeElectricCoolingPower = 0.0;
    3039         8931 :         Real64 ChargeRuntimeFraction = 0.0;
    3040         8931 :         if (TESCanBeCharged) { // coil is running to charge but not to cool at evaporator
    3041         8931 :             Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
    3042              :             Real64 ChargeCapModFac =
    3043         8931 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    3044         8931 :             ChargeCapModFac = max(0.0, ChargeCapModFac);
    3045              : 
    3046         8931 :             Real64 ChargeCapPLRModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingCapFEvapPLRCurve, PartLoadRatio);
    3047         8931 :             ChargeCapPLRModFac = max(0.0, ChargeCapPLRModFac);
    3048              : 
    3049         8931 :             TotChargeCap = thisTESCoil.CoolingAndChargeRatedChargeCap * ChargeCapModFac * ChargeCapPLRModFac;
    3050         8931 :             ChargeRuntimeFraction = 1.0;
    3051         8931 :             if (TotChargeCap > QdotChargeLimit) {
    3052            4 :                 ChargeRuntimeFraction = QdotChargeLimit / TotChargeCap;
    3053            4 :                 TotChargeCap = min(TotChargeCap, QdotChargeLimit);
    3054              :             }
    3055              :             Real64 ChargeEIRTempModFac =
    3056         8931 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    3057         8931 :             ChargeEIRTempModFac = max(0.0, ChargeEIRTempModFac);
    3058              : 
    3059         8931 :             Real64 ChargeEIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingEIRFFLowCurve, AirMassFlowRatio);
    3060         8931 :             ChargeEIRFlowModFac = max(0.0, ChargeEIRFlowModFac);
    3061              : 
    3062         8931 :             Real64 const ChargeEIR = (ChargeEIRTempModFac * ChargeEIRFlowModFac) / thisTESCoil.CoolingAndChargeChargingRatedCOP;
    3063         8931 :             ChargeElectricCoolingPower = TotChargeCap * ChargeEIR;
    3064         8931 :             thisTESCoil.QdotTES = -TotChargeCap;
    3065              :         } else {
    3066            0 :             TotChargeCap = 0.0;
    3067            0 :             ChargeElectricCoolingPower = 0.0;
    3068            0 :             thisTESCoil.QdotTES = 0.0;
    3069            0 :             ChargeRuntimeFraction = 0.0;
    3070              :         }
    3071              : 
    3072         8931 :         thisTESCoil.ElecCoolingPower = ChargeElectricCoolingPower + thisTESCoil.AncillaryControlsPower;
    3073         8931 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3074              : 
    3075         8931 :         thisTESCoil.RuntimeFraction = 0.0;
    3076         8931 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    3077         8931 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    3078         8931 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
    3079         8931 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    3080         8931 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    3081         8931 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    3082         8931 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    3083         8931 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    3084         8931 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    3085         8931 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
    3086              : 
    3087         8931 :         thisTESCoil.EvapTotCoolingRate = 0.0;
    3088         8931 :         thisTESCoil.EvapTotCoolingEnergy = 0.0;
    3089         8931 :         thisTESCoil.EvapSensCoolingRate = 0.0;
    3090         8931 :         thisTESCoil.EvapSensCoolingEnergy = 0.0;
    3091         8931 :         thisTESCoil.EvapLatCoolingRate = 0.0;
    3092         8931 :         thisTESCoil.EvapLatCoolingEnergy = 0.0;
    3093              : 
    3094         8931 :         if (TotChargeCap == 0.0) {
    3095            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3096            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    3097            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
    3098            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
    3099            0 :                 state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
    3100            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    3101            0 :                 state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
    3102            0 :             thisTESCoil.CondenserRuntimeFraction = 0.0;
    3103              :         } else {
    3104              : 
    3105              :             // determine condenser leaving conditions
    3106         8931 :             Real64 const QdotCond = TotChargeCap + ChargeElectricCoolingPower;
    3107         8931 :             state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3108         8931 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3109         8931 :             Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
    3110         8931 :             Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
    3111         8931 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
    3112         8931 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
    3113         8931 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
    3114         8931 :             thisTESCoil.CondenserRuntimeFraction = 1.0;
    3115              :         }
    3116              :     }
    3117              : 
    3118        14200 :     thisTESCoil.QdotTES = -TotChargeCap;
    3119        14200 :     thisTESCoil.Q_TES = thisTESCoil.QdotTES * TimeStepSysSec;
    3120              : 
    3121        14200 :     UpdateTEStorage(state, TESCoilNum);
    3122              : 
    3123        14200 :     thisTESCoil.CondInletTemp = CondInletTemp;
    3124              : 
    3125        14200 :     UpdateColdWeatherProtection(state, TESCoilNum);
    3126              : 
    3127        14200 :     if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    3128         2321 :         UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
    3129         2321 :         UpdateEvaporativeCondenserWaterUse(state, TESCoilNum, CondInletHumRat, thisTESCoil.CondAirInletNodeNum);
    3130              :     }
    3131        14200 : }
    3132              : 
    3133         2338 : void CalcTESCoilCoolingAndDischargeMode(EnergyPlusData &state,
    3134              :                                         int const TESCoilNum,
    3135              :                                         [[maybe_unused]] HVAC::FanOp const fanOp,
    3136              :                                         Real64 const PartLoadRatio)
    3137              : {
    3138              : 
    3139              :     // SUBROUTINE INFORMATION:
    3140              :     //       AUTHOR         Brent Griffith
    3141              :     //       DATE WRITTEN   April 2013
    3142              :     //       MODIFIED       na
    3143              :     //       RE-ENGINEERED  na
    3144              : 
    3145              :     // Using/Aliasing
    3146         2338 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    3147              : 
    3148              :     // SUBROUTINE PARAMETER DEFINITIONS:
    3149         2338 :     int constexpr MaxIter(30);
    3150         2338 :     Real64 constexpr RelaxationFactor(0.4);
    3151         2338 :     Real64 constexpr Tolerance(0.1);
    3152              :     static constexpr std::string_view RoutineName("CalcTESCoilCoolingAndDischargeMode");
    3153              : 
    3154              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3155              :     Real64 CondInletTemp;   // Condenser inlet temperature (C). Outdoor dry-bulb temp for air-cooled condenser.
    3156              :                             // Outdoor Wetbulb +(1 - effectiveness)*(outdoor drybulb - outdoor wetbulb) for evap condenser.
    3157              :     Real64 CondInletHumRat; // Condenser inlet humidity ratio (kg/kg). Zero for air-cooled condenser.
    3158              :                             // For evap condenser, its the humidity ratio of the air leaving the evap cooling pads.
    3159              : 
    3160         2338 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    3161              : 
    3162              :     // first deal with condenser
    3163         2338 :     if (thisTESCoil.CondenserType == TESCondenserType::Air) {
    3164         2338 :         Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
    3165         2338 :         if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
    3166            0 :             CondInletTemp = state.dataEnvrn->OutDryBulbTemp;
    3167            0 :             CondInletHumRat = state.dataEnvrn->OutHumRat;
    3168              :         } else {
    3169         2338 :             CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3170         2338 :             CondInletHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    3171              :         }
    3172            0 :     } else if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    3173            0 :         Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
    3174            0 :         Real64 OutdoorDryBulb = 0.0;
    3175            0 :         Real64 OutdoorWetBulb = 0.0;
    3176            0 :         if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
    3177            0 :             OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
    3178            0 :             OutdoorWetBulb = state.dataEnvrn->OutWetBulbTemp;
    3179              :         } else {
    3180            0 :             OutdoorDryBulb = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3181            0 :             Real64 const OutdoorHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    3182            0 :             OutdoorWetBulb = PsyTwbFnTdbWPb(state, OutdoorDryBulb, OutdoorHumRat, CondAirSidePressure, RoutineName);
    3183              :         }
    3184              :         // direct evap cool model
    3185            0 :         CondInletTemp = OutdoorWetBulb + (OutdoorDryBulb - OutdoorWetBulb) * (1.0 - thisTESCoil.EvapCondEffect);
    3186            0 :         CondInletHumRat = PsyWFnTdbTwbPb(state, CondInletTemp, OutdoorWetBulb, CondAirSidePressure, RoutineName);
    3187              :     }
    3188              : 
    3189              :     Real64 QdotDischargeLimit; // limit for discharge cooling power to hit limit of storage.
    3190              :     Real64 sTES;               // stat of Thermal energy storage [C or fraction of ice]
    3191         2338 :     bool TESHasSomeCharge = false;
    3192              : 
    3193         2338 :     switch (thisTESCoil.StorageMedia) {
    3194         2338 :     case MediaType::Water:
    3195              :     case MediaType::UserDefindFluid:
    3196         2338 :         sTES = thisTESCoil.FluidTankTempFinalLastTimestep;
    3197         2338 :         if ((sTES >= thisTESCoil.MinimumFluidTankTempLimit) && (sTES < thisTESCoil.MaximumFluidTankTempLimit)) {
    3198         2338 :             TESHasSomeCharge = true;
    3199         2338 :             Real64 const rho = thisTESCoil.glycol->getDensity(state, sTES, RoutineName);
    3200         2338 :             Real64 const TankMass = rho * thisTESCoil.FluidStorageVolume;
    3201         2338 :             Real64 const CpTank = thisTESCoil.glycol->getSpecificHeat(state, sTES, RoutineName);
    3202              :             // simple linear approximation of DT/Dt term in McpDT/Dt
    3203         2338 :             QdotDischargeLimit = TankMass * CpTank * (thisTESCoil.MaximumFluidTankTempLimit - sTES) / TimeStepSysSec;
    3204         2338 :         } else {
    3205            0 :             TESHasSomeCharge = false;
    3206              :         }
    3207         2338 :         break;
    3208            0 :     case MediaType::Ice:
    3209            0 :         sTES = thisTESCoil.IceFracRemainLastTimestep;
    3210            0 :         if (sTES > 0.0) {
    3211            0 :             TESHasSomeCharge = true;
    3212              :             // discharge limit
    3213            0 :             QdotDischargeLimit = (sTES)*thisTESCoil.IceStorageCapacity / TimeStepSysSec;
    3214              :         } else {
    3215            0 :             TESHasSomeCharge = false;
    3216              :         }
    3217            0 :         break;
    3218            0 :     default:
    3219            0 :         break;
    3220              :     }
    3221              : 
    3222         2338 :     Real64 const EvapAirMassFlow = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    3223              : 
    3224         2338 :     if ((EvapAirMassFlow > HVAC::SmallMassFlow) && (PartLoadRatio > 0.0)) { // coil is running
    3225              : 
    3226         1550 :         Real64 const EvapInletDryBulb = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    3227         1550 :         Real64 const EvapInletHumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    3228         1550 :         Real64 const EvapInletWetBulb = PsyTwbFnTdbWPb(state, EvapInletDryBulb, EvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
    3229         1550 :         Real64 const EvapInletEnthalpy = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Enthalpy;
    3230              : 
    3231              :         // evaporator inlet air mass flow divided by design mass flow [ ]
    3232         1550 :         Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
    3233              : 
    3234              :         // total cooling capacity modification factor due to temps []
    3235              :         Real64 EvapTotCapTempModFac =
    3236         1550 :             EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    3237         1550 :         EvapTotCapTempModFac = max(0.0, EvapTotCapTempModFac); // could warn if negative, DXcoil does
    3238              : 
    3239              :         // total cooling capacity modification factor due to flow []
    3240         1550 :         Real64 EvapTotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingCapFFlowCurve, AirMassFlowRatio);
    3241         1550 :         EvapTotCapFlowModFac = max(0.0, EvapTotCapFlowModFac); // could warn if negative, DXcoil does
    3242              : 
    3243              :         // total cooling capacity
    3244         1550 :         Real64 EvapTotCap = thisTESCoil.CoolingAndDischargeRatedTotCap * EvapTotCapTempModFac * EvapTotCapFlowModFac;
    3245              : 
    3246              :         // now see if coil is running dry
    3247         1550 :         Real64 const PartLoadOutAirEnth = EvapInletEnthalpy - (EvapTotCap * PartLoadRatio) / EvapAirMassFlow;
    3248         1550 :         Real64 const PartLoadDryCoilOutAirTemp = PsyTdbFnHW(PartLoadOutAirEnth, EvapInletHumRat);
    3249              : 
    3250         1550 :         bool CoilMightBeDry = false;
    3251         1550 :         Real64 DryCoilTestEvapInletHumRat = 0.0;
    3252         1550 :         Real64 SHRadp = 0.0;
    3253              : 
    3254         1550 :         if (PartLoadDryCoilOutAirTemp > PsyTsatFnHPb(state, PartLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    3255            0 :             CoilMightBeDry = true;
    3256              :             // find wADP, humidity ratio at apparatus dewpoint and inlet hum rat that would have dry coil
    3257            0 :             DryCoilTestEvapInletHumRat = EvapInletHumRat;
    3258            0 :             Real64 DryCoilTestEvapInletWetBulb = EvapInletWetBulb;
    3259            0 :             int Counter = 0;
    3260            0 :             bool Converged = false;
    3261            0 :             while (!Converged) {
    3262            0 :                 EvapTotCapTempModFac = EnergyPlus::Curve::CurveValue(
    3263              :                     state, thisTESCoil.CoolingAndDischargeCoolingCapFTempCurve, DryCoilTestEvapInletWetBulb, CondInletTemp, sTES);
    3264            0 :                 EvapTotCapTempModFac = max(0.0, EvapTotCapTempModFac); // could warn if negative, DXcoil does
    3265            0 :                 EvapTotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingCapFFlowCurve, AirMassFlowRatio);
    3266            0 :                 EvapTotCapFlowModFac = max(0.0, EvapTotCapFlowModFac); // could warn if negative, DXcoil does
    3267            0 :                 EvapTotCap = thisTESCoil.CoolingAndDischargeRatedTotCap * EvapTotCapTempModFac * EvapTotCapFlowModFac;
    3268              :                 // coil bypass factor = 0.0
    3269            0 :                 Real64 const hADP = EvapInletEnthalpy - (EvapTotCap / EvapAirMassFlow);
    3270            0 :                 Real64 const tADP = PsyTsatFnHPb(state, hADP, state.dataEnvrn->OutBaroPress, RoutineName);
    3271            0 :                 Real64 const wADP = min(EvapInletHumRat, PsyWFnTdbH(state, tADP, hADP, RoutineName));
    3272            0 :                 Real64 const hTinwADP = PsyHFnTdbW(EvapInletDryBulb, wADP);
    3273            0 :                 if ((EvapInletEnthalpy - hADP) > 1.e-10) {
    3274            0 :                     SHRadp = min((hTinwADP - hADP) / (EvapInletEnthalpy - hADP), 1.0);
    3275              :                 } else {
    3276            0 :                     SHRadp = 1.0;
    3277              :                 }
    3278              : 
    3279            0 :                 if ((wADP > DryCoilTestEvapInletHumRat) || (Counter >= 1 && Counter < MaxIter)) {
    3280            0 :                     if (DryCoilTestEvapInletHumRat <= 0.0) {
    3281            0 :                         DryCoilTestEvapInletHumRat = 0.00001;
    3282              :                     }
    3283            0 :                     Real64 const werror = (DryCoilTestEvapInletHumRat - wADP) / DryCoilTestEvapInletHumRat;
    3284              : 
    3285            0 :                     DryCoilTestEvapInletHumRat = RelaxationFactor * wADP + (1.0 - RelaxationFactor) * DryCoilTestEvapInletHumRat;
    3286              :                     DryCoilTestEvapInletWetBulb =
    3287            0 :                         PsyTwbFnTdbWPb(state, EvapInletDryBulb, DryCoilTestEvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
    3288              : 
    3289            0 :                     ++Counter;
    3290            0 :                     Converged = (std::abs(werror) <= Tolerance);
    3291            0 :                 } else {
    3292            0 :                     Converged = true;
    3293              :                 }
    3294              :             }
    3295              :         }
    3296              : 
    3297              :         // total cooling capacity modification factors
    3298              :         Real64 const SHRTempFac =
    3299         1550 :             (state.dataCurveManager->curves(thisTESCoil.CoolingAndDischargeSHRFTempCurve)->numDims == 2)
    3300         1550 :                 ? EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeSHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb)
    3301         1550 :                 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeSHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb, sTES);
    3302         1550 :         Real64 const SHRFlowFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeSHRFFlowCurve, AirMassFlowRatio);
    3303         1550 :         Real64 SHR = thisTESCoil.CoolingAndDischargeRatedSHR * SHRTempFac * SHRFlowFac;
    3304         1550 :         SHR = min(SHR, 1.0); // warn maybe
    3305         1550 :         SHR = max(SHR, 0.0); // warn maybe
    3306         1550 :         if (CoilMightBeDry) {
    3307            0 :             if ((EvapInletHumRat < DryCoilTestEvapInletHumRat) && (SHRadp > SHR)) { // coil is dry for sure
    3308            0 :                 SHR = 1.0;
    3309            0 :             } else if (SHRadp > SHR) {
    3310            0 :                 SHR = SHRadp;
    3311              :             }
    3312              :         }
    3313              :         // part load factor
    3314         1550 :         Real64 const PLF = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingPLFFPLRCurve, PartLoadRatio);
    3315              :         // compressor running time divided by full time of timestep.
    3316         1550 :         Real64 EvapRuntimeFraction = 1.0;
    3317         1550 :         if (PLF >= PartLoadRatio && PLF > 0.0) {
    3318         1550 :             EvapRuntimeFraction = PartLoadRatio / PLF;
    3319              :         } else {
    3320            0 :             EvapRuntimeFraction = 1.0; // warn maybe
    3321              :         }
    3322              :         // Calculate electricity consumed. First, get EIR modifying factors for off-rated conditions
    3323              :         Real64 EIRTempModFac =
    3324         1550 :             EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    3325         1550 :         EIRTempModFac = max(EIRTempModFac, 0.0);
    3326              : 
    3327         1550 :         Real64 EIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingEIRFFlowCurve, AirMassFlowRatio);
    3328         1550 :         EIRFlowModFac = max(EIRFlowModFac, 0.0);
    3329              : 
    3330         1550 :         Real64 const EIR = EIRTempModFac * EIRFlowModFac / thisTESCoil.CoolingAndDischargeCoolingRatedCOP;
    3331              : 
    3332         1550 :         Real64 const EvapElecCoolingPower = EvapTotCap * EIR * EvapRuntimeFraction;
    3333              : 
    3334         1550 :         Real64 TotDischargeCap = 0.0;
    3335         1550 :         Real64 DischargeRuntimeFraction = 0.0;
    3336         1550 :         Real64 DischargeElectricCoolingPower = 0.0;
    3337         1550 :         if (TESHasSomeCharge) {
    3338              :             Real64 DischargeCapTempModFac =
    3339         1550 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    3340         1550 :             DischargeCapTempModFac = max(0.0, DischargeCapTempModFac);
    3341              :             Real64 DischargeCapFlowModFac =
    3342         1550 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingCapFFlowCurve, AirMassFlowRatio);
    3343         1550 :             DischargeCapFlowModFac = max(0.0, DischargeCapFlowModFac);
    3344              : 
    3345              :             Real64 const DischargePLF =
    3346         1550 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingCapFEvapPLRCurve, PartLoadRatio);
    3347         1550 :             if (DischargePLF >= PartLoadRatio && DischargePLF > 0.0) {
    3348          930 :                 DischargeRuntimeFraction = PartLoadRatio / DischargePLF;
    3349              :             } else {
    3350          620 :                 DischargeRuntimeFraction = 1.0; // warn maybe
    3351              :             }
    3352              : 
    3353         1550 :             TotDischargeCap =
    3354         1550 :                 thisTESCoil.CoolingAndDischargeRatedDischargeCap * DischargeCapTempModFac * DischargeCapFlowModFac * DischargeRuntimeFraction;
    3355         1550 :             if (TotDischargeCap > QdotDischargeLimit) {
    3356            0 :                 TotDischargeCap = min(TotDischargeCap, QdotDischargeLimit);
    3357              :             }
    3358              :             Real64 DischargeEIRTempModFac =
    3359         1550 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    3360         1550 :             DischargeEIRTempModFac = max(0.0, DischargeEIRTempModFac);
    3361              : 
    3362              :             Real64 DischargeEIRFlowModFac =
    3363         1550 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingEIRFFLowCurve, AirMassFlowRatio);
    3364         1550 :             DischargeEIRFlowModFac = max(0.0, DischargeEIRFlowModFac);
    3365              : 
    3366         1550 :             Real64 const DischargeEIR = (DischargeEIRTempModFac * DischargeEIRFlowModFac) / thisTESCoil.CoolingAndDischargeDischargingRatedCOP;
    3367         1550 :             DischargeElectricCoolingPower = TotDischargeCap * DischargeEIR * DischargeRuntimeFraction;
    3368         1550 :             thisTESCoil.QdotTES = TotDischargeCap;
    3369              :         } else {
    3370            0 :             TotDischargeCap = 0.0;
    3371            0 :             DischargeRuntimeFraction = 0.0;
    3372            0 :             DischargeElectricCoolingPower = 0.0;
    3373            0 :             thisTESCoil.QdotTES = 0.0;
    3374              :         }
    3375              : 
    3376         1550 :         Real64 const TotCap = EvapTotCap + TotDischargeCap;
    3377              :         //  Calculate full load output conditions
    3378              : 
    3379         1550 :         Real64 const hTinwout = EvapInletEnthalpy - (1.0 - SHR) * (TotCap / EvapAirMassFlow);
    3380         1550 :         Real64 const FullLoadOutAirEnth = EvapInletEnthalpy - TotCap / EvapAirMassFlow;
    3381              :         // The following will often throw psych warnings for neg w, suppress warnings because error condition is handled in next IF
    3382         1550 :         Real64 FullLoadOutAirHumRat = PsyWFnTdbH(state, EvapInletDryBulb, hTinwout, RoutineName, true);
    3383         1550 :         Real64 FullLoadOutAirTemp = PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
    3384              :         // Check for saturation error and modify temperature at constant enthalpy
    3385         1550 :         if (FullLoadOutAirTemp < PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    3386         1550 :             FullLoadOutAirTemp = PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName);
    3387         1550 :             FullLoadOutAirHumRat = PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
    3388              :         }
    3389              :         // Continuous fan, cycling compressor
    3390         1550 :         Real64 const EvapOutletAirEnthalpy = ((PartLoadRatio)*FullLoadOutAirEnth + (1.0 - (PartLoadRatio)) * EvapInletEnthalpy);
    3391         1550 :         Real64 EvapOutletAirHumRat = ((PartLoadRatio)*FullLoadOutAirHumRat + (1.0 - (PartLoadRatio)) * EvapInletHumRat);
    3392         1550 :         Real64 EvapOutletAirTemp = PsyTdbFnHW(EvapOutletAirEnthalpy, EvapOutletAirHumRat);
    3393         1550 :         if (EvapOutletAirTemp < PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName)) {
    3394          198 :             EvapOutletAirTemp = PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName);
    3395          198 :             EvapOutletAirHumRat = PsyWFnTdbH(state, EvapOutletAirTemp, EvapOutletAirEnthalpy, RoutineName);
    3396              :         }
    3397              : 
    3398         1550 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = EvapOutletAirTemp;
    3399         1550 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = EvapOutletAirHumRat;
    3400         1550 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = EvapOutletAirEnthalpy;
    3401         1550 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate = EvapAirMassFlow;
    3402         1550 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    3403         1550 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    3404         1550 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    3405         1550 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    3406              : 
    3407              :         // determine condenser leaving conditions
    3408         1550 :         Real64 const QdotCond = EvapTotCap * EvapRuntimeFraction + EvapElecCoolingPower;
    3409         1550 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3410         1550 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3411         1550 :         Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
    3412         1550 :         Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
    3413         1550 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
    3414         1550 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
    3415         1550 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
    3416              : 
    3417         1550 :         thisTESCoil.ElecCoolingPower = EvapElecCoolingPower + DischargeElectricCoolingPower + thisTESCoil.AncillaryControlsPower;
    3418         1550 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3419         1550 :         thisTESCoil.RuntimeFraction =
    3420         1550 :             (EvapTotCap * EvapRuntimeFraction + TotDischargeCap * DischargeRuntimeFraction) / (EvapTotCap + TotDischargeCap);
    3421              : 
    3422         1550 :         thisTESCoil.EvapTotCoolingRate = EvapTotCap * EvapRuntimeFraction + TotDischargeCap * DischargeRuntimeFraction;
    3423         1550 :         thisTESCoil.EvapTotCoolingEnergy = thisTESCoil.EvapTotCoolingRate * TimeStepSysSec;
    3424         1550 :         Real64 const MinAirHumRat = min(state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat,
    3425         1550 :                                         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat);
    3426         1550 :         thisTESCoil.EvapSensCoolingRate =
    3427         1550 :             EvapAirMassFlow * (PsyHFnTdbW(EvapInletDryBulb, MinAirHumRat) - PsyHFnTdbW(EvapOutletAirTemp, MinAirHumRat));
    3428         1550 :         if (thisTESCoil.EvapSensCoolingRate > thisTESCoil.EvapTotCoolingRate) {
    3429            0 :             thisTESCoil.EvapSensCoolingRate = thisTESCoil.EvapTotCoolingRate;
    3430              :         }
    3431         1550 :         thisTESCoil.EvapSensCoolingEnergy = thisTESCoil.EvapSensCoolingRate * TimeStepSysSec;
    3432         1550 :         thisTESCoil.EvapLatCoolingRate = thisTESCoil.EvapTotCoolingRate - thisTESCoil.EvapSensCoolingRate;
    3433         1550 :         thisTESCoil.EvapLatCoolingEnergy = thisTESCoil.EvapLatCoolingRate * TimeStepSysSec;
    3434              : 
    3435         1550 :     } else { // coil is off; just pass through conditions
    3436          788 :         thisTESCoil.QdotTES = 0.0;
    3437              : 
    3438          788 :         thisTESCoil.ElecCoolingPower = thisTESCoil.AncillaryControlsPower;
    3439          788 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3440          788 :         thisTESCoil.RuntimeFraction = 0.0;
    3441              : 
    3442          788 :         thisTESCoil.RuntimeFraction = 0.0;
    3443          788 :         thisTESCoil.EvapTotCoolingRate = 0.0;
    3444          788 :         thisTESCoil.EvapTotCoolingEnergy = 0.0;
    3445          788 :         thisTESCoil.EvapSensCoolingRate = 0.0;
    3446          788 :         thisTESCoil.EvapSensCoolingEnergy = 0.0;
    3447          788 :         thisTESCoil.EvapLatCoolingRate = 0.0;
    3448          788 :         thisTESCoil.EvapLatCoolingEnergy = 0.0;
    3449              : 
    3450          788 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    3451          788 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    3452          788 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
    3453          788 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    3454          788 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    3455          788 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    3456          788 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    3457          788 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    3458          788 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    3459          788 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
    3460              :         // nothing happens at condenser
    3461          788 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3462          788 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    3463          788 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
    3464          788 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
    3465          788 :             state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
    3466          788 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    3467          788 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
    3468          788 :         thisTESCoil.CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3469              :     }
    3470         2338 :     thisTESCoil.Q_TES = thisTESCoil.QdotTES * TimeStepSysSec;
    3471         2338 :     UpdateTEStorage(state, TESCoilNum);
    3472              : 
    3473         2338 :     UpdateColdWeatherProtection(state, TESCoilNum);
    3474              : 
    3475         2338 :     if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    3476            0 :         UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
    3477            0 :         UpdateEvaporativeCondenserWaterUse(state, TESCoilNum, CondInletHumRat, thisTESCoil.CondAirInletNodeNum);
    3478              :     }
    3479         2338 : }
    3480              : 
    3481         1349 : void CalcTESCoilChargeOnlyMode(EnergyPlusData &state, int const TESCoilNum)
    3482              : {
    3483              : 
    3484              :     // SUBROUTINE INFORMATION:
    3485              :     //       AUTHOR         Brent Griffith
    3486              :     //       DATE WRITTEN   May 2013
    3487              :     //       MODIFIED       na
    3488              :     //       RE-ENGINEERED  na
    3489              : 
    3490              :     // Using/Aliasing
    3491         1349 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    3492              : 
    3493              :     // SUBROUTINE PARAMETER DEFINITIONS:
    3494              :     static constexpr std::string_view RoutineName("CalcTESCoilChargeOnlyMode");
    3495              : 
    3496              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3497              :     Real64 CondInletTemp; // Condenser inlet temperature (C). Outdoor dry-bulb temp for air-cooled condenser.
    3498              :     // Outdoor Wetbulb +(1 - effectiveness)*(outdoor drybulb - outdoor wetbulb) for evap condenser.
    3499              :     Real64 CondInletHumRat; // Condenser inlet humidity ratio (kg/kg). Zero for air-cooled condenser.
    3500              :                             // For evap condenser, its the humidity ratio of the air leaving the evap cooling pads.
    3501              : 
    3502         1349 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    3503              : 
    3504              :     // nothing happens at Evaporator
    3505         1349 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    3506         1349 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    3507         1349 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
    3508         1349 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    3509         1349 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    3510         1349 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    3511         1349 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    3512         1349 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    3513         1349 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    3514         1349 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
    3515              : 
    3516              :     // first deal with condenser
    3517         1349 :     if (thisTESCoil.CondenserType == TESCondenserType::Air) {
    3518         1349 :         Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
    3519         1349 :         if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
    3520            0 :             CondInletTemp = state.dataEnvrn->OutDryBulbTemp;
    3521            0 :             CondInletHumRat = state.dataEnvrn->OutHumRat;
    3522              :         } else {
    3523         1349 :             CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3524         1349 :             CondInletHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    3525              :         }
    3526            0 :     } else if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    3527            0 :         Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
    3528            0 :         Real64 OutdoorDryBulb = 0.0;
    3529            0 :         Real64 OutdoorWetBulb = 0.0;
    3530            0 :         if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
    3531            0 :             OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
    3532            0 :             OutdoorWetBulb = state.dataEnvrn->OutWetBulbTemp;
    3533              :         } else {
    3534            0 :             OutdoorDryBulb = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3535            0 :             Real64 const OutdoorHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    3536            0 :             OutdoorWetBulb = PsyTwbFnTdbWPb(state, OutdoorDryBulb, OutdoorHumRat, CondAirSidePressure, RoutineName);
    3537              :         }
    3538              :         // direct evap cool model
    3539            0 :         CondInletTemp = OutdoorWetBulb + (OutdoorDryBulb - OutdoorWetBulb) * (1.0 - thisTESCoil.EvapCondEffect);
    3540            0 :         CondInletHumRat = PsyWFnTdbTwbPb(state, CondInletTemp, OutdoorWetBulb, CondAirSidePressure, RoutineName);
    3541              :     }
    3542              : 
    3543         1349 :     bool TESCanBeCharged = false; // true if room for tank to be charged.
    3544              :     Real64 QdotChargeLimit;       // limit for charge cooling power to hit limit of storage.
    3545              :     Real64 sTES;                  // local state of Thermal Energy Storage (C or ice fraction)
    3546              : 
    3547         1349 :     switch (thisTESCoil.StorageMedia) {
    3548            0 :     case MediaType::Water:
    3549              :     case MediaType::UserDefindFluid:
    3550            0 :         sTES = thisTESCoil.FluidTankTempFinalLastTimestep;
    3551            0 :         if ((sTES > thisTESCoil.MinimumFluidTankTempLimit) && (sTES < thisTESCoil.MaximumFluidTankTempLimit)) {
    3552            0 :             TESCanBeCharged = true;
    3553              :             // find charge limit to reach limits
    3554              :             // density of water in tank (kg/m3)
    3555            0 :             Real64 const rho = thisTESCoil.glycol->getDensity(state, sTES, RoutineName);
    3556              :             // Mass of water in tank (kg)
    3557            0 :             Real64 const TankMass = rho * thisTESCoil.FluidStorageVolume;
    3558              :             // Specific heat of water in tank (J/kg K)
    3559            0 :             Real64 const CpTank = thisTESCoil.glycol->getSpecificHeat(state, sTES, RoutineName);
    3560              :             // simple linear approximation of DT/Dt term in McpDT/Dt
    3561            0 :             QdotChargeLimit = TankMass * CpTank * (sTES - thisTESCoil.MinimumFluidTankTempLimit) / TimeStepSysSec;
    3562            0 :         } else {
    3563            0 :             TESCanBeCharged = false;
    3564              :         }
    3565            0 :         break;
    3566         1349 :     case MediaType::Ice:
    3567         1349 :         sTES = thisTESCoil.IceFracRemainLastTimestep;
    3568         1349 :         if (sTES < 1.0) {
    3569         1349 :             TESCanBeCharged = true;
    3570              :             // find charge limit to reach limit
    3571         1349 :             QdotChargeLimit = (1.0 - sTES) * thisTESCoil.IceStorageCapacity / TimeStepSysSec;
    3572              :         } else {
    3573            0 :             TESCanBeCharged = false;
    3574              :         }
    3575         1349 :         break;
    3576            0 :     default:
    3577            0 :         break;
    3578              :     }
    3579              : 
    3580         1349 :     if (TESCanBeCharged) { // coil is running
    3581         1349 :         Real64 CapModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.ChargeOnlyChargingCapFTempCurve, CondInletTemp, sTES);
    3582         1349 :         CapModFac = max(0.0, CapModFac);
    3583         1349 :         Real64 TotCap = thisTESCoil.ChargeOnlyRatedCapacity * CapModFac;
    3584         1349 :         if (TotCap > QdotChargeLimit) {
    3585            1 :             thisTESCoil.RuntimeFraction = QdotChargeLimit / TotCap;
    3586            1 :             TotCap = min(TotCap, QdotChargeLimit);
    3587              :         } else {
    3588         1348 :             thisTESCoil.RuntimeFraction = 1.0;
    3589              :         }
    3590         1349 :         Real64 EIRModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.ChargeOnlyChargingEIRFTempCurve, CondInletTemp, sTES);
    3591         1349 :         EIRModFac = max(0.0, EIRModFac);
    3592              : 
    3593         1349 :         Real64 const EIR = EIRModFac / thisTESCoil.ChargeOnlyRatedCOP;
    3594         1349 :         Real64 const ElecCoolingPower = TotCap * EIR;
    3595              :         // condenser total heat rejection rate [W]
    3596         1349 :         Real64 const &QdotCond = TotCap + ElecCoolingPower;
    3597         1349 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3598         1349 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3599              :         // condenser inlet enthalpy [J/kg]
    3600         1349 :         Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
    3601         1349 :         Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
    3602         1349 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
    3603         1349 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
    3604         1349 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
    3605              : 
    3606         1349 :         thisTESCoil.ElecCoolingPower = ElecCoolingPower + thisTESCoil.AncillaryControlsPower;
    3607         1349 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3608              : 
    3609         1349 :         thisTESCoil.QdotTES = -TotCap; // negative for cooling
    3610              : 
    3611              :     } else { // not running
    3612            0 :         thisTESCoil.ElecCoolingPower = thisTESCoil.AncillaryControlsPower;
    3613            0 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3614            0 :         thisTESCoil.RuntimeFraction = 0.0;
    3615            0 :         thisTESCoil.QdotTES = 0.0;
    3616            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3617            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    3618            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
    3619            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
    3620            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
    3621            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    3622            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
    3623              :     }
    3624         1349 :     thisTESCoil.Q_TES = thisTESCoil.QdotTES * TimeStepSysSec;
    3625              : 
    3626         1349 :     thisTESCoil.EvapTotCoolingRate = 0.0;
    3627         1349 :     thisTESCoil.EvapTotCoolingEnergy = 0.0;
    3628         1349 :     thisTESCoil.EvapSensCoolingRate = 0.0;
    3629         1349 :     thisTESCoil.EvapSensCoolingEnergy = 0.0;
    3630         1349 :     thisTESCoil.EvapLatCoolingRate = 0.0;
    3631         1349 :     thisTESCoil.EvapLatCoolingEnergy = 0.0;
    3632              : 
    3633         1349 :     UpdateTEStorage(state, TESCoilNum);
    3634              : 
    3635         1349 :     UpdateColdWeatherProtection(state, TESCoilNum);
    3636              : 
    3637         1349 :     if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    3638            0 :         UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
    3639            0 :         UpdateEvaporativeCondenserWaterUse(state, TESCoilNum, CondInletHumRat, thisTESCoil.CondAirInletNodeNum);
    3640              :     }
    3641         1349 : }
    3642              : 
    3643        14955 : void CalcTESCoilDischargeOnlyMode(EnergyPlusData &state, int const TESCoilNum, Real64 const PartLoadRatio)
    3644              : {
    3645              : 
    3646              :     // SUBROUTINE INFORMATION:
    3647              :     //       AUTHOR         Brent Griffith
    3648              :     //       DATE WRITTEN   April 2013
    3649              :     //       MODIFIED       na
    3650              :     //       RE-ENGINEERED  na
    3651              : 
    3652              :     // Using/Aliasing
    3653        14955 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    3654              : 
    3655              :     // SUBROUTINE PARAMETER DEFINITIONS:
    3656        14955 :     int constexpr MaxIter(30);
    3657        14955 :     Real64 constexpr RelaxationFactor(0.4);
    3658        14955 :     Real64 constexpr Tolerance(0.1);
    3659              :     static constexpr std::string_view RoutineName("CalcTESCoilDischargeOnlyMode");
    3660              :     static constexpr std::string_view StorageTankName("CalcTESWaterStorageTank");
    3661              : 
    3662        14955 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    3663              : 
    3664              :     Real64 QdotDischargeLimit;     // limit for how much storage can be discharged without overshooting
    3665        14955 :     Real64 sTES = 0.0;             // state of charge of Thermal Energy Storage
    3666        14955 :     bool TESHasSomeCharge = false; // true when there is something avaiable in storage
    3667              : 
    3668        14955 :     switch (thisTESCoil.StorageMedia) {
    3669            0 :     case MediaType::Water:
    3670              :     case MediaType::UserDefindFluid:
    3671            0 :         sTES = thisTESCoil.FluidTankTempFinalLastTimestep;
    3672            0 :         if ((sTES >= thisTESCoil.MinimumFluidTankTempLimit) && (sTES < thisTESCoil.MaximumFluidTankTempLimit)) {
    3673            0 :             TESHasSomeCharge = true;
    3674              :             // density of water in tank (kg/m3)
    3675            0 :             Real64 const rho = thisTESCoil.glycol->getDensity(state, sTES, StorageTankName);
    3676              :             // Mass of water in tank (kg)
    3677            0 :             Real64 const TankMass = rho * thisTESCoil.FluidStorageVolume;
    3678              :             // Specific heat of water in tank (J/kg K)
    3679            0 :             Real64 const CpTank = thisTESCoil.glycol->getSpecificHeat(state, sTES, StorageTankName);
    3680              :             // simple linear approximation of DT/Dt term in McpDT/Dt
    3681            0 :             QdotDischargeLimit = TankMass * CpTank * (thisTESCoil.MaximumFluidTankTempLimit - sTES) / TimeStepSysSec;
    3682            0 :         } else {
    3683            0 :             TESHasSomeCharge = false;
    3684              :         }
    3685            0 :         break;
    3686        14955 :     case MediaType::Ice:
    3687        14955 :         sTES = thisTESCoil.IceFracRemainLastTimestep;
    3688        14955 :         if (sTES > 0.0) {
    3689        14955 :             TESHasSomeCharge = true;
    3690              :             // discharge limit
    3691        14955 :             QdotDischargeLimit = (sTES)*thisTESCoil.IceStorageCapacity / TimeStepSysSec;
    3692              :         } else {
    3693            0 :             TESHasSomeCharge = false;
    3694              :         }
    3695        14955 :         break;
    3696            0 :     default:
    3697            0 :         break;
    3698              :     }
    3699              : 
    3700              :     // local for evaporator air mass flow [kg/s]
    3701        14955 :     Real64 const EvapAirMassFlow = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    3702              : 
    3703        14955 :     if ((EvapAirMassFlow > HVAC::SmallMassFlow) && (PartLoadRatio > 0.0) && TESHasSomeCharge) { // coil is running
    3704              : 
    3705        10058 :         Real64 PLR = PartLoadRatio;
    3706              : 
    3707        10058 :         Real64 const EvapInletDryBulb = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    3708        10058 :         Real64 const EvapInletHumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    3709        10058 :         Real64 const EvapInletWetBulb = PsyTwbFnTdbWPb(state, EvapInletDryBulb, EvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
    3710        10058 :         Real64 const EvapInletEnthalpy = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Enthalpy;
    3711              : 
    3712              :         // evaporator inlet air mass flow divided by design mass flow [ ]
    3713        10058 :         Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
    3714              : 
    3715              :         // total cooling capacity modification factor due to temps []
    3716        10058 :         Real64 TotCapTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyCapFTempCurve, EvapInletWetBulb, sTES);
    3717        10058 :         TotCapTempModFac = max(0.0, TotCapTempModFac);
    3718              :         // Total cooling capacity modification factor due to flow []
    3719        10058 :         Real64 TotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyCapFFlowCurve, AirMassFlowRatio);
    3720        10058 :         TotCapFlowModFac = max(0.0, TotCapFlowModFac);
    3721              :         // total cooling capacity
    3722        10058 :         Real64 TotCap = thisTESCoil.DischargeOnlyRatedDischargeCap * TotCapTempModFac * TotCapFlowModFac;
    3723              : 
    3724              :         // part load factor
    3725        10058 :         Real64 const PLF = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyPLFFPLRCurve, PLR);
    3726              :         // compressor running time divided by full time of timestep.
    3727        10058 :         Real64 RuntimeFraction = 1.0;
    3728        10058 :         if (PLF >= PLR && PLF > 0.0) {
    3729        10058 :             RuntimeFraction = PLR / PLF;
    3730              :         } else {
    3731              :             // warn maybe
    3732              :         }
    3733              :         // Calculate electricity consumed. First, get EIR modifying factors for off-rated conditions
    3734        10058 :         Real64 EIRTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyEIRFTempCurve, EvapInletWetBulb, sTES);
    3735        10058 :         EIRTempModFac = max(EIRTempModFac, 0.0);
    3736              : 
    3737        10058 :         Real64 EIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyEIRFFlowCurve, AirMassFlowRatio);
    3738        10058 :         EIRFlowModFac = max(EIRFlowModFac, 0.0);
    3739        10058 :         Real64 const EIR = EIRTempModFac * EIRFlowModFac / thisTESCoil.DischargeOnlyRatedCOP;
    3740              : 
    3741              :         // compressor electric power
    3742        10058 :         Real64 ElecCoolingPower = TotCap * EIR * RuntimeFraction;
    3743        10058 :         Real64 const QdotTEStest = TotCap * RuntimeFraction + ElecCoolingPower;
    3744              : 
    3745        10058 :         if (QdotTEStest > QdotDischargeLimit) {
    3746           52 :             Real64 const RuntimeFractionLimit = QdotDischargeLimit / (TotCap + TotCap * EIR);
    3747           52 :             RuntimeFraction = min(RuntimeFraction, RuntimeFractionLimit);
    3748           52 :             PLR = RuntimeFraction * PLF;
    3749           52 :             ElecCoolingPower = TotCap * EIR * RuntimeFraction;
    3750              :         }
    3751              :         // now see if coil is running dry
    3752        10058 :         Real64 PartLoadOutAirEnth = EvapInletEnthalpy - (TotCap * PLR) / EvapAirMassFlow;
    3753        10058 :         Real64 const PartLoadDryCoilOutAirTemp = PsyTdbFnHW(PartLoadOutAirEnth, EvapInletHumRat);
    3754              : 
    3755        10058 :         bool CoilMightBeDry = false;
    3756              :         Real64 DryCoilTestEvapInletHumRat;
    3757              :         Real64 SHRadp;
    3758        10058 :         if (PartLoadDryCoilOutAirTemp > PsyTsatFnHPb(state, PartLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    3759           38 :             CoilMightBeDry = true;
    3760              :             // find wADP, humidity ratio at apparatus dewpoint and inlet hum rat that would have dry coil
    3761           38 :             DryCoilTestEvapInletHumRat = EvapInletHumRat;
    3762           38 :             Real64 DryCoilTestEvapInletWetBulb = EvapInletWetBulb;
    3763           38 :             int Counter = 0;
    3764           38 :             bool Converged = false;
    3765           76 :             while (!Converged) {
    3766           38 :                 TotCapTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyCapFTempCurve, DryCoilTestEvapInletWetBulb, sTES);
    3767           38 :                 TotCapTempModFac = max(0.0, TotCapTempModFac);
    3768           38 :                 TotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyCapFFlowCurve, AirMassFlowRatio);
    3769           38 :                 TotCapFlowModFac = max(0.0, TotCapFlowModFac);
    3770           38 :                 TotCap = thisTESCoil.DischargeOnlyRatedDischargeCap * TotCapTempModFac * TotCapFlowModFac;
    3771              :                 // coil bypass factor = 0.0
    3772           38 :                 Real64 const hADP = EvapInletEnthalpy - (TotCap / EvapAirMassFlow);
    3773           38 :                 Real64 const tADP = PsyTsatFnHPb(state, hADP, state.dataEnvrn->OutBaroPress, RoutineName);
    3774           38 :                 Real64 const wADP = min(EvapInletHumRat, PsyWFnTdbH(state, tADP, hADP, RoutineName));
    3775           38 :                 Real64 const hTinwADP = PsyHFnTdbW(EvapInletDryBulb, wADP);
    3776           38 :                 if ((EvapInletEnthalpy - hADP) > 1.e-10) {
    3777           38 :                     SHRadp = min((hTinwADP - hADP) / (EvapInletEnthalpy - hADP), 1.0);
    3778              :                 } else {
    3779            0 :                     SHRadp = 1.0;
    3780              :                 }
    3781              : 
    3782           38 :                 if ((wADP > DryCoilTestEvapInletHumRat) || (Counter >= 1 && Counter < MaxIter)) {
    3783            0 :                     if (DryCoilTestEvapInletHumRat <= 0.0) {
    3784            0 :                         DryCoilTestEvapInletHumRat = 0.00001;
    3785              :                     }
    3786            0 :                     Real64 const werror = (DryCoilTestEvapInletHumRat - wADP) / DryCoilTestEvapInletHumRat;
    3787              : 
    3788            0 :                     DryCoilTestEvapInletHumRat = RelaxationFactor * wADP + (1.0 - RelaxationFactor) * DryCoilTestEvapInletHumRat;
    3789              :                     DryCoilTestEvapInletWetBulb =
    3790            0 :                         PsyTwbFnTdbWPb(state, EvapInletDryBulb, DryCoilTestEvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
    3791              : 
    3792            0 :                     ++Counter;
    3793            0 :                     Converged = std::abs(werror) <= Tolerance;
    3794            0 :                 } else {
    3795           38 :                     Converged = true;
    3796              :                 }
    3797              :             }
    3798              :         } // coil will be wet so use SHR curves
    3799              : 
    3800              :         // total cooling capacity modification factors
    3801              :         Real64 SHRTempFac;
    3802        10058 :         if (state.dataCurveManager->curves(thisTESCoil.DischargeOnlySHRFTempCurve)->numDims == 2) {
    3803        10058 :             SHRTempFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlySHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb);
    3804              :         } else {
    3805            0 :             SHRTempFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlySHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb, sTES);
    3806              :         }
    3807              : 
    3808        10058 :         Real64 const SHRFlowFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlySHRFFLowCurve, AirMassFlowRatio);
    3809        10058 :         Real64 SHR = thisTESCoil.DischargeOnlyRatedSHR * SHRTempFac * SHRFlowFac;
    3810        10058 :         SHR = min(SHR, 1.0); // warn maybe
    3811        10058 :         SHR = max(SHR, 0.0); // warn maybe
    3812        10058 :         if (CoilMightBeDry) {
    3813           38 :             if ((EvapInletHumRat < DryCoilTestEvapInletHumRat) && (SHRadp > SHR)) { // coil is dry for sure
    3814            0 :                 SHR = 1.0;
    3815           38 :             } else if (SHRadp > SHR) {
    3816           38 :                 SHR = SHRadp;
    3817              :             }
    3818              :         }
    3819              :         //  Calculate full load output conditions
    3820              :         // evaporator outlet full load enthalpy [J/kg]
    3821        10058 :         Real64 const FullLoadOutAirEnth = EvapInletEnthalpy - TotCap / EvapAirMassFlow;
    3822              : 
    3823              :         // Enthalpy at inlet dry-bulb and outlet humidity ratio [J/kg]
    3824        10058 :         Real64 const hTinwout = EvapInletEnthalpy - (1.0 - SHR) * (TotCap / EvapAirMassFlow);
    3825              :         // The following will often throw psych warnings for neg w, suppress warnings because error condition is handled in next IF
    3826        10058 :         Real64 FullLoadOutAirHumRat = PsyWFnTdbH(state, EvapInletDryBulb, hTinwout, RoutineName, true);
    3827        10058 :         Real64 FullLoadOutAirTemp = PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
    3828              :         // Check for saturation error and modify temperature at constant enthalpy
    3829        10058 :         if (FullLoadOutAirTemp < PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    3830           20 :             FullLoadOutAirTemp = PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName);
    3831           20 :             FullLoadOutAirHumRat = PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
    3832              :         }
    3833              : 
    3834              :         // Continuous fan, cycling compressor
    3835        10058 :         Real64 const EvapOutletAirEnthalpy = ((PLR)*FullLoadOutAirEnth + (1.0 - (PLR)) * EvapInletEnthalpy);
    3836        10058 :         Real64 EvapOutletAirHumRat = ((PLR)*FullLoadOutAirHumRat + (1.0 - (PLR)) * EvapInletHumRat);
    3837        10058 :         Real64 EvapOutletAirTemp = PsyTdbFnHW(EvapOutletAirEnthalpy, EvapOutletAirHumRat);
    3838        10058 :         if (EvapOutletAirTemp < PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName)) {
    3839            0 :             EvapOutletAirTemp = PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName);
    3840            0 :             EvapOutletAirHumRat = PsyWFnTdbH(state, EvapOutletAirTemp, EvapOutletAirEnthalpy, RoutineName);
    3841              :         }
    3842              : 
    3843        10058 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = EvapOutletAirTemp;
    3844        10058 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = EvapOutletAirHumRat;
    3845        10058 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = EvapOutletAirEnthalpy;
    3846        10058 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate = EvapAirMassFlow;
    3847        10058 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    3848        10058 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    3849        10058 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    3850        10058 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    3851        10058 :         thisTESCoil.ElecCoolingPower = ElecCoolingPower + thisTESCoil.AncillaryControlsPower;
    3852        10058 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3853        10058 :         thisTESCoil.RuntimeFraction = RuntimeFraction;
    3854        10058 :         thisTESCoil.EvapTotCoolingRate = TotCap * RuntimeFraction; // double check this
    3855        10058 :         thisTESCoil.EvapTotCoolingEnergy = TotCap * RuntimeFraction * TimeStepSysSec;
    3856        10058 :         Real64 const MinAirHumRat = min(state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat,
    3857        10058 :                                         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat);
    3858        10058 :         thisTESCoil.EvapSensCoolingRate =
    3859        10058 :             EvapAirMassFlow * (PsyHFnTdbW(EvapInletDryBulb, MinAirHumRat) - PsyHFnTdbW(EvapOutletAirTemp, MinAirHumRat));
    3860        10058 :         if (thisTESCoil.EvapSensCoolingRate > thisTESCoil.EvapTotCoolingRate) {
    3861            0 :             thisTESCoil.EvapSensCoolingRate = thisTESCoil.EvapTotCoolingRate;
    3862              :         }
    3863        10058 :         thisTESCoil.EvapSensCoolingEnergy = thisTESCoil.EvapSensCoolingRate * TimeStepSysSec;
    3864        10058 :         thisTESCoil.EvapLatCoolingRate = thisTESCoil.EvapTotCoolingRate - thisTESCoil.EvapSensCoolingRate;
    3865        10058 :         thisTESCoil.EvapLatCoolingEnergy = thisTESCoil.EvapLatCoolingRate * TimeStepSysSec;
    3866              : 
    3867        10058 :         thisTESCoil.QdotTES = TotCap * RuntimeFraction + ElecCoolingPower; // all heat rejection into storage
    3868              : 
    3869        10058 :     } else { // coil is off; just pass through conditions
    3870         4897 :         thisTESCoil.QdotTES = 0.0;
    3871              : 
    3872         4897 :         thisTESCoil.ElecCoolingPower = thisTESCoil.AncillaryControlsPower;
    3873         4897 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3874         4897 :         thisTESCoil.RuntimeFraction = 0.0;
    3875              : 
    3876         4897 :         thisTESCoil.RuntimeFraction = 0.0;
    3877         4897 :         thisTESCoil.EvapTotCoolingRate = 0.0;
    3878         4897 :         thisTESCoil.EvapTotCoolingEnergy = 0.0;
    3879         4897 :         thisTESCoil.EvapSensCoolingRate = 0.0;
    3880         4897 :         thisTESCoil.EvapSensCoolingEnergy = 0.0;
    3881         4897 :         thisTESCoil.EvapLatCoolingRate = 0.0;
    3882         4897 :         thisTESCoil.EvapLatCoolingEnergy = 0.0;
    3883              : 
    3884         4897 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    3885         4897 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    3886         4897 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
    3887         4897 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    3888         4897 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    3889         4897 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    3890         4897 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    3891         4897 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    3892         4897 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    3893         4897 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
    3894              :     }
    3895              : 
    3896              :     // nothing happens at condenser
    3897        14955 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3898        14955 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    3899        14955 :     state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
    3900        14955 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
    3901        14955 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
    3902        14955 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    3903        14955 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
    3904        14955 :     thisTESCoil.CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3905        14955 :     thisTESCoil.Q_TES = thisTESCoil.QdotTES * TimeStepSysSec;
    3906        14955 :     UpdateTEStorage(state, TESCoilNum);
    3907              : 
    3908        14955 :     UpdateColdWeatherProtection(state, TESCoilNum);
    3909              : 
    3910        14955 :     if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    3911         5977 :         UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
    3912        11954 :         UpdateEvaporativeCondenserWaterUse(
    3913         5977 :             state, TESCoilNum, state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat, thisTESCoil.CondAirInletNodeNum);
    3914              :     }
    3915        14955 : }
    3916              : 
    3917        63397 : void UpdateTEStorage(EnergyPlusData &state, int const TESCoilNum)
    3918              : {
    3919              : 
    3920              :     // SUBROUTINE INFORMATION:
    3921              :     //       AUTHOR         <author>
    3922              :     //       DATE WRITTEN   <date_written>
    3923              :     //       MODIFIED       na
    3924              :     //       RE-ENGINEERED  na
    3925              : 
    3926        63397 :     switch (state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).StorageMedia) {
    3927        16775 :     case MediaType::Water:
    3928              :     case MediaType::UserDefindFluid:
    3929        16775 :         CalcTESWaterStorageTank(state, TESCoilNum);
    3930        16775 :         break;
    3931        46622 :     case MediaType::Ice:
    3932        46622 :         CalcTESIceStorageTank(state, TESCoilNum);
    3933        46622 :         break;
    3934            0 :     default:
    3935            0 :         break;
    3936              :     }
    3937        63397 : }
    3938              : 
    3939        16775 : void CalcTESWaterStorageTank(EnergyPlusData &state, int const TESCoilNum)
    3940              : {
    3941              : 
    3942              :     // SUBROUTINE INFORMATION:
    3943              :     //       AUTHOR         <author>
    3944              :     //       DATE WRITTEN   <date_written>
    3945              :     //       MODIFIED       na
    3946              :     //       RE-ENGINEERED  na
    3947              : 
    3948              :     // SUBROUTINE PARAMETER DEFINITIONS:
    3949              :     static constexpr std::string_view RoutineName("CalcTESWaterStorageTank");
    3950              :     static constexpr std::string_view calcTESIceStorageTank("CalcTESIceStorageTank");
    3951              : 
    3952              :     // Using/Aliasing
    3953        16775 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    3954              :     using WaterThermalTanks::WaterThermalTankData;
    3955              : 
    3956        16775 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    3957              : 
    3958              :     // Seconds in one timestep (s)
    3959        16775 :     Real64 const SecInTimeStep = TimeStepSysSec;
    3960              :     // Time remaining in the current timestep (s)
    3961        16775 :     Real64 const TimeRemaining = SecInTimeStep;
    3962              : 
    3963              :     // Fraction of the current hour that has elapsed (h)
    3964              :     Real64 const TimeElapsed =
    3965        16775 :         state.dataGlobal->HourOfDay + state.dataGlobal->TimeStep * state.dataGlobal->TimeStepZone + state.dataHVACGlobal->SysTimeElapsed;
    3966              : 
    3967        16775 :     if (thisTESCoil.TimeElapsed != TimeElapsed) {
    3968         2831 :         thisTESCoil.FluidTankTempFinalLastTimestep = thisTESCoil.FluidTankTempFinal;
    3969         2831 :         thisTESCoil.TimeElapsed = TimeElapsed;
    3970              :     }
    3971              : 
    3972              :     // Instantaneous tank temperature (C)
    3973        16775 :     Real64 const TankTemp = thisTESCoil.FluidTankTempFinalLastTimestep;
    3974              :     // Current ambient air temperature around tank (C)
    3975        16775 :     Real64 const AmbientTemp = state.dataLoopNodes->Node(thisTESCoil.StorageAmbientNodeNum).Temp;
    3976              :     // Use side inlet temperature (C)
    3977        16775 :     Real64 const UseInletTemp = state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).Temp;
    3978              :     // Source side inlet temperature (C)
    3979        16775 :     Real64 const SourceInletTemp = thisTESCoil.FluidTankTempFinalLastTimestep;
    3980              :     // density of water in tank (kg/m3)
    3981        16775 :     Real64 const rho = thisTESCoil.glycol->getDensity(state, TankTemp, RoutineName);
    3982              :     // Mass of water in tank (kg)
    3983        16775 :     Real64 const TankMass = rho * thisTESCoil.FluidStorageVolume;
    3984              :     // Specific heat of water in tank (J/kg K)
    3985        16775 :     Real64 const CpTank = thisTESCoil.glycol->getSpecificHeat(state, TankTemp, RoutineName);
    3986              : 
    3987              :     // Use side flow rate, including effectiveness factor (kg/s)
    3988        16775 :     Real64 const UseMassFlowRate = thisTESCoil.TESPlantConnectionAvailable
    3989        16775 :                                        ? state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).MassFlowRate * thisTESCoil.TESPlantEffectiveness
    3990        16775 :                                        : 0.0;
    3991              : 
    3992              :     // Source side flow rate, including effectiveness factor (kg/s)
    3993        16775 :     Real64 constexpr SourceMassFlowRate = 0.0;
    3994              :     // Loss coefficient to ambient environment (W/K)
    3995        16775 :     Real64 const LossCoeff = thisTESCoil.StorageUA;
    3996              :     // heat exchange directly into tank from charging system [W]
    3997        16775 :     Real64 const QdotTES = thisTESCoil.QdotTES;
    3998              : 
    3999              :     // Predicted new tank temperature (C)
    4000        16775 :     Real64 const NewTankTemp = WaterThermalTanks::WaterThermalTankData::CalcTankTemp(TankTemp,
    4001              :                                                                                      AmbientTemp,
    4002              :                                                                                      UseInletTemp,
    4003              :                                                                                      SourceInletTemp,
    4004              :                                                                                      TankMass,
    4005              :                                                                                      CpTank,
    4006              :                                                                                      UseMassFlowRate,
    4007              :                                                                                      SourceMassFlowRate,
    4008              :                                                                                      LossCoeff,
    4009              :                                                                                      QdotTES,
    4010              :                                                                                      TimeRemaining);
    4011              : 
    4012        16775 :     thisTESCoil.FluidTankTempFinal = NewTankTemp;
    4013              : 
    4014        16775 :     if (thisTESCoil.TESPlantConnectionAvailable) {
    4015              :         // Specific heat of fluid in plant connection (J/kg K)
    4016              :         Real64 const CpPlantConnection =
    4017        16775 :             state.dataPlnt->PlantLoop(thisTESCoil.TESPlantLoopNum)
    4018        16775 :                 .glycol->getSpecificHeat(state, state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).Temp, calcTESIceStorageTank);
    4019              : 
    4020        16775 :         thisTESCoil.QdotPlant = state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).MassFlowRate * CpPlantConnection *
    4021        16775 :                                 thisTESCoil.TESPlantEffectiveness * (UseInletTemp - NewTankTemp);
    4022        16775 :         thisTESCoil.Q_Plant = thisTESCoil.QdotPlant * TimeStepSysSec;
    4023              :         // now get correct outlet temp with actual massflow (not modified by effectiveness)
    4024        16775 :         Real64 NewOutletTemp = UseInletTemp; // calculated new tankoutlet temp (C)
    4025        16775 :         if (state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).MassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
    4026        16730 :             NewOutletTemp =
    4027        16730 :                 UseInletTemp - thisTESCoil.QdotPlant / (state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).MassFlowRate * CpPlantConnection);
    4028              :         }
    4029        16775 :         state.dataLoopNodes->Node(thisTESCoil.TESPlantOutletNodeNum).Temp = NewOutletTemp;
    4030              :     }
    4031              : 
    4032              :     // Change in integrated tank temperature, dividing by time gives the average (C s)
    4033        16775 :     Real64 const deltaTsum = WaterThermalTankData::CalcTempIntegral(TankTemp,
    4034              :                                                                     NewTankTemp,
    4035              :                                                                     AmbientTemp,
    4036              :                                                                     UseInletTemp,
    4037              :                                                                     SourceInletTemp,
    4038              :                                                                     TankMass,
    4039              :                                                                     CpTank,
    4040              :                                                                     UseMassFlowRate,
    4041              :                                                                     SourceMassFlowRate,
    4042              :                                                                     LossCoeff,
    4043              :                                                                     QdotTES,
    4044              :                                                                     TimeRemaining);
    4045        16775 :     thisTESCoil.QdotAmbient = (LossCoeff * (AmbientTemp * TimeRemaining - deltaTsum)) / SecInTimeStep;
    4046        16775 :     thisTESCoil.Q_Ambient = thisTESCoil.QdotAmbient * TimeStepSysSec;
    4047        16775 : }
    4048              : 
    4049        46622 : void CalcTESIceStorageTank(EnergyPlusData &state, int const TESCoilNum)
    4050              : {
    4051              : 
    4052              :     // SUBROUTINE INFORMATION:
    4053              :     //       AUTHOR         <author>
    4054              :     //       DATE WRITTEN   <date_written>
    4055              :     //       MODIFIED       na
    4056              :     //       RE-ENGINEERED  na
    4057              : 
    4058              :     // Using/Aliasing
    4059        46622 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    4060              : 
    4061              :     // SUBROUTINE PARAMETER DEFINITIONS:
    4062        46622 :     constexpr Real64 FreezingTemp(0.0); // zero degrees C
    4063              :     static constexpr std::string_view RoutineName("CalcTESIceStorageTank");
    4064              : 
    4065        46622 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    4066              : 
    4067              :     // Fraction of the current hour that has elapsed (h)
    4068              :     Real64 const TimeElapsed =
    4069        46622 :         state.dataGlobal->HourOfDay + state.dataGlobal->TimeStep * state.dataGlobal->TimeStepZone + state.dataHVACGlobal->SysTimeElapsed;
    4070              : 
    4071        46622 :     if (thisTESCoil.TimeElapsed != TimeElapsed) {
    4072         8493 :         thisTESCoil.IceFracRemainLastTimestep = thisTESCoil.IceFracRemain;
    4073         8493 :         thisTESCoil.TimeElapsed = TimeElapsed;
    4074              :     }
    4075              : 
    4076              :     // update plant connection (if any)
    4077        46622 :     if (thisTESCoil.TESPlantConnectionAvailable) {
    4078              : 
    4079            0 :         auto const &inletNode = state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum);
    4080            0 :         Real64 const Cp = state.dataPlnt->PlantLoop(thisTESCoil.TESPlantLoopNum).glycol->getSpecificHeat(state, inletNode.Temp, RoutineName);
    4081              : 
    4082            0 :         thisTESCoil.QdotPlant = inletNode.MassFlowRate * Cp * thisTESCoil.TESPlantEffectiveness * (inletNode.Temp - FreezingTemp);
    4083            0 :         thisTESCoil.Q_Plant = thisTESCoil.QdotPlant * TimeStepSysSec;
    4084              :         // now get correct outlet temp with actual massflow (not modified by effectiveness)
    4085            0 :         Real64 NewOutletTemp = inletNode.Temp; // calculated new tank outlet temp (C)
    4086            0 :         if (inletNode.MassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
    4087            0 :             NewOutletTemp += thisTESCoil.QdotPlant / (inletNode.MassFlowRate * Cp);
    4088              :         }
    4089            0 :         state.dataLoopNodes->Node(thisTESCoil.TESPlantOutletNodeNum).Temp = NewOutletTemp;
    4090              :     } else {
    4091        46622 :         thisTESCoil.QdotPlant = 0.0;
    4092        46622 :         thisTESCoil.Q_Plant = 0.0;
    4093              :     }
    4094              : 
    4095              :     // update ambient heat transfer
    4096              : 
    4097        46622 :     thisTESCoil.QdotAmbient = thisTESCoil.StorageUA * (state.dataLoopNodes->Node(thisTESCoil.StorageAmbientNodeNum).Temp - FreezingTemp);
    4098        46622 :     thisTESCoil.Q_Ambient = thisTESCoil.QdotAmbient * TimeStepSysSec;
    4099              : 
    4100              :     // local rate of heat transfer to ice (negative cooling) [W]
    4101        46622 :     Real64 const QdotIce = thisTESCoil.QdotPlant + thisTESCoil.QdotAmbient + thisTESCoil.QdotTES;
    4102              : 
    4103        46622 :     if (QdotIce < 0.0) { // charging ice level
    4104        17247 :         thisTESCoil.IceFracRemain = thisTESCoil.IceFracRemainLastTimestep + std::abs(QdotIce) / (thisTESCoil.IceStorageCapacity / TimeStepSysSec);
    4105        17247 :         if (thisTESCoil.IceFracRemain > 1.0) {
    4106         2765 :             thisTESCoil.IceFracRemain = 1.0;
    4107              :         }
    4108              :     } else { // not charging,but discharging
    4109        29375 :         thisTESCoil.IceFracRemain = thisTESCoil.IceFracRemainLastTimestep - QdotIce / (thisTESCoil.IceStorageCapacity / TimeStepSysSec);
    4110        29375 :         if (thisTESCoil.IceFracRemain < 0.0) {
    4111         3537 :             thisTESCoil.IceFracRemain = 0.0;
    4112              :         }
    4113              :     }
    4114        46622 : }
    4115              : 
    4116        63397 : void UpdateColdWeatherProtection(EnergyPlusData &state, int const TESCoilNum)
    4117              : {
    4118              : 
    4119              :     // SUBROUTINE INFORMATION:
    4120              :     //       AUTHOR         B. Griffith
    4121              :     //       DATE WRITTEN   April 2013
    4122              :     //       MODIFIED       na
    4123              :     //       RE-ENGINEERED  na
    4124              : 
    4125              :     // Using/Aliasing
    4126        63397 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    4127              : 
    4128        63397 :     if ((state.dataLoopNodes->Node(state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).StorageAmbientNodeNum).Temp <
    4129        75912 :          state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ColdWeatherMinimumTempLimit) &&
    4130        12515 :         (state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).availSched->getCurrentVal() != 0.0)) {
    4131        12515 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectColdWeatherPower =
    4132        12515 :             state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ColdWeatherAncillaryPower;
    4133              : 
    4134              :     } else {
    4135        50882 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectColdWeatherPower = 0.0;
    4136              :     }
    4137        63397 :     state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectColdWeatherEnergy =
    4138        63397 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectColdWeatherPower * TimeStepSysSec;
    4139        63397 : }
    4140              : 
    4141        15925 : void UpdateEvaporativeCondenserBasinHeater(EnergyPlusData &state, int const TESCoilNum)
    4142              : {
    4143              : 
    4144              :     // SUBROUTINE INFORMATION:
    4145              :     //       AUTHOR         B. Griffith
    4146              :     //       DATE WRITTEN   April 2013
    4147              :     //       MODIFIED       na
    4148              :     //       RE-ENGINEERED  na
    4149              : 
    4150              :     // PURPOSE OF THIS SUBROUTINE:
    4151              :     // determine basin heater electrical power and energy
    4152              : 
    4153              :     // Using/Aliasing
    4154        15925 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    4155              : 
    4156        47775 :     CalcBasinHeaterPower(state,
    4157        15925 :                          state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).BasinHeaterPowerFTempDiff,
    4158        15925 :                          state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).basinHeaterAvailSched,
    4159        15925 :                          state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).BasinHeaterSetpointTemp,
    4160        15925 :                          state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectEvapCondBasinHeaterPower);
    4161              : 
    4162        15925 :     state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectEvapCondBasinHeaterEnergy =
    4163        15925 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectEvapCondBasinHeaterPower * TimeStepSysSec;
    4164        15925 : }
    4165              : 
    4166        15921 : void UpdateEvaporativeCondenserWaterUse(EnergyPlusData &state, int const TESCoilNum, Real64 const HumRatAfterEvap, int const InletNodeNum)
    4167              : {
    4168              : 
    4169              :     // SUBROUTINE INFORMATION:
    4170              :     //       AUTHOR         B. Griffith
    4171              :     //       DATE WRITTEN   June 2013
    4172              :     //       MODIFIED       na
    4173              :     //       RE-ENGINEERED  na
    4174              : 
    4175              :     // PURPOSE OF THIS SUBROUTINE:
    4176              :     // update and calculate water consumption for evaporatively cooled condensers
    4177              : 
    4178        15921 :     Real64 const RhoWater = RhoH2O(state.dataLoopNodes->Node(InletNodeNum).Temp);
    4179        15921 :     state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsumpRate =
    4180        15921 :         (HumRatAfterEvap - state.dataLoopNodes->Node(InletNodeNum).HumRat) * state.dataLoopNodes->Node(InletNodeNum).MassFlowRate / RhoWater *
    4181        15921 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).CondenserRuntimeFraction;
    4182              : 
    4183              :     // Set the demand request for supply water from water storage tank (if needed)
    4184        15921 :     if (state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterSupplyMode == EvapWaterSupply::WaterSupplyFromTank) {
    4185            0 :         state.dataWaterData->WaterStorage(state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterSupTankID)
    4186            0 :             .VdotRequestDemand(state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterTankDemandARRID) =
    4187            0 :             state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsumpRate;
    4188              :     }
    4189              : 
    4190              :     // check if should be starved by restricted flow from tank
    4191        15921 :     if (state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterSupplyMode == EvapWaterSupply::WaterSupplyFromTank) {
    4192            0 :         Real64 const AvailWaterRate = state.dataWaterData->WaterStorage(state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterSupTankID)
    4193            0 :                                           .VdotAvailDemand(state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterTankDemandARRID);
    4194            0 :         if (AvailWaterRate < state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsumpRate) {
    4195            0 :             state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterStarvMakupRate =
    4196            0 :                 state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsumpRate - AvailWaterRate;
    4197            0 :             state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsumpRate = AvailWaterRate;
    4198              :         } else {
    4199            0 :             state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterStarvMakupRate = 0.0;
    4200              :         }
    4201              :     }
    4202              : 
    4203        15921 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    4204        15921 :     state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsump =
    4205        15921 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsumpRate * TimeStepSysSec;
    4206              : 
    4207        15921 :     state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterStarvMakup =
    4208        15921 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterStarvMakupRate * TimeStepSysSec;
    4209              : 
    4210        15921 :     state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapCondPumpElecPower =
    4211        15921 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapCondPumpElecNomPower *
    4212        15921 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).CondenserRuntimeFraction;
    4213        15921 :     state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapCondPumpElecConsumption =
    4214        15921 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapCondPumpElecPower * TimeStepSysSec;
    4215        15921 : }
    4216              : 
    4217            4 : void GetTESCoilIndex(
    4218              :     EnergyPlusData &state, std::string const &CoilName, int &CoilIndex, bool &ErrorsFound, std::string_view const CurrentModuleObject)
    4219              : {
    4220              : 
    4221              :     // SUBROUTINE INFORMATION:
    4222              :     //       AUTHOR         Richard Raustad
    4223              :     //       DATE WRITTEN   August 2013
    4224              :     //       MODIFIED       na
    4225              :     //       RE-ENGINEERED  na
    4226              : 
    4227              :     // PURPOSE OF THIS SUBROUTINE:
    4228              :     // This subroutine sets an index for a given TES Cooling Coil -- issues error message if that
    4229              :     // coil is not a legal TES Cooling Coil.
    4230              : 
    4231              :     // Obtains and allocates TESCoil related parameters from input file
    4232            4 :     if (state.dataPackagedThermalStorageCoil->GetTESInputFlag) { // First time subroutine has been called, get input data
    4233            1 :         GetTESCoilInput(state);
    4234            1 :         state.dataPackagedThermalStorageCoil->GetTESInputFlag =
    4235              :             false; // Set logic flag to disallow getting the input data on future calls to this subroutine
    4236              :     }
    4237              : 
    4238            4 :     if (state.dataPackagedThermalStorageCoil->NumTESCoils > 0) {
    4239            4 :         CoilIndex = Util::FindItem(CoilName, state.dataPackagedThermalStorageCoil->TESCoil);
    4240              :     } else {
    4241            0 :         CoilIndex = 0;
    4242              :     }
    4243              : 
    4244            4 :     if (CoilIndex == 0) {
    4245            0 :         if (!CurrentModuleObject.empty()) {
    4246            0 :             ShowSevereError(state, fmt::format("{}, GetTESCoilIndex: TES Cooling Coil not found={}", CurrentModuleObject, CoilName));
    4247              :         } else {
    4248            0 :             ShowSevereError(state, format("GetTESCoilIndex: TES Cooling Coil not found={}", CoilName));
    4249              :         }
    4250            0 :         ErrorsFound = true;
    4251              :     }
    4252            4 : }
    4253              : 
    4254            0 : void GetTESCoilAirInletNode(
    4255              :     EnergyPlusData &state, std::string const &CoilName, int &CoilAirInletNode, bool &ErrorsFound, std::string const &CurrentModuleObject)
    4256              : {
    4257              : 
    4258              :     // SUBROUTINE INFORMATION:
    4259              :     //       AUTHOR         Richard Raustad
    4260              :     //       DATE WRITTEN   July 2015
    4261              :     //       MODIFIED       na
    4262              :     //       RE-ENGINEERED  na
    4263              : 
    4264              :     // PURPOSE OF THIS SUBROUTINE:
    4265              :     // This subroutine gets a given TES Cooling Coil's air inlet node -- issues error message if that
    4266              :     // coil is not a legal TES Cooling Coil and sets air node to 0, otherwise, returns inlet air node number.
    4267              : 
    4268              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4269              :     int CoilIndex;
    4270              : 
    4271              :     // Obtains and allocates TESCoil related parameters from input file
    4272            0 :     if (state.dataPackagedThermalStorageCoil->GetTESInputFlag) { // First time subroutine has been called, get input data
    4273            0 :         GetTESCoilInput(state);
    4274            0 :         state.dataPackagedThermalStorageCoil->GetTESInputFlag =
    4275              :             false; // Set logic flag to disallow getting the input data on future calls to this subroutine
    4276              :     }
    4277              : 
    4278            0 :     if (state.dataPackagedThermalStorageCoil->NumTESCoils > 0) {
    4279            0 :         CoilIndex = Util::FindItem(CoilName, state.dataPackagedThermalStorageCoil->TESCoil, state.dataPackagedThermalStorageCoil->NumTESCoils);
    4280              :     } else {
    4281            0 :         CoilIndex = 0;
    4282              :     }
    4283              : 
    4284            0 :     if (CoilIndex == 0) {
    4285            0 :         ShowSevereError(state, format("{}, GetTESCoilAirInletNode: TES Cooling Coil not found={}", CurrentModuleObject, CoilName));
    4286            0 :         ErrorsFound = true;
    4287            0 :         CoilAirInletNode = 0;
    4288              :     } else {
    4289            0 :         CoilAirInletNode = state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).EvapAirInletNodeNum;
    4290              :     }
    4291            0 : }
    4292              : 
    4293            0 : void GetTESCoilAirOutletNode(
    4294              :     EnergyPlusData &state, std::string const &CoilName, int &CoilAirOutletNode, bool &ErrorsFound, std::string const &CurrentModuleObject)
    4295              : {
    4296              : 
    4297              :     // SUBROUTINE INFORMATION:
    4298              :     //       AUTHOR         Richard Raustad
    4299              :     //       DATE WRITTEN   July 2015
    4300              :     //       MODIFIED       na
    4301              :     //       RE-ENGINEERED  na
    4302              : 
    4303              :     // PURPOSE OF THIS SUBROUTINE:
    4304              :     // This subroutine gets a given TES Cooling Coil's air outlet node -- issues error message if that
    4305              :     // coil is not a legal TES Cooling Coil and sets air node to 0, otherwise, returns outlet air node number.
    4306              : 
    4307              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4308              :     int CoilIndex;
    4309              : 
    4310              :     // Obtains and allocates TESCoil related parameters from input file
    4311            0 :     if (state.dataPackagedThermalStorageCoil->GetTESInputFlag) { // First time subroutine has been called, get input data
    4312            0 :         GetTESCoilInput(state);
    4313            0 :         state.dataPackagedThermalStorageCoil->GetTESInputFlag =
    4314              :             false; // Set logic flag to disallow getting the input data on future calls to this subroutine
    4315              :     }
    4316              : 
    4317            0 :     if (state.dataPackagedThermalStorageCoil->NumTESCoils > 0) {
    4318            0 :         CoilIndex = Util::FindItem(CoilName, state.dataPackagedThermalStorageCoil->TESCoil, state.dataPackagedThermalStorageCoil->NumTESCoils);
    4319              :     } else {
    4320            0 :         CoilIndex = 0;
    4321              :     }
    4322              : 
    4323            0 :     if (CoilIndex == 0) {
    4324            0 :         ShowSevereError(state, format("{}, GetTESCoilAirOutletNode: TES Cooling Coil not found={}", CurrentModuleObject, CoilName));
    4325            0 :         ErrorsFound = true;
    4326            0 :         CoilAirOutletNode = 0;
    4327              :     } else {
    4328            0 :         CoilAirOutletNode = state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).EvapAirOutletNodeNum;
    4329              :     }
    4330            0 : }
    4331              : 
    4332            4 : void GetTESCoilCoolingCapacity(
    4333              :     EnergyPlusData &state, std::string const &CoilName, Real64 &CoilCoolCapacity, bool &ErrorsFound, std::string const &CurrentModuleObject)
    4334              : {
    4335              : 
    4336              :     // SUBROUTINE INFORMATION:
    4337              :     //       AUTHOR         Richard Raustad
    4338              :     //       DATE WRITTEN   July 2015
    4339              :     //       MODIFIED       na
    4340              :     //       RE-ENGINEERED  na
    4341              : 
    4342              :     // PURPOSE OF THIS SUBROUTINE:
    4343              :     // This subroutine gets a given TES Cooling Coil's cooling only capacity -- issues error message if that
    4344              :     // coil is not a legal TES Cooling Coil and sets capacity to 0, otherwise, returns cooling capacity.
    4345              : 
    4346              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4347              :     int CoilIndex;
    4348              : 
    4349              :     // Obtains and allocates TESCoil related parameters from input file
    4350            4 :     if (state.dataPackagedThermalStorageCoil->GetTESInputFlag) { // First time subroutine has been called, get input data
    4351            0 :         GetTESCoilInput(state);
    4352            0 :         state.dataPackagedThermalStorageCoil->GetTESInputFlag =
    4353              :             false; // Set logic flag to disallow getting the input data on future calls to this subroutine
    4354              :     }
    4355              : 
    4356            4 :     if (state.dataPackagedThermalStorageCoil->NumTESCoils > 0) {
    4357            4 :         CoilIndex = Util::FindItem(CoilName, state.dataPackagedThermalStorageCoil->TESCoil, state.dataPackagedThermalStorageCoil->NumTESCoils);
    4358              :     } else {
    4359            0 :         CoilIndex = 0;
    4360              :     }
    4361              : 
    4362            4 :     if (CoilIndex == 0) {
    4363            0 :         ShowSevereError(state, format("{}, GetTESCoilCoolingCapacity: TES Cooling Coil not found={}", CurrentModuleObject, CoilName));
    4364            0 :         ErrorsFound = true;
    4365            0 :         CoilCoolCapacity = 0.0;
    4366              :     } else {
    4367            4 :         if (state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).CoolingOnlyModeIsAvailable) { // get input data for this mode
    4368            4 :             CoilCoolCapacity = state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).CoolingOnlyRatedTotCap;
    4369            0 :         } else if (state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).CoolingAndChargeModeAvailable) {
    4370            0 :             CoilCoolCapacity = state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).CoolingAndChargeRatedTotCap;
    4371            0 :         } else if (state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).CoolingAndDischargeModeAvailable) {
    4372            0 :             CoilCoolCapacity = state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).CoolingAndDischargeRatedTotCap;
    4373              :         } else {
    4374            0 :             CoilCoolCapacity = 0.0;
    4375              :         }
    4376              :     }
    4377            4 : }
    4378              : 
    4379            0 : void GetTESCoilCoolingAirFlowRate(
    4380              :     EnergyPlusData &state, std::string const &CoilName, Real64 &CoilCoolAirFlow, bool &ErrorsFound, std::string const &CurrentModuleObject)
    4381              : {
    4382              : 
    4383              :     // SUBROUTINE INFORMATION:
    4384              :     //       AUTHOR         Richard Raustad
    4385              :     //       DATE WRITTEN   September 2015
    4386              :     //       MODIFIED       na
    4387              :     //       RE-ENGINEERED  na
    4388              : 
    4389              :     // PURPOSE OF THIS SUBROUTINE:
    4390              :     // This subroutine gets a given TES Cooling Coil's evaporator air flow rate -- issues error message if that
    4391              :     // coil is not a legal TES Cooling Coil and sets air flow to 0, otherwise, returns cooling air flow rate.
    4392              : 
    4393              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4394              :     int CoilIndex;
    4395              : 
    4396              :     // Obtains and allocates TESCoil related parameters from input file
    4397            0 :     if (state.dataPackagedThermalStorageCoil->GetTESInputFlag) { // First time subroutine has been called, get input data
    4398            0 :         GetTESCoilInput(state);
    4399            0 :         state.dataPackagedThermalStorageCoil->GetTESInputFlag =
    4400              :             false; // Set logic flag to disallow getting the input data on future calls to this subroutine
    4401              :     }
    4402              : 
    4403            0 :     if (state.dataPackagedThermalStorageCoil->NumTESCoils > 0) {
    4404            0 :         CoilIndex = Util::FindItem(CoilName, state.dataPackagedThermalStorageCoil->TESCoil, state.dataPackagedThermalStorageCoil->NumTESCoils);
    4405              :     } else {
    4406            0 :         CoilIndex = 0;
    4407              :     }
    4408              : 
    4409            0 :     if (CoilIndex == 0) {
    4410            0 :         ShowSevereError(state, format("{}, GetTESCoilCoolingCapacity: TES Cooling Coil not found={}", CurrentModuleObject, CoilName));
    4411            0 :         ErrorsFound = true;
    4412            0 :         CoilCoolAirFlow = 0.0;
    4413              :     } else {
    4414            0 :         CoilCoolAirFlow = state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).RatedEvapAirVolFlowRate;
    4415              :     }
    4416            0 : }
    4417              : 
    4418              : } // namespace EnergyPlus::PackagedThermalStorageCoil
        

Generated by: LCOV version 2.0-1