LCOV - code coverage report
Current view: top level - EnergyPlus - PackagedThermalStorageCoil.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 0.0 % 2377 0
Test Date: 2025-05-22 16:09:37 Functions: 0.0 % 21 0

            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            0 : 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            0 :     if (state.dataPackagedThermalStorageCoil->GetTESInputFlag) {
     128            0 :         GetTESCoilInput(state);
     129            0 :         state.dataPackagedThermalStorageCoil->GetTESInputFlag = false;
     130              :     }
     131              : 
     132            0 :     int TESCoilNum = 0;
     133            0 :     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            0 :         TESCoilNum = CompIndex;
     141            0 :         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            0 :         if (state.dataPackagedThermalStorageCoil->CheckEquipName(TESCoilNum)) {
     149            0 :             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            0 :             state.dataPackagedThermalStorageCoil->CheckEquipName(TESCoilNum) = false;
     157              :         }
     158              :     }
     159              : 
     160            0 :     TESOpMode = PTSCOperatingMode::CoolingOnly;
     161              : 
     162            0 :     InitTESCoil(state, TESCoilNum);
     163              : 
     164            0 :     TESOpMode = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).CurControlMode;
     165            0 :     switch (TESOpMode) {
     166            0 :     case PTSCOperatingMode::Off:
     167            0 :         CalcTESCoilOffMode(state, TESCoilNum);
     168            0 :         break;
     169            0 :     case PTSCOperatingMode::CoolingOnly:
     170            0 :         CalcTESCoilCoolingOnlyMode(state, TESCoilNum, fanOp, PartLoadRatio);
     171            0 :         break;
     172            0 :     case PTSCOperatingMode::CoolingAndCharge:
     173            0 :         CalcTESCoilCoolingAndChargeMode(state, TESCoilNum, fanOp, PartLoadRatio);
     174            0 :         break;
     175            0 :     case PTSCOperatingMode::CoolingAndDischarge:
     176            0 :         CalcTESCoilCoolingAndDischargeMode(state, TESCoilNum, fanOp, PartLoadRatio);
     177            0 :         break;
     178            0 :     case PTSCOperatingMode::ChargeOnly:
     179            0 :         CalcTESCoilChargeOnlyMode(state, TESCoilNum);
     180            0 :         break;
     181            0 :     case PTSCOperatingMode::DischargeOnly:
     182            0 :         CalcTESCoilDischargeOnlyMode(state, TESCoilNum, PartLoadRatio);
     183            0 :         break;
     184            0 :     default:
     185            0 :         assert(false);
     186              :     }
     187            0 : }
     188              : 
     189            0 : 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            0 :     int NumAlphas = 0;       // Number of alphas in input
     212            0 :     int NumNumbers = 0;      // Number of numeric items in input
     213            0 :     int IOStatus = -1;       // Input status returned from GetObjectItem
     214            0 :     bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
     215              : 
     216            0 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     217            0 :     cCurrentModuleObject = "Coil:Cooling:DX:SingleSpeed:ThermalStorage";
     218            0 :     state.dataPackagedThermalStorageCoil->NumTESCoils = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     219              : 
     220            0 :     state.dataPackagedThermalStorageCoil->TESCoil.allocate(state.dataPackagedThermalStorageCoil->NumTESCoils);
     221            0 :     state.dataPackagedThermalStorageCoil->CheckEquipName.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, true);
     222              : 
     223            0 :     for (int item = 1; item <= state.dataPackagedThermalStorageCoil->NumTESCoils; ++item) {
     224              : 
     225            0 :         auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(item);
     226              : 
     227            0 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     228              :                                                                  cCurrentModuleObject,
     229              :                                                                  item,
     230            0 :                                                                  state.dataIPShortCut->cAlphaArgs,
     231              :                                                                  NumAlphas,
     232            0 :                                                                  state.dataIPShortCut->rNumericArgs,
     233              :                                                                  NumNumbers,
     234              :                                                                  IOStatus,
     235            0 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     236            0 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     237            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     238            0 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     239              : 
     240            0 :         ErrorObjectHeader eoh{routineName, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)};
     241              : 
     242            0 :         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            0 :         VerifyUniqueCoilName(state, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, cCurrentModuleObject + " Name");
     246              : 
     247            0 :         thisTESCoil.Name = state.dataIPShortCut->cAlphaArgs(1);
     248            0 :         if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
     249            0 :             thisTESCoil.availSched = Sched::GetScheduleAlwaysOn(state);
     250            0 :         } 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            0 :         thisTESCoil.ModeControlType = static_cast<PTSCCtrlType>(getEnumValue(modeControlStrings, state.dataIPShortCut->cAlphaArgs(3)));
     256            0 :         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            0 :         if (thisTESCoil.ModeControlType == PTSCCtrlType::ScheduledOpModes) {
     264            0 :             if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
     265            0 :                 ShowSevereEmptyField(state, eoh, state.dataIPShortCut->cAlphaFieldNames(4));
     266            0 :                 ErrorsFound = true;
     267            0 :             } 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            0 :         thisTESCoil.StorageMedia = static_cast<MediaType>(getEnumValue(mediaStrings, state.dataIPShortCut->cAlphaArgs(5)));
     274            0 :         switch (thisTESCoil.StorageMedia) {
     275            0 :         case MediaType::Ice:
     276              :         case MediaType::UserDefindFluid:
     277              :             // nothing else to do for now
     278            0 :             break;
     279            0 :         case MediaType::Water:
     280            0 :             thisTESCoil.StorageFluidName = "WATER";
     281            0 :             thisTESCoil.glycol = Fluid::GetWater(state);
     282            0 :             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            0 :         thisTESCoil.StorageFluidName = state.dataIPShortCut->cAlphaArgs(6);
     291            0 :         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            0 :         switch (thisTESCoil.StorageMedia) {
     302            0 :         case MediaType::Water:
     303              :         case MediaType::UserDefindFluid:
     304            0 :             if (!state.dataIPShortCut->lNumericFieldBlanks(1)) {
     305            0 :                 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            0 :             break;
     313            0 :         case MediaType::Ice:
     314            0 :             if (!state.dataIPShortCut->lNumericFieldBlanks(2)) {
     315            0 :                 if (state.dataIPShortCut->rNumericArgs(2) == Constant::AutoCalculate) {
     316            0 :                     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            0 :             break;
     328            0 :         default:
     329              :             // nothing
     330            0 :             break;
     331              :         }
     332              : 
     333            0 :         thisTESCoil.StorageCapacitySizingFactor = state.dataIPShortCut->rNumericArgs(3);
     334              : 
     335            0 :         thisTESCoil.StorageAmbientNodeNum = GetOnlySingleNode(state,
     336            0 :                                                               state.dataIPShortCut->cAlphaArgs(7),
     337              :                                                               ErrorsFound,
     338              :                                                               DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
     339            0 :                                                               state.dataIPShortCut->cAlphaArgs(1),
     340              :                                                               DataLoopNode::NodeFluidType::Air,
     341              :                                                               DataLoopNode::ConnectionType::Sensor,
     342              :                                                               NodeInputManager::CompFluidStream::Primary,
     343              :                                                               ObjectIsNotParent);
     344              : 
     345            0 :         int const ZoneIndexTrial = FindControlledZoneIndexFromSystemNodeNumberForZone(state, thisTESCoil.StorageAmbientNodeNum);
     346            0 :         if (ZoneIndexTrial > 0) { // tank is inside a zone so setup internal gains
     347            0 :             SetupZoneInternalGain(
     348              :                 state, ZoneIndexTrial, thisTESCoil.Name, DataHeatBalance::IntGainType::PackagedTESCoilTank, &thisTESCoil.QdotAmbient);
     349              :         }
     350              : 
     351            0 :         thisTESCoil.StorageUA = state.dataIPShortCut->rNumericArgs(4);
     352            0 :         thisTESCoil.RatedFluidTankTemp = state.dataIPShortCut->rNumericArgs(5);
     353            0 :         thisTESCoil.RatedEvapAirVolFlowRate = state.dataIPShortCut->rNumericArgs(6);
     354              : 
     355            0 :         thisTESCoil.EvapAirInletNodeNum = GetOnlySingleNode(state,
     356            0 :                                                             state.dataIPShortCut->cAlphaArgs(8),
     357              :                                                             ErrorsFound,
     358              :                                                             DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
     359            0 :                                                             state.dataIPShortCut->cAlphaArgs(1),
     360              :                                                             DataLoopNode::NodeFluidType::Air,
     361              :                                                             DataLoopNode::ConnectionType::Inlet,
     362              :                                                             NodeInputManager::CompFluidStream::Primary,
     363              :                                                             ObjectIsNotParent);
     364            0 :         thisTESCoil.EvapAirOutletNodeNum = GetOnlySingleNode(state,
     365            0 :                                                              state.dataIPShortCut->cAlphaArgs(9),
     366              :                                                              ErrorsFound,
     367              :                                                              DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
     368            0 :                                                              state.dataIPShortCut->cAlphaArgs(1),
     369              :                                                              DataLoopNode::NodeFluidType::Air,
     370              :                                                              DataLoopNode::ConnectionType::Outlet,
     371              :                                                              NodeInputManager::CompFluidStream::Primary,
     372              :                                                              ObjectIsNotParent);
     373            0 :         TestCompSet(state,
     374              :                     cCurrentModuleObject,
     375            0 :                     state.dataIPShortCut->cAlphaArgs(1),
     376            0 :                     state.dataIPShortCut->cAlphaArgs(8),
     377            0 :                     state.dataIPShortCut->cAlphaArgs(9),
     378              :                     "Air Nodes");
     379              : 
     380            0 :         BooleanSwitch const answer = getYesNoValue(state.dataIPShortCut->cAlphaArgs(10));
     381            0 :         switch (answer) {
     382            0 :         case BooleanSwitch::Yes:
     383              :         case BooleanSwitch::No:
     384            0 :             thisTESCoil.CoolingOnlyModeIsAvailable = static_cast<bool>(answer);
     385            0 :             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            0 :         thisTESCoil.CoolingOnlyRatedTotCap = state.dataIPShortCut->rNumericArgs(7);
     395            0 :         if (thisTESCoil.CoolingOnlyModeIsAvailable) { // get input data for this mode
     396              : 
     397            0 :             thisTESCoil.CoolingOnlyRatedSHR = state.dataIPShortCut->rNumericArgs(8);
     398            0 :             thisTESCoil.CoolingOnlyRatedCOP = state.dataIPShortCut->rNumericArgs(9);
     399              : 
     400            0 :             thisTESCoil.CoolingOnlyCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(11));
     401            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(11)); // Field Name
     420              :             }
     421              : 
     422            0 :             thisTESCoil.CoolingOnlyCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(12));
     423            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(12)); // Field Name
     442              :             }
     443              : 
     444            0 :             thisTESCoil.CoolingOnlyEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(13));
     445            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(13)); // Field Name
     464              :             }
     465              : 
     466            0 :             thisTESCoil.CoolingOnlyEIRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(14));
     467            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(14)); // Field Name
     486              :             }
     487              : 
     488            0 :             thisTESCoil.CoolingOnlyPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(15));
     489            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(15)); // Field Name
     508              :             }
     509              : 
     510            0 :             thisTESCoil.CoolingOnlySHRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(16));
     511            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(16)); // Field Name
     530              :             }
     531              : 
     532            0 :             thisTESCoil.CoolingOnlySHRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(17));
     533            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(17)); // Field Name
     552              :             }
     553              :         }
     554              : 
     555            0 :         BooleanSwitch const answer2 = getYesNoValue(state.dataIPShortCut->cAlphaArgs(18));
     556            0 :         switch (answer2) {
     557            0 :         case BooleanSwitch::Yes:
     558              :         case BooleanSwitch::No:
     559            0 :             thisTESCoil.CoolingAndChargeModeAvailable = static_cast<bool>(answer2);
     560            0 :             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            0 :         if (thisTESCoil.CoolingAndChargeModeAvailable) {
     570              : 
     571            0 :             thisTESCoil.CoolingAndChargeRatedTotCap = state.dataIPShortCut->rNumericArgs(10); // gross total evaporator cooling capacity [W]
     572            0 :             thisTESCoil.CoolingAndChargeRatedTotCapSizingFactor =
     573            0 :                 state.dataIPShortCut->rNumericArgs(11); // sizing factor for gross total evaporator [ ]
     574            0 :             thisTESCoil.CoolingAndChargeRatedChargeCap =
     575            0 :                 state.dataIPShortCut->rNumericArgs(12); // net storage charging capacity at rating conditions [W]
     576            0 :             thisTESCoil.CoolingAndChargeRatedChargeCapSizingFactor =
     577            0 :                 state.dataIPShortCut->rNumericArgs(13);                                            // sizing factor for charging capacity [ ]
     578            0 :             thisTESCoil.CoolingAndChargeRatedSHR = state.dataIPShortCut->rNumericArgs(14);         // Sensible heat ratio (sens cap/total cap)  [W/W]
     579            0 :             thisTESCoil.CoolingAndChargeCoolingRatedCOP = state.dataIPShortCut->rNumericArgs(15);  // Coefficient of performance , for cooling [W/W]
     580            0 :             thisTESCoil.CoolingAndChargeChargingRatedCOP = state.dataIPShortCut->rNumericArgs(16); // Coefficient of performance , for charging [W/W]
     581              : 
     582            0 :             thisTESCoil.CoolingAndChargeCoolingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(19));
     583            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(19));      // Field Name
     602              :             }
     603              : 
     604            0 :             thisTESCoil.CoolingAndChargeCoolingCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(20));
     605            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(20));      // Field Name
     624              :             }
     625            0 :             thisTESCoil.CoolingAndChargeCoolingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(21));
     626            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(21));      // Field Name
     645              :             }
     646              : 
     647            0 :             thisTESCoil.CoolingAndChargeCoolingEIRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(22));
     648            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(22));      // Field Name
     667              :             }
     668              : 
     669            0 :             thisTESCoil.CoolingAndChargeCoolingPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(23));
     670            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(23));     // Field Name
     689              :             }
     690              : 
     691            0 :             thisTESCoil.CoolingAndChargeChargingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(24));
     692            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(24));       // Field Name
     711              :             }
     712              : 
     713            0 :             thisTESCoil.CoolingAndChargeChargingCapFEvapPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(25));
     714            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(25));          // Field Name
     733              :             }
     734              : 
     735            0 :             thisTESCoil.CoolingAndChargeChargingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(26));
     736            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(26));       // Field Name
     755              :             }
     756              : 
     757            0 :             thisTESCoil.CoolingAndChargeChargingEIRFFLowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(27));
     758            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(27));       // Field Name
     777              :             }
     778              : 
     779            0 :             thisTESCoil.CoolingAndChargeChargingPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(28));
     780            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(28));      // Field Name
     799              :             }
     800              : 
     801            0 :             thisTESCoil.CoolingAndChargeSHRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(29));
     802            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(29)); // Field Name
     821              :             }
     822              : 
     823            0 :             thisTESCoil.CoolingAndChargeSHRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(30));
     824            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(30)); // Field Name
     843              :             }
     844              : 
     845              :         } // Cooling and Charge Mode available
     846              : 
     847            0 :         BooleanSwitch answer3 = getYesNoValue(state.dataIPShortCut->cAlphaArgs(31));
     848            0 :         switch (answer3) {
     849            0 :         case BooleanSwitch::Yes:
     850              :         case BooleanSwitch::No:
     851            0 :             thisTESCoil.CoolingAndDischargeModeAvailable = static_cast<bool>(answer3);
     852            0 :             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            0 :         if (thisTESCoil.CoolingAndDischargeModeAvailable) {
     862              : 
     863            0 :             thisTESCoil.CoolingAndDischargeRatedTotCap = state.dataIPShortCut->rNumericArgs(17); // gross total evaporator cooling capacity  [W]
     864            0 :             thisTESCoil.CoolingAndDischargeRatedTotCapSizingFactor =
     865            0 :                 state.dataIPShortCut->rNumericArgs(18); // sizing factor gross total cooling capacity []
     866            0 :             thisTESCoil.CoolingAndDischargeRatedDischargeCap = state.dataIPShortCut->rNumericArgs(19); // net storage discharging capacity  [W]
     867            0 :             thisTESCoil.CoolingAndDischargeRatedDischargeCapSizingFactor =
     868            0 :                 state.dataIPShortCut->rNumericArgs(20);                                              // sizing factor discharging capacity []
     869            0 :             thisTESCoil.CoolingAndDischargeRatedSHR = state.dataIPShortCut->rNumericArgs(21);        // Sensible heat ratio (sens cap/total cap) [W/W]
     870            0 :             thisTESCoil.CoolingAndDischargeCoolingRatedCOP = state.dataIPShortCut->rNumericArgs(22); // Coefficient of performance , for cooling [W/W]
     871            0 :             thisTESCoil.CoolingAndDischargeDischargingRatedCOP =
     872            0 :                 state.dataIPShortCut->rNumericArgs(23); // Coefficient of performance , for charging [W/W]
     873              : 
     874            0 :             thisTESCoil.CoolingAndDischargeCoolingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(32));
     875            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(32));         // Field Name
     894              :             }
     895              : 
     896            0 :             thisTESCoil.CoolingAndDischargeCoolingCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(33));
     897            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(33));         // Field Name
     916              :             }
     917              : 
     918            0 :             thisTESCoil.CoolingAndDischargeCoolingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(34));
     919            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(34));         // Field Name
     938              :             }
     939              : 
     940            0 :             thisTESCoil.CoolingAndDischargeCoolingEIRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(35));
     941            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(35));         // Field Name
     960              :             }
     961              : 
     962            0 :             thisTESCoil.CoolingAndDischargeCoolingPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(36));
     963            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(36));        // Field Name
     982              :             }
     983              : 
     984            0 :             thisTESCoil.CoolingAndDischargeDischargingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(37));
     985            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(37));             // Field Name
    1004              :             }
    1005              : 
    1006            0 :             thisTESCoil.CoolingAndDischargeDischargingCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(38));
    1007            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(38));             // Field Name
    1026              :             }
    1027              : 
    1028            0 :             thisTESCoil.CoolingAndDischargeDischargingCapFEvapPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(39));
    1029            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(39));                // Field Name
    1048              :             }
    1049              : 
    1050            0 :             thisTESCoil.CoolingAndDischargeDischargingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(40));
    1051            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(40));             // Field Name
    1070              :             }
    1071              : 
    1072            0 :             thisTESCoil.CoolingAndDischargeDischargingEIRFFLowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(41));
    1073            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(41));             // Field Name
    1092              :             }
    1093              : 
    1094            0 :             thisTESCoil.CoolingAndDischargeDischargingPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(42));
    1095            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(42));            // Field Name
    1114              :             }
    1115              : 
    1116            0 :             thisTESCoil.CoolingAndDischargeSHRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(43));
    1117            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(43)); // Field Name
    1136              :             }
    1137              : 
    1138            0 :             thisTESCoil.CoolingAndDischargeSHRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(44));
    1139            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(44));  // Field Name
    1158              :             }
    1159              : 
    1160              :         } // cooling and discharge mode available
    1161              : 
    1162            0 :         BooleanSwitch answer4 = getYesNoValue(state.dataIPShortCut->cAlphaArgs(45));
    1163            0 :         switch (answer4) {
    1164            0 :         case BooleanSwitch::Yes:
    1165              :         case BooleanSwitch::No:
    1166            0 :             thisTESCoil.ChargeOnlyModeAvailable = static_cast<bool>(answer4);
    1167            0 :             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            0 :         if (thisTESCoil.ChargeOnlyModeAvailable) {
    1177              : 
    1178            0 :             thisTESCoil.ChargeOnlyRatedCapacity = state.dataIPShortCut->rNumericArgs(24); // net storage charging capacity at rating conditions [W]
    1179            0 :             thisTESCoil.ChargeOnlyRatedCapacitySizingFactor = state.dataIPShortCut->rNumericArgs(25); // sizing factor for charging capacity []
    1180            0 :             thisTESCoil.ChargeOnlyRatedCOP = state.dataIPShortCut->rNumericArgs(26); // coefficient of performance at rating conditions [W/W]
    1181              : 
    1182            0 :             thisTESCoil.ChargeOnlyChargingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(46));
    1183            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(46)); // Field Name
    1202              :             }
    1203              : 
    1204            0 :             thisTESCoil.ChargeOnlyChargingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(47));
    1205            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(47)); // Field Name
    1224              :             }
    1225              : 
    1226              :         } // Charge only mode available
    1227              : 
    1228            0 :         BooleanSwitch answer5 = getYesNoValue(state.dataIPShortCut->cAlphaArgs(48));
    1229            0 :         switch (answer5) {
    1230            0 :         case BooleanSwitch::Yes:
    1231              :         case BooleanSwitch::No:
    1232            0 :             thisTESCoil.DischargeOnlyModeAvailable = static_cast<bool>(answer5);
    1233            0 :             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            0 :         if (thisTESCoil.DischargeOnlyModeAvailable) {
    1243            0 :             thisTESCoil.DischargeOnlyRatedDischargeCap = state.dataIPShortCut->rNumericArgs(27); // gross total evaporator cooling capacity  [W]
    1244            0 :             thisTESCoil.DischargeOnlyRatedDischargeCapSizingFactor = state.dataIPShortCut->rNumericArgs(28); // sizing factor for cooling capacity []
    1245            0 :             thisTESCoil.DischargeOnlyRatedSHR = state.dataIPShortCut->rNumericArgs(29); // sensible heat ratio (sens cap/total cap)
    1246            0 :             thisTESCoil.DischargeOnlyRatedCOP = state.dataIPShortCut->rNumericArgs(30); // coefficient of performance  for discharging [W/W]
    1247              : 
    1248            0 :             thisTESCoil.DischargeOnlyCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(49));
    1249            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(49)); // Field Name
    1268              :             }
    1269              : 
    1270            0 :             thisTESCoil.DischargeOnlyCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(50));
    1271            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(50)); // Field Name
    1290              :             }
    1291              : 
    1292            0 :             thisTESCoil.DischargeOnlyEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(51));
    1293            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(51)); // Field Name
    1312              :             }
    1313              : 
    1314            0 :             thisTESCoil.DischargeOnlyEIRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(52));
    1315            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(52)); // Field Name
    1334              :             }
    1335              : 
    1336            0 :             thisTESCoil.DischargeOnlyPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(53));
    1337            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(53)); // Field Name
    1356              :             }
    1357              : 
    1358            0 :             thisTESCoil.DischargeOnlySHRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(54));
    1359            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(54)); // Field Name
    1378              :             }
    1379              : 
    1380            0 :             thisTESCoil.DischargeOnlySHRFFLowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(55));
    1381            0 :             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            0 :                 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            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames(55)); // Field Name
    1400              :             }
    1401              : 
    1402              :         } // Discharge Only mode available
    1403              : 
    1404            0 :         thisTESCoil.AncillaryControlsPower = state.dataIPShortCut->rNumericArgs(31);
    1405            0 :         thisTESCoil.ColdWeatherMinimumTempLimit = state.dataIPShortCut->rNumericArgs(32);
    1406            0 :         thisTESCoil.ColdWeatherAncillaryPower = state.dataIPShortCut->rNumericArgs(33);
    1407            0 :         thisTESCoil.CondAirInletNodeNum = GetOnlySingleNode(state,
    1408            0 :                                                             state.dataIPShortCut->cAlphaArgs(56),
    1409              :                                                             ErrorsFound,
    1410              :                                                             DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
    1411            0 :                                                             thisTESCoil.Name,
    1412              :                                                             DataLoopNode::NodeFluidType::Air,
    1413              :                                                             DataLoopNode::ConnectionType::OutsideAirReference,
    1414              :                                                             NodeInputManager::CompFluidStream::Primary,
    1415              :                                                             ObjectIsNotParent);
    1416            0 :         thisTESCoil.CondAirOutletNodeNum = GetOnlySingleNode(state,
    1417            0 :                                                              state.dataIPShortCut->cAlphaArgs(57),
    1418              :                                                              ErrorsFound,
    1419              :                                                              DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
    1420            0 :                                                              thisTESCoil.Name,
    1421              :                                                              DataLoopNode::NodeFluidType::Air,
    1422              :                                                              DataLoopNode::ConnectionType::ReliefAir,
    1423              :                                                              NodeInputManager::CompFluidStream::Primary,
    1424              :                                                              ObjectIsNotParent);
    1425              : 
    1426            0 :         thisTESCoil.CondenserAirVolumeFlow = state.dataIPShortCut->rNumericArgs(34);
    1427            0 :         thisTESCoil.CondenserAirFlowSizingFactor = state.dataIPShortCut->rNumericArgs(35);
    1428              : 
    1429            0 :         thisTESCoil.CondenserType = static_cast<TESCondenserType>(getEnumValue(condenserTypesUC, state.dataIPShortCut->cAlphaArgs(58)));
    1430            0 :         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            0 :         thisTESCoil.EvapCondEffect = state.dataIPShortCut->rNumericArgs(36);
    1438            0 :         thisTESCoil.EvapCondPumpElecNomPower = state.dataIPShortCut->rNumericArgs(37);
    1439            0 :         thisTESCoil.BasinHeaterPowerFTempDiff = state.dataIPShortCut->rNumericArgs(38);
    1440            0 :         thisTESCoil.BasinHeaterSetpointTemp = state.dataIPShortCut->rNumericArgs(39);
    1441              : 
    1442            0 :         if (state.dataIPShortCut->lAlphaFieldBlanks(59)) {
    1443            0 :             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            0 :         if (state.dataIPShortCut->lAlphaFieldBlanks(60)) {
    1450            0 :             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            0 :         if (state.dataIPShortCut->lAlphaFieldBlanks(61)) {
    1464            0 :             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            0 :         if (!state.dataIPShortCut->lAlphaFieldBlanks(62)) {
    1478            0 :             thisTESCoil.TESPlantInletNodeNum = GetOnlySingleNode(state,
    1479            0 :                                                                  state.dataIPShortCut->cAlphaArgs(62),
    1480              :                                                                  ErrorsFound,
    1481              :                                                                  DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
    1482            0 :                                                                  state.dataIPShortCut->cAlphaArgs(1),
    1483              :                                                                  DataLoopNode::NodeFluidType::Water,
    1484              :                                                                  DataLoopNode::ConnectionType::Inlet,
    1485              :                                                                  NodeInputManager::CompFluidStream::Secondary,
    1486              :                                                                  ObjectIsNotParent);
    1487              : 
    1488            0 :             thisTESCoil.TESPlantConnectionAvailable = true;
    1489              :         } else {
    1490            0 :             thisTESCoil.TESPlantConnectionAvailable = false;
    1491              :         }
    1492            0 :         if (!state.dataIPShortCut->lAlphaFieldBlanks(63)) {
    1493            0 :             thisTESCoil.TESPlantOutletNodeNum = GetOnlySingleNode(state,
    1494            0 :                                                                   state.dataIPShortCut->cAlphaArgs(63),
    1495              :                                                                   ErrorsFound,
    1496              :                                                                   DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
    1497            0 :                                                                   state.dataIPShortCut->cAlphaArgs(1),
    1498              :                                                                   DataLoopNode::NodeFluidType::Water,
    1499              :                                                                   DataLoopNode::ConnectionType::Outlet,
    1500              :                                                                   NodeInputManager::CompFluidStream::Secondary,
    1501              :                                                                   ObjectIsNotParent);
    1502              :         } else {
    1503            0 :             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            0 :         if (thisTESCoil.TESPlantConnectionAvailable) {
    1510            0 :             TestCompSet(state,
    1511              :                         cCurrentModuleObject,
    1512            0 :                         state.dataIPShortCut->cAlphaArgs(1),
    1513            0 :                         state.dataIPShortCut->cAlphaArgs(62),
    1514            0 :                         state.dataIPShortCut->cAlphaArgs(63),
    1515              :                         "Water Nodes");
    1516              :         }
    1517              : 
    1518            0 :         if (!state.dataIPShortCut->lNumericFieldBlanks(40)) {
    1519            0 :             thisTESCoil.TESPlantDesignVolumeFlowRate = state.dataIPShortCut->rNumericArgs(40);
    1520              :         }
    1521            0 :         if (!state.dataIPShortCut->lNumericFieldBlanks(41)) {
    1522            0 :             thisTESCoil.TESPlantEffectiveness = state.dataIPShortCut->rNumericArgs(41);
    1523              :         }
    1524              : 
    1525            0 :         switch (thisTESCoil.StorageMedia) {
    1526            0 :         case MediaType::UserDefindFluid:
    1527              :         case MediaType::Water: {
    1528            0 :             Real64 TminRho = -9999.0;
    1529            0 :             Real64 TmaxRho = 9999.0;
    1530            0 :             Real64 TminCp = -9999.0;
    1531            0 :             Real64 TmaxCp = 9999.0;
    1532            0 :             if (!state.dataIPShortCut->lNumericFieldBlanks(42)) {
    1533            0 :                 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            0 :             if (!state.dataIPShortCut->lNumericFieldBlanks(43)) {
    1540            0 :                 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            0 :         default:
    1548              :             // nothing
    1549            0 :             break;
    1550              :         }
    1551              :     }
    1552              : 
    1553            0 :     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            0 :     for (int item = 1; item <= state.dataPackagedThermalStorageCoil->NumTESCoils; ++item) {
    1560            0 :         auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(item);
    1561              : 
    1562            0 :         SetupOutputVariable(state,
    1563              :                             "Cooling Coil Operating Mode Index",
    1564              :                             Constant::Units::None,
    1565            0 :                             thisTESCoil.curControlModeReport,
    1566              :                             OutputProcessor::TimeStepType::System,
    1567              :                             OutputProcessor::StoreType::Average,
    1568            0 :                             thisTESCoil.Name);
    1569              : 
    1570              :         // cCurrentModuleObject = "Coil:Cooling:DX:SingleSpeed:ThermalStorage"
    1571            0 :         SetupOutputVariable(state,
    1572              :                             "Cooling Coil Total Cooling Rate",
    1573              :                             Constant::Units::W,
    1574            0 :                             thisTESCoil.EvapTotCoolingRate,
    1575              :                             OutputProcessor::TimeStepType::System,
    1576              :                             OutputProcessor::StoreType::Average,
    1577            0 :                             thisTESCoil.Name);
    1578            0 :         SetupOutputVariable(state,
    1579              :                             "Cooling Coil Total Cooling Energy",
    1580              :                             Constant::Units::J,
    1581            0 :                             thisTESCoil.EvapTotCoolingEnergy,
    1582              :                             OutputProcessor::TimeStepType::System,
    1583              :                             OutputProcessor::StoreType::Sum,
    1584            0 :                             thisTESCoil.Name,
    1585              :                             Constant::eResource::EnergyTransfer,
    1586              :                             OutputProcessor::Group::HVAC,
    1587              :                             OutputProcessor::EndUseCat::CoolingCoils);
    1588            0 :         SetupOutputVariable(state,
    1589              :                             "Cooling Coil Sensible Cooling Rate",
    1590              :                             Constant::Units::W,
    1591            0 :                             thisTESCoil.EvapSensCoolingRate,
    1592              :                             OutputProcessor::TimeStepType::System,
    1593              :                             OutputProcessor::StoreType::Average,
    1594            0 :                             thisTESCoil.Name);
    1595            0 :         SetupOutputVariable(state,
    1596              :                             "Cooling Coil Sensible Cooling Energy",
    1597              :                             Constant::Units::J,
    1598            0 :                             thisTESCoil.EvapSensCoolingEnergy,
    1599              :                             OutputProcessor::TimeStepType::System,
    1600              :                             OutputProcessor::StoreType::Sum,
    1601            0 :                             thisTESCoil.Name);
    1602            0 :         SetupOutputVariable(state,
    1603              :                             "Cooling Coil Latent Cooling Rate",
    1604              :                             Constant::Units::W,
    1605            0 :                             thisTESCoil.EvapLatCoolingRate,
    1606              :                             OutputProcessor::TimeStepType::System,
    1607              :                             OutputProcessor::StoreType::Average,
    1608            0 :                             thisTESCoil.Name);
    1609            0 :         SetupOutputVariable(state,
    1610              :                             "Cooling Coil Latent Cooling Energy",
    1611              :                             Constant::Units::J,
    1612            0 :                             thisTESCoil.EvapLatCoolingEnergy,
    1613              :                             OutputProcessor::TimeStepType::System,
    1614              :                             OutputProcessor::StoreType::Sum,
    1615            0 :                             thisTESCoil.Name);
    1616            0 :         SetupOutputVariable(state,
    1617              :                             "Cooling Coil Electricity Rate",
    1618              :                             Constant::Units::W,
    1619            0 :                             thisTESCoil.ElecCoolingPower,
    1620              :                             OutputProcessor::TimeStepType::System,
    1621              :                             OutputProcessor::StoreType::Average,
    1622            0 :                             thisTESCoil.Name);
    1623            0 :         SetupOutputVariable(state,
    1624              :                             "Cooling Coil Electricity Energy",
    1625              :                             Constant::Units::J,
    1626            0 :                             thisTESCoil.ElecCoolingEnergy,
    1627              :                             OutputProcessor::TimeStepType::System,
    1628              :                             OutputProcessor::StoreType::Sum,
    1629            0 :                             thisTESCoil.Name,
    1630              :                             Constant::eResource::Electricity,
    1631              :                             OutputProcessor::Group::HVAC,
    1632              :                             OutputProcessor::EndUseCat::Cooling);
    1633              : 
    1634            0 :         SetupOutputVariable(state,
    1635              :                             "Cooling Coil Runtime Fraction",
    1636              :                             Constant::Units::None,
    1637            0 :                             thisTESCoil.RuntimeFraction,
    1638              :                             OutputProcessor::TimeStepType::System,
    1639              :                             OutputProcessor::StoreType::Average,
    1640            0 :                             thisTESCoil.Name);
    1641            0 :         SetupOutputVariable(state,
    1642              :                             "Cooling Coil Cold Weather Protection Electricity Energy",
    1643              :                             Constant::Units::J,
    1644            0 :                             thisTESCoil.ElectColdWeatherEnergy,
    1645              :                             OutputProcessor::TimeStepType::System,
    1646              :                             OutputProcessor::StoreType::Sum,
    1647            0 :                             thisTESCoil.Name,
    1648              :                             Constant::eResource::Electricity,
    1649              :                             OutputProcessor::Group::HVAC,
    1650              :                             OutputProcessor::EndUseCat::Cooling,
    1651              :                             "Thermal Protection");
    1652            0 :         SetupOutputVariable(state,
    1653              :                             "Cooling Coil Cold Weather Protection Electricity Rate",
    1654              :                             Constant::Units::W,
    1655            0 :                             thisTESCoil.ElectColdWeatherPower,
    1656              :                             OutputProcessor::TimeStepType::System,
    1657              :                             OutputProcessor::StoreType::Average,
    1658            0 :                             thisTESCoil.Name);
    1659              : 
    1660            0 :         SetupOutputVariable(state,
    1661              :                             "Cooling Coil Thermal Storage Mechanical Heat Transfer Rate",
    1662              :                             Constant::Units::W,
    1663            0 :                             thisTESCoil.QdotTES,
    1664              :                             OutputProcessor::TimeStepType::System,
    1665              :                             OutputProcessor::StoreType::Average,
    1666            0 :                             thisTESCoil.Name);
    1667              : 
    1668            0 :         SetupOutputVariable(state,
    1669              :                             "Cooling Coil Thermal Storage Mechanical Heat Transfer Energy",
    1670              :                             Constant::Units::J,
    1671            0 :                             thisTESCoil.Q_TES,
    1672              :                             OutputProcessor::TimeStepType::System,
    1673              :                             OutputProcessor::StoreType::Sum,
    1674            0 :                             thisTESCoil.Name);
    1675              : 
    1676            0 :         SetupOutputVariable(state,
    1677              :                             "Cooling Coil Thermal Storage Ambient Heat Transfer Rate",
    1678              :                             Constant::Units::W,
    1679            0 :                             thisTESCoil.QdotAmbient,
    1680              :                             OutputProcessor::TimeStepType::System,
    1681              :                             OutputProcessor::StoreType::Average,
    1682            0 :                             thisTESCoil.Name);
    1683              : 
    1684            0 :         SetupOutputVariable(state,
    1685              :                             "Cooling Coil Thermal Storage Ambient Heat Transfer Energy",
    1686              :                             Constant::Units::J,
    1687            0 :                             thisTESCoil.Q_Ambient,
    1688              :                             OutputProcessor::TimeStepType::System,
    1689              :                             OutputProcessor::StoreType::Sum,
    1690            0 :                             thisTESCoil.Name);
    1691              : 
    1692            0 :         if (thisTESCoil.TESPlantConnectionAvailable) {
    1693            0 :             SetupOutputVariable(state,
    1694              :                                 "Cooling Coil Thermal Storage Plant Heat Transfer Rate",
    1695              :                                 Constant::Units::W,
    1696            0 :                                 thisTESCoil.QdotPlant,
    1697              :                                 OutputProcessor::TimeStepType::System,
    1698              :                                 OutputProcessor::StoreType::Average,
    1699            0 :                                 thisTESCoil.Name);
    1700            0 :             SetupOutputVariable(state,
    1701              :                                 "Cooling Coil Thermal Storage Plant Heat Transfer Energy",
    1702              :                                 Constant::Units::J,
    1703            0 :                                 thisTESCoil.Q_Plant,
    1704              :                                 OutputProcessor::TimeStepType::System,
    1705              :                                 OutputProcessor::StoreType::Sum,
    1706            0 :                                 thisTESCoil.Name);
    1707              :         }
    1708              : 
    1709            0 :         if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    1710            0 :             SetupOutputVariable(state,
    1711              :                                 "Cooling Coil Condenser Inlet Temperature",
    1712              :                                 Constant::Units::C,
    1713            0 :                                 thisTESCoil.CondInletTemp,
    1714              :                                 OutputProcessor::TimeStepType::System,
    1715              :                                 OutputProcessor::StoreType::Average,
    1716            0 :                                 thisTESCoil.Name);
    1717              : 
    1718            0 :             if (thisTESCoil.EvapWaterSupplyMode == EvapWaterSupply::WaterSupplyFromMains) {
    1719            0 :                 SetupOutputVariable(state,
    1720              :                                     "Cooling Coil Evaporative Condenser Water Volume",
    1721              :                                     Constant::Units::m3,
    1722            0 :                                     thisTESCoil.EvapWaterConsump,
    1723              :                                     OutputProcessor::TimeStepType::System,
    1724              :                                     OutputProcessor::StoreType::Sum,
    1725            0 :                                     thisTESCoil.Name,
    1726              :                                     Constant::eResource::Water,
    1727              :                                     OutputProcessor::Group::HVAC,
    1728              :                                     OutputProcessor::EndUseCat::Cooling);
    1729            0 :                 SetupOutputVariable(state,
    1730              :                                     "Cooling Coil Evaporative Condenser Mains Supply Water Volume",
    1731              :                                     Constant::Units::m3,
    1732            0 :                                     thisTESCoil.EvapWaterConsump,
    1733              :                                     OutputProcessor::TimeStepType::System,
    1734              :                                     OutputProcessor::StoreType::Sum,
    1735            0 :                                     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            0 :             SetupOutputVariable(state,
    1773              :                                 "Cooling Coil Evaporative Condenser Pump Electricity Rate",
    1774              :                                 Constant::Units::W,
    1775            0 :                                 thisTESCoil.EvapCondPumpElecPower,
    1776              :                                 OutputProcessor::TimeStepType::System,
    1777              :                                 OutputProcessor::StoreType::Average,
    1778            0 :                                 thisTESCoil.Name);
    1779            0 :             SetupOutputVariable(state,
    1780              :                                 "Cooling Coil Evaporative Condenser Pump Electricity Energy",
    1781              :                                 Constant::Units::J,
    1782            0 :                                 thisTESCoil.EvapCondPumpElecConsumption,
    1783              :                                 OutputProcessor::TimeStepType::System,
    1784              :                                 OutputProcessor::StoreType::Sum,
    1785            0 :                                 thisTESCoil.Name,
    1786              :                                 Constant::eResource::Electricity,
    1787              :                                 OutputProcessor::Group::HVAC,
    1788              :                                 OutputProcessor::EndUseCat::Cooling);
    1789              : 
    1790            0 :             SetupOutputVariable(state,
    1791              :                                 "Cooling Coil Basin Heater Electricity Rate",
    1792              :                                 Constant::Units::W,
    1793            0 :                                 thisTESCoil.ElectEvapCondBasinHeaterPower,
    1794              :                                 OutputProcessor::TimeStepType::System,
    1795              :                                 OutputProcessor::StoreType::Average,
    1796            0 :                                 thisTESCoil.Name);
    1797            0 :             SetupOutputVariable(state,
    1798              :                                 "Cooling Coil Basin Heater Electricity Energy",
    1799              :                                 Constant::Units::J,
    1800            0 :                                 thisTESCoil.ElectEvapCondBasinHeaterEnergy,
    1801              :                                 OutputProcessor::TimeStepType::System,
    1802              :                                 OutputProcessor::StoreType::Sum,
    1803            0 :                                 thisTESCoil.Name,
    1804              :                                 Constant::eResource::Electricity,
    1805              :                                 OutputProcessor::Group::HVAC,
    1806              :                                 OutputProcessor::EndUseCat::Cooling,
    1807              :                                 "Thermal Protection");
    1808              :         }
    1809              : 
    1810            0 :         switch (thisTESCoil.StorageMedia) {
    1811            0 :         case MediaType::Water:
    1812              :         case MediaType::UserDefindFluid:
    1813            0 :             SetupOutputVariable(state,
    1814              :                                 "Cooling Coil Fluid Thermal Storage End Temperature",
    1815              :                                 Constant::Units::C,
    1816            0 :                                 thisTESCoil.FluidTankTempFinal,
    1817              :                                 OutputProcessor::TimeStepType::System,
    1818              :                                 OutputProcessor::StoreType::Average,
    1819            0 :                                 thisTESCoil.Name);
    1820            0 :             break;
    1821            0 :         case MediaType::Ice:
    1822            0 :             SetupOutputVariable(state,
    1823              :                                 "Cooling Coil Ice Thermal Storage End Fraction",
    1824              :                                 Constant::Units::None,
    1825            0 :                                 thisTESCoil.IceFracRemain,
    1826              :                                 OutputProcessor::TimeStepType::System,
    1827              :                                 OutputProcessor::StoreType::Average,
    1828            0 :                                 thisTESCoil.Name);
    1829            0 :             break;
    1830            0 :         default:
    1831              :             // nothing
    1832            0 :             break;
    1833              :         }
    1834              :     }
    1835              : 
    1836            0 :     if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    1837            0 :         for (int item = 1; item <= state.dataPackagedThermalStorageCoil->NumTESCoils; ++item) {
    1838            0 :             auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(item);
    1839              :             // setup EMS actuator for control mode
    1840            0 :             SetupEMSActuator(state,
    1841              :                              "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
    1842              :                              thisTESCoil.Name,
    1843              :                              "Operating Mode",
    1844              :                              "[ ]",
    1845            0 :                              thisTESCoil.EMSControlModeOn,
    1846            0 :                              thisTESCoil.EMSControlModeValue);
    1847              :         }
    1848              :     }
    1849            0 : }
    1850              : 
    1851            0 : 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            0 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    1866              : 
    1867            0 :     if (state.dataPackagedThermalStorageCoil->MyOneTimeFlag) {
    1868              :         // initialize the environment and sizing flags
    1869            0 :         state.dataPackagedThermalStorageCoil->MyFlag.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, true);
    1870            0 :         state.dataPackagedThermalStorageCoil->MySizeFlag.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, true);
    1871            0 :         state.dataPackagedThermalStorageCoil->MyEnvrnFlag.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, true);
    1872            0 :         state.dataPackagedThermalStorageCoil->MyWarmupFlag.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, false);
    1873            0 :         state.dataPackagedThermalStorageCoil->MyOneTimeFlag = false;
    1874              :     }
    1875              : 
    1876            0 :     if (state.dataPackagedThermalStorageCoil->MyFlag(TESCoilNum)) {
    1877              : 
    1878            0 :         if (thisTESCoil.TESPlantConnectionAvailable) {
    1879            0 :             bool errFlag = false;
    1880            0 :             PlantLocation plantLoc{};
    1881            0 :             ScanPlantLoopsForObject(state, thisTESCoil.Name, DataPlant::PlantEquipmentType::PackagedTESCoolingCoil, plantLoc, errFlag);
    1882              : 
    1883              :             // double check node names match
    1884            0 :             if (errFlag) {
    1885            0 :                 ShowFatalError(state, "InitTESCoil: Program terminated due to previous condition(s).");
    1886              :             }
    1887            0 :             thisTESCoil.TESPlantLoopNum = plantLoc.loopNum;
    1888            0 :             thisTESCoil.TESPlantLoopSideNum = plantLoc.loopSideNum;
    1889            0 :             thisTESCoil.TESPlantBranchNum = plantLoc.branchNum;
    1890            0 :             thisTESCoil.TESPlantCompNum = plantLoc.compNum;
    1891              : 
    1892            0 :             if ((DataPlant::CompData::getPlantComponent(state, plantLoc).NodeNumIn != thisTESCoil.TESPlantInletNodeNum) ||
    1893            0 :                 (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            0 :             if (errFlag) {
    1913            0 :                 ShowFatalError(state, "InitTESCoil: Program terminated due to previous condition(s).");
    1914              :             }
    1915              : 
    1916              :         } // any plant connection to TES
    1917            0 :         state.dataPackagedThermalStorageCoil->MyFlag(TESCoilNum) = false;
    1918              :     }
    1919              : 
    1920            0 :     if (state.dataPackagedThermalStorageCoil->MySizeFlag(TESCoilNum)) {
    1921              : 
    1922            0 :         SizeTESCoil(state, TESCoilNum);
    1923              : 
    1924            0 :         state.dataPackagedThermalStorageCoil->MySizeFlag(TESCoilNum) = false;
    1925              :     }
    1926              : 
    1927            0 :     if (state.dataGlobal->BeginEnvrnFlag && state.dataPackagedThermalStorageCoil->MyEnvrnFlag(TESCoilNum)) {
    1928            0 :         thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
    1929            0 :         thisTESCoil.QdotPlant = 0.0;
    1930            0 :         thisTESCoil.Q_Plant = 0.0;
    1931            0 :         thisTESCoil.QdotAmbient = 0.0;
    1932            0 :         thisTESCoil.Q_Ambient = 0.0;
    1933            0 :         thisTESCoil.QdotTES = 0.0;
    1934            0 :         thisTESCoil.Q_TES = 0.0;
    1935            0 :         thisTESCoil.TimeElapsed = 0.0;
    1936            0 :         thisTESCoil.IceFracRemain = 0.0;
    1937            0 :         thisTESCoil.IceFracRemainLastTimestep = 0.0;
    1938            0 :         thisTESCoil.FluidTankTempFinal = thisTESCoil.RatedFluidTankTemp;
    1939            0 :         thisTESCoil.FluidTankTempFinalLastTimestep = thisTESCoil.RatedFluidTankTemp;
    1940            0 :         thisTESCoil.ElecCoolingPower = 0.0;     // electric power for cooling [W]
    1941            0 :         thisTESCoil.ElecCoolingEnergy = 0.0;    // electric energy for cooling [J], metered
    1942            0 :         thisTESCoil.EvapTotCoolingRate = 0.0;   // evaporator coil total cooling rate [W]
    1943            0 :         thisTESCoil.EvapTotCoolingEnergy = 0.0; // evaporatory coil total cooling energy [J], metered
    1944            0 :         thisTESCoil.EvapSensCoolingRate = 0.0;
    1945            0 :         thisTESCoil.EvapSensCoolingEnergy = 0.0;
    1946            0 :         thisTESCoil.EvapLatCoolingRate = 0.0;
    1947            0 :         thisTESCoil.EvapLatCoolingEnergy = 0.0;
    1948            0 :         thisTESCoil.RuntimeFraction = 0.0;
    1949            0 :         thisTESCoil.ElectColdWeatherPower = 0.0;  // electric power for cold weather protection [W]
    1950            0 :         thisTESCoil.ElectColdWeatherEnergy = 0.0; // electric energy for cold weather protection [J], metered
    1951            0 :         thisTESCoil.ElectEvapCondBasinHeaterPower = 0.0;
    1952            0 :         thisTESCoil.ElectEvapCondBasinHeaterEnergy = 0.0;
    1953              : 
    1954            0 :         state.dataPackagedThermalStorageCoil->MyEnvrnFlag(TESCoilNum) = false;
    1955              :     }
    1956              : 
    1957            0 :     if (!state.dataGlobal->BeginEnvrnFlag) {
    1958            0 :         state.dataPackagedThermalStorageCoil->MyEnvrnFlag(TESCoilNum) = true;
    1959              :     }
    1960              : 
    1961            0 :     if (state.dataPackagedThermalStorageCoil->MyWarmupFlag(TESCoilNum) && (!state.dataGlobal->WarmupFlag)) {
    1962              :         // reset to initial condition once warm up is over.
    1963            0 :         thisTESCoil.IceFracRemain = 0.0;
    1964            0 :         thisTESCoil.IceFracRemainLastTimestep = 0.0;
    1965            0 :         thisTESCoil.FluidTankTempFinal = thisTESCoil.RatedFluidTankTemp;
    1966            0 :         thisTESCoil.FluidTankTempFinalLastTimestep = thisTESCoil.RatedFluidTankTemp;
    1967            0 :         state.dataPackagedThermalStorageCoil->MyWarmupFlag(TESCoilNum) = false;
    1968              :     }
    1969              : 
    1970            0 :     if (state.dataGlobal->WarmupFlag) {
    1971            0 :         state.dataPackagedThermalStorageCoil->MyWarmupFlag(TESCoilNum) = true;
    1972              :     }
    1973              : 
    1974              :     // determine control mode
    1975            0 :     if (thisTESCoil.availSched->getCurrentVal() != 0.0) {
    1976            0 :         if (thisTESCoil.ModeControlType == PTSCCtrlType::ScheduledOpModes) {
    1977            0 :             Real64 const tmpSchedValue = thisTESCoil.controlModeSched->getCurrentVal();
    1978              :             // check if value is valid
    1979            0 :             if (tmpSchedValue > static_cast<int>(PTSCOperatingMode::Invalid) && tmpSchedValue < static_cast<int>(PTSCOperatingMode::Num)) {
    1980            0 :                 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            0 :         } else if (thisTESCoil.ModeControlType == PTSCCtrlType::EMSActuatedOpModes) {
    1997            0 :             if (thisTESCoil.EMSControlModeOn) {
    1998            0 :                 int const tmpEMSValue = std::floor(thisTESCoil.EMSControlModeValue);
    1999              : 
    2000              :                 // check for invalid value first
    2001            0 :                 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            0 :                     thisTESCoil.CurControlMode = static_cast<PTSCOperatingMode>(tmpEMSValue);
    2017              :                     // but then we need to do some error handling for certain cases
    2018            0 :                     switch (thisTESCoil.CurControlMode) {
    2019            0 :                     case PTSCOperatingMode::Off:
    2020            0 :                         break; // nothing to check
    2021              : 
    2022            0 :                     case PTSCOperatingMode::CoolingOnly:
    2023            0 :                         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            0 :                         break;
    2031            0 :                     case PTSCOperatingMode::CoolingAndCharge:
    2032            0 :                         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            0 :                         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            0 :                     case PTSCOperatingMode::ChargeOnly:
    2050            0 :                         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            0 :                         break;
    2058            0 :                     case PTSCOperatingMode::DischargeOnly:
    2059            0 :                         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            0 :                         break;
    2067            0 :                     default:
    2068              :                         // no need to handle other cases
    2069            0 :                         break;
    2070              :                     }
    2071              :                 }
    2072              : 
    2073              :             } else {
    2074            0 :                 thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
    2075              :             }
    2076              :         }
    2077              :     } else {
    2078            0 :         thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
    2079              :     }
    2080              : 
    2081              :     // update the integer report variable
    2082            0 :     thisTESCoil.curControlModeReport = static_cast<int>(thisTESCoil.CurControlMode);
    2083              : 
    2084            0 :     thisTESCoil.QdotPlant = 0.0;   // heat exchange rate for plant connection to TES tank [W]
    2085            0 :     thisTESCoil.Q_Plant = 0.0;     //  heat exchange energy for plant connection to TES tank [J]
    2086            0 :     thisTESCoil.QdotAmbient = 0.0; // heat exchange rate for skin losses/gains for TES tank to surroundings [W]
    2087            0 :     thisTESCoil.Q_Ambient = 0.0;   // heat exchange enegy for skin losses/gains for TES tank to surroundings [J]
    2088            0 :     thisTESCoil.QdotTES = 0.0;     // heat exchange rate by mechanical systems to charge or discharge TES [W]
    2089            0 :     thisTESCoil.Q_TES = 0.0;       // heat exchange energy by mechanical systems to charge or discharge TES [J]
    2090              : 
    2091              :     // dynamic calculated data
    2092            0 :     thisTESCoil.ElecCoolingPower = 0.0;     // electric power for cooling [W]
    2093            0 :     thisTESCoil.ElecCoolingEnergy = 0.0;    // electric energy for cooling [J], metered
    2094            0 :     thisTESCoil.EvapTotCoolingRate = 0.0;   // evaporator coil total cooling rate [W]
    2095            0 :     thisTESCoil.EvapTotCoolingEnergy = 0.0; // evaporatory coil total cooling energy [J], metered
    2096            0 :     thisTESCoil.EvapSensCoolingRate = 0.0;
    2097            0 :     thisTESCoil.EvapSensCoolingEnergy = 0.0;
    2098            0 :     thisTESCoil.EvapLatCoolingRate = 0.0;
    2099            0 :     thisTESCoil.EvapLatCoolingEnergy = 0.0;
    2100            0 :     thisTESCoil.RuntimeFraction = 0.0;
    2101            0 :     thisTESCoil.CondenserRuntimeFraction = 0.0;
    2102            0 :     thisTESCoil.ElectColdWeatherPower = 0.0;  // electric power for cold weather protection [W]
    2103            0 :     thisTESCoil.ElectColdWeatherEnergy = 0.0; // electric energy for cold weather protection [J], metered
    2104            0 :     thisTESCoil.ElectEvapCondBasinHeaterPower = 0.0;
    2105            0 :     thisTESCoil.ElectEvapCondBasinHeaterEnergy = 0.0;
    2106            0 : }
    2107              : 
    2108            0 : 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            0 :     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            0 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    2145              : 
    2146            0 :     if (thisTESCoil.RatedEvapAirVolFlowRate == AutoSize) {
    2147              : 
    2148            0 :         if (state.dataSize->CurSysNum > 0) {
    2149            0 :             CheckSysSizing(state, "Coil:Cooling:DX:SingleSpeed:ThermalStorage", thisTESCoil.Name);
    2150            0 :             if (state.dataSize->CurOASysNum > 0) {
    2151            0 :                 thisTESCoil.RatedEvapAirVolFlowRate = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesOutAirVolFlow;
    2152              :             } else {
    2153            0 :                 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            0 :         if (thisTESCoil.RatedEvapAirVolFlowRate < HVAC::SmallAirVolFlow) {
    2162            0 :             thisTESCoil.RatedEvapAirVolFlowRate = 0.0;
    2163              :         }
    2164            0 :         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            0 :     thisTESCoil.RatedEvapAirMassFlowRate = state.dataEnvrn->StdRhoAir * thisTESCoil.RatedEvapAirVolFlowRate;
    2172              : 
    2173            0 :     if (thisTESCoil.CondenserAirVolumeFlow == Constant::AutoCalculate) {
    2174            0 :         thisTESCoil.CondenserAirVolumeFlow = thisTESCoil.RatedEvapAirVolFlowRate * thisTESCoil.CondenserAirFlowSizingFactor;
    2175            0 :         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            0 :     thisTESCoil.CondenserAirMassFlow = state.dataEnvrn->StdRhoAir * thisTESCoil.CondenserAirVolumeFlow;
    2183              : 
    2184            0 :     if (thisTESCoil.CoolingOnlyRatedTotCap == AutoSize) {
    2185            0 :         if (state.dataSize->CurSysNum > 0) {
    2186            0 :             CheckSysSizing(state, "Coil:Cooling:DX:SingleSpeed:ThermalStorage", thisTESCoil.Name);
    2187            0 :             VolFlowRate = thisTESCoil.RatedEvapAirVolFlowRate;
    2188            0 :             if (VolFlowRate >= HVAC::SmallAirVolFlow) {
    2189            0 :                 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            0 :                     SupTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).CoolSupTemp;
    2198            0 :                     SupHumRat = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).CoolSupHumRat;
    2199            0 :                     if (state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).NumOACoolCoils ==
    2200              :                         0) { // there is no precooling of the OA stream
    2201            0 :                         MixTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).MixTempAtCoolPeak;
    2202            0 :                         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            0 :                 OutTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).OutTempAtCoolPeak;
    2217            0 :                 rhoair = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, MixTemp, MixHumRat, RoutineName);
    2218            0 :                 MixEnth = PsyHFnTdbW(MixTemp, MixHumRat);
    2219            0 :                 MixWetBulb = PsyTwbFnTdbWPb(state, MixTemp, MixHumRat, state.dataEnvrn->StdBaroPress, RoutineName);
    2220            0 :                 SupEnth = PsyHFnTdbW(SupTemp, SupHumRat);
    2221            0 :                 TotCapTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFTempCurve, MixWetBulb, OutTemp);
    2222            0 :                 CoolCapAtPeak = max(0.0, (rhoair * VolFlowRate * (MixEnth - SupEnth)));
    2223            0 :                 if (TotCapTempModFac > 0.0) {
    2224            0 :                     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            0 :         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            0 :     if (thisTESCoil.CoolingAndChargeModeAvailable && (thisTESCoil.CoolingAndChargeRatedTotCap == Constant::AutoCalculate)) {
    2282            0 :         thisTESCoil.CoolingAndChargeRatedTotCap = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingAndChargeRatedTotCapSizingFactor;
    2283            0 :         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            0 :     if (thisTESCoil.CoolingAndChargeModeAvailable && (thisTESCoil.CoolingAndChargeRatedChargeCap == Constant::AutoCalculate)) {
    2291            0 :         thisTESCoil.CoolingAndChargeRatedChargeCap = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingAndChargeRatedChargeCapSizingFactor;
    2292            0 :         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            0 :     if (thisTESCoil.CoolingAndDischargeModeAvailable && (thisTESCoil.CoolingAndDischargeRatedTotCap == Constant::AutoCalculate)) {
    2300            0 :         thisTESCoil.CoolingAndDischargeRatedTotCap = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingAndDischargeRatedTotCapSizingFactor;
    2301            0 :         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            0 :     if (thisTESCoil.CoolingAndDischargeModeAvailable && (thisTESCoil.CoolingAndDischargeRatedDischargeCap == Constant::AutoCalculate)) {
    2309            0 :         thisTESCoil.CoolingAndDischargeRatedDischargeCap =
    2310            0 :             thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingAndDischargeRatedDischargeCapSizingFactor;
    2311            0 :         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            0 :     if (thisTESCoil.ChargeOnlyModeAvailable && (thisTESCoil.ChargeOnlyRatedCapacity == Constant::AutoCalculate)) {
    2319            0 :         thisTESCoil.ChargeOnlyRatedCapacity = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.ChargeOnlyRatedCapacitySizingFactor;
    2320            0 :         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            0 :     if (thisTESCoil.DischargeOnlyModeAvailable && (thisTESCoil.DischargeOnlyRatedDischargeCap == Constant::AutoCalculate)) {
    2328            0 :         thisTESCoil.DischargeOnlyRatedDischargeCap = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.DischargeOnlyRatedDischargeCapSizingFactor;
    2329            0 :         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            0 :     switch (thisTESCoil.StorageMedia) {
    2337            0 :     case MediaType::UserDefindFluid:
    2338              :     case MediaType::Water:
    2339            0 :         if (thisTESCoil.FluidStorageVolume == Constant::AutoCalculate) {
    2340              : 
    2341              :             // for fluid tanks, assume a 10C deltaT or diff between max and min, whichever is smaller
    2342            0 :             deltaT = min(FluidTankSizingDeltaT, (thisTESCoil.MaximumFluidTankTempLimit - thisTESCoil.MinimumFluidTankTempLimit));
    2343            0 :             rho = thisTESCoil.glycol->getDensity(state, Constant::CWInitConvTemp, calcTESWaterStorageTank);
    2344            0 :             Cp = thisTESCoil.glycol->getSpecificHeat(state, Constant::CWInitConvTemp, calcTESWaterStorageTank);
    2345            0 :             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            0 :                 thisTESCoil.FluidStorageVolume =
    2351            0 :                     (thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.StorageCapacitySizingFactor * Constant::rSecsInHour) / (rho * Cp * deltaT);
    2352              :             }
    2353            0 :             BaseSizer::reportSizerOutput(
    2354              :                 state, "Coil:Cooling:DX:SingleSpeed:ThermalStorage", thisTESCoil.Name, "Fluid Storage Volume [m3]", thisTESCoil.FluidStorageVolume);
    2355              :         }
    2356            0 :         break;
    2357            0 :     case MediaType::Ice:
    2358            0 :         if (thisTESCoil.IceStorageCapacity == Constant::AutoCalculate) {
    2359            0 :             if (thisTESCoil.DischargeOnlyRatedDischargeCap > 0.0 && thisTESCoil.DischargeOnlyModeAvailable) {
    2360            0 :                 thisTESCoil.IceStorageCapacity =
    2361            0 :                     thisTESCoil.DischargeOnlyRatedDischargeCap * thisTESCoil.StorageCapacitySizingFactor * Constant::rSecsInHour;
    2362              :             } else {
    2363            0 :                 thisTESCoil.IceStorageCapacity = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.StorageCapacitySizingFactor * Constant::rSecsInHour;
    2364              :             }
    2365            0 :             BaseSizer::reportSizerOutput(state,
    2366              :                                          "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
    2367              :                                          thisTESCoil.Name,
    2368              :                                          "Ice Storage Capacity [GJ]",
    2369            0 :                                          thisTESCoil.IceStorageCapacity / gigaJoulesToJoules);
    2370              :         }
    2371              :     default:
    2372            0 :         break;
    2373              :     }
    2374              : 
    2375            0 :     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            0 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilType, thisTESCoil.Name, "Coil:Cooling:DX:SingleSpeed:ThermalStorage");
    2385              : 
    2386            0 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilTotCap, thisTESCoil.Name, thisTESCoil.CoolingOnlyRatedTotCap);
    2387            0 :     PreDefTableEntry(state,
    2388            0 :                      state.dataOutRptPredefined->pdchCoolCoilSensCap,
    2389              :                      thisTESCoil.Name,
    2390            0 :                      thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingOnlyRatedSHR);
    2391            0 :     PreDefTableEntry(state,
    2392            0 :                      state.dataOutRptPredefined->pdchCoolCoilLatCap,
    2393              :                      thisTESCoil.Name,
    2394            0 :                      thisTESCoil.CoolingOnlyRatedTotCap - thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingOnlyRatedSHR);
    2395            0 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilSHR, thisTESCoil.Name, thisTESCoil.CoolingOnlyRatedSHR);
    2396            0 :     PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilNomEff, thisTESCoil.Name, thisTESCoil.CoolingOnlyRatedCOP);
    2397            0 : }
    2398              : 
    2399            0 : 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            0 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    2409              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2410              : 
    2411            0 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    2412              : 
    2413              :     // coil is off; just pass through conditions
    2414            0 :     Real64 StandbyAncillaryPower = 0.0;
    2415            0 :     if (thisTESCoil.availSched->getCurrentVal() != 0.0) {
    2416            0 :         StandbyAncillaryPower = thisTESCoil.AncillaryControlsPower;
    2417              :     }
    2418              : 
    2419            0 :     thisTESCoil.ElecCoolingPower = StandbyAncillaryPower;
    2420            0 :     thisTESCoil.ElecCoolingEnergy = StandbyAncillaryPower * TimeStepSysSec;
    2421              : 
    2422            0 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    2423            0 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    2424            0 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
    2425            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    2426            0 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    2427            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    2428            0 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    2429            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    2430            0 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    2431            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
    2432              : 
    2433            0 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    2434            0 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    2435            0 :     state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
    2436            0 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
    2437            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
    2438            0 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    2439            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
    2440            0 :     thisTESCoil.RuntimeFraction = 0.0;
    2441            0 :     thisTESCoil.EvapTotCoolingRate = 0.0;
    2442            0 :     thisTESCoil.EvapTotCoolingEnergy = 0.0;
    2443            0 :     thisTESCoil.EvapSensCoolingRate = 0.0;
    2444            0 :     thisTESCoil.EvapSensCoolingEnergy = 0.0;
    2445            0 :     thisTESCoil.EvapLatCoolingRate = 0.0;
    2446            0 :     thisTESCoil.EvapLatCoolingEnergy = 0.0;
    2447              : 
    2448            0 :     thisTESCoil.QdotTES = 0.0;
    2449            0 :     thisTESCoil.Q_TES = 0.0;
    2450              : 
    2451            0 :     UpdateTEStorage(state, TESCoilNum);
    2452              : 
    2453            0 :     thisTESCoil.CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    2454              : 
    2455            0 :     UpdateColdWeatherProtection(state, TESCoilNum);
    2456              : 
    2457            0 :     if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    2458            0 :         UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
    2459              :     }
    2460            0 : }
    2461              : 
    2462            0 : 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            0 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    2473              : 
    2474              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2475            0 :     int constexpr MaxIter(30);
    2476            0 :     Real64 constexpr RelaxationFactor(0.4);
    2477            0 :     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            0 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    2487              : 
    2488              :     // first deal with condenser
    2489            0 :     if (thisTESCoil.CondenserType == TESCondenserType::Air) {
    2490            0 :         Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
    2491            0 :         if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
    2492            0 :             CondInletTemp = state.dataEnvrn->OutDryBulbTemp;
    2493            0 :             CondInletHumRat = state.dataEnvrn->OutHumRat;
    2494              :         } else {
    2495            0 :             CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    2496            0 :             CondInletHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    2497              :         }
    2498            0 :     } else if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    2499            0 :         Real64 CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
    2500            0 :         Real64 OutdoorDryBulb = 0.0;
    2501            0 :         Real64 OutdoorWetBulb = 0.0;
    2502            0 :         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            0 :             OutdoorDryBulb = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    2508            0 :             Real64 const OutdoorHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    2509            0 :             OutdoorWetBulb = PsyTwbFnTdbWPb(state, OutdoorDryBulb, OutdoorHumRat, CondAirSidePressure, RoutineName);
    2510              :         }
    2511              :         // direct evap cool model
    2512            0 :         CondInletTemp = OutdoorWetBulb + (OutdoorDryBulb - OutdoorWetBulb) * (1.0 - thisTESCoil.EvapCondEffect);
    2513            0 :         CondInletHumRat = PsyWFnTdbTwbPb(state, CondInletTemp, OutdoorWetBulb, CondAirSidePressure, RoutineName);
    2514              :     }
    2515              : 
    2516            0 :     Real64 const EvapAirMassFlow = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    2517              : 
    2518            0 :     if ((EvapAirMassFlow > HVAC::SmallMassFlow) && (PartLoadRatio > 0.0)) { // coil is running
    2519              : 
    2520            0 :         Real64 const EvapInletDryBulb = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    2521            0 :         Real64 const EvapInletHumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    2522            0 :         Real64 const EvapInletWetBulb = PsyTwbFnTdbWPb(state, EvapInletDryBulb, EvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
    2523            0 :         Real64 const EvapInletEnthalpy = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Enthalpy;
    2524              : 
    2525            0 :         Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
    2526            0 :         Real64 TotCapTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFTempCurve, EvapInletWetBulb, CondInletTemp);
    2527            0 :         TotCapTempModFac = max(0.0, TotCapTempModFac); // could warn if negative, DXcoil does
    2528            0 :         Real64 TotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFFlowCurve, AirMassFlowRatio);
    2529            0 :         TotCapFlowModFac = max(0.0, TotCapFlowModFac); // could warn if negative, DXcoil does
    2530            0 :         Real64 TotCap = thisTESCoil.CoolingOnlyRatedTotCap * TotCapTempModFac * TotCapFlowModFac;
    2531              : 
    2532              :         // now see if coil might be running dry
    2533            0 :         Real64 const PartLoadOutAirEnth = EvapInletEnthalpy - (TotCap * PartLoadRatio) / EvapAirMassFlow;
    2534            0 :         Real64 const PartLoadDryCoilOutAirTemp = PsyTdbFnHW(PartLoadOutAirEnth, EvapInletHumRat);
    2535              : 
    2536            0 :         bool CoilMightBeDry = false;
    2537            0 :         Real64 DryCoilTestEvapInletHumRat = 0.0;
    2538            0 :         Real64 SHRadp = 0.0;
    2539            0 :         if (PartLoadDryCoilOutAirTemp > PsyTsatFnHPb(state, PartLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    2540              : 
    2541            0 :             CoilMightBeDry = true;
    2542              :             // find wADP, humidity ratio at apparatus dewpoint and inlet hum rat that would have dry coil
    2543            0 :             DryCoilTestEvapInletHumRat = EvapInletHumRat;
    2544            0 :             Real64 DryCoilTestEvapInletWetBulb = EvapInletWetBulb;
    2545            0 :             int Counter = 0;
    2546            0 :             bool Converged = false;
    2547            0 :             while (!Converged) {
    2548              :                 TotCapTempModFac =
    2549            0 :                     EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFTempCurve, DryCoilTestEvapInletWetBulb, CondInletTemp);
    2550            0 :                 TotCapTempModFac = max(0.0, TotCapTempModFac); // could warn if negative, DXcoil does
    2551              : 
    2552            0 :                 TotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFFlowCurve, AirMassFlowRatio);
    2553            0 :                 TotCapFlowModFac = max(0.0, TotCapFlowModFac); // could warn if negative, DXcoil does
    2554            0 :                 TotCap = thisTESCoil.CoolingOnlyRatedTotCap * TotCapTempModFac * TotCapFlowModFac;
    2555              : 
    2556              :                 // coil bypass factor = 0.0
    2557            0 :                 Real64 const hADP = EvapInletEnthalpy - (TotCap / EvapAirMassFlow);
    2558            0 :                 Real64 const tADP = PsyTsatFnHPb(state, hADP, state.dataEnvrn->OutBaroPress, RoutineName);
    2559            0 :                 Real64 const wADP = min(EvapInletHumRat, PsyWFnTdbH(state, tADP, hADP, RoutineName));
    2560            0 :                 Real64 const hTinwADP = PsyHFnTdbW(EvapInletDryBulb, wADP);
    2561            0 :                 if ((EvapInletEnthalpy - hADP) > 1.e-10) {
    2562            0 :                     SHRadp = min((hTinwADP - hADP) / (EvapInletEnthalpy - hADP), 1.0);
    2563              :                 } else {
    2564            0 :                     SHRadp = 1.0;
    2565              :                 }
    2566              : 
    2567            0 :                 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            0 :                     Converged = true;
    2581              :                 }
    2582              :             }
    2583              :         }
    2584              : 
    2585              :         // total cooling capacity modification factors
    2586            0 :         Real64 const SHRTempFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlySHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb);
    2587            0 :         Real64 const SHRFlowFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlySHRFFlowCurve, AirMassFlowRatio);
    2588              : 
    2589            0 :         Real64 SHR = thisTESCoil.CoolingOnlyRatedSHR * SHRTempFac * SHRFlowFac;
    2590            0 :         SHR = min(SHR, 1.0); // warn maybe
    2591            0 :         SHR = max(SHR, 0.0); // warn maybe
    2592            0 :         if (CoilMightBeDry) {
    2593            0 :             if ((EvapInletHumRat < DryCoilTestEvapInletHumRat) && (SHRadp > SHR)) { // coil is dry for sure
    2594            0 :                 SHR = 1.0;
    2595            0 :             } else if (SHRadp > SHR) {
    2596            0 :                 SHR = SHRadp;
    2597              :             }
    2598              :         }
    2599              : 
    2600              :         // part load factor
    2601            0 :         Real64 const PLF = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyPLFFPLRCurve, PartLoadRatio);
    2602              :         // compressor running time divided by full time of timestep.
    2603            0 :         Real64 RuntimeFraction = 1.0;
    2604            0 :         if (PLF >= PartLoadRatio && PLF > 0.0) {
    2605            0 :             RuntimeFraction = PartLoadRatio / PLF;
    2606              :         } else {
    2607            0 :             RuntimeFraction = 1.0; // warn maybe
    2608              :         }
    2609              :         //  Calculate full load output conditions
    2610            0 :         Real64 const FullLoadOutAirEnth = EvapInletEnthalpy - TotCap / EvapAirMassFlow;
    2611              : 
    2612              :         // Enthalpy at inlet dry-bulb and outlet humidity ratio [J/kg]
    2613            0 :         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            0 :         Real64 FullLoadOutAirHumRat = PsyWFnTdbH(state, EvapInletDryBulb, hTinwout, RoutineName, true);
    2616            0 :         Real64 FullLoadOutAirTemp = PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
    2617              :         // Check for saturation error and modify temperature at constant enthalpy
    2618            0 :         if (FullLoadOutAirTemp < PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    2619            0 :             FullLoadOutAirTemp = PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName);
    2620            0 :             FullLoadOutAirHumRat = PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
    2621              :         }
    2622              : 
    2623              :         // Continuous fan, cycling compressor
    2624            0 :         Real64 const EvapOutletAirEnthalpy = ((PartLoadRatio)*FullLoadOutAirEnth + (1.0 - (PartLoadRatio)) * EvapInletEnthalpy);
    2625            0 :         Real64 EvapOutletAirHumRat = ((PartLoadRatio)*FullLoadOutAirHumRat + (1.0 - (PartLoadRatio)) * EvapInletHumRat);
    2626            0 :         Real64 EvapOutletAirTemp = PsyTdbFnHW(EvapOutletAirEnthalpy, EvapOutletAirHumRat);
    2627            0 :         if (EvapOutletAirTemp < PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName)) {
    2628            0 :             EvapOutletAirTemp = PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName);
    2629            0 :             EvapOutletAirHumRat = PsyWFnTdbH(state, EvapOutletAirTemp, EvapOutletAirEnthalpy, RoutineName);
    2630              :         }
    2631              :         // Calculate electricity consumed. First, get EIR modifying factors for off-rated conditions
    2632            0 :         Real64 EIRTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyEIRFTempCurve, EvapInletWetBulb, CondInletTemp);
    2633            0 :         EIRTempModFac = max(EIRTempModFac, 0.0);
    2634              : 
    2635            0 :         Real64 EIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyEIRFFlowCurve, AirMassFlowRatio);
    2636            0 :         EIRFlowModFac = max(EIRFlowModFac, 0.0);
    2637              : 
    2638            0 :         Real64 const EIR = EIRTempModFac * EIRFlowModFac / thisTESCoil.CoolingOnlyRatedCOP;
    2639              : 
    2640            0 :         Real64 const ElecCoolingPower = TotCap * EIR * RuntimeFraction;
    2641              : 
    2642            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = EvapOutletAirTemp;
    2643            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = EvapOutletAirHumRat;
    2644            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = EvapOutletAirEnthalpy;
    2645            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate = EvapAirMassFlow;
    2646            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    2647            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    2648            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    2649            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    2650              : 
    2651              :         // determine condenser leaving conditions
    2652            0 :         Real64 const QdotCond = TotCap * RuntimeFraction + ElecCoolingPower;
    2653            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    2654            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    2655            0 :         Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
    2656            0 :         Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
    2657            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
    2658            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
    2659            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
    2660              : 
    2661            0 :         thisTESCoil.ElecCoolingPower = ElecCoolingPower + thisTESCoil.AncillaryControlsPower;
    2662            0 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    2663              : 
    2664            0 :         thisTESCoil.RuntimeFraction = RuntimeFraction;
    2665            0 :         thisTESCoil.CondenserRuntimeFraction = RuntimeFraction;
    2666            0 :         thisTESCoil.EvapTotCoolingRate = TotCap * RuntimeFraction; // double check this
    2667            0 :         thisTESCoil.EvapTotCoolingEnergy = TotCap * RuntimeFraction * TimeStepSysSec;
    2668            0 :         Real64 const MinAirHumRat = min(state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat,
    2669            0 :                                         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat);
    2670            0 :         thisTESCoil.EvapSensCoolingRate =
    2671            0 :             EvapAirMassFlow * (PsyHFnTdbW(EvapInletDryBulb, MinAirHumRat) - PsyHFnTdbW(EvapOutletAirTemp, MinAirHumRat));
    2672            0 :         if (thisTESCoil.EvapSensCoolingRate > thisTESCoil.EvapTotCoolingRate) {
    2673            0 :             thisTESCoil.EvapSensCoolingRate = thisTESCoil.EvapTotCoolingRate;
    2674              :         }
    2675            0 :         thisTESCoil.EvapSensCoolingEnergy = thisTESCoil.EvapSensCoolingRate * TimeStepSysSec;
    2676            0 :         thisTESCoil.EvapLatCoolingRate = thisTESCoil.EvapTotCoolingRate - thisTESCoil.EvapSensCoolingRate;
    2677            0 :         thisTESCoil.EvapLatCoolingEnergy = thisTESCoil.EvapLatCoolingRate * TimeStepSysSec;
    2678              : 
    2679            0 :     } else { // coil is off; just pass through conditions
    2680            0 :         thisTESCoil.ElecCoolingPower = thisTESCoil.AncillaryControlsPower;
    2681            0 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    2682            0 :         thisTESCoil.RuntimeFraction = 0.0;
    2683            0 :         thisTESCoil.CondenserRuntimeFraction = 0.0;
    2684            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    2685            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    2686            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
    2687            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    2688            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    2689            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    2690            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    2691            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    2692            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    2693            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
    2694              : 
    2695            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    2696            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    2697            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
    2698            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
    2699            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
    2700            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    2701            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
    2702            0 :         thisTESCoil.EvapTotCoolingRate = 0.0;
    2703            0 :         thisTESCoil.EvapTotCoolingEnergy = 0.0;
    2704            0 :         thisTESCoil.EvapSensCoolingRate = 0.0;
    2705            0 :         thisTESCoil.EvapSensCoolingEnergy = 0.0;
    2706            0 :         thisTESCoil.EvapLatCoolingRate = 0.0;
    2707            0 :         thisTESCoil.EvapLatCoolingEnergy = 0.0;
    2708              :     }
    2709              : 
    2710            0 :     thisTESCoil.QdotTES = 0.0;
    2711            0 :     thisTESCoil.Q_TES = 0.0;
    2712              : 
    2713            0 :     UpdateTEStorage(state, TESCoilNum);
    2714              : 
    2715            0 :     thisTESCoil.CondInletTemp = CondInletTemp;
    2716              : 
    2717            0 :     UpdateColdWeatherProtection(state, TESCoilNum);
    2718              : 
    2719            0 :     if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    2720            0 :         UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
    2721            0 :         UpdateEvaporativeCondenserWaterUse(state, TESCoilNum, CondInletHumRat, thisTESCoil.CondAirInletNodeNum);
    2722              :     }
    2723            0 : }
    2724              : 
    2725            0 : 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            0 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    2739              : 
    2740              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2741            0 :     int constexpr MaxIter(30);
    2742            0 :     Real64 constexpr RelaxationFactor(0.4);
    2743            0 :     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            0 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    2753              : 
    2754              :     // first deal with condenser
    2755            0 :     if (thisTESCoil.CondenserType == TESCondenserType::Air) {
    2756            0 :         Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
    2757            0 :         if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
    2758            0 :             CondInletTemp = state.dataEnvrn->OutDryBulbTemp;
    2759            0 :             CondInletHumRat = state.dataEnvrn->OutHumRat;
    2760              :         } else {
    2761            0 :             CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    2762            0 :             CondInletHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    2763              :         }
    2764            0 :     } else if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    2765            0 :         Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
    2766            0 :         Real64 OutdoorDryBulb = 0.0;
    2767            0 :         Real64 OutdoorWetBulb = 0.0;
    2768            0 :         if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
    2769            0 :             OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
    2770            0 :             OutdoorWetBulb = state.dataEnvrn->OutWetBulbTemp;
    2771              :         } else {
    2772            0 :             OutdoorDryBulb = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    2773            0 :             Real64 const OutdoorHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    2774            0 :             OutdoorWetBulb = PsyTwbFnTdbWPb(state, OutdoorDryBulb, OutdoorHumRat, CondAirSidePressure, RoutineName);
    2775              :         }
    2776              :         // direct evap cool model
    2777            0 :         CondInletTemp = OutdoorWetBulb + (OutdoorDryBulb - OutdoorWetBulb) * (1.0 - thisTESCoil.EvapCondEffect);
    2778            0 :         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            0 :     switch (state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).StorageMedia) {
    2786            0 :     case MediaType::Water:
    2787              :     case MediaType::UserDefindFluid:
    2788            0 :         sTES = thisTESCoil.FluidTankTempFinalLastTimestep;
    2789            0 :         if ((sTES > thisTESCoil.MinimumFluidTankTempLimit) && (sTES < thisTESCoil.MaximumFluidTankTempLimit)) {
    2790            0 :             TESCanBeCharged = true;
    2791              :             // find charge limit to reach limits
    2792            0 :             Real64 const rho = thisTESCoil.glycol->getDensity(state, sTES, RoutineName);
    2793            0 :             Real64 const TankMass = rho * thisTESCoil.FluidStorageVolume;
    2794            0 :             Real64 const CpTank = thisTESCoil.glycol->getSpecificHeat(state, sTES, RoutineName);
    2795              :             // simple linear approximation of DT/Dt term in McpDT/Dt
    2796            0 :             QdotChargeLimit = TankMass * CpTank * (sTES - thisTESCoil.MinimumFluidTankTempLimit) / TimeStepSysSec;
    2797            0 :         } else {
    2798            0 :             TESCanBeCharged = false;
    2799              :         }
    2800            0 :         break;
    2801            0 :     case MediaType::Ice:
    2802            0 :         sTES = thisTESCoil.IceFracRemainLastTimestep;
    2803            0 :         if (sTES < 1.0) {
    2804            0 :             TESCanBeCharged = true;
    2805              :             // find charge limit to reach limit
    2806            0 :             QdotChargeLimit = (1.0 - sTES) * thisTESCoil.IceStorageCapacity / TimeStepSysSec;
    2807              :         } else {
    2808            0 :             TESCanBeCharged = false;
    2809              :         }
    2810            0 :         break;
    2811            0 :     default:
    2812            0 :         break;
    2813              :     }
    2814              : 
    2815              :     // local for evaporator air mass flow [kg/s]
    2816            0 :     Real64 const EvapAirMassFlow = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    2817              :     // evaporator inlet air drybulb [C]
    2818            0 :     Real64 const EvapInletDryBulb = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    2819              :     // evaporator inlet air humidity ratio [kg/kg]
    2820            0 :     Real64 const EvapInletHumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    2821              :     // evaporator inlet air wetbulb [C]
    2822            0 :     Real64 const EvapInletWetBulb = PsyTwbFnTdbWPb(state, EvapInletDryBulb, EvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
    2823              : 
    2824            0 :     Real64 TotChargeCap = 0.0;
    2825              : 
    2826            0 :     if ((EvapAirMassFlow > HVAC::SmallMassFlow) && (PartLoadRatio > 0.0)) { // coil is running
    2827              : 
    2828            0 :         Real64 const EvapInletEnthalpy = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Enthalpy;
    2829              : 
    2830              :         // evaporator inlet air mass flow divided by design mass flow [ ]
    2831            0 :         Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
    2832              : 
    2833              :         // total cooling capacity modification factor due to temps []
    2834              :         Real64 EvapTotCapTempModFac =
    2835            0 :             EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    2836            0 :         EvapTotCapTempModFac = max(0.0, EvapTotCapTempModFac); // could warn if negative, DXcoil does
    2837              : 
    2838              :         // total cooling capacity modification factor due to flow []
    2839            0 :         Real64 EvapTotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingCapFFlowCurve, AirMassFlowRatio);
    2840            0 :         EvapTotCapFlowModFac = max(0.0, EvapTotCapFlowModFac); // could warn if negative, DXcoil does
    2841              : 
    2842              :         // total cooling capacity
    2843            0 :         Real64 EvapTotCap = thisTESCoil.CoolingAndChargeRatedTotCap * EvapTotCapTempModFac * EvapTotCapFlowModFac;
    2844              : 
    2845              :         // now see if coil is running dry
    2846            0 :         Real64 const PartLoadOutAirEnth = EvapInletEnthalpy - (EvapTotCap * PartLoadRatio) / EvapAirMassFlow;
    2847            0 :         Real64 const PartLoadDryCoilOutAirTemp = PsyTdbFnHW(PartLoadOutAirEnth, EvapInletHumRat);
    2848              : 
    2849            0 :         bool CoilMightBeDry = false;
    2850            0 :         Real64 DryCoilTestEvapInletHumRat = 0.0;
    2851            0 :         Real64 SHRadp = 0.0;
    2852            0 :         if (PartLoadDryCoilOutAirTemp > PsyTsatFnHPb(state, PartLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    2853            0 :             CoilMightBeDry = true;
    2854              :             // find wADP, humidity ratio at apparatus dewpoint and inlet hum rat that would have dry coil
    2855            0 :             DryCoilTestEvapInletHumRat = EvapInletHumRat;
    2856            0 :             Real64 DryCoilTestEvapInletWetBulb = EvapInletWetBulb;
    2857            0 :             int Counter = 0;
    2858            0 :             bool Converged = false;
    2859            0 :             while (!Converged) {
    2860            0 :                 EvapTotCapTempModFac = EnergyPlus::Curve::CurveValue(
    2861              :                     state, thisTESCoil.CoolingAndChargeCoolingCapFTempCurve, DryCoilTestEvapInletWetBulb, CondInletTemp, sTES);
    2862            0 :                 EvapTotCapTempModFac = max(0.0, EvapTotCapTempModFac); // could warn if negative, DXcoil does
    2863            0 :                 EvapTotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingCapFFlowCurve, AirMassFlowRatio);
    2864            0 :                 EvapTotCapFlowModFac = max(0.0, EvapTotCapFlowModFac); // could warn if negative, DXcoil does
    2865            0 :                 EvapTotCap = thisTESCoil.CoolingAndChargeRatedTotCap * EvapTotCapTempModFac * EvapTotCapFlowModFac;
    2866              :                 // coil bypass factor = 0.0
    2867            0 :                 Real64 const hADP = EvapInletEnthalpy - (EvapTotCap / EvapAirMassFlow);
    2868            0 :                 Real64 const tADP = PsyTsatFnHPb(state, hADP, state.dataEnvrn->OutBaroPress, RoutineName);
    2869            0 :                 Real64 const wADP = min(EvapInletHumRat, PsyWFnTdbH(state, tADP, hADP, RoutineName));
    2870            0 :                 Real64 const hTinwADP = PsyHFnTdbW(EvapInletDryBulb, wADP);
    2871            0 :                 if ((EvapInletEnthalpy - hADP) > 1.e-10) {
    2872            0 :                     SHRadp = min((hTinwADP - hADP) / (EvapInletEnthalpy - hADP), 1.0);
    2873              :                 } else {
    2874            0 :                     SHRadp = 1.0;
    2875              :                 }
    2876              : 
    2877            0 :                 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            0 :                     Converged = true;
    2891              :                 }
    2892              :             }
    2893              :         }
    2894              : 
    2895              :         // total cooling capacity modification factors
    2896              :         Real64 const SHRTempFac =
    2897            0 :             (state.dataCurveManager->curves(thisTESCoil.CoolingAndChargeSHRFTempCurve)->numDims == 2)
    2898            0 :                 ? EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeSHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb)
    2899            0 :                 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeSHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb, sTES);
    2900            0 :         Real64 const SHRFlowFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeSHRFFlowCurve, AirMassFlowRatio);
    2901            0 :         Real64 SHR = thisTESCoil.CoolingAndChargeRatedSHR * SHRTempFac * SHRFlowFac;
    2902            0 :         SHR = min(SHR, 1.0); // warn maybe
    2903            0 :         SHR = max(SHR, 0.0); // warn maybe
    2904            0 :         if (CoilMightBeDry) {
    2905            0 :             if ((EvapInletHumRat < DryCoilTestEvapInletHumRat) && (SHRadp > SHR)) { // coil is dry for sure
    2906            0 :                 SHR = 1.0;
    2907            0 :             } else if (SHRadp > SHR) {
    2908            0 :                 SHR = SHRadp;
    2909              :             }
    2910              :         }
    2911              : 
    2912              :         // part load factor
    2913            0 :         Real64 const PLF = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingPLFFPLRCurve, PartLoadRatio);
    2914              :         // compressor running time divided by full time of timestep.
    2915            0 :         Real64 EvapRuntimeFraction = 1.0;
    2916            0 :         if (PLF >= PartLoadRatio && PLF > 0.0) {
    2917            0 :             EvapRuntimeFraction = PartLoadRatio / PLF;
    2918              :         } else {
    2919            0 :             EvapRuntimeFraction = 1.0; // warn maybe
    2920              :         }
    2921              : 
    2922              :         // Calculate electricity consumed. First, get EIR modifying factors for off-rated conditions
    2923              :         Real64 EIRTempModFac =
    2924            0 :             EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    2925            0 :         EIRTempModFac = max(EIRTempModFac, 0.0);
    2926              : 
    2927            0 :         Real64 EIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingEIRFFlowCurve, AirMassFlowRatio);
    2928            0 :         EIRFlowModFac = max(EIRFlowModFac, 0.0);
    2929              : 
    2930            0 :         Real64 const EIR = EIRTempModFac * EIRFlowModFac / thisTESCoil.CoolingAndChargeCoolingRatedCOP;
    2931              : 
    2932            0 :         Real64 const EvapElecCoolingPower = EvapTotCap * EIR * EvapRuntimeFraction;
    2933              : 
    2934            0 :         TotChargeCap = 0.0;
    2935            0 :         Real64 ChargeRuntimeFraction = 0.0;
    2936            0 :         Real64 ChargeElectricCoolingPower = 0.0;
    2937            0 :         if (TESCanBeCharged) {
    2938              :             Real64 ChargeCapModFac =
    2939            0 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    2940            0 :             ChargeCapModFac = max(0.0, ChargeCapModFac);
    2941              : 
    2942            0 :             Real64 ChargeCapPLRModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingCapFEvapPLRCurve, PartLoadRatio);
    2943            0 :             ChargeCapPLRModFac = max(0.0, ChargeCapPLRModFac);
    2944              : 
    2945            0 :             TotChargeCap = thisTESCoil.CoolingAndChargeRatedChargeCap * ChargeCapModFac * ChargeCapPLRModFac;
    2946            0 :             if (TotChargeCap > QdotChargeLimit) {
    2947            0 :                 ChargeRuntimeFraction = QdotChargeLimit / TotChargeCap;
    2948            0 :                 TotChargeCap = min(TotChargeCap, QdotChargeLimit);
    2949              :             } else {
    2950            0 :                 ChargeRuntimeFraction = 1.0;
    2951              :             }
    2952              :             Real64 ChargeEIRTempModFac =
    2953            0 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    2954            0 :             ChargeEIRTempModFac = max(0.0, ChargeEIRTempModFac);
    2955              : 
    2956            0 :             Real64 ChargeEIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingEIRFFLowCurve, AirMassFlowRatio);
    2957            0 :             ChargeEIRFlowModFac = max(0.0, ChargeEIRFlowModFac);
    2958              : 
    2959            0 :             Real64 const ChargeEIR = (ChargeEIRTempModFac * ChargeEIRFlowModFac) / thisTESCoil.CoolingAndChargeChargingRatedCOP;
    2960            0 :             ChargeElectricCoolingPower = TotChargeCap * ChargeEIR;
    2961            0 :             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            0 :         Real64 const FullLoadOutAirEnth = EvapInletEnthalpy - EvapTotCap / EvapAirMassFlow;
    2971              : 
    2972            0 :         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            0 :         Real64 FullLoadOutAirHumRat = PsyWFnTdbH(state, EvapInletDryBulb, hTinwout, RoutineName, true);
    2975            0 :         Real64 FullLoadOutAirTemp = PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
    2976              :         // Check for saturation error and modify temperature at constant enthalpy
    2977            0 :         if (FullLoadOutAirTemp < PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    2978            0 :             FullLoadOutAirTemp = PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName);
    2979            0 :             FullLoadOutAirHumRat = PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
    2980              :         }
    2981              : 
    2982              :         // Continuous fan, cycling compressor
    2983            0 :         Real64 const EvapOutletAirEnthalpy = ((PartLoadRatio)*FullLoadOutAirEnth + (1.0 - (PartLoadRatio)) * EvapInletEnthalpy);
    2984            0 :         Real64 EvapOutletAirHumRat = ((PartLoadRatio)*FullLoadOutAirHumRat + (1.0 - (PartLoadRatio)) * EvapInletHumRat);
    2985            0 :         Real64 EvapOutletAirTemp = PsyTdbFnHW(EvapOutletAirEnthalpy, EvapOutletAirHumRat);
    2986            0 :         if (EvapOutletAirTemp < PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName)) {
    2987            0 :             EvapOutletAirTemp = PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName);
    2988            0 :             EvapOutletAirHumRat = PsyWFnTdbH(state, EvapOutletAirTemp, EvapOutletAirEnthalpy, RoutineName);
    2989              :         }
    2990              : 
    2991            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = EvapOutletAirTemp;
    2992            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = EvapOutletAirHumRat;
    2993            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = EvapOutletAirEnthalpy;
    2994            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate = EvapAirMassFlow;
    2995            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    2996            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    2997            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    2998            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    2999              : 
    3000              :         // determine condenser leaving conditions
    3001              :         // condenser total heat rejection rate [W]
    3002            0 :         Real64 const QdotCond = EvapTotCap * EvapRuntimeFraction + EvapElecCoolingPower + TotChargeCap + ChargeElectricCoolingPower;
    3003            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3004            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3005              :         // condenser inlet enthalpy [J/kg]
    3006            0 :         Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
    3007            0 :         Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
    3008            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
    3009            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
    3010            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
    3011              : 
    3012            0 :         thisTESCoil.ElecCoolingPower = EvapElecCoolingPower + ChargeElectricCoolingPower + thisTESCoil.AncillaryControlsPower;
    3013            0 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3014              : 
    3015            0 :         thisTESCoil.RuntimeFraction = EvapRuntimeFraction;
    3016            0 :         if (ChargeRuntimeFraction > 0.0) {
    3017            0 :             thisTESCoil.CondenserRuntimeFraction = max(ChargeRuntimeFraction, EvapRuntimeFraction);
    3018              :         } else {
    3019            0 :             thisTESCoil.CondenserRuntimeFraction = EvapRuntimeFraction;
    3020              :         }
    3021              : 
    3022            0 :         thisTESCoil.EvapTotCoolingRate = EvapTotCap * EvapRuntimeFraction; // double check this
    3023            0 :         thisTESCoil.EvapTotCoolingEnergy = EvapTotCap * EvapRuntimeFraction * TimeStepSysSec;
    3024            0 :         Real64 const MinAirHumRat = min(state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat,
    3025            0 :                                         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat);
    3026            0 :         thisTESCoil.EvapSensCoolingRate =
    3027            0 :             EvapAirMassFlow * (PsyHFnTdbW(EvapInletDryBulb, MinAirHumRat) - PsyHFnTdbW(EvapOutletAirTemp, MinAirHumRat));
    3028            0 :         if (thisTESCoil.EvapSensCoolingRate > thisTESCoil.EvapTotCoolingRate) {
    3029            0 :             thisTESCoil.EvapSensCoolingRate = thisTESCoil.EvapTotCoolingRate;
    3030              :         }
    3031            0 :         thisTESCoil.EvapSensCoolingEnergy = thisTESCoil.EvapSensCoolingRate * TimeStepSysSec;
    3032            0 :         thisTESCoil.EvapLatCoolingRate = thisTESCoil.EvapTotCoolingRate - thisTESCoil.EvapSensCoolingRate;
    3033            0 :         thisTESCoil.EvapLatCoolingEnergy = thisTESCoil.EvapLatCoolingRate * TimeStepSysSec;
    3034              : 
    3035            0 :     } else { // Evap off, but may still charge
    3036              : 
    3037            0 :         TotChargeCap = 0.0;
    3038            0 :         Real64 ChargeElectricCoolingPower = 0.0;
    3039            0 :         Real64 ChargeRuntimeFraction = 0.0;
    3040            0 :         if (TESCanBeCharged) { // coil is running to charge but not to cool at evaporator
    3041            0 :             Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
    3042              :             Real64 ChargeCapModFac =
    3043            0 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    3044            0 :             ChargeCapModFac = max(0.0, ChargeCapModFac);
    3045              : 
    3046            0 :             Real64 ChargeCapPLRModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingCapFEvapPLRCurve, PartLoadRatio);
    3047            0 :             ChargeCapPLRModFac = max(0.0, ChargeCapPLRModFac);
    3048              : 
    3049            0 :             TotChargeCap = thisTESCoil.CoolingAndChargeRatedChargeCap * ChargeCapModFac * ChargeCapPLRModFac;
    3050            0 :             ChargeRuntimeFraction = 1.0;
    3051            0 :             if (TotChargeCap > QdotChargeLimit) {
    3052            0 :                 ChargeRuntimeFraction = QdotChargeLimit / TotChargeCap;
    3053            0 :                 TotChargeCap = min(TotChargeCap, QdotChargeLimit);
    3054              :             }
    3055              :             Real64 ChargeEIRTempModFac =
    3056            0 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    3057            0 :             ChargeEIRTempModFac = max(0.0, ChargeEIRTempModFac);
    3058              : 
    3059            0 :             Real64 ChargeEIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingEIRFFLowCurve, AirMassFlowRatio);
    3060            0 :             ChargeEIRFlowModFac = max(0.0, ChargeEIRFlowModFac);
    3061              : 
    3062            0 :             Real64 const ChargeEIR = (ChargeEIRTempModFac * ChargeEIRFlowModFac) / thisTESCoil.CoolingAndChargeChargingRatedCOP;
    3063            0 :             ChargeElectricCoolingPower = TotChargeCap * ChargeEIR;
    3064            0 :             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            0 :         thisTESCoil.ElecCoolingPower = ChargeElectricCoolingPower + thisTESCoil.AncillaryControlsPower;
    3073            0 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3074              : 
    3075            0 :         thisTESCoil.RuntimeFraction = 0.0;
    3076            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    3077            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    3078            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
    3079            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    3080            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    3081            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    3082            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    3083            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    3084            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    3085            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
    3086              : 
    3087            0 :         thisTESCoil.EvapTotCoolingRate = 0.0;
    3088            0 :         thisTESCoil.EvapTotCoolingEnergy = 0.0;
    3089            0 :         thisTESCoil.EvapSensCoolingRate = 0.0;
    3090            0 :         thisTESCoil.EvapSensCoolingEnergy = 0.0;
    3091            0 :         thisTESCoil.EvapLatCoolingRate = 0.0;
    3092            0 :         thisTESCoil.EvapLatCoolingEnergy = 0.0;
    3093              : 
    3094            0 :         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            0 :             Real64 const QdotCond = TotChargeCap + ChargeElectricCoolingPower;
    3107            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3108            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3109            0 :             Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
    3110            0 :             Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
    3111            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
    3112            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
    3113            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
    3114            0 :             thisTESCoil.CondenserRuntimeFraction = 1.0;
    3115              :         }
    3116              :     }
    3117              : 
    3118            0 :     thisTESCoil.QdotTES = -TotChargeCap;
    3119            0 :     thisTESCoil.Q_TES = thisTESCoil.QdotTES * TimeStepSysSec;
    3120              : 
    3121            0 :     UpdateTEStorage(state, TESCoilNum);
    3122              : 
    3123            0 :     thisTESCoil.CondInletTemp = CondInletTemp;
    3124              : 
    3125            0 :     UpdateColdWeatherProtection(state, TESCoilNum);
    3126              : 
    3127            0 :     if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    3128            0 :         UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
    3129            0 :         UpdateEvaporativeCondenserWaterUse(state, TESCoilNum, CondInletHumRat, thisTESCoil.CondAirInletNodeNum);
    3130              :     }
    3131            0 : }
    3132              : 
    3133            0 : 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            0 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    3147              : 
    3148              :     // SUBROUTINE PARAMETER DEFINITIONS:
    3149            0 :     int constexpr MaxIter(30);
    3150            0 :     Real64 constexpr RelaxationFactor(0.4);
    3151            0 :     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            0 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    3161              : 
    3162              :     // first deal with condenser
    3163            0 :     if (thisTESCoil.CondenserType == TESCondenserType::Air) {
    3164            0 :         Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
    3165            0 :         if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
    3166            0 :             CondInletTemp = state.dataEnvrn->OutDryBulbTemp;
    3167            0 :             CondInletHumRat = state.dataEnvrn->OutHumRat;
    3168              :         } else {
    3169            0 :             CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3170            0 :             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            0 :     bool TESHasSomeCharge = false;
    3192              : 
    3193            0 :     switch (thisTESCoil.StorageMedia) {
    3194            0 :     case MediaType::Water:
    3195              :     case MediaType::UserDefindFluid:
    3196            0 :         sTES = thisTESCoil.FluidTankTempFinalLastTimestep;
    3197            0 :         if ((sTES >= thisTESCoil.MinimumFluidTankTempLimit) && (sTES < thisTESCoil.MaximumFluidTankTempLimit)) {
    3198            0 :             TESHasSomeCharge = true;
    3199            0 :             Real64 const rho = thisTESCoil.glycol->getDensity(state, sTES, RoutineName);
    3200            0 :             Real64 const TankMass = rho * thisTESCoil.FluidStorageVolume;
    3201            0 :             Real64 const CpTank = thisTESCoil.glycol->getSpecificHeat(state, sTES, RoutineName);
    3202              :             // simple linear approximation of DT/Dt term in McpDT/Dt
    3203            0 :             QdotDischargeLimit = TankMass * CpTank * (thisTESCoil.MaximumFluidTankTempLimit - sTES) / TimeStepSysSec;
    3204            0 :         } else {
    3205            0 :             TESHasSomeCharge = false;
    3206              :         }
    3207            0 :         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            0 :     Real64 const EvapAirMassFlow = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    3223              : 
    3224            0 :     if ((EvapAirMassFlow > HVAC::SmallMassFlow) && (PartLoadRatio > 0.0)) { // coil is running
    3225              : 
    3226            0 :         Real64 const EvapInletDryBulb = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    3227            0 :         Real64 const EvapInletHumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    3228            0 :         Real64 const EvapInletWetBulb = PsyTwbFnTdbWPb(state, EvapInletDryBulb, EvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
    3229            0 :         Real64 const EvapInletEnthalpy = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Enthalpy;
    3230              : 
    3231              :         // evaporator inlet air mass flow divided by design mass flow [ ]
    3232            0 :         Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
    3233              : 
    3234              :         // total cooling capacity modification factor due to temps []
    3235              :         Real64 EvapTotCapTempModFac =
    3236            0 :             EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    3237            0 :         EvapTotCapTempModFac = max(0.0, EvapTotCapTempModFac); // could warn if negative, DXcoil does
    3238              : 
    3239              :         // total cooling capacity modification factor due to flow []
    3240            0 :         Real64 EvapTotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingCapFFlowCurve, AirMassFlowRatio);
    3241            0 :         EvapTotCapFlowModFac = max(0.0, EvapTotCapFlowModFac); // could warn if negative, DXcoil does
    3242              : 
    3243              :         // total cooling capacity
    3244            0 :         Real64 EvapTotCap = thisTESCoil.CoolingAndDischargeRatedTotCap * EvapTotCapTempModFac * EvapTotCapFlowModFac;
    3245              : 
    3246              :         // now see if coil is running dry
    3247            0 :         Real64 const PartLoadOutAirEnth = EvapInletEnthalpy - (EvapTotCap * PartLoadRatio) / EvapAirMassFlow;
    3248            0 :         Real64 const PartLoadDryCoilOutAirTemp = PsyTdbFnHW(PartLoadOutAirEnth, EvapInletHumRat);
    3249              : 
    3250            0 :         bool CoilMightBeDry = false;
    3251            0 :         Real64 DryCoilTestEvapInletHumRat = 0.0;
    3252            0 :         Real64 SHRadp = 0.0;
    3253              : 
    3254            0 :         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            0 :             (state.dataCurveManager->curves(thisTESCoil.CoolingAndDischargeSHRFTempCurve)->numDims == 2)
    3300            0 :                 ? EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeSHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb)
    3301            0 :                 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeSHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb, sTES);
    3302            0 :         Real64 const SHRFlowFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeSHRFFlowCurve, AirMassFlowRatio);
    3303            0 :         Real64 SHR = thisTESCoil.CoolingAndDischargeRatedSHR * SHRTempFac * SHRFlowFac;
    3304            0 :         SHR = min(SHR, 1.0); // warn maybe
    3305            0 :         SHR = max(SHR, 0.0); // warn maybe
    3306            0 :         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            0 :         Real64 const PLF = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingPLFFPLRCurve, PartLoadRatio);
    3315              :         // compressor running time divided by full time of timestep.
    3316            0 :         Real64 EvapRuntimeFraction = 1.0;
    3317            0 :         if (PLF >= PartLoadRatio && PLF > 0.0) {
    3318            0 :             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            0 :             EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    3325            0 :         EIRTempModFac = max(EIRTempModFac, 0.0);
    3326              : 
    3327            0 :         Real64 EIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingEIRFFlowCurve, AirMassFlowRatio);
    3328            0 :         EIRFlowModFac = max(EIRFlowModFac, 0.0);
    3329              : 
    3330            0 :         Real64 const EIR = EIRTempModFac * EIRFlowModFac / thisTESCoil.CoolingAndDischargeCoolingRatedCOP;
    3331              : 
    3332            0 :         Real64 const EvapElecCoolingPower = EvapTotCap * EIR * EvapRuntimeFraction;
    3333              : 
    3334            0 :         Real64 TotDischargeCap = 0.0;
    3335            0 :         Real64 DischargeRuntimeFraction = 0.0;
    3336            0 :         Real64 DischargeElectricCoolingPower = 0.0;
    3337            0 :         if (TESHasSomeCharge) {
    3338              :             Real64 DischargeCapTempModFac =
    3339            0 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    3340            0 :             DischargeCapTempModFac = max(0.0, DischargeCapTempModFac);
    3341              :             Real64 DischargeCapFlowModFac =
    3342            0 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingCapFFlowCurve, AirMassFlowRatio);
    3343            0 :             DischargeCapFlowModFac = max(0.0, DischargeCapFlowModFac);
    3344              : 
    3345              :             Real64 const DischargePLF =
    3346            0 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingCapFEvapPLRCurve, PartLoadRatio);
    3347            0 :             if (DischargePLF >= PartLoadRatio && DischargePLF > 0.0) {
    3348            0 :                 DischargeRuntimeFraction = PartLoadRatio / DischargePLF;
    3349              :             } else {
    3350            0 :                 DischargeRuntimeFraction = 1.0; // warn maybe
    3351              :             }
    3352              : 
    3353            0 :             TotDischargeCap =
    3354            0 :                 thisTESCoil.CoolingAndDischargeRatedDischargeCap * DischargeCapTempModFac * DischargeCapFlowModFac * DischargeRuntimeFraction;
    3355            0 :             if (TotDischargeCap > QdotDischargeLimit) {
    3356            0 :                 TotDischargeCap = min(TotDischargeCap, QdotDischargeLimit);
    3357              :             }
    3358              :             Real64 DischargeEIRTempModFac =
    3359            0 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
    3360            0 :             DischargeEIRTempModFac = max(0.0, DischargeEIRTempModFac);
    3361              : 
    3362              :             Real64 DischargeEIRFlowModFac =
    3363            0 :                 EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingEIRFFLowCurve, AirMassFlowRatio);
    3364            0 :             DischargeEIRFlowModFac = max(0.0, DischargeEIRFlowModFac);
    3365              : 
    3366            0 :             Real64 const DischargeEIR = (DischargeEIRTempModFac * DischargeEIRFlowModFac) / thisTESCoil.CoolingAndDischargeDischargingRatedCOP;
    3367            0 :             DischargeElectricCoolingPower = TotDischargeCap * DischargeEIR * DischargeRuntimeFraction;
    3368            0 :             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            0 :         Real64 const TotCap = EvapTotCap + TotDischargeCap;
    3377              :         //  Calculate full load output conditions
    3378              : 
    3379            0 :         Real64 const hTinwout = EvapInletEnthalpy - (1.0 - SHR) * (TotCap / EvapAirMassFlow);
    3380            0 :         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            0 :         Real64 FullLoadOutAirHumRat = PsyWFnTdbH(state, EvapInletDryBulb, hTinwout, RoutineName, true);
    3383            0 :         Real64 FullLoadOutAirTemp = PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
    3384              :         // Check for saturation error and modify temperature at constant enthalpy
    3385            0 :         if (FullLoadOutAirTemp < PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    3386            0 :             FullLoadOutAirTemp = PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName);
    3387            0 :             FullLoadOutAirHumRat = PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
    3388              :         }
    3389              :         // Continuous fan, cycling compressor
    3390            0 :         Real64 const EvapOutletAirEnthalpy = ((PartLoadRatio)*FullLoadOutAirEnth + (1.0 - (PartLoadRatio)) * EvapInletEnthalpy);
    3391            0 :         Real64 EvapOutletAirHumRat = ((PartLoadRatio)*FullLoadOutAirHumRat + (1.0 - (PartLoadRatio)) * EvapInletHumRat);
    3392            0 :         Real64 EvapOutletAirTemp = PsyTdbFnHW(EvapOutletAirEnthalpy, EvapOutletAirHumRat);
    3393            0 :         if (EvapOutletAirTemp < PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName)) {
    3394            0 :             EvapOutletAirTemp = PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName);
    3395            0 :             EvapOutletAirHumRat = PsyWFnTdbH(state, EvapOutletAirTemp, EvapOutletAirEnthalpy, RoutineName);
    3396              :         }
    3397              : 
    3398            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = EvapOutletAirTemp;
    3399            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = EvapOutletAirHumRat;
    3400            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = EvapOutletAirEnthalpy;
    3401            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate = EvapAirMassFlow;
    3402            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    3403            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    3404            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    3405            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    3406              : 
    3407              :         // determine condenser leaving conditions
    3408            0 :         Real64 const QdotCond = EvapTotCap * EvapRuntimeFraction + EvapElecCoolingPower;
    3409            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3410            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3411            0 :         Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
    3412            0 :         Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
    3413            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
    3414            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
    3415            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
    3416              : 
    3417            0 :         thisTESCoil.ElecCoolingPower = EvapElecCoolingPower + DischargeElectricCoolingPower + thisTESCoil.AncillaryControlsPower;
    3418            0 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3419            0 :         thisTESCoil.RuntimeFraction =
    3420            0 :             (EvapTotCap * EvapRuntimeFraction + TotDischargeCap * DischargeRuntimeFraction) / (EvapTotCap + TotDischargeCap);
    3421              : 
    3422            0 :         thisTESCoil.EvapTotCoolingRate = EvapTotCap * EvapRuntimeFraction + TotDischargeCap * DischargeRuntimeFraction;
    3423            0 :         thisTESCoil.EvapTotCoolingEnergy = thisTESCoil.EvapTotCoolingRate * TimeStepSysSec;
    3424            0 :         Real64 const MinAirHumRat = min(state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat,
    3425            0 :                                         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat);
    3426            0 :         thisTESCoil.EvapSensCoolingRate =
    3427            0 :             EvapAirMassFlow * (PsyHFnTdbW(EvapInletDryBulb, MinAirHumRat) - PsyHFnTdbW(EvapOutletAirTemp, MinAirHumRat));
    3428            0 :         if (thisTESCoil.EvapSensCoolingRate > thisTESCoil.EvapTotCoolingRate) {
    3429            0 :             thisTESCoil.EvapSensCoolingRate = thisTESCoil.EvapTotCoolingRate;
    3430              :         }
    3431            0 :         thisTESCoil.EvapSensCoolingEnergy = thisTESCoil.EvapSensCoolingRate * TimeStepSysSec;
    3432            0 :         thisTESCoil.EvapLatCoolingRate = thisTESCoil.EvapTotCoolingRate - thisTESCoil.EvapSensCoolingRate;
    3433            0 :         thisTESCoil.EvapLatCoolingEnergy = thisTESCoil.EvapLatCoolingRate * TimeStepSysSec;
    3434              : 
    3435            0 :     } else { // coil is off; just pass through conditions
    3436            0 :         thisTESCoil.QdotTES = 0.0;
    3437              : 
    3438            0 :         thisTESCoil.ElecCoolingPower = thisTESCoil.AncillaryControlsPower;
    3439            0 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3440            0 :         thisTESCoil.RuntimeFraction = 0.0;
    3441              : 
    3442            0 :         thisTESCoil.RuntimeFraction = 0.0;
    3443            0 :         thisTESCoil.EvapTotCoolingRate = 0.0;
    3444            0 :         thisTESCoil.EvapTotCoolingEnergy = 0.0;
    3445            0 :         thisTESCoil.EvapSensCoolingRate = 0.0;
    3446            0 :         thisTESCoil.EvapSensCoolingEnergy = 0.0;
    3447            0 :         thisTESCoil.EvapLatCoolingRate = 0.0;
    3448            0 :         thisTESCoil.EvapLatCoolingEnergy = 0.0;
    3449              : 
    3450            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    3451            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    3452            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
    3453            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    3454            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    3455            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    3456            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    3457            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    3458            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    3459            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
    3460              :         // nothing happens at condenser
    3461            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3462            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    3463            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
    3464            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
    3465            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
    3466            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    3467            0 :             state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
    3468            0 :         thisTESCoil.CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3469              :     }
    3470            0 :     thisTESCoil.Q_TES = thisTESCoil.QdotTES * TimeStepSysSec;
    3471            0 :     UpdateTEStorage(state, TESCoilNum);
    3472              : 
    3473            0 :     UpdateColdWeatherProtection(state, TESCoilNum);
    3474              : 
    3475            0 :     if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    3476            0 :         UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
    3477            0 :         UpdateEvaporativeCondenserWaterUse(state, TESCoilNum, CondInletHumRat, thisTESCoil.CondAirInletNodeNum);
    3478              :     }
    3479            0 : }
    3480              : 
    3481            0 : 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            0 :     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            0 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    3503              : 
    3504              :     // nothing happens at Evaporator
    3505            0 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    3506            0 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    3507            0 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
    3508            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    3509            0 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    3510            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    3511            0 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    3512            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    3513            0 :     state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    3514            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
    3515              : 
    3516              :     // first deal with condenser
    3517            0 :     if (thisTESCoil.CondenserType == TESCondenserType::Air) {
    3518            0 :         Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
    3519            0 :         if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
    3520            0 :             CondInletTemp = state.dataEnvrn->OutDryBulbTemp;
    3521            0 :             CondInletHumRat = state.dataEnvrn->OutHumRat;
    3522              :         } else {
    3523            0 :             CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3524            0 :             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            0 :     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            0 :     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            0 :     case MediaType::Ice:
    3567            0 :         sTES = thisTESCoil.IceFracRemainLastTimestep;
    3568            0 :         if (sTES < 1.0) {
    3569            0 :             TESCanBeCharged = true;
    3570              :             // find charge limit to reach limit
    3571            0 :             QdotChargeLimit = (1.0 - sTES) * thisTESCoil.IceStorageCapacity / TimeStepSysSec;
    3572              :         } else {
    3573            0 :             TESCanBeCharged = false;
    3574              :         }
    3575            0 :         break;
    3576            0 :     default:
    3577            0 :         break;
    3578              :     }
    3579              : 
    3580            0 :     if (TESCanBeCharged) { // coil is running
    3581            0 :         Real64 CapModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.ChargeOnlyChargingCapFTempCurve, CondInletTemp, sTES);
    3582            0 :         CapModFac = max(0.0, CapModFac);
    3583            0 :         Real64 TotCap = thisTESCoil.ChargeOnlyRatedCapacity * CapModFac;
    3584            0 :         if (TotCap > QdotChargeLimit) {
    3585            0 :             thisTESCoil.RuntimeFraction = QdotChargeLimit / TotCap;
    3586            0 :             TotCap = min(TotCap, QdotChargeLimit);
    3587              :         } else {
    3588            0 :             thisTESCoil.RuntimeFraction = 1.0;
    3589              :         }
    3590            0 :         Real64 EIRModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.ChargeOnlyChargingEIRFTempCurve, CondInletTemp, sTES);
    3591            0 :         EIRModFac = max(0.0, EIRModFac);
    3592              : 
    3593            0 :         Real64 const EIR = EIRModFac / thisTESCoil.ChargeOnlyRatedCOP;
    3594            0 :         Real64 const ElecCoolingPower = TotCap * EIR;
    3595              :         // condenser total heat rejection rate [W]
    3596            0 :         Real64 const &QdotCond = TotCap + ElecCoolingPower;
    3597            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3598            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
    3599              :         // condenser inlet enthalpy [J/kg]
    3600            0 :         Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
    3601            0 :         Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
    3602            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
    3603            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
    3604            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
    3605              : 
    3606            0 :         thisTESCoil.ElecCoolingPower = ElecCoolingPower + thisTESCoil.AncillaryControlsPower;
    3607            0 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3608              : 
    3609            0 :         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            0 :     thisTESCoil.Q_TES = thisTESCoil.QdotTES * TimeStepSysSec;
    3625              : 
    3626            0 :     thisTESCoil.EvapTotCoolingRate = 0.0;
    3627            0 :     thisTESCoil.EvapTotCoolingEnergy = 0.0;
    3628            0 :     thisTESCoil.EvapSensCoolingRate = 0.0;
    3629            0 :     thisTESCoil.EvapSensCoolingEnergy = 0.0;
    3630            0 :     thisTESCoil.EvapLatCoolingRate = 0.0;
    3631            0 :     thisTESCoil.EvapLatCoolingEnergy = 0.0;
    3632              : 
    3633            0 :     UpdateTEStorage(state, TESCoilNum);
    3634              : 
    3635            0 :     UpdateColdWeatherProtection(state, TESCoilNum);
    3636              : 
    3637            0 :     if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    3638            0 :         UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
    3639            0 :         UpdateEvaporativeCondenserWaterUse(state, TESCoilNum, CondInletHumRat, thisTESCoil.CondAirInletNodeNum);
    3640              :     }
    3641            0 : }
    3642              : 
    3643            0 : 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            0 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    3654              : 
    3655              :     // SUBROUTINE PARAMETER DEFINITIONS:
    3656            0 :     int constexpr MaxIter(30);
    3657            0 :     Real64 constexpr RelaxationFactor(0.4);
    3658            0 :     Real64 constexpr Tolerance(0.1);
    3659              :     static constexpr std::string_view RoutineName("CalcTESCoilDischargeOnlyMode");
    3660              :     static constexpr std::string_view StorageTankName("CalcTESWaterStorageTank");
    3661              : 
    3662            0 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    3663              : 
    3664              :     Real64 QdotDischargeLimit;     // limit for how much storage can be discharged without overshooting
    3665            0 :     Real64 sTES = 0.0;             // state of charge of Thermal Energy Storage
    3666            0 :     bool TESHasSomeCharge = false; // true when there is something avaiable in storage
    3667              : 
    3668            0 :     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            0 :     case MediaType::Ice:
    3687            0 :         sTES = thisTESCoil.IceFracRemainLastTimestep;
    3688            0 :         if (sTES > 0.0) {
    3689            0 :             TESHasSomeCharge = true;
    3690              :             // discharge limit
    3691            0 :             QdotDischargeLimit = (sTES)*thisTESCoil.IceStorageCapacity / TimeStepSysSec;
    3692              :         } else {
    3693            0 :             TESHasSomeCharge = false;
    3694              :         }
    3695            0 :         break;
    3696            0 :     default:
    3697            0 :         break;
    3698              :     }
    3699              : 
    3700              :     // local for evaporator air mass flow [kg/s]
    3701            0 :     Real64 const EvapAirMassFlow = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    3702              : 
    3703            0 :     if ((EvapAirMassFlow > HVAC::SmallMassFlow) && (PartLoadRatio > 0.0) && TESHasSomeCharge) { // coil is running
    3704              : 
    3705            0 :         Real64 PLR = PartLoadRatio;
    3706              : 
    3707            0 :         Real64 const EvapInletDryBulb = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    3708            0 :         Real64 const EvapInletHumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    3709            0 :         Real64 const EvapInletWetBulb = PsyTwbFnTdbWPb(state, EvapInletDryBulb, EvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
    3710            0 :         Real64 const EvapInletEnthalpy = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Enthalpy;
    3711              : 
    3712              :         // evaporator inlet air mass flow divided by design mass flow [ ]
    3713            0 :         Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
    3714              : 
    3715              :         // total cooling capacity modification factor due to temps []
    3716            0 :         Real64 TotCapTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyCapFTempCurve, EvapInletWetBulb, sTES);
    3717            0 :         TotCapTempModFac = max(0.0, TotCapTempModFac);
    3718              :         // Total cooling capacity modification factor due to flow []
    3719            0 :         Real64 TotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyCapFFlowCurve, AirMassFlowRatio);
    3720            0 :         TotCapFlowModFac = max(0.0, TotCapFlowModFac);
    3721              :         // total cooling capacity
    3722            0 :         Real64 TotCap = thisTESCoil.DischargeOnlyRatedDischargeCap * TotCapTempModFac * TotCapFlowModFac;
    3723              : 
    3724              :         // part load factor
    3725            0 :         Real64 const PLF = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyPLFFPLRCurve, PLR);
    3726              :         // compressor running time divided by full time of timestep.
    3727            0 :         Real64 RuntimeFraction = 1.0;
    3728            0 :         if (PLF >= PLR && PLF > 0.0) {
    3729            0 :             RuntimeFraction = PLR / PLF;
    3730              :         } else {
    3731              :             // warn maybe
    3732              :         }
    3733              :         // Calculate electricity consumed. First, get EIR modifying factors for off-rated conditions
    3734            0 :         Real64 EIRTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyEIRFTempCurve, EvapInletWetBulb, sTES);
    3735            0 :         EIRTempModFac = max(EIRTempModFac, 0.0);
    3736              : 
    3737            0 :         Real64 EIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyEIRFFlowCurve, AirMassFlowRatio);
    3738            0 :         EIRFlowModFac = max(EIRFlowModFac, 0.0);
    3739            0 :         Real64 const EIR = EIRTempModFac * EIRFlowModFac / thisTESCoil.DischargeOnlyRatedCOP;
    3740              : 
    3741              :         // compressor electric power
    3742            0 :         Real64 ElecCoolingPower = TotCap * EIR * RuntimeFraction;
    3743            0 :         Real64 const QdotTEStest = TotCap * RuntimeFraction + ElecCoolingPower;
    3744              : 
    3745            0 :         if (QdotTEStest > QdotDischargeLimit) {
    3746            0 :             Real64 const RuntimeFractionLimit = QdotDischargeLimit / (TotCap + TotCap * EIR);
    3747            0 :             RuntimeFraction = min(RuntimeFraction, RuntimeFractionLimit);
    3748            0 :             PLR = RuntimeFraction * PLF;
    3749            0 :             ElecCoolingPower = TotCap * EIR * RuntimeFraction;
    3750              :         }
    3751              :         // now see if coil is running dry
    3752            0 :         Real64 PartLoadOutAirEnth = EvapInletEnthalpy - (TotCap * PLR) / EvapAirMassFlow;
    3753            0 :         Real64 const PartLoadDryCoilOutAirTemp = PsyTdbFnHW(PartLoadOutAirEnth, EvapInletHumRat);
    3754              : 
    3755            0 :         bool CoilMightBeDry = false;
    3756              :         Real64 DryCoilTestEvapInletHumRat;
    3757              :         Real64 SHRadp;
    3758            0 :         if (PartLoadDryCoilOutAirTemp > PsyTsatFnHPb(state, PartLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    3759            0 :             CoilMightBeDry = true;
    3760              :             // find wADP, humidity ratio at apparatus dewpoint and inlet hum rat that would have dry coil
    3761            0 :             DryCoilTestEvapInletHumRat = EvapInletHumRat;
    3762            0 :             Real64 DryCoilTestEvapInletWetBulb = EvapInletWetBulb;
    3763            0 :             int Counter = 0;
    3764            0 :             bool Converged = false;
    3765            0 :             while (!Converged) {
    3766            0 :                 TotCapTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyCapFTempCurve, DryCoilTestEvapInletWetBulb, sTES);
    3767            0 :                 TotCapTempModFac = max(0.0, TotCapTempModFac);
    3768            0 :                 TotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyCapFFlowCurve, AirMassFlowRatio);
    3769            0 :                 TotCapFlowModFac = max(0.0, TotCapFlowModFac);
    3770            0 :                 TotCap = thisTESCoil.DischargeOnlyRatedDischargeCap * TotCapTempModFac * TotCapFlowModFac;
    3771              :                 // coil bypass factor = 0.0
    3772            0 :                 Real64 const hADP = EvapInletEnthalpy - (TotCap / EvapAirMassFlow);
    3773            0 :                 Real64 const tADP = PsyTsatFnHPb(state, hADP, state.dataEnvrn->OutBaroPress, RoutineName);
    3774            0 :                 Real64 const wADP = min(EvapInletHumRat, PsyWFnTdbH(state, tADP, hADP, RoutineName));
    3775            0 :                 Real64 const hTinwADP = PsyHFnTdbW(EvapInletDryBulb, wADP);
    3776            0 :                 if ((EvapInletEnthalpy - hADP) > 1.e-10) {
    3777            0 :                     SHRadp = min((hTinwADP - hADP) / (EvapInletEnthalpy - hADP), 1.0);
    3778              :                 } else {
    3779            0 :                     SHRadp = 1.0;
    3780              :                 }
    3781              : 
    3782            0 :                 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            0 :                     Converged = true;
    3796              :                 }
    3797              :             }
    3798              :         } // coil will be wet so use SHR curves
    3799              : 
    3800              :         // total cooling capacity modification factors
    3801              :         Real64 SHRTempFac;
    3802            0 :         if (state.dataCurveManager->curves(thisTESCoil.DischargeOnlySHRFTempCurve)->numDims == 2) {
    3803            0 :             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            0 :         Real64 const SHRFlowFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlySHRFFLowCurve, AirMassFlowRatio);
    3809            0 :         Real64 SHR = thisTESCoil.DischargeOnlyRatedSHR * SHRTempFac * SHRFlowFac;
    3810            0 :         SHR = min(SHR, 1.0); // warn maybe
    3811            0 :         SHR = max(SHR, 0.0); // warn maybe
    3812            0 :         if (CoilMightBeDry) {
    3813            0 :             if ((EvapInletHumRat < DryCoilTestEvapInletHumRat) && (SHRadp > SHR)) { // coil is dry for sure
    3814            0 :                 SHR = 1.0;
    3815            0 :             } else if (SHRadp > SHR) {
    3816            0 :                 SHR = SHRadp;
    3817              :             }
    3818              :         }
    3819              :         //  Calculate full load output conditions
    3820              :         // evaporator outlet full load enthalpy [J/kg]
    3821            0 :         Real64 const FullLoadOutAirEnth = EvapInletEnthalpy - TotCap / EvapAirMassFlow;
    3822              : 
    3823              :         // Enthalpy at inlet dry-bulb and outlet humidity ratio [J/kg]
    3824            0 :         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            0 :         Real64 FullLoadOutAirHumRat = PsyWFnTdbH(state, EvapInletDryBulb, hTinwout, RoutineName, true);
    3827            0 :         Real64 FullLoadOutAirTemp = PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
    3828              :         // Check for saturation error and modify temperature at constant enthalpy
    3829            0 :         if (FullLoadOutAirTemp < PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
    3830            0 :             FullLoadOutAirTemp = PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName);
    3831            0 :             FullLoadOutAirHumRat = PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
    3832              :         }
    3833              : 
    3834              :         // Continuous fan, cycling compressor
    3835            0 :         Real64 const EvapOutletAirEnthalpy = ((PLR)*FullLoadOutAirEnth + (1.0 - (PLR)) * EvapInletEnthalpy);
    3836            0 :         Real64 EvapOutletAirHumRat = ((PLR)*FullLoadOutAirHumRat + (1.0 - (PLR)) * EvapInletHumRat);
    3837            0 :         Real64 EvapOutletAirTemp = PsyTdbFnHW(EvapOutletAirEnthalpy, EvapOutletAirHumRat);
    3838            0 :         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            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = EvapOutletAirTemp;
    3844            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = EvapOutletAirHumRat;
    3845            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = EvapOutletAirEnthalpy;
    3846            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate = EvapAirMassFlow;
    3847            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    3848            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    3849            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    3850            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    3851            0 :         thisTESCoil.ElecCoolingPower = ElecCoolingPower + thisTESCoil.AncillaryControlsPower;
    3852            0 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3853            0 :         thisTESCoil.RuntimeFraction = RuntimeFraction;
    3854            0 :         thisTESCoil.EvapTotCoolingRate = TotCap * RuntimeFraction; // double check this
    3855            0 :         thisTESCoil.EvapTotCoolingEnergy = TotCap * RuntimeFraction * TimeStepSysSec;
    3856            0 :         Real64 const MinAirHumRat = min(state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat,
    3857            0 :                                         state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat);
    3858            0 :         thisTESCoil.EvapSensCoolingRate =
    3859            0 :             EvapAirMassFlow * (PsyHFnTdbW(EvapInletDryBulb, MinAirHumRat) - PsyHFnTdbW(EvapOutletAirTemp, MinAirHumRat));
    3860            0 :         if (thisTESCoil.EvapSensCoolingRate > thisTESCoil.EvapTotCoolingRate) {
    3861            0 :             thisTESCoil.EvapSensCoolingRate = thisTESCoil.EvapTotCoolingRate;
    3862              :         }
    3863            0 :         thisTESCoil.EvapSensCoolingEnergy = thisTESCoil.EvapSensCoolingRate * TimeStepSysSec;
    3864            0 :         thisTESCoil.EvapLatCoolingRate = thisTESCoil.EvapTotCoolingRate - thisTESCoil.EvapSensCoolingRate;
    3865            0 :         thisTESCoil.EvapLatCoolingEnergy = thisTESCoil.EvapLatCoolingRate * TimeStepSysSec;
    3866              : 
    3867            0 :         thisTESCoil.QdotTES = TotCap * RuntimeFraction + ElecCoolingPower; // all heat rejection into storage
    3868              : 
    3869            0 :     } else { // coil is off; just pass through conditions
    3870            0 :         thisTESCoil.QdotTES = 0.0;
    3871              : 
    3872            0 :         thisTESCoil.ElecCoolingPower = thisTESCoil.AncillaryControlsPower;
    3873            0 :         thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
    3874            0 :         thisTESCoil.RuntimeFraction = 0.0;
    3875              : 
    3876            0 :         thisTESCoil.RuntimeFraction = 0.0;
    3877            0 :         thisTESCoil.EvapTotCoolingRate = 0.0;
    3878            0 :         thisTESCoil.EvapTotCoolingEnergy = 0.0;
    3879            0 :         thisTESCoil.EvapSensCoolingRate = 0.0;
    3880            0 :         thisTESCoil.EvapSensCoolingEnergy = 0.0;
    3881            0 :         thisTESCoil.EvapLatCoolingRate = 0.0;
    3882            0 :         thisTESCoil.EvapLatCoolingEnergy = 0.0;
    3883              : 
    3884            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
    3885            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
    3886            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
    3887            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
    3888            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
    3889            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
    3890            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
    3891            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
    3892            0 :         state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    3893            0 :             state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
    3894              :     }
    3895              : 
    3896              :     // nothing happens at condenser
    3897            0 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3898            0 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
    3899            0 :     state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
    3900            0 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
    3901            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
    3902            0 :     state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
    3903            0 :         state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
    3904            0 :     thisTESCoil.CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
    3905            0 :     thisTESCoil.Q_TES = thisTESCoil.QdotTES * TimeStepSysSec;
    3906            0 :     UpdateTEStorage(state, TESCoilNum);
    3907              : 
    3908            0 :     UpdateColdWeatherProtection(state, TESCoilNum);
    3909              : 
    3910            0 :     if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
    3911            0 :         UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
    3912            0 :         UpdateEvaporativeCondenserWaterUse(
    3913            0 :             state, TESCoilNum, state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat, thisTESCoil.CondAirInletNodeNum);
    3914              :     }
    3915            0 : }
    3916              : 
    3917            0 : 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            0 :     switch (state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).StorageMedia) {
    3927            0 :     case MediaType::Water:
    3928              :     case MediaType::UserDefindFluid:
    3929            0 :         CalcTESWaterStorageTank(state, TESCoilNum);
    3930            0 :         break;
    3931            0 :     case MediaType::Ice:
    3932            0 :         CalcTESIceStorageTank(state, TESCoilNum);
    3933            0 :         break;
    3934            0 :     default:
    3935            0 :         break;
    3936              :     }
    3937            0 : }
    3938              : 
    3939            0 : 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            0 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    3954              :     using WaterThermalTanks::WaterThermalTankData;
    3955              : 
    3956            0 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    3957              : 
    3958              :     // Seconds in one timestep (s)
    3959            0 :     Real64 const SecInTimeStep = TimeStepSysSec;
    3960              :     // Time remaining in the current timestep (s)
    3961            0 :     Real64 const TimeRemaining = SecInTimeStep;
    3962              : 
    3963              :     // Fraction of the current hour that has elapsed (h)
    3964              :     Real64 const TimeElapsed =
    3965            0 :         state.dataGlobal->HourOfDay + state.dataGlobal->TimeStep * state.dataGlobal->TimeStepZone + state.dataHVACGlobal->SysTimeElapsed;
    3966              : 
    3967            0 :     if (thisTESCoil.TimeElapsed != TimeElapsed) {
    3968            0 :         thisTESCoil.FluidTankTempFinalLastTimestep = thisTESCoil.FluidTankTempFinal;
    3969            0 :         thisTESCoil.TimeElapsed = TimeElapsed;
    3970              :     }
    3971              : 
    3972              :     // Instantaneous tank temperature (C)
    3973            0 :     Real64 const TankTemp = thisTESCoil.FluidTankTempFinalLastTimestep;
    3974              :     // Current ambient air temperature around tank (C)
    3975            0 :     Real64 const AmbientTemp = state.dataLoopNodes->Node(thisTESCoil.StorageAmbientNodeNum).Temp;
    3976              :     // Use side inlet temperature (C)
    3977            0 :     Real64 const UseInletTemp = state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).Temp;
    3978              :     // Source side inlet temperature (C)
    3979            0 :     Real64 const SourceInletTemp = thisTESCoil.FluidTankTempFinalLastTimestep;
    3980              :     // density of water in tank (kg/m3)
    3981            0 :     Real64 const rho = thisTESCoil.glycol->getDensity(state, TankTemp, RoutineName);
    3982              :     // Mass of water in tank (kg)
    3983            0 :     Real64 const TankMass = rho * thisTESCoil.FluidStorageVolume;
    3984              :     // Specific heat of water in tank (J/kg K)
    3985            0 :     Real64 const CpTank = thisTESCoil.glycol->getSpecificHeat(state, TankTemp, RoutineName);
    3986              : 
    3987              :     // Use side flow rate, including effectiveness factor (kg/s)
    3988            0 :     Real64 const UseMassFlowRate = thisTESCoil.TESPlantConnectionAvailable
    3989            0 :                                        ? state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).MassFlowRate * thisTESCoil.TESPlantEffectiveness
    3990            0 :                                        : 0.0;
    3991              : 
    3992              :     // Source side flow rate, including effectiveness factor (kg/s)
    3993            0 :     Real64 constexpr SourceMassFlowRate = 0.0;
    3994              :     // Loss coefficient to ambient environment (W/K)
    3995            0 :     Real64 const LossCoeff = thisTESCoil.StorageUA;
    3996              :     // heat exchange directly into tank from charging system [W]
    3997            0 :     Real64 const QdotTES = thisTESCoil.QdotTES;
    3998              : 
    3999              :     // Predicted new tank temperature (C)
    4000            0 :     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            0 :     thisTESCoil.FluidTankTempFinal = NewTankTemp;
    4013              : 
    4014            0 :     if (thisTESCoil.TESPlantConnectionAvailable) {
    4015              :         // Specific heat of fluid in plant connection (J/kg K)
    4016              :         Real64 const CpPlantConnection =
    4017            0 :             state.dataPlnt->PlantLoop(thisTESCoil.TESPlantLoopNum)
    4018            0 :                 .glycol->getSpecificHeat(state, state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).Temp, calcTESIceStorageTank);
    4019              : 
    4020            0 :         thisTESCoil.QdotPlant = state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).MassFlowRate * CpPlantConnection *
    4021            0 :                                 thisTESCoil.TESPlantEffectiveness * (UseInletTemp - NewTankTemp);
    4022            0 :         thisTESCoil.Q_Plant = thisTESCoil.QdotPlant * TimeStepSysSec;
    4023              :         // now get correct outlet temp with actual massflow (not modified by effectiveness)
    4024            0 :         Real64 NewOutletTemp = UseInletTemp; // calculated new tankoutlet temp (C)
    4025            0 :         if (state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).MassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
    4026            0 :             NewOutletTemp =
    4027            0 :                 UseInletTemp - thisTESCoil.QdotPlant / (state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).MassFlowRate * CpPlantConnection);
    4028              :         }
    4029            0 :         state.dataLoopNodes->Node(thisTESCoil.TESPlantOutletNodeNum).Temp = NewOutletTemp;
    4030              :     }
    4031              : 
    4032              :     // Change in integrated tank temperature, dividing by time gives the average (C s)
    4033            0 :     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            0 :     thisTESCoil.QdotAmbient = (LossCoeff * (AmbientTemp * TimeRemaining - deltaTsum)) / SecInTimeStep;
    4046            0 :     thisTESCoil.Q_Ambient = thisTESCoil.QdotAmbient * TimeStepSysSec;
    4047            0 : }
    4048              : 
    4049            0 : 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            0 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    4060              : 
    4061              :     // SUBROUTINE PARAMETER DEFINITIONS:
    4062            0 :     constexpr Real64 FreezingTemp(0.0); // zero degrees C
    4063              :     static constexpr std::string_view RoutineName("CalcTESIceStorageTank");
    4064              : 
    4065            0 :     auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
    4066              : 
    4067              :     // Fraction of the current hour that has elapsed (h)
    4068              :     Real64 const TimeElapsed =
    4069            0 :         state.dataGlobal->HourOfDay + state.dataGlobal->TimeStep * state.dataGlobal->TimeStepZone + state.dataHVACGlobal->SysTimeElapsed;
    4070              : 
    4071            0 :     if (thisTESCoil.TimeElapsed != TimeElapsed) {
    4072            0 :         thisTESCoil.IceFracRemainLastTimestep = thisTESCoil.IceFracRemain;
    4073            0 :         thisTESCoil.TimeElapsed = TimeElapsed;
    4074              :     }
    4075              : 
    4076              :     // update plant connection (if any)
    4077            0 :     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            0 :         thisTESCoil.QdotPlant = 0.0;
    4092            0 :         thisTESCoil.Q_Plant = 0.0;
    4093              :     }
    4094              : 
    4095              :     // update ambient heat transfer
    4096              : 
    4097            0 :     thisTESCoil.QdotAmbient = thisTESCoil.StorageUA * (state.dataLoopNodes->Node(thisTESCoil.StorageAmbientNodeNum).Temp - FreezingTemp);
    4098            0 :     thisTESCoil.Q_Ambient = thisTESCoil.QdotAmbient * TimeStepSysSec;
    4099              : 
    4100              :     // local rate of heat transfer to ice (negative cooling) [W]
    4101            0 :     Real64 const QdotIce = thisTESCoil.QdotPlant + thisTESCoil.QdotAmbient + thisTESCoil.QdotTES;
    4102              : 
    4103            0 :     if (QdotIce < 0.0) { // charging ice level
    4104            0 :         thisTESCoil.IceFracRemain = thisTESCoil.IceFracRemainLastTimestep + std::abs(QdotIce) / (thisTESCoil.IceStorageCapacity / TimeStepSysSec);
    4105            0 :         if (thisTESCoil.IceFracRemain > 1.0) {
    4106            0 :             thisTESCoil.IceFracRemain = 1.0;
    4107              :         }
    4108              :     } else { // not charging,but discharging
    4109            0 :         thisTESCoil.IceFracRemain = thisTESCoil.IceFracRemainLastTimestep - QdotIce / (thisTESCoil.IceStorageCapacity / TimeStepSysSec);
    4110            0 :         if (thisTESCoil.IceFracRemain < 0.0) {
    4111            0 :             thisTESCoil.IceFracRemain = 0.0;
    4112              :         }
    4113              :     }
    4114            0 : }
    4115              : 
    4116            0 : 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            0 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    4127              : 
    4128            0 :     if ((state.dataLoopNodes->Node(state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).StorageAmbientNodeNum).Temp <
    4129            0 :          state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ColdWeatherMinimumTempLimit) &&
    4130            0 :         (state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).availSched->getCurrentVal() != 0.0)) {
    4131            0 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectColdWeatherPower =
    4132            0 :             state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ColdWeatherAncillaryPower;
    4133              : 
    4134              :     } else {
    4135            0 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectColdWeatherPower = 0.0;
    4136              :     }
    4137            0 :     state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectColdWeatherEnergy =
    4138            0 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectColdWeatherPower * TimeStepSysSec;
    4139            0 : }
    4140              : 
    4141            0 : 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            0 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    4155              : 
    4156            0 :     CalcBasinHeaterPower(state,
    4157            0 :                          state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).BasinHeaterPowerFTempDiff,
    4158            0 :                          state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).basinHeaterAvailSched,
    4159            0 :                          state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).BasinHeaterSetpointTemp,
    4160            0 :                          state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectEvapCondBasinHeaterPower);
    4161              : 
    4162            0 :     state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectEvapCondBasinHeaterEnergy =
    4163            0 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectEvapCondBasinHeaterPower * TimeStepSysSec;
    4164            0 : }
    4165              : 
    4166            0 : 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            0 :     Real64 const RhoWater = RhoH2O(state.dataLoopNodes->Node(InletNodeNum).Temp);
    4179            0 :     state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsumpRate =
    4180            0 :         (HumRatAfterEvap - state.dataLoopNodes->Node(InletNodeNum).HumRat) * state.dataLoopNodes->Node(InletNodeNum).MassFlowRate / RhoWater *
    4181            0 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).CondenserRuntimeFraction;
    4182              : 
    4183              :     // Set the demand request for supply water from water storage tank (if needed)
    4184            0 :     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            0 :     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            0 :     Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    4204            0 :     state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsump =
    4205            0 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsumpRate * TimeStepSysSec;
    4206              : 
    4207            0 :     state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterStarvMakup =
    4208            0 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterStarvMakupRate * TimeStepSysSec;
    4209              : 
    4210            0 :     state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapCondPumpElecPower =
    4211            0 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapCondPumpElecNomPower *
    4212            0 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).CondenserRuntimeFraction;
    4213            0 :     state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapCondPumpElecConsumption =
    4214            0 :         state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapCondPumpElecPower * TimeStepSysSec;
    4215            0 : }
    4216              : 
    4217            0 : 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            0 :     if (state.dataPackagedThermalStorageCoil->GetTESInputFlag) { // First time subroutine has been called, get input data
    4233            0 :         GetTESCoilInput(state);
    4234            0 :         state.dataPackagedThermalStorageCoil->GetTESInputFlag =
    4235              :             false; // Set logic flag to disallow getting the input data on future calls to this subroutine
    4236              :     }
    4237              : 
    4238            0 :     if (state.dataPackagedThermalStorageCoil->NumTESCoils > 0) {
    4239            0 :         CoilIndex = Util::FindItem(CoilName, state.dataPackagedThermalStorageCoil->TESCoil);
    4240              :     } else {
    4241            0 :         CoilIndex = 0;
    4242              :     }
    4243              : 
    4244            0 :     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            0 : }
    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            0 : 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            0 :     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            0 :     if (state.dataPackagedThermalStorageCoil->NumTESCoils > 0) {
    4357            0 :         CoilIndex = Util::FindItem(CoilName, state.dataPackagedThermalStorageCoil->TESCoil, state.dataPackagedThermalStorageCoil->NumTESCoils);
    4358              :     } else {
    4359            0 :         CoilIndex = 0;
    4360              :     }
    4361              : 
    4362            0 :     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            0 :         if (state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).CoolingOnlyModeIsAvailable) { // get input data for this mode
    4368            0 :             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            0 : }
    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