LCOV - code coverage report
Current view: top level - EnergyPlus - PackagedThermalStorageCoil.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 1589 2400 66.2 %
Date: 2024-08-23 23:50:59 Functions: 18 21 85.7 %

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

Generated by: LCOV version 1.14