LCOV - code coverage report
Current view: top level - EnergyPlus - WaterThermalTanks.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 4482 6419 69.8 %
Date: 2023-01-17 19:17:23 Functions: 67 71 94.4 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2023, 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             : // ObjexxFCL Headers
      49             : #include <ObjexxFCL/Array.functions.hh>
      50             : #include <ObjexxFCL/Optional.hh>
      51             : #include <ObjexxFCL/floops.hh>
      52             : #include <ObjexxFCL/member.functions.hh>
      53             : 
      54             : // EnergyPlus Headers
      55             : #include <EnergyPlus/Autosizing/Base.hh>
      56             : #include <EnergyPlus/BranchNodeConnections.hh>
      57             : #include <EnergyPlus/Coils/CoilCoolingDX.hh>
      58             : #include <EnergyPlus/CurveManager.hh>
      59             : #include <EnergyPlus/DXCoils.hh>
      60             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      61             : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
      62             : #include <EnergyPlus/DataHVACGlobals.hh>
      63             : #include <EnergyPlus/DataHeatBalance.hh>
      64             : #include <EnergyPlus/DataIPShortCuts.hh>
      65             : #include <EnergyPlus/DataLoopNode.hh>
      66             : #include <EnergyPlus/DataSizing.hh>
      67             : #include <EnergyPlus/DataZoneEquipment.hh>
      68             : #include <EnergyPlus/Fans.hh>
      69             : #include <EnergyPlus/FluidProperties.hh>
      70             : #include <EnergyPlus/General.hh>
      71             : #include <EnergyPlus/GeneralRoutines.hh>
      72             : #include <EnergyPlus/GlobalNames.hh>
      73             : #include <EnergyPlus/HVACFan.hh>
      74             : #include <EnergyPlus/HeatBalanceInternalHeatGains.hh>
      75             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      76             : #include <EnergyPlus/IntegratedHeatPump.hh>
      77             : #include <EnergyPlus/NodeInputManager.hh>
      78             : #include <EnergyPlus/OutAirNodeManager.hh>
      79             : #include <EnergyPlus/OutputProcessor.hh>
      80             : #include <EnergyPlus/OutputReportPredefined.hh>
      81             : #include <EnergyPlus/Plant/DataPlant.hh>
      82             : #include <EnergyPlus/Plant/PlantLocation.hh>
      83             : #include <EnergyPlus/PlantUtilities.hh>
      84             : #include <EnergyPlus/Psychrometrics.hh>
      85             : #include <EnergyPlus/RefrigeratedCase.hh>
      86             : #include <EnergyPlus/ScheduleManager.hh>
      87             : #include <EnergyPlus/SolarCollectors.hh>
      88             : #include <EnergyPlus/VariableSpeedCoils.hh>
      89             : #include <EnergyPlus/WaterThermalTanks.hh>
      90             : #include <EnergyPlus/WaterToAirHeatPumpSimple.hh>
      91             : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      92             : 
      93             : namespace EnergyPlus::WaterThermalTanks {
      94             : 
      95             : // MODULE INFORMATION:
      96             : //       AUTHOR         Brandon Anderson
      97             : //       DATE WRITTEN   May 2000
      98             : //       MODIFIED       Feb 2005, PGE; July 2005, FSEC - added HPWH's and desuperheater water heating coils
      99             : //                      Jan 2007, PGE - added stratified water heater
     100             : //                      Oct 2007, BTG - extended for indirect water heater
     101             : //                      May 2008, Stovall - added desup from condenser and removed double counting
     102             : //                           (includes "d0"s from revision 145)
     103             : //                       Nov 2011, BAN; corrected use and source outlet temp. calculation of stratified tank
     104             : //       RE-ENGINEERED  Feb 2004, PGE
     105             : //                      Sep 2008, BTG - refactored, was PlantWaterHeater.cc is now PlantWaterThermalTank.cc
     106             : //                                 reuse water heater code for chilled water storage
     107             : 
     108             : // PURPOSE OF THIS MODULE:
     109             : // This module simulates water thermal storage tanks heaters in the plant loop.  Tanks can
     110             : // be positioned as supply side equipment or demand side equipment.  Water heater versions can be stand-alone as
     111             : // non-zone equipment.
     112             : 
     113             : // METHODOLOGY EMPLOYED:
     114             : // Two water thermal tank models are implemented, MIXED and STRATIFIED with hot and cold versions of each:
     115             : // WaterHeater:Mixed simulates a well-mixed, single-node tank for hot water applications.  Source (e.g. heat recovery) and
     116             : // use plant connections are allowed.  A scheduled domestic hot water demand can also be specified
     117             : // to directly utilize the hot water without use side connections.
     118             : // WaterHeater:Stratified simulates a stratified, multi-node tank for hot water applicatons.
     119             : // The model shares most of the same capabilities as WaterHeater:Mixed
     120             : // but also has up to two heating elements which can be operated in
     121             : // a master-slave mode or simultaneous mode.
     122             : 
     123             : // ThermalStorage:ChilledWater:Mixed simulates a well-mixed, single-node tank for chilled water applications
     124             : 
     125             : // ThermalStorage:ChilledWater:Stratified simulates a stratified, multi-node tank for chilled water applications.
     126             : 
     127         771 : std::string const cMixedWHModuleObj = "WaterHeater:Mixed";
     128         771 : std::string const cStratifiedWHModuleObj = "WaterHeater:Stratified";
     129         771 : std::string const cMixedCWTankModuleObj = "ThermalStorage:ChilledWater:Mixed";
     130         771 : std::string const cStratifiedCWTankModuleObj = "ThermalStorage:ChilledWater:Stratified";
     131         771 : std::string const cHPWHPumpedCondenser = "WaterHeater:HeatPump:PumpedCondenser";
     132         771 : std::string const cHPWHWrappedCondenser = "WaterHeater:HeatPump:WrappedCondenser";
     133         771 : std::string const cCoilDesuperheater = "Coil:WaterHeating:Desuperheater";
     134         771 : std::string const fluidNameWater = "WATER";
     135             : 
     136         136 : PlantComponent *WaterThermalTankData::factory(EnergyPlusData &state, std::string const &objectName)
     137             : {
     138             :     // Process the input data
     139         136 :     if (state.dataWaterThermalTanks->getWaterThermalTankInputFlag) {
     140          10 :         GetWaterThermalTankInput(state);
     141          10 :         state.dataWaterThermalTanks->getWaterThermalTankInputFlag = false;
     142             :     }
     143             : 
     144             :     // Now look for this object in the list
     145         156 :     for (auto &tank : state.dataWaterThermalTanks->WaterThermalTank) {
     146         156 :         if (tank.Name == objectName) {
     147         136 :             return &tank;
     148             :         }
     149             :     }
     150             :     // If we didn't find it, fatal
     151             :     ShowFatalError(state, "LocalWaterTankFactory: Error getting inputs for tank named: " + objectName); // LCOV_EXCL_LINE
     152             :     // Shut up the compiler
     153             :     return nullptr; // LCOV_EXCL_LINE
     154             : }
     155             : 
     156         736 : void WaterThermalTankData::onInitLoopEquip(EnergyPlusData &state, const PlantLocation &calledFromLocation)
     157             : {
     158         736 :     this->initialize(state, true);
     159         736 :     this->MinePlantStructForInfo(state);
     160         736 :     if (calledFromLocation.loopNum > 0) {
     161         736 :         if ((this->SrcSidePlantLoc.loopNum == calledFromLocation.loopNum) || (this->UseSidePlantLoc.loopNum == calledFromLocation.loopNum)) {
     162         731 :             this->SizeTankForDemandSide(state);
     163         731 :             this->SizeDemandSidePlantConnections(state);
     164         731 :             this->SizeSupplySidePlantConnections(state, calledFromLocation.loopNum);
     165         731 :             this->SizeTankForSupplySide(state);
     166             :         } else {
     167           5 :             return;
     168             :         }
     169             :     } else {
     170           0 :         this->SizeTankForDemandSide(state);
     171           0 :         this->SizeDemandSidePlantConnections(state);
     172           0 :         this->SizeSupplySidePlantConnections(state);
     173           0 :         this->SizeTankForSupplySide(state);
     174             :     }
     175             : 
     176         731 :     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
     177         159 :         if (!this->IsChilledWaterTank) {
     178         150 :             this->CalcStandardRatings(state);
     179             :         } else {
     180           9 :             this->ReportCWTankInits(state);
     181             :         }
     182             :     }
     183             : }
     184             : 
     185         686 : void WaterThermalTankData::getDesignCapacities([[maybe_unused]] EnergyPlusData &state,
     186             :                                                [[maybe_unused]] const PlantLocation &calledFromLocation,
     187             :                                                Real64 &MaxLoad,
     188             :                                                Real64 &MinLoad,
     189             :                                                Real64 &OptLoad)
     190             : {
     191         686 :     MinLoad = 0.0;
     192         686 :     MaxLoad = this->MaxCapacity;
     193         686 :     OptLoad = this->MaxCapacity;
     194         686 : }
     195             : 
     196           0 : int getTankIDX(EnergyPlusData &state, std::string_view CompName, int &CompIndex)
     197             : {
     198           0 :     if (state.dataWaterThermalTanks->getWaterThermalTankInputFlag) {
     199           0 :         GetWaterThermalTankInput(state);
     200           0 :         state.dataWaterThermalTanks->getWaterThermalTankInputFlag = false;
     201             :     }
     202             : 
     203             :     int CompNum;
     204             : 
     205           0 :     if (CompIndex == 0) {
     206           0 :         CompNum = UtilityRoutines::FindItem(CompName, state.dataWaterThermalTanks->WaterThermalTank);
     207           0 :         if (CompNum == 0) {
     208           0 :             ShowFatalError(state, "SimWaterThermalTank_WaterTank:  Unit not found=" + std::string{CompName});
     209             :         }
     210           0 :         CompIndex = CompNum;
     211             :     } else {
     212           0 :         CompNum = CompIndex;
     213           0 :         if (CompNum > state.dataWaterThermalTanks->numWaterThermalTank || CompNum < 1) {
     214           0 :             ShowFatalError(state,
     215           0 :                            format("SimWaterThermalTank_WaterTank:  Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
     216             :                                   CompNum,
     217           0 :                                   state.dataWaterThermalTanks->numWaterThermalTank,
     218           0 :                                   CompName));
     219             :         }
     220           0 :         if (state.dataWaterThermalTanks->WaterThermalTank(CompNum).CheckWTTEquipName) {
     221           0 :             if (CompName != state.dataWaterThermalTanks->WaterThermalTank(CompNum).Name) {
     222           0 :                 ShowFatalError(state,
     223           0 :                                format("SimWaterThermalTank_WaterTank: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
     224             :                                       CompNum,
     225             :                                       CompName,
     226           0 :                                       state.dataWaterThermalTanks->WaterThermalTank(CompNum).Name));
     227             :             }
     228           0 :             state.dataWaterThermalTanks->WaterThermalTank(CompNum).CheckWTTEquipName = false;
     229             :         }
     230             :     }
     231             : 
     232           0 :     return CompNum;
     233             : }
     234             : 
     235        5048 : int getHPTankIDX(EnergyPlusData &state, std::string_view CompName, int &CompIndex)
     236             : {
     237        5048 :     if (state.dataWaterThermalTanks->getWaterThermalTankInputFlag) {
     238           0 :         GetWaterThermalTankInput(state);
     239           0 :         state.dataWaterThermalTanks->getWaterThermalTankInputFlag = false;
     240             :     }
     241             : 
     242             :     int CompNum;
     243             : 
     244        5048 :     if (CompIndex == 0) {
     245           0 :         CompNum = UtilityRoutines::FindItem(CompName, state.dataWaterThermalTanks->HPWaterHeater);
     246           0 :         if (CompNum == 0) {
     247           0 :             ShowFatalError(state, "SimWaterThermalTank_HeatPump:  Unit not found=" + std::string{CompName});
     248             :         }
     249           0 :         CompIndex = CompNum;
     250             :     } else {
     251        5048 :         CompNum = CompIndex;
     252        5048 :         if (CompNum > state.dataWaterThermalTanks->numWaterThermalTank || CompNum < 1) {
     253           0 :             ShowFatalError(state,
     254           0 :                            format("SimWaterThermalTank_HeatPump:  Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
     255             :                                   CompNum,
     256           0 :                                   state.dataWaterThermalTanks->numHeatPumpWaterHeater,
     257           0 :                                   CompName));
     258             :         }
     259        5048 :         if (state.dataWaterThermalTanks->HPWaterHeater(CompNum).CheckHPWHEquipName) {
     260           1 :             if (CompName != state.dataWaterThermalTanks->HPWaterHeater(CompNum).Name) {
     261           0 :                 ShowFatalError(state,
     262           0 :                                format("SimWaterThermalTank_HeatPump: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
     263             :                                       CompNum,
     264             :                                       CompName,
     265           0 :                                       state.dataWaterThermalTanks->HPWaterHeater(CompNum).Name));
     266             :             }
     267           1 :             state.dataWaterThermalTanks->HPWaterHeater(CompNum).CheckHPWHEquipName = false;
     268             :         }
     269             :     }
     270             : 
     271        5048 :     return CompNum;
     272             : }
     273             : 
     274     5468492 : void WaterThermalTankData::simulate(
     275             :     EnergyPlusData &state, const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, [[maybe_unused]] bool RunFlag)
     276             : {
     277             :     // SUBROUTINE INFORMATION:
     278             :     //       AUTHOR         Brandon Anderson
     279             :     //       DATE WRITTEN   May 2000
     280             :     //       MODIFIED       FSEC, July 2005
     281             :     //       RE-ENGINEERED  na
     282             : 
     283             :     // set the caller loop num to mimic what was happening in plant loop equip
     284     5468492 :     this->callerLoopNum = calledFromLocation.loopNum;
     285             : 
     286     5468492 :     this->oneTimeInit(state);
     287             : 
     288     5468492 :     if (this->MyOneTimeFlagWH) {
     289         168 :         this->MyOneTimeFlagWH = false;
     290             :     } else {
     291     5468324 :         if (this->MyTwoTimeFlagWH) {
     292         168 :             this->MinePlantStructForInfo(state); // call it again to get control types filled out
     293         168 :             this->MyTwoTimeFlagWH = false;
     294             :         }
     295             :     }
     296     5468492 :     this->UseSideLoadRequested = std::abs(CurLoad);
     297    10599928 :     if (this->UseSidePlantLoc.loopNum > 0 && this->UseSidePlantLoc.loopSideNum != DataPlant::LoopSideLocation::Invalid &&
     298     5131436 :         !state.dataGlobal->KickOffSimulation) {
     299     5111902 :         this->UseCurrentFlowLock = state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).LoopSide(this->UseSidePlantLoc.loopSideNum).FlowLock;
     300             :     } else {
     301      356590 :         this->UseCurrentFlowLock = DataPlant::FlowLock::Locked;
     302             :     }
     303     5468492 :     this->initialize(state, FirstHVACIteration);
     304             :     //       Plant connected water heaters may have a desuperheater heating coil attached
     305     5468492 :     if (this->DesuperheaterNum == 0) {
     306     5998913 :         if ((this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed) ||
     307      560471 :             (this->WaterThermalTankType == DataPlant::PlantEquipmentType::ChilledWaterTankMixed)) {
     308     5193004 :             this->CalcWaterThermalTankMixed(state);
     309      418411 :         } else if ((this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) ||
     310      172973 :                    (this->WaterThermalTankType == DataPlant::PlantEquipmentType::ChilledWaterTankStratified)) {
     311      245438 :             this->CalcWaterThermalTankStratified(state);
     312             :         }
     313       30050 :     } else if (this->DesuperheaterNum > 0) {
     314       30050 :         this->CalcDesuperheaterWaterHeater(state, FirstHVACIteration);
     315             :     }
     316     5468492 :     this->UpdateWaterThermalTank(state);
     317     5468492 :     this->ReportWaterThermalTank(state);
     318             :     // reset the caller loop num to mimic what was happening in PlantLoopEquip
     319     5468492 :     this->callerLoopNum = 0;
     320     5468492 : }
     321             : 
     322          10 : PlantComponent *HeatPumpWaterHeaterData::factory(EnergyPlusData &state, std::string const &objectName)
     323             : {
     324             :     // Process the input data
     325          10 :     if (state.dataWaterThermalTanks->getWaterThermalTankInputFlag) {
     326           3 :         GetWaterThermalTankInput(state);
     327           3 :         state.dataWaterThermalTanks->getWaterThermalTankInputFlag = false;
     328             :     }
     329             : 
     330             :     // Now look for this object in the list
     331          28 :     for (auto &HPWH : state.dataWaterThermalTanks->HPWaterHeater) {
     332          28 :         if (HPWH.Name == objectName) {
     333          10 :             return &HPWH;
     334             :         }
     335             :     }
     336             :     // If we didn't find it, fatal
     337             :     ShowFatalError(state, "LocalHeatPumpWaterHeaterFactory: Error getting inputs for object named: " + objectName); // LCOV_EXCL_LINE
     338             :     // Shut up the compiler
     339             :     return nullptr; // LCOV_EXCL_LINE
     340             : }
     341             : 
     342          50 : void HeatPumpWaterHeaterData::onInitLoopEquip(EnergyPlusData &state, const PlantLocation &calledFromLocation)
     343             : {
     344          50 :     auto &Tank = state.dataWaterThermalTanks->WaterThermalTank(this->WaterHeaterTankNum);
     345          50 :     Tank.onInitLoopEquip(state, calledFromLocation);
     346          50 : }
     347             : 
     348          50 : void HeatPumpWaterHeaterData::getDesignCapacities([[maybe_unused]] EnergyPlusData &state,
     349             :                                                   [[maybe_unused]] const PlantLocation &calledFromLocation,
     350             :                                                   Real64 &MaxLoad,
     351             :                                                   Real64 &MinLoad,
     352             :                                                   Real64 &OptLoad)
     353             : {
     354          50 :     MinLoad = 0.0;
     355          50 :     MaxLoad = this->Capacity;
     356          50 :     OptLoad = this->Capacity;
     357          50 : }
     358             : 
     359      644606 : void HeatPumpWaterHeaterData::simulate(
     360             :     EnergyPlusData &state, const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, [[maybe_unused]] bool RunFlag)
     361             : {
     362             :     // SUBROUTINE INFORMATION:
     363             :     //       AUTHOR         Brandon Anderson
     364             :     //       DATE WRITTEN   May 2000
     365             :     //       MODIFIED       FSEC, July 2005
     366             :     //       RE-ENGINEERED  na
     367             : 
     368      644606 :     auto &Tank = state.dataWaterThermalTanks->WaterThermalTank(this->WaterHeaterTankNum);
     369             : 
     370             :     // set caller loop num to mimic what plantloopequip was doing
     371      644606 :     Tank.callerLoopNum = calledFromLocation.loopNum;
     372             : 
     373      644606 :     if (this->myOneTimeInitFlag) {
     374          23 :         if (Tank.myOneTimeInitFlag) {
     375          23 :             Tank.setupOutputVars(state);
     376          23 :             Tank.myOneTimeInitFlag = false;
     377             :         }
     378          23 :         this->myOneTimeInitFlag = false;
     379             :     }
     380             : 
     381      644606 :     if (this->MyOneTimeFlagHP) {
     382          23 :         this->MyOneTimeFlagHP = false;
     383             :     } else {
     384      644583 :         if (this->MyTwoTimeFlagHP) {
     385          23 :             Tank.MinePlantStructForInfo(state); // call it again to get control types filled out
     386          23 :             this->MyTwoTimeFlagHP = false;
     387             :         }
     388             :     }
     389      644606 :     Tank.UseSideLoadRequested = std::abs(CurLoad);
     390     1179616 :     if (Tank.UseSidePlantLoc.loopNum > 0 && Tank.UseSidePlantLoc.loopSideNum != DataPlant::LoopSideLocation::Invalid &&
     391      535010 :         !state.dataGlobal->KickOffSimulation) {
     392      533630 :         Tank.UseCurrentFlowLock = state.dataPlnt->PlantLoop(Tank.UseSidePlantLoc.loopNum).LoopSide(Tank.UseSidePlantLoc.loopSideNum).FlowLock;
     393             :     } else {
     394      110976 :         Tank.UseCurrentFlowLock = DataPlant::FlowLock::Locked;
     395             :     }
     396             : 
     397      644606 :     Tank.initialize(state, FirstHVACIteration);
     398             : 
     399      644606 :     int InletNodeSav = this->HeatPumpAirInletNode;
     400      644606 :     int OutletNodeSav = this->HeatPumpAirOutletNode;
     401      644606 :     int DXINletNodeSav = this->DXCoilAirInletNode;
     402      644606 :     int IHPFanIndexSav = this->FanNum;
     403     1289212 :     std::string IHPFanNameSave = this->FanName;
     404      644606 :     int IHPFanplaceSav = this->FanPlacement;
     405             : 
     406      644606 :     if (this->bIsIHP) // pass the tank indexes to the IHP object
     407             :     {
     408       10098 :         state.dataIntegratedHP->IntegratedHeatPumps(this->DXCoilNum).WHtankType = this->HPWHType;
     409       10098 :         state.dataIntegratedHP->IntegratedHeatPumps(this->DXCoilNum).WHtankName = this->Name;
     410       10098 :         state.dataIntegratedHP->IntegratedHeatPumps(this->DXCoilNum).WHtankID = this->WaterHeaterTankNum;
     411       10098 :         IntegratedHeatPump::IHPOperationMode IHPMode = IntegratedHeatPump::GetCurWorkMode(state, this->DXCoilNum);
     412             : 
     413       10098 :         if ((IntegratedHeatPump::IHPOperationMode::DedicatedWaterHtg == IHPMode) ||
     414        7695 :             (IntegratedHeatPump::IHPOperationMode::SpaceClgDedicatedWaterHtg == IHPMode) ||
     415        7695 :             (IntegratedHeatPump::IHPOperationMode::SHDWHElecHeatOff == IHPMode) ||
     416             :             (IntegratedHeatPump::IHPOperationMode::SHDWHElecHeatOn == IHPMode)) { // default is to specify the air nodes for SCWH mode
     417        2403 :             bool bDWHCoilReading = false;
     418        2403 :             this->HeatPumpAirInletNode =
     419        4806 :                 VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state,
     420             :                                                                   "COIL:WATERHEATING:AIRTOWATERHEATPUMP:VARIABLESPEED",
     421        2403 :                                                                   state.dataIntegratedHP->IntegratedHeatPumps(this->DXCoilNum).DWHCoilName,
     422             :                                                                   bDWHCoilReading);
     423        2403 :             this->HeatPumpAirOutletNode =
     424        4806 :                 VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state,
     425             :                                                                    "COIL:WATERHEATING:AIRTOWATERHEATPUMP:VARIABLESPEED",
     426        2403 :                                                                    state.dataIntegratedHP->IntegratedHeatPumps(this->DXCoilNum).DWHCoilName,
     427             :                                                                    bDWHCoilReading);
     428        2403 :             this->DXCoilAirInletNode = this->HeatPumpAirInletNode;
     429             :         } else // default is to input outdoor fan to the the this
     430             :         {
     431        7695 :             this->FanNum = state.dataIntegratedHP->IntegratedHeatPumps(this->DXCoilNum).IDFanID;
     432        7695 :             this->FanName = state.dataIntegratedHP->IntegratedHeatPumps(this->DXCoilNum).IDFanName;
     433        7695 :             this->FanPlacement = state.dataIntegratedHP->IntegratedHeatPumps(this->DXCoilNum).IDFanPlace;
     434             :         }
     435             :     }
     436             : 
     437      644606 :     Tank.CalcHeatPumpWaterHeater(state, FirstHVACIteration);
     438      644606 :     Tank.UpdateWaterThermalTank(state);
     439      644606 :     Tank.ReportWaterThermalTank(state);
     440             : 
     441      644606 :     this->HeatPumpAirInletNode = InletNodeSav;
     442      644606 :     this->HeatPumpAirOutletNode = OutletNodeSav;
     443      644606 :     this->DXCoilAirInletNode = DXINletNodeSav;
     444      644606 :     this->FanNum = IHPFanIndexSav;
     445      644606 :     this->FanName = IHPFanNameSave;
     446      644606 :     this->FanPlacement = IHPFanplaceSav;
     447             :     // reset caller loop num to 0 to mimic what plantloopequip was doing
     448      644606 :     Tank.callerLoopNum = 0;
     449      644606 : }
     450           0 : void HeatPumpWaterHeaterData::oneTimeInit([[maybe_unused]] EnergyPlusData &state)
     451             : {
     452           0 : }
     453             : 
     454     1420050 : void SimulateWaterHeaterStandAlone(EnergyPlusData &state, int const WaterHeaterNum, bool const FirstHVACIteration)
     455             : {
     456             : 
     457             :     // SUBROUTINE INFORMATION:
     458             :     //       AUTHOR         Peter Graham Ellis
     459             :     //       DATE WRITTEN   January 2004
     460             :     //       MODIFIED       July 2005, FSEC - added HPWHs and desuperheater water heating coils
     461             :     //       RE-ENGINEERED  na
     462             : 
     463             :     // PURPOSE OF THIS SUBROUTINE:
     464             :     // This subroutine acts an interface to SimWaterHeater for stand-alone water heaters with no plant connections,
     465             :     // HPWHs not defined as zone equipment with no plant connections, and stand-alone water heaters with
     466             :     // desuperheater heating coils with no plant connections.
     467             : 
     468             :     // METHODOLOGY EMPLOYED:
     469             :     // The necessary control flags and dummy variables are set and passed into SimWaterHeater. This subroutine is
     470             :     // called from NonZoneEquipmentManager.
     471             : 
     472             :     Real64 MyLoad;
     473             : 
     474     1420050 :     if (state.dataWaterThermalTanks->getWaterThermalTankInputFlag) {
     475           7 :         GetWaterThermalTankInput(state);
     476           7 :         state.dataWaterThermalTanks->getWaterThermalTankInputFlag = false;
     477             :     }
     478             : 
     479     1420050 :     auto &Tank = state.dataWaterThermalTanks->WaterThermalTank(WaterHeaterNum);
     480             : 
     481             :     // Only simulate stand-alone water heaters here.  Plant connected water heaters are called by the PlantLoopEquipments.
     482     1420050 :     if (Tank.StandAlone) {
     483      293710 :         bool localRunFlag = true;
     484      293710 :         PlantLocation A(0, DataPlant::LoopSideLocation::Invalid, 0, 0);
     485      293710 :         Tank.simulate(state, A, FirstHVACIteration, MyLoad, localRunFlag);
     486             : 
     487             :         // HPWHs with inlet air from a zone and not connected to a plant loop are simulated through a CALL from ZoneEquipmentManager.
     488             :         // HPWHs that are plant connected are always simulated through a CALL from PlantLoopEquipments directly to SimWaterThermalTank.
     489             : 
     490             :         // NOTE: HPWHs with inlet air from a zone AND plant connected are not stand alone and are simulated in PlantLoopEquipments
     491     1126340 :     } else if (Tank.HeatPumpNum > 0) {
     492             :         //   Only HPWHs with inlet air from outdoors or scheduled HPWHs (not connected to a plant loop) are simulated here.
     493             : 
     494      192042 :         auto &HPWaterHtr = state.dataWaterThermalTanks->HPWaterHeater(Tank.HeatPumpNum);
     495             : 
     496      293644 :         if (HPWaterHtr.StandAlone &&
     497      174016 :             (HPWaterHtr.InletAirConfiguration == WTTAmbientTemp::OutsideAir || HPWaterHtr.InletAirConfiguration == WTTAmbientTemp::Schedule)) {
     498       53326 :             bool LocalRunFlag = true;
     499       53326 :             PlantLocation A(0, DataPlant::LoopSideLocation::Invalid, 0, 0);
     500       53326 :             HPWaterHtr.simulate(state, A, FirstHVACIteration, MyLoad, LocalRunFlag);
     501             :         }
     502             : 
     503             :         // Only simulate stand-alone water heaters with desuperheater water heating coils here.  Plant connected water heaters
     504             :         // with desuperheater water heating coils are called by PlantLoopEquipments.
     505      934298 :     } else if (Tank.DesuperheaterNum > 0) {
     506       30050 :         if (state.dataWaterThermalTanks->WaterHeaterDesuperheater(Tank.DesuperheaterNum).StandAlone) {
     507       30050 :             bool localRunFlag = true;
     508       30050 :             PlantLocation A(0, DataPlant::LoopSideLocation::Invalid, 0, 0);
     509       30050 :             Tank.simulate(state, A, FirstHVACIteration, MyLoad, localRunFlag);
     510             :         }
     511             :     }
     512     1420050 : }
     513             : 
     514      256753 : void SimHeatPumpWaterHeater(EnergyPlusData &state,
     515             :                             std::string_view CompName,
     516             :                             bool const FirstHVACIteration,
     517             :                             Real64 &SensLoadMet, // sensible load met by this equipment and sent to zone, W
     518             :                             Real64 &LatLoadMet,  // net latent load met and sent to zone (kg/s), dehumid = negative
     519             :                             int &CompIndex)
     520             : {
     521             :     // SUBROUTINE INFORMATION:
     522             :     //       AUTHOR         Richard Raustad
     523             :     //       DATE WRITTEN   April 2005
     524             :     //       MODIFIED       Don Shirey, Aug 2009 (LatLoadMet)
     525             :     //       RE-ENGINEERED  na
     526             : 
     527             :     // PURPOSE OF THIS SUBROUTINE:
     528             :     // This subroutine acts as an interface to SimWaterHeater.
     529             :     // HPWHs defined as zone equipment and not connected to a plant loop are called here by ZoneEquipmentManager
     530             : 
     531             :     // METHODOLOGY EMPLOYED:
     532             :     // The necessary control flags and dummy variables are set and passed into SimWaterHeater.
     533             : 
     534      256753 :     if (state.dataWaterThermalTanks->getWaterThermalTankInputFlag) {
     535           0 :         GetWaterThermalTankInput(state);
     536           0 :         state.dataWaterThermalTanks->getWaterThermalTankInputFlag = false;
     537             :     }
     538             : 
     539             :     // Find the correct Heat Pump Water Heater
     540             :     int HeatPumpNum;
     541      256753 :     if (CompIndex == 0) {
     542          10 :         HeatPumpNum = UtilityRoutines::FindItemInList(CompName, state.dataWaterThermalTanks->HPWaterHeater);
     543          10 :         if (HeatPumpNum == 0) {
     544           0 :             ShowFatalError(state, "SimHeatPumpWaterHeater: Unit not found=" + std::string{CompName});
     545             :         }
     546          10 :         CompIndex = HeatPumpNum;
     547             :     } else {
     548      256743 :         HeatPumpNum = CompIndex;
     549      256743 :         if (HeatPumpNum > state.dataWaterThermalTanks->numHeatPumpWaterHeater || HeatPumpNum < 1) {
     550           0 :             ShowFatalError(state,
     551           0 :                            format("SimHeatPumpWaterHeater:  Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
     552             :                                   HeatPumpNum,
     553           0 :                                   state.dataWaterThermalTanks->numHeatPumpWaterHeater,
     554           0 :                                   CompName));
     555             :         }
     556             :     }
     557             : 
     558             :     // Only simulate HPWHs specified as zone equipment and not connected to a plant loop.
     559             :     // HPWHs not defined as zone equipment with no plant connections are simulated in NonZoneEquipmentManager.
     560             :     // Plant connected HPWHs are called by PlantLoopEquipments (but only those on supply side ).
     561             :     // HPWH will not be included in sizing calculations, fan is initialized only during BeginEnvrnFlag (FALSE during sizing)
     562             :     // (fan will be turned off during Standard Ratings procedure yielding incorrect results)
     563      256753 :     if (state.dataGlobal->DoingSizing) return;
     564             : 
     565             :     // For HPWHs, StandAlone means not connected to a plant loop (use nodes are not used, source nodes are connected to a HPWH)
     566      256743 :     if (state.dataWaterThermalTanks->HPWaterHeater(HeatPumpNum).StandAlone) {
     567       51222 :         bool LocalRunFlag = true;
     568             :         Real64 MyLoad;
     569             : 
     570       51222 :         PlantLocation A(0, DataPlant::LoopSideLocation::Invalid, 0, 0);
     571       51222 :         state.dataWaterThermalTanks->HPWaterHeater(HeatPumpNum).simulate(state, A, FirstHVACIteration, MyLoad, LocalRunFlag);
     572             : 
     573       51222 :         SensLoadMet = state.dataWaterThermalTanks->HPWaterHeater(HeatPumpNum).HPWaterHeaterSensibleCapacity;
     574       51222 :         LatLoadMet = state.dataWaterThermalTanks->HPWaterHeater(HeatPumpNum).HPWaterHeaterLatentCapacity;
     575             :     } else {
     576             :         // HPWH is plant connected and will get simulated when called from plant SimWaterThermalTank, but need to update loads met here
     577      205521 :         SensLoadMet = state.dataWaterThermalTanks->HPWaterHeater(HeatPumpNum).HPWaterHeaterSensibleCapacity;
     578      205521 :         LatLoadMet = state.dataWaterThermalTanks->HPWaterHeater(HeatPumpNum).HPWaterHeaterLatentCapacity;
     579             :     }
     580             : }
     581             : 
     582     2568509 : void CalcWaterThermalTankZoneGains(EnergyPlusData &state)
     583             : {
     584             : 
     585             :     // SUBROUTINE INFORMATION:
     586             :     //       AUTHOR         Peter Graham Ellis
     587             :     //       DATE WRITTEN   March 2005
     588             :     //       MODIFIED       B. Griffith November 2011, new internal gains structure
     589             :     //       RE-ENGINEERED  na
     590             : 
     591             :     // PURPOSE OF THIS SUBROUTINE:
     592             :     // Calculates the zone internal gains due to water heater skin losses during sizing.
     593             :     // initializes gains to zone at begin environment.
     594             : 
     595             :     // METHODOLOGY EMPLOYED:
     596             :     // Sums the tank losses from all of the water heaters in the zone to add as a gain to the zone.
     597             :     // Now used to determine tank losses during sizing.  Internal gains are summed in a centralized way now
     598             : 
     599     2568509 :     if (state.dataWaterThermalTanks->numWaterThermalTank == 0) {
     600             : 
     601     2063949 :         if (!state.dataGlobal->DoingSizing) {
     602     1490778 :             return;
     603             :         } else {
     604      573171 :             if (state.dataWaterThermalTanks->getWaterThermalTankInputFlag) {
     605         406 :                 GetWaterThermalTankInput(state);
     606         406 :                 state.dataWaterThermalTanks->getWaterThermalTankInputFlag = false;
     607             :             }
     608      573171 :             if (state.dataWaterThermalTanks->numWaterThermalTank == 0) return;
     609             :         }
     610             :     }
     611             : 
     612      504668 :     if (state.dataGlobal->BeginEnvrnFlag && state.dataWaterThermalTanks->calcWaterThermalTankZoneGainsMyEnvrnFlag) {
     613        3220 :         for (auto &e : state.dataWaterThermalTanks->WaterThermalTank) {
     614        1936 :             e.AmbientZoneGain = 0.0;
     615        1936 :             e.FuelEnergy = 0.0;
     616        1936 :             e.OffCycParaFuelEnergy = 0.0;
     617        1936 :             e.OnCycParaFuelEnergy = 0.0;
     618             :         }
     619        1284 :         state.dataWaterThermalTanks->calcWaterThermalTankZoneGainsMyEnvrnFlag = false;
     620             :     }
     621             : 
     622      504668 :     if (!state.dataGlobal->BeginEnvrnFlag) state.dataWaterThermalTanks->calcWaterThermalTankZoneGainsMyEnvrnFlag = true;
     623             : 
     624     1200536 :     for (int WaterThermalTankNum = 1; WaterThermalTankNum <= state.dataWaterThermalTanks->numWaterThermalTank; ++WaterThermalTankNum) {
     625      695868 :         auto &Tank = state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum);
     626      695868 :         if (Tank.AmbientTempZone == 0) continue;
     627      241812 :         auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(Tank.AmbientTempZone);
     628      241812 :         if (state.dataGlobal->DoingSizing) {
     629             :             // Initialize tank temperature to setpoint
     630             :             // (use HPWH or Desuperheater heating coil set point if applicable)
     631             :             int SchIndex;
     632      105084 :             if (Tank.HeatPumpNum > 0) {
     633       14844 :                 SchIndex = state.dataWaterThermalTanks->HPWaterHeater(Tank.HeatPumpNum).SetPointTempSchedule;
     634       90240 :             } else if (Tank.DesuperheaterNum > 0) {
     635        1350 :                 SchIndex = state.dataWaterThermalTanks->WaterHeaterDesuperheater(Tank.DesuperheaterNum).SetPointTempSchedule;
     636             :             } else {
     637       88890 :                 SchIndex = Tank.SetPointTempSchedule;
     638             :             }
     639             : 
     640             :             Real64 TankTemp;
     641      105084 :             Real64 QLossToZone = 0.0;
     642      105084 :             if (SchIndex > 0) {
     643      105084 :                 TankTemp = ScheduleManager::GetCurrentScheduleValue(state, SchIndex);
     644             :             } else {
     645           0 :                 TankTemp = 20.0;
     646             :             }
     647      105084 :             switch (Tank.WaterThermalTankType) {
     648       88896 :             case DataPlant::PlantEquipmentType::WtrHeaterMixed: {
     649      177792 :                 QLossToZone = max(Tank.OnCycLossCoeff * Tank.OnCycLossFracToZone, Tank.OffCycLossCoeff * Tank.OffCycLossFracToZone) *
     650       88896 :                               (TankTemp - thisZoneHB.MAT);
     651       88896 :                 break;
     652             :             }
     653        8094 :             case DataPlant::PlantEquipmentType::WtrHeaterStratified: {
     654       16188 :                 QLossToZone = max(Tank.Node(1).OnCycLossCoeff * Tank.SkinLossFracToZone, Tank.Node(1).OffCycLossCoeff * Tank.SkinLossFracToZone) *
     655        8094 :                               (TankTemp - thisZoneHB.MAT);
     656        8094 :                 break;
     657             :             }
     658        4050 :             case DataPlant::PlantEquipmentType::ChilledWaterTankMixed: {
     659        4050 :                 QLossToZone = Tank.OffCycLossCoeff * Tank.OffCycLossFracToZone * (TankTemp - thisZoneHB.MAT);
     660        4050 :                 break;
     661             :             }
     662        4044 :             case DataPlant::PlantEquipmentType::ChilledWaterTankStratified: {
     663        4044 :                 QLossToZone = Tank.Node(1).OffCycLossCoeff * Tank.SkinLossFracToZone * (TankTemp - thisZoneHB.MAT);
     664        4044 :                 break;
     665             :             }
     666           0 :             default:
     667           0 :                 break;
     668             :             }
     669      105084 :             Tank.AmbientZoneGain = QLossToZone;
     670             :         }
     671             :     }
     672             : }
     673             : 
     674           6 : bool getDesuperHtrInput(EnergyPlusData &state)
     675             : {
     676           6 :     bool ErrorsFound = false;
     677             :     static constexpr std::string_view RoutineName = "getDesuperHtrInput";
     678             :     // Make local copies of IPShortCut because other getinputs might overwrite the ones in state
     679          12 :     auto cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     680          12 :     auto cAlphaArgs = state.dataIPShortCut->cAlphaArgs;
     681          12 :     auto rNumericArgs = state.dataIPShortCut->rNumericArgs;
     682          12 :     auto lNumericFieldBlanks = state.dataIPShortCut->lNumericFieldBlanks;
     683          12 :     auto lAlphaFieldBlanks = state.dataIPShortCut->lAlphaFieldBlanks;
     684          12 :     auto cAlphaFieldNames = state.dataIPShortCut->cAlphaFieldNames;
     685          12 :     auto cNumericFieldNames = state.dataIPShortCut->cNumericFieldNames;
     686             : 
     687           6 :     cCurrentModuleObject = cCoilDesuperheater;
     688          12 :     for (int DesuperheaterNum = 1; DesuperheaterNum <= state.dataWaterThermalTanks->numWaterHeaterDesuperheater; ++DesuperheaterNum) {
     689             :         int NumAlphas;
     690             :         int NumNums;
     691             :         int IOStat;
     692           6 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     693             :                                                                  cCurrentModuleObject,
     694             :                                                                  DesuperheaterNum,
     695             :                                                                  cAlphaArgs,
     696             :                                                                  NumAlphas,
     697             :                                                                  rNumericArgs,
     698             :                                                                  NumNums,
     699             :                                                                  IOStat,
     700             :                                                                  lNumericFieldBlanks,
     701             :                                                                  lAlphaFieldBlanks,
     702             :                                                                  cAlphaFieldNames,
     703             :                                                                  cNumericFieldNames);
     704           6 :         UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
     705             : 
     706             :         // ErrorsFound will be set to True if problem was found, left untouched otherwise
     707           6 :         GlobalNames::VerifyUniqueCoilName(state, cCurrentModuleObject, cAlphaArgs(1), ErrorsFound, cCurrentModuleObject + " Name");
     708             : 
     709           6 :         auto &DesupHtr = state.dataWaterThermalTanks->WaterHeaterDesuperheater(DesuperheaterNum);
     710             : 
     711           6 :         DesupHtr.Name = cAlphaArgs(1);
     712           6 :         DesupHtr.Type = cCurrentModuleObject;
     713             : 
     714             :         //       convert availability schedule name to pointer
     715           6 :         if (!lAlphaFieldBlanks(2)) {
     716           6 :             DesupHtr.AvailSchedPtr = ScheduleManager::GetScheduleIndex(state, cAlphaArgs(2));
     717           6 :             if (DesupHtr.AvailSchedPtr == 0) {
     718           0 :                 ShowSevereError(state, "Invalid, " + cAlphaFieldNames(2) + " = " + cAlphaArgs(2));
     719           0 :                 ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + cAlphaArgs(1));
     720           0 :                 ErrorsFound = true;
     721             :             }
     722             :         } else {
     723           0 :             DesupHtr.AvailSchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
     724             :         }
     725             : 
     726             :         // convert schedule name to pointer
     727           6 :         DesupHtr.SetPointTempSchedule = ScheduleManager::GetScheduleIndex(state, cAlphaArgs(3));
     728           6 :         if (DesupHtr.SetPointTempSchedule == 0) {
     729           0 :             ShowSevereError(state, "Invalid, " + cAlphaFieldNames(3) + " = " + cAlphaArgs(3));
     730           0 :             ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + cAlphaArgs(1));
     731           0 :             ErrorsFound = true;
     732             :         }
     733             : 
     734           6 :         DesupHtr.DeadBandTempDiff = rNumericArgs(1);
     735           6 :         if (DesupHtr.DeadBandTempDiff <= 0.0 || DesupHtr.DeadBandTempDiff > 20.0) {
     736           0 :             ShowSevereError(state,
     737           0 :                             format("{} = {}: {} must be > 0 and <= 20. {} = {:.1T}",
     738             :                                    cCurrentModuleObject,
     739             :                                    DesupHtr.Name,
     740             :                                    cNumericFieldNames(1),
     741             :                                    cNumericFieldNames(1),
     742           0 :                                    rNumericArgs(1)));
     743           0 :             ErrorsFound = true;
     744             :         }
     745             : 
     746             :         // Error limits on heat reclaim efficiency applied after source type identified
     747             : 
     748           6 :         DesupHtr.RatedInletWaterTemp = rNumericArgs(3);
     749           6 :         DesupHtr.RatedOutdoorAirTemp = rNumericArgs(4);
     750           6 :         DesupHtr.MaxInletWaterTemp = rNumericArgs(5);
     751             : 
     752           6 :         if (!lAlphaFieldBlanks(4)) {
     753           6 :             DesupHtr.HEffFTemp = Curve::GetCurveIndex(state, cAlphaArgs(4));
     754           6 :             if (DesupHtr.HEffFTemp == 0) {
     755           0 :                 ShowSevereError(state, cCurrentModuleObject + " = " + DesupHtr.Name + ":  " + cAlphaFieldNames(4) + " not found = " + cAlphaArgs(4));
     756           0 :                 ErrorsFound = true;
     757             :             } else {
     758           6 :                 ErrorsFound |= Curve::CheckCurveDims(state,
     759             :                                                      DesupHtr.HEffFTemp,   // Curve index
     760             :                                                      {2},                  // Valid dimensions
     761             :                                                      RoutineName,          // Routine name
     762             :                                                      cCurrentModuleObject, // Object Type
     763             :                                                      DesupHtr.Name,        // Object Name
     764           6 :                                                      cAlphaFieldNames(4)); // Field Name
     765           6 :                 if (!ErrorsFound) {
     766           6 :                     if (DesupHtr.HEffFTemp > 0) {
     767          12 :                         Real64 HEffFTemp = min(
     768           6 :                             1.0, max(0.0, Curve::CurveValue(state, DesupHtr.HEffFTemp, DesupHtr.RatedInletWaterTemp, DesupHtr.RatedOutdoorAirTemp)));
     769           6 :                         if (std::abs(HEffFTemp - 1.0) > 0.05) {
     770           0 :                             ShowWarningError(state, cCurrentModuleObject + ", \"" + DesupHtr.Name + "\":");
     771           0 :                             ShowContinueError(state, "The " + cAlphaFieldNames(4) + " should be normalized ");
     772           0 :                             ShowContinueError(state, format(" to 1.0 at the rating point. Curve output at the rating point = {:.3T}", HEffFTemp));
     773           0 :                             ShowContinueError(state, " The simulation continues using the user-specified curve.");
     774             :                         }
     775             :                     }
     776             :                 }
     777             :             }
     778             :         }
     779             : 
     780           6 :         DesupHtr.WaterInletNode = NodeInputManager::GetOnlySingleNode(state,
     781           6 :                                                                       cAlphaArgs(5),
     782             :                                                                       ErrorsFound,
     783             :                                                                       DataLoopNode::ConnectionObjectType::CoilWaterHeatingDesuperheater,
     784           6 :                                                                       cAlphaArgs(1),
     785             :                                                                       DataLoopNode::NodeFluidType::Water,
     786             :                                                                       DataLoopNode::ConnectionType::Inlet,
     787             :                                                                       NodeInputManager::CompFluidStream::Primary,
     788           6 :                                                                       DataLoopNode::ObjectIsParent);
     789             : 
     790           6 :         DesupHtr.WaterOutletNode = NodeInputManager::GetOnlySingleNode(state,
     791           6 :                                                                        cAlphaArgs(6),
     792             :                                                                        ErrorsFound,
     793             :                                                                        DataLoopNode::ConnectionObjectType::CoilWaterHeatingDesuperheater,
     794           6 :                                                                        cAlphaArgs(1),
     795             :                                                                        DataLoopNode::NodeFluidType::Water,
     796             :                                                                        DataLoopNode::ConnectionType::Outlet,
     797             :                                                                        NodeInputManager::CompFluidStream::Primary,
     798           6 :                                                                        DataLoopNode::ObjectIsParent);
     799             : 
     800           6 :         DesupHtr.InletNodeName1 = cAlphaArgs(5);
     801           6 :         DesupHtr.OutletNodeName1 = cAlphaArgs(6);
     802             : 
     803           6 :         DesupHtr.TankType = cAlphaArgs(7);
     804             : 
     805           7 :         if (!UtilityRoutines::SameString(DesupHtr.TankType, cMixedWHModuleObj) &&
     806           1 :             !UtilityRoutines::SameString(DesupHtr.TankType, cStratifiedWHModuleObj)) {
     807             : 
     808           0 :             ShowSevereError(state, cCurrentModuleObject + " = " + state.dataWaterThermalTanks->HPWaterHeater(DesuperheaterNum).Name + ":");
     809           0 :             ShowContinueError(state, "Desuperheater can only be used with " + cMixedWHModuleObj + " or " + cStratifiedWHModuleObj + ".");
     810           0 :             ErrorsFound = true;
     811             :         }
     812             : 
     813           6 :         DesupHtr.TankName = cAlphaArgs(8);
     814             : 
     815             :         // Set up comp set for water side nodes (reverse inlet/outlet for water heater)
     816           6 :         BranchNodeConnections::SetUpCompSets(state, DesupHtr.Type, DesupHtr.Name, DesupHtr.TankType, DesupHtr.TankName, cAlphaArgs(6), cAlphaArgs(5));
     817             : 
     818          12 :         std::string const heatSourceObjType = cAlphaArgs(9);
     819             : 
     820          17 :         if ((UtilityRoutines::SameString(heatSourceObjType, "Refrigeration:Condenser:AirCooled")) ||
     821          17 :             (UtilityRoutines::SameString(heatSourceObjType, "Refrigeration:Condenser:EvaporativeCooled")) ||
     822          11 :             (UtilityRoutines::SameString(heatSourceObjType, "Refrigeration:Condenser:WaterCooled"))) {
     823           1 :             if (lNumericFieldBlanks(2)) {
     824           0 :                 DesupHtr.HeatReclaimRecoveryEff = 0.8;
     825             :             } else {
     826           1 :                 DesupHtr.HeatReclaimRecoveryEff = rNumericArgs(2);
     827           1 :                 if (DesupHtr.HeatReclaimRecoveryEff <= 0.0 || DesupHtr.HeatReclaimRecoveryEff > 0.9) {
     828           0 :                     ShowSevereError(state,
     829           0 :                                     format("{} = {}: {} must be > 0.0 and <= 0.9, Efficiency = {:.3T}",
     830             :                                            cCurrentModuleObject,
     831             :                                            DesupHtr.Name,
     832             :                                            cNumericFieldNames(2),
     833           0 :                                            DesupHtr.HeatReclaimRecoveryEff));
     834           0 :                     ErrorsFound = true;
     835             :                 }
     836             :             }    // Blank Num(2)
     837             :         } else { // max is 0.3 for all other sources
     838           5 :             if (lNumericFieldBlanks(2)) {
     839           0 :                 DesupHtr.HeatReclaimRecoveryEff = 0.25;
     840             :             } else {
     841           5 :                 DesupHtr.HeatReclaimRecoveryEff = rNumericArgs(2);
     842           5 :                 if (DesupHtr.HeatReclaimRecoveryEff <= 0.0 || DesupHtr.HeatReclaimRecoveryEff > 0.3) {
     843           0 :                     ShowSevereError(state,
     844           0 :                                     format("{} = {}: {} must be > 0.0 and <= 0.3, {} = {:.3T}",
     845             :                                            cCurrentModuleObject,
     846             :                                            DesupHtr.Name,
     847             :                                            cNumericFieldNames(2),
     848             :                                            cNumericFieldNames(2),
     849           0 :                                            DesupHtr.HeatReclaimRecoveryEff));
     850           0 :                     ErrorsFound = true;
     851             :                 }
     852             :             } // Blank Num(2)
     853             :         }     // setting limits on heat recovery efficiency
     854             : 
     855             :         //       Find the Refrigeration equipment index associated with the desuperheater heating coil.
     856           6 :         bool errFlag = false;
     857           6 :         DesupHtr.HeatingSourceType = heatSourceObjType;
     858           6 :         DesupHtr.HeatingSourceName = cAlphaArgs(10);
     859           6 :         if (UtilityRoutines::SameString(heatSourceObjType, "Refrigeration:CompressorRack")) {
     860           0 :             DesupHtr.ReclaimHeatingSource = ReclaimHeatObjectType::CompressorRackRefrigeratedCase;
     861           0 :             for (int RackNum = 1; RackNum <= state.dataRefrigCase->NumRefrigeratedRacks; ++RackNum) {
     862           0 :                 if (!UtilityRoutines::SameString(state.dataHeatBal->HeatReclaimRefrigeratedRack(RackNum).Name, cAlphaArgs(10))) continue;
     863           0 :                 DesupHtr.ReclaimHeatingSourceIndexNum = RackNum;
     864           0 :                 if (allocated(state.dataHeatBal->HeatReclaimRefrigeratedRack)) {
     865             :                     DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
     866           0 :                         state.dataHeatBal->HeatReclaimRefrigeratedRack(DesupHtr.ReclaimHeatingSourceIndexNum);
     867           0 :                     if (!allocated(HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat)) {
     868           0 :                         HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat.allocate(state.dataWaterThermalTanks->numWaterHeaterDesuperheater);
     869           0 :                         for (auto &num : HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat)
     870           0 :                             num = 0.0;
     871             :                     }
     872           0 :                     DesupHtr.ValidSourceType = true;
     873           0 :                     HeatReclaim.ReclaimEfficiencyTotal += DesupHtr.HeatReclaimRecoveryEff;
     874           0 :                     if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
     875           0 :                         ShowSevereError(state,
     876           0 :                                         cCurrentModuleObject + " = " + DesupHtr.Name +
     877             :                                             ": "
     878           0 :                                             " sum of heat reclaim recovery efficiencies from the same source coil: \"" +
     879           0 :                                             DesupHtr.HeatingSourceName + "\" cannot be over 0.3");
     880           0 :                         ErrorsFound = true;
     881             :                     }
     882             :                 }
     883           0 :                 break;
     884             :             }
     885          17 :         } else if ((UtilityRoutines::SameString(heatSourceObjType, "Refrigeration:Condenser:AirCooled")) ||
     886          17 :                    (UtilityRoutines::SameString(heatSourceObjType, "Refrigeration:Condenser:EvaporativeCooled")) ||
     887          11 :                    (UtilityRoutines::SameString(heatSourceObjType, "Refrigeration:Condenser:WaterCooled"))) {
     888           1 :             DesupHtr.ReclaimHeatingSource = ReclaimHeatObjectType::CondenserRefrigeration;
     889           2 :             for (int CondNum = 1; CondNum <= state.dataRefrigCase->NumRefrigCondensers; ++CondNum) {
     890           2 :                 if (!UtilityRoutines::SameString(state.dataHeatBal->HeatReclaimRefrigCondenser(CondNum).Name, cAlphaArgs(10))) continue;
     891           1 :                 DesupHtr.ReclaimHeatingSourceIndexNum = CondNum;
     892           1 :                 if (allocated(state.dataHeatBal->HeatReclaimRefrigCondenser)) {
     893             :                     DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
     894           1 :                         state.dataHeatBal->HeatReclaimRefrigCondenser(DesupHtr.ReclaimHeatingSourceIndexNum);
     895           1 :                     if (!allocated(HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat)) {
     896           1 :                         HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat.allocate(state.dataWaterThermalTanks->numWaterHeaterDesuperheater);
     897           2 :                         for (auto &num : HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat)
     898           1 :                             num = 0.0;
     899             :                     }
     900           1 :                     DesupHtr.ValidSourceType = true;
     901           1 :                     HeatReclaim.ReclaimEfficiencyTotal += DesupHtr.HeatReclaimRecoveryEff;
     902           1 :                     if (HeatReclaim.ReclaimEfficiencyTotal > 0.9) {
     903           0 :                         ShowSevereError(state,
     904           0 :                                         cCurrentModuleObject + " = " + DesupHtr.Name +
     905             :                                             ": "
     906           0 :                                             " sum of heat reclaim recovery efficiencies from the same source coil: \"" +
     907           0 :                                             DesupHtr.HeatingSourceName + "\" cannot be over 0.9");
     908           0 :                         ErrorsFound = true;
     909             :                     }
     910             :                 }
     911           1 :                 break;
     912             :             }
     913          13 :         } else if (UtilityRoutines::SameString(heatSourceObjType, "Coil:Cooling:DX:SingleSpeed") ||
     914          11 :                    UtilityRoutines::SameString(heatSourceObjType, "Coil:Cooling:DX:TwoSpeed") ||
     915          16 :                    UtilityRoutines::SameString(heatSourceObjType, "Coil:Cooling:DX:MultiSpeed") ||
     916           8 :                    UtilityRoutines::SameString(heatSourceObjType, "Coil:Cooling:DX:TwoStageWithHumidityControlMode")) {
     917             : 
     918           2 :             if (UtilityRoutines::SameString(heatSourceObjType, "Coil:Cooling:DX:SingleSpeed")) {
     919           2 :                 DesupHtr.ReclaimHeatingSource = ReclaimHeatObjectType::DXCooling;
     920           0 :             } else if (UtilityRoutines::SameString(heatSourceObjType, "Coil:Cooling:DX:TwoStageWithHumidityControlMode")) {
     921           0 :                 DesupHtr.ReclaimHeatingSource = ReclaimHeatObjectType::DXMultiMode;
     922             :             } else {
     923           0 :                 DesupHtr.ReclaimHeatingSource = ReclaimHeatObjectType::DXMultiSpeed;
     924             :             }
     925           2 :             DXCoils::GetDXCoilIndex(state, DesupHtr.HeatingSourceName, DesupHtr.ReclaimHeatingSourceIndexNum, errFlag, cCurrentModuleObject);
     926           2 :             if (allocated(state.dataHeatBal->HeatReclaimDXCoil)) {
     927           2 :                 DataHeatBalance::HeatReclaimDataBase &HeatReclaim = state.dataHeatBal->HeatReclaimDXCoil(DesupHtr.ReclaimHeatingSourceIndexNum);
     928           2 :                 if (!allocated(HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat)) {
     929           2 :                     HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat.allocate(state.dataWaterThermalTanks->numWaterHeaterDesuperheater);
     930           4 :                     for (auto &num : HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat)
     931           2 :                         num = 0.0;
     932             :                 }
     933           2 :                 DesupHtr.ValidSourceType = true;
     934           2 :                 HeatReclaim.ReclaimEfficiencyTotal += DesupHtr.HeatReclaimRecoveryEff;
     935           2 :                 if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
     936           0 :                     ShowSevereError(state,
     937           0 :                                     cCurrentModuleObject + " = " + DesupHtr.Name +
     938             :                                         ": "
     939           0 :                                         " sum of heat reclaim recovery efficiencies from the same source coil: \"" +
     940           0 :                                         DesupHtr.HeatingSourceName + "\" cannot be over 0.3");
     941           0 :                     ErrorsFound = true;
     942             :                 }
     943             :             }
     944           3 :         } else if (UtilityRoutines::SameString(heatSourceObjType, "Coil:Cooling:DX:VariableSpeed")) {
     945           1 :             DesupHtr.ReclaimHeatingSource = ReclaimHeatObjectType::DXVariableCooling;
     946           1 :             DesupHtr.ReclaimHeatingSourceIndexNum = VariableSpeedCoils::GetCoilIndexVariableSpeed(state, heatSourceObjType, cAlphaArgs(10), errFlag);
     947           1 :             if (allocated(state.dataHeatBal->HeatReclaimVS_DXCoil)) {
     948           1 :                 DataHeatBalance::HeatReclaimDataBase &HeatReclaim = state.dataHeatBal->HeatReclaimVS_DXCoil(DesupHtr.ReclaimHeatingSourceIndexNum);
     949           1 :                 if (!allocated(HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat)) {
     950           1 :                     HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat.allocate(state.dataWaterThermalTanks->numWaterHeaterDesuperheater);
     951           2 :                     for (auto &num : HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat)
     952           1 :                         num = 0.0;
     953             :                 }
     954           1 :                 DesupHtr.ValidSourceType = true;
     955           1 :                 HeatReclaim.ReclaimEfficiencyTotal += DesupHtr.HeatReclaimRecoveryEff;
     956           1 :                 if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
     957           0 :                     ShowSevereError(state,
     958           0 :                                     cCurrentModuleObject + " = " + DesupHtr.Name +
     959             :                                         ": "
     960           0 :                                         " sum of heat reclaim recovery efficiencies from the same source coil: \"" +
     961           0 :                                         DesupHtr.HeatingSourceName + "\" cannot be over 0.3");
     962           0 :                     ErrorsFound = true;
     963             :                 }
     964             :             }
     965           2 :         } else if (UtilityRoutines::SameString(heatSourceObjType, "Coil:Cooling:WaterToAirHeatPump:EquationFit")) {
     966           1 :             DesupHtr.ReclaimHeatingSource = ReclaimHeatObjectType::AirWaterHeatPumpEQ;
     967           1 :             DesupHtr.ReclaimHeatingSourceIndexNum = WaterToAirHeatPumpSimple::GetCoilIndex(state, heatSourceObjType, cAlphaArgs(10), errFlag);
     968           1 :             if (allocated(state.dataHeatBal->HeatReclaimSimple_WAHPCoil)) {
     969             :                 DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
     970           1 :                     state.dataHeatBal->HeatReclaimSimple_WAHPCoil(DesupHtr.ReclaimHeatingSourceIndexNum);
     971           1 :                 if (!allocated(HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat)) {
     972           1 :                     HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat.allocate(state.dataWaterThermalTanks->numWaterHeaterDesuperheater);
     973           2 :                     for (auto &num : HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat)
     974           1 :                         num = 0.0;
     975             :                 }
     976           1 :                 DesupHtr.ValidSourceType = true;
     977           1 :                 HeatReclaim.ReclaimEfficiencyTotal += DesupHtr.HeatReclaimRecoveryEff;
     978           1 :                 if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
     979           0 :                     ShowSevereError(state,
     980           0 :                                     cCurrentModuleObject + " = " + DesupHtr.Name +
     981             :                                         ": "
     982           0 :                                         " sum of heat reclaim recovery efficiencies from the same source coil: \"" +
     983           0 :                                         DesupHtr.HeatingSourceName + "\" cannot be over 0.3");
     984           0 :                     ErrorsFound = true;
     985             :                 }
     986             :             }
     987           1 :         } else if (UtilityRoutines::SameString(heatSourceObjType, "Coil:Cooling:DX")) {
     988           1 :             DesupHtr.ReclaimHeatingSource = ReclaimHeatObjectType::CoilCoolingDX;
     989           1 :             DesupHtr.ReclaimHeatingSourceIndexNum = CoilCoolingDX::factory(state, cAlphaArgs(10));
     990           1 :             if (DesupHtr.ReclaimHeatingSourceIndexNum < 0) {
     991           0 :                 ShowSevereError(
     992             :                     state,
     993           0 :                     format("{}={}, could not find desuperheater coil {}={}", cCurrentModuleObject, DesupHtr.Name, cAlphaArgs(9), cAlphaArgs(10)));
     994           0 :                 ErrorsFound = true;
     995             :             } else {
     996             :                 DataHeatBalance::HeatReclaimDataBase &HeatReclaim =
     997           1 :                     state.dataCoilCooingDX->coilCoolingDXs[DesupHtr.ReclaimHeatingSourceIndexNum].reclaimHeat;
     998           1 :                 if (!allocated(HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat)) {
     999           1 :                     HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat.allocate(state.dataWaterThermalTanks->numWaterHeaterDesuperheater);
    1000           2 :                     for (auto &num : HeatReclaim.WaterHeatingDesuperheaterReclaimedHeat)
    1001           1 :                         num = 0.0;
    1002             :                 }
    1003           1 :                 DesupHtr.ValidSourceType = true;
    1004           1 :                 HeatReclaim.ReclaimEfficiencyTotal += DesupHtr.HeatReclaimRecoveryEff;
    1005           1 :                 if (HeatReclaim.ReclaimEfficiencyTotal > 0.3) {
    1006           0 :                     ShowSevereError(state,
    1007           0 :                                     cCurrentModuleObject + ", \"" + DesupHtr.Name +
    1008           0 :                                         "\" sum of heat reclaim recovery efficiencies from the same source coil: \"" + DesupHtr.HeatingSourceName +
    1009             :                                         "\" cannot be over 0.3");
    1010           0 :                     ErrorsFound = true;
    1011             :                 }
    1012             :             }
    1013             :         } else {
    1014           0 :             ShowSevereError(state, cCurrentModuleObject + " = " + DesupHtr.Name + ':');
    1015           0 :             ShowContinueError(state, " desuperheater can only be used with Coil:Cooling:DX:SingleSpeed, ");
    1016           0 :             ShowContinueError(state,
    1017             :                               " Coil:Cooling:DX:TwoSpeed, Coil:Cooling:DX:MultiSpeed, Coil:Cooling:DX:TwoStageWithHumidityControlMode, "
    1018             :                               "Coil:Cooling:DX:VariableSpeed, "
    1019             :                               "Coil:Cooling:WaterToAirHeatPump:EquationFit, Refrigeration:CompressorRack,");
    1020           0 :             ShowContinueError(state, " Refrigeration:Condenser:AirCooled ,Refrigeration:Condenser:EvaporativeCooled, ");
    1021           0 :             ShowContinueError(state, " or Refrigeration:Condenser:WaterCooled.");
    1022           0 :             ShowContinueError(state, " Invalid desuperheater heat source object: " + heatSourceObjType + " \"" + cAlphaArgs(10) + "\"");
    1023           0 :             ErrorsFound = true;
    1024             :         }
    1025           6 :         if (errFlag) {
    1026           0 :             ShowContinueError(state, "...occurs in " + cCurrentModuleObject + '=' + DesupHtr.Name);
    1027           0 :             ErrorsFound = true;
    1028             :         }
    1029             : 
    1030           6 :         if (DesupHtr.ReclaimHeatingSourceIndexNum == 0 && DesupHtr.ReclaimHeatingSource != ReclaimHeatObjectType::CoilCoolingDX) {
    1031           0 :             ShowSevereError(state,
    1032           0 :                             cCurrentModuleObject + ", \"" + DesupHtr.Name + "\" desuperheater heat source object not found: " + heatSourceObjType +
    1033           0 :                                 " \"" + cAlphaArgs(10) + "\"");
    1034           0 :             ErrorsFound = true;
    1035             :         }
    1036             : 
    1037           6 :         DesupHtr.OperatingWaterFlowRate = rNumericArgs(6);
    1038           6 :         if (DesupHtr.OperatingWaterFlowRate <= 0.0) {
    1039           0 :             ShowSevereError(state,
    1040           0 :                             format("{} = {}: {} must be greater than 0. {} = {:.6T}",
    1041             :                                    cCurrentModuleObject,
    1042             :                                    DesupHtr.Name,
    1043             :                                    cNumericFieldNames(6),
    1044             :                                    cNumericFieldNames(6),
    1045           0 :                                    rNumericArgs(6)));
    1046           0 :             ErrorsFound = true;
    1047             :         }
    1048             : 
    1049           6 :         DesupHtr.PumpElecPower = rNumericArgs(7);
    1050           6 :         if (DesupHtr.PumpElecPower < 0.0) {
    1051           0 :             ShowSevereError(state,
    1052           0 :                             format("{} = {}: {} must be >= 0. {} = {:.2T}",
    1053             :                                    cCurrentModuleObject,
    1054             :                                    DesupHtr.Name,
    1055             :                                    cNumericFieldNames(7),
    1056             :                                    cNumericFieldNames(7),
    1057           0 :                                    rNumericArgs(7)));
    1058           0 :             ErrorsFound = true;
    1059             :         }
    1060             : 
    1061           6 :         if ((DesupHtr.PumpElecPower / DesupHtr.OperatingWaterFlowRate) > 7.9264e6) {
    1062           0 :             ShowWarningError(state,
    1063           0 :                              format("{} = {}: {} to {} ratio > 7.9264E6. {} to {} = {:.3T}",
    1064             :                                     cCurrentModuleObject,
    1065             :                                     DesupHtr.Name,
    1066             :                                     cNumericFieldNames(7),
    1067             :                                     cNumericFieldNames(6),
    1068             :                                     cNumericFieldNames(7),
    1069             :                                     cNumericFieldNames(6),
    1070           0 :                                     (DesupHtr.PumpElecPower / DesupHtr.OperatingWaterFlowRate)));
    1071           0 :             ShowContinueError(state, " Suggest reducing " + cNumericFieldNames(7) + " or increasing " + cNumericFieldNames(6) + '.');
    1072           0 :             ShowContinueError(state, " The simulation will continue using the user defined values.");
    1073             :         }
    1074             : 
    1075           6 :         DesupHtr.PumpFracToWater = rNumericArgs(8);
    1076           6 :         if (DesupHtr.PumpFracToWater < 0.0 || DesupHtr.PumpFracToWater > 1.0) {
    1077           0 :             ShowSevereError(state,
    1078           0 :                             format("{} = {}: {} must be >= 0 or <= 1. {} = {:.3T}",
    1079             :                                    cCurrentModuleObject,
    1080             :                                    DesupHtr.Name,
    1081             :                                    cNumericFieldNames(8),
    1082             :                                    cNumericFieldNames(8),
    1083           0 :                                    rNumericArgs(8)));
    1084           0 :             ErrorsFound = true;
    1085             :         }
    1086             : 
    1087           6 :         DesupHtr.OnCycParaLoad = rNumericArgs(9);
    1088           6 :         if (DesupHtr.OnCycParaLoad < 0.0) {
    1089           0 :             ShowSevereError(state,
    1090           0 :                             format("{} = {}: {} must be >= 0. {} = {:.2T}",
    1091             :                                    cCurrentModuleObject,
    1092             :                                    DesupHtr.Name,
    1093             :                                    cNumericFieldNames(9),
    1094             :                                    cNumericFieldNames(9),
    1095           0 :                                    rNumericArgs(9)));
    1096           0 :             ErrorsFound = true;
    1097             :         }
    1098             : 
    1099           6 :         DesupHtr.OffCycParaLoad = rNumericArgs(10);
    1100           6 :         if (DesupHtr.OffCycParaLoad < 0.0) {
    1101           0 :             ShowSevereError(state,
    1102           0 :                             format("{} = {}: {} must be >= 0. {} = {:.2T}",
    1103             :                                    cCurrentModuleObject,
    1104             :                                    DesupHtr.Name,
    1105             :                                    cNumericFieldNames(10),
    1106             :                                    cNumericFieldNames(10),
    1107           0 :                                    rNumericArgs(10)));
    1108           0 :             ErrorsFound = true;
    1109             :         }
    1110             :     }
    1111             : 
    1112           6 :     if (ErrorsFound) {
    1113           0 :         ShowFatalError(state, "Errors found in getting " + cCurrentModuleObject + " input. Preceding condition causes termination.");
    1114             :     }
    1115             : 
    1116          12 :     return ErrorsFound;
    1117             : 
    1118             : } // namespace WaterThermalTanks
    1119             : 
    1120           9 : bool getHPWaterHeaterInput(EnergyPlusData &state)
    1121             : {
    1122           9 :     bool ErrorsFound = false;
    1123             : 
    1124           9 :     int const NumPumpedCondenser = state.dataInputProcessing->inputProcessor->getNumObjectsFound(
    1125           9 :         state, cHPWHPumpedCondenser); // number of WaterHeater:HeatPump:PumpedCondenser objects
    1126             :     int nAlphaOffset;                 // the difference of array location between alpha items between pumped and wrapped condensers
    1127             :     int nNumericOffset;               // the difference of array location between numeric items between pumped and wrapped condensers
    1128             :     int nNumPossibleNumericArgs;      // the number of possible numeric arguments in the idd
    1129             :     int nNumPossibleAlphaArgs;        // the number of possible numeric arguments in the idd
    1130             : 
    1131             :     // For looking up in IDF/epJSON, you need the index that corresponds to the actual object type (Pumped or Wrapped)
    1132             :     int HPWaterHeaterNumOfSpecificType;
    1133             : 
    1134          32 :     for (int HPWaterHeaterNum = 1; HPWaterHeaterNum <= state.dataWaterThermalTanks->numHeatPumpWaterHeater; ++HPWaterHeaterNum) {
    1135             : 
    1136             :         // Create reference to current HPWH object in array.
    1137          23 :         HeatPumpWaterHeaterData &HPWH = state.dataWaterThermalTanks->HPWaterHeater(HPWaterHeaterNum);
    1138             : 
    1139             :         // Initialize the offsets to zero
    1140          23 :         nAlphaOffset = 0;
    1141          23 :         nNumericOffset = 0;
    1142             : 
    1143             :         DataLoopNode::ConnectionObjectType objType;
    1144             : 
    1145          23 :         if (HPWaterHeaterNum <= NumPumpedCondenser) {
    1146             :             // Pumped Condenser
    1147          20 :             state.dataIPShortCut->cCurrentModuleObject = cHPWHPumpedCondenser;
    1148          20 :             objType = DataLoopNode::ConnectionObjectType::WaterHeaterHeatPumpPumpedCondenser;
    1149          20 :             HPWH.HPWHType = DataPlant::PlantEquipmentType::HeatPumpWtrHeaterPumped;
    1150          20 :             nNumPossibleAlphaArgs = 29;
    1151          20 :             nNumPossibleNumericArgs = 9;
    1152             :             // Actual index of Pumped type
    1153          20 :             HPWaterHeaterNumOfSpecificType = HPWaterHeaterNum;
    1154             :         } else {
    1155             :             // Wrapped Condenser
    1156           3 :             state.dataIPShortCut->cCurrentModuleObject = cHPWHWrappedCondenser;
    1157           3 :             objType = DataLoopNode::ConnectionObjectType::WaterHeaterHeatPumpWrappedCondenser;
    1158           3 :             HPWH.HPWHType = DataPlant::PlantEquipmentType::HeatPumpWtrHeaterWrapped;
    1159           3 :             nNumPossibleAlphaArgs = 27;
    1160           3 :             nNumPossibleNumericArgs = 10;
    1161             :             // Actual index of Wrapped type
    1162           3 :             HPWaterHeaterNumOfSpecificType = HPWaterHeaterNum - NumPumpedCondenser;
    1163             :         }
    1164             : 
    1165             :         int NumAlphas;
    1166             :         int NumNums;
    1167             :         int IOStat;
    1168         184 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1169          23 :                                                                  state.dataIPShortCut->cCurrentModuleObject,
    1170             :                                                                  HPWaterHeaterNumOfSpecificType,
    1171          23 :                                                                  state.dataIPShortCut->cAlphaArgs,
    1172             :                                                                  NumAlphas,
    1173          23 :                                                                  state.dataIPShortCut->rNumericArgs,
    1174             :                                                                  NumNums,
    1175             :                                                                  IOStat,
    1176          23 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
    1177          23 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
    1178          23 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
    1179          23 :                                                                  state.dataIPShortCut->cNumericFieldNames);
    1180             : 
    1181             :         // Copy those lists into C++ std::maps
    1182          46 :         std::map<int, std::string> hpwhAlpha;
    1183          46 :         std::map<int, Real64> hpwhNumeric;
    1184          46 :         std::map<int, bool> hpwhAlphaBlank;
    1185          46 :         std::map<int, bool> hpwhNumericBlank;
    1186          46 :         std::map<int, std::string> hpwhAlphaFieldNames;
    1187          46 :         std::map<int, std::string> hpwhNumericFieldNames;
    1188         204 :         for (int i = 1; i <= NumNums; ++i) {
    1189         181 :             hpwhNumeric[i] = state.dataIPShortCut->rNumericArgs(i);
    1190         181 :             hpwhNumericBlank[i] = state.dataIPShortCut->lNumericFieldBlanks(i);
    1191         181 :             hpwhNumericFieldNames[i] = state.dataIPShortCut->cNumericFieldNames(i);
    1192             :         }
    1193          55 :         for (int i = NumNums + 1; i <= nNumPossibleNumericArgs; ++i) {
    1194          32 :             hpwhNumericBlank[i] = true;
    1195             :         }
    1196         642 :         for (int i = 1; i <= NumAlphas; ++i) {
    1197         619 :             hpwhAlpha[i] = state.dataIPShortCut->cAlphaArgs(i);
    1198         619 :             hpwhAlphaBlank[i] = state.dataIPShortCut->lAlphaFieldBlanks(i);
    1199         619 :             hpwhAlphaFieldNames[i] = state.dataIPShortCut->cAlphaFieldNames(i);
    1200             :         }
    1201          65 :         for (int i = NumAlphas + 1; i <= nNumPossibleAlphaArgs; ++i) {
    1202          42 :             hpwhAlphaBlank[i] = true;
    1203             :         }
    1204          23 :         UtilityRoutines::IsNameEmpty(state, hpwhAlpha[1], state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
    1205             : 
    1206             :         // Name and type
    1207          23 :         HPWH.Name = hpwhAlpha[1];
    1208          23 :         HPWH.Type = state.dataIPShortCut->cCurrentModuleObject;
    1209             : 
    1210             :         // Availability Schedule
    1211             :         // convert schedule name to pointer
    1212          23 :         if (!hpwhAlphaBlank[2]) {
    1213          23 :             HPWH.AvailSchedPtr = ScheduleManager::GetScheduleIndex(state, hpwhAlpha[2]);
    1214          23 :             if (HPWH.AvailSchedPtr == 0) {
    1215           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", not found");
    1216           0 :                 ShowContinueError(state, hpwhAlphaFieldNames[2] + "=\"" + hpwhAlpha[2] + "\".");
    1217           0 :                 ErrorsFound = true;
    1218             :             }
    1219             :         } else {
    1220           0 :             HPWH.AvailSchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
    1221             :         }
    1222             : 
    1223             :         // Compressor Setpoint Temperature Schedule
    1224             :         // convert schedule name to pointer
    1225          23 :         if (!hpwhAlphaBlank[3]) {
    1226          23 :             HPWH.SetPointTempSchedule = ScheduleManager::GetScheduleIndex(state, hpwhAlpha[3]);
    1227          23 :             if (HPWH.SetPointTempSchedule == 0) {
    1228           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", not found");
    1229           0 :                 ShowContinueError(state, hpwhAlphaFieldNames[3] + "=\"" + hpwhAlpha[3] + "\".");
    1230           0 :                 ErrorsFound = true;
    1231             :             }
    1232             :         } else {
    1233           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", ");
    1234           0 :             ShowContinueError(state, "required " + hpwhAlphaFieldNames[3] + " is blank.");
    1235           0 :             ErrorsFound = true;
    1236             :         }
    1237             : 
    1238             :         // Dead Band Temperature Difference
    1239          23 :         HPWH.DeadBandTempDiff = hpwhNumeric[1 + nNumericOffset];
    1240          23 :         if (HPWH.DeadBandTempDiff <= 0.0 || HPWH.DeadBandTempDiff > 20.0) {
    1241           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", ");
    1242           0 :             ShowContinueError(state,
    1243           0 :                               hpwhNumericFieldNames[1 + nNumericOffset] +
    1244           0 :                                   format(" difference must be > 0 and <= 20. Dead band = {:.1T}", hpwhNumeric[1 + nNumericOffset]));
    1245           0 :             ErrorsFound = true;
    1246             :         }
    1247             : 
    1248          23 :         if (HPWH.HPWHType == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterPumped) {
    1249             : 
    1250             :             // Condenser Inlet/Outlet Nodes
    1251          60 :             HPWH.CondWaterInletNode = NodeInputManager::GetOnlySingleNode(state,
    1252          40 :                                                                           hpwhAlpha[4],
    1253             :                                                                           ErrorsFound,
    1254             :                                                                           objType,
    1255             :                                                                           HPWH.Name,
    1256             :                                                                           DataLoopNode::NodeFluidType::Water,
    1257             :                                                                           DataLoopNode::ConnectionType::Inlet,
    1258             :                                                                           NodeInputManager::CompFluidStream::Secondary,
    1259          20 :                                                                           DataLoopNode::ObjectIsParent);
    1260          20 :             HPWH.InletNodeName1 = hpwhAlpha[4];
    1261          60 :             HPWH.CondWaterOutletNode = NodeInputManager::GetOnlySingleNode(state,
    1262          40 :                                                                            hpwhAlpha[5],
    1263             :                                                                            ErrorsFound,
    1264             :                                                                            objType,
    1265             :                                                                            HPWH.Name,
    1266             :                                                                            DataLoopNode::NodeFluidType::Water,
    1267             :                                                                            DataLoopNode::ConnectionType::Outlet,
    1268             :                                                                            NodeInputManager::CompFluidStream::Secondary,
    1269          20 :                                                                            DataLoopNode::ObjectIsParent);
    1270          20 :             HPWH.OutletNodeName1 = hpwhAlpha[5];
    1271             : 
    1272             :             // Condenser Water Flow Rate
    1273          20 :             HPWH.OperatingWaterFlowRate = hpwhNumeric[2];
    1274          20 :             if (HPWH.OperatingWaterFlowRate <= 0.0 && hpwhNumeric[2] != DataGlobalConstants::AutoCalculate) {
    1275           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", ");
    1276           0 :                 ShowContinueError(state,
    1277           0 :                                   format("{} must be greater than 0. Condenser water flow rate = {:.6T}", hpwhNumericFieldNames[2], hpwhNumeric[2]));
    1278           0 :                 ErrorsFound = true;
    1279             :             }
    1280             : 
    1281           3 :         } else if (HPWH.HPWHType == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterWrapped) {
    1282             : 
    1283             :             // Wrapped Condenser Location
    1284           3 :             HPWH.WrappedCondenserBottomLocation = hpwhNumeric[2 + nNumericOffset];
    1285           3 :             HPWH.WrappedCondenserTopLocation = hpwhNumeric[3 + nNumericOffset];
    1286             : 
    1287           3 :             if (HPWH.WrappedCondenserBottomLocation < 0.0) {
    1288           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", ");
    1289           0 :                 ShowContinueError(state,
    1290           0 :                                   format("{} must be greater than 0. Condenser bottom location = {:.6T}",
    1291           0 :                                          hpwhNumericFieldNames[2],
    1292           0 :                                          HPWH.WrappedCondenserBottomLocation));
    1293           0 :                 ErrorsFound = true;
    1294             :             }
    1295             : 
    1296           3 :             if (HPWH.WrappedCondenserBottomLocation >= HPWH.WrappedCondenserTopLocation) {
    1297           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", ");
    1298           0 :                 ShowContinueError(state,
    1299           0 :                                   format("{} ({:.6T}) must be greater than {} ({:.6T}).",
    1300             :                                          HPWH.WrappedCondenserTopLocation,
    1301           0 :                                          hpwhNumericFieldNames[2],
    1302           0 :                                          hpwhNumericFieldNames[3],
    1303           0 :                                          HPWH.WrappedCondenserBottomLocation));
    1304           0 :                 ErrorsFound = true;
    1305             :             }
    1306             : 
    1307             :             // Reset the offset
    1308           3 :             nAlphaOffset = -2;
    1309           3 :             nNumericOffset = 1;
    1310             : 
    1311             :         } else {
    1312           0 :             assert(0);
    1313             :         }
    1314             : 
    1315             :         // Evaporator Air Flow Rate
    1316          23 :         HPWH.OperatingAirFlowRate = hpwhNumeric[3 + nNumericOffset];
    1317          23 :         if (HPWH.OperatingAirFlowRate <= 0.0 && hpwhNumeric[3 + nNumericOffset] != DataGlobalConstants::AutoCalculate) {
    1318           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", ");
    1319           0 :             ShowContinueError(state,
    1320           0 :                               hpwhNumericFieldNames[3 + nNumericOffset] +
    1321           0 :                                   format(" must be greater than 0. Evaporator air flow rate = {:.6T}", hpwhNumeric[3 + nNumericOffset]));
    1322           0 :             ErrorsFound = true;
    1323             :         }
    1324             : 
    1325             :         // Inlet Air Configuration
    1326          23 :         HPWH.InletAirConfiguration =
    1327          46 :             static_cast<WTTAmbientTemp>(getEnumerationValue(HPWHAmbientTempNamesUC, UtilityRoutines::MakeUPPERCase(hpwhAlpha[6 + nAlphaOffset])));
    1328          23 :         switch (HPWH.InletAirConfiguration) {
    1329           3 :         case WTTAmbientTemp::Schedule: {
    1330             : 
    1331             :             // Inlet Air Temperature Schedule
    1332           3 :             if (!hpwhAlphaBlank[11 + nAlphaOffset]) {
    1333           3 :                 HPWH.AmbientTempSchedule = ScheduleManager::GetScheduleIndex(state, hpwhAlpha[11 + nAlphaOffset]);
    1334           3 :                 if (HPWH.AmbientTempSchedule == 0) {
    1335           0 :                     ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", not found");
    1336           0 :                     ShowContinueError(state, hpwhAlphaFieldNames[11 + nAlphaOffset] + "=\"" + hpwhAlpha[11 + nAlphaOffset] + "\".");
    1337           0 :                     ErrorsFound = true;
    1338             :                 }
    1339             :             } else {
    1340           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", ");
    1341           0 :                 ShowContinueError(state, "required " + hpwhAlphaFieldNames[11 + nAlphaOffset] + " is blank.");
    1342           0 :                 ErrorsFound = true;
    1343             :             }
    1344             : 
    1345             :             // Inlet Air Humidity Schedule
    1346           3 :             if (!hpwhAlphaBlank[12 + nAlphaOffset]) {
    1347           3 :                 HPWH.AmbientRHSchedule = ScheduleManager::GetScheduleIndex(state, hpwhAlpha[12 + nAlphaOffset]);
    1348           3 :                 if (HPWH.AmbientRHSchedule == 0) {
    1349           0 :                     ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", not found");
    1350           0 :                     ShowContinueError(state, hpwhAlphaFieldNames[12 + nAlphaOffset] + "=\"" + hpwhAlpha[12 + nAlphaOffset] + "\".");
    1351           0 :                     ErrorsFound = true;
    1352             :                 } else {
    1353           3 :                     if (!ScheduleManager::CheckScheduleValueMinMax(state, HPWH.AmbientRHSchedule, ">=", 0.0, "<=", 1.0)) {
    1354           0 :                         ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", invalid values");
    1355           0 :                         ShowContinueError(state,
    1356           0 :                                           hpwhAlphaFieldNames[12 + nAlphaOffset] + "=\"" + hpwhAlpha[12 + nAlphaOffset] +
    1357             :                                               "\", schedule values must be (>=0., <=1.)");
    1358           0 :                         ErrorsFound = true;
    1359             :                     }
    1360             :                 }
    1361             :             } else {
    1362           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", ");
    1363           0 :                 ShowContinueError(state, "required " + hpwhAlphaFieldNames[12 + nAlphaOffset] + " is blank.");
    1364           0 :                 ErrorsFound = true;
    1365             :             }
    1366             : 
    1367           3 :             break;
    1368             :         }
    1369          10 :         case WTTAmbientTemp::ZoneAndOA:
    1370             :         case WTTAmbientTemp::TempZone: {
    1371             : 
    1372             :             // Inlet Air Zone
    1373          10 :             if (!hpwhAlphaBlank[13 + nAlphaOffset]) {
    1374          10 :                 HPWH.AmbientTempZone = UtilityRoutines::FindItemInList(hpwhAlpha[13 + nAlphaOffset], state.dataHeatBal->Zone);
    1375          10 :                 if (HPWH.AmbientTempZone == 0) {
    1376           0 :                     ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", not found");
    1377           0 :                     ShowContinueError(state, hpwhAlphaFieldNames[13 + nAlphaOffset] + "=\"" + hpwhAlpha[13 + nAlphaOffset] + "\".");
    1378           0 :                     ErrorsFound = true;
    1379             :                 }
    1380             :             } else {
    1381           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", ");
    1382           0 :                 ShowContinueError(state, "required " + hpwhAlphaFieldNames[13 + nAlphaOffset] + " is blank.");
    1383           0 :                 ErrorsFound = true;
    1384             :             }
    1385          10 :             break;
    1386             :         }
    1387          10 :         default:
    1388             :         case WTTAmbientTemp::OutsideAir:
    1389          10 :             break;
    1390             :         }
    1391             : 
    1392             :         // Read air inlet nodes after mixer/splitter nodes have been read in (state.dataIPShortCut->cAlphaArgs 7-10),
    1393             :         // Node_ConnectionType differs for inlet node if mixer/splitter node exists
    1394             : 
    1395             :         // Tank Name
    1396             :         // We will verify this exists and is the right kind of tank later when the tanks are all loaded.
    1397          23 :         HPWH.TankName = hpwhAlpha[15 + nAlphaOffset];
    1398          23 :         HPWH.TankType = hpwhAlpha[14 + nAlphaOffset];
    1399             : 
    1400             :         // Use Side Inlet/Outlet
    1401             :         // Get the water heater tank use side inlet node names for HPWHs connected to a plant loop
    1402             :         // Save the name of the node for use with set up comp sets
    1403          23 :         HPWH.InletNodeName2 = hpwhAlpha[16 + nAlphaOffset];
    1404          23 :         HPWH.OutletNodeName2 = hpwhAlpha[17 + nAlphaOffset];
    1405             : 
    1406          23 :         if (!hpwhAlphaBlank[16 + nAlphaOffset] && !hpwhAlphaBlank[17 + nAlphaOffset]) {
    1407          10 :             HPWH.WHUseInletNode = NodeInputManager::GetOnlySingleNode(state,
    1408             :                                                                       HPWH.InletNodeName2,
    1409             :                                                                       ErrorsFound,
    1410             :                                                                       objType,
    1411             :                                                                       HPWH.Name,
    1412             :                                                                       DataLoopNode::NodeFluidType::Water,
    1413             :                                                                       DataLoopNode::ConnectionType::Inlet,
    1414             :                                                                       NodeInputManager::CompFluidStream::Primary,
    1415          10 :                                                                       DataLoopNode::ObjectIsParent);
    1416          10 :             HPWH.WHUseOutletNode = NodeInputManager::GetOnlySingleNode(state,
    1417             :                                                                        HPWH.OutletNodeName2,
    1418             :                                                                        ErrorsFound,
    1419             :                                                                        objType,
    1420             :                                                                        HPWH.Name,
    1421             :                                                                        DataLoopNode::NodeFluidType::Water,
    1422             :                                                                        DataLoopNode::ConnectionType::Outlet,
    1423             :                                                                        NodeInputManager::CompFluidStream::Primary,
    1424          10 :                                                                        DataLoopNode::ObjectIsParent);
    1425             :         }
    1426             : 
    1427             :         // DX Coil
    1428             :         // get Coil:DX:HeatPumpWaterHeater object
    1429          23 :         HPWH.DXCoilName = hpwhAlpha[19 + nAlphaOffset];
    1430          23 :         HPWH.DXCoilType = hpwhAlpha[18 + nAlphaOffset];
    1431             : 
    1432             :         // check that the DX Coil exists
    1433          23 :         bool DXCoilErrFlag = false;
    1434          23 :         bool bIsVScoil = false;
    1435          23 :         DXCoils::GetDXCoilIndex(state, HPWH.DXCoilName, HPWH.DXCoilNum, DXCoilErrFlag, state.dataIPShortCut->cCurrentModuleObject, true);
    1436          23 :         if (DXCoilErrFlag) {
    1437             :             // This could be a variable speed heat pump water heater
    1438           7 :             bool bVSCoilErrFlag = false;
    1439             : 
    1440           7 :             bool checkIHPFirst = IntegratedHeatPump::IHPInModel(state);
    1441           7 :             if (checkIHPFirst) {
    1442           1 :                 HPWH.DXCoilNum =
    1443           2 :                     IntegratedHeatPump::GetCoilIndexIHP(state, "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE", HPWH.DXCoilName, bVSCoilErrFlag);
    1444             : 
    1445           1 :                 if (!bVSCoilErrFlag) {
    1446           1 :                     HPWH.bIsIHP = true;
    1447             :                 }
    1448             :             }
    1449             : 
    1450           7 :             if (bVSCoilErrFlag || !checkIHPFirst) {
    1451           6 :                 bVSCoilErrFlag = false;
    1452           6 :                 HPWH.DXCoilNum = VariableSpeedCoils::GetCoilIndexVariableSpeed(
    1453             :                     state, "Coil:WaterHeating:AirToWaterHeatPump:VariableSpeed", HPWH.DXCoilName, bVSCoilErrFlag);
    1454             : 
    1455           6 :                 if (bVSCoilErrFlag) {
    1456           0 :                     ShowContinueError(state, "...occurs in " + state.dataIPShortCut->cCurrentModuleObject + " =" + HPWH.Name);
    1457           0 :                     ShowContinueError(state, "...could not find either DXCoils::DXCoil or Variable Speed Coil " + HPWH.DXCoilName);
    1458           0 :                     ErrorsFound = true;
    1459             :                 }
    1460             :             }
    1461             : 
    1462           7 :             bIsVScoil = true;
    1463           7 :             HPWH.DXCoilTypeNum = 0;
    1464           7 :             if (HPWH.bIsIHP) {
    1465           1 :                 HPWH.DXCoilType = "COILSYSTEM:INTEGRATEDHEATPUMP:AIRSOURCE";
    1466             :             } else {
    1467           6 :                 HPWH.DXCoilType = state.dataVariableSpeedCoils->VarSpeedCoil(HPWH.DXCoilNum).VarSpeedCoilType;
    1468             :             }
    1469             :         } else {
    1470             :             // this is a single speed coil
    1471          16 :             DXCoils::DXCoilData &Coil = state.dataDXCoils->DXCoil(HPWH.DXCoilNum);
    1472          16 :             if (!UtilityRoutines::SameString(HPWH.DXCoilType, Coil.DXCoilType)) {
    1473           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", ");
    1474           0 :                 ShowContinueError(state, "specifies the coil " + HPWH.DXCoilType + "=\"" + HPWH.DXCoilName + "\".");
    1475           0 :                 ShowContinueError(state, "However, " + HPWH.DXCoilName + " is a coil of type " + Coil.DXCoilType + ".");
    1476           0 :                 ErrorsFound = true;
    1477             :             }
    1478          16 :             HPWH.DXCoilTypeNum = Coil.DXCoilType_Num;
    1479             :         }
    1480             : 
    1481             :         // Make sure that the coil and tank are compatible.
    1482          23 :         if (bIsVScoil) {
    1483           7 :             if (HPWH.HPWHType != DataPlant::PlantEquipmentType::HeatPumpWtrHeaterPumped) {
    1484           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    1485           0 :                 ShowContinueError(state,
    1486             :                                   "Coil:WaterHeating:AirToWaterHeatPump:VariableSpeed can only be used with a pumped condenser heat pump "
    1487             :                                   "water heater.");
    1488           0 :                 ErrorsFound = true;
    1489             :             }
    1490             :         } else {
    1491          32 :             if (!((HPWH.DXCoilTypeNum == DataHVACGlobals::CoilDX_HeatPumpWaterHeaterPumped &&
    1492          13 :                    HPWH.HPWHType == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterPumped) ||
    1493           6 :                   (HPWH.DXCoilTypeNum == DataHVACGlobals::CoilDX_HeatPumpWaterHeaterWrapped &&
    1494           3 :                    HPWH.HPWHType == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterWrapped))) {
    1495           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    1496           0 :                 std::string ExpectedCoilType;
    1497           0 :                 if (HPWH.HPWHType == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterPumped) {
    1498           0 :                     ExpectedCoilType = DataHVACGlobals::cAllCoilTypes(DataHVACGlobals::CoilDX_HeatPumpWaterHeaterPumped);
    1499           0 :                 } else if (HPWH.HPWHType == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterWrapped) {
    1500           0 :                     ExpectedCoilType = DataHVACGlobals::cAllCoilTypes(DataHVACGlobals::CoilDX_HeatPumpWaterHeaterWrapped);
    1501             :                 } else {
    1502           0 :                     assert(0);
    1503             :                 }
    1504           0 :                 ShowContinueError(state, "can only be used with " + ExpectedCoilType);
    1505           0 :                 ErrorsFound = true;
    1506             :             }
    1507             :         }
    1508             : 
    1509             :         // Dummy condenser Inlet/Outlet Nodes for wrapped tanks
    1510          23 :         if (HPWH.DXCoilTypeNum == DataHVACGlobals::CoilDX_HeatPumpWaterHeaterWrapped) {
    1511           3 :             DXCoils::DXCoilData &Coil = state.dataDXCoils->DXCoil(HPWH.DXCoilNum);
    1512             : 
    1513           3 :             HPWH.InletNodeName1 = "DUMMY CONDENSER INLET " + Coil.Name;
    1514           3 :             HPWH.CondWaterInletNode = NodeInputManager::GetOnlySingleNode(state,
    1515             :                                                                           HPWH.InletNodeName1,
    1516             :                                                                           ErrorsFound,
    1517             :                                                                           objType,
    1518             :                                                                           HPWH.Name,
    1519             :                                                                           DataLoopNode::NodeFluidType::Water,
    1520             :                                                                           DataLoopNode::ConnectionType::Inlet,
    1521             :                                                                           NodeInputManager::CompFluidStream::Secondary,
    1522           3 :                                                                           DataLoopNode::ObjectIsParent);
    1523           3 :             HPWH.OutletNodeName1 = "DUMMY CONDENSER OUTLET " + Coil.Name;
    1524           3 :             HPWH.CondWaterOutletNode = NodeInputManager::GetOnlySingleNode(state,
    1525             :                                                                            HPWH.OutletNodeName1,
    1526             :                                                                            ErrorsFound,
    1527             :                                                                            objType,
    1528             :                                                                            HPWH.Name,
    1529             :                                                                            DataLoopNode::NodeFluidType::Water,
    1530             :                                                                            DataLoopNode::ConnectionType::Outlet,
    1531             :                                                                            NodeInputManager::CompFluidStream::Secondary,
    1532           3 :                                                                            DataLoopNode::ObjectIsParent);
    1533             :         }
    1534             : 
    1535             :         // Minimum Inlet Air Temperature for Compressor Operation
    1536          23 :         HPWH.MinAirTempForHPOperation = hpwhNumeric[4 + nNumericOffset];
    1537             : 
    1538             :         // Maximum Inlet Air Temperature for Compressor Operation
    1539          23 :         HPWH.MaxAirTempForHPOperation = hpwhNumeric[5 + nNumericOffset];
    1540          23 :         if (HPWH.MaxAirTempForHPOperation <= HPWH.MinAirTempForHPOperation) {
    1541           0 :             ShowWarningError(state,
    1542           0 :                              state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name +
    1543             :                                  "\": maximum inlet air temperature for heat pump compressor operation");
    1544           0 :             ShowContinueError(state, "must be greater than the minimum inlet air temperature for heat pump compressor operation.");
    1545           0 :             ShowContinueError(state, format("...Minimum inlet air temperature = {:.1T}", HPWH.MinAirTempForHPOperation));
    1546           0 :             ShowContinueError(state, format("...Maximum inlet air temperature = {:.1T}", HPWH.MaxAirTempForHPOperation));
    1547             :         }
    1548             : 
    1549             :         // Compressor Location
    1550          23 :         HPWH.CrankcaseTempIndicator = static_cast<CrankcaseHeaterControlTemp>(
    1551          46 :             getEnumerationValue(CrankcaseHeaterControlTempNamesUC, UtilityRoutines::MakeUPPERCase(hpwhAlpha[20 + nAlphaOffset])));
    1552          23 :         switch (HPWH.CrankcaseTempIndicator) {
    1553           3 :         case CrankcaseHeaterControlTemp::Schedule: {
    1554           3 :             if (!hpwhAlphaBlank[21 + nAlphaOffset]) {
    1555             :                 // Compressor Ambient Temperature Schedule
    1556           3 :                 HPWH.CrankcaseTempSchedule = ScheduleManager::GetScheduleIndex(state, hpwhAlpha[21 + nAlphaOffset]);
    1557           3 :                 if (HPWH.CrankcaseTempSchedule == 0) {
    1558           0 :                     ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", not found");
    1559           0 :                     ShowContinueError(state, hpwhAlphaFieldNames[21 + nAlphaOffset] + "=\"" + hpwhAlpha[21 + nAlphaOffset] + "\".");
    1560           0 :                     ErrorsFound = true;
    1561             :                 }
    1562             :             } else {
    1563           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", ");
    1564           0 :                 ShowContinueError(state, "required " + hpwhAlphaFieldNames[21 + nAlphaOffset] + " is blank.");
    1565           0 :                 ErrorsFound = true;
    1566             :             }
    1567             : 
    1568           3 :             break;
    1569             :         }
    1570          10 :         case CrankcaseHeaterControlTemp::Zone: {
    1571          10 :             if (HPWH.InletAirConfiguration == WTTAmbientTemp::OutsideAir || HPWH.InletAirConfiguration == WTTAmbientTemp::Schedule) {
    1572           0 :                 ShowSevereError(state,
    1573           0 :                                 state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name +
    1574             :                                     "\":  Inlet Air Configuration must be Zone Air Only or Zone And");
    1575           0 :                 ShowContinueError(state, " Outdoor Air when compressor location equals ZONE.");
    1576           0 :                 ErrorsFound = true;
    1577             :             }
    1578             : 
    1579          10 :             if (!hpwhAlphaBlank[21 + nAlphaOffset]) {
    1580           0 :                 ShowWarningError(state,
    1581           0 :                                  state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\"  " + hpwhAlphaFieldNames[21 + nAlphaOffset] +
    1582           0 :                                      " was provided but will not be used based on compressor location input=\"" + hpwhAlpha[20 + nAlphaOffset] +
    1583             :                                      "\".");
    1584             :             }
    1585          10 :             break;
    1586             :         }
    1587          10 :         case CrankcaseHeaterControlTemp::Outdoors: {
    1588          10 :             if (!hpwhAlphaBlank[21 + nAlphaOffset]) {
    1589           0 :                 ShowWarningError(state,
    1590           0 :                                  state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\"  " + hpwhAlphaFieldNames[21 + nAlphaOffset] +
    1591           0 :                                      " was provided but will not be used based on " + hpwhAlphaFieldNames[21 + nAlphaOffset] + "=\"" +
    1592           0 :                                      hpwhAlpha[20 + nAlphaOffset] + "\".");
    1593             :             }
    1594          10 :             break;
    1595             :         }
    1596           0 :         default:
    1597           0 :             break;
    1598             :         }
    1599             : 
    1600             :         // Fan Name
    1601          23 :         HPWH.FanName = hpwhAlpha[23 + nAlphaOffset];
    1602          23 :         HPWH.FanType = hpwhAlpha[22 + nAlphaOffset];
    1603             : 
    1604             :         // check that the fan exists
    1605          23 :         bool errFlag = false;
    1606          23 :         ValidateComponent(state, HPWH.FanType, HPWH.FanName, errFlag, state.dataIPShortCut->cCurrentModuleObject);
    1607             : 
    1608          23 :         Real64 FanVolFlow = 0.0;
    1609          23 :         if (errFlag) {
    1610           0 :             ShowContinueError(state, "...occurs in " + state.dataIPShortCut->cCurrentModuleObject + ", unit=\"" + HPWH.Name + "\".");
    1611           0 :             ErrorsFound = true;
    1612             :         } else {
    1613          23 :             if (UtilityRoutines::SameString(HPWH.FanType, "Fan:SystemModel")) {
    1614          13 :                 HPWH.FanType_Num = DataHVACGlobals::FanType_SystemModelObject;
    1615          13 :                 state.dataHVACFan->fanObjs.emplace_back(new HVACFan::FanSystem(state, HPWH.FanName)); // call constructor
    1616          13 :                 HPWH.FanNum = HVACFan::getFanObjectVectorIndex(state, HPWH.FanName);
    1617          13 :                 FanVolFlow = state.dataHVACFan->fanObjs[HPWH.FanNum]->designAirVolFlowRate;
    1618             : 
    1619             :             } else {
    1620          10 :                 Fans::GetFanType(state, HPWH.FanName, HPWH.FanType_Num, errFlag, state.dataIPShortCut->cCurrentModuleObject, HPWH.Name);
    1621          10 :                 Fans::GetFanIndex(state, HPWH.FanName, HPWH.FanNum, errFlag, state.dataIPShortCut->cCurrentModuleObject);
    1622          10 :                 Fans::GetFanVolFlow(state, HPWH.FanNum, FanVolFlow);
    1623             :             }
    1624             :         }
    1625             :         // issue #5630, set fan info in coils.
    1626          23 :         if (bIsVScoil) {
    1627           7 :             VariableSpeedCoils::setVarSpeedHPWHFanTypeNum(state, HPWH.DXCoilNum, HPWH.FanType_Num);
    1628           7 :             VariableSpeedCoils::setVarSpeedHPWHFanIndex(state, HPWH.DXCoilNum, HPWH.FanNum);
    1629             :         } else {
    1630          16 :             DXCoils::SetDXCoolingCoilData(state, HPWH.DXCoilNum, errFlag, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, HPWH.FanName);
    1631          16 :             DXCoils::SetDXCoolingCoilData(state, HPWH.DXCoilNum, errFlag, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, HPWH.FanNum);
    1632          16 :             DXCoils::SetDXCoolingCoilData(
    1633             :                 state, HPWH.DXCoilNum, errFlag, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, HPWH.FanType_Num);
    1634             :         }
    1635             : 
    1636          23 :         if (errFlag) {
    1637           0 :             ErrorsFound = true;
    1638          23 :         } else if (HPWH.FanType_Num != DataHVACGlobals::FanType_SimpleOnOff && HPWH.FanType_Num != DataHVACGlobals::FanType_SystemModelObject) {
    1639           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\": illegal fan type specified.");
    1640           0 :             ShowContinueError(
    1641           0 :                 state, " The fan object (" + HPWH.FanName + ") type must be Fan:SystemModel or Fan:OnOff when used with a heat pump water heater.");
    1642           0 :             ErrorsFound = true;
    1643          23 :         } else if (!UtilityRoutines::SameString(HPWH.FanType, "Fan:OnOff") && !UtilityRoutines::SameString(HPWH.FanType, "Fan:SystemModel")) {
    1644           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\": illegal fan type specified.");
    1645           0 :             ShowContinueError(state, " The " + state.dataIPShortCut->cCurrentModuleObject + " must specify that the fan object");
    1646           0 :             ShowContinueError(state,
    1647             :                               " is of type FanSystemModel or Fan:OnOff in addition to the fan actually being of that type and defined elsewhere.");
    1648             :         }
    1649             : 
    1650          23 :         if (FanVolFlow != DataSizing::AutoSize && !errFlag) {
    1651          21 :             if (FanVolFlow < HPWH.OperatingAirFlowRate) {
    1652           0 :                 ShowSevereError(state,
    1653           0 :                                 format("{} - air flow rate = {:.7T} in fan object {} is less than the  HPWHs evaporator air flow rate.",
    1654           0 :                                        state.dataIPShortCut->cCurrentModuleObject,
    1655             :                                        FanVolFlow,
    1656           0 :                                        HPWH.FanName));
    1657           0 :                 ShowContinueError(state, " The fan flow rate must be >= to the HPWHs evaporator volumetric air flow rate.");
    1658           0 :                 ShowContinueError(state, " Occurs in unit = " + HPWH.Name);
    1659           0 :                 ErrorsFound = true;
    1660             :             }
    1661             :         }
    1662             : 
    1663             :         // Fan Placement
    1664          23 :         if (UtilityRoutines::SameString(hpwhAlpha[24 + nAlphaOffset], "BlowThrough")) {
    1665          12 :             HPWH.FanPlacement = DataHVACGlobals::BlowThru;
    1666             : 
    1667          11 :         } else if (UtilityRoutines::SameString(hpwhAlpha[24 + nAlphaOffset], "DrawThrough")) {
    1668          11 :             HPWH.FanPlacement = DataHVACGlobals::DrawThru;
    1669             : 
    1670             :         } else {
    1671           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", invalid ");
    1672           0 :             ShowContinueError(state, hpwhAlphaFieldNames[24 + nAlphaOffset] + "=\"" + hpwhAlpha[24 + nAlphaOffset] + "\".");
    1673           0 :             ErrorsFound = true;
    1674             :         }
    1675             : 
    1676          23 :         if (HPWH.DXCoilNum > 0 && !bIsVScoil) {
    1677             :             // get HPWH capacity, air inlet node, and PLF curve info from DX coil object
    1678          16 :             HPWH.Capacity = state.dataDXCoils->DXCoil(HPWH.DXCoilNum).RatedTotCap2;
    1679          16 :             HPWH.DXCoilAirInletNode = state.dataDXCoils->DXCoil(HPWH.DXCoilNum).AirInNode;
    1680          16 :             HPWH.DXCoilPLFFPLR = state.dataDXCoils->DXCoil(HPWH.DXCoilNum).PLFFPLR(1);
    1681             :             // check the range of condenser pump power to be <= 5 gpm/ton
    1682          32 :             if (state.dataDXCoils->DXCoil(HPWH.DXCoilNum).HPWHCondPumpElecNomPower / state.dataDXCoils->DXCoil(HPWH.DXCoilNum).RatedTotCap2 >
    1683             :                 0.1422) {
    1684           0 :                 ShowWarningError(
    1685             :                     state,
    1686           0 :                     state.dataDXCoils->DXCoil(HPWH.DXCoilNum).DXCoilType + "= " + state.dataDXCoils->DXCoil(HPWH.DXCoilNum).Name +
    1687           0 :                         format(": Rated condenser pump power per watt of rated heating capacity has exceeded the recommended maximum of 0.1422 "
    1688             :                                "W/W (41.67 watt/MBH). Condenser pump power per watt = {:.4T}",
    1689           0 :                                (state.dataDXCoils->DXCoil(HPWH.DXCoilNum).HPWHCondPumpElecNomPower /
    1690           0 :                                 state.dataDXCoils->DXCoil(HPWH.DXCoilNum).RatedTotCap2)));
    1691             :             }
    1692           7 :         } else if ((HPWH.DXCoilNum > 0) && (bIsVScoil)) {
    1693             : 
    1694           7 :             if (HPWH.bIsIHP) {
    1695           1 :                 HPWH.Capacity =
    1696           1 :                     GetDWHCoilCapacityIHP(state, HPWH.DXCoilType, HPWH.DXCoilName, IntegratedHeatPump::IHPOperationMode::SCWHMatchWH, DXCoilErrFlag);
    1697           1 :                 HPWH.DXCoilAirInletNode = IntegratedHeatPump::GetCoilInletNodeIHP(state, HPWH.DXCoilType, HPWH.DXCoilName, DXCoilErrFlag);
    1698           1 :                 HPWH.DXCoilPLFFPLR =
    1699           1 :                     GetIHPDWHCoilPLFFPLR(state, HPWH.DXCoilType, HPWH.DXCoilName, IntegratedHeatPump::IHPOperationMode::SCWHMatchWH, DXCoilErrFlag);
    1700             :             } else {
    1701           6 :                 HPWH.Capacity = VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, HPWH.DXCoilType, HPWH.DXCoilName, DXCoilErrFlag);
    1702           6 :                 HPWH.DXCoilAirInletNode = VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, HPWH.DXCoilType, HPWH.DXCoilName, DXCoilErrFlag);
    1703           6 :                 HPWH.DXCoilPLFFPLR = VariableSpeedCoils::GetVSCoilPLFFPLR(state, HPWH.DXCoilType, HPWH.DXCoilName, DXCoilErrFlag);
    1704             :             }
    1705             :             //         check the range of condenser pump power to be <= 5 gpm/ton, will be checked in the coil object
    1706             :         }
    1707             : 
    1708          23 :         if (HPWH.OperatingWaterFlowRate == DataGlobalConstants::AutoCalculate) {
    1709           8 :             HPWH.OperatingWaterFlowRate = 0.00000004487 * HPWH.Capacity;
    1710           8 :             HPWH.WaterFlowRateAutoSized = true;
    1711             :         }
    1712             : 
    1713          23 :         if (HPWH.OperatingAirFlowRate == DataGlobalConstants::AutoCalculate) {
    1714          10 :             HPWH.OperatingAirFlowRate = 0.00005035 * HPWH.Capacity;
    1715          10 :             HPWH.AirFlowRateAutoSized = true;
    1716             :         }
    1717             : 
    1718             :         // On Cycle Parasitic Electric Load
    1719          23 :         HPWH.OnCycParaLoad = hpwhNumeric[6 + nNumericOffset];
    1720          23 :         if (HPWH.OnCycParaLoad < 0.0) {
    1721           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\",");
    1722           0 :             ShowContinueError(state,
    1723           0 :                               hpwhNumericFieldNames[6 + nNumericOffset] + " must be >= 0. " + hpwhNumericFieldNames[6 + nNumericOffset] +
    1724           0 :                                   format(" = {:.2T}", hpwhNumeric[6 + nNumericOffset]));
    1725           0 :             ErrorsFound = true;
    1726             :         }
    1727             : 
    1728             :         // Off Cycle Parasitic Electric Load
    1729          23 :         HPWH.OffCycParaLoad = hpwhNumeric[7 + nNumericOffset];
    1730          23 :         if (HPWH.OffCycParaLoad < 0.0) {
    1731           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\",");
    1732           0 :             ShowContinueError(state,
    1733           0 :                               hpwhNumericFieldNames[7 + nNumericOffset] + " must be >= 0. " + hpwhNumericFieldNames[2 + nNumericOffset] +
    1734           0 :                                   format(" = {:.2T}", hpwhNumeric[7 + nNumericOffset]));
    1735           0 :             ErrorsFound = true;
    1736             :         }
    1737             : 
    1738             :         // Parasitic Heat Rejection Location
    1739          23 :         if (UtilityRoutines::SameString(hpwhAlpha[25 + nAlphaOffset], "Zone")) {
    1740           8 :             HPWH.ParasiticTempIndicator = WTTAmbientTemp::TempZone;
    1741           8 :             if (HPWH.InletAirConfiguration == WTTAmbientTemp::OutsideAir || HPWH.InletAirConfiguration == WTTAmbientTemp::Schedule) {
    1742           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\",");
    1743           0 :                 ShowContinueError(state, hpwhAlphaFieldNames[25 + nAlphaOffset] + " must be ZoneAirOnly or ZoneAndOutdoorAir");
    1744           0 :                 ShowContinueError(state, " when parasitic heat rejection location equals Zone.");
    1745           0 :                 ErrorsFound = true;
    1746             :             }
    1747          15 :         } else if (UtilityRoutines::SameString(hpwhAlpha[25 + nAlphaOffset], "Outdoors")) {
    1748          15 :             HPWH.ParasiticTempIndicator = WTTAmbientTemp::OutsideAir;
    1749             :         } else {
    1750           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    1751           0 :             ShowContinueError(state, " parasitic heat rejection location must be either Zone or Outdoors.");
    1752           0 :             ErrorsFound = true;
    1753             :         }
    1754             : 
    1755             :         // Inlet Air Mixer Node
    1756             :         // get mixer/splitter nodes only when Inlet Air Configuration is ZoneAndOutdoorAir
    1757          23 :         if (!hpwhAlphaBlank[26 + nAlphaOffset]) {
    1758             :             // For the inlet air mixer node, NodeConnectionType is outlet from the HPWH inlet air node
    1759           3 :             if (HPWH.InletAirConfiguration == WTTAmbientTemp::ZoneAndOA) {
    1760           6 :                 HPWH.InletAirMixerNode = NodeInputManager::GetOnlySingleNode(state,
    1761           6 :                                                                              hpwhAlpha[26 + nAlphaOffset],
    1762             :                                                                              ErrorsFound,
    1763             :                                                                              objType,
    1764           6 :                                                                              HPWH.Name + "-INLET AIR MIXER",
    1765             :                                                                              DataLoopNode::NodeFluidType::Air,
    1766             :                                                                              DataLoopNode::ConnectionType::Outlet,
    1767             :                                                                              NodeInputManager::CompFluidStream::Primary,
    1768           3 :                                                                              DataLoopNode::ObjectIsNotParent);
    1769             :             } else {
    1770           0 :                 ShowWarningError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    1771           0 :                 ShowContinueError(state,
    1772             :                                   "Inlet air mixer node name specified but only required when Inlet Air Configuration is selected as "
    1773             :                                   "Zone and OutdoorAir. Node name disregarded and simulation continues.");
    1774             :             }
    1775          20 :         } else if (hpwhAlphaBlank[26 + nAlphaOffset] && HPWH.InletAirConfiguration == WTTAmbientTemp::ZoneAndOA) {
    1776           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    1777           0 :             ShowContinueError(state, "Inlet air mixer node name required when Inlet Air Configuration is selected as ZoneAndOutdoorAir.");
    1778           0 :             ErrorsFound = true;
    1779             :         }
    1780             : 
    1781             :         // Outlet Air Splitter Node
    1782          23 :         if (!hpwhAlphaBlank[27 + nAlphaOffset]) {
    1783             :             //  For the outlet air splitter node, NodeConnectionType is inlet to the HPWH outlet air node
    1784           3 :             if (HPWH.InletAirConfiguration == WTTAmbientTemp::ZoneAndOA) {
    1785           6 :                 HPWH.OutletAirSplitterNode = NodeInputManager::GetOnlySingleNode(state,
    1786           6 :                                                                                  hpwhAlpha[27 + nAlphaOffset],
    1787             :                                                                                  ErrorsFound,
    1788             :                                                                                  objType,
    1789           6 :                                                                                  HPWH.Name + "-OUTLET AIR SPLITTER",
    1790             :                                                                                  DataLoopNode::NodeFluidType::Air,
    1791             :                                                                                  DataLoopNode::ConnectionType::Inlet,
    1792             :                                                                                  NodeInputManager::CompFluidStream::Primary,
    1793           3 :                                                                                  DataLoopNode::ObjectIsNotParent);
    1794             :             } else {
    1795           0 :                 ShowWarningError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    1796           0 :                 ShowContinueError(state,
    1797             :                                   "Outlet air splitter node name specified but only required when Inlet Air Configuration is selected as "
    1798             :                                   "ZoneAndOutdoorAir. Node name disregarded and simulation continues.");
    1799             :             }
    1800          20 :         } else if (hpwhAlphaBlank[27 + nAlphaOffset] && HPWH.InletAirConfiguration == WTTAmbientTemp::ZoneAndOA) {
    1801           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    1802           0 :             ShowContinueError(state, "Outlet air splitter node name required when Inlet Air Configuration is selected as ZoneAndOutdoorAir.");
    1803           0 :             ErrorsFound = true;
    1804             :         }
    1805             : 
    1806             :         // get node data for HPWH
    1807          23 :         if (HPWH.InletAirMixerNode != 0) {
    1808             :             // when mixer/splitter nodes are used the HPWH's inlet/outlet node are set up as DataLoopNode::ObjectIsNotParent
    1809             : 
    1810           6 :             HPWH.HeatPumpAirInletNode = NodeInputManager::GetOnlySingleNode(state,
    1811           6 :                                                                             hpwhAlpha[7 + nAlphaOffset],
    1812             :                                                                             ErrorsFound,
    1813             :                                                                             objType,
    1814           6 :                                                                             HPWH.Name + "-INLET AIR MIXER",
    1815             :                                                                             DataLoopNode::NodeFluidType::Air,
    1816             :                                                                             DataLoopNode::ConnectionType::Inlet,
    1817             :                                                                             NodeInputManager::CompFluidStream::Primary,
    1818           3 :                                                                             DataLoopNode::ObjectIsNotParent);
    1819             : 
    1820           6 :             HPWH.HeatPumpAirOutletNode = NodeInputManager::GetOnlySingleNode(state,
    1821           6 :                                                                              hpwhAlpha[8 + nAlphaOffset],
    1822             :                                                                              ErrorsFound,
    1823             :                                                                              objType,
    1824           6 :                                                                              HPWH.Name + "-OUTLET AIR SPLITTER",
    1825             :                                                                              DataLoopNode::NodeFluidType::Air,
    1826             :                                                                              DataLoopNode::ConnectionType::Outlet,
    1827             :                                                                              NodeInputManager::CompFluidStream::Primary,
    1828           3 :                                                                              DataLoopNode::ObjectIsNotParent);
    1829             : 
    1830           9 :             HPWH.OutsideAirNode = NodeInputManager::GetOnlySingleNode(state,
    1831           6 :                                                                       hpwhAlpha[9 + nAlphaOffset],
    1832             :                                                                       ErrorsFound,
    1833             :                                                                       objType,
    1834             :                                                                       HPWH.Name,
    1835             :                                                                       DataLoopNode::NodeFluidType::Air,
    1836             :                                                                       DataLoopNode::ConnectionType::OutsideAirReference,
    1837             :                                                                       NodeInputManager::CompFluidStream::Primary,
    1838           3 :                                                                       DataLoopNode::ObjectIsParent);
    1839           3 :             if (!hpwhAlpha[9 + nAlphaOffset].empty()) {
    1840             :                 bool Okay;
    1841           3 :                 OutAirNodeManager::CheckAndAddAirNodeNumber(state, HPWH.OutsideAirNode, Okay);
    1842           3 :                 if (!Okay) {
    1843           0 :                     ShowWarningError(state,
    1844           0 :                                      state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name +
    1845           0 :                                          "\": Adding outdoor air node=" + hpwhAlpha[9 + nAlphaOffset]);
    1846             :                 }
    1847             :             }
    1848             : 
    1849           9 :             HPWH.ExhaustAirNode = NodeInputManager::GetOnlySingleNode(state,
    1850           6 :                                                                       hpwhAlpha[10 + nAlphaOffset],
    1851             :                                                                       ErrorsFound,
    1852             :                                                                       objType,
    1853             :                                                                       HPWH.Name,
    1854             :                                                                       DataLoopNode::NodeFluidType::Air,
    1855             :                                                                       DataLoopNode::ConnectionType::ReliefAir,
    1856             :                                                                       NodeInputManager::CompFluidStream::Primary,
    1857           3 :                                                                       DataLoopNode::ObjectIsParent);
    1858             : 
    1859             :         } else {
    1860             :             // when mixer/splitter nodes are NOT used the HPWH's inlet/outlet nodes are set up as DataLoopNode::ObjectIsParent
    1861          20 :             if (HPWH.InletAirConfiguration == WTTAmbientTemp::Schedule) {
    1862             :                 // for scheduled HPWH's the inlet node is not on any branch or parent object, make it an outlet node
    1863             :                 // to avoid node connection errors
    1864           9 :                 HPWH.HeatPumpAirInletNode = NodeInputManager::GetOnlySingleNode(state,
    1865           6 :                                                                                 hpwhAlpha[7 + nAlphaOffset],
    1866             :                                                                                 ErrorsFound,
    1867             :                                                                                 objType,
    1868             :                                                                                 HPWH.Name,
    1869             :                                                                                 DataLoopNode::NodeFluidType::Air,
    1870             :                                                                                 DataLoopNode::ConnectionType::Outlet,
    1871             :                                                                                 NodeInputManager::CompFluidStream::Primary,
    1872           3 :                                                                                 DataLoopNode::ObjectIsParent);
    1873             : 
    1874           9 :                 HPWH.HeatPumpAirOutletNode = NodeInputManager::GetOnlySingleNode(state,
    1875           6 :                                                                                  hpwhAlpha[8 + nAlphaOffset],
    1876             :                                                                                  ErrorsFound,
    1877             :                                                                                  objType,
    1878             :                                                                                  HPWH.Name,
    1879             :                                                                                  DataLoopNode::NodeFluidType::Air,
    1880             :                                                                                  DataLoopNode::ConnectionType::Outlet,
    1881             :                                                                                  NodeInputManager::CompFluidStream::Primary,
    1882           3 :                                                                                  DataLoopNode::ObjectIsParent);
    1883             : 
    1884             :             } else { // HPWH is connected to a zone with no mixer/splitter nodes
    1885          17 :                 if (HPWH.InletAirConfiguration == WTTAmbientTemp::TempZone) {
    1886          21 :                     HPWH.HeatPumpAirInletNode = NodeInputManager::GetOnlySingleNode(state,
    1887          14 :                                                                                     hpwhAlpha[7 + nAlphaOffset],
    1888             :                                                                                     ErrorsFound,
    1889             :                                                                                     objType,
    1890             :                                                                                     HPWH.Name,
    1891             :                                                                                     DataLoopNode::NodeFluidType::Air,
    1892             :                                                                                     DataLoopNode::ConnectionType::Inlet,
    1893             :                                                                                     NodeInputManager::CompFluidStream::Primary,
    1894           7 :                                                                                     DataLoopNode::ObjectIsParent);
    1895             : 
    1896          21 :                     HPWH.HeatPumpAirOutletNode = NodeInputManager::GetOnlySingleNode(state,
    1897          14 :                                                                                      hpwhAlpha[8 + nAlphaOffset],
    1898             :                                                                                      ErrorsFound,
    1899             :                                                                                      objType,
    1900             :                                                                                      HPWH.Name,
    1901             :                                                                                      DataLoopNode::NodeFluidType::Air,
    1902             :                                                                                      DataLoopNode::ConnectionType::Outlet,
    1903             :                                                                                      NodeInputManager::CompFluidStream::Primary,
    1904           7 :                                                                                      DataLoopNode::ObjectIsParent);
    1905             :                 } else { // HPWH is located outdoors
    1906          30 :                     HPWH.OutsideAirNode = NodeInputManager::GetOnlySingleNode(state,
    1907          20 :                                                                               hpwhAlpha[9 + nAlphaOffset],
    1908             :                                                                               ErrorsFound,
    1909             :                                                                               objType,
    1910             :                                                                               HPWH.Name,
    1911             :                                                                               DataLoopNode::NodeFluidType::Air,
    1912             :                                                                               DataLoopNode::ConnectionType::OutsideAirReference,
    1913             :                                                                               NodeInputManager::CompFluidStream::Primary,
    1914          10 :                                                                               DataLoopNode::ObjectIsParent);
    1915          10 :                     if (!hpwhAlphaBlank[9 + nAlphaOffset]) {
    1916             :                         bool Okay;
    1917          10 :                         OutAirNodeManager::CheckAndAddAirNodeNumber(state, HPWH.OutsideAirNode, Okay);
    1918          10 :                         if (!Okay) {
    1919           0 :                             ShowWarningError(state,
    1920           0 :                                              state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name +
    1921           0 :                                                  "\": Adding outdoor air node =" + hpwhAlpha[9 + nAlphaOffset]);
    1922             :                         }
    1923             :                     }
    1924             : 
    1925          30 :                     HPWH.ExhaustAirNode = NodeInputManager::GetOnlySingleNode(state,
    1926          20 :                                                                               hpwhAlpha[10 + nAlphaOffset],
    1927             :                                                                               ErrorsFound,
    1928             :                                                                               objType,
    1929             :                                                                               HPWH.Name,
    1930             :                                                                               DataLoopNode::NodeFluidType::Air,
    1931             :                                                                               DataLoopNode::ConnectionType::ReliefAir,
    1932             :                                                                               NodeInputManager::CompFluidStream::Primary,
    1933          10 :                                                                               DataLoopNode::ObjectIsParent);
    1934             :                 }
    1935             :             }
    1936             :         }
    1937             :         // check that required node names are present
    1938          23 :         if (HPWH.InletAirConfiguration == WTTAmbientTemp::Schedule || HPWH.InletAirConfiguration == WTTAmbientTemp::TempZone) {
    1939          20 :             if (HPWH.HeatPumpAirInletNode == 0 || HPWH.HeatPumpAirOutletNode == 0) {
    1940           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    1941           0 :                 ShowContinueError(state, "When " + hpwhAlphaFieldNames[6 + nAlphaOffset] + "=\"" + hpwhAlpha[6 + nAlphaOffset] + "\".");
    1942           0 :                 ShowContinueError(state,
    1943           0 :                                   hpwhAlphaFieldNames[7 + nAlphaOffset] + " and " + hpwhAlphaFieldNames[8 + nAlphaOffset] + " must be specified.");
    1944           0 :                 ErrorsFound = true;
    1945             :             }
    1946          13 :         } else if (HPWH.InletAirConfiguration == WTTAmbientTemp::OutsideAir) {
    1947          10 :             if (HPWH.OutsideAirNode == 0 || HPWH.ExhaustAirNode == 0) {
    1948           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    1949           0 :                 ShowContinueError(state, "When " + hpwhAlphaFieldNames[6 + nAlphaOffset] + "=\"" + hpwhAlpha[6 + nAlphaOffset] + "\".");
    1950           0 :                 ShowContinueError(state,
    1951           0 :                                   hpwhAlphaFieldNames[9 + nAlphaOffset] + " and " + hpwhAlphaFieldNames[10 + nAlphaOffset] + " must be specified.");
    1952           0 :                 ErrorsFound = true;
    1953             :             }
    1954           3 :         } else if (HPWH.InletAirMixerNode > 0 && HPWH.OutletAirSplitterNode > 0 && HPWH.InletAirConfiguration == WTTAmbientTemp::ZoneAndOA) {
    1955           3 :             if (HPWH.HeatPumpAirInletNode == 0 || HPWH.HeatPumpAirOutletNode == 0 || HPWH.OutsideAirNode == 0 || HPWH.ExhaustAirNode == 0) {
    1956           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    1957           0 :                 ShowContinueError(state, "When " + hpwhAlphaFieldNames[6 + nAlphaOffset] + "=\"" + hpwhAlpha[6 + nAlphaOffset] + "\".");
    1958           0 :                 if (HPWH.HeatPumpAirInletNode == 0 || HPWH.HeatPumpAirOutletNode == 0) {
    1959           0 :                     ShowContinueError(
    1960           0 :                         state, hpwhAlphaFieldNames[7 + nAlphaOffset] + " and " + hpwhAlphaFieldNames[8 + nAlphaOffset] + " must be specified.");
    1961             :                 }
    1962           0 :                 if (HPWH.OutsideAirNode == 0 || HPWH.ExhaustAirNode == 0) {
    1963           0 :                     ShowContinueError(
    1964           0 :                         state, hpwhAlphaFieldNames[9 + nAlphaOffset] + " and " + hpwhAlphaFieldNames[10 + nAlphaOffset] + " must be specified.");
    1965             :                 }
    1966           0 :                 ErrorsFound = true;
    1967             :             }
    1968             :         }
    1969             : 
    1970             :         // check that the HPWH inlet and outlet nodes are in the same zone (ZoneHVAC:EquipmentConnections) when
    1971             :         // Inlet Air Configuration is Zone Air Only or Zone and Outdoor Air
    1972          33 :         if ((HPWH.InletAirConfiguration == WTTAmbientTemp::TempZone || HPWH.InletAirConfiguration == WTTAmbientTemp::ZoneAndOA) &&
    1973          10 :             HPWH.AmbientTempZone > 0) {
    1974          10 :             if (!state.dataZoneEquip->ZoneEquipInputsFilled) {
    1975           0 :                 DataZoneEquipment::GetZoneEquipmentData(state);
    1976           0 :                 state.dataZoneEquip->ZoneEquipInputsFilled = true;
    1977             :             }
    1978          10 :             if (allocated(state.dataZoneEquip->ZoneEquipConfig)) {
    1979          10 :                 bool FoundInletNode = false;
    1980          10 :                 bool FoundOutletNode = false;
    1981          10 :                 int ZoneNum = HPWH.AmbientTempZone;
    1982          10 :                 if (ZoneNum <= state.dataGlobal->NumOfZones) {
    1983          37 :                     for (int SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(ZoneNum).NumInletNodes; ++SupAirIn) {
    1984          27 :                         if (HPWH.HeatPumpAirOutletNode != state.dataZoneEquip->ZoneEquipConfig(ZoneNum).InletNode(SupAirIn)) continue;
    1985          10 :                         FoundOutletNode = true;
    1986             :                     }
    1987          27 :                     for (int ExhAirOut = 1; ExhAirOut <= state.dataZoneEquip->ZoneEquipConfig(ZoneNum).NumExhaustNodes; ++ExhAirOut) {
    1988          17 :                         if (HPWH.HeatPumpAirInletNode != state.dataZoneEquip->ZoneEquipConfig(ZoneNum).ExhaustNode(ExhAirOut)) continue;
    1989          10 :                         FoundInletNode = true;
    1990             :                     }
    1991          10 :                     if (!FoundInletNode) {
    1992           0 :                         ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    1993           0 :                         ShowContinueError(state, "The HPWH's air inlet node name = " + hpwhAlpha[7 + nAlphaOffset] + " was not properly specified ");
    1994           0 :                         ShowContinueError(state,
    1995           0 :                                           "as an exhaust air node for zone = " + hpwhAlpha[13 + nAlphaOffset] +
    1996             :                                               " in a ZoneHVAC:EquipmentConnections object.");
    1997           0 :                         ErrorsFound = true;
    1998             :                     }
    1999          10 :                     if (!FoundOutletNode) {
    2000           0 :                         ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    2001           0 :                         ShowContinueError(state, "The HPWH's air outlet node name = " + hpwhAlpha[8 + nAlphaOffset] + " was not properly specified ");
    2002           0 :                         ShowContinueError(
    2003           0 :                             state, "as an inlet air node for zone = " + hpwhAlpha[13 + nAlphaOffset] + " in a ZoneHVAC:EquipmentConnections object.");
    2004           0 :                         ErrorsFound = true;
    2005             :                     }
    2006             :                 }
    2007             :             } else {
    2008           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    2009           0 :                 ShowContinueError(state,
    2010             :                                   "Heat pump water heater air inlet node name and air outlet node name must be listed in a "
    2011             :                                   "ZoneHVAC:EquipmentConnections object when Inlet Air Configuration is equal to ZoneAirOnly or "
    2012             :                                   "ZoneAndOutdoorAir.");
    2013           0 :                 ErrorsFound = true;
    2014             :             }
    2015             :         }
    2016             : 
    2017             :         // only get the inlet air mixer schedule if the inlet air configuration is zone and outdoor air
    2018          23 :         if (!hpwhAlphaBlank[28 + nAlphaOffset] && HPWH.InletAirConfiguration == WTTAmbientTemp::ZoneAndOA) {
    2019           3 :             HPWH.InletAirMixerSchPtr = ScheduleManager::GetScheduleIndex(state, hpwhAlpha[28 + nAlphaOffset]);
    2020           3 :             if (HPWH.InletAirMixerSchPtr == 0) {
    2021           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", not found");
    2022           0 :                 ShowContinueError(state, hpwhAlphaFieldNames[28 + nAlphaOffset] + "=\"" + hpwhAlpha[28 + nAlphaOffset] + "\",");
    2023           0 :                 ErrorsFound = true;
    2024             :             } else {
    2025           3 :                 bool ValidScheduleValue = ScheduleManager::CheckScheduleValueMinMax(state, HPWH.InletAirMixerSchPtr, ">=", 0.0, "<=", 1.0);
    2026           3 :                 if (!ValidScheduleValue) {
    2027           0 :                     ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\", not found");
    2028           0 :                     ShowContinueError(state,
    2029           0 :                                       hpwhAlphaFieldNames[28 + nAlphaOffset] + " values out of range of 0 to 1, Schedule=\"" +
    2030           0 :                                           hpwhAlpha[28 + nAlphaOffset] + "\".");
    2031           0 :                     ErrorsFound = true;
    2032             :                 }
    2033             :                 //           set outlet air splitter schedule index equal to inlet air mixer schedule index
    2034             :                 //           (place holder for when zone pressurization/depressurization is allowed and different schedules can be used)
    2035           3 :                 HPWH.OutletAirSplitterSchPtr = ScheduleManager::GetScheduleIndex(state, hpwhAlpha[28 + nAlphaOffset]);
    2036             :             }
    2037             :         }
    2038             : 
    2039             :         // set fan outlet node variable for use in setting Node(FanOutletNode)%MassFlowRateMax for fan object
    2040          23 :         if (HPWH.FanPlacement == DataHVACGlobals::DrawThru) {
    2041          11 :             if (HPWH.OutletAirSplitterNode != 0) {
    2042           3 :                 HPWH.FanOutletNode = HPWH.OutletAirSplitterNode;
    2043             :             } else {
    2044           8 :                 if (HPWH.InletAirConfiguration == WTTAmbientTemp::OutsideAir) {
    2045           1 :                     HPWH.FanOutletNode = HPWH.ExhaustAirNode;
    2046             :                 } else {
    2047           7 :                     HPWH.FanOutletNode = HPWH.HeatPumpAirOutletNode;
    2048             :                 }
    2049             :             }
    2050          12 :         } else if (HPWH.FanPlacement == DataHVACGlobals::BlowThru) {
    2051             :             // set fan outlet node variable for use in setting Node(FanOutletNode)%MassFlowRateMax for fan object
    2052          12 :             if (bIsVScoil) {
    2053           5 :                 if (HPWH.bIsIHP) {
    2054           1 :                     HPWH.FanOutletNode = IntegratedHeatPump::GetDWHCoilInletNodeIHP(state, HPWH.DXCoilType, HPWH.DXCoilName, DXCoilErrFlag);
    2055             :                 } else {
    2056           4 :                     HPWH.FanOutletNode = VariableSpeedCoils::GetCoilInletNodeVariableSpeed(state, HPWH.DXCoilType, HPWH.DXCoilName, DXCoilErrFlag);
    2057             :                 }
    2058             :             } else {
    2059           7 :                 HPWH.FanOutletNode = state.dataDXCoils->DXCoil(HPWH.DXCoilNum).AirInNode;
    2060             :             }
    2061             :         }
    2062             : 
    2063             :         // check that fan outlet node is indeed correct
    2064          23 :         int FanOutletNodeNum(0);
    2065          23 :         if (HPWH.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    2066          13 :             FanOutletNodeNum = state.dataHVACFan->fanObjs[HPWH.FanNum]->outletNodeNum;
    2067             :         } else {
    2068          10 :             errFlag = false;
    2069          10 :             FanOutletNodeNum = Fans::GetFanOutletNode(state, HPWH.FanType, HPWH.FanName, errFlag);
    2070          10 :             if (errFlag) {
    2071           0 :                 ShowContinueError(state, "...occurs in unit=\"" + HPWH.Name + "\".");
    2072           0 :                 ErrorsFound = true;
    2073             :             }
    2074             :         }
    2075          23 :         if (FanOutletNodeNum != HPWH.FanOutletNode) {
    2076           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    2077           0 :             ShowContinueError(state, "Heat pump water heater fan outlet node name does not match next connected component.");
    2078           0 :             if (FanOutletNodeNum != 0) {
    2079           0 :                 ShowContinueError(state, "Fan outlet node name = " + state.dataLoopNodes->NodeID(FanOutletNodeNum));
    2080             :             }
    2081           0 :             if (HPWH.FanOutletNode != 0) {
    2082           0 :                 ShowContinueError(state, "Expected fan outlet node name = " + state.dataLoopNodes->NodeID(HPWH.FanOutletNode));
    2083             :             }
    2084           0 :             ErrorsFound = true;
    2085             :         }
    2086          23 :         int FanInletNodeNum(0);
    2087          23 :         if (HPWH.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    2088          13 :             FanInletNodeNum = state.dataHVACFan->fanObjs[HPWH.FanNum]->inletNodeNum;
    2089             :         } else {
    2090          10 :             errFlag = false;
    2091          10 :             FanInletNodeNum = Fans::GetFanInletNode(state, HPWH.FanType, HPWH.FanName, errFlag);
    2092          10 :             if (errFlag) {
    2093           0 :                 ShowContinueError(state, "...occurs in unit=\"" + HPWH.Name + "\".");
    2094           0 :                 ErrorsFound = true;
    2095             :             }
    2096             :         }
    2097          23 :         int HPWHFanInletNodeNum(0);
    2098          23 :         if (HPWH.InletAirMixerNode != 0) {
    2099           3 :             HPWHFanInletNodeNum = HPWH.InletAirMixerNode;
    2100             :         } else {
    2101          20 :             if (HPWH.InletAirConfiguration == WTTAmbientTemp::OutsideAir) {
    2102          10 :                 HPWHFanInletNodeNum = HPWH.OutsideAirNode;
    2103             :             } else {
    2104          10 :                 HPWHFanInletNodeNum = HPWH.HeatPumpAirInletNode;
    2105             :             }
    2106             :         }
    2107          23 :         if (HPWH.FanPlacement == DataHVACGlobals::BlowThru) {
    2108          12 :             if (FanInletNodeNum != HPWHFanInletNodeNum) {
    2109           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    2110           0 :                 ShowContinueError(state, "Heat pump water heater fan inlet node name does not match previous connected component.");
    2111           0 :                 if (FanOutletNodeNum != 0) {
    2112           0 :                     ShowContinueError(state, "Fan inlet node name = " + state.dataLoopNodes->NodeID(FanInletNodeNum));
    2113             :                 }
    2114           0 :                 if (HPWH.FanOutletNode != 0) {
    2115           0 :                     ShowContinueError(state, "Expected fan inlet node name = " + state.dataLoopNodes->NodeID(HPWHFanInletNodeNum));
    2116             :                 }
    2117           0 :                 ErrorsFound = true;
    2118             :             }
    2119             :         }
    2120             : 
    2121          23 :         int DXCoilAirOutletNodeNum(0);
    2122          23 :         if ((HPWH.DXCoilNum > 0) && (bIsVScoil)) {
    2123          14 :             if (HPWH.bIsIHP) {
    2124           1 :                 DXCoilAirOutletNodeNum = IntegratedHeatPump::GetDWHCoilOutletNodeIHP(state, HPWH.DXCoilType, HPWH.DXCoilName, DXCoilErrFlag);
    2125             :             } else {
    2126           6 :                 DXCoilAirOutletNodeNum = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(state, HPWH.DXCoilType, HPWH.DXCoilName, DXCoilErrFlag);
    2127             :             }
    2128             : 
    2129          16 :         } else if (HPWH.DXCoilNum > 0) {
    2130          16 :             DXCoilAirOutletNodeNum = state.dataDXCoils->DXCoil(HPWH.DXCoilNum).AirOutNode;
    2131             :         }
    2132          23 :         if (HPWH.FanPlacement == DataHVACGlobals::DrawThru) {
    2133          11 :             if (FanInletNodeNum != DXCoilAirOutletNodeNum) {
    2134           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    2135           0 :                 ShowContinueError(state, "Heat pump water heater fan inlet node name does not match previous connected component.");
    2136           0 :                 if (FanInletNodeNum != 0) {
    2137           0 :                     ShowContinueError(state, "Fan inlet node name = " + state.dataLoopNodes->NodeID(FanInletNodeNum));
    2138             :                 }
    2139           0 :                 if (DXCoilAirOutletNodeNum != 0) {
    2140           0 :                     ShowContinueError(state, "Expected fan inlet node name = " + state.dataLoopNodes->NodeID(DXCoilAirOutletNodeNum));
    2141             :                 }
    2142           0 :                 ErrorsFound = true;
    2143             :             }
    2144          12 :         } else if (HPWH.FanPlacement == DataHVACGlobals::BlowThru) {
    2145          12 :             int HPWHCoilOutletNodeNum(0);
    2146          12 :             if (HPWH.OutletAirSplitterNode != 0) {
    2147           0 :                 HPWHCoilOutletNodeNum = HPWH.OutletAirSplitterNode;
    2148             :             } else {
    2149          12 :                 if (HPWH.InletAirConfiguration == WTTAmbientTemp::OutsideAir) {
    2150           9 :                     HPWHCoilOutletNodeNum = HPWH.ExhaustAirNode;
    2151             :                 } else {
    2152           3 :                     HPWHCoilOutletNodeNum = HPWH.HeatPumpAirOutletNode;
    2153             :                 }
    2154             :             }
    2155          12 :             if (DXCoilAirOutletNodeNum != HPWHCoilOutletNodeNum) {
    2156           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    2157           0 :                 ShowContinueError(state, "Heat pump water heater coil outlet node name does not match next connected component.");
    2158           0 :                 if (DXCoilAirOutletNodeNum != 0) {
    2159           0 :                     ShowContinueError(state, "Coil outlet node name = " + state.dataLoopNodes->NodeID(DXCoilAirOutletNodeNum));
    2160             :                 }
    2161           0 :                 if (HPWHCoilOutletNodeNum != 0) {
    2162           0 :                     ShowContinueError(state, "Expected coil outlet node name = " + state.dataLoopNodes->NodeID(HPWHCoilOutletNodeNum));
    2163             :                 }
    2164           0 :                 ErrorsFound = true;
    2165             :             }
    2166             :         }
    2167             : 
    2168             :         // set the max mass flow rate for outdoor fans
    2169          23 :         if (HPWH.FanOutletNode > 0)
    2170          23 :             state.dataLoopNodes->Node(HPWH.FanOutletNode).MassFlowRateMax =
    2171          46 :                 HPWH.OperatingAirFlowRate * Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, 20.0, 0.0);
    2172             : 
    2173          23 :         if (HPWH.FanPlacement == DataHVACGlobals::BlowThru) {
    2174          12 :             if (HPWH.InletAirMixerNode > 0) {
    2175           0 :                 HPWH.FanInletNode_str = hpwhAlpha[26 + nAlphaOffset];
    2176           0 :                 HPWH.FanOutletNode_str = "UNDEFINED";
    2177             :             } else {
    2178          12 :                 if (HPWH.OutsideAirNode == 0) {
    2179           3 :                     HPWH.FanInletNode_str = hpwhAlpha[7 + nAlphaOffset];
    2180           3 :                     HPWH.FanOutletNode_str = "UNDEFINED";
    2181             :                 } else {
    2182           9 :                     HPWH.FanInletNode_str = hpwhAlpha[9 + nAlphaOffset];
    2183           9 :                     HPWH.FanOutletNode_str = "UNDEFINED";
    2184             :                 }
    2185             :             }
    2186          12 :             if (HPWH.OutletAirSplitterNode > 0) {
    2187           0 :                 HPWH.CoilInletNode_str = "UNDEFINED";
    2188           0 :                 HPWH.CoilOutletNode_str = hpwhAlpha[27 + nAlphaOffset];
    2189             :             } else {
    2190          12 :                 if (HPWH.OutsideAirNode == 0) {
    2191           3 :                     HPWH.CoilInletNode_str = "UNDEFINED";
    2192           3 :                     HPWH.CoilOutletNode_str = hpwhAlpha[8 + nAlphaOffset];
    2193             :                 } else {
    2194           9 :                     HPWH.CoilInletNode_str = "UNDEFINED";
    2195           9 :                     HPWH.CoilOutletNode_str = hpwhAlpha[10 + nAlphaOffset];
    2196             :                 }
    2197             :             }
    2198             :         } else {
    2199          11 :             if (HPWH.InletAirMixerNode > 0) {
    2200           3 :                 HPWH.CoilInletNode_str = hpwhAlpha[26 + nAlphaOffset];
    2201           3 :                 HPWH.CoilOutletNode_str = "UNDEFINED";
    2202             :             } else {
    2203           8 :                 if (HPWH.OutsideAirNode == 0) {
    2204           7 :                     HPWH.CoilInletNode_str = hpwhAlpha[7 + nAlphaOffset];
    2205           7 :                     HPWH.CoilOutletNode_str = "UNDEFINED";
    2206             :                 } else {
    2207           1 :                     HPWH.CoilInletNode_str = hpwhAlpha[9 + nAlphaOffset];
    2208           1 :                     HPWH.CoilOutletNode_str = "UNDEFINED";
    2209             :                 }
    2210             :             }
    2211          11 :             if (HPWH.OutletAirSplitterNode > 0) {
    2212           3 :                 HPWH.FanInletNode_str = "UNDEFINED";
    2213           3 :                 HPWH.FanOutletNode_str = hpwhAlpha[27 + nAlphaOffset];
    2214             :             } else {
    2215           8 :                 if (HPWH.OutsideAirNode == 0) {
    2216           7 :                     HPWH.FanInletNode_str = "UNDEFINED";
    2217           7 :                     HPWH.FanOutletNode_str = hpwhAlpha[8 + nAlphaOffset];
    2218             :                 } else {
    2219           1 :                     HPWH.FanInletNode_str = "UNDEFINED";
    2220           1 :                     HPWH.FanOutletNode_str = hpwhAlpha[10 + nAlphaOffset];
    2221             :                 }
    2222             :             }
    2223             :         }
    2224             : 
    2225             :         // set up comp set for air side nodes (can be blow thru or draw thru, may or may not have damper nodes)
    2226          23 :         if (HPWH.bIsIHP) {
    2227           3 :             BranchNodeConnections::SetUpCompSets(
    2228           3 :                 state, HPWH.Type, HPWH.Name, HPWH.DXCoilType, HPWH.DXCoilName + " Outdoor Coil", HPWH.CoilInletNode_str, HPWH.CoilOutletNode_str);
    2229             :         } else {
    2230          22 :             BranchNodeConnections::SetUpCompSets(
    2231          22 :                 state, HPWH.Type, HPWH.Name, HPWH.DXCoilType, HPWH.DXCoilName, HPWH.CoilInletNode_str, HPWH.CoilOutletNode_str);
    2232             :         }
    2233             : 
    2234          23 :         BranchNodeConnections::SetUpCompSets(state, HPWH.Type, HPWH.Name, HPWH.FanType, HPWH.FanName, HPWH.FanInletNode_str, HPWH.FanOutletNode_str);
    2235             : 
    2236             :         // Control Logic Flag
    2237          46 :         std::string CtrlLogicFlag = hpwhAlphaBlank[29 + nAlphaOffset] ? "SIMULTANEOUS" : hpwhAlpha[29 + nAlphaOffset];
    2238          23 :         if (UtilityRoutines::SameString(CtrlLogicFlag, "SIMULTANEOUS")) {
    2239          20 :             HPWH.AllowHeatingElementAndHeatPumpToRunAtSameTime = true;
    2240           3 :         } else if (UtilityRoutines::SameString(CtrlLogicFlag, "MUTUALLYEXCLUSIVE")) {
    2241           3 :             HPWH.AllowHeatingElementAndHeatPumpToRunAtSameTime = false;
    2242             :         } else {
    2243           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + HPWH.Name + "\":");
    2244           0 :             ShowContinueError(state, CtrlLogicFlag + " is not a valid value for field Tank Element Control Logic.");
    2245           0 :             ErrorsFound = true;
    2246             :         }
    2247             : 
    2248             :         // Control Sensor 1 Location In Stratified Tank
    2249          23 :         if (!hpwhNumericBlank[8 + nNumericOffset]) {
    2250          11 :             HPWH.ControlSensor1Height = hpwhNumeric[8 + nNumericOffset];
    2251             :         } else {
    2252             :             // use heater1 location, which we don't know right now
    2253          12 :             HPWH.ControlSensor1Height = -1.0;
    2254             :         }
    2255             : 
    2256             :         // Control Sensor 1 Weight
    2257          23 :         HPWH.ControlSensor1Weight = hpwhNumericBlank[9 + nNumericOffset] ? 1.0 : hpwhNumeric[9 + nNumericOffset];
    2258             : 
    2259             :         // Control Sensor 2 Location In Stratified Tank
    2260          23 :         if (!hpwhNumericBlank[10 + nNumericOffset]) {
    2261          23 :             HPWH.ControlSensor2Height = hpwhNumeric[10 + nNumericOffset];
    2262             :         } else {
    2263           0 :             HPWH.ControlSensor2Height = -1.0;
    2264             :         }
    2265             : 
    2266             :         // Control Sensor 2 Weight
    2267          23 :         HPWH.ControlSensor2Weight = 1.0 - HPWH.ControlSensor1Weight;
    2268             :     }
    2269             : 
    2270           9 :     return ErrorsFound;
    2271             : }
    2272             : 
    2273         119 : bool getWaterHeaterMixedInputs(EnergyPlusData &state)
    2274             : {
    2275         119 :     bool ErrorsFound = false;
    2276         119 :     state.dataIPShortCut->cCurrentModuleObject = cMixedWHModuleObj;
    2277             :     static constexpr std::string_view RoutineName = "getWaterHeaterMixedInputs";
    2278             : 
    2279         291 :     for (int WaterThermalTankNum = 1; WaterThermalTankNum <= state.dataWaterThermalTanks->numWaterHeaterMixed; ++WaterThermalTankNum) {
    2280             :         int NumAlphas;
    2281             :         int NumNums;
    2282             :         int IOStat;
    2283        1376 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2284         172 :                                                                  state.dataIPShortCut->cCurrentModuleObject,
    2285             :                                                                  WaterThermalTankNum,
    2286         172 :                                                                  state.dataIPShortCut->cAlphaArgs,
    2287             :                                                                  NumAlphas,
    2288         172 :                                                                  state.dataIPShortCut->rNumericArgs,
    2289             :                                                                  NumNums,
    2290             :                                                                  IOStat,
    2291         172 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
    2292         172 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
    2293         172 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
    2294         172 :                                                                  state.dataIPShortCut->cNumericFieldNames);
    2295         516 :         GlobalNames::VerifyUniqueInterObjectName(state,
    2296         172 :                                                  state.dataWaterThermalTanks->UniqueWaterThermalTankNames,
    2297         172 :                                                  state.dataIPShortCut->cAlphaArgs(1),
    2298         172 :                                                  state.dataIPShortCut->cCurrentModuleObject,
    2299         172 :                                                  state.dataIPShortCut->cAlphaFieldNames(1),
    2300             :                                                  ErrorsFound);
    2301             : 
    2302         172 :         auto &Tank = state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum);
    2303             : 
    2304         172 :         Tank.Name = state.dataIPShortCut->cAlphaArgs(1);
    2305         172 :         Tank.Type = state.dataIPShortCut->cCurrentModuleObject;
    2306         172 :         Tank.WaterThermalTankType = DataPlant::PlantEquipmentType::WtrHeaterMixed;
    2307         172 :         Tank.FluidIndex = Tank.waterIndex;
    2308             : 
    2309             :         // default to always on
    2310         172 :         Tank.SourceSideAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
    2311         172 :         Tank.UseSideAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
    2312             : 
    2313             :         // A user field will be added in a later release
    2314         172 :         Tank.EndUseSubcategoryName = "Water Heater";
    2315             : 
    2316         172 :         Tank.Volume = state.dataIPShortCut->rNumericArgs(1);
    2317         172 :         if (Tank.Volume == DataSizing::AutoSize) {
    2318           2 :             Tank.VolumeWasAutoSized = true;
    2319             :         }
    2320         172 :         if (state.dataIPShortCut->rNumericArgs(1) == 0.0) {
    2321             :             // Set volume to a really small number to simulate a tankless/instantaneous water heater
    2322           0 :             Tank.Volume = 0.000001; // = 1 cm3
    2323             :         }
    2324             : 
    2325         172 :         Tank.SetPointTempSchedule = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
    2326         172 :         if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
    2327           0 :             ShowSevereError(state,
    2328           0 :                             std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
    2329             :                                 "\", missing data.");
    2330           0 :             ShowContinueError(state, "blank field, missing " + state.dataIPShortCut->cAlphaFieldNames(2) + " is required");
    2331           0 :             ErrorsFound = true;
    2332         172 :         } else if (Tank.SetPointTempSchedule == 0) {
    2333           0 :             ShowSevereError(state,
    2334           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) + ":  " +
    2335           0 :                                 state.dataIPShortCut->cAlphaFieldNames(2) + " not found = " + state.dataIPShortCut->cAlphaArgs(2));
    2336           0 :             ErrorsFound = true;
    2337             :         }
    2338             : 
    2339         172 :         if (state.dataIPShortCut->rNumericArgs(2) > 0.0001) {
    2340         166 :             Tank.DeadBandDeltaTemp = state.dataIPShortCut->rNumericArgs(2);
    2341             :         } else {
    2342             :             // Default to very small number (however it can't be TINY or it will break the algorithm)
    2343           6 :             Tank.DeadBandDeltaTemp = 0.5;
    2344             :         }
    2345             : 
    2346         172 :         if (state.dataIPShortCut->rNumericArgs(3) > 0.0) {
    2347         172 :             Tank.TankTempLimit = state.dataIPShortCut->rNumericArgs(3);
    2348             :         } else {
    2349             :             // Default to very large number
    2350             :             // BG comment why a large number here why not boilng point of water?
    2351           0 :             Tank.TankTempLimit = 100.0; // 1.0E9
    2352             :         }
    2353             : 
    2354         172 :         Tank.MaxCapacity = state.dataIPShortCut->rNumericArgs(4);
    2355         172 :         if (Tank.MaxCapacity == DataSizing::AutoSize) {
    2356           0 :             Tank.MaxCapacityWasAutoSized = true;
    2357             :         }
    2358             : 
    2359         172 :         if ((state.dataIPShortCut->rNumericArgs(5) > Tank.MaxCapacity) && (!Tank.MaxCapacityWasAutoSized)) {
    2360           0 :             ShowSevereError(state,
    2361           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2362             :                                 ":  Heater Minimum Capacity cannot be greater than Heater Maximum Capacity");
    2363           0 :             ErrorsFound = true;
    2364             :         } else {
    2365         172 :             Tank.MinCapacity = state.dataIPShortCut->rNumericArgs(5);
    2366             :         }
    2367             : 
    2368             :         // Validate Heater Control Type
    2369         172 :         Tank.ControlType = static_cast<HeaterControlMode>(
    2370         344 :             getEnumerationValue(HeaterControlModeNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(3))));
    2371         172 :         switch (Tank.ControlType) {
    2372         167 :         case HeaterControlMode::Cycle: {
    2373         167 :             Tank.MinCapacity = Tank.MaxCapacity;
    2374         167 :             break;
    2375             :         }
    2376           5 :         case HeaterControlMode::Modulate: {
    2377             : 
    2378             :             // CASE ('MODULATE WITH OVERHEAT')  ! Not yet implemented
    2379             : 
    2380             :             // CASE ('MODULATE WITH UNDERHEAT')  ! Not yet implemented
    2381             : 
    2382           5 :             break;
    2383             :         }
    2384           0 :         default: {
    2385           0 :             ShowSevereError(state,
    2386           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2387           0 :                                 ":  Invalid Control Type entered=" + state.dataIPShortCut->cAlphaArgs(3));
    2388           0 :             ErrorsFound = true;
    2389           0 :             break;
    2390             :         }
    2391             :         }
    2392             : 
    2393         172 :         Tank.VolFlowRateMin = state.dataIPShortCut->rNumericArgs(6);
    2394         172 :         Tank.VolFlowRateMin = max(0.0, Tank.VolFlowRateMin);
    2395         172 :         Tank.IgnitionDelay = state.dataIPShortCut->rNumericArgs(7); // Not yet implemented
    2396             : 
    2397             :         // Validate Heater Fuel Type
    2398         172 :         Tank.FuelType = static_cast<Fuel>(getEnumerationValue(FuelTypeNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(4))));
    2399         172 :         switch (Tank.FuelType) {
    2400           0 :         case Fuel::Invalid: {
    2401           0 :             ShowSevereError(state,
    2402           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2403           0 :                                 ":  Invalid Heater Fuel Type entered=" + state.dataIPShortCut->cAlphaArgs(4));
    2404             :             // Set to Electric to avoid errors when setting up output variables
    2405           0 :             Tank.FuelType = Fuel::Electricity;
    2406           0 :             ErrorsFound = true;
    2407           0 :             break;
    2408             :         }
    2409         172 :         default:
    2410         172 :             break;
    2411             :         }
    2412             : 
    2413         172 :         if (state.dataIPShortCut->rNumericArgs(8) > 0.0) {
    2414         172 :             Tank.Efficiency = state.dataIPShortCut->rNumericArgs(8);
    2415             :         } else {
    2416           0 :             ShowSevereError(state,
    2417           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2418             :                                 ":  Heater Thermal Efficiency must be greater than zero");
    2419           0 :             ErrorsFound = true;
    2420             :         }
    2421             : 
    2422         172 :         if (!state.dataIPShortCut->cAlphaArgs(5).empty()) {
    2423           0 :             Tank.PLFCurve = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(5));
    2424           0 :             if (Tank.PLFCurve == 0) {
    2425           0 :                 ShowSevereError(state,
    2426           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2427           0 :                                     ":  Part Load Factor curve not found = " + state.dataIPShortCut->cAlphaArgs(5));
    2428           0 :                 ErrorsFound = true;
    2429             :             } else {
    2430             :                 bool IsValid;
    2431           0 :                 EnergyPlus::WaterThermalTanks::WaterThermalTankData::ValidatePLFCurve(state, Tank.PLFCurve, IsValid);
    2432             : 
    2433           0 :                 if (!IsValid) {
    2434           0 :                     ShowSevereError(state,
    2435           0 :                                     state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2436             :                                         ":  Part Load Factor curve failed to evaluate to greater than zero for all numbers in the domain of 0 to 1");
    2437           0 :                     ErrorsFound = true;
    2438             :                 }
    2439             : 
    2440           0 :                 ErrorsFound |= Curve::CheckCurveDims(state,
    2441             :                                                      Tank.PLFCurve,                              // Curve index
    2442             :                                                      {1},                                        // Valid dimensions
    2443             :                                                      RoutineName,                                // Routine name
    2444           0 :                                                      state.dataIPShortCut->cCurrentModuleObject, // Object Type
    2445             :                                                      Tank.Name,                                  // Object Name
    2446           0 :                                                      state.dataIPShortCut->cAlphaFieldNames(5)); // Field Name
    2447             :             }
    2448             :         }
    2449             : 
    2450         172 :         Tank.OffCycParaLoad = state.dataIPShortCut->rNumericArgs(9);
    2451             : 
    2452             :         // Validate Off-Cycle Parasitic Fuel Type
    2453         172 :         Tank.OffCycParaFuelType =
    2454         344 :             static_cast<Fuel>(getEnumerationValue(FuelTypeNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(6))));
    2455         172 :         switch (Tank.OffCycParaFuelType) {
    2456          15 :         case Fuel::Invalid:
    2457          15 :             if (state.dataIPShortCut->cAlphaArgs(6).empty()) { // If blank, default to Fuel Type for heater
    2458          15 :                 Tank.OffCycParaFuelType = Tank.FuelType;
    2459             :             } else { // could have been an unsupported value
    2460           0 :                 ShowSevereError(state,
    2461           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2462           0 :                                     ":  Invalid Off-Cycle Parasitic Fuel Type entered=" + state.dataIPShortCut->cAlphaArgs(6));
    2463             :                 // Set to Electric to avoid errors when setting up output variables
    2464           0 :                 Tank.OffCycParaFuelType = Fuel::Electricity;
    2465           0 :                 ErrorsFound = true;
    2466             :             }
    2467          15 :             break;
    2468         157 :         default:
    2469         157 :             break;
    2470             :         }
    2471             : 
    2472         172 :         Tank.OffCycParaFracToTank = state.dataIPShortCut->rNumericArgs(10);
    2473             : 
    2474         172 :         Tank.OnCycParaLoad = state.dataIPShortCut->rNumericArgs(11);
    2475             : 
    2476             :         // Validate On-Cycle Parasitic Fuel Type
    2477         172 :         Tank.OnCycParaFuelType =
    2478         344 :             static_cast<Fuel>(getEnumerationValue(FuelTypeNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(7))));
    2479         172 :         switch (Tank.OnCycParaFuelType) {
    2480          55 :         case Fuel::Invalid:
    2481          55 :             if (state.dataIPShortCut->cAlphaArgs(7).empty()) { // If blank, default to Fuel Type for heater
    2482          55 :                 Tank.OnCycParaFuelType = Tank.FuelType;
    2483             :             } else { // could have been an unsupported value
    2484           0 :                 ShowSevereError(state,
    2485           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2486           0 :                                     ":  Invalid On-Cycle Parasitic Fuel Type entered=" + state.dataIPShortCut->cAlphaArgs(7));
    2487             :                 // Set to Electric to avoid errors when setting up output variables
    2488           0 :                 Tank.OnCycParaFuelType = Fuel::Electricity;
    2489           0 :                 ErrorsFound = true;
    2490             :             }
    2491          55 :             break;
    2492         117 :         default:
    2493         117 :             break;
    2494             :         }
    2495             : 
    2496         172 :         Tank.OnCycParaFracToTank = state.dataIPShortCut->rNumericArgs(12);
    2497             : 
    2498         172 :         Tank.AmbientTempIndicator = static_cast<WTTAmbientTemp>(
    2499         344 :             getEnumerationValue(TankAmbientTempNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(8))));
    2500         172 :         switch (Tank.AmbientTempIndicator) {
    2501          96 :         case WTTAmbientTemp::Schedule: {
    2502          96 :             Tank.AmbientTempSchedule = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(9));
    2503          96 :             if (Tank.AmbientTempSchedule == 0) {
    2504           0 :                 ShowSevereError(state,
    2505           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2506           0 :                                     ":  Ambient Temperature Schedule not found = " + state.dataIPShortCut->cAlphaArgs(9));
    2507           0 :                 ErrorsFound = true;
    2508             :             }
    2509             : 
    2510          96 :             break;
    2511             :         }
    2512          69 :         case WTTAmbientTemp::TempZone: {
    2513          69 :             Tank.AmbientTempZone = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(10), state.dataHeatBal->Zone);
    2514          69 :             if (Tank.AmbientTempZone == 0) {
    2515           0 :                 ShowSevereError(state,
    2516           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2517           0 :                                     ":  Ambient Temperature Zone not found = " + state.dataIPShortCut->cAlphaArgs(10));
    2518           0 :                 ErrorsFound = true;
    2519             :             }
    2520             : 
    2521          69 :             break;
    2522             :         }
    2523           7 :         case WTTAmbientTemp::OutsideAir: {
    2524           7 :             Tank.AmbientTempOutsideAirNode = NodeInputManager::GetOnlySingleNode(state,
    2525           7 :                                                                                  state.dataIPShortCut->cAlphaArgs(11),
    2526             :                                                                                  ErrorsFound,
    2527             :                                                                                  DataLoopNode::ConnectionObjectType::WaterHeaterMixed,
    2528           7 :                                                                                  state.dataIPShortCut->cAlphaArgs(1),
    2529             :                                                                                  DataLoopNode::NodeFluidType::Air,
    2530             :                                                                                  DataLoopNode::ConnectionType::OutsideAirReference,
    2531             :                                                                                  NodeInputManager::CompFluidStream::Primary,
    2532           7 :                                                                                  DataLoopNode::ObjectIsNotParent);
    2533           7 :             if (!state.dataIPShortCut->cAlphaArgs(11).empty()) {
    2534           7 :                 if (!OutAirNodeManager::CheckOutAirNodeNumber(state, Tank.AmbientTempOutsideAirNode)) {
    2535           0 :                     ShowSevereError(state,
    2536           0 :                                     state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2537             :                                         ": Outdoor Air Node not on OutdoorAir:NodeList or OutdoorAir:Node");
    2538           0 :                     ShowContinueError(state, "...Referenced Node Name=" + state.dataIPShortCut->cAlphaArgs(11));
    2539           0 :                     ErrorsFound = true;
    2540             :                 }
    2541             :             } else {
    2542           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    2543           0 :                 ShowContinueError(state, "An Ambient Outdoor Air Node name must be used when the Ambient Temperature Indicator is Outdoors.");
    2544           0 :                 ErrorsFound = true;
    2545             :             }
    2546             : 
    2547           7 :             break;
    2548             :         }
    2549           0 :         default: {
    2550           0 :             ShowSevereError(state,
    2551           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2552           0 :                                 ":  Invalid Ambient Temperature Indicator entered=" + state.dataIPShortCut->cAlphaArgs(8));
    2553           0 :             ShowContinueError(state, " Valid entries are SCHEDULE, ZONE, and OUTDOORS.");
    2554           0 :             ErrorsFound = true;
    2555           0 :             break;
    2556             :         }
    2557             :         }
    2558             : 
    2559         172 :         Tank.OffCycLossCoeff = state.dataIPShortCut->rNumericArgs(13);
    2560         172 :         Tank.OffCycLossFracToZone = state.dataIPShortCut->rNumericArgs(14);
    2561             : 
    2562         172 :         Tank.OnCycLossCoeff = state.dataIPShortCut->rNumericArgs(15);
    2563         172 :         Tank.OnCycLossFracToZone = state.dataIPShortCut->rNumericArgs(16);
    2564         172 :         Real64 rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, DataGlobalConstants::InitConvTemp, Tank.FluidIndex, RoutineName);
    2565         172 :         Tank.MassFlowRateMax = state.dataIPShortCut->rNumericArgs(17) * rho;
    2566             : 
    2567         172 :         if ((state.dataIPShortCut->cAlphaArgs(14).empty()) && (state.dataIPShortCut->cAlphaArgs(15).empty())) {
    2568          61 :             if (!state.dataIPShortCut->cAlphaArgs(12).empty()) {
    2569          61 :                 Tank.FlowRateSchedule = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(12));
    2570          61 :                 if (Tank.FlowRateSchedule == 0) {
    2571           0 :                     ShowSevereError(state,
    2572           0 :                                     state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2573           0 :                                         ":  Flow Rate Schedule not found = " + state.dataIPShortCut->cAlphaArgs(12));
    2574           0 :                     ErrorsFound = true;
    2575             :                 }
    2576             :             }
    2577             :         }
    2578             : 
    2579         172 :         if (!state.dataIPShortCut->cAlphaArgs(13).empty()) {
    2580           9 :             Tank.UseInletTempSchedule = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(13));
    2581           9 :             if (Tank.UseInletTempSchedule == 0) {
    2582           0 :                 ShowSevereError(state,
    2583           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2584           0 :                                     ":  Cold Water Supply Temperature Schedule not found = " + state.dataIPShortCut->cAlphaArgs(13));
    2585           0 :                 ErrorsFound = true;
    2586             :             }
    2587             :         }
    2588             : 
    2589         172 :         if (NumNums > 17) {
    2590         127 :             if ((state.dataIPShortCut->rNumericArgs(18) > 1) || (state.dataIPShortCut->rNumericArgs(18) < 0)) {
    2591           0 :                 ShowSevereError(state,
    2592           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2593             :                                     ":  Use Side Effectiveness is out of bounds (0 to 1)");
    2594           0 :                 ErrorsFound = true;
    2595             :             }
    2596         127 :             Tank.UseEffectiveness = state.dataIPShortCut->rNumericArgs(18);
    2597             :         } else {
    2598          45 :             Tank.UseEffectiveness = 1.0; // Default for stand-alone mode
    2599             :         }
    2600             : 
    2601         172 :         if (NumNums > 18) {
    2602         127 :             if ((state.dataIPShortCut->rNumericArgs(19) > 1) || (state.dataIPShortCut->rNumericArgs(19) <= 0)) {
    2603           0 :                 ShowSevereError(state,
    2604           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2605             :                                     ":  Source Side Effectiveness is out of bounds (>0 to 1)");
    2606           0 :                 ErrorsFound = true;
    2607             :             }
    2608         127 :             Tank.SourceEffectiveness = state.dataIPShortCut->rNumericArgs(19);
    2609             :         } else {
    2610          45 :             Tank.SourceEffectiveness = 1.0;
    2611             :         }
    2612             : 
    2613             :         // If no plant nodes are connected, simulate in stand-alone mode.
    2614         466 :         if (state.dataIPShortCut->cAlphaArgs(14).empty() && state.dataIPShortCut->cAlphaArgs(15).empty() &&
    2615         280 :             state.dataIPShortCut->cAlphaArgs(16).empty() && state.dataIPShortCut->cAlphaArgs(17).empty()) {
    2616          47 :             Tank.StandAlone = true;
    2617             :         }
    2618             : 
    2619         172 :         if (!state.dataIPShortCut->lNumericFieldBlanks(20)) {
    2620         111 :             Tank.UseDesignVolFlowRate = state.dataIPShortCut->rNumericArgs(20);
    2621         111 :             if (Tank.UseDesignVolFlowRate == DataSizing::AutoSize) {
    2622         105 :                 Tank.UseDesignVolFlowRateWasAutoSized = true;
    2623             :             }
    2624             :         } else {
    2625          61 :             Tank.UseDesignVolFlowRate = 0.0;
    2626             :         }
    2627         172 :         Tank.UseSidePlantLoc.loopSideNum = DataPlant::LoopSideLocation::Invalid;
    2628             : 
    2629         172 :         if (!state.dataIPShortCut->lNumericFieldBlanks(21)) {
    2630         103 :             Tank.SourceDesignVolFlowRate = state.dataIPShortCut->rNumericArgs(21);
    2631         103 :             if (Tank.SourceDesignVolFlowRate == DataSizing::AutoSize) {
    2632          94 :                 Tank.SourceDesignVolFlowRateWasAutoSized = true;
    2633             :             }
    2634             :         } else {
    2635          69 :             Tank.SourceDesignVolFlowRate = 0.0;
    2636             :         }
    2637         172 :         Tank.SrcSidePlantLoc.loopSideNum = DataPlant::LoopSideLocation::Invalid;
    2638             : 
    2639         172 :         if (!state.dataIPShortCut->lNumericFieldBlanks(22)) {
    2640          90 :             Tank.SizingRecoveryTime = state.dataIPShortCut->rNumericArgs(22);
    2641             :         } else {
    2642          82 :             Tank.SizingRecoveryTime = 1.5;
    2643             :         }
    2644             : 
    2645         172 :         if ((!state.dataIPShortCut->cAlphaArgs(14).empty()) || (!state.dataIPShortCut->cAlphaArgs(15).empty())) {
    2646         111 :             Tank.UseInletNode = NodeInputManager::GetOnlySingleNode(state,
    2647         111 :                                                                     state.dataIPShortCut->cAlphaArgs(14),
    2648             :                                                                     ErrorsFound,
    2649             :                                                                     DataLoopNode::ConnectionObjectType::WaterHeaterMixed,
    2650         111 :                                                                     state.dataIPShortCut->cAlphaArgs(1),
    2651             :                                                                     DataLoopNode::NodeFluidType::Water,
    2652             :                                                                     DataLoopNode::ConnectionType::Inlet,
    2653             :                                                                     NodeInputManager::CompFluidStream::Primary,
    2654         111 :                                                                     DataLoopNode::ObjectIsNotParent);
    2655         111 :             Tank.InletNodeName1 = state.dataIPShortCut->cAlphaArgs(14);
    2656         111 :             Tank.UseOutletNode = NodeInputManager::GetOnlySingleNode(state,
    2657         111 :                                                                      state.dataIPShortCut->cAlphaArgs(15),
    2658             :                                                                      ErrorsFound,
    2659             :                                                                      DataLoopNode::ConnectionObjectType::WaterHeaterMixed,
    2660         111 :                                                                      state.dataIPShortCut->cAlphaArgs(1),
    2661             :                                                                      DataLoopNode::NodeFluidType::Water,
    2662             :                                                                      DataLoopNode::ConnectionType::Outlet,
    2663             :                                                                      NodeInputManager::CompFluidStream::Primary,
    2664         111 :                                                                      DataLoopNode::ObjectIsNotParent);
    2665         111 :             Tank.OutletNodeName1 = state.dataIPShortCut->cAlphaArgs(15);
    2666             : 
    2667         111 :             if (state.dataIPShortCut->rNumericArgs(17) > 0) {
    2668           0 :                 ShowWarningError(state,
    2669           0 :                                  state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2670             :                                      ":  Use side nodes are specified; Peak Volumetric Use Flow Rate will not be used");
    2671             :             }
    2672             : 
    2673         111 :             if (Tank.FlowRateSchedule > 0) {
    2674           0 :                 ShowWarningError(state,
    2675           0 :                                  state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2676             :                                      ":  Use side nodes are specified; Use Flow Rate Fraction Schedule will not be used");
    2677             :             }
    2678             : 
    2679         111 :             if (Tank.UseInletTempSchedule > 0) {
    2680           0 :                 ShowWarningError(state,
    2681           0 :                                  state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2682             :                                      ":  Use side nodes are specified; Cold Water Supply Temperature Schedule will not be used");
    2683             :             }
    2684             :         }
    2685             : 
    2686         172 :         if ((!state.dataIPShortCut->cAlphaArgs(16).empty()) || (!state.dataIPShortCut->cAlphaArgs(17).empty())) {
    2687          32 :             Tank.SourceInletNode = NodeInputManager::GetOnlySingleNode(state,
    2688          32 :                                                                        state.dataIPShortCut->cAlphaArgs(16),
    2689             :                                                                        ErrorsFound,
    2690             :                                                                        DataLoopNode::ConnectionObjectType::WaterHeaterMixed,
    2691          32 :                                                                        state.dataIPShortCut->cAlphaArgs(1),
    2692             :                                                                        DataLoopNode::NodeFluidType::Water,
    2693             :                                                                        DataLoopNode::ConnectionType::Inlet,
    2694             :                                                                        NodeInputManager::CompFluidStream::Secondary,
    2695          32 :                                                                        DataLoopNode::ObjectIsNotParent);
    2696          32 :             Tank.InletNodeName2 = state.dataIPShortCut->cAlphaArgs(16);
    2697          32 :             Tank.SourceOutletNode = NodeInputManager::GetOnlySingleNode(state,
    2698          32 :                                                                         state.dataIPShortCut->cAlphaArgs(17),
    2699             :                                                                         ErrorsFound,
    2700             :                                                                         DataLoopNode::ConnectionObjectType::WaterHeaterMixed,
    2701          32 :                                                                         state.dataIPShortCut->cAlphaArgs(1),
    2702             :                                                                         DataLoopNode::NodeFluidType::Water,
    2703             :                                                                         DataLoopNode::ConnectionType::Outlet,
    2704             :                                                                         NodeInputManager::CompFluidStream::Secondary,
    2705          32 :                                                                         DataLoopNode::ObjectIsNotParent);
    2706          32 :             Tank.OutletNodeName2 = state.dataIPShortCut->cAlphaArgs(17);
    2707             :         }
    2708             : 
    2709         172 :         if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) {
    2710           1 :             Tank.SourceSideControlMode = static_cast<SourceSideControl>(
    2711           2 :                 getEnumerationValue(SourceSideControlNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(18))));
    2712           1 :             if (Tank.SourceSideControlMode == SourceSideControl::Invalid) {
    2713           0 :                 ShowSevereError(state,
    2714           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2715           0 :                                     ":  Invalid Control Mode entered=" + state.dataIPShortCut->cAlphaArgs(18));
    2716           0 :                 ErrorsFound = true;
    2717             :             }
    2718             :         } else {
    2719         171 :             Tank.SourceSideControlMode = SourceSideControl::IndirectHeatPrimarySetpoint;
    2720             :         }
    2721             : 
    2722         172 :         if (!state.dataIPShortCut->lAlphaFieldBlanks(19)) {
    2723           0 :             Tank.SourceSideAltSetpointSchedNum = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(19));
    2724           0 :             if (Tank.SourceSideAltSetpointSchedNum == 0) {
    2725           0 :                 ShowSevereError(state,
    2726           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) + ":  " +
    2727           0 :                                     state.dataIPShortCut->cAlphaFieldNames(19) + " not found = " + state.dataIPShortCut->cAlphaArgs(19));
    2728           0 :                 ErrorsFound = true;
    2729             :             }
    2730             :         }
    2731         172 :         if (NumAlphas > 19) {
    2732           1 :             Tank.EndUseSubcategoryName = state.dataIPShortCut->cAlphaArgs(20);
    2733             :         }
    2734             : 
    2735             :     } // WaterThermalTankNum
    2736             : 
    2737         119 :     return ErrorsFound;
    2738             : }
    2739             : 
    2740          10 : bool getWaterHeaterStratifiedInput(EnergyPlusData &state)
    2741             : {
    2742          10 :     bool ErrorsFound = false;
    2743             :     static constexpr std::string_view RoutineName = "getWaterHeaterStratifiedInput";
    2744             : 
    2745          10 :     state.dataIPShortCut->cCurrentModuleObject = cStratifiedWHModuleObj; //'WaterHeater:Stratified'
    2746             : 
    2747          26 :     for (int WaterThermalTankNum = state.dataWaterThermalTanks->numWaterHeaterMixed + 1;
    2748          26 :          WaterThermalTankNum <= state.dataWaterThermalTanks->numWaterHeaterMixed + state.dataWaterThermalTanks->numWaterHeaterStratified;
    2749             :          ++WaterThermalTankNum) {
    2750             :         int NumAlphas;
    2751             :         int NumNums;
    2752             :         int IOStat;
    2753         144 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2754          16 :                                                                  state.dataIPShortCut->cCurrentModuleObject,
    2755          16 :                                                                  WaterThermalTankNum - state.dataWaterThermalTanks->numWaterHeaterMixed,
    2756          16 :                                                                  state.dataIPShortCut->cAlphaArgs,
    2757             :                                                                  NumAlphas,
    2758          16 :                                                                  state.dataIPShortCut->rNumericArgs,
    2759             :                                                                  NumNums,
    2760             :                                                                  IOStat,
    2761          16 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
    2762          16 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
    2763          16 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
    2764          16 :                                                                  state.dataIPShortCut->cNumericFieldNames);
    2765          48 :         GlobalNames::VerifyUniqueInterObjectName(state,
    2766          16 :                                                  state.dataWaterThermalTanks->UniqueWaterThermalTankNames,
    2767          16 :                                                  state.dataIPShortCut->cAlphaArgs(1),
    2768          16 :                                                  state.dataIPShortCut->cCurrentModuleObject,
    2769          16 :                                                  state.dataIPShortCut->cAlphaFieldNames(1),
    2770             :                                                  ErrorsFound);
    2771             : 
    2772          16 :         auto &Tank = state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum);
    2773             : 
    2774          16 :         Tank.Name = state.dataIPShortCut->cAlphaArgs(1);
    2775          16 :         Tank.Type = state.dataIPShortCut->cCurrentModuleObject;
    2776          16 :         Tank.WaterThermalTankType = DataPlant::PlantEquipmentType::WtrHeaterStratified;
    2777          16 :         Tank.FluidIndex = Tank.waterIndex;
    2778             : 
    2779             :         // default to always on
    2780          16 :         Tank.SourceSideAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
    2781          16 :         Tank.UseSideAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
    2782             : 
    2783          16 :         Tank.EndUseSubcategoryName = state.dataIPShortCut->cAlphaArgs(2);
    2784             : 
    2785          16 :         Tank.Volume = state.dataIPShortCut->rNumericArgs(1);
    2786          16 :         if (Tank.Volume == DataSizing::AutoSize) {
    2787           0 :             Tank.VolumeWasAutoSized = true;
    2788             :         }
    2789          16 :         Real64 rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, DataGlobalConstants::InitConvTemp, Tank.FluidIndex, RoutineName);
    2790          16 :         Tank.Mass = Tank.Volume * rho;
    2791          16 :         Tank.Height = state.dataIPShortCut->rNumericArgs(2);
    2792          16 :         if (Tank.Height == DataSizing::AutoSize) {
    2793           0 :             Tank.HeightWasAutoSized = true;
    2794             :         }
    2795             : 
    2796          16 :         Tank.Shape =
    2797          32 :             static_cast<TankShape>(getEnumerationValue(TankShapeNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(3))));
    2798          16 :         switch (Tank.Shape) {
    2799          16 :         case TankShape::HorizCylinder:
    2800             :         case TankShape::VertCylinder: {
    2801          16 :             break;
    2802             :         }
    2803           0 :         case TankShape::Other: {
    2804           0 :             if (state.dataIPShortCut->rNumericArgs(3) > 0.0) {
    2805           0 :                 Tank.Perimeter = state.dataIPShortCut->rNumericArgs(3);
    2806             :             } else {
    2807           0 :                 ShowSevereError(state,
    2808           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2809             :                                     ":  Tank Perimeter must be greater than zero for Tank Shape=OTHER");
    2810           0 :                 ErrorsFound = true;
    2811             :             }
    2812             : 
    2813           0 :             break;
    2814             :         }
    2815           0 :         default: {
    2816           0 :             ShowSevereError(state,
    2817           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2818           0 :                                 ":  Invalid Tank Shape entered=" + state.dataIPShortCut->cAlphaArgs(3));
    2819           0 :             Tank.Shape = TankShape::VertCylinder;
    2820           0 :             ErrorsFound = true;
    2821           0 :             break;
    2822             :         }
    2823             :         }
    2824             : 
    2825          16 :         if (state.dataIPShortCut->rNumericArgs(4) > 0.0) {
    2826          16 :             Tank.TankTempLimit = state.dataIPShortCut->rNumericArgs(4);
    2827             :         } else {
    2828             :             // Default to very large number
    2829           0 :             Tank.TankTempLimit = 1.0e9;
    2830             :         }
    2831             : 
    2832             :         // Validate Heater Priority Control
    2833          16 :         Tank.StratifiedControlMode = static_cast<PriorityControlMode>(
    2834          32 :             getEnumerationValue(PriorityControlModeNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(4))));
    2835          16 :         if (Tank.StratifiedControlMode == PriorityControlMode::Invalid) {
    2836           0 :             ShowSevereError(state,
    2837           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2838           0 :                                 ":  Invalid Heater Priority Control entered=" + state.dataIPShortCut->cAlphaArgs(4));
    2839           0 :             ErrorsFound = true;
    2840             :         }
    2841             : 
    2842          16 :         Tank.SetPointTempSchedule = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(5));
    2843          16 :         if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
    2844           0 :             ShowSevereError(state,
    2845           0 :                             std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
    2846             :                                 "\", missing data.");
    2847           0 :             ShowContinueError(state, "blank field, missing " + state.dataIPShortCut->cAlphaFieldNames(5) + " is required");
    2848           0 :             ErrorsFound = true;
    2849          16 :         } else if (Tank.SetPointTempSchedule == 0) {
    2850           0 :             ShowSevereError(state,
    2851           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) + ": " +
    2852           0 :                                 state.dataIPShortCut->cAlphaFieldNames(5) + " not found = " + state.dataIPShortCut->cAlphaArgs(5));
    2853           0 :             ErrorsFound = true;
    2854             :         }
    2855             : 
    2856          16 :         if (state.dataIPShortCut->rNumericArgs(5) > 0.0) {
    2857          16 :             Tank.DeadBandDeltaTemp = state.dataIPShortCut->rNumericArgs(5);
    2858             :         } else {
    2859             :             // Default to very small number (however it can't be TINY or it will break the algorithm)
    2860           0 :             Tank.DeadBandDeltaTemp = 0.0001;
    2861             :         }
    2862             : 
    2863          16 :         Tank.MaxCapacity = state.dataIPShortCut->rNumericArgs(6);
    2864          16 :         if (Tank.MaxCapacity == DataSizing::AutoSize) {
    2865           2 :             Tank.MaxCapacityWasAutoSized = true;
    2866             :         }
    2867             : 
    2868          16 :         Tank.HeaterHeight1 = state.dataIPShortCut->rNumericArgs(7);
    2869             : 
    2870             :         // adjust tank height used in these calculations for testing heater height
    2871             :         Real64 tankHeightForTesting;
    2872          16 :         if (Tank.Shape == TankShape::HorizCylinder) {
    2873           0 :             tankHeightForTesting = 2.0 * sqrt((Tank.Volume / Tank.Height) / DataGlobalConstants::Pi);
    2874             :         } else {
    2875          16 :             tankHeightForTesting = Tank.Height;
    2876             :         }
    2877             : 
    2878             :         // Test if Heater height is within range
    2879          16 :         if ((!Tank.HeightWasAutoSized) && (Tank.HeaterHeight1 > tankHeightForTesting)) {
    2880           0 :             ShowSevereError(state,
    2881           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2882             :                                 ": Heater 1 is located higher than overall tank height.");
    2883           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
    2884           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(7), state.dataIPShortCut->rNumericArgs(7)));
    2885           0 :             ErrorsFound = true;
    2886             :         }
    2887             : 
    2888          16 :         Tank.SetPointTempSchedule2 = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(6));
    2889          16 :         if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
    2890           0 :             ShowSevereError(state,
    2891           0 :                             std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
    2892             :                                 "\", missing data.");
    2893           0 :             ShowContinueError(state, "blank field, missing " + state.dataIPShortCut->cAlphaFieldNames(6) + " is required");
    2894           0 :             ErrorsFound = true;
    2895          16 :         } else if (Tank.SetPointTempSchedule2 == 0) {
    2896           0 :             ShowSevereError(state,
    2897           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) + ":  " +
    2898           0 :                                 state.dataIPShortCut->cAlphaFieldNames(6) + " not found = " + state.dataIPShortCut->cAlphaArgs(6));
    2899           0 :             ErrorsFound = true;
    2900             :         }
    2901             : 
    2902          16 :         if (state.dataIPShortCut->rNumericArgs(5) > 0.0) {
    2903          16 :             Tank.DeadBandDeltaTemp2 = state.dataIPShortCut->rNumericArgs(8);
    2904             :         } else {
    2905             :             // Default to very small number (however it can't be TINY or it will break the algorithm)
    2906           0 :             Tank.DeadBandDeltaTemp2 = 0.0001;
    2907             :         }
    2908             : 
    2909          16 :         Tank.MaxCapacity2 = state.dataIPShortCut->rNumericArgs(9);
    2910          16 :         Tank.HeaterHeight2 = state.dataIPShortCut->rNumericArgs(10);
    2911             : 
    2912             :         // Test if Heater height is within range
    2913          16 :         if ((!Tank.HeightWasAutoSized) && (Tank.HeaterHeight2 > tankHeightForTesting)) {
    2914           0 :             ShowSevereError(state,
    2915           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2916             :                                 ": Heater 2 is located higher than overall tank height.");
    2917           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
    2918           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(10), state.dataIPShortCut->rNumericArgs(10)));
    2919           0 :             ErrorsFound = true;
    2920             :         }
    2921             : 
    2922             :         // Validate Heater Fuel Type
    2923          16 :         Tank.FuelType = static_cast<Fuel>(
    2924          48 :             getEnumerationValue(FuelTypeNamesUC,
    2925          48 :                                 UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(
    2926          32 :                                     7)))); // returns all kinds of fuels including district heat and cool + steam, returns unassigned if unsupported
    2927          16 :         if (Tank.FuelType == Fuel::Invalid) {
    2928           0 :             ShowSevereError(state,
    2929           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2930           0 :                                 ":  Invalid Heater Fuel Type entered=" + state.dataIPShortCut->cAlphaArgs(7));
    2931             :             // Set to Electric to avoid errors when setting up output variables
    2932           0 :             Tank.FuelType = Fuel::Electricity;
    2933           0 :             ErrorsFound = true;
    2934             :         }
    2935             : 
    2936          16 :         if (state.dataIPShortCut->rNumericArgs(11) > 0.0) {
    2937          16 :             Tank.Efficiency = state.dataIPShortCut->rNumericArgs(11);
    2938             :         } else {
    2939           0 :             ShowSevereError(state,
    2940           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2941             :                                 ":  Heater Thermal Efficiency must be greater than zero");
    2942           0 :             ErrorsFound = true;
    2943             :         }
    2944             : 
    2945          16 :         Tank.OffCycParaLoad = state.dataIPShortCut->rNumericArgs(12);
    2946             : 
    2947             :         // Validate Off-Cycle Parasitic Fuel Type
    2948          16 :         Tank.OffCycParaFuelType = static_cast<Fuel>(
    2949          48 :             getEnumerationValue(FuelTypeNamesUC,
    2950          48 :                                 UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(
    2951          32 :                                     8)))); // returns all kinds of fuels including district heat and cool + steam, returns unassigned if unsupported
    2952          16 :         if (Tank.OffCycParaFuelType == Fuel::Invalid) {
    2953           0 :             if (state.dataIPShortCut->cAlphaArgs(8).empty()) {
    2954           0 :                 Tank.OffCycParaFuelType = Tank.FuelType;
    2955             :             } else {
    2956           0 :                 ShowSevereError(state,
    2957           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2958           0 :                                     ":  Invalid Off-Cycle Parasitic Fuel Type entered=" + state.dataIPShortCut->cAlphaArgs(8));
    2959             :                 // Set to Electric to avoid errors when setting up output variables
    2960           0 :                 Tank.OffCycParaFuelType = Fuel::Electricity;
    2961           0 :                 ErrorsFound = true;
    2962             :             }
    2963             :         }
    2964             : 
    2965          16 :         Tank.OffCycParaFracToTank = state.dataIPShortCut->rNumericArgs(13);
    2966          16 :         Tank.OffCycParaHeight = state.dataIPShortCut->rNumericArgs(14);
    2967             : 
    2968          16 :         Tank.OnCycParaLoad = state.dataIPShortCut->rNumericArgs(15);
    2969             : 
    2970             :         // Validate On-Cycle Parasitic Fuel Type
    2971          32 :         Tank.OnCycParaFuelType = static_cast<Fuel>(getEnumerationValue(
    2972             :             FuelTypeNamesUC,
    2973          48 :             UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(
    2974          32 :                 9)))); // returns all kinds of fuels including district heat and cool + steam, returns unassigned if unsupported/empty
    2975          16 :         if (Tank.OnCycParaFuelType == Fuel::Invalid) {
    2976           0 :             if (state.dataIPShortCut->cAlphaArgs(9).empty()) {
    2977           0 :                 Tank.OnCycParaFuelType = Tank.FuelType;
    2978             :             } else {
    2979           0 :                 ShowSevereError(state,
    2980           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    2981           0 :                                     ":  Invalid On-Cycle Parasitic Fuel Type entered=" + state.dataIPShortCut->cAlphaArgs(9));
    2982             :                 // Set to Electric to avoid errors when setting up output variables
    2983           0 :                 Tank.OnCycParaFuelType = Fuel::Electricity;
    2984           0 :                 ErrorsFound = true;
    2985             :             }
    2986             :         }
    2987             : 
    2988          16 :         Tank.OnCycParaFracToTank = state.dataIPShortCut->rNumericArgs(16);
    2989          16 :         Tank.OnCycParaHeight = state.dataIPShortCut->rNumericArgs(17);
    2990             : 
    2991          16 :         Tank.AmbientTempIndicator = static_cast<WTTAmbientTemp>(
    2992          32 :             getEnumerationValue(TankAmbientTempNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(10))));
    2993          16 :         switch (Tank.AmbientTempIndicator) {
    2994             : 
    2995           8 :         case WTTAmbientTemp::Schedule: {
    2996           8 :             Tank.AmbientTempSchedule = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(11));
    2997           8 :             if (Tank.AmbientTempSchedule == 0) {
    2998           0 :                 ShowSevereError(state,
    2999           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3000           0 :                                     ":  Ambient Temperature Schedule not found = " + state.dataIPShortCut->cAlphaArgs(11));
    3001           0 :                 ErrorsFound = true;
    3002             :             }
    3003             : 
    3004           8 :             break;
    3005             :         }
    3006           6 :         case WTTAmbientTemp::TempZone: {
    3007           6 :             Tank.AmbientTempZone = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(12), state.dataHeatBal->Zone);
    3008           6 :             if (Tank.AmbientTempZone == 0) {
    3009           0 :                 ShowSevereError(state,
    3010           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3011           0 :                                     ":  Ambient Temperature Zone not found = " + state.dataIPShortCut->cAlphaArgs(12));
    3012           0 :                 ErrorsFound = true;
    3013             :             }
    3014             : 
    3015           6 :             break;
    3016             :         }
    3017           2 :         case WTTAmbientTemp::OutsideAir: {
    3018           2 :             Tank.AmbientTempOutsideAirNode = NodeInputManager::GetOnlySingleNode(state,
    3019           2 :                                                                                  state.dataIPShortCut->cAlphaArgs(13),
    3020             :                                                                                  ErrorsFound,
    3021             :                                                                                  DataLoopNode::ConnectionObjectType::WaterHeaterStratified,
    3022           2 :                                                                                  state.dataIPShortCut->cAlphaArgs(1),
    3023             :                                                                                  DataLoopNode::NodeFluidType::Air,
    3024             :                                                                                  DataLoopNode::ConnectionType::Inlet,
    3025             :                                                                                  NodeInputManager::CompFluidStream::Primary,
    3026           2 :                                                                                  DataLoopNode::ObjectIsNotParent);
    3027           2 :             if (!state.dataIPShortCut->cAlphaArgs(13).empty()) {
    3028           2 :                 if (!OutAirNodeManager::CheckOutAirNodeNumber(state, Tank.AmbientTempOutsideAirNode)) {
    3029           0 :                     ShowSevereError(state,
    3030           0 :                                     state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3031             :                                         ": Outdoor Air Node not on OutdoorAir:NodeList or OutdoorAir:Node");
    3032           0 :                     ShowContinueError(state, "...Referenced Node Name=" + state.dataIPShortCut->cAlphaArgs(13));
    3033           0 :                     ErrorsFound = true;
    3034             :                 }
    3035             :             } else {
    3036           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    3037           0 :                 ShowContinueError(state, "An Ambient Outdoor Air Node name must be used when the Ambient Temperature Indicator is Outdoors.");
    3038           0 :                 ErrorsFound = true;
    3039             :             }
    3040             : 
    3041           2 :             break;
    3042             :         }
    3043           0 :         default: {
    3044           0 :             ShowSevereError(state,
    3045           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3046           0 :                                 ":  Invalid Ambient Temperature Indicator entered=" + state.dataIPShortCut->cAlphaArgs(10));
    3047           0 :             ShowContinueError(state, " Valid entries are Schedule, Zone, and Outdoors.");
    3048           0 :             ErrorsFound = true;
    3049           0 :             break;
    3050             :         }
    3051             :         }
    3052             : 
    3053          16 :         Tank.SkinLossCoeff = state.dataIPShortCut->rNumericArgs(18);
    3054          16 :         Tank.SkinLossFracToZone = state.dataIPShortCut->rNumericArgs(19);
    3055          16 :         Tank.OffCycFlueLossCoeff = state.dataIPShortCut->rNumericArgs(20);
    3056          16 :         Tank.OffCycFlueLossFracToZone = state.dataIPShortCut->rNumericArgs(21);
    3057             : 
    3058             :         // this is temporary until we know fluid type
    3059          16 :         rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, DataGlobalConstants::InitConvTemp, Tank.FluidIndex, RoutineName);
    3060          16 :         Tank.MassFlowRateMax = state.dataIPShortCut->rNumericArgs(22) * rho;
    3061             : 
    3062          16 :         if ((state.dataIPShortCut->cAlphaArgs(16).empty()) && (state.dataIPShortCut->cAlphaArgs(17).empty())) {
    3063           7 :             if (!state.dataIPShortCut->cAlphaArgs(14).empty()) {
    3064           7 :                 Tank.FlowRateSchedule = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(14));
    3065           7 :                 if (Tank.FlowRateSchedule == 0) {
    3066           0 :                     ShowSevereError(state,
    3067           0 :                                     state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3068           0 :                                         ":  Flow Rate Schedule not found = " + state.dataIPShortCut->cAlphaArgs(14));
    3069           0 :                     ErrorsFound = true;
    3070             :                 }
    3071             :             }
    3072             :         }
    3073             : 
    3074          16 :         if (!state.dataIPShortCut->cAlphaArgs(15).empty()) {
    3075           0 :             Tank.UseInletTempSchedule = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(15));
    3076           0 :             if (Tank.UseInletTempSchedule == 0) {
    3077           0 :                 ShowSevereError(state,
    3078           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3079           0 :                                     ":  Cold Water Supply Temperature Schedule not found = " + state.dataIPShortCut->cAlphaArgs(15));
    3080           0 :                 ErrorsFound = true;
    3081             :             }
    3082             :         }
    3083             : 
    3084          16 :         if (NumNums > 22) {
    3085          16 :             Tank.UseEffectiveness = state.dataIPShortCut->rNumericArgs(23);
    3086             :         } else {
    3087           0 :             Tank.UseEffectiveness = 1.0; // Default for stand-alone mode
    3088             :         }
    3089             : 
    3090          16 :         if (NumNums > 23) {
    3091          16 :             Tank.UseInletHeight = state.dataIPShortCut->rNumericArgs(24);
    3092             :         } else {
    3093             :             // Defaults to bottom of tank
    3094           0 :             Tank.UseInletHeight = 0.0;
    3095             :         }
    3096          16 :         if ((!Tank.HeightWasAutoSized) && (Tank.UseInletHeight > Tank.Height)) {
    3097           0 :             ShowSevereError(state,
    3098           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3099             :                                 ": Use inlet is located higher than overall tank height.");
    3100           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
    3101           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(24), state.dataIPShortCut->rNumericArgs(24)));
    3102           0 :             ErrorsFound = true;
    3103             :         }
    3104             : 
    3105          16 :         if ((NumNums > 24) && (state.dataIPShortCut->rNumericArgs(25) != DataGlobalConstants::AutoCalculate)) {
    3106           1 :             Tank.UseOutletHeight = state.dataIPShortCut->rNumericArgs(25);
    3107             :         } else {
    3108             :             // Defaults to top of tank
    3109          15 :             Tank.UseOutletHeight = Tank.Height;
    3110             :         }
    3111          16 :         if (Tank.UseOutletHeight == DataSizing::AutoSize) {
    3112           0 :             Tank.UseOutletHeightWasAutoSized = true;
    3113             :         }
    3114          16 :         if ((!Tank.HeightWasAutoSized) && (Tank.UseOutletHeight > Tank.Height)) {
    3115           0 :             ShowSevereError(state,
    3116           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3117             :                                 ": Use outlet is located higher than overall tank height.");
    3118           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
    3119           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(25), state.dataIPShortCut->rNumericArgs(25)));
    3120           0 :             ErrorsFound = true;
    3121             :         }
    3122             : 
    3123          16 :         if (NumNums > 25) {
    3124          16 :             if ((state.dataIPShortCut->rNumericArgs(26) > 1) || (state.dataIPShortCut->rNumericArgs(26) <= 0)) {
    3125           0 :                 ShowSevereError(state,
    3126           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3127             :                                     ":  Source Side Effectiveness is out of bounds (>0 to 1)");
    3128           0 :                 ErrorsFound = true;
    3129             :             }
    3130          16 :             Tank.SourceEffectiveness = state.dataIPShortCut->rNumericArgs(26);
    3131             :         } else {
    3132           0 :             Tank.SourceEffectiveness = 1.0;
    3133             :         }
    3134             : 
    3135          16 :         if ((NumNums > 26) && (state.dataIPShortCut->rNumericArgs(27) != DataGlobalConstants::AutoCalculate)) {
    3136          11 :             Tank.SourceInletHeight = state.dataIPShortCut->rNumericArgs(27);
    3137             :         } else {
    3138             :             // Defaults to top of tank
    3139           5 :             Tank.SourceInletHeight = Tank.Height;
    3140             :         }
    3141          16 :         if (Tank.SourceInletHeight == DataSizing::AutoSize) {
    3142           0 :             Tank.SourceInletHeightWasAutoSized = true;
    3143             :         }
    3144          16 :         if ((!Tank.HeightWasAutoSized) && (Tank.SourceInletHeight > Tank.Height)) {
    3145           0 :             ShowSevereError(state,
    3146           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3147             :                                 ": Source inlet is located higher than overall tank height.");
    3148           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
    3149           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(27), state.dataIPShortCut->rNumericArgs(27)));
    3150           0 :             ErrorsFound = true;
    3151             :         }
    3152             : 
    3153          16 :         if ((NumNums > 27) && (state.dataIPShortCut->rNumericArgs(28) != DataGlobalConstants::AutoCalculate)) {
    3154          16 :             Tank.SourceOutletHeight = state.dataIPShortCut->rNumericArgs(28);
    3155             :         } else {
    3156             :             // Defaults to bottom of tank
    3157           0 :             Tank.SourceOutletHeight = 0.0;
    3158             :         }
    3159          16 :         if ((!Tank.HeightWasAutoSized) && (Tank.SourceOutletHeight > Tank.Height)) {
    3160           0 :             ShowSevereError(state,
    3161           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3162             :                                 ": Source outlet is located higher than overall tank height.");
    3163           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
    3164           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(28), state.dataIPShortCut->rNumericArgs(28)));
    3165           0 :             ErrorsFound = true;
    3166             :         }
    3167             : 
    3168             :         // If no plant nodes are connected, simulate in stand-alone mode.
    3169          46 :         if (state.dataIPShortCut->cAlphaArgs(16).empty() && state.dataIPShortCut->cAlphaArgs(17).empty() &&
    3170          25 :             state.dataIPShortCut->cAlphaArgs(18).empty() && state.dataIPShortCut->cAlphaArgs(19).empty())
    3171           2 :             Tank.StandAlone = true;
    3172             : 
    3173          16 :         if (!state.dataIPShortCut->lNumericFieldBlanks(29)) {
    3174           9 :             Tank.UseDesignVolFlowRate = state.dataIPShortCut->rNumericArgs(29);
    3175           9 :             if (Tank.UseDesignVolFlowRate == DataSizing::AutoSize) {
    3176           9 :                 Tank.UseDesignVolFlowRateWasAutoSized = true;
    3177             :             }
    3178             :         } else {
    3179           7 :             Tank.UseDesignVolFlowRate = 0.0;
    3180             :         }
    3181             : 
    3182          16 :         Tank.UseSidePlantLoc.loopSideNum = DataPlant::LoopSideLocation::Invalid;
    3183             : 
    3184          16 :         if (!state.dataIPShortCut->lNumericFieldBlanks(30)) {
    3185           6 :             Tank.SourceDesignVolFlowRate = state.dataIPShortCut->rNumericArgs(30);
    3186           6 :             if (Tank.SourceDesignVolFlowRate == DataSizing::AutoSize) {
    3187           4 :                 Tank.SourceDesignVolFlowRateWasAutoSized = true;
    3188             :             }
    3189             :         } else {
    3190          10 :             Tank.SourceDesignVolFlowRate = 0.0;
    3191             :         }
    3192             : 
    3193          16 :         if (NumNums > 30) {
    3194          16 :             Tank.SizingRecoveryTime = state.dataIPShortCut->rNumericArgs(31);
    3195             :         } else {
    3196           0 :             Tank.SizingRecoveryTime = 1.5;
    3197             :         }
    3198             : 
    3199          16 :         Tank.SrcSidePlantLoc.loopSideNum = DataPlant::LoopSideLocation::Invalid;
    3200             : 
    3201          16 :         if ((!state.dataIPShortCut->cAlphaArgs(16).empty()) || (!state.dataIPShortCut->cAlphaArgs(17).empty())) {
    3202           9 :             Tank.UseInletNode = NodeInputManager::GetOnlySingleNode(state,
    3203           9 :                                                                     state.dataIPShortCut->cAlphaArgs(16),
    3204             :                                                                     ErrorsFound,
    3205             :                                                                     DataLoopNode::ConnectionObjectType::WaterHeaterStratified,
    3206           9 :                                                                     state.dataIPShortCut->cAlphaArgs(1),
    3207             :                                                                     DataLoopNode::NodeFluidType::Water,
    3208             :                                                                     DataLoopNode::ConnectionType::Inlet,
    3209             :                                                                     NodeInputManager::CompFluidStream::Primary,
    3210           9 :                                                                     DataLoopNode::ObjectIsNotParent);
    3211           9 :             Tank.InletNodeName1 = state.dataIPShortCut->cAlphaArgs(16);
    3212           9 :             Tank.UseOutletNode = NodeInputManager::GetOnlySingleNode(state,
    3213           9 :                                                                      state.dataIPShortCut->cAlphaArgs(17),
    3214             :                                                                      ErrorsFound,
    3215             :                                                                      DataLoopNode::ConnectionObjectType::WaterHeaterStratified,
    3216           9 :                                                                      state.dataIPShortCut->cAlphaArgs(1),
    3217             :                                                                      DataLoopNode::NodeFluidType::Water,
    3218             :                                                                      DataLoopNode::ConnectionType::Outlet,
    3219             :                                                                      NodeInputManager::CompFluidStream::Primary,
    3220           9 :                                                                      DataLoopNode::ObjectIsNotParent);
    3221           9 :             Tank.OutletNodeName1 = state.dataIPShortCut->cAlphaArgs(17);
    3222             : 
    3223           9 :             if (state.dataIPShortCut->rNumericArgs(22) > 0) {
    3224           0 :                 ShowWarningError(state,
    3225           0 :                                  state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3226             :                                      ":  Use side nodes are specified; Peak Volumetric Use Flow Rate will not be used");
    3227             :             }
    3228             : 
    3229           9 :             if (Tank.FlowRateSchedule > 0) {
    3230           0 :                 ShowWarningError(state,
    3231           0 :                                  state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3232             :                                      ":  Use side nodes are specified; Use Flow Rate Fraction Schedule will not be used");
    3233             :             }
    3234             : 
    3235           9 :             if (Tank.UseInletTempSchedule > 0) {
    3236           0 :                 ShowWarningError(state,
    3237           0 :                                  state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3238             :                                      ":  Use side nodes are specified; Cold Water Supply Temperature Schedule will not be used");
    3239             :             }
    3240             :         }
    3241             : 
    3242          16 :         if ((!state.dataIPShortCut->cAlphaArgs(18).empty()) || (!state.dataIPShortCut->cAlphaArgs(19).empty())) {
    3243          10 :             Tank.SourceInletNode = NodeInputManager::GetOnlySingleNode(state,
    3244          10 :                                                                        state.dataIPShortCut->cAlphaArgs(18),
    3245             :                                                                        ErrorsFound,
    3246             :                                                                        DataLoopNode::ConnectionObjectType::WaterHeaterStratified,
    3247          10 :                                                                        state.dataIPShortCut->cAlphaArgs(1),
    3248             :                                                                        DataLoopNode::NodeFluidType::Water,
    3249             :                                                                        DataLoopNode::ConnectionType::Inlet,
    3250             :                                                                        NodeInputManager::CompFluidStream::Secondary,
    3251          10 :                                                                        DataLoopNode::ObjectIsNotParent);
    3252          10 :             Tank.InletNodeName2 = state.dataIPShortCut->cAlphaArgs(18);
    3253          10 :             Tank.SourceOutletNode = NodeInputManager::GetOnlySingleNode(state,
    3254          10 :                                                                         state.dataIPShortCut->cAlphaArgs(19),
    3255             :                                                                         ErrorsFound,
    3256             :                                                                         DataLoopNode::ConnectionObjectType::WaterHeaterStratified,
    3257          10 :                                                                         state.dataIPShortCut->cAlphaArgs(1),
    3258             :                                                                         DataLoopNode::NodeFluidType::Water,
    3259             :                                                                         DataLoopNode::ConnectionType::Outlet,
    3260             :                                                                         NodeInputManager::CompFluidStream::Secondary,
    3261          10 :                                                                         DataLoopNode::ObjectIsNotParent);
    3262          10 :             Tank.OutletNodeName2 = state.dataIPShortCut->cAlphaArgs(19);
    3263             :         }
    3264             : 
    3265             :         // Validate inlet mode
    3266          16 :         Tank.InletMode = static_cast<InletPositionMode>(
    3267          32 :             getEnumerationValue(InletPositionModeNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(20))));
    3268             : 
    3269          16 :         Tank.Nodes = state.dataIPShortCut->rNumericArgs(32);
    3270          16 :         int specifiedNodes = 0;
    3271          16 :         Tank.AdditionalCond = state.dataIPShortCut->rNumericArgs(33);
    3272             : 
    3273          16 :         Tank.AdditionalLossCoeff.allocate(Tank.Nodes);
    3274          16 :         Tank.AdditionalLossCoeff = 0.0;
    3275          44 :         for (int NodeNum = 1; NodeNum <= 12; ++NodeNum) {
    3276          44 :             int index = 33 + NodeNum;
    3277          44 :             if (NumNums >= index) {
    3278          28 :                 if (NodeNum <= Tank.Nodes) {
    3279          28 :                     ++specifiedNodes;
    3280          28 :                     Tank.AdditionalLossCoeff(NodeNum) = state.dataIPShortCut->rNumericArgs(index);
    3281           0 :                 } else if (!state.dataIPShortCut->lNumericFieldBlanks(index) && (state.dataIPShortCut->rNumericArgs(index) != 0)) {
    3282             :                     // If either blank, or zero (default), then do not warn
    3283           0 :                     ++specifiedNodes;
    3284             :                 }
    3285             :             } else {
    3286          16 :                 break;
    3287             :             }
    3288             :         }
    3289             : 
    3290          16 :         if (specifiedNodes > Tank.Nodes) {
    3291           0 :             ShowWarningError(state,
    3292           0 :                              state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3293             :                                  ":  More Additional Loss Coefficients were entered than the number of nodes; extra coefficients will not be used");
    3294             :         }
    3295             : 
    3296          16 :         Tank.SetupStratifiedNodes(state);
    3297             : 
    3298          16 :         if (!state.dataIPShortCut->lAlphaFieldBlanks(21)) {
    3299           0 :             Tank.SourceSideControlMode = static_cast<SourceSideControl>(
    3300           0 :                 getEnumerationValue(SourceSideControlNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(21))));
    3301           0 :             if (Tank.SourceSideControlMode == SourceSideControl::Invalid) {
    3302           0 :                 ShowSevereError(state,
    3303           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3304           0 :                                     ":  Invalid Control Mode entered=" + state.dataIPShortCut->cAlphaArgs(21));
    3305           0 :                 ErrorsFound = true;
    3306             :             }
    3307             :         } else {
    3308          16 :             Tank.SourceSideControlMode = SourceSideControl::IndirectHeatPrimarySetpoint;
    3309             :         }
    3310             : 
    3311          16 :         if (!state.dataIPShortCut->lAlphaFieldBlanks(22)) {
    3312           0 :             Tank.SourceSideAltSetpointSchedNum = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(22));
    3313           0 :             if (Tank.SourceSideAltSetpointSchedNum == 0) {
    3314           0 :                 ShowSevereError(state,
    3315           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) + ":  " +
    3316           0 :                                     state.dataIPShortCut->cAlphaFieldNames(22) + " not found = " + state.dataIPShortCut->cAlphaArgs(22));
    3317           0 :                 ErrorsFound = true;
    3318             :             }
    3319             :         }
    3320             :     }
    3321             : 
    3322          10 :     return ErrorsFound;
    3323             : }
    3324             : 
    3325           3 : bool getWaterTankMixedInput(EnergyPlusData &state)
    3326             : {
    3327           3 :     bool ErrorsFound = false;
    3328             : 
    3329           3 :     state.dataIPShortCut->cCurrentModuleObject = cMixedCWTankModuleObj; // 'ThermalStorage:ChilledWater:Mixed'
    3330           6 :     for (int WaterThermalTankNum = state.dataWaterThermalTanks->numWaterHeaterMixed + state.dataWaterThermalTanks->numWaterHeaterStratified + 1;
    3331          12 :          WaterThermalTankNum <= state.dataWaterThermalTanks->numWaterHeaterMixed + state.dataWaterThermalTanks->numWaterHeaterStratified +
    3332           6 :                                     state.dataWaterThermalTanks->numChilledWaterMixed;
    3333             :          ++WaterThermalTankNum) {
    3334             :         int NumAlphas;
    3335             :         int NumNums;
    3336             :         int IOStat;
    3337          27 :         state.dataInputProcessing->inputProcessor->getObjectItem(
    3338             :             state,
    3339           3 :             state.dataIPShortCut->cCurrentModuleObject,
    3340           3 :             WaterThermalTankNum - (state.dataWaterThermalTanks->numWaterHeaterMixed + state.dataWaterThermalTanks->numWaterHeaterStratified),
    3341           3 :             state.dataIPShortCut->cAlphaArgs,
    3342             :             NumAlphas,
    3343           3 :             state.dataIPShortCut->rNumericArgs,
    3344             :             NumNums,
    3345             :             IOStat,
    3346           3 :             state.dataIPShortCut->lNumericFieldBlanks,
    3347           3 :             state.dataIPShortCut->lAlphaFieldBlanks,
    3348           3 :             state.dataIPShortCut->cAlphaFieldNames,
    3349           3 :             state.dataIPShortCut->cNumericFieldNames);
    3350           9 :         GlobalNames::VerifyUniqueInterObjectName(state,
    3351           3 :                                                  state.dataWaterThermalTanks->UniqueWaterThermalTankNames,
    3352           3 :                                                  state.dataIPShortCut->cAlphaArgs(1),
    3353           3 :                                                  state.dataIPShortCut->cCurrentModuleObject,
    3354           3 :                                                  state.dataIPShortCut->cAlphaFieldNames(1),
    3355             :                                                  ErrorsFound);
    3356             : 
    3357           3 :         auto &Tank = state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum);
    3358             : 
    3359           3 :         Tank.Name = state.dataIPShortCut->cAlphaArgs(1);
    3360           3 :         Tank.Type = state.dataIPShortCut->cCurrentModuleObject;
    3361           3 :         Tank.WaterThermalTankType = DataPlant::PlantEquipmentType::ChilledWaterTankMixed;
    3362           3 :         Tank.FluidIndex = Tank.waterIndex;
    3363           3 :         Tank.IsChilledWaterTank = true;
    3364           3 :         Tank.EndUseSubcategoryName = "Chilled Water Storage";
    3365             : 
    3366           3 :         Tank.Volume = state.dataIPShortCut->rNumericArgs(1);
    3367           3 :         if (Tank.Volume == DataSizing::AutoSize) {
    3368           0 :             Tank.VolumeWasAutoSized = true;
    3369             :         }
    3370             : 
    3371           3 :         if (state.dataIPShortCut->rNumericArgs(1) == 0.0) {
    3372             :             // Set volume to a really small number to continue simulation
    3373           0 :             Tank.Volume = 0.000001; // = 1 cm3
    3374             :         }
    3375             : 
    3376           3 :         Tank.SetPointTempSchedule = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
    3377           3 :         if (Tank.SetPointTempSchedule == 0) {
    3378           0 :             ShowSevereError(state, "Invalid, " + state.dataIPShortCut->cAlphaFieldNames(2) + " = " + state.dataIPShortCut->cAlphaArgs(2));
    3379           0 :             ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + state.dataIPShortCut->cAlphaArgs(1));
    3380             : 
    3381           0 :             ErrorsFound = true;
    3382             :         }
    3383             : 
    3384           3 :         if (state.dataIPShortCut->rNumericArgs(2) > 0.0001) {
    3385           3 :             Tank.DeadBandDeltaTemp = state.dataIPShortCut->rNumericArgs(2);
    3386             :         } else {
    3387             :             // Default to very small number (however it can't be TINY or it will break the algorithm)
    3388           0 :             Tank.DeadBandDeltaTemp = 0.5;
    3389             :         }
    3390             : 
    3391           3 :         if (state.dataIPShortCut->rNumericArgs(3) > 0.0) {
    3392           3 :             Tank.TankTempLimit = state.dataIPShortCut->rNumericArgs(3);
    3393             :         } else {
    3394             :             // default to just above freezing
    3395           0 :             Tank.TankTempLimit = 1.0;
    3396             :         }
    3397             : 
    3398           3 :         Tank.MaxCapacity = state.dataIPShortCut->rNumericArgs(4);
    3399           3 :         if (Tank.MaxCapacity == DataSizing::AutoSize) {
    3400           0 :             Tank.MaxCapacityWasAutoSized = true;
    3401             :         }
    3402             : 
    3403           3 :         Tank.MinCapacity = 0.0;
    3404           3 :         Tank.ControlType = HeaterControlMode::Cycle;
    3405             : 
    3406           3 :         Tank.MassFlowRateMin = 0.0;
    3407           3 :         Tank.IgnitionDelay = 0.0;
    3408           3 :         Tank.FuelType = Fuel::Electricity;
    3409           3 :         Tank.Efficiency = 1.0;
    3410           3 :         Tank.PLFCurve = 0;
    3411           3 :         Tank.OffCycParaLoad = 0.0;
    3412           3 :         Tank.OffCycParaFuelType = Fuel::Electricity;
    3413           3 :         Tank.OffCycParaFracToTank = 0.0;
    3414           3 :         Tank.OnCycParaLoad = 0.0;
    3415           3 :         Tank.OnCycParaFuelType = Fuel::Electricity;
    3416           3 :         Tank.OnCycParaFracToTank = 0.0;
    3417             : 
    3418           3 :         Tank.AmbientTempIndicator = static_cast<WTTAmbientTemp>(
    3419           6 :             getEnumerationValue(TankAmbientTempNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(3))));
    3420           3 :         switch (Tank.AmbientTempIndicator) {
    3421             : 
    3422           0 :         case WTTAmbientTemp::Schedule: {
    3423           0 :             Tank.AmbientTempSchedule = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(4));
    3424           0 :             if (Tank.AmbientTempSchedule == 0) {
    3425           0 :                 ShowSevereError(state, "Invalid, " + state.dataIPShortCut->cAlphaFieldNames(4) + " = " + state.dataIPShortCut->cAlphaArgs(4));
    3426           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    3427           0 :                 ShowContinueError(state, "Schedule was not found.");
    3428           0 :                 ErrorsFound = true;
    3429             :             }
    3430             : 
    3431           0 :             break;
    3432             :         }
    3433           3 :         case WTTAmbientTemp::TempZone: {
    3434           3 :             Tank.AmbientTempZone = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(5), state.dataHeatBal->Zone);
    3435           3 :             if (Tank.AmbientTempZone == 0) {
    3436           0 :                 ShowSevereError(state, "Invalid, " + state.dataIPShortCut->cAlphaFieldNames(5) + " = " + state.dataIPShortCut->cAlphaArgs(5));
    3437           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    3438           0 :                 ShowContinueError(state, "Zone was not found.");
    3439           0 :                 ErrorsFound = true;
    3440             :             }
    3441             : 
    3442           3 :             break;
    3443             :         }
    3444           0 :         case WTTAmbientTemp::OutsideAir: {
    3445           0 :             Tank.AmbientTempOutsideAirNode = NodeInputManager::GetOnlySingleNode(state,
    3446           0 :                                                                                  state.dataIPShortCut->cAlphaArgs(6),
    3447             :                                                                                  ErrorsFound,
    3448             :                                                                                  DataLoopNode::ConnectionObjectType::ThermalStorageChilledWaterMixed,
    3449           0 :                                                                                  state.dataIPShortCut->cAlphaArgs(1),
    3450             :                                                                                  DataLoopNode::NodeFluidType::Air,
    3451             :                                                                                  DataLoopNode::ConnectionType::OutsideAirReference,
    3452             :                                                                                  NodeInputManager::CompFluidStream::Primary,
    3453           0 :                                                                                  DataLoopNode::ObjectIsNotParent);
    3454           0 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) {
    3455           0 :                 if (!OutAirNodeManager::CheckOutAirNodeNumber(state, Tank.AmbientTempOutsideAirNode)) {
    3456           0 :                     ShowSevereError(state, "Invalid, " + state.dataIPShortCut->cAlphaFieldNames(6) + " = " + state.dataIPShortCut->cAlphaArgs(6));
    3457           0 :                     ShowContinueError(state,
    3458           0 :                                       "Entered in " + state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    3459           0 :                     ShowContinueError(state, "Outdoor Air Node not on OutdoorAir:NodeList or OutdoorAir:Node");
    3460           0 :                     ErrorsFound = true;
    3461             :                 }
    3462             :             } else {
    3463           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    3464           0 :                 ShowContinueError(state, "An Ambient Outdoor Air Node name must be used when the Ambient Temperature Indicator is Outdoors.");
    3465           0 :                 ErrorsFound = true;
    3466             :             }
    3467             : 
    3468           0 :             break;
    3469             :         }
    3470           0 :         default: {
    3471           0 :             ShowSevereError(state,
    3472           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3473           0 :                                 ":  Invalid Ambient Temperature Indicator entered=" + state.dataIPShortCut->cAlphaArgs(3));
    3474           0 :             ShowContinueError(state, " Valid entries are Schedule, Zone, and Outdoors.");
    3475           0 :             ErrorsFound = true;
    3476           0 :             break;
    3477             :         }
    3478             :         }
    3479             : 
    3480           3 :         Tank.OffCycLossCoeff = state.dataIPShortCut->rNumericArgs(5);
    3481           3 :         Tank.OffCycLossFracToZone = 1.0;
    3482             : 
    3483           3 :         Tank.OnCycLossCoeff = state.dataIPShortCut->rNumericArgs(5);
    3484           3 :         Tank.OnCycLossFracToZone = 1.0;
    3485             : 
    3486           3 :         Tank.MassFlowRateMax = 0.0;
    3487           3 :         Tank.FlowRateSchedule = 0;
    3488           3 :         Tank.UseInletTempSchedule = 0;
    3489             : 
    3490             :         // default to always on
    3491           3 :         Tank.SourceSideAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
    3492           3 :         Tank.UseSideAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
    3493             : 
    3494           3 :         if ((state.dataIPShortCut->rNumericArgs(6) > 1) || (state.dataIPShortCut->rNumericArgs(6) < 0)) {
    3495           0 :             ShowSevereError(state,
    3496           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3497             :                                 ":  Use Side Effectiveness is out of bounds (0 to 1)");
    3498           0 :             ErrorsFound = true;
    3499             :         }
    3500           3 :         Tank.UseEffectiveness = state.dataIPShortCut->rNumericArgs(6);
    3501             : 
    3502           3 :         if ((state.dataIPShortCut->rNumericArgs(8) > 1) || (state.dataIPShortCut->rNumericArgs(8) <= 0)) {
    3503           0 :             ShowSevereError(state,
    3504           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3505             :                                 ":  Source Side Effectiveness is out of bounds (>0 to 1)");
    3506           0 :             ErrorsFound = true;
    3507             :         }
    3508           3 :         Tank.SourceEffectiveness = state.dataIPShortCut->rNumericArgs(8);
    3509             : 
    3510           3 :         if (state.dataIPShortCut->lNumericFieldBlanks(7)) {
    3511           0 :             Tank.UseDesignVolFlowRate = 0.0;
    3512             :         } else {
    3513           3 :             Tank.UseDesignVolFlowRate = state.dataIPShortCut->rNumericArgs(7);
    3514           3 :             if (Tank.UseDesignVolFlowRate) {
    3515           3 :                 Tank.UseDesignVolFlowRateWasAutoSized = true;
    3516             :             }
    3517             :         }
    3518             : 
    3519           3 :         Tank.UseSidePlantLoc.loopSideNum = DataPlant::LoopSideLocation::Invalid;
    3520             : 
    3521           3 :         if (state.dataIPShortCut->lAlphaFieldBlanks(9)) {
    3522           0 :             Tank.UseSideAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
    3523             :         } else {
    3524           3 :             Tank.UseSideAvailSchedNum = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(9));
    3525           3 :             if (Tank.UseSideAvailSchedNum == 0) {
    3526           0 :                 ShowSevereError(state, "Invalid, " + state.dataIPShortCut->cAlphaFieldNames(9) + " = " + state.dataIPShortCut->cAlphaArgs(9));
    3527           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    3528           0 :                 ShowContinueError(state, "Schedule was not found.");
    3529           0 :                 ErrorsFound = true;
    3530             :             }
    3531             :         }
    3532             : 
    3533           3 :         Tank.SrcSidePlantLoc.loopSideNum = DataPlant::LoopSideLocation::Invalid;
    3534             : 
    3535           3 :         if (state.dataIPShortCut->lNumericFieldBlanks(9)) {
    3536           0 :             Tank.SourceDesignVolFlowRate = 0.0;
    3537             :         } else {
    3538           3 :             Tank.SourceDesignVolFlowRate = state.dataIPShortCut->rNumericArgs(9);
    3539           3 :             if (Tank.SourceDesignVolFlowRate == DataSizing::AutoSize) {
    3540           3 :                 Tank.SourceDesignVolFlowRateWasAutoSized = true;
    3541             :             }
    3542             :         }
    3543             : 
    3544           3 :         if (state.dataIPShortCut->lAlphaFieldBlanks(12)) {
    3545           0 :             Tank.SourceSideAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
    3546             :         } else {
    3547           3 :             Tank.SourceSideAvailSchedNum = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(12));
    3548           3 :             if (Tank.SourceSideAvailSchedNum == 0) {
    3549           0 :                 ShowSevereError(state, "Invalid, " + state.dataIPShortCut->cAlphaFieldNames(12) + " = " + state.dataIPShortCut->cAlphaArgs(12));
    3550           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    3551           0 :                 ShowContinueError(state, "Schedule was not found.");
    3552           0 :                 ErrorsFound = true;
    3553             :             }
    3554             :         }
    3555           3 :         if (state.dataIPShortCut->lNumericFieldBlanks(10)) {
    3556           0 :             Tank.SizingRecoveryTime = 4.0;
    3557             :         } else {
    3558           3 :             Tank.SizingRecoveryTime = state.dataIPShortCut->rNumericArgs(10);
    3559             :         }
    3560             : 
    3561           3 :         if ((!state.dataIPShortCut->lAlphaFieldBlanks(7)) || (!state.dataIPShortCut->lAlphaFieldBlanks(8))) {
    3562           3 :             Tank.UseInletNode = NodeInputManager::GetOnlySingleNode(state,
    3563           3 :                                                                     state.dataIPShortCut->cAlphaArgs(7),
    3564             :                                                                     ErrorsFound,
    3565             :                                                                     DataLoopNode::ConnectionObjectType::ThermalStorageChilledWaterMixed,
    3566           3 :                                                                     state.dataIPShortCut->cAlphaArgs(1),
    3567             :                                                                     DataLoopNode::NodeFluidType::Water,
    3568             :                                                                     DataLoopNode::ConnectionType::Inlet,
    3569             :                                                                     NodeInputManager::CompFluidStream::Primary,
    3570           3 :                                                                     DataLoopNode::ObjectIsNotParent);
    3571           3 :             Tank.InletNodeName1 = state.dataIPShortCut->cAlphaArgs(7);
    3572           3 :             Tank.UseOutletNode = NodeInputManager::GetOnlySingleNode(state,
    3573           3 :                                                                      state.dataIPShortCut->cAlphaArgs(8),
    3574             :                                                                      ErrorsFound,
    3575             :                                                                      DataLoopNode::ConnectionObjectType::ThermalStorageChilledWaterMixed,
    3576           3 :                                                                      state.dataIPShortCut->cAlphaArgs(1),
    3577             :                                                                      DataLoopNode::NodeFluidType::Water,
    3578             :                                                                      DataLoopNode::ConnectionType::Outlet,
    3579             :                                                                      NodeInputManager::CompFluidStream::Primary,
    3580           3 :                                                                      DataLoopNode::ObjectIsNotParent);
    3581           3 :             Tank.OutletNodeName1 = state.dataIPShortCut->cAlphaArgs(8);
    3582             :         }
    3583             : 
    3584           3 :         if ((!state.dataIPShortCut->lAlphaFieldBlanks(10)) || (!state.dataIPShortCut->lAlphaFieldBlanks(11))) {
    3585           3 :             Tank.SourceInletNode = NodeInputManager::GetOnlySingleNode(state,
    3586           3 :                                                                        state.dataIPShortCut->cAlphaArgs(10),
    3587             :                                                                        ErrorsFound,
    3588             :                                                                        DataLoopNode::ConnectionObjectType::ThermalStorageChilledWaterMixed,
    3589           3 :                                                                        state.dataIPShortCut->cAlphaArgs(1),
    3590             :                                                                        DataLoopNode::NodeFluidType::Water,
    3591             :                                                                        DataLoopNode::ConnectionType::Inlet,
    3592             :                                                                        NodeInputManager::CompFluidStream::Secondary,
    3593           3 :                                                                        DataLoopNode::ObjectIsNotParent);
    3594           3 :             Tank.InletNodeName2 = state.dataIPShortCut->cAlphaArgs(10);
    3595           3 :             Tank.SourceOutletNode = NodeInputManager::GetOnlySingleNode(state,
    3596           3 :                                                                         state.dataIPShortCut->cAlphaArgs(11),
    3597             :                                                                         ErrorsFound,
    3598             :                                                                         DataLoopNode::ConnectionObjectType::ThermalStorageChilledWaterMixed,
    3599           3 :                                                                         state.dataIPShortCut->cAlphaArgs(1),
    3600             :                                                                         DataLoopNode::NodeFluidType::Water,
    3601             :                                                                         DataLoopNode::ConnectionType::Outlet,
    3602             :                                                                         NodeInputManager::CompFluidStream::Secondary,
    3603           3 :                                                                         DataLoopNode::ObjectIsNotParent);
    3604           3 :             Tank.OutletNodeName2 = state.dataIPShortCut->cAlphaArgs(11);
    3605             :         }
    3606             : 
    3607           3 :         if (Tank.UseSidePlantLoc.loopSideNum == DataPlant::LoopSideLocation::Demand && Tank.SourceInletNode != 0) {
    3608           0 :             PlantUtilities::RegisterPlantCompDesignFlow(state, Tank.SourceInletNode, Tank.SourceDesignVolFlowRate);
    3609             :         }
    3610             : 
    3611             :     } // WaterThermalTankNum
    3612             : 
    3613           3 :     return ErrorsFound;
    3614             : }
    3615             : 
    3616           2 : bool getWaterTankStratifiedInput(EnergyPlusData &state)
    3617             : {
    3618           2 :     bool ErrorsFound = false;
    3619             :     static constexpr std::string_view RoutineName = "getWaterTankStratifiedInput";
    3620             : 
    3621           2 :     state.dataIPShortCut->cCurrentModuleObject = cStratifiedCWTankModuleObj; // 'ThermalStorage:ChilledWater:Stratified'
    3622             : 
    3623           6 :     for (int WaterThermalTankNum = state.dataWaterThermalTanks->numWaterHeaterMixed + state.dataWaterThermalTanks->numWaterHeaterStratified +
    3624           4 :                                    state.dataWaterThermalTanks->numChilledWaterMixed + 1;
    3625          12 :          WaterThermalTankNum <= state.dataWaterThermalTanks->numWaterHeaterMixed + state.dataWaterThermalTanks->numWaterHeaterStratified +
    3626           8 :                                     state.dataWaterThermalTanks->numChilledWaterMixed + state.dataWaterThermalTanks->numChilledWaterStratified;
    3627             :          ++WaterThermalTankNum) {
    3628             :         int NumNums;
    3629             :         int NumAlphas;
    3630             :         int IOStat;
    3631          18 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3632           2 :                                                                  state.dataIPShortCut->cCurrentModuleObject,
    3633           4 :                                                                  WaterThermalTankNum - (state.dataWaterThermalTanks->numWaterHeaterMixed +
    3634           4 :                                                                                         state.dataWaterThermalTanks->numWaterHeaterStratified +
    3635           2 :                                                                                         state.dataWaterThermalTanks->numChilledWaterMixed),
    3636           2 :                                                                  state.dataIPShortCut->cAlphaArgs,
    3637             :                                                                  NumAlphas,
    3638           2 :                                                                  state.dataIPShortCut->rNumericArgs,
    3639             :                                                                  NumNums,
    3640             :                                                                  IOStat,
    3641           2 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
    3642           2 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
    3643           2 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
    3644           2 :                                                                  state.dataIPShortCut->cNumericFieldNames);
    3645           6 :         GlobalNames::VerifyUniqueInterObjectName(state,
    3646           2 :                                                  state.dataWaterThermalTanks->UniqueWaterThermalTankNames,
    3647           2 :                                                  state.dataIPShortCut->cAlphaArgs(1),
    3648           2 :                                                  state.dataIPShortCut->cCurrentModuleObject,
    3649           2 :                                                  state.dataIPShortCut->cAlphaFieldNames(1),
    3650             :                                                  ErrorsFound);
    3651             : 
    3652           2 :         auto &Tank = state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum);
    3653             : 
    3654           2 :         Tank.Name = state.dataIPShortCut->cAlphaArgs(1);
    3655           2 :         Tank.Type = state.dataIPShortCut->cCurrentModuleObject;
    3656           2 :         Tank.WaterThermalTankType = DataPlant::PlantEquipmentType::ChilledWaterTankStratified;
    3657           2 :         Tank.FluidIndex = Tank.waterIndex;
    3658           2 :         Tank.IsChilledWaterTank = true;
    3659           2 :         Tank.EndUseSubcategoryName = "Chilled Water Storage";
    3660             : 
    3661           2 :         Tank.Volume = state.dataIPShortCut->rNumericArgs(1);
    3662           2 :         if (Tank.Volume == DataSizing::AutoSize) {
    3663           0 :             Tank.VolumeWasAutoSized = true;
    3664             :         }
    3665           2 :         Real64 rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, DataGlobalConstants::InitConvTemp, Tank.FluidIndex, RoutineName);
    3666           2 :         Tank.Mass = Tank.Volume * rho;
    3667           2 :         Tank.Height = state.dataIPShortCut->rNumericArgs(2);
    3668           2 :         if (Tank.Height == DataSizing::AutoSize) {
    3669           0 :             Tank.HeightWasAutoSized = true;
    3670             :         }
    3671             : 
    3672           2 :         Tank.Shape =
    3673           4 :             static_cast<TankShape>(getEnumerationValue(TankShapeNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(2))));
    3674           2 :         switch (Tank.Shape) {
    3675           2 :         case TankShape::HorizCylinder:
    3676             :         case TankShape::VertCylinder: {
    3677           2 :             break;
    3678             :         }
    3679           0 :         case TankShape::Other: {
    3680           0 :             if (state.dataIPShortCut->rNumericArgs(3) > 0.0) {
    3681           0 :                 Tank.Perimeter = state.dataIPShortCut->rNumericArgs(3);
    3682             :             } else {
    3683           0 :                 ShowSevereError(state,
    3684           0 :                                 state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3685             :                                     ":  Tank Perimeter must be greater than zero for Tank Shape=OTHER");
    3686           0 :                 ErrorsFound = true;
    3687             :             }
    3688           0 :             break;
    3689             :         }
    3690           0 :         default: {
    3691           0 :             ShowSevereError(state,
    3692           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3693           0 :                                 ":  Invalid Tank Shape entered=" + state.dataIPShortCut->cAlphaArgs(2));
    3694           0 :             Tank.Shape = TankShape::VertCylinder;
    3695           0 :             ErrorsFound = true;
    3696           0 :             break;
    3697             :         }
    3698             :         }
    3699             : 
    3700           2 :         if (state.dataIPShortCut->rNumericArgs(6) > 0.0) {
    3701           2 :             Tank.TankTempLimit = state.dataIPShortCut->rNumericArgs(6);
    3702             :         } else {
    3703             :             // default to just above freezing
    3704           0 :             Tank.TankTempLimit = 1.0;
    3705             :         }
    3706             : 
    3707           2 :         Tank.SetPointTempSchedule = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
    3708           2 :         if (Tank.SetPointTempSchedule == 0) {
    3709           0 :             ShowSevereError(state, "Invalid, " + state.dataIPShortCut->cAlphaFieldNames(3) + " = " + state.dataIPShortCut->cAlphaArgs(3));
    3710           0 :             ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    3711           0 :             ShowContinueError(state, "Schedule was not found.");
    3712           0 :             ErrorsFound = true;
    3713             :         }
    3714             : 
    3715           2 :         if (state.dataIPShortCut->rNumericArgs(4) > 0.0) {
    3716           2 :             Tank.DeadBandDeltaTemp = state.dataIPShortCut->rNumericArgs(4);
    3717             :         } else {
    3718             :             // Default to very small number (however it can't be TINY or it will break the algorithm)
    3719           0 :             Tank.DeadBandDeltaTemp = 0.0001;
    3720             :         }
    3721             : 
    3722           2 :         Tank.HeaterHeight1 = state.dataIPShortCut->rNumericArgs(5);
    3723           2 :         Tank.MaxCapacity = state.dataIPShortCut->rNumericArgs(7);
    3724           2 :         if (Tank.MaxCapacity == DataSizing::AutoSize) {
    3725           0 :             Tank.MaxCapacityWasAutoSized = true;
    3726             :         }
    3727             : 
    3728           2 :         Tank.Efficiency = 1.0;
    3729           2 :         Tank.SetPointTempSchedule2 = 0;
    3730           2 :         Tank.MaxCapacity2 = 0.0;
    3731           2 :         Tank.HeaterHeight2 = 0.0;
    3732           2 :         Tank.FuelType = Fuel::Electricity;
    3733             : 
    3734           2 :         Tank.OffCycParaLoad = 0.0;
    3735           2 :         Tank.OffCycParaFuelType = Fuel::Electricity;
    3736           2 :         Tank.OffCycParaFracToTank = 0.0;
    3737           2 :         Tank.OffCycParaHeight = 0.0;
    3738           2 :         Tank.OnCycParaLoad = 0.0;
    3739           2 :         Tank.OnCycParaFuelType = Fuel::Electricity;
    3740           2 :         Tank.OnCycParaFracToTank = 0.0;
    3741           2 :         Tank.OnCycParaHeight = 0.0;
    3742             : 
    3743           2 :         Tank.AmbientTempIndicator = static_cast<WTTAmbientTemp>(
    3744           4 :             getEnumerationValue(TankAmbientTempNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(4))));
    3745           2 :         switch (Tank.AmbientTempIndicator) {
    3746             : 
    3747           0 :         case WTTAmbientTemp::Schedule: {
    3748           0 :             Tank.AmbientTempSchedule = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(5));
    3749           0 :             if (Tank.AmbientTempSchedule == 0) {
    3750           0 :                 ShowSevereError(state, "Invalid, " + state.dataIPShortCut->cAlphaFieldNames(5) + " = " + state.dataIPShortCut->cAlphaArgs(5));
    3751           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    3752           0 :                 ShowContinueError(state, "Schedule was not found.");
    3753           0 :                 ErrorsFound = true;
    3754             :             }
    3755             : 
    3756           0 :             break;
    3757             :         }
    3758           2 :         case WTTAmbientTemp::TempZone: {
    3759           2 :             Tank.AmbientTempZone = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(6), state.dataHeatBal->Zone);
    3760           2 :             if (Tank.AmbientTempZone == 0) {
    3761           0 :                 ShowSevereError(state, "Invalid, " + state.dataIPShortCut->cAlphaFieldNames(6) + " = " + state.dataIPShortCut->cAlphaArgs(6));
    3762           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    3763           0 :                 ShowContinueError(state, "Zone was not found.");
    3764           0 :                 ErrorsFound = true;
    3765             :             }
    3766           2 :             Tank.OffCycLossFracToZone = 1.0;
    3767             : 
    3768           2 :             break;
    3769             :         }
    3770           0 :         case WTTAmbientTemp::OutsideAir: {
    3771           0 :             Tank.AmbientTempOutsideAirNode =
    3772           0 :                 NodeInputManager::GetOnlySingleNode(state,
    3773           0 :                                                     state.dataIPShortCut->cAlphaArgs(7),
    3774             :                                                     ErrorsFound,
    3775             :                                                     DataLoopNode::ConnectionObjectType::ThermalStorageChilledWaterStratified,
    3776           0 :                                                     state.dataIPShortCut->cAlphaArgs(1),
    3777             :                                                     DataLoopNode::NodeFluidType::Air,
    3778             :                                                     DataLoopNode::ConnectionType::Inlet,
    3779             :                                                     NodeInputManager::CompFluidStream::Primary,
    3780           0 :                                                     DataLoopNode::ObjectIsNotParent);
    3781           0 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) {
    3782           0 :                 if (!OutAirNodeManager::CheckOutAirNodeNumber(state, Tank.AmbientTempOutsideAirNode)) {
    3783           0 :                     ShowSevereError(state, "Invalid, " + state.dataIPShortCut->cAlphaFieldNames(7) + " = " + state.dataIPShortCut->cAlphaArgs(7));
    3784           0 :                     ShowContinueError(state,
    3785           0 :                                       "Entered in " + state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    3786           0 :                     ShowContinueError(state, "Outdoor Air Node not on OutdoorAir:NodeList or OutdoorAir:Node");
    3787           0 :                     ErrorsFound = true;
    3788             :                 }
    3789             :             } else {
    3790           0 :                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    3791           0 :                 ShowContinueError(state, "An Ambient Outdoor Air Node name must be used when the Ambient Temperature Indicator is Outdoors.");
    3792           0 :                 ErrorsFound = true;
    3793             :             }
    3794             : 
    3795           0 :             break;
    3796             :         }
    3797           0 :         default: {
    3798           0 :             ShowSevereError(state,
    3799           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3800           0 :                                 ":  Invalid Ambient Temperature Indicator entered=" + state.dataIPShortCut->cAlphaArgs(4));
    3801           0 :             ShowContinueError(state, "  Valid entries are Schedule, Zone, and Outdoors.");
    3802           0 :             ErrorsFound = true;
    3803           0 :             break;
    3804             :         }
    3805             :         }
    3806             : 
    3807           2 :         Tank.SkinLossCoeff = state.dataIPShortCut->rNumericArgs(8);
    3808           2 :         Tank.SkinLossFracToZone = 1.0;
    3809           2 :         Tank.OffCycFlueLossCoeff = 0.0;
    3810           2 :         Tank.OffCycFlueLossFracToZone = 0.0;
    3811             : 
    3812           2 :         Tank.MassFlowRateMax = 0.0;
    3813           2 :         Tank.FlowRateSchedule = 0;
    3814           2 :         Tank.UseInletTempSchedule = 0;
    3815           2 :         Tank.UseEffectiveness = state.dataIPShortCut->rNumericArgs(9);
    3816           2 :         Tank.UseInletHeight = state.dataIPShortCut->rNumericArgs(10);
    3817             : 
    3818             :         // default to always on
    3819           2 :         Tank.SourceSideAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
    3820           2 :         Tank.UseSideAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
    3821             : 
    3822           2 :         if (state.dataIPShortCut->rNumericArgs(10) == DataGlobalConstants::AutoCalculate) {
    3823           0 :             Tank.UseInletHeight = Tank.Height; // top of tank
    3824             :         }
    3825           2 :         if (Tank.UseInletHeight > Tank.Height) {
    3826           0 :             ShowSevereError(state,
    3827           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3828             :                                 ": Use inlet is located higher than overall tank height.");
    3829           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
    3830           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(10), state.dataIPShortCut->rNumericArgs(10)));
    3831           0 :             ErrorsFound = true;
    3832             :         }
    3833             : 
    3834           2 :         Tank.UseOutletHeight = state.dataIPShortCut->rNumericArgs(11);
    3835           2 :         if (Tank.UseOutletHeight > Tank.Height) {
    3836           0 :             ShowSevereError(state,
    3837           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3838             :                                 ": Use outlet is located higher than overall tank height.");
    3839           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
    3840           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(11), state.dataIPShortCut->rNumericArgs(11)));
    3841           0 :             ErrorsFound = true;
    3842             :         }
    3843             : 
    3844           2 :         if ((state.dataIPShortCut->rNumericArgs(13) > 1) || (state.dataIPShortCut->rNumericArgs(13) <= 0)) {
    3845           0 :             ShowSevereError(state,
    3846           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3847             :                                 ":  Source Side Effectiveness is out of bounds (>0 to 1)");
    3848           0 :             ErrorsFound = true;
    3849             :         }
    3850           2 :         Tank.SourceEffectiveness = state.dataIPShortCut->rNumericArgs(13);
    3851             : 
    3852           2 :         Tank.SourceInletHeight = state.dataIPShortCut->rNumericArgs(14);
    3853           2 :         if (Tank.SourceInletHeight > Tank.Height) {
    3854           0 :             ShowSevereError(state,
    3855           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3856             :                                 ": Source inlet is located higher than overall tank height.");
    3857           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
    3858           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(14), state.dataIPShortCut->rNumericArgs(14)));
    3859           0 :             ErrorsFound = true;
    3860             :         }
    3861             : 
    3862           2 :         Tank.SourceOutletHeight = state.dataIPShortCut->rNumericArgs(15);
    3863           2 :         if (state.dataIPShortCut->rNumericArgs(15) == DataGlobalConstants::AutoCalculate) {
    3864           0 :             Tank.SourceOutletHeight = Tank.Height; // top of tank
    3865             :         }
    3866           2 :         if (Tank.SourceOutletHeight > Tank.Height) {
    3867           0 :             ShowSevereError(state,
    3868           0 :                             state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3869             :                                 ": Source outlet is located higher than overall tank height.");
    3870           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
    3871           0 :             ShowContinueError(state, format("{} = {:.4R}", state.dataIPShortCut->cNumericFieldNames(15), state.dataIPShortCut->rNumericArgs(15)));
    3872           0 :             ErrorsFound = true;
    3873             :         }
    3874             : 
    3875           2 :         Tank.StandAlone = false;
    3876             : 
    3877           2 :         if (state.dataIPShortCut->lNumericFieldBlanks(12)) {
    3878           0 :             Tank.UseDesignVolFlowRate = 0.0;
    3879             :         } else {
    3880           2 :             Tank.UseDesignVolFlowRate = state.dataIPShortCut->rNumericArgs(12);
    3881           2 :             if (Tank.UseDesignVolFlowRate == DataSizing::AutoSize) {
    3882           2 :                 Tank.UseDesignVolFlowRateWasAutoSized = true;
    3883             :             }
    3884             :         }
    3885             : 
    3886           2 :         Tank.UseSidePlantLoc.loopSideNum = DataPlant::LoopSideLocation::Invalid;
    3887             : 
    3888           2 :         if (state.dataIPShortCut->lNumericFieldBlanks(16)) {
    3889           0 :             Tank.SourceDesignVolFlowRate = 0.0;
    3890             :         } else {
    3891           2 :             Tank.SourceDesignVolFlowRate = state.dataIPShortCut->rNumericArgs(16);
    3892           2 :             if (Tank.SourceDesignVolFlowRate == DataSizing::AutoSize) {
    3893           0 :                 Tank.SourceDesignVolFlowRateWasAutoSized = true;
    3894             :             }
    3895             :         }
    3896             : 
    3897           2 :         Tank.SizingRecoveryTime = state.dataIPShortCut->rNumericArgs(17);
    3898             : 
    3899           2 :         Tank.SrcSidePlantLoc.loopSideNum = DataPlant::LoopSideLocation::Invalid;
    3900             : 
    3901           2 :         if ((!state.dataIPShortCut->lAlphaFieldBlanks(8)) || (!state.dataIPShortCut->lAlphaFieldBlanks(9))) {
    3902           2 :             Tank.UseInletNode = NodeInputManager::GetOnlySingleNode(state,
    3903           2 :                                                                     state.dataIPShortCut->cAlphaArgs(8),
    3904             :                                                                     ErrorsFound,
    3905             :                                                                     DataLoopNode::ConnectionObjectType::ThermalStorageChilledWaterStratified,
    3906           2 :                                                                     state.dataIPShortCut->cAlphaArgs(1),
    3907             :                                                                     DataLoopNode::NodeFluidType::Water,
    3908             :                                                                     DataLoopNode::ConnectionType::Inlet,
    3909             :                                                                     NodeInputManager::CompFluidStream::Primary,
    3910           2 :                                                                     DataLoopNode::ObjectIsNotParent);
    3911           2 :             Tank.InletNodeName1 = state.dataIPShortCut->cAlphaArgs(8);
    3912           2 :             Tank.UseOutletNode = NodeInputManager::GetOnlySingleNode(state,
    3913           2 :                                                                      state.dataIPShortCut->cAlphaArgs(9),
    3914             :                                                                      ErrorsFound,
    3915             :                                                                      DataLoopNode::ConnectionObjectType::ThermalStorageChilledWaterStratified,
    3916           2 :                                                                      state.dataIPShortCut->cAlphaArgs(1),
    3917             :                                                                      DataLoopNode::NodeFluidType::Water,
    3918             :                                                                      DataLoopNode::ConnectionType::Outlet,
    3919             :                                                                      NodeInputManager::CompFluidStream::Primary,
    3920           2 :                                                                      DataLoopNode::ObjectIsNotParent);
    3921           2 :             Tank.OutletNodeName1 = state.dataIPShortCut->cAlphaArgs(9);
    3922             :         }
    3923             : 
    3924           2 :         if ((!state.dataIPShortCut->lAlphaFieldBlanks(11)) || (!state.dataIPShortCut->lAlphaFieldBlanks(12))) {
    3925           1 :             Tank.SourceInletNode = NodeInputManager::GetOnlySingleNode(state,
    3926           1 :                                                                        state.dataIPShortCut->cAlphaArgs(11),
    3927             :                                                                        ErrorsFound,
    3928             :                                                                        DataLoopNode::ConnectionObjectType::ThermalStorageChilledWaterStratified,
    3929           1 :                                                                        state.dataIPShortCut->cAlphaArgs(1),
    3930             :                                                                        DataLoopNode::NodeFluidType::Water,
    3931             :                                                                        DataLoopNode::ConnectionType::Inlet,
    3932             :                                                                        NodeInputManager::CompFluidStream::Secondary,
    3933           1 :                                                                        DataLoopNode::ObjectIsNotParent);
    3934           1 :             Tank.InletNodeName2 = state.dataIPShortCut->cAlphaArgs(11);
    3935           1 :             Tank.SourceOutletNode = NodeInputManager::GetOnlySingleNode(state,
    3936           1 :                                                                         state.dataIPShortCut->cAlphaArgs(12),
    3937             :                                                                         ErrorsFound,
    3938             :                                                                         DataLoopNode::ConnectionObjectType::ThermalStorageChilledWaterStratified,
    3939           1 :                                                                         state.dataIPShortCut->cAlphaArgs(1),
    3940             :                                                                         DataLoopNode::NodeFluidType::Water,
    3941             :                                                                         DataLoopNode::ConnectionType::Outlet,
    3942             :                                                                         NodeInputManager::CompFluidStream::Secondary,
    3943           1 :                                                                         DataLoopNode::ObjectIsNotParent);
    3944           1 :             Tank.OutletNodeName2 = state.dataIPShortCut->cAlphaArgs(12);
    3945             :         }
    3946             : 
    3947           2 :         if (state.dataIPShortCut->lAlphaFieldBlanks(10)) {
    3948           0 :             Tank.UseSideAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
    3949             :         } else {
    3950           2 :             Tank.UseSideAvailSchedNum = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(10));
    3951           2 :             if (Tank.UseSideAvailSchedNum == 0) {
    3952           0 :                 ShowSevereError(state, "Invalid, " + state.dataIPShortCut->cAlphaFieldNames(10) + " = " + state.dataIPShortCut->cAlphaArgs(10));
    3953           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    3954           0 :                 ShowContinueError(state, "Schedule was not found.");
    3955           0 :                 ErrorsFound = true;
    3956             :             }
    3957             :         }
    3958             : 
    3959           2 :         if (Tank.UseSidePlantLoc.loopSideNum == DataPlant::LoopSideLocation::Demand && Tank.SourceInletNode != 0) {
    3960           0 :             PlantUtilities::RegisterPlantCompDesignFlow(state, Tank.SourceInletNode, Tank.SourceDesignVolFlowRate);
    3961             :         }
    3962             : 
    3963           2 :         if (state.dataIPShortCut->lAlphaFieldBlanks(13)) {
    3964           0 :             Tank.SourceSideAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
    3965             :         } else {
    3966           2 :             Tank.SourceSideAvailSchedNum = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(13));
    3967           2 :             if (Tank.SourceSideAvailSchedNum == 0) {
    3968           0 :                 ShowSevereError(state, "Invalid, " + state.dataIPShortCut->cAlphaFieldNames(13) + " = " + state.dataIPShortCut->cAlphaArgs(13));
    3969           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1));
    3970           0 :                 ShowContinueError(state, "Schedule was not found.");
    3971           0 :                 ErrorsFound = true;
    3972             :             }
    3973             :         }
    3974             : 
    3975             :         // Validate inlet mode
    3976           2 :         Tank.InletMode = static_cast<InletPositionMode>(
    3977           4 :             getEnumerationValue(InletPositionModeNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(14))));
    3978             : 
    3979           2 :         Tank.Nodes = state.dataIPShortCut->rNumericArgs(18);
    3980           2 :         Tank.AdditionalCond = state.dataIPShortCut->rNumericArgs(19);
    3981             : 
    3982           2 :         Tank.AdditionalLossCoeff.allocate(Tank.Nodes);
    3983           2 :         Tank.AdditionalLossCoeff = 0.0;
    3984           2 :         for (int NodeNum = 1; NodeNum <= Tank.Nodes; ++NodeNum) {
    3985           2 :             if (NumNums > 19 + NodeNum) {
    3986           0 :                 Tank.AdditionalLossCoeff(NodeNum) = state.dataIPShortCut->rNumericArgs(19 + NodeNum);
    3987             :             } else {
    3988           2 :                 break;
    3989             :             }
    3990             :         }
    3991             : 
    3992           2 :         if (NumNums > 19 + Tank.Nodes) {
    3993           0 :             ShowWarningError(state,
    3994           0 :                              state.dataIPShortCut->cCurrentModuleObject + " = " + state.dataIPShortCut->cAlphaArgs(1) +
    3995             :                                  ":  More Additional Loss Coefficients were entered than the number of nodes; extra coefficients will not be used");
    3996             :         }
    3997             : 
    3998           2 :         Tank.SetupStratifiedNodes(state);
    3999             :     }
    4000             : 
    4001           2 :     return ErrorsFound;
    4002             : }
    4003             : 
    4004         426 : bool GetWaterThermalTankInput(EnergyPlusData &state)
    4005             : {
    4006             : 
    4007             :     // SUBROUTINE INFORMATION:
    4008             :     //       AUTHOR         Dan Fisher and Brandon Anderson
    4009             :     //       DATE WRITTEN   May 2000
    4010             :     //       MODIFIED       R. Raustad, June 2005, added HPWH and desuperheater water heating coils
    4011             :     //                      B. Griffith, Oct. 2007 extensions for indirect water heaters
    4012             :     //                      B. Griffith, Feb. 2008 extensions for autosizing water heaters
    4013             :     //                      BG Mar 2009.  Trap for bad heater height input for stratified water heater CR7718
    4014             :     //                      B. Shen 12/2014, add air-source variable-speed heat pump water heating
    4015             : 
    4016             :     // PURPOSE OF THIS SUBROUTINE:
    4017             :     // Gets the water heater, HPWH, and/or desuperheater heating coil input from the input file.
    4018             : 
    4019         426 :     bool ErrorsFound = false;
    4020             : 
    4021             :     // Make sure refrigeration input is gotten before this input
    4022         426 :     RefrigeratedCase::CheckRefrigerationInput(state);
    4023             : 
    4024         426 :     if (state.dataWaterThermalTanks->getWaterThermalTankInputFlag) {
    4025         426 :         state.dataWaterThermalTanks->numWaterHeaterMixed = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cMixedWHModuleObj);
    4026         426 :         state.dataWaterThermalTanks->numWaterHeaterStratified =
    4027         426 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cStratifiedWHModuleObj);
    4028         426 :         state.dataWaterThermalTanks->numChilledWaterMixed =
    4029         426 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cMixedCWTankModuleObj);
    4030         426 :         state.dataWaterThermalTanks->numChilledWaterStratified =
    4031         426 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cStratifiedCWTankModuleObj);
    4032         426 :         state.dataWaterThermalTanks->numWaterThermalTank =
    4033         852 :             state.dataWaterThermalTanks->numWaterHeaterMixed + state.dataWaterThermalTanks->numWaterHeaterStratified +
    4034         852 :             state.dataWaterThermalTanks->numChilledWaterMixed + state.dataWaterThermalTanks->numChilledWaterStratified;
    4035         426 :         state.dataWaterThermalTanks->numHeatPumpWaterHeater =
    4036         852 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cHPWHPumpedCondenser) +
    4037         426 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cHPWHWrappedCondenser);
    4038         426 :         state.dataWaterThermalTanks->numWaterHeaterDesuperheater =
    4039         426 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCoilDesuperheater);
    4040             : 
    4041         426 :         if (state.dataWaterThermalTanks->numWaterThermalTank > 0) {
    4042             :             static constexpr std::string_view Format_720(
    4043             :                 "! <Water Heater Information>,Type,Name,Volume {{m3}},Maximum Capacity {{W}},Standard Rated Recovery Efficiency, "
    4044             :                 "Standard Rated Energy Factor\n");
    4045             :             static constexpr std::string_view Format_721(
    4046             :                 "! <Heat Pump Water Heater Information>,Type,Name,Volume {{m3}},Maximum Capacity {{W}},Standard Rated Recovery "
    4047             :                 "Efficiency,Standard Rated Energy Factor,\"DX Coil Total Cooling Rate {{W, HPWH Only}}\"\n");
    4048             :             static constexpr std::string_view Format_722(
    4049             :                 "! <Water Heater Stratified Node Information>,Node Number,Height {{m}},Volume {{m3}},Maximum Capacity "
    4050             :                 "{{W}},Off-Cycle UA {{W/K}},On-Cycle UA {{W/K}},Number Of Inlets,Number Of Outlets\n");
    4051             :             static constexpr std::string_view Format_725(
    4052             :                 "! <Chilled Water Tank Information>,Type,Name,Volume {{m3}},Use Side Design Flow Rate {{m3/s}}, "
    4053             :                 "Source Side Design Flow Rate {{m3/s}}\n");
    4054             :             static constexpr std::string_view Format_726(
    4055             :                 "! <Chilled Water Tank Stratified Node Information>,Node Number,Height {{m}},Volume {{m3}},UA {{W/K}},Number Of "
    4056             :                 "Inlets,Number Of Outlets\n");
    4057             : 
    4058             :             // Write water heater header for EIO
    4059         128 :             if ((state.dataWaterThermalTanks->numWaterHeaterMixed > 0) || (state.dataWaterThermalTanks->numWaterHeaterStratified > 0))
    4060         128 :                 print(state.files.eio, Format_720);
    4061         128 :             if (state.dataWaterThermalTanks->numHeatPumpWaterHeater > 0) print(state.files.eio, Format_721);
    4062         128 :             if (state.dataWaterThermalTanks->numWaterHeaterStratified > 0) print(state.files.eio, Format_722);
    4063         128 :             if (state.dataWaterThermalTanks->numChilledWaterMixed > 0) print(state.files.eio, Format_725);
    4064         128 :             if (state.dataWaterThermalTanks->numChilledWaterStratified > 0) print(state.files.eio, Format_726);
    4065             :         }
    4066             : 
    4067         426 :         if (state.dataWaterThermalTanks->numWaterThermalTank > 0) {
    4068         128 :             state.dataWaterThermalTanks->WaterThermalTank.allocate(state.dataWaterThermalTanks->numWaterThermalTank);
    4069         128 :             state.dataWaterThermalTanks->UniqueWaterThermalTankNames.reserve(static_cast<unsigned>(state.dataWaterThermalTanks->numWaterThermalTank));
    4070             :         }
    4071         426 :         if (state.dataWaterThermalTanks->numHeatPumpWaterHeater > 0) {
    4072           9 :             state.dataWaterThermalTanks->HPWaterHeater.allocate(state.dataWaterThermalTanks->numHeatPumpWaterHeater);
    4073             :         }
    4074             : 
    4075         426 :         if (state.dataWaterThermalTanks->numWaterHeaterDesuperheater > 0) {
    4076           6 :             state.dataWaterThermalTanks->WaterHeaterDesuperheater.allocate(state.dataWaterThermalTanks->numWaterHeaterDesuperheater);
    4077             :         }
    4078             : 
    4079             :         // =======   Get Coil:WaterHeating:Desuperheater ======================================================================
    4080         426 :         if (state.dataWaterThermalTanks->numWaterHeaterDesuperheater > 0) {
    4081           6 :             ErrorsFound |= getDesuperHtrInput(state);
    4082             :         }
    4083             : 
    4084             :         //  =======   Get HEAT PUMP:WATER HEATER ===============================================================================
    4085         426 :         if (state.dataWaterThermalTanks->numHeatPumpWaterHeater > 0) {
    4086           9 :             ErrorsFound |= getHPWaterHeaterInput(state);
    4087             :         }
    4088             : 
    4089             :         //  =======   Get WATER HEATER:MIXED ===================================================================================
    4090         426 :         if (state.dataWaterThermalTanks->numWaterHeaterMixed > 0) {
    4091         119 :             ErrorsFound |= getWaterHeaterMixedInputs(state);
    4092             :         }
    4093             : 
    4094             :         //  =======   Get WATER HEATER:STRATIFIED ==============================================================================
    4095         426 :         if (state.dataWaterThermalTanks->numWaterHeaterStratified > 0) {
    4096          10 :             ErrorsFound |= getWaterHeaterStratifiedInput(state);
    4097             :         }
    4098             : 
    4099             :         //  =======   Get Chilled Water :MIXED ===================================================================================
    4100         426 :         if (state.dataWaterThermalTanks->numChilledWaterMixed > 0) {
    4101           3 :             ErrorsFound |= getWaterTankMixedInput(state);
    4102             :         }
    4103             : 
    4104             :         //  =======   Get 'ThermalStorage:ChilledWater:Stratified' =======================================================
    4105         426 :         if (state.dataWaterThermalTanks->numChilledWaterStratified > 0) {
    4106           2 :             ErrorsFound |= getWaterTankStratifiedInput(state);
    4107             :         }
    4108             : 
    4109             :         //   Loop through all desuperheating coils and then search all water heaters for the tank connected to the desuperheating coil
    4110         426 :         if (state.dataWaterThermalTanks->numWaterHeaterDesuperheater > 0) {
    4111           6 :             state.dataIPShortCut->cCurrentModuleObject = cCoilDesuperheater;
    4112          12 :             for (int DesuperheaterNum = 1; DesuperheaterNum <= state.dataWaterThermalTanks->numWaterHeaterDesuperheater; ++DesuperheaterNum) {
    4113           6 :                 auto &DesuperHtr = state.dataWaterThermalTanks->WaterHeaterDesuperheater(DesuperheaterNum);
    4114          12 :                 for (int WtrHtrNum = 1; WtrHtrNum <= state.dataWaterThermalTanks->numWaterThermalTank; ++WtrHtrNum) {
    4115           6 :                     auto &Tank = state.dataWaterThermalTanks->WaterThermalTank(WtrHtrNum);
    4116           6 :                     if (!UtilityRoutines::SameString(DesuperHtr.TankName, Tank.Name) || !UtilityRoutines::SameString(DesuperHtr.TankType, Tank.Type))
    4117           0 :                         continue;
    4118           6 :                     Tank.DesuperheaterNum = DesuperheaterNum;
    4119           6 :                     DesuperHtr.WaterHeaterTankNum = WtrHtrNum;
    4120           6 :                     DesuperHtr.TankTypeNum = Tank.WaterThermalTankType;
    4121           6 :                     DesuperHtr.BackupElementCapacity = Tank.MaxCapacity;
    4122           6 :                     if (Tank.UseInletNode == 0 && Tank.UseOutletNode == 0) DesuperHtr.StandAlone = true;
    4123             : 
    4124             :                     //         verify Desuperheater/tank source node connections
    4125           6 :                     if (DesuperHtr.WaterInletNode != Tank.SourceOutletNode) {
    4126           0 :                         ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + DesuperHtr.Name + ':');
    4127           0 :                         ShowContinueError(state, "Desuperheater inlet node name does not match thermal tank source outlet node name.");
    4128           0 :                         ShowContinueError(state,
    4129           0 :                                           "Desuperheater water inlet and outlet node names = " + DesuperHtr.InletNodeName1 + " and " +
    4130             :                                               DesuperHtr.OutletNodeName1);
    4131           0 :                         ShowContinueError(state,
    4132           0 :                                           "Thermal tank source side inlet and outlet node names      = " + Tank.InletNodeName2 + " and " +
    4133             :                                               Tank.OutletNodeName2);
    4134           0 :                         ErrorsFound = true;
    4135             :                     }
    4136             : 
    4137           6 :                     if (DesuperHtr.WaterOutletNode != Tank.SourceInletNode) {
    4138           0 :                         ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + DesuperHtr.Name + ':');
    4139           0 :                         ShowContinueError(state, "Desuperheater water outlet node name does not match thermal tank source inlet node name.");
    4140           0 :                         ShowContinueError(state,
    4141           0 :                                           "Desuperheater water inlet and outlet node names = " + DesuperHtr.InletNodeName1 + " and " +
    4142             :                                               DesuperHtr.OutletNodeName1);
    4143           0 :                         ShowContinueError(state,
    4144           0 :                                           "Thermal tank source side inlet and outlet node names      = " + Tank.InletNodeName2 + " and " +
    4145             :                                               Tank.OutletNodeName2);
    4146           0 :                         ErrorsFound = true;
    4147             :                     }
    4148             :                 }
    4149             : 
    4150           6 :                 if (DesuperHtr.WaterHeaterTankNum == 0) {
    4151           0 :                     ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + DesuperHtr.Name + ':');
    4152           0 :                     ShowContinueError(state, " Water heater tank = " + DesuperHtr.TankName + " not found.");
    4153           0 :                     ErrorsFound = true;
    4154             :                 }
    4155             :             }
    4156             :         }
    4157             : 
    4158             :         // Loop through HPWH's and then search all water heaters for the tank connected to the HPWH
    4159         426 :         if (state.dataWaterThermalTanks->numHeatPumpWaterHeater > 0) {
    4160             : 
    4161           9 :             int const NumPumpedCondenser = state.dataInputProcessing->inputProcessor->getNumObjectsFound(
    4162           9 :                 state, cHPWHPumpedCondenser); // number of WaterHeater:HeatPump:PumpedCondenser objects
    4163          32 :             for (int HPWaterHeaterNum = 1; HPWaterHeaterNum <= state.dataWaterThermalTanks->numHeatPumpWaterHeater; ++HPWaterHeaterNum) {
    4164             : 
    4165             :                 // Create reference to current HPWH object in array.
    4166          23 :                 HeatPumpWaterHeaterData &HPWH = state.dataWaterThermalTanks->HPWaterHeater(HPWaterHeaterNum);
    4167          23 :                 if (HPWaterHeaterNum <= NumPumpedCondenser) {
    4168             :                     // Pumped Condenser
    4169          20 :                     state.dataIPShortCut->cCurrentModuleObject = cHPWHPumpedCondenser;
    4170             :                 } else {
    4171             :                     // Wrapped Condenser
    4172           3 :                     state.dataIPShortCut->cCurrentModuleObject = cHPWHWrappedCondenser;
    4173             :                 }
    4174             : 
    4175             :                 // find the tank associated with the heat pump water heater and change its %TYPE to HEAT PUMP:WATER HEATER
    4176         143 :                 for (int CheckWaterHeaterNum = 1; CheckWaterHeaterNum <= state.dataWaterThermalTanks->numWaterThermalTank; ++CheckWaterHeaterNum) {
    4177             : 
    4178         120 :                     auto &Tank = state.dataWaterThermalTanks->WaterThermalTank(CheckWaterHeaterNum);
    4179             : 
    4180         120 :                     if (!(UtilityRoutines::SameString(HPWH.TankName, Tank.Name) && UtilityRoutines::SameString(HPWH.TankType, Tank.Type))) continue;
    4181             : 
    4182             :                     // save backup element and on/off-cycle parasitic properties for use during standard rating procedure
    4183          23 :                     HPWH.BackupElementCapacity = Tank.MaxCapacity;
    4184          23 :                     HPWH.BackupElementEfficiency = Tank.Efficiency;
    4185          23 :                     HPWH.WHOnCycParaLoad = Tank.OnCycParaLoad;
    4186          23 :                     HPWH.WHOffCycParaLoad = Tank.OffCycParaLoad;
    4187          23 :                     HPWH.WHOnCycParaFracToTank = Tank.OnCycParaFracToTank;
    4188          23 :                     HPWH.WHOffCycParaFracToTank = Tank.OffCycParaFracToTank;
    4189          23 :                     HPWH.WHPLFCurve = Tank.PLFCurve;
    4190             : 
    4191          35 :                     if (((Tank.WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed) &&
    4192          23 :                          (HPWH.HPWHType == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterPumped)) ||
    4193          11 :                         (Tank.WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified)) {
    4194          23 :                         HPWH.TankType = Tank.Type;
    4195          23 :                         HPWH.HPWHTankType = Tank.WaterThermalTankType;
    4196             :                     } else {
    4197           0 :                         ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HPWH.Name + ':');
    4198           0 :                         ShowContinueError(state, "Invalid water heater tank type = " + Tank.Type);
    4199           0 :                         ErrorsFound = true;
    4200             :                     }
    4201             : 
    4202             :                     // Set up comp set for condenser water side nodes (reverse inlet/outlet for water heater)
    4203          23 :                     if (HPWH.bIsIHP) {
    4204           3 :                         BranchNodeConnections::SetUpCompSets(state,
    4205             :                                                              HPWH.Type,
    4206             :                                                              HPWH.Name,
    4207             :                                                              HPWH.DXCoilType,
    4208           2 :                                                              HPWH.DXCoilName + " Water Coil",
    4209             :                                                              HPWH.InletNodeName1,
    4210             :                                                              HPWH.OutletNodeName1,
    4211           1 :                                                              "HPWH To Coil");
    4212             :                     } else {
    4213          22 :                         BranchNodeConnections::SetUpCompSets(
    4214          22 :                             state, HPWH.Type, HPWH.Name, HPWH.DXCoilType, HPWH.DXCoilName, HPWH.InletNodeName1, HPWH.OutletNodeName1, "HPWH To Coil");
    4215             :                     }
    4216          23 :                     BranchNodeConnections::SetUpCompSets(
    4217          23 :                         state, HPWH.Type, HPWH.Name, HPWH.TankType, HPWH.TankName, HPWH.OutletNodeName1, HPWH.InletNodeName1, "HPWH To Tank");
    4218             : 
    4219             :                     // If WaterHeaterMixed: do not allow modulating control for HPWH's (i.e. modulating control usually used for tankless WH's)
    4220          35 :                     if ((Tank.WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed) &&
    4221          12 :                         (Tank.ControlType == HeaterControlMode::Modulate)) {
    4222           0 :                         ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HPWH.Name + ':');
    4223           0 :                         ShowContinueError(state, "Heater Control Type for " + Tank.Type + " = " + Tank.Name + " must be CYCLE.");
    4224           0 :                         ErrorsFound = true;
    4225             :                     }
    4226             : 
    4227          23 :                     Tank.HeatPumpNum = HPWaterHeaterNum;
    4228          23 :                     HPWH.WaterHeaterTankNum = CheckWaterHeaterNum;
    4229          23 :                     HPWH.FoundTank = true;
    4230             : 
    4231          23 :                     if (Tank.DesuperheaterNum > 0) {
    4232           0 :                         ShowSevereError(state,
    4233           0 :                                         state.dataIPShortCut->cCurrentModuleObject + " = " + HPWH.Name + "and Coil:WaterHeating:Desuperheater = " +
    4234           0 :                                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(CheckWaterHeaterNum).Name +
    4235           0 :                                             ":  cannot be connected to the same water heater tank = " + Tank.Name);
    4236             :                     }
    4237             : 
    4238             :                     // check that water heater source side effectiveness is greater than 0
    4239          23 :                     if (Tank.SourceEffectiveness <= 0.0) {
    4240           0 :                         ShowSevereError(state,
    4241           0 :                                         format("{} = {}:  Invalid source side effectiveness for heat pump water heater = {:.3T}",
    4242           0 :                                                state.dataIPShortCut->cCurrentModuleObject,
    4243             :                                                HPWH.Name,
    4244           0 :                                                Tank.SourceEffectiveness));
    4245           0 :                         ShowContinueError(state, " water heater source effectiveness will default to 1.0 and simulation continues.");
    4246           0 :                         Tank.SourceEffectiveness = 1.0;
    4247             :                     }
    4248             : 
    4249             :                     // Set up the source side nodes for wrapped condensers
    4250          23 :                     if (HPWH.HPWHType == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterWrapped) {
    4251           3 :                         if (Tank.SourceInletNode > 0 || Tank.SourceOutletNode > 0) {
    4252           0 :                             ShowSevereError(state, Tank.Type + " = " + Tank.Name + " has a source inlet or outlet node specified,");
    4253           0 :                             ShowContinueError(
    4254           0 :                                 state, "but it is attached to " + HPWH.Type + " = " + HPWH.Name + ", which doesn't permit source side connections.");
    4255           0 :                             ShowContinueError(state, "Please leave the source side inlet and outlet fields blank.");
    4256           0 :                             ErrorsFound = true;
    4257             :                         } else {
    4258             : 
    4259           6 :                             auto objType = (DataLoopNode::ConnectionObjectType)getEnumerationValue(BranchNodeConnections::ConnectionObjectTypeNamesUC,
    4260           9 :                                                                                                    UtilityRoutines::MakeUPPERCase(Tank.Type));
    4261             : 
    4262           3 :                             Tank.SourceInletNode = NodeInputManager::GetOnlySingleNode(state,
    4263             :                                                                                        HPWH.OutletNodeName1,
    4264             :                                                                                        ErrorsFound,
    4265             :                                                                                        objType,
    4266             :                                                                                        Tank.Name,
    4267             :                                                                                        DataLoopNode::NodeFluidType::Water,
    4268             :                                                                                        DataLoopNode::ConnectionType::Inlet,
    4269             :                                                                                        NodeInputManager::CompFluidStream::Secondary,
    4270           3 :                                                                                        DataLoopNode::ObjectIsNotParent);
    4271           3 :                             Tank.InletNodeName2 = HPWH.OutletNodeName1;
    4272           3 :                             Tank.SourceOutletNode = NodeInputManager::GetOnlySingleNode(state,
    4273             :                                                                                         HPWH.InletNodeName1,
    4274             :                                                                                         ErrorsFound,
    4275             :                                                                                         objType,
    4276             :                                                                                         Tank.Name,
    4277             :                                                                                         DataLoopNode::NodeFluidType::Water,
    4278             :                                                                                         DataLoopNode::ConnectionType::Outlet,
    4279             :                                                                                         NodeInputManager::CompFluidStream::Secondary,
    4280           3 :                                                                                         DataLoopNode::ObjectIsNotParent);
    4281           3 :                             Tank.OutletNodeName2 = HPWH.InletNodeName1;
    4282             :                         }
    4283             : 
    4284             :                         // Mark the tank as not stand alone because it is connected now.
    4285           3 :                         Tank.StandAlone = false;
    4286             :                     }
    4287             : 
    4288             :                     // Set HPWH structure variable StandAlone to TRUE if use nodes are not connected
    4289          23 :                     if (Tank.UseInletNode == 0 && Tank.UseOutletNode == 0) HPWH.StandAlone = true;
    4290             : 
    4291          23 :                     if (HPWH.WHUseInletNode != Tank.UseInletNode || HPWH.WHUseOutletNode != Tank.UseOutletNode) {
    4292           0 :                         ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HPWH.Name + ':');
    4293           0 :                         ShowContinueError(state,
    4294             :                                           "Heat pump water heater tank use side inlet and outlet node names must match the use side inlet and "
    4295           0 :                                           "outlet node names for water heater tank = " +
    4296           0 :                                               HPWH.TankType + ": " + HPWH.TankName);
    4297           0 :                         ShowContinueError(state,
    4298           0 :                                           "Heat pump water heater use side inlet and outlet node names = " + HPWH.InletNodeName2 + " and " +
    4299             :                                               HPWH.OutletNodeName2);
    4300           0 :                         ShowContinueError(state,
    4301           0 :                                           "Water heater tank use side inlet and outlet node names      = " + Tank.InletNodeName1 + " and " +
    4302             :                                               Tank.OutletNodeName1);
    4303           0 :                         ErrorsFound = true;
    4304             :                     } else {
    4305          23 :                         if (!HPWH.StandAlone) {
    4306          10 :                             BranchNodeConnections::TestCompSet(state, HPWH.Type, HPWH.Name, Tank.InletNodeName1, Tank.OutletNodeName1, "Water Nodes");
    4307             :                         }
    4308             :                     }
    4309             : 
    4310             :                     // verify HP/tank source node connections
    4311          23 :                     if (HPWH.CondWaterInletNode != Tank.SourceOutletNode) {
    4312           0 :                         ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HPWH.Name + ':');
    4313           0 :                         ShowContinueError(state,
    4314             :                                           "Heat Pump condenser water inlet node name does not match water heater tank source outlet node name.");
    4315           0 :                         ShowContinueError(
    4316           0 :                             state, "Heat pump condenser water inlet and outlet node names = " + HPWH.InletNodeName1 + " and " + HPWH.OutletNodeName1);
    4317           0 :                         ShowContinueError(state,
    4318           0 :                                           "Water heater tank source side inlet and outlet node names      = " + Tank.InletNodeName2 + " and " +
    4319             :                                               Tank.OutletNodeName2);
    4320           0 :                         ErrorsFound = true;
    4321             :                     }
    4322             : 
    4323          23 :                     if (HPWH.CondWaterOutletNode != Tank.SourceInletNode) {
    4324           0 :                         ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HPWH.Name + ':');
    4325           0 :                         ShowContinueError(state,
    4326             :                                           "Heat Pump condenser water outlet node name does not match water heater tank source inlet node name.");
    4327           0 :                         ShowContinueError(
    4328           0 :                             state, "Heat pump condenser water inlet and outlet node names = " + HPWH.InletNodeName1 + " and " + HPWH.OutletNodeName1);
    4329           0 :                         ShowContinueError(state,
    4330           0 :                                           "Water heater tank source side inlet and outlet node names      = " + Tank.InletNodeName2 + " and " +
    4331             :                                               Tank.OutletNodeName2);
    4332           0 :                         ErrorsFound = true;
    4333             :                     }
    4334             : 
    4335             :                     // verify wrapped condenser location
    4336          23 :                     if (HPWH.HPWHType == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterWrapped) {
    4337             :                         // make sure the top of the condenser is not above the tank height.
    4338           3 :                         if (HPWH.WrappedCondenserTopLocation > Tank.Height) {
    4339           0 :                             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HPWH.Name + ':');
    4340           0 :                             ShowContinueError(state, "The height of the top of the wrapped condenser is greater than the height of the tank.");
    4341           0 :                             ErrorsFound = true;
    4342             :                         }
    4343             :                     }
    4344             : 
    4345             :                     // Verify tank name is in a zone equipment list if HPWH Inlet Air Configuration is Zone Air Only or Zone and Outdoor Air
    4346          23 :                     if (HPWH.InletAirConfiguration == WTTAmbientTemp::TempZone || HPWH.InletAirConfiguration == WTTAmbientTemp::ZoneAndOA) {
    4347          10 :                         if (allocated(state.dataZoneEquip->ZoneEquipConfig) && allocated(state.dataZoneEquip->ZoneEquipList)) {
    4348          10 :                             bool FoundTankInList = false;
    4349          10 :                             bool TankNotLowestPriority = false;
    4350          10 :                             int ZoneEquipConfigNum = HPWH.AmbientTempZone;
    4351          10 :                             int ZoneEquipListNum = state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum).EquipListIndex;
    4352          10 :                             int TankCoolingPriority = 0;
    4353          10 :                             int TankHeatingPriority = 0;
    4354          19 :                             for (int EquipmentTypeNum = 1; EquipmentTypeNum <= state.dataZoneEquip->ZoneEquipList(ZoneEquipListNum).NumOfEquipTypes;
    4355             :                                  ++EquipmentTypeNum) {
    4356          19 :                                 if (state.dataZoneEquip->ZoneEquipList(ZoneEquipListNum).EquipName(EquipmentTypeNum) != HPWH.Name) continue;
    4357          10 :                                 FoundTankInList = true;
    4358          10 :                                 TankCoolingPriority = state.dataZoneEquip->ZoneEquipList(ZoneEquipListNum).CoolingPriority(EquipmentTypeNum);
    4359          10 :                                 TankHeatingPriority = state.dataZoneEquip->ZoneEquipList(ZoneEquipListNum).HeatingPriority(EquipmentTypeNum);
    4360          10 :                                 break;
    4361             :                             } // EquipmentTypeNum
    4362          10 :                             if (!FoundTankInList) {
    4363           0 :                                 ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HPWH.Name + ':');
    4364           0 :                                 ShowContinueError(state,
    4365             :                                                   "Heat pump water heater type and name must be listed in the correct "
    4366             :                                                   "ZoneHVAC:EquipmentList object when Inlet Air Configuration is equal to "
    4367             :                                                   "ZoneAirOnly or ZoneAndOutdoorAir.");
    4368           0 :                                 ErrorsFound = true;
    4369             :                             }
    4370             :                             //                     check that tank has lower priority than all other non-HPWH objects in Zone
    4371             :                             //                     Equipment List
    4372          39 :                             for (int EquipmentTypeNum = 1; EquipmentTypeNum <= state.dataZoneEquip->ZoneEquipList(ZoneEquipListNum).NumOfEquipTypes;
    4373             :                                  ++EquipmentTypeNum) {
    4374          29 :                                 if (UtilityRoutines::SameString(state.dataZoneEquip->ZoneEquipList(ZoneEquipListNum).EquipType(EquipmentTypeNum),
    4375          29 :                                                                 state.dataIPShortCut->cCurrentModuleObject))
    4376          14 :                                     continue;
    4377          30 :                                 if (TankCoolingPriority > state.dataZoneEquip->ZoneEquipList(ZoneEquipListNum).CoolingPriority(EquipmentTypeNum) ||
    4378          15 :                                     TankHeatingPriority > state.dataZoneEquip->ZoneEquipList(ZoneEquipListNum).HeatingPriority(EquipmentTypeNum)) {
    4379           0 :                                     TankNotLowestPriority = true;
    4380             :                                 }
    4381             :                             } // EquipmentTypeNum
    4382          10 :                             if (TankNotLowestPriority && FoundTankInList) {
    4383           0 :                                 ShowWarningError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HPWH.Name + ':');
    4384           0 :                                 ShowContinueError(state,
    4385             :                                                   "Heat pump water heaters should be simulated first, before other space "
    4386             :                                                   "conditioning equipment.");
    4387           0 :                                 ShowContinueError(state,
    4388             :                                                   "Poor temperature control may result if the Heating/Cooling sequence number is "
    4389             :                                                   "not 1 in the ZoneHVAC:EquipmentList.");
    4390             :                             }
    4391             :                         } else {
    4392           0 :                             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HPWH.Name + ':');
    4393           0 :                             ShowContinueError(state,
    4394             :                                               "ZoneHVAC:EquipmentList and ZoneHVAC:EquipmentConnections objects are required when Inlet Air "
    4395             :                                               "Configuration is either ZoneAirOnly or ZoneAndOutdoorAir.");
    4396           0 :                             ErrorsFound = true;
    4397             :                         } // ALLOCATED
    4398             :                     }     // InletAirConfiguration
    4399             : 
    4400          23 :                     if (Tank.WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
    4401             : 
    4402             :                         // Nodal heat distribution fraction for stratified tank wrapped condensers
    4403          11 :                         if (HPWH.HPWHType == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterWrapped) {
    4404           3 :                             if (Tank.Shape == TankShape::HorizCylinder) {
    4405           0 :                                 ShowWarningError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HPWH.Name + ":");
    4406           0 :                                 ShowContinueError(state, "A wrapped condenser HPWH model should not be used with a horizontal stratified tank.");
    4407           0 :                                 ShowContinueError(
    4408             :                                     state, "Ignoring condenser location and distributing heat evenly throughout the tank. Simulation continues.");
    4409           0 :                                 Real64 const SameFrac = 1.0 / Tank.Nodes;
    4410           0 :                                 for (int NodeNum = 1; NodeNum <= Tank.Nodes; ++NodeNum) {
    4411           0 :                                     Tank.Node(NodeNum).HPWHWrappedCondenserHeatingFrac = SameFrac;
    4412             :                                 }
    4413             :                             } else {
    4414           3 :                                 Real64 H0 = Tank.Height; // height of top of node
    4415             :                                 Real64 H;                // height of bottom of node
    4416           3 :                                 Real64 SumFrac(0.0);
    4417             :                                 // Get the fraction of each stratified node that is wrapped by the condenser
    4418          17 :                                 for (int NodeNum = 1; NodeNum <= Tank.Nodes; ++NodeNum) {
    4419          14 :                                     StratifiedNodeData &CurNode = Tank.Node(NodeNum);
    4420          14 :                                     if (NodeNum == Tank.Nodes) {
    4421           3 :                                         H = 0.0;
    4422             :                                     } else {
    4423          11 :                                         H = H0 - CurNode.Height;
    4424             :                                     }
    4425          14 :                                     if (H < HPWH.WrappedCondenserBottomLocation && H0 > HPWH.WrappedCondenserBottomLocation) {
    4426             :                                         // The bottom of the condenser starts partway through this node.
    4427           3 :                                         CurNode.HPWHWrappedCondenserHeatingFrac = 1.0 - (HPWH.WrappedCondenserBottomLocation - H) / CurNode.Height;
    4428          11 :                                     } else if (H >= HPWH.WrappedCondenserBottomLocation && H <= HPWH.WrappedCondenserTopLocation) {
    4429          12 :                                         if (H0 > HPWH.WrappedCondenserTopLocation) {
    4430             :                                             // the top of the condenser ends partway through this node.
    4431           1 :                                             CurNode.HPWHWrappedCondenserHeatingFrac = (HPWH.WrappedCondenserTopLocation - H) / CurNode.Height;
    4432             :                                         } else {
    4433             :                                             // the entire node is wrapped by the condenser
    4434           5 :                                             CurNode.HPWHWrappedCondenserHeatingFrac = 1.0;
    4435             :                                         }
    4436             :                                     } else {
    4437           5 :                                         CurNode.HPWHWrappedCondenserHeatingFrac = 0.0;
    4438             :                                     }
    4439          14 :                                     SumFrac += CurNode.HPWHWrappedCondenserHeatingFrac;
    4440          14 :                                     H0 = H;
    4441             :                                 }
    4442             :                                 // Normalize the fractions so they sum to 1.
    4443          17 :                                 for (int NodeNum = 1; NodeNum <= Tank.Nodes; ++NodeNum) {
    4444          14 :                                     Tank.Node(NodeNum).HPWHWrappedCondenserHeatingFrac /= SumFrac;
    4445             :                                 }
    4446             :                             }
    4447             :                         }
    4448             : 
    4449             :                         // Stratified Tank HPWH control sensor node locations
    4450          11 :                         if (HPWH.ControlSensor1Height < 0.0) {
    4451             :                             // default to heater 1
    4452           0 :                             HPWH.ControlSensor1Height = Tank.HeaterHeight1;
    4453             :                         }
    4454          11 :                         if (HPWH.ControlSensor2Height < 0.0) {
    4455             :                             // default to heater 2
    4456           0 :                             HPWH.ControlSensor2Height = Tank.HeaterHeight2;
    4457             :                         }
    4458             : 
    4459             :                         // Get the vertical tank height depending on the type of tank
    4460             :                         Real64 TankHeight;
    4461          11 :                         if (Tank.Shape == TankShape::VertCylinder || Tank.Shape == TankShape::Other) {
    4462          11 :                             TankHeight = Tank.Height;
    4463             :                         } else {
    4464           0 :                             assert(Tank.Shape == TankShape::HorizCylinder);
    4465             :                             // For horizontal cylinders, the tank "height" is actually the length.
    4466             :                             // We need to calculate the height.
    4467           0 :                             Real64 EndArea = Tank.Volume / Tank.Height;
    4468           0 :                             Real64 Radius = std::sqrt(EndArea / DataGlobalConstants::Pi);
    4469           0 :                             TankHeight = 2.0 * Radius; // actual vertical height
    4470             :                         }
    4471             : 
    4472             :                         // Make sure the control sensor locations are in the tank
    4473          11 :                         if (HPWH.ControlSensor1Height < 0.0 || HPWH.ControlSensor1Height > TankHeight) {
    4474           0 :                             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HPWH.Name + ':');
    4475           0 :                             ShowContinueError(state, "Control Sensor 1 is located outside the tank.");
    4476           0 :                             ErrorsFound = true;
    4477             :                         }
    4478          11 :                         if (HPWH.ControlSensor2Height < 0.0 || HPWH.ControlSensor2Height > TankHeight) {
    4479           0 :                             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HPWH.Name + ':');
    4480           0 :                             ShowContinueError(state, "Control Sensor 2 is located outside the tank.");
    4481           0 :                             ErrorsFound = true;
    4482             :                         }
    4483             : 
    4484             :                         // Assign the control sensors to the appropriate nodes
    4485          11 :                         Real64 H0 = TankHeight;
    4486             :                         Real64 H;
    4487          97 :                         for (int NodeNum = 1; NodeNum <= Tank.Nodes; ++NodeNum) {
    4488          86 :                             StratifiedNodeData const &TankNode = Tank.Node(NodeNum);
    4489          86 :                             if (NodeNum == Tank.Nodes) {
    4490          11 :                                 H = -1.0; // Avoids rounding errors and ensures that anything at height 0.0 goes into the bottom node
    4491             :                             } else {
    4492          75 :                                 H = H0 - TankNode.Height;
    4493             :                             }
    4494             : 
    4495             :                             // Control Sensor 1 Node
    4496          86 :                             if (HPWH.ControlSensor1Height <= H0 && HPWH.ControlSensor1Height > H) {
    4497          11 :                                 HPWH.ControlSensor1Node = NodeNum;
    4498             :                             }
    4499             : 
    4500             :                             // Control Sensor 2 Node
    4501          86 :                             if (HPWH.ControlSensor2Height <= H0 && HPWH.ControlSensor2Height > H) {
    4502          11 :                                 HPWH.ControlSensor2Node = NodeNum;
    4503             :                             }
    4504             : 
    4505          86 :                             H0 = H;
    4506             :                         }
    4507             :                     }
    4508             : 
    4509             :                 } // DO CheckWaterHeaterNum = 1, NumWaterHeater
    4510             : 
    4511          23 :                 if (!HPWH.FoundTank) {
    4512           0 :                     ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + " = " + HPWH.Name + ':');
    4513           0 :                     ShowContinueError(state, "Water heater tank object not found = " + HPWH.TankType + ", " + HPWH.TankName);
    4514           0 :                     ErrorsFound = true;
    4515             :                 }
    4516             : 
    4517             :             } // DO HPWaterHeaterNum = 1, NumHeatPumpWaterHeater
    4518             :         }
    4519             : 
    4520             :         // Get water heater sizing input.
    4521         426 :         state.dataIPShortCut->cCurrentModuleObject = "WaterHeater:Sizing";
    4522         426 :         state.dataWaterThermalTanks->numWaterHeaterSizing =
    4523         426 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
    4524             : 
    4525         426 :         if (state.dataWaterThermalTanks->numWaterHeaterSizing > 0) {
    4526             : 
    4527           8 :             for (int WHsizingNum = 1; WHsizingNum <= state.dataWaterThermalTanks->numWaterHeaterSizing; ++WHsizingNum) {
    4528             :                 int NumAlphas;
    4529             :                 int NumNums;
    4530             :                 int IOStat;
    4531          16 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    4532           4 :                                                                          state.dataIPShortCut->cCurrentModuleObject,
    4533             :                                                                          WHsizingNum,
    4534           4 :                                                                          state.dataIPShortCut->cAlphaArgs,
    4535             :                                                                          NumAlphas,
    4536           4 :                                                                          state.dataIPShortCut->rNumericArgs,
    4537             :                                                                          NumNums,
    4538             :                                                                          IOStat);
    4539             : 
    4540             :                 // find which water heater this object is for
    4541             :                 int WaterThermalTankNum =
    4542           4 :                     UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataWaterThermalTanks->WaterThermalTank);
    4543           4 :                 if (WaterThermalTankNum == 0) {
    4544             :                     // did not match name throw warning.
    4545           0 :                     ShowSevereError(state,
    4546           0 :                                     state.dataIPShortCut->cCurrentModuleObject + " object name: " + state.dataIPShortCut->cAlphaArgs(1) +
    4547             :                                         " does not match any of the water heaters defined in the file");
    4548           0 :                     ErrorsFound = true;
    4549           0 :                     continue;
    4550             :                 } else { // we have a match
    4551             :                     // store the sizing data in "sizing" nested derived type for the correct water heater
    4552             : 
    4553           4 :                     if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(2), "PeakDraw")) {
    4554           2 :                         state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.DesignMode = SizingMode::PeakDraw;
    4555           2 :                     } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(2), "ResidentialHUD-FHAMinimum")) {
    4556           2 :                         state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.DesignMode = SizingMode::ResidentialMin;
    4557           0 :                     } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(2), "PerPerson")) {
    4558           0 :                         state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.DesignMode = SizingMode::PerPerson;
    4559           0 :                     } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(2), "PerFloorArea")) {
    4560           0 :                         state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.DesignMode = SizingMode::PerFloorArea;
    4561           0 :                     } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(2), "PerUnit")) {
    4562           0 :                         state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.DesignMode = SizingMode::PerUnit;
    4563           0 :                     } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(2), "PerSolarCollectorArea")) {
    4564           0 :                         state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.DesignMode = SizingMode::PerSolarColArea;
    4565             :                     } else {
    4566             :                         // wrong design mode entered, throw error
    4567           0 :                         ShowSevereError(state,
    4568           0 :                                         state.dataIPShortCut->cCurrentModuleObject + " object named: " + state.dataIPShortCut->cAlphaArgs(1) +
    4569           0 :                                             " contains an incorrect Design Mode of: " + state.dataIPShortCut->cAlphaArgs(2));
    4570           0 :                         ErrorsFound = true;
    4571             :                     }
    4572             : 
    4573           4 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.TankDrawTime = state.dataIPShortCut->rNumericArgs(1);
    4574           4 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.RecoveryTime = state.dataIPShortCut->rNumericArgs(2);
    4575           4 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.NominalVolForSizingDemandSideFlow =
    4576           4 :                         state.dataIPShortCut->rNumericArgs(3);
    4577           4 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.NumberOfBedrooms =
    4578           4 :                         int(state.dataIPShortCut->rNumericArgs(4));
    4579           4 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.NumberOfBathrooms =
    4580           4 :                         int(state.dataIPShortCut->rNumericArgs(5));
    4581           4 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.TankCapacityPerPerson =
    4582           4 :                         state.dataIPShortCut->rNumericArgs(6);
    4583           4 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.RecoveryCapacityPerPerson =
    4584           4 :                         state.dataIPShortCut->rNumericArgs(7);
    4585           4 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.TankCapacityPerArea =
    4586           4 :                         state.dataIPShortCut->rNumericArgs(8);
    4587           4 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.RecoveryCapacityPerArea =
    4588           4 :                         state.dataIPShortCut->rNumericArgs(9);
    4589           4 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.NumberOfUnits = state.dataIPShortCut->rNumericArgs(10);
    4590           4 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.TankCapacityPerUnit =
    4591           4 :                         state.dataIPShortCut->rNumericArgs(11);
    4592           4 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.RecoveryCapacityPerUnit =
    4593           4 :                         state.dataIPShortCut->rNumericArgs(12);
    4594           4 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.TankCapacityPerCollectorArea =
    4595           4 :                         state.dataIPShortCut->rNumericArgs(13);
    4596           4 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.HeightAspectRatio =
    4597           4 :                         state.dataIPShortCut->rNumericArgs(14);
    4598             : 
    4599           4 :                     switch (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.DesignMode) {
    4600             : 
    4601           0 :                     case SizingMode::Invalid: {
    4602             :                         // do nothing, error thrown if design mode not found
    4603           0 :                         break;
    4604             :                     }
    4605           2 :                     case SizingMode::PeakDraw: { // need to have entered a reasonable value for TankDrawTime
    4606           2 :                         if (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.TankDrawTime <= 0.0) {
    4607           0 :                             ShowSevereError(state,
    4608           0 :                                             state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4609             :                                                 ", design mode set to Peak Draw but needs a positive value for tank draw time");
    4610           0 :                             ErrorsFound = true;
    4611             :                         }
    4612             :                         // constrain crazy sizes by limiting to 10 years or 8760*10
    4613           2 :                         if (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.TankDrawTime > 87600.0) {
    4614           0 :                             ShowWarningError(state,
    4615           0 :                                              state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4616             :                                                  ",  has input with an unreasonably large Tank Draw Time, more than 10 years");
    4617           0 :                             ErrorsFound = true;
    4618             :                         }
    4619             :                         // if both volume and demand side flow connections are autosized, must be a good NominalVolForSizingDemandSideFlow
    4620           4 :                         if ((state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).UseSidePlantLoc.loopSideNum ==
    4621           2 :                              DataPlant::LoopSideLocation::Demand) &&
    4622           0 :                             (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).UseDesignVolFlowRateWasAutoSized)) {
    4623           0 :                             if (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.NominalVolForSizingDemandSideFlow <= 0.0) {
    4624           0 :                                 ShowWarningError(state,
    4625           0 :                                                  state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4626             :                                                      " needs a value for Nominal Tank Volume for Autosizing Plant Connections");
    4627           0 :                                 ErrorsFound = true;
    4628             :                             }
    4629             :                         }
    4630           4 :                         if ((state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).SrcSidePlantLoc.loopSideNum ==
    4631           2 :                              DataPlant::LoopSideLocation::Demand) &&
    4632           0 :                             (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).SourceDesignVolFlowRateWasAutoSized)) {
    4633           0 :                             if (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.NominalVolForSizingDemandSideFlow <= 0.0) {
    4634           0 :                                 ShowWarningError(state,
    4635           0 :                                                  state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4636             :                                                      " needs a value for Nominal Tank Volume for Autosizing Plant Connections");
    4637           0 :                                 ErrorsFound = true;
    4638             :                             }
    4639             :                         }
    4640             : 
    4641           2 :                         break;
    4642             :                     }
    4643           2 :                     case SizingMode::ResidentialMin: {
    4644             :                         // it would have to have at least on bedroom and any more than 10 is crazy for this mode
    4645           2 :                         if (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.NumberOfBedrooms < 1) {
    4646           0 :                             ShowSevereError(state,
    4647           0 :                                             state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4648             :                                                 ", mode needs at least one bedroom");
    4649           0 :                             ErrorsFound = true;
    4650             :                         }
    4651           2 :                         if (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.NumberOfBedrooms > 10) {
    4652           0 :                             ShowWarningError(state,
    4653           0 :                                              state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4654             :                                                  ", probably has too many bedrooms for the selected design mode");
    4655             :                         }
    4656             : 
    4657           2 :                         break;
    4658             :                     }
    4659           0 :                     case SizingMode::PerPerson: {
    4660             : 
    4661           0 :                         if ((state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).VolumeWasAutoSized) &&
    4662           0 :                             (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.TankCapacityPerPerson <= 0.0)) {
    4663           0 :                             ShowSevereError(state,
    4664           0 :                                             state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4665             :                                                 ", PerPerson mode needs positive value input for storage capacity per person");
    4666           0 :                             ErrorsFound = true;
    4667             :                         }
    4668             : 
    4669           0 :                         if ((state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).MaxCapacityWasAutoSized) &&
    4670           0 :                             (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.RecoveryCapacityPerPerson <= 0.0)) {
    4671           0 :                             ShowSevereError(state,
    4672           0 :                                             state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4673             :                                                 ", PerPerson mode needs positive value input for recovery capacity per person");
    4674           0 :                             ErrorsFound = true;
    4675             :                         }
    4676             : 
    4677           0 :                         break;
    4678             :                     }
    4679           0 :                     case SizingMode::PerFloorArea: {
    4680           0 :                         if ((state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).VolumeWasAutoSized) &&
    4681           0 :                             (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.TankCapacityPerArea <= 0.0)) {
    4682           0 :                             ShowSevereError(state,
    4683           0 :                                             state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4684             :                                                 ", PerArea mode needs positive value input for storage capacity per floor area");
    4685           0 :                             ErrorsFound = true;
    4686             :                         }
    4687           0 :                         if ((state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).MaxCapacityWasAutoSized) &&
    4688           0 :                             (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.RecoveryCapacityPerArea <= 0.0)) {
    4689           0 :                             ShowSevereError(state,
    4690           0 :                                             state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4691             :                                                 ", PerArea mode needs positive value input for recovery capacity per floor area");
    4692           0 :                             ErrorsFound = true;
    4693             :                         }
    4694             : 
    4695           0 :                         break;
    4696             :                     }
    4697           0 :                     case SizingMode::PerUnit: {
    4698           0 :                         if ((state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).VolumeWasAutoSized) &&
    4699           0 :                             (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.TankCapacityPerUnit <= 0.0)) {
    4700           0 :                             ShowSevereError(state,
    4701           0 :                                             state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4702             :                                                 ", PerUnit mode needs positive value input for storage capacity per unit");
    4703           0 :                             ErrorsFound = true;
    4704             :                         }
    4705           0 :                         if ((state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).VolumeWasAutoSized) &&
    4706           0 :                             (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.NumberOfUnits <= 0.0)) {
    4707           0 :                             ShowSevereError(state,
    4708           0 :                                             state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4709             :                                                 ", PerUnit mode needs positive value input for number of units");
    4710           0 :                             ErrorsFound = true;
    4711             :                         }
    4712           0 :                         if ((state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).MaxCapacityWasAutoSized) &&
    4713           0 :                             (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.RecoveryCapacityPerUnit <= 0.0)) {
    4714           0 :                             ShowSevereError(state,
    4715           0 :                                             state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4716             :                                                 ", PerUnit mode needs positive value input for recovery capacity per unit");
    4717           0 :                             ErrorsFound = true;
    4718             :                         }
    4719           0 :                         if ((state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).MaxCapacityWasAutoSized) &&
    4720           0 :                             (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.NumberOfUnits <= 0.0)) {
    4721           0 :                             ShowSevereError(state,
    4722           0 :                                             state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4723             :                                                 ", PerUnit mode needs positive value input for number of units");
    4724           0 :                             ErrorsFound = true;
    4725             :                         }
    4726           0 :                         break;
    4727             :                     }
    4728           0 :                     case SizingMode::PerSolarColArea: {
    4729           0 :                         if ((state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).VolumeWasAutoSized) &&
    4730           0 :                             (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.TankCapacityPerCollectorArea <= 0.0)) {
    4731           0 :                             ShowSevereError(state,
    4732           0 :                                             state.dataIPShortCut->cCurrentModuleObject + ", named " + state.dataIPShortCut->cAlphaArgs(1) +
    4733             :                                                 ", PerSolarCollectorArea mode needs positive value input for storage capacity per collector area");
    4734           0 :                             ErrorsFound = true;
    4735             :                         }
    4736           0 :                         break;
    4737             :                     }
    4738           0 :                     default:
    4739           0 :                         break;
    4740             :                     }
    4741             : 
    4742             :                 } // found water heater num okay
    4743             :             }     // loop over sizing objects
    4744             : 
    4745             :         } // any water heater sizing objects
    4746             : 
    4747             :         // now check that if water heater fields were autosized, that there was also a sizing object for that water heater
    4748         426 :         if (state.dataWaterThermalTanks->numWaterThermalTank > 0) {
    4749         321 :             for (int WaterThermalTankNum = 1; WaterThermalTankNum <= state.dataWaterThermalTanks->numWaterThermalTank; ++WaterThermalTankNum) {
    4750             : 
    4751         195 :                 if ((state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).VolumeWasAutoSized) &&
    4752           2 :                     (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.DesignMode == SizingMode::Invalid)) {
    4753           0 :                     ShowWarningError(state,
    4754           0 :                                      "Water heater named " + state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Name +
    4755             :                                          "has tank volume set to AUTOSIZE but it is missing associated WaterHeater:Sizing object");
    4756           0 :                     ErrorsFound = true;
    4757             :                 }
    4758         195 :                 if ((state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).MaxCapacityWasAutoSized) &&
    4759           2 :                     (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.DesignMode == SizingMode::Invalid)) {
    4760           0 :                     ShowWarningError(state,
    4761           0 :                                      "Water heater named " + state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Name +
    4762             :                                          "has heater capacity set to AUTOSIZE but it is missing associated WaterHeater:Sizing object");
    4763           0 :                     ErrorsFound = true;
    4764             :                 }
    4765         193 :                 if ((state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).HeightWasAutoSized) &&
    4766           0 :                     (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Sizing.DesignMode == SizingMode::Invalid)) {
    4767           0 :                     ShowWarningError(state,
    4768           0 :                                      "Water heater named " + state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Name +
    4769             :                                          "has tank height set to AUTOSIZE but it is missing associated WaterHeater:Sizing object");
    4770           0 :                     ErrorsFound = true;
    4771             :                 }
    4772             :             }
    4773             :         }
    4774             : 
    4775             :         //    now do calls to TestCompSet for tanks, depending on nodes and heat pump water heater
    4776         426 :         if (state.dataWaterThermalTanks->numWaterThermalTank > 0) {
    4777         321 :             for (int WaterThermalTankNum = 1; WaterThermalTankNum <= state.dataWaterThermalTanks->numWaterThermalTank; ++WaterThermalTankNum) {
    4778         318 :                 if (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).UseInletNode > 0 &&
    4779         125 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).UseOutletNode > 0) {
    4780         125 :                     if (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).HeatPumpNum > 0) {
    4781             :                         // do nothing, Use nodes are tested for HeatPump:WaterHeater not tank
    4782             :                     } else {
    4783         575 :                         BranchNodeConnections::TestCompSet(state,
    4784         115 :                                                            state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Type,
    4785         115 :                                                            state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Name,
    4786         115 :                                                            state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).InletNodeName1,
    4787         115 :                                                            state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).OutletNodeName1,
    4788             :                                                            "Use Side Water Nodes");
    4789             :                     }
    4790             :                 }
    4791         242 :                 if (state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).SourceInletNode > 0 &&
    4792          49 :                     state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).SourceOutletNode > 0) {
    4793             : 
    4794         245 :                     BranchNodeConnections::TestCompSet(state,
    4795          49 :                                                        state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Type,
    4796          49 :                                                        state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).Name,
    4797          49 :                                                        state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).InletNodeName2,
    4798          49 :                                                        state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).OutletNodeName2,
    4799             :                                                        "Source Side Water Nodes");
    4800             :                 }
    4801             :             }
    4802             :         }
    4803             : 
    4804         426 :         if (state.dataWaterThermalTanks->numWaterThermalTank > 0) {
    4805         321 :             for (int WaterThermalTankNum = 1; WaterThermalTankNum <= state.dataWaterThermalTanks->numWaterThermalTank; ++WaterThermalTankNum) {
    4806             : 
    4807         193 :                 state.dataWaterThermalTanks->WaterThermalTank(WaterThermalTankNum).setupZoneInternalGains(state);
    4808             : 
    4809             :             } // WaterThermalTankNum
    4810             :         }
    4811             :     } // get input flag
    4812             : 
    4813         426 :     return ErrorsFound;
    4814             : }
    4815             : 
    4816         191 : void WaterThermalTankData::setupOutputVars(EnergyPlusData &state)
    4817             : {
    4818         379 :     if ((this->WaterThermalTankType == DataPlant::PlantEquipmentType::ChilledWaterTankMixed) ||
    4819         188 :         (this->WaterThermalTankType == DataPlant::PlantEquipmentType::ChilledWaterTankStratified)) {
    4820           5 :         this->setupChilledWaterTankOutputVars(state);
    4821             :     } else {
    4822             :         // moving setupWaterHeaterOutputVars to here causes big table diffs...
    4823         186 :         this->setupWaterHeaterOutputVars(state);
    4824             :     }
    4825             :     // moving setupZoneInternalGains to here causes math and table diffs...
    4826             :     // this->setupZoneInternalGains();
    4827         191 : }
    4828             : 
    4829           5 : void WaterThermalTankData::setupChilledWaterTankOutputVars(EnergyPlusData &state)
    4830             : {
    4831             : 
    4832             :     // CurrentModuleObject='ThermalStorage:ChilledWater:Mixed/ThermalStorage:ChilledWater:Stratified'
    4833          10 :     SetupOutputVariable(state,
    4834             :                         "Chilled Water Thermal Storage Tank Temperature",
    4835             :                         OutputProcessor::Unit::C,
    4836             :                         this->TankTempAvg,
    4837             :                         OutputProcessor::SOVTimeStepType::System,
    4838             :                         OutputProcessor::SOVStoreType::Average,
    4839           5 :                         this->Name);
    4840             : 
    4841          10 :     SetupOutputVariable(state,
    4842             :                         "Chilled Water Thermal Storage Final Tank Temperature",
    4843             :                         OutputProcessor::Unit::C,
    4844             :                         this->TankTemp,
    4845             :                         OutputProcessor::SOVTimeStepType::System,
    4846             :                         OutputProcessor::SOVStoreType::Average,
    4847           5 :                         this->Name);
    4848             : 
    4849          10 :     SetupOutputVariable(state,
    4850             :                         "Chilled Water Thermal Storage Tank Heat Gain Rate",
    4851             :                         OutputProcessor::Unit::W,
    4852             :                         this->LossRate,
    4853             :                         OutputProcessor::SOVTimeStepType::System,
    4854             :                         OutputProcessor::SOVStoreType::Average,
    4855           5 :                         this->Name);
    4856          10 :     SetupOutputVariable(state,
    4857             :                         "Chilled Water Thermal Storage Tank Heat Gain Energy",
    4858             :                         OutputProcessor::Unit::J,
    4859             :                         this->LossEnergy,
    4860             :                         OutputProcessor::SOVTimeStepType::System,
    4861             :                         OutputProcessor::SOVStoreType::Summed,
    4862           5 :                         this->Name);
    4863             : 
    4864          10 :     SetupOutputVariable(state,
    4865             :                         "Chilled Water Thermal Storage Use Side Mass Flow Rate",
    4866             :                         OutputProcessor::Unit::kg_s,
    4867             :                         this->UseMassFlowRate,
    4868             :                         OutputProcessor::SOVTimeStepType::System,
    4869             :                         OutputProcessor::SOVStoreType::Average,
    4870           5 :                         this->Name);
    4871             : 
    4872          10 :     SetupOutputVariable(state,
    4873             :                         "Chilled Water Thermal Storage Use Side Inlet Temperature",
    4874             :                         OutputProcessor::Unit::C,
    4875             :                         this->UseInletTemp,
    4876             :                         OutputProcessor::SOVTimeStepType::System,
    4877             :                         OutputProcessor::SOVStoreType::Average,
    4878           5 :                         this->Name);
    4879             : 
    4880          10 :     SetupOutputVariable(state,
    4881             :                         "Chilled Water Thermal Storage Use Side Outlet Temperature",
    4882             :                         OutputProcessor::Unit::C,
    4883             :                         this->UseOutletTemp,
    4884             :                         OutputProcessor::SOVTimeStepType::System,
    4885             :                         OutputProcessor::SOVStoreType::Average,
    4886           5 :                         this->Name);
    4887             : 
    4888          10 :     SetupOutputVariable(state,
    4889             :                         "Chilled Water Thermal Storage Use Side Heat Transfer Rate",
    4890             :                         OutputProcessor::Unit::W,
    4891             :                         this->UseRate,
    4892             :                         OutputProcessor::SOVTimeStepType::System,
    4893             :                         OutputProcessor::SOVStoreType::Average,
    4894           5 :                         this->Name);
    4895          10 :     SetupOutputVariable(state,
    4896             :                         "Chilled Water Thermal Storage Use Side Heat Transfer Energy",
    4897             :                         OutputProcessor::Unit::J,
    4898             :                         this->UseEnergy,
    4899             :                         OutputProcessor::SOVTimeStepType::System,
    4900             :                         OutputProcessor::SOVStoreType::Summed,
    4901           5 :                         this->Name);
    4902             : 
    4903          10 :     SetupOutputVariable(state,
    4904             :                         "Chilled Water Thermal Storage Source Side Mass Flow Rate",
    4905             :                         OutputProcessor::Unit::kg_s,
    4906             :                         this->SourceMassFlowRate,
    4907             :                         OutputProcessor::SOVTimeStepType::System,
    4908             :                         OutputProcessor::SOVStoreType::Average,
    4909           5 :                         this->Name);
    4910             : 
    4911          10 :     SetupOutputVariable(state,
    4912             :                         "Chilled Water Thermal Storage Source Side Inlet Temperature",
    4913             :                         OutputProcessor::Unit::C,
    4914             :                         this->SourceInletTemp,
    4915             :                         OutputProcessor::SOVTimeStepType::System,
    4916             :                         OutputProcessor::SOVStoreType::Average,
    4917           5 :                         this->Name);
    4918             : 
    4919          10 :     SetupOutputVariable(state,
    4920             :                         "Chilled Water Thermal Storage Source Side Outlet Temperature",
    4921             :                         OutputProcessor::Unit::C,
    4922             :                         this->SourceOutletTemp,
    4923             :                         OutputProcessor::SOVTimeStepType::System,
    4924             :                         OutputProcessor::SOVStoreType::Average,
    4925           5 :                         this->Name);
    4926             : 
    4927          10 :     SetupOutputVariable(state,
    4928             :                         "Chilled Water Thermal Storage Source Side Heat Transfer Rate",
    4929             :                         OutputProcessor::Unit::W,
    4930             :                         this->SourceRate,
    4931             :                         OutputProcessor::SOVTimeStepType::System,
    4932             :                         OutputProcessor::SOVStoreType::Average,
    4933           5 :                         this->Name);
    4934          10 :     SetupOutputVariable(state,
    4935             :                         "Chilled Water Thermal Storage Source Side Heat Transfer Energy",
    4936             :                         OutputProcessor::Unit::J,
    4937             :                         this->SourceEnergy,
    4938             :                         OutputProcessor::SOVTimeStepType::System,
    4939             :                         OutputProcessor::SOVStoreType::Summed,
    4940           5 :                         this->Name);
    4941             : 
    4942           5 :     if (this->WaterThermalTankType == DataPlant::PlantEquipmentType::ChilledWaterTankStratified) {
    4943             : 
    4944          14 :         for (int NodeNum = 1; NodeNum <= this->Nodes; ++NodeNum) {
    4945          48 :             SetupOutputVariable(state,
    4946          24 :                                 format("Chilled Water Thermal Storage Temperature Node {}", NodeNum),
    4947             :                                 OutputProcessor::Unit::C,
    4948          12 :                                 this->Node(NodeNum).TempAvg,
    4949             :                                 OutputProcessor::SOVTimeStepType::System,
    4950             :                                 OutputProcessor::SOVStoreType::Average,
    4951             :                                 this->Name);
    4952             :         }
    4953             : 
    4954          14 :         for (int NodeNum = 1; NodeNum <= this->Nodes; ++NodeNum) {
    4955          48 :             SetupOutputVariable(state,
    4956          24 :                                 format("Chilled Water Thermal Storage Final Temperature Node {}", NodeNum),
    4957             :                                 OutputProcessor::Unit::C,
    4958          12 :                                 this->Node(NodeNum).Temp,
    4959             :                                 OutputProcessor::SOVTimeStepType::System,
    4960             :                                 OutputProcessor::SOVStoreType::Average,
    4961             :                                 this->Name);
    4962             :         }
    4963             :     }
    4964             : 
    4965           5 :     if (this->WaterThermalTankType == DataPlant::PlantEquipmentType::ChilledWaterTankStratified) {
    4966             : 
    4967          14 :         for (int NodeNum = 1; NodeNum <= this->Nodes; ++NodeNum) {
    4968             :             static constexpr std::string_view Format_724("Chilled Water Tank Stratified Node Information,{},{:.4T},{:.4T},{:.4T},{},{}\n");
    4969             : 
    4970          60 :             print(state.files.eio,
    4971             :                   Format_724,
    4972             :                   NodeNum,
    4973          12 :                   this->Node(NodeNum).Height,
    4974          12 :                   this->Node(NodeNum).Volume,
    4975          12 :                   this->Node(NodeNum).OffCycLossCoeff,
    4976          12 :                   this->Node(NodeNum).Inlets,
    4977          12 :                   this->Node(NodeNum).Outlets);
    4978             :         }
    4979             :     }
    4980           5 : }
    4981             : 
    4982         193 : void WaterThermalTankData::setupZoneInternalGains(EnergyPlusData &state)
    4983             : {
    4984             :     // set up internal gains if tank is in a thermal zone
    4985         193 :     if (this->AmbientTempZone > 0) {
    4986          80 :         switch (this->WaterThermalTankType) {
    4987          69 :         case DataPlant::PlantEquipmentType::WtrHeaterMixed: {
    4988          69 :             SetupZoneInternalGain(state, this->AmbientTempZone, this->Name, DataHeatBalance::IntGainType::WaterHeaterMixed, &this->AmbientZoneGain);
    4989          69 :             break;
    4990             :         }
    4991           6 :         case DataPlant::PlantEquipmentType::WtrHeaterStratified: {
    4992           6 :             SetupZoneInternalGain(
    4993             :                 state, this->AmbientTempZone, this->Name, DataHeatBalance::IntGainType::WaterHeaterStratified, &this->AmbientZoneGain);
    4994           6 :             break;
    4995             :         }
    4996           3 :         case DataPlant::PlantEquipmentType::ChilledWaterTankMixed: {
    4997           3 :             SetupZoneInternalGain(
    4998             :                 state, this->AmbientTempZone, this->Name, DataHeatBalance::IntGainType::ThermalStorageChilledWaterMixed, &this->AmbientZoneGain);
    4999           3 :             break;
    5000             :         }
    5001           2 :         case DataPlant::PlantEquipmentType::ChilledWaterTankStratified: {
    5002           2 :             SetupZoneInternalGain(
    5003             :                 state, this->AmbientTempZone, this->Name, DataHeatBalance::IntGainType::ThermalStorageChilledWaterStratified, &this->AmbientZoneGain);
    5004           2 :             break;
    5005             :         }
    5006           0 :         default:
    5007           0 :             break;
    5008             :         }
    5009             :     }
    5010         193 : }
    5011             : 
    5012         186 : void WaterThermalTankData::setupWaterHeaterOutputVars(EnergyPlusData &state)
    5013             : {
    5014             : 
    5015             :     // Setup report variables for WaterHeater:Mixed
    5016             :     // CurrentModuleObject='WaterHeater:Mixed'
    5017         372 :     SetupOutputVariable(state,
    5018             :                         "Water Heater Tank Temperature",
    5019             :                         OutputProcessor::Unit::C,
    5020             :                         this->TankTempAvg,
    5021             :                         OutputProcessor::SOVTimeStepType::System,
    5022             :                         OutputProcessor::SOVStoreType::Average,
    5023         186 :                         this->Name);
    5024             : 
    5025         372 :     SetupOutputVariable(state,
    5026             :                         "Water Heater Final Tank Temperature",
    5027             :                         OutputProcessor::Unit::C,
    5028             :                         this->TankTemp,
    5029             :                         OutputProcessor::SOVTimeStepType::System,
    5030             :                         OutputProcessor::SOVStoreType::Average,
    5031         186 :                         this->Name);
    5032             : 
    5033         372 :     SetupOutputVariable(state,
    5034             :                         "Water Heater Heat Loss Rate",
    5035             :                         OutputProcessor::Unit::W,
    5036             :                         this->LossRate,
    5037             :                         OutputProcessor::SOVTimeStepType::System,
    5038             :                         OutputProcessor::SOVStoreType::Average,
    5039         186 :                         this->Name);
    5040         372 :     SetupOutputVariable(state,
    5041             :                         "Water Heater Heat Loss Energy",
    5042             :                         OutputProcessor::Unit::J,
    5043             :                         this->LossEnergy,
    5044             :                         OutputProcessor::SOVTimeStepType::System,
    5045             :                         OutputProcessor::SOVStoreType::Summed,
    5046         186 :                         this->Name);
    5047             : 
    5048         372 :     SetupOutputVariable(state,
    5049             :                         "Water Heater Use Side Mass Flow Rate",
    5050             :                         OutputProcessor::Unit::kg_s,
    5051             :                         this->UseMassFlowRate,
    5052             :                         OutputProcessor::SOVTimeStepType::System,
    5053             :                         OutputProcessor::SOVStoreType::Average,
    5054         186 :                         this->Name);
    5055             : 
    5056         372 :     SetupOutputVariable(state,
    5057             :                         "Water Heater Use Side Inlet Temperature",
    5058             :                         OutputProcessor::Unit::C,
    5059             :                         this->UseInletTemp,
    5060             :                         OutputProcessor::SOVTimeStepType::System,
    5061             :                         OutputProcessor::SOVStoreType::Average,
    5062         186 :                         this->Name);
    5063             : 
    5064         372 :     SetupOutputVariable(state,
    5065             :                         "Water Heater Use Side Outlet Temperature",
    5066             :                         OutputProcessor::Unit::C,
    5067             :                         this->UseOutletTemp,
    5068             :                         OutputProcessor::SOVTimeStepType::System,
    5069             :                         OutputProcessor::SOVStoreType::Average,
    5070         186 :                         this->Name);
    5071             : 
    5072         372 :     SetupOutputVariable(state,
    5073             :                         "Water Heater Use Side Heat Transfer Rate",
    5074             :                         OutputProcessor::Unit::W,
    5075             :                         this->UseRate,
    5076             :                         OutputProcessor::SOVTimeStepType::System,
    5077             :                         OutputProcessor::SOVStoreType::Average,
    5078         186 :                         this->Name);
    5079         372 :     SetupOutputVariable(state,
    5080             :                         "Water Heater Use Side Heat Transfer Energy",
    5081             :                         OutputProcessor::Unit::J,
    5082             :                         this->UseEnergy,
    5083             :                         OutputProcessor::SOVTimeStepType::System,
    5084             :                         OutputProcessor::SOVStoreType::Summed,
    5085         186 :                         this->Name);
    5086             : 
    5087         372 :     SetupOutputVariable(state,
    5088             :                         "Water Heater Source Side Mass Flow Rate",
    5089             :                         OutputProcessor::Unit::kg_s,
    5090             :                         this->SourceMassFlowRate,
    5091             :                         OutputProcessor::SOVTimeStepType::System,
    5092             :                         OutputProcessor::SOVStoreType::Average,
    5093         186 :                         this->Name);
    5094             : 
    5095         372 :     SetupOutputVariable(state,
    5096             :                         "Water Heater Source Side Inlet Temperature",
    5097             :                         OutputProcessor::Unit::C,
    5098             :                         this->SourceInletTemp,
    5099             :                         OutputProcessor::SOVTimeStepType::System,
    5100             :                         OutputProcessor::SOVStoreType::Average,
    5101         186 :                         this->Name);
    5102             : 
    5103         372 :     SetupOutputVariable(state,
    5104             :                         "Water Heater Source Side Outlet Temperature",
    5105             :                         OutputProcessor::Unit::C,
    5106             :                         this->SourceOutletTemp,
    5107             :                         OutputProcessor::SOVTimeStepType::System,
    5108             :                         OutputProcessor::SOVStoreType::Average,
    5109         186 :                         this->Name);
    5110             : 
    5111         372 :     SetupOutputVariable(state,
    5112             :                         "Water Heater Source Side Heat Transfer Rate",
    5113             :                         OutputProcessor::Unit::W,
    5114             :                         this->SourceRate,
    5115             :                         OutputProcessor::SOVTimeStepType::System,
    5116             :                         OutputProcessor::SOVStoreType::Average,
    5117         186 :                         this->Name);
    5118         372 :     SetupOutputVariable(state,
    5119             :                         "Water Heater Source Side Heat Transfer Energy",
    5120             :                         OutputProcessor::Unit::J,
    5121             :                         this->SourceEnergy,
    5122             :                         OutputProcessor::SOVTimeStepType::System,
    5123             :                         OutputProcessor::SOVStoreType::Summed,
    5124             :                         this->Name,
    5125             :                         _,
    5126             :                         "PLANTLOOPHEATINGDEMAND",
    5127             :                         "DHW",
    5128             :                         this->EndUseSubcategoryName,
    5129         186 :                         "Plant");
    5130             : 
    5131         372 :     SetupOutputVariable(state,
    5132             :                         "Water Heater Off Cycle Parasitic Tank Heat Transfer Rate",
    5133             :                         OutputProcessor::Unit::W,
    5134             :                         this->OffCycParaRateToTank,
    5135             :                         OutputProcessor::SOVTimeStepType::System,
    5136             :                         OutputProcessor::SOVStoreType::Average,
    5137         186 :                         this->Name);
    5138         372 :     SetupOutputVariable(state,
    5139             :                         "Water Heater Off Cycle Parasitic Tank Heat Transfer Energy",
    5140             :                         OutputProcessor::Unit::J,
    5141             :                         this->OffCycParaEnergyToTank,
    5142             :                         OutputProcessor::SOVTimeStepType::System,
    5143             :                         OutputProcessor::SOVStoreType::Summed,
    5144         186 :                         this->Name);
    5145             : 
    5146         372 :     SetupOutputVariable(state,
    5147             :                         "Water Heater On Cycle Parasitic Tank Heat Transfer Rate",
    5148             :                         OutputProcessor::Unit::W,
    5149             :                         this->OnCycParaRateToTank,
    5150             :                         OutputProcessor::SOVTimeStepType::System,
    5151             :                         OutputProcessor::SOVStoreType::Average,
    5152         186 :                         this->Name);
    5153         372 :     SetupOutputVariable(state,
    5154             :                         "Water Heater On Cycle Parasitic Tank Heat Transfer Energy",
    5155             :                         OutputProcessor::Unit::J,
    5156             :                         this->OnCycParaEnergyToTank,
    5157             :                         OutputProcessor::SOVTimeStepType::System,
    5158             :                         OutputProcessor::SOVStoreType::Summed,
    5159         186 :                         this->Name);
    5160             : 
    5161         372 :     SetupOutputVariable(state,
    5162             :                         "Water Heater Total Demand Heat Transfer Rate",
    5163             :                         OutputProcessor::Unit::W,
    5164             :                         this->TotalDemandRate,
    5165             :                         OutputProcessor::SOVTimeStepType::System,
    5166             :                         OutputProcessor::SOVStoreType::Average,
    5167         186 :                         this->Name);
    5168         372 :     SetupOutputVariable(state,
    5169             :                         "Water Heater Total Demand Heat Transfer Energy",
    5170             :                         OutputProcessor::Unit::J,
    5171             :                         this->TotalDemandEnergy,
    5172             :                         OutputProcessor::SOVTimeStepType::System,
    5173             :                         OutputProcessor::SOVStoreType::Summed,
    5174         186 :                         this->Name);
    5175             : 
    5176         372 :     SetupOutputVariable(state,
    5177             :                         "Water Heater Heating Rate",
    5178             :                         OutputProcessor::Unit::W,
    5179             :                         this->HeaterRate,
    5180             :                         OutputProcessor::SOVTimeStepType::System,
    5181             :                         OutputProcessor::SOVStoreType::Average,
    5182         186 :                         this->Name);
    5183         372 :     SetupOutputVariable(state,
    5184             :                         "Water Heater Heating Energy",
    5185             :                         OutputProcessor::Unit::J,
    5186             :                         this->HeaterEnergy,
    5187             :                         OutputProcessor::SOVTimeStepType::System,
    5188             :                         OutputProcessor::SOVStoreType::Summed,
    5189         186 :                         this->Name);
    5190             : 
    5191         372 :     SetupOutputVariable(state,
    5192             :                         "Water Heater Unmet Demand Heat Transfer Rate",
    5193             :                         OutputProcessor::Unit::W,
    5194             :                         this->UnmetRate,
    5195             :                         OutputProcessor::SOVTimeStepType::System,
    5196             :                         OutputProcessor::SOVStoreType::Average,
    5197         186 :                         this->Name);
    5198         372 :     SetupOutputVariable(state,
    5199             :                         "Water Heater Unmet Demand Heat Transfer Energy",
    5200             :                         OutputProcessor::Unit::J,
    5201             :                         this->UnmetEnergy,
    5202             :                         OutputProcessor::SOVTimeStepType::System,
    5203             :                         OutputProcessor::SOVStoreType::Summed,
    5204         186 :                         this->Name);
    5205             : 
    5206         372 :     SetupOutputVariable(state,
    5207             :                         "Water Heater Venting Heat Transfer Rate",
    5208             :                         OutputProcessor::Unit::W,
    5209             :                         this->VentRate,
    5210             :                         OutputProcessor::SOVTimeStepType::System,
    5211             :                         OutputProcessor::SOVStoreType::Average,
    5212         186 :                         this->Name);
    5213         372 :     SetupOutputVariable(state,
    5214             :                         "Water Heater Venting Heat Transfer Energy",
    5215             :                         OutputProcessor::Unit::J,
    5216             :                         this->VentEnergy,
    5217             :                         OutputProcessor::SOVTimeStepType::System,
    5218             :                         OutputProcessor::SOVStoreType::Summed,
    5219         186 :                         this->Name);
    5220             : 
    5221         372 :     SetupOutputVariable(state,
    5222             :                         "Water Heater Net Heat Transfer Rate",
    5223             :                         OutputProcessor::Unit::W,
    5224             :                         this->NetHeatTransferRate,
    5225             :                         OutputProcessor::SOVTimeStepType::System,
    5226             :                         OutputProcessor::SOVStoreType::Average,
    5227         186 :                         this->Name);
    5228         372 :     SetupOutputVariable(state,
    5229             :                         "Water Heater Net Heat Transfer Energy",
    5230             :                         OutputProcessor::Unit::J,
    5231             :                         this->NetHeatTransferEnergy,
    5232             :                         OutputProcessor::SOVTimeStepType::System,
    5233             :                         OutputProcessor::SOVStoreType::Summed,
    5234         186 :                         this->Name);
    5235             : 
    5236         372 :     SetupOutputVariable(state,
    5237             :                         "Water Heater Cycle On Count",
    5238             :                         OutputProcessor::Unit::None,
    5239             :                         this->CycleOnCount,
    5240             :                         OutputProcessor::SOVTimeStepType::System,
    5241             :                         OutputProcessor::SOVStoreType::Summed,
    5242         186 :                         this->Name);
    5243         372 :     SetupOutputVariable(state,
    5244             :                         "Water Heater Runtime Fraction",
    5245             :                         OutputProcessor::Unit::None,
    5246             :                         this->RuntimeFraction,
    5247             :                         OutputProcessor::SOVTimeStepType::System,
    5248             :                         OutputProcessor::SOVStoreType::Average,
    5249         186 :                         this->Name);
    5250         372 :     SetupOutputVariable(state,
    5251             :                         "Water Heater Part Load Ratio",
    5252             :                         OutputProcessor::Unit::None,
    5253             :                         this->PartLoadRatio,
    5254             :                         OutputProcessor::SOVTimeStepType::System,
    5255             :                         OutputProcessor::SOVStoreType::Average,
    5256         186 :                         this->Name);
    5257             : 
    5258         558 :     SetupOutputVariable(state,
    5259         372 :                         format("Water Heater {} Rate", FuelTypeNames[static_cast<int>(this->FuelType)]),
    5260             :                         OutputProcessor::Unit::W,
    5261             :                         this->FuelRate,
    5262             :                         OutputProcessor::SOVTimeStepType::System,
    5263             :                         OutputProcessor::SOVStoreType::Average,
    5264             :                         this->Name);
    5265         744 :     SetupOutputVariable(state,
    5266         372 :                         format("Water Heater {} Energy", FuelTypeNames[static_cast<int>(this->FuelType)]),
    5267             :                         OutputProcessor::Unit::J,
    5268             :                         this->FuelEnergy,
    5269             :                         OutputProcessor::SOVTimeStepType::System,
    5270             :                         OutputProcessor::SOVStoreType::Summed,
    5271             :                         this->Name,
    5272             :                         _,
    5273         186 :                         FuelTypeNames[static_cast<int>(this->FuelType)],
    5274             :                         "DHW",
    5275             :                         this->EndUseSubcategoryName,
    5276             :                         "Plant");
    5277             : 
    5278         558 :     SetupOutputVariable(state,
    5279         372 :                         format("Water Heater Off Cycle Parasitic {} Rate", FuelTypeNames[static_cast<int>(this->OffCycParaFuelType)]),
    5280             :                         OutputProcessor::Unit::W,
    5281             :                         this->OffCycParaFuelRate,
    5282             :                         OutputProcessor::SOVTimeStepType::System,
    5283             :                         OutputProcessor::SOVStoreType::Average,
    5284             :                         this->Name);
    5285         744 :     SetupOutputVariable(state,
    5286         372 :                         format("Water Heater Off Cycle Parasitic {} Energy", FuelTypeNames[static_cast<int>(this->OffCycParaFuelType)]),
    5287             :                         OutputProcessor::Unit::J,
    5288             :                         this->OffCycParaFuelEnergy,
    5289             :                         OutputProcessor::SOVTimeStepType::System,
    5290             :                         OutputProcessor::SOVStoreType::Summed,
    5291             :                         this->Name,
    5292             :                         _,
    5293         186 :                         FuelTypeNames[static_cast<int>(this->OffCycParaFuelType)],
    5294             :                         "DHW",
    5295             :                         this->EndUseSubcategoryName,
    5296             :                         "Plant");
    5297             : 
    5298         558 :     SetupOutputVariable(state,
    5299         372 :                         format("Water Heater On Cycle Parasitic {} Rate", FuelTypeNames[static_cast<int>(this->OnCycParaFuelType)]),
    5300             :                         OutputProcessor::Unit::W,
    5301             :                         this->OnCycParaFuelRate,
    5302             :                         OutputProcessor::SOVTimeStepType::System,
    5303             :                         OutputProcessor::SOVStoreType::Average,
    5304             :                         this->Name);
    5305         744 :     SetupOutputVariable(state,
    5306         372 :                         format("Water Heater On Cycle Parasitic {} Energy", FuelTypeNames[static_cast<int>(this->OnCycParaFuelType)]),
    5307             :                         OutputProcessor::Unit::J,
    5308             :                         this->OnCycParaFuelEnergy,
    5309             :                         OutputProcessor::SOVTimeStepType::System,
    5310             :                         OutputProcessor::SOVStoreType::Summed,
    5311             :                         this->Name,
    5312             :                         _,
    5313         186 :                         FuelTypeNames[static_cast<int>(this->OnCycParaFuelType)],
    5314             :                         "DHW",
    5315             :                         this->EndUseSubcategoryName,
    5316             :                         "Plant");
    5317             : 
    5318         372 :     SetupOutputVariable(state,
    5319             :                         "Water Heater Water Volume Flow Rate",
    5320             :                         OutputProcessor::Unit::m3_s,
    5321             :                         this->VolFlowRate,
    5322             :                         OutputProcessor::SOVTimeStepType::System,
    5323             :                         OutputProcessor::SOVStoreType::Average,
    5324         186 :                         this->Name);
    5325         372 :     SetupOutputVariable(state,
    5326             :                         "Water Heater Water Volume",
    5327             :                         OutputProcessor::Unit::m3,
    5328             :                         this->VolumeConsumed,
    5329             :                         OutputProcessor::SOVTimeStepType::System,
    5330             :                         OutputProcessor::SOVStoreType::Summed,
    5331             :                         this->Name,
    5332             :                         _,
    5333             :                         "Water",
    5334             :                         "DHW",
    5335             :                         this->EndUseSubcategoryName,
    5336         186 :                         "Plant");
    5337         372 :     SetupOutputVariable(state,
    5338             :                         "Water Heater Mains Water Volume",
    5339             :                         OutputProcessor::Unit::m3,
    5340             :                         this->VolumeConsumed,
    5341             :                         OutputProcessor::SOVTimeStepType::System,
    5342             :                         OutputProcessor::SOVStoreType::Summed,
    5343             :                         this->Name,
    5344             :                         _,
    5345             :                         "MainsWater",
    5346             :                         "DHW",
    5347             :                         this->EndUseSubcategoryName,
    5348         186 :                         "Plant");
    5349             : 
    5350         186 :     if (this->HeatPumpNum > 0) {
    5351             :         // CurrentModuleObject='WaterHeater:HeatPump:PumpedCondenser'
    5352          23 :         HeatPumpWaterHeaterData &HPWH = state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum);
    5353          46 :         SetupOutputVariable(state,
    5354             :                             "Water Heater Compressor Part Load Ratio",
    5355             :                             OutputProcessor::Unit::None,
    5356             :                             HPWH.HeatingPLR,
    5357             :                             OutputProcessor::SOVTimeStepType::System,
    5358             :                             OutputProcessor::SOVStoreType::Average,
    5359          23 :                             HPWH.Name);
    5360          46 :         SetupOutputVariable(state,
    5361             :                             "Water Heater Off Cycle Ancillary Electricity Rate",
    5362             :                             OutputProcessor::Unit::W,
    5363             :                             HPWH.OffCycParaFuelRate,
    5364             :                             OutputProcessor::SOVTimeStepType::System,
    5365             :                             OutputProcessor::SOVStoreType::Average,
    5366          23 :                             HPWH.Name);
    5367          46 :         SetupOutputVariable(state,
    5368             :                             "Water Heater Off Cycle Ancillary Electricity Energy",
    5369             :                             OutputProcessor::Unit::J,
    5370             :                             HPWH.OffCycParaFuelEnergy,
    5371             :                             OutputProcessor::SOVTimeStepType::System,
    5372             :                             OutputProcessor::SOVStoreType::Summed,
    5373             :                             HPWH.Name,
    5374             :                             _,
    5375             :                             "Electricity",
    5376             :                             "DHW",
    5377             :                             "Water Heater Parasitic",
    5378          23 :                             "Plant");
    5379          46 :         SetupOutputVariable(state,
    5380             :                             "Water Heater On Cycle Ancillary Electricity Rate",
    5381             :                             OutputProcessor::Unit::W,
    5382             :                             HPWH.OnCycParaFuelRate,
    5383             :                             OutputProcessor::SOVTimeStepType::System,
    5384             :                             OutputProcessor::SOVStoreType::Average,
    5385          23 :                             HPWH.Name);
    5386          46 :         SetupOutputVariable(state,
    5387             :                             "Water Heater On Cycle Ancillary Electricity Energy",
    5388             :                             OutputProcessor::Unit::J,
    5389             :                             HPWH.OnCycParaFuelEnergy,
    5390             :                             OutputProcessor::SOVTimeStepType::System,
    5391             :                             OutputProcessor::SOVStoreType::Summed,
    5392             :                             HPWH.Name,
    5393             :                             _,
    5394             :                             "Electricity",
    5395             :                             "DHW",
    5396             :                             "Water Heater Parasitic",
    5397          23 :                             "Plant");
    5398          46 :         SetupOutputVariable(state,
    5399             :                             "Water Heater Heat Pump Control Tank Temperature",
    5400             :                             OutputProcessor::Unit::C,
    5401             :                             HPWH.ControlTempAvg,
    5402             :                             OutputProcessor::SOVTimeStepType::System,
    5403             :                             OutputProcessor::SOVStoreType::Average,
    5404          23 :                             HPWH.Name);
    5405          46 :         SetupOutputVariable(state,
    5406             :                             "Water Heater Heat Pump Control Tank Final Temperature",
    5407             :                             OutputProcessor::Unit::C,
    5408             :                             HPWH.ControlTempFinal,
    5409             :                             OutputProcessor::SOVTimeStepType::System,
    5410             :                             OutputProcessor::SOVStoreType::Average,
    5411          23 :                             HPWH.Name);
    5412             :     }
    5413             : 
    5414         186 :     if (this->DesuperheaterNum > 0) {
    5415             :         // CurrentModuleObject='Coil:WaterHeating:Desuperheater'
    5416          24 :         SetupOutputVariable(state,
    5417             :                             "Water Heater Part Load Ratio",
    5418             :                             OutputProcessor::Unit::None,
    5419           6 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).DesuperheaterPLR,
    5420             :                             OutputProcessor::SOVTimeStepType::System,
    5421             :                             OutputProcessor::SOVStoreType::Average,
    5422          12 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).Name);
    5423          24 :         SetupOutputVariable(state,
    5424             :                             "Water Heater On Cycle Parasitic Electricity Rate",
    5425             :                             OutputProcessor::Unit::W,
    5426           6 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).OnCycParaFuelRate,
    5427             :                             OutputProcessor::SOVTimeStepType::System,
    5428             :                             OutputProcessor::SOVStoreType::Average,
    5429          12 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).Name);
    5430          24 :         SetupOutputVariable(state,
    5431             :                             "Water Heater On Cycle Parasitic Electricity Energy",
    5432             :                             OutputProcessor::Unit::J,
    5433           6 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).OnCycParaFuelEnergy,
    5434             :                             OutputProcessor::SOVTimeStepType::System,
    5435             :                             OutputProcessor::SOVStoreType::Summed,
    5436           6 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).Name,
    5437             :                             _,
    5438             :                             "Electricity",
    5439             :                             "DHW",
    5440             :                             "Water Heater Parasitic",
    5441           6 :                             "Plant");
    5442          24 :         SetupOutputVariable(state,
    5443             :                             "Water Heater Off Cycle Parasitic Electricity Rate",
    5444             :                             OutputProcessor::Unit::W,
    5445           6 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).OffCycParaFuelRate,
    5446             :                             OutputProcessor::SOVTimeStepType::System,
    5447             :                             OutputProcessor::SOVStoreType::Average,
    5448          12 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).Name);
    5449          24 :         SetupOutputVariable(state,
    5450             :                             "Water Heater Off Cycle Parasitic Electricity Energy",
    5451             :                             OutputProcessor::Unit::J,
    5452           6 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).OffCycParaFuelEnergy,
    5453             :                             OutputProcessor::SOVTimeStepType::System,
    5454             :                             OutputProcessor::SOVStoreType::Summed,
    5455           6 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).Name,
    5456             :                             _,
    5457             :                             "Electricity",
    5458             :                             "DHW",
    5459             :                             "Water Heater Parasitic",
    5460           6 :                             "Plant");
    5461          24 :         SetupOutputVariable(state,
    5462             :                             "Water Heater Heat Reclaim Efficiency Modifier Multiplier",
    5463             :                             OutputProcessor::Unit::None,
    5464           6 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).HEffFTempOutput,
    5465             :                             OutputProcessor::SOVTimeStepType::System,
    5466             :                             OutputProcessor::SOVStoreType::Average,
    5467          12 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).Name);
    5468          24 :         SetupOutputVariable(state,
    5469             :                             "Water Heater Pump Electricity Rate",
    5470             :                             OutputProcessor::Unit::W,
    5471           6 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).PumpPower,
    5472             :                             OutputProcessor::SOVTimeStepType::System,
    5473             :                             OutputProcessor::SOVStoreType::Average,
    5474          12 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).Name);
    5475          24 :         SetupOutputVariable(state,
    5476             :                             "Water Heater Pump Electricity Energy",
    5477             :                             OutputProcessor::Unit::J,
    5478           6 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).PumpEnergy,
    5479             :                             OutputProcessor::SOVTimeStepType::System,
    5480             :                             OutputProcessor::SOVStoreType::Summed,
    5481           6 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).Name,
    5482             :                             _,
    5483             :                             "Electricity",
    5484             :                             "DHW",
    5485             :                             "Desuperheater Pump",
    5486           6 :                             "Plant");
    5487          24 :         SetupOutputVariable(state,
    5488             :                             "Water Heater Heating Rate",
    5489             :                             OutputProcessor::Unit::W,
    5490           6 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).HeaterRate,
    5491             :                             OutputProcessor::SOVTimeStepType::System,
    5492             :                             OutputProcessor::SOVStoreType::Average,
    5493          12 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).Name);
    5494          24 :         SetupOutputVariable(state,
    5495             :                             "Water Heater Heating Energy",
    5496             :                             OutputProcessor::Unit::J,
    5497           6 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).HeaterEnergy,
    5498             :                             OutputProcessor::SOVTimeStepType::System,
    5499             :                             OutputProcessor::SOVStoreType::Summed,
    5500           6 :                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).Name,
    5501             :                             _,
    5502             :                             "EnergyTransfer",
    5503             :                             "DHW",
    5504             :                             "Water Heater",
    5505           6 :                             "Plant");
    5506             :     }
    5507             : 
    5508             :     // Setup report variables for WaterHeater:Stratified
    5509             :     // CurrentModuleObject='WaterHeater:Stratified'
    5510         186 :     if (this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
    5511             : 
    5512          32 :         SetupOutputVariable(state,
    5513             :                             "Water Heater Heater 1 Heating Rate",
    5514             :                             OutputProcessor::Unit::W,
    5515             :                             this->HeaterRate1,
    5516             :                             OutputProcessor::SOVTimeStepType::System,
    5517             :                             OutputProcessor::SOVStoreType::Average,
    5518          16 :                             this->Name);
    5519          32 :         SetupOutputVariable(state,
    5520             :                             "Water Heater Heater 2 Heating Rate",
    5521             :                             OutputProcessor::Unit::W,
    5522             :                             this->HeaterRate2,
    5523             :                             OutputProcessor::SOVTimeStepType::System,
    5524             :                             OutputProcessor::SOVStoreType::Average,
    5525          16 :                             this->Name);
    5526             : 
    5527          32 :         SetupOutputVariable(state,
    5528             :                             "Water Heater Heater 1 Heating Energy",
    5529             :                             OutputProcessor::Unit::J,
    5530             :                             this->HeaterEnergy1,
    5531             :                             OutputProcessor::SOVTimeStepType::System,
    5532             :                             OutputProcessor::SOVStoreType::Summed,
    5533          16 :                             this->Name);
    5534          32 :         SetupOutputVariable(state,
    5535             :                             "Water Heater Heater 2 Heating Energy",
    5536             :                             OutputProcessor::Unit::J,
    5537             :                             this->HeaterEnergy2,
    5538             :                             OutputProcessor::SOVTimeStepType::System,
    5539             :                             OutputProcessor::SOVStoreType::Summed,
    5540          16 :                             this->Name);
    5541             : 
    5542          32 :         SetupOutputVariable(state,
    5543             :                             "Water Heater Heater 1 Cycle On Count",
    5544             :                             OutputProcessor::Unit::None,
    5545             :                             this->CycleOnCount1,
    5546             :                             OutputProcessor::SOVTimeStepType::System,
    5547             :                             OutputProcessor::SOVStoreType::Summed,
    5548          16 :                             this->Name);
    5549          32 :         SetupOutputVariable(state,
    5550             :                             "Water Heater Heater 2 Cycle On Count",
    5551             :                             OutputProcessor::Unit::None,
    5552             :                             this->CycleOnCount2,
    5553             :                             OutputProcessor::SOVTimeStepType::System,
    5554             :                             OutputProcessor::SOVStoreType::Summed,
    5555          16 :                             this->Name);
    5556             : 
    5557          32 :         SetupOutputVariable(state,
    5558             :                             "Water Heater Heater 1 Runtime Fraction",
    5559             :                             OutputProcessor::Unit::None,
    5560             :                             this->RuntimeFraction1,
    5561             :                             OutputProcessor::SOVTimeStepType::System,
    5562             :                             OutputProcessor::SOVStoreType::Average,
    5563          16 :                             this->Name);
    5564          32 :         SetupOutputVariable(state,
    5565             :                             "Water Heater Heater 2 Runtime Fraction",
    5566             :                             OutputProcessor::Unit::None,
    5567             :                             this->RuntimeFraction2,
    5568             :                             OutputProcessor::SOVTimeStepType::System,
    5569             :                             OutputProcessor::SOVStoreType::Average,
    5570          16 :                             this->Name);
    5571             : 
    5572         144 :         for (int NodeNum = 1; NodeNum <= this->Nodes; ++NodeNum) {
    5573         512 :             SetupOutputVariable(state,
    5574         256 :                                 format("Water Heater Temperature Node {}", NodeNum),
    5575             :                                 OutputProcessor::Unit::C,
    5576         128 :                                 this->Node(NodeNum).TempAvg,
    5577             :                                 OutputProcessor::SOVTimeStepType::System,
    5578             :                                 OutputProcessor::SOVStoreType::Average,
    5579             :                                 this->Name);
    5580             :         }
    5581             : 
    5582         144 :         for (int NodeNum = 1; NodeNum <= this->Nodes; ++NodeNum) {
    5583         512 :             SetupOutputVariable(state,
    5584         256 :                                 format("Water Heater Final Temperature Node {}", NodeNum),
    5585             :                                 OutputProcessor::Unit::C,
    5586         128 :                                 this->Node(NodeNum).Temp,
    5587             :                                 OutputProcessor::SOVTimeStepType::System,
    5588             :                                 OutputProcessor::SOVStoreType::Average,
    5589             :                                 this->Name);
    5590             :         }
    5591             :     }
    5592             : 
    5593         186 :     if (this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
    5594             : 
    5595         144 :         for (int NodeNum = 1; NodeNum <= this->Nodes; ++NodeNum) {
    5596             :             static constexpr std::string_view Format_723("Water Heater Stratified Node Information,{},{:.4T},{:.4T},{:.3T},{:.4T},{:.4T},{},{}\n");
    5597         896 :             print(state.files.eio,
    5598             :                   Format_723,
    5599             :                   NodeNum,
    5600         128 :                   this->Node(NodeNum).Height,
    5601         128 :                   this->Node(NodeNum).Volume,
    5602         128 :                   this->Node(NodeNum).MaxCapacity,
    5603         128 :                   this->Node(NodeNum).OffCycLossCoeff,
    5604         128 :                   this->Node(NodeNum).OnCycLossCoeff,
    5605         128 :                   this->Node(NodeNum).Inlets,
    5606         128 :                   this->Node(NodeNum).Outlets);
    5607             :         }
    5608             :     }
    5609         186 : }
    5610             : 
    5611           0 : void WaterThermalTankData::ValidatePLFCurve(EnergyPlusData &state, int const CurveIndex, bool &IsValid)
    5612             : {
    5613             : 
    5614             :     // SUBROUTINE INFORMATION:
    5615             :     //       AUTHOR         Peter Graham Ellis
    5616             :     //       DATE WRITTEN   February 2005
    5617             :     //       MODIFIED       na
    5618             :     //       RE-ENGINEERED  na
    5619             : 
    5620             :     // PURPOSE OF THIS SUBROUTINE:
    5621             :     // Validates the Part Load Factor curve by making sure it can never be less than or equal to zero
    5622             :     // over the domain of Part Load Ratio inputs from 0 to 1.
    5623             : 
    5624             :     // METHODOLOGY EMPLOYED:
    5625             :     // Currently can only check 0 and 1.  Need changes in CurveManager to be able to check minimums and
    5626             :     // maximums.
    5627             : 
    5628           0 :     IsValid = true;
    5629             : 
    5630             :     // Check 0 and 1
    5631           0 :     if (Curve::CurveValue(state, CurveIndex, 0.0) <= 0) IsValid = false;
    5632           0 :     if (Curve::CurveValue(state, CurveIndex, 1.0) <= 0) IsValid = false;
    5633           0 : }
    5634             : 
    5635          18 : void WaterThermalTankData::SetupStratifiedNodes(EnergyPlusData &state)
    5636             : {
    5637             : 
    5638             :     // SUBROUTINE INFORMATION:
    5639             :     //       AUTHOR         Peter Graham Ellis
    5640             :     //       DATE WRITTEN   January 2007
    5641             :     //       MODIFIED       na
    5642             :     //       RE-ENGINEERED  na
    5643             : 
    5644             :     // PURPOSE OF THIS SUBROUTINE:
    5645             :     // Sets up node properties based on the tank shape, i.e., vertical cylinder, horizontal cylinder, or other.
    5646             :     // Node height, skin area, vertical conduction area, and loss coefficients are calculated and assigned.
    5647             :     // Heating elements, parasitics, and fluid inlet and outlet flows are assigned according to node height.
    5648             : 
    5649             :     // METHODOLOGY EMPLOYED:
    5650             :     // Tank is divided into nodes of equal mass.  For horizontal cylinders, node heights are calculated using
    5651             :     // the Newton-Raphson iterative method.  For vertical cylinders and other shapes, the node heights are calculated
    5652             :     // using basic geometry.
    5653             : 
    5654             :     static constexpr std::string_view RoutineName("GetWaterThermalTankInput");
    5655             : 
    5656          18 :     constexpr Real64 Tolerance(1.0e-8); // Tolerance for Newton-Raphson solution
    5657          18 :     constexpr Real64 FluidCond(0.6);    // Conductivity of water (W/m-K)
    5658             : 
    5659          18 :     int NumNodes = this->Nodes;
    5660          18 :     this->Node.allocate(NumNodes);
    5661             :     Real64 rho;
    5662          18 :     if ((this->UseSidePlantLoc.loopNum > 0) && allocated(state.dataPlnt->PlantLoop)) {
    5663           0 :         rho = FluidProperties::GetDensityGlycol(state,
    5664           0 :                                                 state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
    5665             :                                                 DataGlobalConstants::InitConvTemp,
    5666           0 :                                                 state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
    5667             :                                                 RoutineName);
    5668             :     } else {
    5669          18 :         rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, DataGlobalConstants::InitConvTemp, this->FluidIndex, RoutineName);
    5670             :     }
    5671             : 
    5672          18 :     Real64 NodeMass = this->Volume * rho / NumNodes;
    5673             :     Real64 TankHeight;
    5674             : 
    5675             :     // Mixing rate set to 50% of the max value for dt = 1.0
    5676          18 :     this->InversionMixingRate = NodeMass * 0.5 * 1.0;
    5677             : 
    5678          18 :     if ((this->Shape == TankShape::VertCylinder) || (this->Shape == TankShape::Other)) {
    5679          18 :         TankHeight = this->Height;
    5680          18 :         Real64 EndArea = this->Volume / TankHeight;
    5681          18 :         Real64 NodeHeight = TankHeight / NumNodes;
    5682          18 :         Real64 CondCoeff = (FluidCond + this->AdditionalCond) * EndArea / NodeHeight;
    5683             : 
    5684             :         Real64 Perimeter_loc;
    5685          18 :         if (this->Shape == TankShape::VertCylinder) {
    5686          18 :             Real64 Radius = std::sqrt(EndArea / DataGlobalConstants::Pi);
    5687          18 :             Perimeter_loc = 2.0 * DataGlobalConstants::Pi * Radius;
    5688             :         } else { // TankShapeOther
    5689           0 :             Perimeter_loc = this->Perimeter;
    5690             :         }
    5691             : 
    5692         158 :         for (int NodeNum = 1; NodeNum <= NumNodes; ++NodeNum) {
    5693         140 :             this->Node(NodeNum).Mass = NodeMass;
    5694         140 :             this->Node(NodeNum).Volume = this->Volume / NumNodes;
    5695         140 :             this->Node(NodeNum).Height = NodeHeight;
    5696         140 :             this->Node(NodeNum).CondCoeffUp = CondCoeff;
    5697         140 :             this->Node(NodeNum).CondCoeffDn = CondCoeff;
    5698             : 
    5699             :             Real64 SkinArea;
    5700         140 :             if ((NodeNum == 1) || (NodeNum == NumNodes)) {
    5701          34 :                 SkinArea = Perimeter_loc * NodeHeight + EndArea;
    5702             :             } else {
    5703         106 :                 SkinArea = Perimeter_loc * NodeHeight;
    5704             :             }
    5705             : 
    5706         140 :             this->Node(NodeNum).OnCycLossCoeff = this->SkinLossCoeff * SkinArea + this->AdditionalLossCoeff(NodeNum);
    5707             : 
    5708         140 :             this->Node(NodeNum).OffCycLossCoeff = this->Node(NodeNum).OnCycLossCoeff + this->OffCycFlueLossCoeff;
    5709             : 
    5710             :         } // NodeNum
    5711             : 
    5712          18 :         this->Node(1).CondCoeffUp = 0.0;
    5713          18 :         this->Node(NumNodes).CondCoeffDn = 0.0;
    5714             : 
    5715             :     } else {                              // Tank%Shape == TankShapeHorizCylinder
    5716           0 :         Real64 TankLength = this->Height; // Height is the length in the axial direction
    5717           0 :         Real64 EndArea = this->Volume / TankLength;
    5718           0 :         Real64 Radius = std::sqrt(EndArea / DataGlobalConstants::Pi);
    5719           0 :         TankHeight = 2.0 * Radius; // Actual vertical height
    5720           0 :         Real64 NodeEndArea = EndArea / NumNodes;
    5721             : 
    5722           0 :         Real64 R = Radius;
    5723           0 :         Real64 H0 = 0.0;
    5724           0 :         Real64 ChordLength = 0.0;
    5725           0 :         for (int NodeNum = 1; NodeNum <= NumNodes; ++NodeNum) {
    5726           0 :             this->Node(NodeNum).Mass = NodeMass;
    5727           0 :             this->Node(NodeNum).Volume = this->Volume / NumNodes;
    5728             :             Real64 H;
    5729           0 :             if (NodeNum == NumNodes) {
    5730           0 :                 H = TankHeight;
    5731             :             } else {
    5732             :                 // Use the Newton-Raphson method to solve the nonlinear algebraic equation for node height
    5733           0 :                 H = H0 + TankHeight / NumNodes; // Initial guess
    5734             : 
    5735             :                 while (true) {
    5736           0 :                     Real64 a = std::sqrt(H);
    5737           0 :                     Real64 b = std::sqrt(2.0 * R - H);
    5738           0 :                     Real64 c = 2.0 * R * R * std::atan(a / b) - (2.0 * R * R - 3.0 * H * R + H * H) * (a / b);
    5739             :                     Real64 c0;
    5740           0 :                     if (H0 > 0.0) {
    5741           0 :                         Real64 a0 = std::sqrt(H0);
    5742           0 :                         Real64 b0 = std::sqrt(2.0 * R - H0);
    5743           0 :                         c0 = 2.0 * R * R * std::atan(a0 / b0) - (2.0 * R * R - 3.0 * H0 * R + H0 * H0) * (a0 / b0);
    5744             :                     } else {
    5745           0 :                         c0 = 0.0;
    5746             :                     }
    5747             : 
    5748           0 :                     Real64 ApproxEndArea = c - c0;          // Area approximated by iteration
    5749           0 :                     Real64 G = ApproxEndArea - NodeEndArea; // G is the function that should converge to zero
    5750             : 
    5751           0 :                     if (std::abs(G) < Tolerance) {
    5752           0 :                         break; // Converged !!!
    5753             :                     } else {
    5754           0 :                         H -= G / (2.0 * a * b); // Calculate next guess:  H = Hprev - G/G'
    5755             :                     }
    5756           0 :                 } // Newton-Raphson
    5757             :             }
    5758             : 
    5759           0 :             this->Node(NodeNum).Height = H - H0;
    5760             : 
    5761           0 :             if (NodeNum > 1) {
    5762           0 :                 Real64 CrossArea = 2.0 * ChordLength * TankLength; // Use old ChordLength from previous node
    5763           0 :                 Real64 CondCoeff = (FluidCond + this->AdditionalCond) * CrossArea / (0.5 * (H - H0) + 0.5 * this->Node(NodeNum - 1).Height);
    5764           0 :                 this->Node(NodeNum - 1).CondCoeffUp = CondCoeff; // Set for previous node
    5765           0 :                 this->Node(NodeNum).CondCoeffDn = CondCoeff;     // Set for this node
    5766             :             }
    5767             : 
    5768           0 :             ChordLength = std::sqrt(2.0 * R * H - H * H); // Calc new ChordLength to be used with next node
    5769             : 
    5770           0 :             Real64 Perimeter_loc = 2.0 * R * (std::acos((R - H) / R) - std::acos((R - H0) / R)); // Segments of circular perimeter
    5771           0 :             Real64 SkinArea = Perimeter_loc * TankLength + 2.0 * NodeEndArea;
    5772             : 
    5773           0 :             this->Node(NodeNum).OnCycLossCoeff = this->SkinLossCoeff * SkinArea + this->AdditionalLossCoeff(NodeNum);
    5774             : 
    5775           0 :             this->Node(NodeNum).OffCycLossCoeff = this->Node(NodeNum).OnCycLossCoeff + this->OffCycFlueLossCoeff;
    5776             :             // Although it doesn't make much sense to have a flue in a horizontal tank, keep it in anyway
    5777             : 
    5778           0 :             H0 = H;
    5779             :         } // NodeNum
    5780             : 
    5781           0 :         this->Node(1).CondCoeffUp = 0.0;
    5782           0 :         this->Node(NumNodes).CondCoeffDn = 0.0;
    5783             :     }
    5784             : 
    5785             :     // Loop through nodes again (from top to bottom this time) and assign heating elements, parasitics, flow inlets/outlets
    5786             :     // according to their vertical heights in the tank
    5787          18 :     Real64 H0 = TankHeight;
    5788         158 :     for (int NodeNum = 1; NodeNum <= NumNodes; ++NodeNum) {
    5789             :         Real64 H;
    5790         140 :         if (NodeNum == NumNodes) {
    5791          18 :             H = -1.0; // Avoids rounding errors and ensures that anything at height 0.0 goes into the bottom node
    5792             :         } else {
    5793         122 :             H = H0 - this->Node(NodeNum).Height;
    5794             :         }
    5795             : 
    5796             :         // Assign heater elements to the nodes at the specified heights
    5797         140 :         if ((this->HeaterHeight1 <= H0) && (this->HeaterHeight1 > H)) {
    5798             :             //       sensor node will not get set if user enters 0 for this heater capacity
    5799             :             //       (Tank%MaxCapacity > 0.0d0)) THEN
    5800          18 :             this->HeaterNode1 = NodeNum;
    5801          18 :             this->Node(NodeNum).MaxCapacity = this->MaxCapacity;
    5802             :         }
    5803             : 
    5804         140 :         if ((this->HeaterHeight2 <= H0) && (this->HeaterHeight2 > H)) {
    5805             :             //       sensor node will not get set if user enters 0 for this heater capacity
    5806             :             //      .AND. (Tank%MaxCapacity2 > 0.0d0)) THEN
    5807          18 :             this->HeaterNode2 = NodeNum;
    5808             : 
    5809          18 :             if ((NodeNum == this->HeaterNode1) && (this->StratifiedControlMode == PriorityControlMode::Simultaneous)) {
    5810           0 :                 this->Node(NodeNum).MaxCapacity += this->MaxCapacity2;
    5811             :             } else {
    5812          18 :                 this->Node(NodeNum).MaxCapacity = this->MaxCapacity2;
    5813             :             }
    5814             :         }
    5815             : 
    5816             :         // Assign parasitic heat gains to the nodes at the specified heights
    5817         140 :         if ((this->OffCycParaHeight <= H0) && (this->OffCycParaHeight > H)) {
    5818          18 :             this->Node(NodeNum).OffCycParaLoad = this->OffCycParaFracToTank * this->OffCycParaLoad;
    5819             :         }
    5820             : 
    5821         140 :         if ((this->OnCycParaHeight <= H0) && (this->OnCycParaHeight > H)) {
    5822          18 :             this->Node(NodeNum).OnCycParaLoad = this->OnCycParaFracToTank * this->OnCycParaLoad;
    5823             :         }
    5824             : 
    5825             :         // Assign inlets and outlets to the nodes at the specified heights
    5826         140 :         if ((this->UseInletHeight <= H0) && (this->UseInletHeight > H)) {
    5827          18 :             this->UseInletStratNode = NodeNum;
    5828             : 
    5829          18 :             if ((this->UseInletNode > 0) || (this->MassFlowRateMax > 0.0)) ++this->Node(NodeNum).Inlets;
    5830             :         }
    5831             : 
    5832         140 :         if ((this->UseOutletHeight <= H0) && (this->UseOutletHeight > H)) {
    5833          18 :             this->UseOutletStratNode = NodeNum;
    5834             : 
    5835          18 :             if ((this->UseOutletNode > 0) || (this->MassFlowRateMax > 0.0)) ++this->Node(NodeNum).Outlets;
    5836             :         }
    5837             : 
    5838         140 :         if ((this->SourceInletHeight <= H0) && (this->SourceInletHeight > H) && (this->SourceInletNode > 0)) {
    5839             : 
    5840          11 :             this->SourceInletStratNode = NodeNum;
    5841          11 :             ++this->Node(NodeNum).Inlets;
    5842             :         }
    5843             : 
    5844         140 :         if ((this->SourceOutletHeight <= H0) && (this->SourceOutletHeight > H) && (this->SourceOutletNode > 0)) {
    5845             : 
    5846          11 :             this->SourceOutletStratNode = NodeNum;
    5847          11 :             ++this->Node(NodeNum).Outlets;
    5848             :         }
    5849             : 
    5850         140 :         H0 = H;
    5851             :     } // NodeNum
    5852          18 : }
    5853             : 
    5854     6113834 : void WaterThermalTankData::initialize(EnergyPlusData &state, bool const FirstHVACIteration)
    5855             : {
    5856             : 
    5857             :     // SUBROUTINE INFORMATION:
    5858             :     //       AUTHOR         Peter Graham Ellis
    5859             :     //       DATE WRITTEN   February 2004
    5860             :     //       MODIFIED       FSEC, July 2005
    5861             :     //                      Brent Griffith, October 2007 indirect fired water heater
    5862             :     //                        B. Shen 12/2014, add air-source variable-speed heat pump water heating
    5863             :     //       RE-ENGINEERED  na
    5864             : 
    5865             :     // PURPOSE OF THIS SUBROUTINE:
    5866             :     // Initialize the water heater, heat pump water heater, or desuperheater heating coil objects during the simulation.
    5867             :     // determine flow rates thru use side and source side plant connections (if any)
    5868             : 
    5869             :     // METHODOLOGY EMPLOYED:
    5870             :     // Inlet and outlet nodes are initialized.  Scheduled values are retrieved for the current timestep.
    5871             : 
    5872     6113834 :     auto &ZoneEqSizing(state.dataSize->ZoneEqSizing);
    5873             : 
    5874             :     static constexpr std::string_view RoutineName("InitWaterThermalTank");
    5875             :     static constexpr std::string_view GetWaterThermalTankInput("GetWaterThermalTankInput");
    5876             :     static constexpr std::string_view SizeTankForDemand("SizeTankForDemandSide");
    5877             : 
    5878     6113834 :     if (this->scanPlantLoopsFlag && allocated(state.dataPlnt->PlantLoop)) {
    5879         191 :         if ((this->UseInletNode > 0) && (this->HeatPumpNum == 0)) {
    5880         113 :             bool errFlag = false;
    5881         113 :             PlantUtilities::ScanPlantLoopsForObject(
    5882             :                 state, this->Name, this->WaterThermalTankType, this->UseSidePlantLoc, errFlag, _, _, _, this->UseInletNode, _);
    5883         113 :             if (errFlag) {
    5884           0 :                 ShowFatalError(state, "InitWaterThermalTank: Program terminated due to previous condition(s).");
    5885             :             }
    5886             :         }
    5887         191 :         if ((this->UseInletNode > 0) && (this->HeatPumpNum > 0)) {
    5888             :             // this is a heat pump water heater, need a separate block because TypeOf_HeatPumpWtrHeater shows up on Branch
    5889             :             //  (input should probably have been the associated tank )
    5890          10 :             bool errFlag = false;
    5891          30 :             PlantUtilities::ScanPlantLoopsForObject(state,
    5892          10 :                                                     state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).Name,
    5893          10 :                                                     state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).HPWHType,
    5894             :                                                     this->UseSidePlantLoc,
    5895             :                                                     errFlag,
    5896             :                                                     _,
    5897             :                                                     _,
    5898             :                                                     _,
    5899             :                                                     this->UseInletNode,
    5900             :                                                     _);
    5901          10 :             if (errFlag) {
    5902           0 :                 ShowFatalError(state, "InitWaterThermalTank: Program terminated due to previous condition(s).");
    5903             :             }
    5904             :         }
    5905         191 :         if ((this->SourceInletNode > 0) && (this->DesuperheaterNum == 0) && (this->HeatPumpNum == 0)) {
    5906          20 :             bool errFlag = false;
    5907          20 :             PlantUtilities::ScanPlantLoopsForObject(
    5908             :                 state, this->Name, this->WaterThermalTankType, this->SrcSidePlantLoc, errFlag, _, _, _, this->SourceInletNode, _);
    5909          20 :             if (this->UseInletNode > 0) {
    5910          20 :                 PlantUtilities::InterConnectTwoPlantLoopSides(state, this->UseSidePlantLoc, this->SrcSidePlantLoc, this->WaterThermalTankType, true);
    5911             :             }
    5912          20 :             if (errFlag) {
    5913           0 :                 ShowFatalError(state, "InitWaterThermalTank: Program terminated due to previous condition(s).");
    5914             :             }
    5915             :         }
    5916         191 :         this->scanPlantLoopsFlag = false;
    5917             :     }
    5918             : 
    5919     6113834 :     if (this->SetLoopIndexFlag && allocated(state.dataPlnt->PlantLoop)) {
    5920        1366 :         if ((this->UseInletNode > 0) && (this->HeatPumpNum == 0)) {
    5921        2576 :             Real64 rho = FluidProperties::GetDensityGlycol(state,
    5922        1288 :                                                            state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
    5923             :                                                            DataGlobalConstants::InitConvTemp,
    5924        1288 :                                                            state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
    5925        1288 :                                                            GetWaterThermalTankInput);
    5926        1288 :             this->PlantUseMassFlowRateMax = this->UseDesignVolFlowRate * rho;
    5927        1288 :             this->Mass = this->Volume * rho;
    5928        1288 :             this->UseSidePlantSizNum = state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).PlantSizNum;
    5929        1288 :             if ((this->UseDesignVolFlowRateWasAutoSized) && (this->UseSidePlantSizNum == 0)) {
    5930           0 :                 ShowSevereError(state, "InitWaterThermalTank: Did not find Sizing:Plant object for use side of plant thermal tank = " + this->Name);
    5931           0 :                 ShowFatalError(state, "InitWaterThermalTank: Program terminated due to previous condition(s).");
    5932             :             }
    5933             :         }
    5934        1366 :         if ((this->UseInletNode > 0) && (this->HeatPumpNum > 0)) {
    5935          20 :             Real64 rho = FluidProperties::GetDensityGlycol(state,
    5936          10 :                                                            state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
    5937             :                                                            DataGlobalConstants::InitConvTemp,
    5938          10 :                                                            state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
    5939          10 :                                                            GetWaterThermalTankInput);
    5940          10 :             this->PlantUseMassFlowRateMax = this->UseDesignVolFlowRate * rho;
    5941          10 :             this->Mass = this->Volume * rho;
    5942          10 :             this->UseSidePlantSizNum = state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).PlantSizNum;
    5943          10 :             if ((this->UseDesignVolFlowRateWasAutoSized) && (this->UseSidePlantSizNum == 0)) {
    5944           0 :                 ShowSevereError(state, "InitWaterThermalTank: Did not find Sizing:Plant object for use side of plant thermal tank = " + this->Name);
    5945           0 :                 ShowFatalError(state, "InitWaterThermalTank: Program terminated due to previous condition(s).");
    5946             :             }
    5947             :         }
    5948        1366 :         if ((this->SourceInletNode > 0) && (this->DesuperheaterNum == 0) && (this->HeatPumpNum == 0)) {
    5949         720 :             Real64 rho = FluidProperties::GetDensityGlycol(state,
    5950         360 :                                                            state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidName,
    5951             :                                                            DataGlobalConstants::InitConvTemp,
    5952         360 :                                                            state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidIndex,
    5953         360 :                                                            GetWaterThermalTankInput);
    5954         360 :             this->PlantSourceMassFlowRateMax = this->SourceDesignVolFlowRate * rho;
    5955         360 :             this->SourceSidePlantSizNum = state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).PlantSizNum;
    5956         360 :             if ((this->SourceDesignVolFlowRateWasAutoSized) && (this->SourceSidePlantSizNum == 0)) {
    5957           0 :                 ShowSevereError(state,
    5958           0 :                                 "InitWaterThermalTank: Did not find Sizing:Plant object for source side of plant thermal tank = " + this->Name);
    5959           0 :                 ShowFatalError(state, "InitWaterThermalTank: Program terminated due to previous condition(s).");
    5960             :             }
    5961             :         }
    5962        1366 :         if (((this->SourceInletNode > 0) && (this->DesuperheaterNum > 0)) || (this->HeatPumpNum > 0)) {
    5963          29 :             this->SetLoopIndexFlag = false;
    5964             :         }
    5965        1366 :         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) this->SetLoopIndexFlag = false;
    5966        1366 :         if (this->StandAlone) {
    5967          49 :             this->SizeStandAloneWaterHeater(state);
    5968          49 :             this->SetLoopIndexFlag = false;
    5969             :         }
    5970     6112468 :     } else if (this->SetLoopIndexFlag && !state.dataGlobal->AnyPlantInModel) {
    5971           0 :         if (this->StandAlone) {
    5972           0 :             this->SizeStandAloneWaterHeater(state);
    5973             :         }
    5974           0 :         this->SetLoopIndexFlag = false;
    5975             :     }
    5976             : 
    5977     6113834 :     if (state.dataGlobal->BeginEnvrnFlag && this->MyEnvrnFlag && !this->SetLoopIndexFlag) {
    5978             : 
    5979       45861 :         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    5980             : 
    5981       44955 :             if (this->ControlType == HeaterControlMode::Cycle) {
    5982       44437 :                 this->MinCapacity = this->MaxCapacity;
    5983             :             }
    5984             : 
    5985             :             // check for sizing issues that model can not support
    5986             : 
    5987             :             // if stratified tank model, ensure that nominal change over rate is greater than one minute, avoid numerical problems.
    5988             : 
    5989       87584 :             if ((this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) ||
    5990       42629 :                 (this->WaterThermalTankType == DataPlant::PlantEquipmentType::ChilledWaterTankStratified)) {
    5991        3004 :                 Real64 MaxSideVolFlow = max(this->UseDesignVolFlowRate, this->SourceDesignVolFlowRate);
    5992             : 
    5993        3004 :                 if (MaxSideVolFlow > 0.0) { // protect div by zero
    5994        2827 :                     Real64 TankChangeRateScale = this->Volume / MaxSideVolFlow;
    5995        2827 :                     if (TankChangeRateScale < 60.0) { // nominal change over in less than one minute
    5996           0 :                         ShowSevereError(state, "InitWaterThermalTank: Detected problem for stratified tank model.  Model cannot be applied.");
    5997           0 :                         ShowContinueError(state, "Occurs for stratified tank name = " + this->Name);
    5998           0 :                         ShowContinueError(state, format("Tank volume = {:.4R} [m3]", this->Volume));
    5999           0 :                         ShowContinueError(state, format("Tank use side volume flow rate = {:.4R} [m3/s]", this->UseDesignVolFlowRate));
    6000           0 :                         ShowContinueError(state, format("Tank source side volume flow rate = {:.4R} [m3/s]", this->SourceDesignVolFlowRate));
    6001           0 :                         ShowContinueError(state, format("Nominal tank change over rate = {:.2R} [s]", TankChangeRateScale));
    6002           0 :                         ShowContinueError(
    6003             :                             state, "Change over rate is too fast, increase tank volume, decrease connection flow rates or use mixed tank model");
    6004             : 
    6005           0 :                         ShowFatalError(state, "InitWaterThermalTank: Simulation halted because of sizing problem in stratified tank model.");
    6006             :                     }
    6007             :                 }
    6008             :             }
    6009             :         }
    6010             : 
    6011             :         // Clear node initial conditions
    6012       45861 :         if (this->UseInletNode > 0 && this->UseOutletNode > 0) {
    6013       44366 :             state.dataLoopNodes->Node(this->UseInletNode).Temp = 0.0;
    6014       88732 :             Real64 rho = FluidProperties::GetDensityGlycol(state,
    6015       44366 :                                                            state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
    6016             :                                                            DataGlobalConstants::InitConvTemp,
    6017       44366 :                                                            state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
    6018       44366 :                                                            GetWaterThermalTankInput);
    6019       44366 :             this->MassFlowRateMin = this->VolFlowRateMin * rho;
    6020       44366 :             this->PlantUseMassFlowRateMax = this->UseDesignVolFlowRate * rho;
    6021       44366 :             PlantUtilities::InitComponentNodes(state, this->MassFlowRateMin, this->PlantUseMassFlowRateMax, this->UseInletNode, this->UseOutletNode);
    6022       44366 :             this->UseOutletTemp = 0.0;
    6023       44366 :             this->UseMassFlowRate = 0.0;
    6024       44366 :             this->SavedUseOutletTemp = 0.0;
    6025             : 
    6026       44366 :             this->Mass = this->Volume * rho;
    6027       44366 :             this->UseBranchControlType = DataPlant::CompData::getPlantComponent(state, this->UseSidePlantLoc).FlowCtrl;
    6028             :         }
    6029             : 
    6030       45861 :         if ((this->SourceInletNode > 0) && (this->DesuperheaterNum == 0) && (this->HeatPumpNum == 0)) {
    6031       29320 :             Real64 rho = FluidProperties::GetDensityGlycol(state,
    6032       14660 :                                                            state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidName,
    6033             :                                                            DataGlobalConstants::InitConvTemp,
    6034       14660 :                                                            state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidIndex,
    6035       14660 :                                                            GetWaterThermalTankInput);
    6036       14660 :             this->PlantSourceMassFlowRateMax = this->SourceDesignVolFlowRate * rho;
    6037       14660 :             PlantUtilities::InitComponentNodes(state, 0.0, this->PlantSourceMassFlowRateMax, this->SourceInletNode, this->SourceOutletNode);
    6038             : 
    6039       14660 :             this->SourceOutletTemp = 0.0;
    6040       14660 :             this->SourceMassFlowRate = 0.0;
    6041       14660 :             this->SavedSourceOutletTemp = 0.0;
    6042             : 
    6043       14660 :             this->SourceBranchControlType = DataPlant::CompData::getPlantComponent(state, this->SrcSidePlantLoc).FlowCtrl;
    6044             :         }
    6045             : 
    6046       45861 :         if ((this->SourceInletNode > 0) && ((this->DesuperheaterNum > 0) || (this->HeatPumpNum > 0))) {
    6047        2412 :             state.dataLoopNodes->Node(this->SourceInletNode).Temp = 0.0;
    6048        2412 :             this->SourceOutletTemp = 0.0;
    6049        2412 :             this->SourceMassFlowRate = 0.0;
    6050        2412 :             this->SavedSourceOutletTemp = 0.0;
    6051             :             Real64 rho =
    6052        2412 :                 FluidProperties::GetDensityGlycol(state, fluidNameWater, DataGlobalConstants::InitConvTemp, this->FluidIndex, SizeTankForDemand);
    6053        2412 :             this->PlantSourceMassFlowRateMax = this->SourceDesignVolFlowRate * rho;
    6054             :         }
    6055             : 
    6056             :         // Initialize tank temperature to setpoint of first hour of warm up period
    6057             :         // (use HPWH or Desuperheater heating coil set point if applicable)
    6058             :         int SchIndex;
    6059       45861 :         if (this->HeatPumpNum > 0) {
    6060        2278 :             state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).Mode = TankOperatingMode::Floating;
    6061        2278 :             state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).SaveMode = TankOperatingMode::Floating;
    6062        2278 :             state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).SaveWHMode = TankOperatingMode::Floating;
    6063        2278 :             SchIndex = state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).SetPointTempSchedule;
    6064       43583 :         } else if (this->DesuperheaterNum > 0) {
    6065         134 :             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).Mode = TankOperatingMode::Floating;
    6066         134 :             SchIndex = state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).SetPointTempSchedule;
    6067             :         } else {
    6068       43449 :             SchIndex = this->SetPointTempSchedule;
    6069             :         }
    6070             : 
    6071       45861 :         if (SchIndex > 0) {
    6072       45861 :             this->TankTemp = ScheduleManager::GetCurrentScheduleValue(state, SchIndex);
    6073       45861 :             this->SavedTankTemp = this->TankTemp;
    6074             : 
    6075       45861 :             if (this->Nodes > 0) {
    6076       27013 :                 for (auto &e : this->Node) {
    6077       23926 :                     e.Temp = e.SavedTemp = this->TankTemp;
    6078             :                 }
    6079             :             }
    6080             :         } else {
    6081           0 :             this->TankTemp = 20.0;
    6082           0 :             this->SavedTankTemp = this->TankTemp;
    6083             : 
    6084           0 :             if (this->Nodes > 0) {
    6085           0 :                 for (auto &e : this->Node) {
    6086           0 :                     e.Temp = e.SavedTemp = this->TankTemp;
    6087             :                 }
    6088             :             }
    6089             :         }
    6090       45861 :         this->SourceOutletTemp = this->SavedTankTemp;
    6091       45861 :         this->SavedSourceOutletTemp = this->SavedTankTemp;
    6092       45861 :         this->UseOutletTemp = this->SavedTankTemp;
    6093       45861 :         this->SavedUseOutletTemp = this->SavedTankTemp;
    6094       45861 :         this->TankTempAvg = this->SavedTankTemp;
    6095             : 
    6096       45861 :         this->SavedHeaterOn1 = false;
    6097       45861 :         this->SavedHeaterOn2 = false;
    6098       45861 :         this->Mode = TankOperatingMode::Floating;
    6099       45861 :         this->SavedMode = TankOperatingMode::Floating;
    6100       45861 :         this->FirstRecoveryDone = false;
    6101       45861 :         this->FirstRecoveryFuel = 0.0;
    6102       45861 :         this->UnmetEnergy = 0.0;
    6103       45861 :         this->LossEnergy = 0.0;
    6104       45861 :         this->FlueLossEnergy = 0.0;
    6105       45861 :         this->UseEnergy = 0.0;
    6106       45861 :         this->TotalDemandEnergy = 0.0;
    6107       45861 :         this->SourceEnergy = 0.0;
    6108       45861 :         this->HeaterEnergy = 0.0;
    6109       45861 :         this->HeaterEnergy1 = 0.0;
    6110       45861 :         this->HeaterEnergy2 = 0.0;
    6111       45861 :         this->FuelEnergy = 0.0;
    6112       45861 :         this->FuelEnergy1 = 0.0;
    6113       45861 :         this->FuelEnergy2 = 0.0;
    6114       45861 :         this->VentEnergy = 0.0;
    6115       45861 :         this->OffCycParaFuelEnergy = 0.0;
    6116       45861 :         this->OffCycParaEnergyToTank = 0.0;
    6117       45861 :         this->OnCycParaFuelEnergy = 0.0;
    6118       45861 :         this->OnCycParaEnergyToTank = 0.0;
    6119       45861 :         this->NetHeatTransferEnergy = 0.0;
    6120             :     }
    6121             : 
    6122     6113834 :     if (!state.dataGlobal->BeginEnvrnFlag) this->MyEnvrnFlag = true;
    6123             : 
    6124     6113834 :     if (this->WarmupFlag && (!state.dataGlobal->WarmupFlag)) {
    6125             :         // reInitialize tank temperature to setpoint of first hour (use HPWH or Desuperheater heating coil set point if applicable)
    6126             :         // BG's interpretation here is that its better to reset initial condition to setpoint once warm up is over.
    6127             :         // (otherwise with a dynamic storage model it is difficult for the user to see the initial performance if it isn't periodic.)
    6128             :         int SchIndex;
    6129         427 :         if (this->HeatPumpNum > 0) {
    6130          46 :             state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).Mode = TankOperatingMode::Floating;
    6131          46 :             SchIndex = state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).SetPointTempSchedule;
    6132         381 :         } else if (this->DesuperheaterNum > 0) {
    6133          12 :             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).Mode = TankOperatingMode::Floating;
    6134          12 :             SchIndex = state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).SetPointTempSchedule;
    6135             :         } else {
    6136         369 :             SchIndex = this->SetPointTempSchedule;
    6137             :         }
    6138             : 
    6139         427 :         if (SchIndex > 0) {
    6140         427 :             this->TankTemp = ScheduleManager::GetCurrentScheduleValue(state, SchIndex);
    6141         427 :             this->SavedTankTemp = this->TankTemp;
    6142             : 
    6143         427 :             if (this->Nodes > 0) {
    6144         316 :                 for (auto &e : this->Node) {
    6145         280 :                     e.Temp = e.SavedTemp = this->TankTemp;
    6146             :                 }
    6147             :             }
    6148             :         } else {
    6149           0 :             this->TankTemp = 20.0;
    6150           0 :             this->SavedTankTemp = this->TankTemp;
    6151             : 
    6152           0 :             if (this->Nodes > 0) {
    6153           0 :                 for (auto &e : this->Node) {
    6154           0 :                     e.Temp = e.SavedTemp = this->TankTemp;
    6155             :                 }
    6156             :             }
    6157             :         }
    6158         427 :         this->SourceOutletTemp = this->SavedTankTemp;
    6159         427 :         this->SavedSourceOutletTemp = this->SavedTankTemp;
    6160         427 :         this->UseOutletTemp = this->SavedTankTemp;
    6161         427 :         this->SavedUseOutletTemp = this->SavedTankTemp;
    6162         427 :         this->SavedHeaterOn1 = false;
    6163         427 :         this->SavedHeaterOn2 = false;
    6164         427 :         this->Mode = TankOperatingMode::Floating;
    6165         427 :         this->SavedMode = TankOperatingMode::Floating;
    6166         427 :         this->WarmupFlag = false;
    6167             :     }
    6168     6113834 :     if (state.dataGlobal->WarmupFlag) this->WarmupFlag = true;
    6169             : 
    6170     6113834 :     if (FirstHVACIteration) {
    6171             :         // Get all scheduled values
    6172     2944790 :         int SchIndex = this->SetPointTempSchedule;
    6173     2944790 :         this->SetPointTemp = ScheduleManager::GetCurrentScheduleValue(state, SchIndex);
    6174             : 
    6175     2944790 :         if (!this->IsChilledWaterTank) {
    6176     2700717 :             if (this->SetPointTemp > this->TankTempLimit) {
    6177             :                 // Setpoint temperature scheduled higher than maximum tank temperature limit
    6178           0 :                 this->SetPointTemp = this->TankTempLimit - 1.0;
    6179             : 
    6180           0 :                 if (this->ShowSetPointWarning) {
    6181           0 :                     ShowSevereError(state,
    6182           0 :                                     "Water heater = " + this->Name +
    6183             :                                         ":  Water heater tank set point temperature is greater than the maximum tank temperature limit.");
    6184           0 :                     ShowContinueErrorTimeStamp(state,
    6185           0 :                                                format("Water heater tank set point temperature is reset to Tank Temperature Limit minus 1 C "
    6186             :                                                       "({:.2T}) and simulation continues.",
    6187           0 :                                                       this->SetPointTemp));
    6188           0 :                     this->ShowSetPointWarning = false;
    6189             :                 }
    6190             :             }
    6191             :         } else {
    6192      244073 :             if (this->SetPointTemp < this->TankTempLimit) {
    6193             :                 // Setpoint temperature scheduled lower than minimum tank temperature limit
    6194           0 :                 this->SetPointTemp = this->TankTempLimit + 1.0;
    6195             : 
    6196           0 :                 if (this->ShowSetPointWarning) {
    6197           0 :                     ShowSevereError(state,
    6198           0 :                                     "Chilled Water Tank = " + this->Name +
    6199             :                                         ":  Water heater tank set point temperature is lower than the minimum tank temperature limit.");
    6200           0 :                     ShowContinueErrorTimeStamp(state,
    6201           0 :                                                format("Chilled water tank set point temperature is reset to Tank Temperature Limit plus 1 C "
    6202             :                                                       "({:.2T}) and simulation continues.",
    6203           0 :                                                       this->SetPointTemp));
    6204           0 :                     this->ShowSetPointWarning = false;
    6205             :                 }
    6206             :             }
    6207             :         }
    6208             : 
    6209     2944790 :         SchIndex = this->SetPointTempSchedule2;
    6210     2944790 :         if (SchIndex > 0) {
    6211      191928 :             this->SetPointTemp2 = ScheduleManager::GetCurrentScheduleValue(state, SchIndex);
    6212             :         }
    6213             : 
    6214     2944790 :         switch (this->AmbientTempIndicator) {
    6215     2135232 :         case WTTAmbientTemp::Schedule: {
    6216     2135232 :             SchIndex = this->AmbientTempSchedule;
    6217     2135232 :             this->AmbientTemp = ScheduleManager::GetCurrentScheduleValue(state, SchIndex);
    6218             : 
    6219     2135232 :             break;
    6220             :         }
    6221      674980 :         case WTTAmbientTemp::TempZone: {
    6222      674980 :             this->AmbientTemp = state.dataZoneTempPredictorCorrector->zoneHeatBalance(this->AmbientTempZone).MAT;
    6223             : 
    6224      674980 :             break;
    6225             :         }
    6226      134578 :         case WTTAmbientTemp::OutsideAir: {
    6227      134578 :             this->AmbientTemp = state.dataLoopNodes->Node(this->AmbientTempOutsideAirNode).Temp;
    6228      134578 :             break;
    6229             :         }
    6230           0 :         default:
    6231           0 :             break;
    6232             :         }
    6233             : 
    6234     2944790 :         if (this->UseInletNode == 0) { // Stand-alone operation
    6235             : 
    6236      224357 :             SchIndex = this->UseInletTempSchedule;
    6237      224357 :             if (SchIndex > 0) {
    6238       80747 :                 this->UseInletTemp = ScheduleManager::GetCurrentScheduleValue(state, SchIndex);
    6239             :             } else {
    6240      143610 :                 this->UseInletTemp = state.dataEnvrn->WaterMainsTemp;
    6241             :             }
    6242             : 
    6243      224357 :             SchIndex = this->FlowRateSchedule;
    6244      224357 :             if (SchIndex > 0) {
    6245      224357 :                 this->UseMassFlowRate = ScheduleManager::GetCurrentScheduleValue(state, SchIndex) * this->MassFlowRateMax;
    6246             : 
    6247      224357 :                 this->VolFlowRate = this->UseMassFlowRate / Psychrometrics::RhoH2O(DataGlobalConstants::InitConvTemp);
    6248             :             } else {
    6249           0 :                 this->UseMassFlowRate = this->MassFlowRateMax;
    6250           0 :                 this->VolFlowRate = this->UseMassFlowRate / Psychrometrics::RhoH2O(DataGlobalConstants::InitConvTemp);
    6251             :             }
    6252             :         }
    6253             : 
    6254     2944790 :         if (this->HeatPumpNum > 0) {
    6255      323309 :             state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).SetPointTemp =
    6256      323309 :                 ScheduleManager::GetCurrentScheduleValue(state, state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).SetPointTempSchedule);
    6257      323309 :             if (state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).SetPointTemp >= this->TankTempLimit) {
    6258             :                 // HP setpoint temperature scheduled equal to or higher than tank temperature limit
    6259           0 :                 state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).SetPointTemp = this->TankTempLimit - 1.0;
    6260             : 
    6261           0 :                 if (state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).ShowSetPointWarning) {
    6262           0 :                     ShowSevereError(
    6263             :                         state,
    6264           0 :                         "Heat Pump Water Heater = " + state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).Name +
    6265             :                             ":  Heat Pump water heater set point temperature is equal to or greater than the maximum tank temperature limit.");
    6266           0 :                     ShowContinueErrorTimeStamp(state,
    6267           0 :                                                format("Heat Pump water heater tank set point temperature is reset to Tank Temperature Limit "
    6268             :                                                       "minus 1 C ({:.2T}) and simulation continues.",
    6269           0 :                                                       state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).SetPointTemp));
    6270           0 :                     state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).ShowSetPointWarning = false;
    6271             :                 }
    6272             :             }
    6273             :         }
    6274             : 
    6275     2944790 :         if (this->DesuperheaterNum > 0) {
    6276       15025 :             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).SetPointTemp = ScheduleManager::GetCurrentScheduleValue(
    6277       15025 :                 state, state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).SetPointTempSchedule);
    6278             :         }
    6279             : 
    6280             :     } // first HVAC Iteration
    6281             : 
    6282     6113834 :     if (this->UseInletNode > 0 && !this->SetLoopIndexFlag) { // setup mass flows for plant connections
    6283             :         Real64 DeadBandTemp;
    6284     5666002 :         if (this->IsChilledWaterTank) {
    6285      487974 :             DeadBandTemp = this->SetPointTemp + this->DeadBandDeltaTemp;
    6286             :         } else {
    6287     5178028 :             DeadBandTemp = this->SetPointTemp - this->DeadBandDeltaTemp;
    6288             :         }
    6289             : 
    6290    11332004 :         Real64 mdotUse = this->PlantMassFlowRatesFunc(state,
    6291             :                                                       this->UseInletNode,
    6292             :                                                       FirstHVACIteration,
    6293             :                                                       WaterHeaterSide::Use,
    6294             :                                                       this->UseSidePlantLoc.loopSideNum,
    6295     5666002 :                                                       this->UseSideSeries,
    6296             :                                                       this->UseBranchControlType,
    6297             :                                                       this->SavedUseOutletTemp,
    6298             :                                                       DeadBandTemp,
    6299     5666002 :                                                       this->SetPointTemp);
    6300     5666002 :         PlantUtilities::SetComponentFlowRate(state, mdotUse, this->UseInletNode, this->UseOutletNode, this->UseSidePlantLoc);
    6301             : 
    6302     5666002 :         this->UseInletTemp = state.dataLoopNodes->Node(this->UseInletNode).Temp;
    6303     5666002 :         this->UseMassFlowRate = mdotUse;
    6304             :     }
    6305             : 
    6306     6113834 :     if (this->SourceInletNode > 0 && !this->SetLoopIndexFlag) { // setup mass flows for plant connections
    6307             :         Real64 DeadBandTemp;
    6308     1990982 :         if (this->IsChilledWaterTank) {
    6309      419296 :             DeadBandTemp = this->SetPointTemp + this->DeadBandDeltaTemp;
    6310             :         } else {
    6311     1571686 :             DeadBandTemp = this->SetPointTemp - this->DeadBandDeltaTemp;
    6312             :         }
    6313             : 
    6314             :         Real64 sensedTemp;
    6315     1990982 :         if (this->WaterThermalTankType == DataPlant::PlantEquipmentType::ChilledWaterTankStratified) {
    6316      104284 :             int tmpNodeNum = this->HeaterNode1;
    6317      104284 :             sensedTemp = this->Node(tmpNodeNum).SavedTemp;
    6318             :         } else {
    6319     1886698 :             sensedTemp = this->SavedSourceOutletTemp;
    6320             :         }
    6321             : 
    6322     3981964 :         Real64 mdotSource = this->PlantMassFlowRatesFunc(state,
    6323             :                                                          this->SourceInletNode,
    6324             :                                                          FirstHVACIteration,
    6325             :                                                          WaterHeaterSide::Source,
    6326             :                                                          this->SrcSidePlantLoc.loopSideNum,
    6327     1990982 :                                                          this->SourceSideSeries,
    6328             :                                                          this->SourceBranchControlType,
    6329             :                                                          sensedTemp,
    6330             :                                                          DeadBandTemp,
    6331     1990982 :                                                          this->SetPointTemp);
    6332     1990982 :         if (this->SrcSidePlantLoc.loopNum > 0) {
    6333     1316276 :             PlantUtilities::SetComponentFlowRate(state, mdotSource, this->SourceInletNode, this->SourceOutletNode, this->SrcSidePlantLoc);
    6334             :         } else { // not really plant connected (desuperheater or heat pump)
    6335      674706 :             state.dataLoopNodes->Node(this->SourceInletNode).MassFlowRate = mdotSource;
    6336      674706 :             state.dataLoopNodes->Node(this->SourceOutletNode).MassFlowRate = mdotSource;
    6337             :         }
    6338             : 
    6339     1990982 :         this->SourceInletTemp = state.dataLoopNodes->Node(this->SourceInletNode).Temp;
    6340     1990982 :         this->SourceMassFlowRate = mdotSource;
    6341             :     }
    6342             : 
    6343             :     // initialize HPWHs each iteration
    6344     6113834 :     if (this->HeatPumpNum > 0) {
    6345             : 
    6346      644656 :         int HPNum = this->HeatPumpNum;
    6347             : 
    6348      644656 :         if (this->MyHPSizeFlag) {
    6349             :             //     autosize info must be calculated in GetWaterThermalTankInputFlag for use in StandardRating procedure
    6350             :             //       (called at end of GetWaterThermalTankInputFlag)
    6351             :             //     report autosizing information here (must be done after GetWaterThermalTankInputFlag is complete)
    6352          69 :             if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).WaterFlowRateAutoSized &&
    6353          32 :                 (state.dataPlnt->PlantFirstSizesOkayToReport || !state.dataGlobal->AnyPlantInModel || this->AlreadyRated)) {
    6354          32 :                 BaseSizer::reportSizerOutput(state,
    6355           8 :                                              state.dataWaterThermalTanks->HPWaterHeater(HPNum).Type,
    6356           8 :                                              state.dataWaterThermalTanks->HPWaterHeater(HPNum).Name,
    6357             :                                              "Condenser water flow rate [m3/s]",
    6358          16 :                                              state.dataWaterThermalTanks->HPWaterHeater(HPNum).OperatingWaterFlowRate);
    6359             :             }
    6360          75 :             if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).AirFlowRateAutoSized &&
    6361          40 :                 (state.dataPlnt->PlantFirstSizesOkayToReport || !state.dataGlobal->AnyPlantInModel || this->AlreadyRated)) {
    6362          40 :                 BaseSizer::reportSizerOutput(state,
    6363          10 :                                              state.dataWaterThermalTanks->HPWaterHeater(HPNum).Type,
    6364          10 :                                              state.dataWaterThermalTanks->HPWaterHeater(HPNum).Name,
    6365             :                                              "Evaporator air flow rate [m3/s]",
    6366          20 :                                              state.dataWaterThermalTanks->HPWaterHeater(HPNum).OperatingAirFlowRate);
    6367             :             }
    6368          45 :             state.dataSize->DataNonZoneNonAirloopValue = state.dataWaterThermalTanks->HPWaterHeater(HPNum).OperatingAirFlowRate;
    6369          45 :             state.dataWaterThermalTanks->HPWaterHeater(HPNum).OperatingAirMassFlowRate =
    6370          45 :                 state.dataWaterThermalTanks->HPWaterHeater(HPNum).OperatingAirFlowRate * state.dataEnvrn->StdRhoAir;
    6371          45 :             if (state.dataSize->CurZoneEqNum > 0) {
    6372          12 :                 ZoneEqSizing(state.dataSize->CurZoneEqNum).CoolingAirFlow = true;
    6373          12 :                 ZoneEqSizing(state.dataSize->CurZoneEqNum).CoolingAirVolFlow = state.dataSize->DataNonZoneNonAirloopValue;
    6374             :             }
    6375          45 :             if (state.dataPlnt->PlantFirstSizesOkayToReport || !state.dataGlobal->AnyPlantInModel || this->AlreadyRated) this->MyHPSizeFlag = false;
    6376             :         }
    6377             : 
    6378      644656 :         int HPAirInletNode = state.dataWaterThermalTanks->HPWaterHeater(HPNum).HeatPumpAirInletNode;
    6379      644656 :         int HPAirOutletNode = state.dataWaterThermalTanks->HPWaterHeater(HPNum).HeatPumpAirOutletNode;
    6380      644656 :         int OutdoorAirNode = state.dataWaterThermalTanks->HPWaterHeater(HPNum).OutsideAirNode;
    6381      644656 :         int ExhaustAirNode = state.dataWaterThermalTanks->HPWaterHeater(HPNum).ExhaustAirNode;
    6382      644656 :         int HPWaterInletNode = state.dataWaterThermalTanks->HPWaterHeater(HPNum).CondWaterInletNode;
    6383      644656 :         int HPWaterOutletNode = state.dataWaterThermalTanks->HPWaterHeater(HPNum).CondWaterOutletNode;
    6384      644656 :         int InletAirMixerNode = state.dataWaterThermalTanks->HPWaterHeater(HPNum).InletAirMixerNode;
    6385      644656 :         int OutletAirSplitterNode = state.dataWaterThermalTanks->HPWaterHeater(HPNum).OutletAirSplitterNode;
    6386             : 
    6387      644656 :         switch (state.dataWaterThermalTanks->HPWaterHeater(HPNum).CrankcaseTempIndicator) {
    6388      337490 :         case CrankcaseHeaterControlTemp::Zone: {
    6389      337490 :             state.dataHVACGlobal->HPWHCrankcaseDBTemp =
    6390      337490 :                 state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataWaterThermalTanks->HPWaterHeater(HPNum).AmbientTempZone).MAT;
    6391      337490 :             break;
    6392             :         }
    6393      283028 :         case CrankcaseHeaterControlTemp::Outdoors: {
    6394      283028 :             state.dataHVACGlobal->HPWHCrankcaseDBTemp = state.dataEnvrn->OutDryBulbTemp;
    6395      283028 :             break;
    6396             :         }
    6397       24138 :         case CrankcaseHeaterControlTemp::Schedule: {
    6398       24138 :             state.dataHVACGlobal->HPWHCrankcaseDBTemp =
    6399       24138 :                 ScheduleManager::GetCurrentScheduleValue(state, state.dataWaterThermalTanks->HPWaterHeater(HPNum).CrankcaseTempSchedule);
    6400       24138 :             break;
    6401             :         }
    6402           0 :         default:
    6403           0 :             break;
    6404             :         }
    6405             : 
    6406             :         //   initialize HPWH report variables to 0 and set tank inlet node equal to outlet node
    6407      644656 :         state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWaterHeaterSensibleCapacity = 0.0;
    6408      644656 :         state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWaterHeaterLatentCapacity = 0.0;
    6409      644656 :         this->SourceMassFlowRate = 0.0;
    6410      644656 :         state.dataWaterThermalTanks->HPWaterHeater(HPNum).HeatingPLR = 0.0;
    6411      644656 :         this->SourceInletTemp = this->SourceOutletTemp;
    6412             : 
    6413             :         //   determine HPWH inlet air conditions based on inlet air configuration (Zone, ZoneAndOA, OutdoorAir, or Schedule)
    6414      644656 :         Real64 HPInletDryBulbTemp = 0.0;
    6415      644656 :         Real64 HPInletHumRat = 0.0;
    6416             :         Real64 HPInletRelHum;
    6417      644656 :         switch (state.dataWaterThermalTanks->HPWaterHeater(HPNum).InletAirConfiguration) {
    6418      311879 :         case WTTAmbientTemp::TempZone: {
    6419      311879 :             state.dataWaterThermalTanks->mixerInletAirSchedule = 0.0;
    6420      311879 :             HPInletDryBulbTemp = state.dataLoopNodes->Node(HPAirInletNode).Temp;
    6421      311879 :             HPInletHumRat = state.dataLoopNodes->Node(HPAirInletNode).HumRat;
    6422      311879 :             break;
    6423             :         }
    6424       25611 :         case WTTAmbientTemp::ZoneAndOA: {
    6425       25611 :             if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).InletAirMixerSchPtr > 0) {
    6426             :                 //         schedule values are checked for boundary of 0 and 1 in GetWaterThermalTankInputFlag
    6427       25611 :                 state.dataWaterThermalTanks->mixerInletAirSchedule =
    6428       25611 :                     ScheduleManager::GetCurrentScheduleValue(state, state.dataWaterThermalTanks->HPWaterHeater(HPNum).InletAirMixerSchPtr);
    6429             :             } else {
    6430           0 :                 state.dataWaterThermalTanks->mixerInletAirSchedule = 0.0;
    6431             :             }
    6432       51222 :             HPInletDryBulbTemp = state.dataWaterThermalTanks->mixerInletAirSchedule * state.dataLoopNodes->Node(OutdoorAirNode).Temp +
    6433       25611 :                                  (1.0 - state.dataWaterThermalTanks->mixerInletAirSchedule) * state.dataLoopNodes->Node(HPAirInletNode).Temp;
    6434       51222 :             HPInletHumRat = state.dataWaterThermalTanks->mixerInletAirSchedule * state.dataLoopNodes->Node(OutdoorAirNode).HumRat +
    6435       25611 :                             (1.0 - state.dataWaterThermalTanks->mixerInletAirSchedule) * state.dataLoopNodes->Node(HPAirInletNode).HumRat;
    6436       25611 :             break;
    6437             :         }
    6438      283028 :         case WTTAmbientTemp::OutsideAir: {
    6439      283028 :             state.dataWaterThermalTanks->mixerInletAirSchedule = 1.0;
    6440      283028 :             HPInletDryBulbTemp = state.dataLoopNodes->Node(OutdoorAirNode).Temp;
    6441      283028 :             HPInletHumRat = state.dataLoopNodes->Node(OutdoorAirNode).HumRat;
    6442             : 
    6443      283028 :             break;
    6444             :         }
    6445       24138 :         case WTTAmbientTemp::Schedule: {
    6446       24138 :             HPInletDryBulbTemp =
    6447       24138 :                 ScheduleManager::GetCurrentScheduleValue(state, state.dataWaterThermalTanks->HPWaterHeater(HPNum).AmbientTempSchedule);
    6448       24138 :             HPInletRelHum = ScheduleManager::GetCurrentScheduleValue(state, state.dataWaterThermalTanks->HPWaterHeater(HPNum).AmbientRHSchedule);
    6449       24138 :             HPInletHumRat = Psychrometrics::PsyWFnTdbRhPb(state, HPInletDryBulbTemp, HPInletRelHum, state.dataEnvrn->OutBaroPress, RoutineName);
    6450       24138 :             state.dataLoopNodes->Node(HPAirInletNode).Temp = HPInletDryBulbTemp;
    6451       24138 :             state.dataLoopNodes->Node(HPAirInletNode).HumRat = HPInletHumRat;
    6452       24138 :             state.dataLoopNodes->Node(HPAirInletNode).Enthalpy = Psychrometrics::PsyHFnTdbW(HPInletDryBulbTemp, HPInletHumRat);
    6453       24138 :             state.dataLoopNodes->Node(HPAirInletNode).Press = state.dataEnvrn->OutBaroPress;
    6454             : 
    6455       24138 :             break;
    6456             :         }
    6457           0 :         default:
    6458           0 :             assert(false);
    6459             :             break;
    6460             :         }
    6461             : 
    6462      644656 :         state.dataWaterThermalTanks->mdotAir = state.dataWaterThermalTanks->HPWaterHeater(HPNum).OperatingAirMassFlowRate;
    6463             : 
    6464             :         //   set up initial conditions on nodes
    6465      644656 :         if (InletAirMixerNode > 0) {
    6466       25611 :             state.dataLoopNodes->Node(InletAirMixerNode).MassFlowRate = 0.0;
    6467       25611 :             state.dataLoopNodes->Node(InletAirMixerNode).MassFlowRateMax = state.dataWaterThermalTanks->mdotAir;
    6468       25611 :             state.dataLoopNodes->Node(InletAirMixerNode).MassFlowRateMaxAvail = state.dataWaterThermalTanks->mdotAir;
    6469       25611 :             state.dataLoopNodes->Node(InletAirMixerNode).Temp = HPInletDryBulbTemp;
    6470       25611 :             state.dataLoopNodes->Node(InletAirMixerNode).HumRat = HPInletHumRat;
    6471       25611 :             state.dataLoopNodes->Node(InletAirMixerNode).Enthalpy = Psychrometrics::PsyHFnTdbW(HPInletDryBulbTemp, HPInletHumRat);
    6472       25611 :             state.dataLoopNodes->Node(HPAirInletNode).MassFlowRate = 0.0;
    6473       25611 :             state.dataLoopNodes->Node(HPAirOutletNode).MassFlowRate = 0.0;
    6474       25611 :             state.dataLoopNodes->Node(OutdoorAirNode).MassFlowRate = 0.0;
    6475       25611 :             state.dataLoopNodes->Node(ExhaustAirNode).MassFlowRate = 0.0;
    6476             :         } else {
    6477      619045 :             if (OutdoorAirNode == 0) {
    6478      336017 :                 state.dataLoopNodes->Node(HPAirInletNode).MassFlowRate = 0.0;
    6479      336017 :                 state.dataLoopNodes->Node(HPAirInletNode).MassFlowRateMax = state.dataWaterThermalTanks->mdotAir;
    6480      336017 :                 state.dataLoopNodes->Node(HPAirInletNode).MassFlowRateMaxAvail = state.dataWaterThermalTanks->mdotAir;
    6481      336017 :                 state.dataLoopNodes->Node(HPAirOutletNode).MassFlowRate = 0.0;
    6482             :             } else {
    6483      283028 :                 state.dataLoopNodes->Node(OutdoorAirNode).MassFlowRate = 0.0;
    6484      283028 :                 state.dataLoopNodes->Node(OutdoorAirNode).MassFlowRateMax = state.dataWaterThermalTanks->mdotAir;
    6485      283028 :                 state.dataLoopNodes->Node(OutdoorAirNode).MassFlowRateMaxAvail = state.dataWaterThermalTanks->mdotAir;
    6486      283028 :                 state.dataLoopNodes->Node(ExhaustAirNode).MassFlowRate = 0.0;
    6487             :             }
    6488             :         }
    6489             : 
    6490      644656 :         if (OutletAirSplitterNode > 0) state.dataLoopNodes->Node(OutletAirSplitterNode).MassFlowRate = 0.0;
    6491             :         // these are water nodes are not managed by plant. the HP connects
    6492             :         // directly to the WH without using plant.
    6493      644656 :         if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHType == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterPumped) {
    6494      465245 :             state.dataLoopNodes->Node(HPWaterInletNode).MassFlowRate = 0.0;
    6495      465245 :             state.dataLoopNodes->Node(HPWaterOutletNode).MassFlowRate = 0.0;
    6496             :         }
    6497             : 
    6498             :         //   set the max mass flow rate for outdoor fans
    6499      644656 :         state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanOutletNode).MassFlowRateMax =
    6500      644656 :             state.dataWaterThermalTanks->mdotAir;
    6501             : 
    6502             :         //   Curve objects in DXCoils::CalcHPWHDXCoil will use inlet conditions to HPWH not inlet air conditions to DX Coil
    6503             :         //   HPWHInletDBTemp and HPWHInletWBTemp are DataHVACGlobals to pass info to HPWHDXCoil
    6504      644656 :         state.dataHVACGlobal->HPWHInletDBTemp = HPInletDryBulbTemp;
    6505      644656 :         state.dataHVACGlobal->HPWHInletWBTemp =
    6506     1289312 :             Psychrometrics::PsyTwbFnTdbWPb(state, state.dataHVACGlobal->HPWHInletDBTemp, HPInletHumRat, state.dataEnvrn->OutBaroPress);
    6507             : 
    6508             :         // initialize flow rates at speed levels for variable-speed HPWH
    6509      654754 :         if ((state.dataWaterThermalTanks->HPWaterHeater(HPNum).bIsIHP) &&
    6510       10098 :             (0 == state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed)) // use SCWH coil represents
    6511             :         {
    6512           1 :             IntegratedHeatPump::SizeIHP(state, state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum); //
    6513             :             // IntegratedHeatPump::SimIHP(modBlankString, HPWaterHeater(HPNum).DXCoilNum,
    6514             :             //    0, EMP1, EMP2, EMP3, 0, 0.0, 1, 0.0, 0.0, 0.0, false, 0.0); //conduct the sizing operation in the IHP
    6515           1 :             int VSCoilID = state.dataIntegratedHP->IntegratedHeatPumps(state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum).SCWHCoilIndex;
    6516           1 :             state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed = state.dataVariableSpeedCoils->VarSpeedCoil(VSCoilID).NumOfSpeeds;
    6517             : 
    6518     1289310 :         } else if (UtilityRoutines::SameString(state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilType,
    6519     1354356 :                                                "Coil:WaterHeating:AirToWaterHeatPump:VariableSpeed") &&
    6520       65046 :                    (state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed == 0)) {
    6521           6 :             Real64 EMP1 = 4.0;
    6522           6 :             Real64 EMP2 = 0.0;
    6523           6 :             Real64 EMP3 = 0.0;
    6524          24 :             VariableSpeedCoils::SimVariableSpeedCoils(state,
    6525          12 :                                                       std::string(),
    6526           6 :                                                       state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum,
    6527             :                                                       0,
    6528             :                                                       EMP1,
    6529             :                                                       EMP2,
    6530             :                                                       EMP3,
    6531             :                                                       DataHVACGlobals::CompressorOperation::Off,
    6532             :                                                       0.0,
    6533             :                                                       1,
    6534             :                                                       0.0,
    6535             :                                                       0.0,
    6536             :                                                       0.0,
    6537             :                                                       0.0); // conduct the sizing operation in the VS WSHP
    6538           6 :             int VSCoilID = state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum;
    6539           6 :             state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed = state.dataVariableSpeedCoils->VarSpeedCoil(VSCoilID).NumOfSpeeds;
    6540             :             // below pass the flow rates from the VS coil to the water heater object
    6541             :         }
    6542             : 
    6543      644656 :         if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed > 0) {
    6544             :             int VSCoilID;
    6545       75144 :             if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).bIsIHP)
    6546       10098 :                 VSCoilID = state.dataIntegratedHP->IntegratedHeatPumps(state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum).SCWHCoilIndex;
    6547             :             else
    6548       65046 :                 VSCoilID = state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum;
    6549             : 
    6550             :             // scale air flow rates
    6551       75144 :             Real64 MulSpeedFlowScale = state.dataVariableSpeedCoils->VarSpeedCoil(VSCoilID).RatedAirVolFlowRate /
    6552      150288 :                                        state.dataVariableSpeedCoils->VarSpeedCoil(VSCoilID).MSRatedAirVolFlowRate(
    6553      150288 :                                            state.dataVariableSpeedCoils->VarSpeedCoil(VSCoilID).NormSpedLevel);
    6554      826584 :             for (int Iter = 1; Iter <= state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed; ++Iter) {
    6555      751440 :                 state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHAirVolFlowRate(Iter) =
    6556      751440 :                     state.dataVariableSpeedCoils->VarSpeedCoil(VSCoilID).MSRatedAirVolFlowRate(Iter) * MulSpeedFlowScale;
    6557             :             }
    6558             : 
    6559             :             // check fan flow rate, should be larger than the max flow rate of the VS coil
    6560       75144 :             Real64 FanVolFlow = 0.0;
    6561       75144 :             if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    6562       60343 :                 FanVolFlow = state.dataHVACFan->fanObjs[state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum]->designAirVolFlowRate;
    6563       14801 :             } else if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanType_Num == DataHVACGlobals::FanType_SimpleOnOff) {
    6564       14801 :                 Fans::GetFanVolFlow(state, state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum, FanVolFlow);
    6565             :             }
    6566             : 
    6567      150288 :             if (FanVolFlow < state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHAirVolFlowRate(
    6568       75144 :                                  state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed)) { // but this is the not the scaled mas flow
    6569             :                 // if ( FanVolFlow  < HPWaterHeater( HPNum ).HPWHAirVolFlowRate( HPWaterHeater( HPNum ).NumofSpeed ) ) {
    6570             : 
    6571           0 :                 ShowWarningError(state,
    6572           0 :                                  format("InitWaterThermalTank: -air flow rate = {:.7T} in fan object  is less than the MSHP system air flow rate "
    6573             :                                         "when waterheating is required({:.7T}).",
    6574             :                                         FanVolFlow,
    6575           0 :                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHAirVolFlowRate(
    6576           0 :                                             state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed)));
    6577           0 :                 ShowContinueError(state,
    6578             :                                   " The MSHP system flow rate when waterheating is required is reset to the"
    6579             :                                   " fan flow rate and the simulation continues.");
    6580           0 :                 ShowContinueError(state, " Occurs in " + state.dataWaterThermalTanks->HPWaterHeater(HPNum).Name);
    6581           0 :                 state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHAirVolFlowRate(state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed) =
    6582             :                     FanVolFlow;
    6583             :                 // Check flow rates in other speeds and ensure flow rates are not above the max flow rate
    6584           0 :                 for (int Iter = state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed - 1; Iter >= 1; --Iter) {
    6585           0 :                     if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHAirVolFlowRate(Iter) >
    6586           0 :                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHAirVolFlowRate(Iter + 1)) {
    6587           0 :                         ShowContinueError(state,
    6588           0 :                                           format(" The MSHP system flow rate when waterheating is required is reset to the flow rate at higher "
    6589             :                                                  "speed and the simulation continues at Speed{}.",
    6590           0 :                                                  Iter));
    6591           0 :                         ShowContinueError(state, " Occurs in " + state.dataWaterThermalTanks->HPWaterHeater(HPNum).Name);
    6592           0 :                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHAirVolFlowRate(Iter) =
    6593           0 :                             state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHAirVolFlowRate(Iter + 1);
    6594             :                     }
    6595             :                 }
    6596             :             }
    6597             : 
    6598      826584 :             for (int Iter = 1; Iter <= state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed; ++Iter) {
    6599      751440 :                 state.dataWaterThermalTanks->HPWaterHeater(HPNum).MSAirSpeedRatio(Iter) =
    6600     1502880 :                     state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHAirVolFlowRate(Iter) /
    6601     1502880 :                     state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHAirVolFlowRate(
    6602      751440 :                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed);
    6603             :             }
    6604             : 
    6605             :             // scale water flow rates
    6606      150288 :             MulSpeedFlowScale = state.dataVariableSpeedCoils->VarSpeedCoil(VSCoilID).RatedWaterVolFlowRate /
    6607      150288 :                                 state.dataVariableSpeedCoils->VarSpeedCoil(VSCoilID).MSRatedWaterVolFlowRate(
    6608       75144 :                                     state.dataVariableSpeedCoils->VarSpeedCoil(VSCoilID).NormSpedLevel);
    6609      826584 :             for (int Iter = 1; Iter <= state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed; ++Iter) {
    6610      751440 :                 state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHWaterVolFlowRate(Iter) =
    6611      751440 :                     state.dataVariableSpeedCoils->VarSpeedCoil(VSCoilID).MSRatedWaterVolFlowRate(Iter) * MulSpeedFlowScale;
    6612      751440 :                 state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHWaterMassFlowRate(Iter) =
    6613      751440 :                     state.dataVariableSpeedCoils->VarSpeedCoil(VSCoilID).MSRatedWaterMassFlowRate(Iter) * MulSpeedFlowScale;
    6614      751440 :                 state.dataWaterThermalTanks->HPWaterHeater(HPNum).MSWaterSpeedRatio(Iter) =
    6615     1502880 :                     state.dataVariableSpeedCoils->VarSpeedCoil(VSCoilID).MSRatedWaterVolFlowRate(Iter) /
    6616     1502880 :                     state.dataVariableSpeedCoils->VarSpeedCoil(VSCoilID).MSRatedWaterVolFlowRate(
    6617      751440 :                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed);
    6618             :             }
    6619             : 
    6620       75144 :             Real64 rhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, HPInletDryBulbTemp, HPInletHumRat);
    6621             : 
    6622      826584 :             for (int Iter = 1; Iter <= state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed; ++Iter) {
    6623      751440 :                 state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHAirMassFlowRate(Iter) =
    6624      751440 :                     state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHAirVolFlowRate(Iter) * rhoAir;
    6625             :             }
    6626             : 
    6627             :             //   set the max mass flow rate for outdoor fans
    6628       75144 :             state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanOutletNode).MassFlowRateMax =
    6629       75144 :                 state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHAirMassFlowRate(state.dataWaterThermalTanks->HPWaterHeater(HPNum).NumofSpeed);
    6630             :         }
    6631             : 
    6632             :     } //  IF(WaterThermalTank(WaterThermalTankNum)%HeatPumpNum .GT. 0)THEN
    6633             : 
    6634             :     // calling CalcStandardRatings early bypasses fan sizing since DataSizing::DataNonZoneNonAirloopValue has not been set yet
    6635     6113834 :     if (!this->AlreadyRated) {
    6636         278 :         if (this->IsChilledWaterTank) {
    6637           5 :             this->AlreadyRated = true;
    6638             :         } else {
    6639         367 :             if (!state.dataGlobal->AnyPlantInModel || state.dataPlnt->PlantFirstSizesOkayToReport || this->MaxCapacity > 0.0 ||
    6640          94 :                 this->HeatPumpNum > 0) {
    6641         181 :                 this->CalcStandardRatings(state);
    6642             :             }
    6643             :         }
    6644             :     }
    6645     6113834 : }
    6646             : 
    6647     6395474 : void WaterThermalTankData::CalcWaterThermalTankMixed(EnergyPlusData &state) // Water Heater being simulated
    6648             : {
    6649             : 
    6650             :     // SUBROUTINE INFORMATION:
    6651             :     //       AUTHOR         Peter Graham Ellis
    6652             :     //       DATE WRITTEN   January 2005
    6653             :     //       MODIFIED       na
    6654             :     //       RE-ENGINEERED  na
    6655             : 
    6656             :     // PURPOSE OF THIS SUBROUTINE:
    6657             :     // Simulates a well-mixed, single node water heater tank.
    6658             : 
    6659             :     // METHODOLOGY EMPLOYED:
    6660             :     // This model uses analytical calculations based on the differential equation describing the tank energy
    6661             :     // balance.  The model operates in three different modes:  heating, floating, and venting.  Temperatures and
    6662             :     // energies change dynamically over the timestep.  The final reported tank temperature is the average over
    6663             :     // the timestep.  The final reported heat rates are averages based on the total energy transfer over the
    6664             :     // timestep.
    6665             : 
    6666             :     static constexpr std::string_view RoutineName("CalcWaterThermalTankMixed");
    6667             : 
    6668             :     Real64 TimeElapsed_loc =
    6669     6395474 :         state.dataGlobal->HourOfDay + state.dataGlobal->TimeStep * state.dataGlobal->TimeStepZone + state.dataHVACGlobal->SysTimeElapsed;
    6670             : 
    6671     6395474 :     if (this->TimeElapsed != TimeElapsed_loc) {
    6672             :         // The simulation has advanced to the next system DataGlobals::TimeStep.  Save conditions from the end of the previous system
    6673             :         // DataGlobals::TimeStep for use as the initial conditions of each iteration that does not advance the system DataGlobals::TimeStep.
    6674      586910 :         this->SavedTankTemp = this->TankTemp;
    6675      586910 :         this->SavedMode = this->Mode;
    6676             : 
    6677             :         // Save outlet temperatures for demand-side flow control
    6678      586910 :         this->SavedUseOutletTemp = this->UseOutletTemp;
    6679      586910 :         this->SavedSourceOutletTemp = this->SourceOutletTemp;
    6680             : 
    6681      586910 :         this->TimeElapsed = TimeElapsed_loc;
    6682             :     }
    6683             : 
    6684     6395474 :     Real64 TankTemp_loc = this->SavedTankTemp;
    6685     6395474 :     TankOperatingMode Mode_loc = this->SavedMode;
    6686             : 
    6687     6395474 :     Real64 Qmaxcap = this->MaxCapacity;
    6688     6395474 :     Real64 Qmincap = this->MinCapacity;
    6689     6395474 :     Real64 Qoffcycfuel = this->OffCycParaLoad;
    6690     6395474 :     Real64 Qoffcycheat = Qoffcycfuel * this->OffCycParaFracToTank;
    6691     6395474 :     Real64 Qoncycfuel = this->OnCycParaLoad;
    6692     6395474 :     Real64 Qoncycheat = Qoncycfuel * this->OnCycParaFracToTank;
    6693             : 
    6694     6395474 :     Real64 SetPointTemp_loc = this->SetPointTemp;
    6695     6395474 :     Real64 DeadBandTemp = this->getDeadBandTemp();
    6696     6395474 :     Real64 MaxTemp = this->TankTempLimit;
    6697     6395474 :     Real64 AmbientTemp_loc = this->AmbientTemp;
    6698             : 
    6699     6395474 :     Real64 UseInletTemp_loc = this->UseInletTemp;
    6700     6395474 :     Real64 UseMassFlowRate_loc = this->UseMassFlowRate * this->UseEffectiveness;
    6701     6395474 :     Real64 SourceInletTemp_loc = this->SourceInletTemp;
    6702     6395474 :     Real64 SourceMassFlowRate_loc = this->SourceMassFlowRate * this->SourceEffectiveness;
    6703             : 
    6704             :     Real64 rho;
    6705     6395474 :     if (this->UseSidePlantLoc.loopNum > 0) {
    6706    11578888 :         rho = FluidProperties::GetDensityGlycol(state,
    6707     5789444 :                                                 state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
    6708             :                                                 TankTemp_loc,
    6709     5789444 :                                                 state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
    6710             :                                                 RoutineName);
    6711             :     } else {
    6712      606030 :         rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, TankTemp_loc, this->waterIndex, RoutineName);
    6713             :     }
    6714             : 
    6715     6395474 :     Real64 TankMass = rho * this->Volume;
    6716             : 
    6717             :     Real64 Cp;
    6718     6395474 :     if (this->UseSidePlantLoc.loopNum > 0) {
    6719    11578888 :         Cp = FluidProperties::GetSpecificHeatGlycol(state,
    6720     5789444 :                                                     state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
    6721             :                                                     TankTemp_loc,
    6722     5789444 :                                                     state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
    6723             :                                                     RoutineName);
    6724             :     } else {
    6725      606030 :         Cp = FluidProperties::GetSpecificHeatGlycol(state, fluidNameWater, TankTemp_loc, this->waterIndex, RoutineName);
    6726             :     }
    6727             : 
    6728     6395474 :     Real64 SecInTimeStep = state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    6729     6395474 :     Real64 TimeRemaining = SecInTimeStep;
    6730     6395474 :     int CycleOnCount_loc = 0;
    6731     6395474 :     int MaxCycles = SecInTimeStep;
    6732     6395474 :     Real64 Runtime = 0.0;
    6733     6395474 :     bool SetPointRecovered = false;
    6734             : 
    6735     6395474 :     Real64 Tsum = 0.0;
    6736     6395474 :     Real64 Eloss = 0.0;
    6737     6395474 :     Real64 Elosszone = 0.0;
    6738     6395474 :     Real64 Euse = 0.0;
    6739     6395474 :     Real64 Esource = 0.0;
    6740     6395474 :     Real64 Eheater = 0.0;
    6741     6395474 :     Real64 Event = 0.0;
    6742     6395474 :     Real64 Eneeded = 0.0;
    6743     6395474 :     Real64 Eunmet = 0.0;
    6744     6395474 :     Real64 Efuel = 0.0;
    6745     6395474 :     Real64 Eoncycfuel = 0.0;
    6746     6395474 :     Real64 Eoffcycfuel = 0.0;
    6747     6395474 :     Real64 PLR = 0.0;
    6748     6395474 :     Real64 PLRsum = 0.0;
    6749             : 
    6750     6395474 :     Real64 Qheat = 0.0;
    6751     6395474 :     Real64 Qheater = 0.0;
    6752     6395474 :     Real64 Qvent = 0.0;
    6753     6395474 :     Real64 Qneeded = 0.0;
    6754     6395474 :     Real64 Qunmet = 0.0;
    6755     6395474 :     Real64 Qfuel = 0.0;
    6756             : 
    6757             :     // Calculate the heating rate from the heat pump.
    6758     6395474 :     Real64 HPWHCondenserDeltaT = 0.0;
    6759             : 
    6760     6395474 :     if (this->HeatPumpNum > 0) {
    6761     1122477 :         HeatPumpWaterHeaterData const &HeatPump = state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum);
    6762     1122477 :         DataLoopNode::NodeData const &HPWHCondWaterInletNode = state.dataLoopNodes->Node(HeatPump.CondWaterInletNode);
    6763     1122477 :         DataLoopNode::NodeData const &HPWHCondWaterOutletNode = state.dataLoopNodes->Node(HeatPump.CondWaterOutletNode);
    6764     1122477 :         HPWHCondenserDeltaT = HPWHCondWaterOutletNode.Temp - HPWHCondWaterInletNode.Temp;
    6765             :     }
    6766     6395474 :     assert(HPWHCondenserDeltaT >= 0);
    6767             : 
    6768             :     Real64 Qheatpump;
    6769             :     Real64 Qsource;
    6770     6395474 :     EnergyPlus::WaterThermalTanks::WaterThermalTankData::CalcMixedTankSourceSideHeatTransferRate(
    6771             :         HPWHCondenserDeltaT, SourceInletTemp_loc, Cp, SetPointTemp_loc, SourceMassFlowRate_loc, Qheatpump, Qsource);
    6772             : 
    6773             :     // Calculate steady-state use heat rate.
    6774     6395474 :     Real64 Quse = UseMassFlowRate_loc * Cp * (UseInletTemp_loc - SetPointTemp_loc);
    6775     6395474 :     Real64 Qloss = 0.0, PLF = 0.0;
    6776             : 
    6777    40633914 :     while (TimeRemaining > 0.0) {
    6778             : 
    6779    17119220 :         Real64 TimeNeeded = 0.0;
    6780             : 
    6781    17119220 :         Real64 NewTankTemp = TankTemp_loc;
    6782    17119220 :         Real64 LossCoeff_loc = 0.0;
    6783    17119220 :         Real64 LossFracToZone = 0.0;
    6784             : 
    6785    17119220 :         switch (Mode_loc) {
    6786             : 
    6787     7562716 :         case TankOperatingMode::Heating: // Heater is on
    6788             : 
    6789             :             // Calculate heat rate needed to maintain the setpoint at steady-state conditions
    6790     7562716 :             LossCoeff_loc = this->OnCycLossCoeff;
    6791     7562716 :             LossFracToZone = this->OnCycLossFracToZone;
    6792     7562716 :             Qloss = LossCoeff_loc * (AmbientTemp_loc - SetPointTemp_loc);
    6793     7562716 :             Qneeded = -Quse - Qsource - Qloss - Qoncycheat;
    6794             : 
    6795     7562724 :             if (TankTemp_loc > SetPointTemp_loc) {
    6796             :                 // Heater is not needed after all, possibly due to step change in scheduled SetPointTemp
    6797             : 
    6798           8 :                 Qheater = 0.0;
    6799           8 :                 Qunmet = 0.0;
    6800           8 :                 Mode_loc = TankOperatingMode::Floating;
    6801           8 :                 continue;
    6802             : 
    6803     7562708 :             } else if (TankTemp_loc < SetPointTemp_loc) {
    6804             :                 // Attempt to recover to the setpoint as quickly as possible by using maximum heater capacity
    6805             : 
    6806             :                 // Qneeded is calculated above
    6807             :                 // Qneeded does not account for the extra energy needed to recover to the setpoint
    6808     4033165 :                 Qheater = Qmaxcap;
    6809     4033165 :                 Qunmet = max(Qneeded - Qheater, 0.0);
    6810     4033165 :                 Qheat = Qoncycheat + Qheater + Qheatpump;
    6811             : 
    6812             :                 // Calculate time needed to recover to the setpoint at maximum heater capacity
    6813     4033165 :                 TimeNeeded = EnergyPlus::WaterThermalTanks::WaterThermalTankData::CalcTimeNeeded(TankTemp_loc,
    6814             :                                                                                                  SetPointTemp_loc,
    6815             :                                                                                                  AmbientTemp_loc,
    6816             :                                                                                                  UseInletTemp_loc,
    6817             :                                                                                                  SourceInletTemp_loc,
    6818             :                                                                                                  TankMass,
    6819             :                                                                                                  Cp,
    6820             :                                                                                                  UseMassFlowRate_loc,
    6821             :                                                                                                  SourceMassFlowRate_loc,
    6822             :                                                                                                  LossCoeff_loc,
    6823             :                                                                                                  Qheat);
    6824             : 
    6825     4033165 :                 if (TimeNeeded > TimeRemaining) {
    6826             :                     // Heater is at maximum capacity and heats for all of the remaining time
    6827             :                     // Setpoint temperature WILL NOT be recovered
    6828             : 
    6829      556173 :                     TimeNeeded = TimeRemaining;
    6830             : 
    6831      556173 :                     NewTankTemp = EnergyPlus::WaterThermalTanks::WaterThermalTankData::CalcTankTemp(TankTemp_loc,
    6832             :                                                                                                     AmbientTemp_loc,
    6833             :                                                                                                     UseInletTemp_loc,
    6834             :                                                                                                     SourceInletTemp_loc,
    6835             :                                                                                                     TankMass,
    6836             :                                                                                                     Cp,
    6837             :                                                                                                     UseMassFlowRate_loc,
    6838             :                                                                                                     SourceMassFlowRate_loc,
    6839             :                                                                                                     LossCoeff_loc,
    6840             :                                                                                                     Qheat,
    6841             :                                                                                                     TimeNeeded);
    6842             : 
    6843             :                 } else { // TimeNeeded <= TimeRemaining
    6844             :                     // Heater is at maximum capacity but will not heat for all of the remaining time (at maximum anyway)
    6845             :                     // Setpoint temperature WILL be recovered
    6846             : 
    6847     3476992 :                     NewTankTemp = SetPointTemp_loc;
    6848             : 
    6849     3476992 :                     SetPointRecovered = true;
    6850             : 
    6851             :                 } // TimeNeeded > TimeRemaining
    6852             : 
    6853             :             } else { // TankTemp == SetPointTemp
    6854             :                 // Attempt to maintain the setpoint by using the needed heater capacity (modulating, if allowed)
    6855             : 
    6856     3538695 :                 if (Qneeded <= 0.0) {
    6857             :                     // Heater is not needed
    6858             : 
    6859        9152 :                     Qneeded = 0.0;
    6860        9152 :                     Qheater = 0.0;
    6861        9152 :                     Qunmet = 0.0;
    6862        9152 :                     Mode_loc = TankOperatingMode::Floating;
    6863        9152 :                     continue;
    6864             : 
    6865     3520391 :                 } else if (Qneeded < Qmincap) {
    6866             :                     // Heater is required at less than the minimum capacity
    6867             :                     // If cycling, Qmincap = Qmaxcap.  Once the setpoint is reached, heater will almost always be shut off here
    6868             : 
    6869     6934366 :                     if (this->ControlType == HeaterControlMode::Cycle) {
    6870             :                         // Control will cycle on and off based on DeadBandTemp
    6871     3467183 :                         Qheater = 0.0;
    6872     3467183 :                         Qunmet = 0.0;
    6873     3467183 :                         Mode_loc = TankOperatingMode::Floating;
    6874     3467183 :                         continue;
    6875             : 
    6876           0 :                     } else if (this->ControlType == HeaterControlMode::Modulate) {
    6877             :                         // Control will cycle on and off based on DeadBandTemp until Qneeded > Qmincap again
    6878           0 :                         Qheater = 0.0;
    6879           0 :                         Qunmet = Qneeded;
    6880           0 :                         Mode_loc = TankOperatingMode::Floating;
    6881           0 :                         continue;
    6882             : 
    6883             :                         // CASE (ControlTypeModulateWithOverheat)  ! Not yet implemented
    6884             :                         // Calculate time to reach steady-state temp; check for venting at MaxTemp limit
    6885             :                         // Qheater = Qmincap
    6886             : 
    6887             :                         // CASE (ControlTypeModulateWithUnderheat)  ! Not yet implemented
    6888             :                         // Heater must not come back on until Qneeded >= Qmincap
    6889             :                         // Mode = modfloatMode
    6890             :                     }
    6891             : 
    6892       53208 :                 } else if (Qneeded <= Qmaxcap) {
    6893             :                     // Heater can exactly meet the needed heat rate (usually by modulating) and heats for all of the remaining time
    6894             :                     // Setpoint temperature WILL be maintained
    6895             : 
    6896       53171 :                     TimeNeeded = TimeRemaining;
    6897             : 
    6898       53171 :                     Qheater = Qneeded;
    6899       53171 :                     Qunmet = 0.0;
    6900             : 
    6901       53171 :                     NewTankTemp = SetPointTemp_loc;
    6902             : 
    6903             :                 } else { // Qneeded > Qmaxcap
    6904             :                     // Heater is at maximum capacity and heats for all of the remaining time
    6905             :                     // Setpoint temperature WILL NOT be maintained
    6906             : 
    6907          37 :                     TimeNeeded = TimeRemaining;
    6908             : 
    6909          37 :                     Qheater = Qmaxcap;
    6910          37 :                     Qunmet = Qneeded - Qheater;
    6911          37 :                     Qheat = Qoncycheat + Qheater + Qheatpump;
    6912             : 
    6913          37 :                     NewTankTemp = EnergyPlus::WaterThermalTanks::WaterThermalTankData::CalcTankTemp(TankTemp_loc,
    6914             :                                                                                                     AmbientTemp_loc,
    6915             :                                                                                                     UseInletTemp_loc,
    6916             :                                                                                                     SourceInletTemp_loc,
    6917             :                                                                                                     TankMass,
    6918             :                                                                                                     Cp,
    6919             :                                                                                                     UseMassFlowRate_loc,
    6920             :                                                                                                     SourceMassFlowRate_loc,
    6921             :                                                                                                     LossCoeff_loc,
    6922             :                                                                                                     Qheat,
    6923             :                                                                                                     TimeNeeded);
    6924             : 
    6925             :                 } // Qneeded > Qmaxcap
    6926             : 
    6927             :             } // TankTemp > SetPointTemp
    6928             : 
    6929             :             // Update summed values
    6930     4086373 :             Eneeded += Qneeded * TimeNeeded;
    6931     4086373 :             Eheater += Qheater * TimeNeeded;
    6932     4086373 :             Eunmet += Qunmet * TimeNeeded;
    6933     4086373 :             Eoncycfuel += Qoncycfuel * TimeNeeded;
    6934             : 
    6935     4086373 :             if (Qmaxcap > 0.0) PLR = Qheater / Qmaxcap;
    6936     4086373 :             PLF = this->PartLoadFactor(state, PLR);
    6937     4086373 :             Efuel += Qheater * TimeNeeded / (PLF * this->Efficiency);
    6938             : 
    6939     4086373 :             Runtime += TimeNeeded;
    6940     4086373 :             PLRsum += PLR * TimeNeeded;
    6941             : 
    6942     4086373 :             if (!this->FirstRecoveryDone) {
    6943      128258 :                 this->FirstRecoveryFuel += Efuel + Eoffcycfuel + Eoncycfuel;
    6944      128258 :                 if (SetPointRecovered) this->FirstRecoveryDone = true;
    6945             :             }
    6946     4086373 :             break;
    6947             : 
    6948     9427850 :         case TankOperatingMode::Floating:
    6949             :         case TankOperatingMode::Cooling: // Heater is off
    6950             : 
    6951             :             // Calculate heat rate needed to maintain the setpoint at steady-state conditions
    6952     9427850 :             LossCoeff_loc = this->OffCycLossCoeff;
    6953     9427850 :             LossFracToZone = this->OffCycLossFracToZone;
    6954     9427850 :             Qloss = LossCoeff_loc * (AmbientTemp_loc - SetPointTemp_loc);
    6955     9427850 :             Qneeded = -Quse - Qsource - Qloss - Qoffcycheat;
    6956             : 
    6957             :             // This section really needs to work differently depending on ControlType
    6958             :             // CYCLE will look at TankTemp, MODULATE will look at Qneeded
    6959             : 
    6960     9428275 :             if ((TankTemp_loc < DeadBandTemp) && (!this->IsChilledWaterTank)) {
    6961             :                 // Tank temperature is already below the minimum, possibly due to step change in scheduled SetPointTemp
    6962             : 
    6963         425 :                 Mode_loc = TankOperatingMode::Heating;
    6964         425 :                 ++CycleOnCount_loc;
    6965         425 :                 continue;
    6966             : 
    6967     9427425 :             } else if ((TankTemp_loc >= DeadBandTemp) && (!this->IsChilledWaterTank)) {
    6968             : 
    6969     9112392 :                 Qheat = Qoffcycheat + Qheatpump;
    6970             : 
    6971             :                 // Calculate time needed for tank temperature to fall to minimum (setpoint - deadband)
    6972     9112392 :                 TimeNeeded = EnergyPlus::WaterThermalTanks::WaterThermalTankData::CalcTimeNeeded(TankTemp_loc,
    6973             :                                                                                                  DeadBandTemp,
    6974             :                                                                                                  AmbientTemp_loc,
    6975             :                                                                                                  UseInletTemp_loc,
    6976             :                                                                                                  SourceInletTemp_loc,
    6977             :                                                                                                  TankMass,
    6978             :                                                                                                  Cp,
    6979             :                                                                                                  UseMassFlowRate_loc,
    6980             :                                                                                                  SourceMassFlowRate_loc,
    6981             :                                                                                                  LossCoeff_loc,
    6982             :                                                                                                  Qheat);
    6983             : 
    6984    18224784 :                 if (TimeNeeded <= TimeRemaining) {
    6985             :                     // Heating will be needed in this DataGlobals::TimeStep
    6986             : 
    6987     3708620 :                     NewTankTemp = DeadBandTemp;
    6988     3708620 :                     Mode_loc = TankOperatingMode::Heating;
    6989     3708620 :                     ++CycleOnCount_loc;
    6990             : 
    6991             :                 } else { // TimeNeeded > TimeRemaining
    6992             :                     // Heating will not be needed for all of the remaining time
    6993             : 
    6994     5403772 :                     NewTankTemp = EnergyPlus::WaterThermalTanks::WaterThermalTankData::CalcTankTemp(TankTemp_loc,
    6995             :                                                                                                     AmbientTemp_loc,
    6996             :                                                                                                     UseInletTemp_loc,
    6997             :                                                                                                     SourceInletTemp_loc,
    6998             :                                                                                                     TankMass,
    6999             :                                                                                                     Cp,
    7000             :                                                                                                     UseMassFlowRate_loc,
    7001             :                                                                                                     SourceMassFlowRate_loc,
    7002             :                                                                                                     LossCoeff_loc,
    7003             :                                                                                                     Qheat,
    7004             :                                                                                                     TimeRemaining);
    7005             : 
    7006     5403772 :                     if ((NewTankTemp < MaxTemp) || (this->IsChilledWaterTank)) {
    7007             :                         // Neither heating nor venting is needed for all of the remaining time
    7008             : 
    7009     5384743 :                         TimeNeeded = TimeRemaining;
    7010             : 
    7011             :                     } else { // NewTankTemp >= MaxTemp
    7012             :                         // Venting will be needed in this DataGlobals::TimeStep
    7013             : 
    7014             :                         // Calculate time needed for tank temperature to rise to the maximum
    7015       19029 :                         TimeNeeded = CalcTimeNeeded(TankTemp_loc,
    7016             :                                                     MaxTemp,
    7017             :                                                     AmbientTemp_loc,
    7018             :                                                     UseInletTemp_loc,
    7019             :                                                     SourceInletTemp_loc,
    7020             :                                                     TankMass,
    7021             :                                                     Cp,
    7022             :                                                     UseMassFlowRate_loc,
    7023             :                                                     SourceMassFlowRate_loc,
    7024             :                                                     LossCoeff_loc,
    7025             :                                                     Qheat);
    7026             : 
    7027             :                         // if limit NewTankTemp >= MaxTemp
    7028       19029 :                         if (TankTemp_loc >= MaxTemp) {
    7029           0 :                             TimeNeeded = TimeRemaining;
    7030             :                         }
    7031       19029 :                         NewTankTemp = MaxTemp;
    7032       19029 :                         Mode_loc = TankOperatingMode::Venting;
    7033             : 
    7034             :                     } // NewTankTemp >= MaxTemp
    7035             : 
    7036             :                 } // TimeNeeded <= TimeRemaining
    7037             : 
    7038      315033 :             } else if ((TankTemp_loc > DeadBandTemp) && (this->IsChilledWaterTank)) {
    7039        2480 :                 Mode_loc = TankOperatingMode::Cooling;
    7040        2480 :                 Qheat = Qheatpump;
    7041             : 
    7042        2480 :                 NewTankTemp = EnergyPlus::WaterThermalTanks::WaterThermalTankData::CalcTankTemp(TankTemp_loc,
    7043             :                                                                                                 AmbientTemp_loc,
    7044             :                                                                                                 UseInletTemp_loc,
    7045             :                                                                                                 SourceInletTemp_loc,
    7046             :                                                                                                 TankMass,
    7047             :                                                                                                 Cp,
    7048             :                                                                                                 UseMassFlowRate_loc,
    7049             :                                                                                                 SourceMassFlowRate_loc,
    7050             :                                                                                                 LossCoeff_loc,
    7051             :                                                                                                 Qheat,
    7052             :                                                                                                 TimeRemaining);
    7053        2480 :                 TimeNeeded = TimeRemaining;
    7054      312553 :             } else if ((TankTemp_loc <= DeadBandTemp) && (this->IsChilledWaterTank)) {
    7055             : 
    7056      312553 :                 if (TankTemp_loc < SetPointTemp_loc) Mode_loc = TankOperatingMode::Floating;
    7057             : 
    7058      312553 :                 Qheat = Qheatpump;
    7059             : 
    7060      312553 :                 NewTankTemp = EnergyPlus::WaterThermalTanks::WaterThermalTankData::CalcTankTemp(TankTemp_loc,
    7061             :                                                                                                 AmbientTemp_loc,
    7062             :                                                                                                 UseInletTemp_loc,
    7063             :                                                                                                 SourceInletTemp_loc,
    7064             :                                                                                                 TankMass,
    7065             :                                                                                                 Cp,
    7066             :                                                                                                 UseMassFlowRate_loc,
    7067             :                                                                                                 SourceMassFlowRate_loc,
    7068             :                                                                                                 LossCoeff_loc,
    7069             :                                                                                                 Qheat,
    7070             :                                                                                                 TimeRemaining);
    7071      312553 :                 TimeNeeded = TimeRemaining;
    7072             :             } // TankTemp vs DeadBandTemp for heaters and chilled water tanks
    7073             : 
    7074             :             // Update summed values
    7075     9427425 :             Eneeded += Qneeded * TimeNeeded;
    7076     9427425 :             Eunmet += Qunmet * TimeNeeded; // Qunmet may be propagated thru from the previous iteration
    7077     9427425 :             Eoffcycfuel += Qoffcycfuel * TimeNeeded;
    7078     9427425 :             break;
    7079             : 
    7080      128654 :         case TankOperatingMode::Venting: // Excess heat is vented
    7081             : 
    7082      128654 :             LossCoeff_loc = this->OffCycLossCoeff;
    7083      128654 :             LossFracToZone = this->OffCycLossFracToZone;
    7084      128654 :             Qheat = Qoffcycheat + Qheatpump;
    7085             : 
    7086      128654 :             NewTankTemp = EnergyPlus::WaterThermalTanks::WaterThermalTankData::CalcTankTemp(TankTemp_loc,
    7087             :                                                                                             AmbientTemp_loc,
    7088             :                                                                                             UseInletTemp_loc,
    7089             :                                                                                             SourceInletTemp_loc,
    7090             :                                                                                             TankMass,
    7091             :                                                                                             Cp,
    7092             :                                                                                             UseMassFlowRate_loc,
    7093             :                                                                                             SourceMassFlowRate_loc,
    7094             :                                                                                             LossCoeff_loc,
    7095             :                                                                                             Qheat,
    7096             :                                                                                             TimeRemaining);
    7097             : 
    7098      170991 :             if (NewTankTemp < MaxTemp) {
    7099             :                 // Venting is no longer needed because conditions have changed
    7100             : 
    7101       42337 :                 Mode_loc = TankOperatingMode::Floating;
    7102       42337 :                 continue;
    7103             : 
    7104             :             } else { // NewTankTemp >= MaxTemp
    7105             : 
    7106       86317 :                 TimeNeeded = TimeRemaining;
    7107             : 
    7108             :                 // Calculate the steady-state venting rate needed to maintain the tank at maximum temperature
    7109       86317 :                 Real64 Qloss = LossCoeff_loc * (AmbientTemp_loc - MaxTemp);
    7110       86317 :                 Quse = UseMassFlowRate_loc * Cp * (UseInletTemp_loc - MaxTemp);
    7111       86317 :                 Qsource = SourceMassFlowRate_loc * Cp * (SourceInletTemp_loc - MaxTemp);
    7112       86317 :                 Qvent = -Quse - Qsource - Qloss - Qoffcycheat;
    7113             : 
    7114       86317 :                 NewTankTemp = MaxTemp;
    7115             : 
    7116             :             } // NewTankTemp < MaxTemp
    7117             : 
    7118             :             // Update summed values
    7119       86317 :             Event += Qvent * TimeNeeded;
    7120       86317 :             Eoffcycfuel += Qoffcycfuel * TimeNeeded;
    7121       86317 :             break;
    7122           0 :         default:
    7123           0 :             assert(false); // should never get here
    7124             :         }
    7125             : 
    7126    13600115 :         Real64 deltaTsum = EnergyPlus::WaterThermalTanks::WaterThermalTankData::CalcTempIntegral(TankTemp_loc,
    7127             :                                                                                                  NewTankTemp,
    7128             :                                                                                                  AmbientTemp_loc,
    7129             :                                                                                                  UseInletTemp_loc,
    7130             :                                                                                                  SourceInletTemp_loc,
    7131             :                                                                                                  TankMass,
    7132             :                                                                                                  Cp,
    7133             :                                                                                                  UseMassFlowRate_loc,
    7134             :                                                                                                  SourceMassFlowRate_loc,
    7135             :                                                                                                  LossCoeff_loc,
    7136             :                                                                                                  Qheat,
    7137    13600115 :                                                                                                  TimeNeeded);
    7138             : 
    7139             :         // Update summed values
    7140    13600115 :         Tsum += deltaTsum;
    7141    13600115 :         Eloss += LossCoeff_loc * (AmbientTemp_loc * TimeNeeded - deltaTsum);
    7142    13600115 :         Elosszone += LossFracToZone * LossCoeff_loc * (AmbientTemp_loc * TimeNeeded - deltaTsum);
    7143    13600115 :         Euse += UseMassFlowRate_loc * Cp * (UseInletTemp_loc * TimeNeeded - deltaTsum);
    7144    13600115 :         if (this->HeatPumpNum > 0) {
    7145     1293386 :             Esource += Qheatpump * TimeNeeded;
    7146             :         } else {
    7147    12306729 :             Esource += SourceMassFlowRate_loc * Cp * (SourceInletTemp_loc * TimeNeeded - deltaTsum);
    7148             :         }
    7149             : 
    7150    13600115 :         TankTemp_loc = NewTankTemp; // Update tank temperature
    7151             : 
    7152    13600115 :         TimeRemaining -= TimeNeeded;
    7153             : 
    7154    13600115 :         if (CycleOnCount_loc > MaxCycles) {
    7155             : 
    7156           0 :             if (!state.dataGlobal->WarmupFlag) {
    7157           0 :                 if (this->MaxCycleErrorIndex == 0) {
    7158           0 :                     ShowWarningError(state, "WaterHeater:Mixed = " + this->Name + ":  Heater is cycling on and off more than once per second.");
    7159           0 :                     ShowContinueError(state, "Try increasing Deadband Temperature Difference or Tank Volume");
    7160           0 :                     ShowContinueErrorTimeStamp(state, "");
    7161             :                 }
    7162           0 :                 ShowRecurringWarningErrorAtEnd(state,
    7163           0 :                                                "WaterHeater:Mixed = " + this->Name + " Heater is cycling on and off more than once per second:",
    7164             :                                                this->MaxCycleErrorIndex);
    7165             :             }
    7166             : 
    7167           0 :             break;
    7168             : 
    7169             :         } // CycleOnCount > MaxCycles
    7170             : 
    7171             :     } // TimeRemaining > 0.0
    7172             : 
    7173             :     // Calculate average values over the DataGlobals::TimeStep based on summed values, Q > 0 is a gain to the tank,  Q < 0 is a loss to the tank
    7174     6395474 :     Real64 TankTempAvg_loc = Tsum / SecInTimeStep;
    7175     6395474 :     Qloss = Eloss / SecInTimeStep;
    7176     6395474 :     Real64 Qlosszone = Elosszone / SecInTimeStep;
    7177     6395474 :     Quse = Euse / SecInTimeStep;
    7178     6395474 :     Qsource = Esource / SecInTimeStep;
    7179     6395474 :     Qheater = Eheater / SecInTimeStep;
    7180     6395474 :     Qoffcycfuel = Eoffcycfuel / SecInTimeStep;
    7181     6395474 :     Qoffcycheat = Qoffcycfuel * this->OffCycParaFracToTank;
    7182     6395474 :     Qoncycfuel = Eoncycfuel / SecInTimeStep;
    7183     6395474 :     Qoncycheat = Qoncycfuel * this->OnCycParaFracToTank;
    7184     6395474 :     Qvent = Event / SecInTimeStep;
    7185     6395474 :     Qneeded = Eneeded / SecInTimeStep;
    7186     6395474 :     Qunmet = Eunmet / SecInTimeStep;
    7187     6395474 :     Real64 RTF = Runtime / SecInTimeStep;
    7188     6395474 :     PLR = PLRsum / SecInTimeStep;
    7189             : 
    7190     6395474 :     if (this->ControlType == HeaterControlMode::Cycle) {
    7191             :         // Recalculate Part Load Factor and fuel energy based on Runtime Fraction, instead of Part Load Ratio
    7192     6340886 :         PLF = this->PartLoadFactor(state, RTF);
    7193     6340886 :         Efuel = Eheater / (PLF * this->Efficiency);
    7194             :     }
    7195             : 
    7196     6395474 :     Qfuel = Efuel / SecInTimeStep;
    7197             : 
    7198     6395474 :     this->Mode = Mode_loc;               // Operating mode for carry-over to next DataGlobals::TimeStep
    7199     6395474 :     this->TankTemp = TankTemp_loc;       // Final tank temperature for carry-over to next DataGlobals::TimeStep
    7200     6395474 :     this->TankTempAvg = TankTempAvg_loc; // Average tank temperature over the DataGlobals::TimeStep for reporting
    7201             : 
    7202     6395474 :     if (!state.dataGlobal->WarmupFlag) {
    7203             :         // Warn for potential freezing when avg of final temp over all nodes is below 2°C (nearing 0°C)
    7204      825294 :         if (this->TankTemp < 2) {
    7205           0 :             if (this->FreezingErrorIndex == 0) {
    7206           0 :                 ShowWarningError(state,
    7207           0 :                                  format("{}: {} = '{}':  Temperature of tank < 2C indicates of possibility of freeze. Tank Temperature = {:.2R} C.",
    7208             :                                         RoutineName,
    7209             :                                         this->Type,
    7210             :                                         this->Name,
    7211           0 :                                         this->TankTemp));
    7212           0 :                 ShowContinueErrorTimeStamp(state, "");
    7213             :             }
    7214           0 :             ShowRecurringWarningErrorAtEnd(state,
    7215           0 :                                            this->Type + " = '" + this->Name + "':  Temperature of tank < 2C indicates of possibility of freeze",
    7216             :                                            this->FreezingErrorIndex,
    7217             :                                            this->TankTemp, // Report Max
    7218             :                                            this->TankTemp, // Report Min
    7219             :                                            _,              // Don't report Sum
    7220             :                                            "{C}",          // Max Unit
    7221             :                                            "{C}");         // Min Unit
    7222             :         }
    7223             :     }
    7224     6395474 :     this->UseOutletTemp = TankTempAvg_loc;    // Because entire tank is at same temperature
    7225     6395474 :     this->SourceOutletTemp = TankTempAvg_loc; // Because entire tank is at same temperature
    7226     6395474 :     if (this->HeatPumpNum > 0) {
    7227     1122477 :         this->SourceInletTemp =
    7228     1122477 :             TankTempAvg_loc + HPWHCondenserDeltaT; // Update the source inlet temperature to the average over the DataGlobals::TimeStep
    7229             :     }
    7230             : 
    7231     6395474 :     this->LossRate = Qloss;
    7232     6395474 :     this->UseRate = Quse;
    7233     6395474 :     this->SourceRate = Qsource;
    7234     6395474 :     this->OffCycParaRateToTank = Qoffcycheat;
    7235     6395474 :     this->OnCycParaRateToTank = Qoncycheat;
    7236     6395474 :     this->TotalDemandRate = -Quse - Qsource - Qloss - Qoffcycheat - Qoncycheat;
    7237     6395474 :     this->HeaterRate = Qheater;
    7238     6395474 :     this->UnmetRate = Qunmet;
    7239     6395474 :     this->VentRate = Qvent;
    7240     6395474 :     this->NetHeatTransferRate = Quse + Qsource + Qloss + Qoffcycheat + Qoncycheat + Qheater + Qvent;
    7241             : 
    7242     6395474 :     this->CycleOnCount = CycleOnCount_loc;
    7243     6395474 :     this->RuntimeFraction = RTF;
    7244     6395474 :     this->PartLoadRatio = PLR;
    7245             : 
    7246     6395474 :     this->FuelRate = Qfuel;
    7247     6395474 :     this->OffCycParaFuelRate = Qoffcycfuel;
    7248     6395474 :     this->OnCycParaFuelRate = Qoncycfuel;
    7249             : 
    7250             :     // Add water heater skin losses and venting losses to ambient zone, if specified
    7251     6395474 :     if (this->AmbientTempZone > 0) this->AmbientZoneGain = -Qlosszone - Qvent;
    7252     6395474 : }
    7253             : 
    7254     6395474 : void WaterThermalTankData::CalcMixedTankSourceSideHeatTransferRate(
    7255             :     Real64 HPWHCondenserDeltaT, // input, The temperature difference (C) across the heat pump, zero if
    7256             :                                 // there is no heat pump or if the heat pump is off
    7257             :     Real64 SourceInletTemp,     // input, Source inlet temperature (C)
    7258             :     Real64 Cp,                  // Specific heat of fluid (J/kg deltaC)
    7259             :     Real64 SetPointTemp,        // input, Mixed tank set point temperature
    7260             :     Real64 &SourceMassFlowRate, // source mass flow rate (kg/s)
    7261             :     Real64 &Qheatpump,          // heat transfer rate from heat pump
    7262             :     Real64 &Qsource             // steady state heat transfer rate from a constant temperature source side flow
    7263             : )
    7264             : {
    7265             :     // Function Information:
    7266             :     //        Author: Noel Merket
    7267             :     //        Date Written: January 2015
    7268             :     //        Modified: na
    7269             :     //        Re-engineered: na
    7270             : 
    7271             :     // Purpose of this function:
    7272             :     // Determines if the source side heat transfer is coming from a heat pump.
    7273             :     // If so it treats the source side heat transfer as a constant heat source
    7274             :     // If it is not coming from a heat pump it treats the source side heat transfer
    7275             :     // as a constant temperature.
    7276             : 
    7277             :     // Determine if the source side heating is coming from a heat pump.
    7278     6395474 :     Qheatpump = SourceMassFlowRate * Cp * HPWHCondenserDeltaT;
    7279     6395474 :     if (Qheatpump > 0.0) {
    7280      630608 :         SourceMassFlowRate = 0.0; // Handle this heating as a constant heat source
    7281      630608 :         Qsource = Qheatpump;
    7282             :     } else {
    7283     5764866 :         Qsource = SourceMassFlowRate * Cp * (SourceInletTemp - SetPointTemp);
    7284             :     }
    7285     6395474 : }
    7286             : 
    7287    13164586 : Real64 WaterThermalTankData::CalcTimeNeeded(Real64 const Ti, // Initial tank temperature (C)
    7288             :                                             Real64 const Tf, // Final tank temperature (C)
    7289             :                                             Real64 const Ta, // Ambient environment temperature (C)
    7290             :                                             Real64 const T1, // Temperature of flow 1 (C)
    7291             :                                             Real64 const T2, // Temperature of flow 2 (C)
    7292             :                                             Real64 const m,  // Mass of tank fluid (kg)
    7293             :                                             Real64 const Cp, // Specific heat of fluid (J/kg deltaC)
    7294             :                                             Real64 const m1, // Mass flow rate 1 (kg/s)
    7295             :                                             Real64 const m2, // Mass flow rate 2 (kg/s)
    7296             :                                             Real64 const UA, // Heat loss coefficient to ambient environment (W/deltaC)
    7297             :                                             Real64 const Q   // Net heating rate for non-temp dependent sources, i.e. heater and parasitics (W)
    7298             : )
    7299             : {
    7300             : 
    7301             :     // SUBROUTINE INFORMATION:
    7302             :     //       AUTHOR         Peter Graham Ellis
    7303             :     //       DATE WRITTEN   February 2005
    7304             :     //       MODIFIED       na
    7305             :     //       RE-ENGINEERED  na
    7306             : 
    7307             :     // PURPOSE OF THIS SUBROUTINE:
    7308             :     // Calculates the time needed for the tank temperature to change from Ti to Tf given heat loss,
    7309             :     // mass flow rates and temperatures, and net heat transfer due to heater and parasitics.
    7310             : 
    7311             :     // METHODOLOGY EMPLOYED:
    7312             :     // Equations are derived by solving the differential equation governing the tank energy balance.
    7313             :     // Special cases which cause the natural logarithm to blow up are trapped and interpreted as
    7314             :     // requiring an infinite amount of time because Tf can never be reached under the given conditions.
    7315             : 
    7316             :     // Return value
    7317             :     Real64 CalcTimeNeeded;
    7318             : 
    7319             :     // SUBROUTINE PARAMETER DEFINITIONS:
    7320    13164586 :     Real64 constexpr Infinity(99999999.9); // A time interval much larger than any single DataGlobals::TimeStep (s)
    7321             : 
    7322             :     Real64 t; // Time elapsed from Ti to Tf (s)
    7323             : 
    7324    13164586 :     if (Tf == Ti) {
    7325             :         // Already at Tf; no time is needed
    7326           0 :         t = 0.0;
    7327             : 
    7328             :     } else {
    7329             :         Real64 a;        // Intermediate variable
    7330             :         Real64 b;        // Intermediate variable
    7331             :         Real64 Tm;       // Mixed temperature after an infinite amount of time has passed (C)
    7332             :         Real64 quotient; // Intermediate variable
    7333             : 
    7334    13164586 :         if (UA / Cp + m1 + m2 == 0.0) {
    7335             : 
    7336       23543 :             if (Q == 0.0) {
    7337             :                 // With no mass flow and no heat flow and Tf<>Ti, then Tf can never be reached
    7338       22578 :                 t = Infinity;
    7339             : 
    7340             :             } else {
    7341         965 :                 a = Q / (m * Cp);
    7342             : 
    7343         965 :                 t = (Tf - Ti) / a;
    7344             :             }
    7345             : 
    7346             :         } else {
    7347    13141043 :             a = (Q / Cp + UA * Ta / Cp + m1 * T1 + m2 * T2) / m;
    7348    13141043 :             b = -(UA / Cp + m1 + m2) / m;
    7349             : 
    7350             :             // Calculate the mixed temperature Tm of the tank after an infinite amount of time has passed
    7351    13141043 :             Tm = -a / b;
    7352             : 
    7353    13141043 :             if (Tm == Ti) {
    7354             :                 // Mixed temperature is the same as Ti; if Tf<>Ti, then Tf can never be reached
    7355        1971 :                 t = Infinity;
    7356             : 
    7357    13139072 :             } else if (Tm == Tf) {
    7358             :                 // Tf only approaches Tm; it can never actually get there in finite time (also avoids divide by zero error)
    7359           0 :                 t = Infinity;
    7360             : 
    7361             :             } else {
    7362    13139072 :                 quotient = (Tf - Tm) / (Ti - Tm);
    7363             : 
    7364    13139072 :                 if (quotient <= 0.0) { // Autodesk:Num Changed < to <= to elim poss floating point error in LOG call
    7365             :                     // Tm is in between Ti and Tf; Tf can never be reached
    7366      554895 :                     t = Infinity;
    7367             : 
    7368             :                 } else {
    7369    12584177 :                     t = std::log(quotient) / b;
    7370             :                 }
    7371             :             }
    7372             :         }
    7373             : 
    7374    13164586 :         if (t < 0.0) t = Infinity; // If negative time, Tf can never be reached in the future
    7375             :     }
    7376             : 
    7377    13164586 :     CalcTimeNeeded = t;
    7378             : 
    7379    13164586 :     return CalcTimeNeeded;
    7380             : }
    7381             : 
    7382     6420614 : Real64 WaterThermalTankData::CalcTankTemp(Real64 const Ti, // Initial tank temperature (C)
    7383             :                                           Real64 const Ta, // Ambient environment temperature (C)
    7384             :                                           Real64 const T1, // Temperature of flow 1 (C)
    7385             :                                           Real64 const T2, // Temperature of flow 2 (C)
    7386             :                                           Real64 const m,  // Mass of tank fluid (kg)
    7387             :                                           Real64 const Cp, // Specific heat of fluid (J/kg deltaC)
    7388             :                                           Real64 const m1, // Mass flow rate 1 (kg/s)
    7389             :                                           Real64 const m2, // Mass flow rate 2 (kg/s)
    7390             :                                           Real64 const UA, // Heat loss coefficient to ambient environment (W/deltaC)
    7391             :                                           Real64 const Q,  // Net heating rate for non-temp dependent sources, i.e. heater and parasitics (W)
    7392             :                                           Real64 const t   // Time elapsed from Ti to Tf (s)
    7393             : )
    7394             : {
    7395             : 
    7396             :     // SUBROUTINE INFORMATION:
    7397             :     //       AUTHOR         Peter Graham Ellis
    7398             :     //       DATE WRITTEN   February 2005
    7399             :     //       MODIFIED       na
    7400             :     //       RE-ENGINEERED  na
    7401             : 
    7402             :     // PURPOSE OF THIS SUBROUTINE:
    7403             :     // Calculates the final tank temperature Tf after time t has elapsed given heat loss,
    7404             :     // mass flow rates and temperatures, and net heat transfer due to heater and parasitics.
    7405             : 
    7406             :     // METHODOLOGY EMPLOYED:
    7407             :     // Equations are derived by solving the differential equation governing the tank energy balance.
    7408             : 
    7409             :     // Return value
    7410             :     Real64 CalcTankTemp;
    7411             : 
    7412             :     // Locals
    7413             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    7414             : 
    7415             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    7416             :     Real64 a;  // Intermediate variable
    7417             :     Real64 b;  // Intermediate variable
    7418             :     Real64 Tf; // Final tank temperature (C)
    7419             : 
    7420     6420614 :     if (UA / Cp + m1 + m2 == 0.0) {
    7421       23471 :         a = Q / (m * Cp);
    7422             : 
    7423       23471 :         Tf = a * t + Ti;
    7424             : 
    7425             :     } else {
    7426     6397143 :         a = (Q / Cp + UA * Ta / Cp + m1 * T1 + m2 * T2) / m;
    7427     6397143 :         b = -(UA / Cp + m1 + m2) / m;
    7428             : 
    7429     6397143 :         Tf = (a / b + Ti) * std::exp(b * t) - a / b;
    7430             :     }
    7431             : 
    7432     6420614 :     CalcTankTemp = Tf;
    7433             : 
    7434     6420614 :     return CalcTankTemp;
    7435             : }
    7436             : 
    7437    13617060 : Real64 WaterThermalTankData::CalcTempIntegral(Real64 const Ti, // Initial tank temperature (C)
    7438             :                                               Real64 const Tf, // Final tank temperature (C)
    7439             :                                               Real64 const Ta, // Ambient environment temperature (C)
    7440             :                                               Real64 const T1, // Temperature of flow 1 (C)
    7441             :                                               Real64 const T2, // Temperature of flow 2 (C)
    7442             :                                               Real64 const m,  // Mass of tank fluid (kg)
    7443             :                                               Real64 const Cp, // Specific heat of fluid (J/kg deltaC)
    7444             :                                               Real64 const m1, // Mass flow rate 1 (kg/s)
    7445             :                                               Real64 const m2, // Mass flow rate 2 (kg/s)
    7446             :                                               Real64 const UA, // Heat loss coefficient to ambient environment (W/deltaC)
    7447             :                                               Real64 const Q,  // Net heating rate for non-temp dependent sources, i.e. heater and parasitics (W)
    7448             :                                               Real64 const t   // Time elapsed from Ti to Tf (s)
    7449             : )
    7450             : {
    7451             : 
    7452             :     // SUBROUTINE INFORMATION:
    7453             :     //       AUTHOR         Peter Graham Ellis
    7454             :     //       DATE WRITTEN   February 2005
    7455             :     //       MODIFIED       na
    7456             :     //       RE-ENGINEERED  na
    7457             : 
    7458             :     // PURPOSE OF THIS SUBROUTINE:
    7459             :     // Calculates the integral of the tank temperature from Ti to Tf.  The integral is added to a sum which is
    7460             :     // later divided by the elapsed time to yield the average tank temperature over the DataGlobals::TimeStep.
    7461             : 
    7462             :     // METHODOLOGY EMPLOYED:
    7463             :     // Equations are the mathematical integrals of the governing differential equations.
    7464             : 
    7465             :     // Return value
    7466             :     Real64 CalcTempIntegral;
    7467             : 
    7468             :     // Locals
    7469             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    7470             : 
    7471             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    7472             :     Real64 a;     // Intermediate variable
    7473             :     Real64 b;     // Intermediate variable
    7474             :     Real64 dTsum; // Integral of tank temperature (C s)
    7475             : 
    7476    13617060 :     if (t == 0.0) {
    7477           0 :         dTsum = 0.0;
    7478             : 
    7479    13617060 :     } else if (Tf == Ti) { // Steady-state conditions
    7480      179295 :         dTsum = Tf * t;
    7481             : 
    7482    13437765 :     } else if (UA / Cp + m1 + m2 == 0.0) {
    7483         965 :         a = Q / (m * Cp);
    7484             : 
    7485             :         // Integral of T(t) = a * t + Ti, evaluated from 0 to t
    7486         965 :         dTsum = 0.5 * a * t * t + Ti * t;
    7487             : 
    7488             :     } else {
    7489    13436800 :         a = (Q / Cp + UA * Ta / Cp + m1 * T1 + m2 * T2) / m;
    7490    13436800 :         b = -(UA / Cp + m1 + m2) / m;
    7491             : 
    7492             :         // Integral of T(t) = (a / b + Ti) * EXP(b * t) - a / b, evaluated from 0 to t
    7493    13436800 :         dTsum = (a / b + Ti) * (std::exp(b * t) - 1.0) / b - a * t / b;
    7494             :     }
    7495             : 
    7496    13617060 :     CalcTempIntegral = dTsum;
    7497             : 
    7498    13617060 :     return CalcTempIntegral;
    7499             : }
    7500             : 
    7501    10427259 : Real64 WaterThermalTankData::PartLoadFactor(EnergyPlusData &state, Real64 const PartLoadRatio_loc)
    7502             : {
    7503             : 
    7504             :     // SUBROUTINE INFORMATION:
    7505             :     //       AUTHOR         Peter Graham Ellis
    7506             :     //       DATE WRITTEN   January 2005
    7507             :     //       MODIFIED       na
    7508             :     //       RE-ENGINEERED  na
    7509             : 
    7510             :     // PURPOSE OF THIS SUBROUTINE:
    7511             :     // Calculates the Part Load Factor (PLF) based on a curve correlated to Part Load Ratio, if Heater Control Type
    7512             :     // is MODULATE, or correlated to Runtime Fraction, if Heater Control Type is CYCLE.
    7513             : 
    7514    10427259 :     if (this->PLFCurve > 0) {
    7515        1260 :         return max(Curve::CurveValue(state, this->PLFCurve, PartLoadRatio_loc), 0.1);
    7516             :     } else {
    7517    10425999 :         return 1.0;
    7518             :     }
    7519             : }
    7520             : 
    7521     1542319 : void WaterThermalTankData::CalcWaterThermalTankStratified(EnergyPlusData &state)
    7522             : {
    7523             :     // SUBROUTINE INFORMATION:
    7524             :     //       AUTHOR         Noel Merket, originally by Peter Graham Ellis
    7525             :     //       DATE WRITTEN   January 2007
    7526             :     //       MODIFIED       Nov 2011, BAN; modified the use and source outlet temperature calculation
    7527             :     //       RE-ENGINEERED  Noel Merket, November 2018
    7528             : 
    7529             :     // PURPOSE OF THIS SUBROUTINE:
    7530             :     // Simulates a stratified, multi-node water heater tank with up to two heating elements.
    7531             : 
    7532             :     // METHODOLOGY EMPLOYED:
    7533             :     // This model uses a numerical calculation based on an analytical solution of the ODE dT/dt = a*T + b.
    7534             :     // A heat balance is calculated for each node.
    7535             :     // Temperatures and energies change dynamically over the system time step.
    7536             :     // Final node temperatures are reported as final instantaneous values as well as averages over the
    7537             :     // time step.  Heat transfer rates are averages over the time step.
    7538             : 
    7539             :     static constexpr std::string_view RoutineName("CalcWaterThermalTankStratified");
    7540     1542319 :     constexpr Real64 TemperatureConvergenceCriteria = 0.0001;
    7541     1542319 :     const Real64 SubTimestepMax = 60.0 * 10.0; // seconds
    7542     1542319 :     constexpr Real64 SubTimestepMin = 10.0;    // seconds
    7543             :     Real64 dt;
    7544             : 
    7545             :     // Tank object reference
    7546     1542319 :     const Real64 &nTankNodes = this->Nodes;
    7547             : 
    7548             :     // Fraction of the current hour that has elapsed (h)
    7549             :     const Real64 TimeElapsed_loc =
    7550     1542319 :         state.dataGlobal->HourOfDay + state.dataGlobal->TimeStep * state.dataGlobal->TimeStepZone + state.dataHVACGlobal->SysTimeElapsed;
    7551             : 
    7552             :     // Seconds in one DataGlobals::TimeStep (s)
    7553     1542319 :     const Real64 SecInTimeStep = state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    7554             : 
    7555             :     // Advance tank simulation to the next system DataGlobals::TimeStep, if applicable
    7556     1542319 :     if (this->TimeElapsed != TimeElapsed_loc) {
    7557             :         // The simulation has advanced to the next system DataGlobals::TimeStep.  Save conditions from the end of the previous system
    7558             :         // DataGlobals::TimeStep for use as the initial conditions of each iteration that does not advance the system DataGlobals::TimeStep.
    7559      424997 :         for (auto &e : this->Node)
    7560      371968 :             e.SavedTemp = e.Temp;
    7561             : 
    7562       53029 :         this->SavedHeaterOn1 = this->HeaterOn1;
    7563       53029 :         this->SavedHeaterOn2 = this->HeaterOn2;
    7564             : 
    7565             :         // Save outlet temperatures for demand-side flow control
    7566       53029 :         this->SavedUseOutletTemp = this->UseOutletTemp;
    7567       53029 :         this->SavedSourceOutletTemp = this->SourceOutletTemp;
    7568             : 
    7569       53029 :         this->TimeElapsed = TimeElapsed_loc;
    7570             :     }
    7571             : 
    7572             :     // Reset node temperatures to what they were at the beginning of the system DataGlobals::TimeStep.
    7573    10107085 :     for (auto &e : this->Node)
    7574     8564766 :         e.Temp = e.SavedTemp;
    7575             : 
    7576     1542319 :     this->HeaterOn1 = this->SavedHeaterOn1;
    7577     1542319 :     this->HeaterOn2 = this->SavedHeaterOn2;
    7578             : 
    7579             :     // Condenser configuration of heat pump water heater
    7580             :     const DataPlant::PlantEquipmentType HPWHCondenserConfig =
    7581     1542319 :         this->HeatPumpNum > 0 ? state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).HPWHType : DataPlant::PlantEquipmentType::Invalid;
    7582             : 
    7583             :     // Heat rate from the heat pump (W)
    7584     4123851 :     const Real64 Qheatpump = [&, this] { // BLB
    7585     1542319 :         if (this->HeatPumpNum == 0) return 0.0;
    7586     3872298 :         HeatPumpWaterHeaterData const &HPWH = state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum);
    7587             :         Real64 CoilTotalHeatingEnergyRate;
    7588     1290766 :         if (HPWH.NumofSpeed > 0) {
    7589             :             // VSHPWH
    7590       70618 :             VariableSpeedCoils::VariableSpeedCoilData const &Coil = state.dataVariableSpeedCoils->VarSpeedCoil(HPWH.DXCoilNum);
    7591       70618 :             CoilTotalHeatingEnergyRate = Coil.TotalHeatingEnergyRate;
    7592             :         } else {
    7593             :             // Single speed HPWH
    7594     1220148 :             DXCoils::DXCoilData const &Coil = state.dataDXCoils->DXCoil(HPWH.DXCoilNum);
    7595     1220148 :             CoilTotalHeatingEnergyRate = Coil.TotalHeatingEnergyRate;
    7596             :         }
    7597     1290766 :         return CoilTotalHeatingEnergyRate * this->SourceEffectiveness;
    7598     1542319 :     }();
    7599             : 
    7600             :     // Minimum tank temperatures
    7601     1542319 :     const Real64 MinTemp1 = this->SetPointTemp - this->DeadBandDeltaTemp;
    7602     1542319 :     const Real64 MinTemp2 = this->SetPointTemp2 - this->DeadBandDeltaTemp2;
    7603             : 
    7604             :     // Specific Heat of water (J/kg K)
    7605     1542319 :     const Real64 Cp = [&] {
    7606     6096703 :         if (this->UseSidePlantLoc.loopNum > 0) {
    7607     5951557 :             return FluidProperties::GetSpecificHeatGlycol(state,
    7608     2939492 :                                                           state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
    7609             :                                                           this->TankTemp,
    7610     2939492 :                                                           state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
    7611     1469746 :                                                           RoutineName);
    7612             :         } else {
    7613      217719 :             return FluidProperties::GetSpecificHeatGlycol(state, fluidNameWater, this->TankTemp, this->waterIndex, RoutineName);
    7614             :         }
    7615     1542319 :     }();
    7616             : 
    7617     1542319 :     Real64 Eloss = 0.0;             // Energy change due to ambient losses over the DataGlobals::TimeStep (J)
    7618     1542319 :     Real64 Euse = 0.0;              // Energy change due to use side mass flow over the DataGlobals::TimeStep (J)
    7619     1542319 :     Real64 Esource = 0.0;           // Energy change due to source side mass flow over the DataGlobals::TimeStep (J)
    7620     1542319 :     Real64 Eheater1 = 0.0;          // Energy change due to heater 1 over the DataGlobals::TimeStep (J)
    7621     1542319 :     Real64 Eheater2 = 0.0;          // Energy change due to heater 2 over the DataGlobals::TimeStep (J)
    7622     1542319 :     Real64 Eunmet = 0.0;            // Energy change unmet over the DataGlobals::TimeStep (J)
    7623     1542319 :     Real64 Event = 0.0;             // Energy change due to venting over the DataGlobals::TimeStep (J)
    7624     1542319 :     int CycleOnCount1_loc = 0;      // Number of times heater 1 cycles on in the current time step
    7625     1542319 :     int CycleOnCount2_loc = 0;      // Number of times heater 2 cycles on in the current time step
    7626     1542319 :     Real64 Runtime = 0.0;           // Time that either heater is running (s)
    7627     1542319 :     Real64 Runtime1 = 0.0;          // Time that heater 1 is running (s)
    7628     1542319 :     Real64 Runtime2 = 0.0;          // Time that heater 2 is running (s)
    7629     1542319 :     bool SetPointRecovered = false; // Flag to indicate when set point is recovered for the first time
    7630             :     // Added three variables for desuperheater sourceinlet temperature update
    7631             :     Real64 MdotDesuperheaterWater;        // mass flow rate of desuperheater source side water, kg/s
    7632     1542319 :     Real64 DesuperheaterPLR = 0.0;        // Desuperheater part load ratio
    7633     1542319 :     Real64 DesuperheaterHeaterRate = 0.0; // Desuperheater heater rate (W)
    7634     1542319 :     Real64 SourceInletTempSum = 0.0;      // Sum the source inlet temperature in sub time step to calculate average tempearature
    7635             :     Real64 Qheater1;                      // Heating rate of burner or electric heating element 1 (W)
    7636             :     Real64 Qheater2;                      // Heating rate of burner or electric heating element 2 (W)
    7637             : 
    7638     1542319 :     if (this->InletMode == InletPositionMode::Fixed) CalcNodeMassFlows(InletPositionMode::Fixed);
    7639             : 
    7640             :     // Time remaining in the current DataGlobals::TimeStep (s)
    7641     1542319 :     Real64 TimeRemaining = SecInTimeStep;
    7642             : 
    7643             :     // Diff Eq. Coefficients for each node
    7644     3084638 :     std::vector<Real64> A;
    7645     1542319 :     A.resize(nTankNodes);
    7646     3084638 :     std::vector<Real64> B;
    7647     1542319 :     B.resize(nTankNodes);
    7648             : 
    7649             :     // Temperature at the end of the internal DataGlobals::TimeStep
    7650     3084638 :     std::vector<Real64> Tfinal;
    7651     1542319 :     Tfinal.resize(nTankNodes);
    7652             : 
    7653             :     // Average temperature of each node over the internal DataGlobals::TimeStep
    7654     3084638 :     std::vector<Real64> Tavg;
    7655     1542319 :     Tavg.resize(nTankNodes);
    7656             : 
    7657     1542319 :     int SubTimestepCount = 0;
    7658             : 
    7659    15771569 :     while (TimeRemaining > 0.0) {
    7660             : 
    7661     7114625 :         ++SubTimestepCount;
    7662             : 
    7663     7114625 :         bool PrevHeaterOn1 = this->HeaterOn1;
    7664     7114625 :         bool PrevHeaterOn2 = this->HeaterOn2;
    7665             : 
    7666     7114625 :         if (this->InletMode == InletPositionMode::Seeking) CalcNodeMassFlows(InletPositionMode::Seeking);
    7667             : 
    7668             :         // Heater control logic
    7669     7114625 :         if (this->IsChilledWaterTank) {
    7670             :             // Chilled Water Tank, no heating
    7671      346050 :             Qheater1 = 0.0;
    7672      346050 :             Qheater2 = 0.0;
    7673             :         } else {
    7674             :             // Control the first heater element (master)
    7675     6768575 :             if (this->MaxCapacity > 0.0) {
    7676     2845198 :                 const Real64 &NodeTemp = this->Node(this->HeaterNode1).Temp;
    7677             : 
    7678     2845198 :                 if (this->HeaterOn1) {
    7679      284631 :                     if (NodeTemp >= this->SetPointTemp) {
    7680       43767 :                         this->HeaterOn1 = false;
    7681       43767 :                         SetPointRecovered = true;
    7682             :                     }
    7683             :                 } else { // Heater is off
    7684     2560567 :                     if (NodeTemp < MinTemp1) {
    7685       85038 :                         this->HeaterOn1 = true;
    7686       85038 :                         ++CycleOnCount1_loc;
    7687             :                     }
    7688             :                 }
    7689             :             }
    7690             : 
    7691     6768575 :             if (this->HeaterOn1) {
    7692      325939 :                 Qheater1 = this->MaxCapacity;
    7693             :             } else {
    7694     6442636 :                 Qheater1 = 0.0;
    7695             :             }
    7696             : 
    7697             :             // Control the second heater element (slave)
    7698     6768575 :             if (this->MaxCapacity2 > 0.0) {
    7699      756839 :                 if ((this->StratifiedControlMode == PriorityControlMode::MasterSlave) && this->HeaterOn1) {
    7700       30941 :                     this->HeaterOn2 = false;
    7701             : 
    7702             :                 } else {
    7703      725898 :                     const Real64 &NodeTemp = this->Node(this->HeaterNode2).Temp;
    7704             : 
    7705      725898 :                     if (this->HeaterOn2) {
    7706      422923 :                         if (NodeTemp >= this->SetPointTemp2) {
    7707        6982 :                             this->HeaterOn2 = false;
    7708        6982 :                             SetPointRecovered = true;
    7709             :                         }
    7710             :                     } else { // Heater is off
    7711      302975 :                         if (NodeTemp < MinTemp2) {
    7712       58350 :                             this->HeaterOn2 = true;
    7713       58350 :                             ++CycleOnCount2_loc;
    7714             :                         }
    7715             :                     }
    7716             :                 }
    7717             :             }
    7718             : 
    7719     6768575 :             if (this->HeaterOn2) {
    7720      474291 :                 Qheater2 = this->MaxCapacity2;
    7721             :             } else {
    7722     6294284 :                 Qheater2 = 0.0;
    7723             :             }
    7724             :         }
    7725             : 
    7726     7114625 :         if (SubTimestepCount == 1) {
    7727     1542319 :             dt = SubTimestepMin;
    7728             :         } else {
    7729             : 
    7730             :             // Set the maximum tank temperature change allowed
    7731     5572306 :             Real64 dT_max = std::numeric_limits<Real64>::max();
    7732     5572306 :             if (this->HeaterOn1) {
    7733      316073 :                 if (this->Node(this->HeaterNode1).Temp < this->SetPointTemp) {
    7734             :                     // Node temperature is less than setpoint and heater is on
    7735      316057 :                     dT_max = min(dT_max, this->SetPointTemp - this->Node(this->HeaterNode1).Temp);
    7736             :                 } else {
    7737             :                     // Node temperature is greater than or equal to setpoint and heater is on
    7738             :                     // Heater will turn off next time around, calculate assuming that
    7739          16 :                     dT_max = min(dT_max, this->Node(this->HeaterNode1).Temp - MinTemp1);
    7740             :                 }
    7741             :             } else { // Heater off
    7742     5256233 :                 if (this->Node(this->HeaterNode1).Temp >= MinTemp1) {
    7743             :                     // Node temperature is greater than or equal to cut in temperature and heater is off
    7744     3481805 :                     dT_max = min(dT_max, this->Node(this->HeaterNode1).Temp - MinTemp1);
    7745             :                 } else {
    7746             :                     // Heater will turn on next time around, calculate to setpoint
    7747     1774428 :                     dT_max = min(dT_max, this->SetPointTemp - this->Node(this->HeaterNode1).Temp);
    7748             :                 }
    7749             :             }
    7750     5572306 :             if (this->HeaterOn2) {
    7751      454788 :                 if (this->Node(this->HeaterNode2).Temp < this->SetPointTemp2) {
    7752             :                     // Node temperature is less than setpoint and heater is on
    7753      454788 :                     dT_max = min(dT_max, this->SetPointTemp2 - this->Node(this->HeaterNode2).Temp);
    7754             :                 } else {
    7755             :                     // Node temperature is greater than or equal to setpoint and heater is on
    7756             :                     // Heater will turn off next time around, calculate assuming that
    7757           0 :                     dT_max = min(dT_max, this->Node(this->HeaterNode2).Temp - MinTemp2);
    7758             :                 }
    7759             :             } else { // Heater off
    7760     5117518 :                 if (this->Node(this->HeaterNode2).Temp >= MinTemp2) {
    7761             :                     // Node temperature is greater than or equal to cut in temperature and heater is off
    7762     2514282 :                     dT_max = min(dT_max, this->Node(this->HeaterNode2).Temp - MinTemp2);
    7763             :                 } else {
    7764             :                     // Heater will turn on next time around, calculate to setpoint
    7765     2603236 :                     dT_max = min(dT_max, this->SetPointTemp2 - this->Node(this->HeaterNode2).Temp);
    7766             :                 }
    7767             :             }
    7768             : 
    7769             :             // Make adjustments to A and B to account for heaters being on or off now
    7770     5572306 :             if (this->HeaterOn1 && !PrevHeaterOn1) {
    7771             :                 // If heater 1 is on now and wasn't before add the heat rate to the B term
    7772       83716 :                 B[this->HeaterNode1 - 1] += Qheater1 / (this->Node(this->HeaterNode1).Mass * Cp);
    7773     5488590 :             } else if (!this->HeaterOn1 && PrevHeaterOn1) {
    7774             :                 // If heater 1 is off now and was on before, remove the heat rate from the B term
    7775       42010 :                 B[this->HeaterNode1 - 1] -= this->MaxCapacity / (this->Node(this->HeaterNode1).Mass * Cp);
    7776             :             }
    7777     5572306 :             if (this->HeaterOn2 && !PrevHeaterOn2) {
    7778             :                 // If heater 2 is on now and wasn't before add the heat rate to the B term
    7779       57698 :                 B[this->HeaterNode2 - 1] += Qheater2 / (this->Node(this->HeaterNode2).Mass * Cp);
    7780     5514608 :             } else if (!this->HeaterOn2 && PrevHeaterOn2) {
    7781             :                 // If heater 1 is off now and was on before, remove the heat rate from the B term
    7782       12221 :                 B[this->HeaterNode2 - 1] -= this->MaxCapacity / (this->Node(this->HeaterNode2).Mass * Cp);
    7783             :             }
    7784             : 
    7785     5572306 :             if ((this->HeaterOn1 || this->HeaterOn2) && !(PrevHeaterOn1 || PrevHeaterOn2)) {
    7786             :                 // Remove off cycle loads
    7787             :                 // Apply on cycle loads
    7788     1267079 :                 for (int i = 0; i < nTankNodes; i++) {
    7789     1131604 :                     auto &node(this->Node[i]);
    7790     1131604 :                     Real64 NodeCapacitance = node.Mass * Cp;
    7791     1131604 :                     A[i] += (node.OffCycLossCoeff - node.OnCycLossCoeff) / NodeCapacitance;
    7792     1131604 :                     B[i] += (-node.OffCycParaLoad + node.OnCycParaLoad + (node.OnCycLossCoeff - node.OffCycLossCoeff) * this->AmbientTemp) /
    7793             :                             NodeCapacitance;
    7794      135475 :                 }
    7795     5436831 :             } else if (!(this->HeaterOn1 || this->HeaterOn2) && (PrevHeaterOn1 || PrevHeaterOn2)) {
    7796             :                 // Remove on cycle loads
    7797             :                 // Apply off cycle loads
    7798      505302 :                 for (int i = 0; i < nTankNodes; i++) {
    7799      457010 :                     auto &node(this->Node[i]);
    7800      457010 :                     Real64 NodeCapacitance = node.Mass * Cp;
    7801      457010 :                     A[i] -= (node.OffCycLossCoeff - node.OnCycLossCoeff) / NodeCapacitance;
    7802      457010 :                     B[i] -= (-node.OffCycParaLoad + node.OnCycParaLoad + (node.OnCycLossCoeff - node.OffCycLossCoeff) * this->AmbientTemp) /
    7803             :                             NodeCapacitance;
    7804             :                 }
    7805             :             }
    7806             : 
    7807             :             // Set the sub DataGlobals::TimeStep (dt)
    7808     5572306 :             dt = TimeRemaining;
    7809    33065752 :             for (int i = 0; i < nTankNodes; ++i) {
    7810    27493446 :                 const Real64 Denominator = fabs(A[i] * Tavg[i] + B[i]);
    7811    27493446 :                 if (Denominator != 0.0) dt = min(dt, dT_max / Denominator);
    7812             :             }
    7813     5572306 :             dt = max(min(SubTimestepMin, TimeRemaining), dt);
    7814     5572306 :             dt = min(SubTimestepMax, dt);
    7815             :         }
    7816             : 
    7817             :         // Make initial guess that average and final temperatures over the DataGlobals::TimeStep are equal to the starting temperatures
    7818    43172837 :         for (int i = 0; i < nTankNodes; i++) {
    7819    36058212 :             const auto &NodeTemp = this->Node[i].Temp;
    7820    36058212 :             Tfinal[i] = NodeTemp;
    7821    36058212 :             Tavg[i] = NodeTemp;
    7822             :         }
    7823             : 
    7824    26552541 :         for (int ConvergenceCounter = 1; ConvergenceCounter <= 10; ConvergenceCounter++) {
    7825             : 
    7826    26208318 :             std::fill(A.begin(), A.end(), 0.0);
    7827    26208318 :             std::fill(B.begin(), B.end(), 0.0);
    7828             : 
    7829             :             // Heater Coefficients
    7830    26208318 :             B[this->HeaterNode1 - 1] += Qheater1;
    7831    26208318 :             B[this->HeaterNode2 - 1] += Qheater2;
    7832             : 
    7833   212378278 :             for (int i = 0; i < nTankNodes; i++) {
    7834   186169960 :                 const int NodeNum = i + 1;
    7835   186169960 :                 const auto &tank_node(this->Node(NodeNum));
    7836             : 
    7837             :                 // Parasitic Loads and Losses to Ambient
    7838   186169960 :                 if (this->HeaterOn1 || this->HeaterOn2) {
    7839             :                     // Parasitic Loads
    7840    31722920 :                     B[i] += tank_node.OnCycParaLoad;
    7841             :                     // Losses to Ambient
    7842    31722920 :                     A[i] += -tank_node.OnCycLossCoeff;
    7843    31722920 :                     B[i] += tank_node.OnCycLossCoeff * this->AmbientTemp;
    7844             :                 } else {
    7845             :                     // Parasitic Loads
    7846   154447040 :                     B[i] += tank_node.OffCycParaLoad;
    7847             :                     // Losses to Ambient
    7848   154447040 :                     A[i] += -tank_node.OffCycLossCoeff;
    7849   154447040 :                     B[i] += tank_node.OffCycLossCoeff * this->AmbientTemp;
    7850             :                 }
    7851             : 
    7852             :                 // Conduction to adjacent nodes
    7853   186169960 :                 A[i] += -(tank_node.CondCoeffDn + tank_node.CondCoeffUp);
    7854   186169960 :                 if (NodeNum > 1) B[i] += tank_node.CondCoeffUp * Tavg[i - 1];
    7855   186169960 :                 if (NodeNum < nTankNodes) B[i] += tank_node.CondCoeffDn * Tavg[i + 1];
    7856             : 
    7857             :                 // Use side plant connection
    7858   186169960 :                 const Real64 use_e_mdot_cp = tank_node.UseMassFlowRate * Cp;
    7859   186169960 :                 A[i] += -use_e_mdot_cp;
    7860   186169960 :                 B[i] += use_e_mdot_cp * this->UseInletTemp;
    7861             : 
    7862             :                 // Source side heat transfer rate
    7863   186169960 :                 if ((this->HeatPumpNum > 0) && (HPWHCondenserConfig == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterPumped)) {
    7864             :                     // Pumped Condenser Heat Pump Water Heater
    7865   125704068 :                     if (tank_node.SourceMassFlowRate > 0.0) B[i] += Qheatpump;
    7866             :                 } else {
    7867             :                     // Source side plant connection (constant temperature)
    7868    60465892 :                     const Real64 src_e_mdot_cp = tank_node.SourceMassFlowRate * Cp;
    7869    60465892 :                     A[i] += -src_e_mdot_cp;
    7870    60465892 :                     B[i] += src_e_mdot_cp * this->SourceInletTemp;
    7871             :                 }
    7872             : 
    7873             :                 // Wrapped condenser heat pump water heater
    7874   186169960 :                 if ((this->HeatPumpNum > 0) && (HPWHCondenserConfig == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterWrapped)) {
    7875    31555538 :                     B[i] += Qheatpump * tank_node.HPWHWrappedCondenserHeatingFrac;
    7876             :                 }
    7877             : 
    7878             :                 // Internodal flow
    7879   186169960 :                 A[i] += -(tank_node.MassFlowFromUpper + tank_node.MassFlowFromLower) * Cp;
    7880   186169960 :                 if (NodeNum > 1) B[i] += tank_node.MassFlowFromUpper * Cp * Tavg[i - 1];
    7881   186169960 :                 if (NodeNum < nTankNodes) B[i] += tank_node.MassFlowFromLower * Cp * Tavg[i + 1];
    7882             : 
    7883             :                 // Divide by mass and specific heat
    7884             :                 // m * cp * dT/dt = q_net  =>  dT/dt = a * T + b
    7885   186169960 :                 A[i] /= tank_node.Mass * Cp;
    7886   186169960 :                 B[i] /= tank_node.Mass * Cp;
    7887             : 
    7888             :             } // end for each node
    7889             : 
    7890             :             // Calculate the average and final temperatures over the interval
    7891    26208318 :             Real64 TfinalDiff = 0.0;
    7892   212378278 :             for (int i = 0; i < nTankNodes; ++i) {
    7893   186169960 :                 const Real64 Tstart = this->Node[i].Temp;
    7894   186169960 :                 const Real64 b_a = B[i] / A[i];
    7895   186169960 :                 const Real64 e_a_dt = exp(A[i] * dt);
    7896   186169960 :                 Tavg[i] = (Tstart + b_a) * (e_a_dt - 1.0) / (A[i] * dt) - b_a;
    7897   186169960 :                 const Real64 Tfinal_old = Tfinal[i];
    7898   186169960 :                 Tfinal[i] = (Tstart + b_a) * e_a_dt - b_a;
    7899   186169960 :                 TfinalDiff = max(fabs(Tfinal[i] - Tfinal_old), TfinalDiff);
    7900             :             }
    7901             : 
    7902    26208318 :             if (TfinalDiff < TemperatureConvergenceCriteria) break;
    7903             : 
    7904    19437916 :             if (this->DesuperheaterNum > 0) {
    7905       47662 :                 DesuperheaterPLR = state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).DesuperheaterPLR;
    7906       47662 :                 DesuperheaterHeaterRate = state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).HeaterRate;
    7907       95324 :                 MdotDesuperheaterWater = state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).OperatingWaterFlowRate *
    7908       47662 :                                          Psychrometrics::RhoH2O(Tavg[this->SourceOutletStratNode - 1]);
    7909       47662 :                 if (DesuperheaterPLR > 0.0 && MdotDesuperheaterWater > 0.0) {
    7910       34056 :                     this->SourceInletTemp =
    7911       34056 :                         Tavg[this->SourceOutletStratNode - 1] + (DesuperheaterHeaterRate / DesuperheaterPLR) / (MdotDesuperheaterWater * Cp);
    7912             :                 } else {
    7913       13606 :                     this->SourceInletTemp = Tavg[this->SourceOutletStratNode - 1];
    7914             :                 }
    7915             :             }
    7916             :         } // end temperature convergence loop
    7917             : 
    7918             :         // Inversion mixing
    7919             :         bool HasInversion;
    7920    10123019 :         do {
    7921    10123019 :             HasInversion = false;
    7922             :             // Starting from the top of the tank check if the node below has a temperature inversion.
    7923    48993567 :             for (int j = 0; j < nTankNodes - 1; ++j) {
    7924    41878942 :                 if (Tfinal[j] < Tfinal[j + 1]) {
    7925             : 
    7926             :                     // Temperature inversion!
    7927     3008394 :                     HasInversion = true;
    7928             : 
    7929             :                     // From the node above the inversion, move down calculating a weighted average
    7930             :                     // of node temperatures until the node below the group of mixed nodes isn't hotter
    7931             :                     // or we hit the bottom of the tank.
    7932     3008394 :                     Real64 Tmixed = 0.0;
    7933     3008394 :                     Real64 MassMixed = 0.0;
    7934             :                     int m;
    7935    14936272 :                     for (m = j; m < nTankNodes; ++m) {
    7936    14936272 :                         Tmixed += Tfinal[m] * this->Node[m].Mass;
    7937    14936272 :                         MassMixed += this->Node[m].Mass;
    7938    14936272 :                         if ((m == nTankNodes - 1) || (Tmixed / MassMixed > Tfinal[m + 1])) break;
    7939             :                     }
    7940     3008394 :                     Tmixed /= MassMixed;
    7941             : 
    7942             :                     // Now we have a range of nodes (j = top, m = bottom) that are mixed
    7943             :                     // and the mixed temperature (Tmixed).
    7944             :                     // Move through the mixed nodes and set the final temperature to the mixed temperature.
    7945             :                     // Also calculate a corrected average temperature for each node.
    7946    17944666 :                     for (int k = j; k <= m; ++k) {
    7947             :                         Real64 FinalFactorMixing;
    7948             :                         Real64 AvgFactorMixing;
    7949    14936272 :                         const Real64 NodeCapacitance = this->Node[k].Mass * Cp;
    7950    14936272 :                         if (A[k] == 0.0) {
    7951           0 :                             FinalFactorMixing = dt / NodeCapacitance;
    7952           0 :                             AvgFactorMixing = FinalFactorMixing / 2.0;
    7953             :                         } else {
    7954    14936272 :                             FinalFactorMixing = (exp(A[k] * dt) - 1.0) / A[k] / NodeCapacitance;
    7955    14936272 :                             AvgFactorMixing = ((exp(A[k] * dt) - 1.0) / A[k] / dt - 1.0) / A[k] / NodeCapacitance;
    7956             :                         }
    7957    14936272 :                         const Real64 Q_AdiabaticMixing = (Tmixed - Tfinal[k]) / FinalFactorMixing;
    7958    14936272 :                         Tfinal[k] = Tmixed;
    7959    14936272 :                         Tavg[k] += Q_AdiabaticMixing * AvgFactorMixing;
    7960             :                     }
    7961             : 
    7962             :                     // Since we mixed, get out of here and start from the top to check again for mixing.
    7963     3008394 :                     break;
    7964             :                 }
    7965             :             }
    7966             :         } while (HasInversion);
    7967             : 
    7968             :         // Venting
    7969     7114625 :         if (!this->IsChilledWaterTank) {
    7970     6768575 :             if (Tfinal[0] > this->TankTempLimit) {
    7971     1061418 :                 for (int i = 0; i < nTankNodes; ++i) {
    7972      917526 :                     if (Tfinal[i] > this->TankTempLimit) {
    7973      369579 :                         Event += this->Node[i].Mass * Cp * (this->TankTempLimit - Tfinal[i]);
    7974      369579 :                         Tfinal[i] = this->TankTempLimit;
    7975             :                     }
    7976             :                 }
    7977             :             }
    7978             :         }
    7979             : 
    7980             :         // Increment to next internal time step
    7981     7114625 :         TimeRemaining -= dt;
    7982     7114625 :         Real64 Qloss = 0.0;
    7983    43172837 :         for (int i = 0; i < nTankNodes; ++i) {
    7984    36058212 :             auto &node = this->Node[i];
    7985    36058212 :             node.Temp = Tfinal[i];
    7986    36058212 :             node.TempSum += Tavg[i] * dt;
    7987             : 
    7988             :             // Bookkeeping for reporting variables, mostly for Qunmet.
    7989    36058212 :             Real64 Qloss_node = (this->AmbientTemp - Tavg[i]);
    7990             :             Real64 Qheat_node;
    7991    36058212 :             const Real64 Quse_node = node.UseMassFlowRate * Cp * (this->UseInletTemp - Tavg[i]);
    7992    36058212 :             const Real64 Qsource_node = [&] {
    7993    42017608 :                 if (this->HeatPumpNum > 0) {
    7994    38611886 :                     if (HPWHCondenserConfig == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterPumped) {
    7995    36058212 :                         if (node.SourceMassFlowRate > 0.0) {
    7996    10103581 :                             return Qheatpump;
    7997             :                         } else {
    7998    19995235 :                             return 0.0;
    7999             :                         }
    8000             :                     } else {
    8001     8513070 :                         assert(HPWHCondenserConfig == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterWrapped);
    8002    17026140 :                         return Qheatpump * node.HPWHWrappedCondenserHeatingFrac;
    8003             :                     }
    8004             :                 } else {
    8005    11918792 :                     return node.SourceMassFlowRate * Cp * (this->SourceInletTemp - Tavg[i]);
    8006             :                 }
    8007    36058212 :             }();
    8008             : 
    8009    36058212 :             if (this->HeaterOn1 || this->HeaterOn2) {
    8010     6043470 :                 Qloss_node *= node.OnCycLossCoeff;
    8011     6043470 :                 Qheat_node = node.OnCycParaLoad * this->OnCycParaFracToTank;
    8012             :             } else {
    8013    30014742 :                 Qloss_node *= node.OffCycLossCoeff;
    8014    30014742 :                 Qheat_node = node.OffCycParaLoad * this->OffCycParaFracToTank;
    8015             :             }
    8016    36058212 :             Qloss += Qloss_node;
    8017    36058212 :             const Real64 Qneeded_node = max(-Quse_node - Qsource_node - Qloss_node - Qheat_node, 0.0);
    8018    36058212 :             const Real64 Qunmet_node = max(Qneeded_node - Qheater1 - Qheater2, 0.0);
    8019    36058212 :             Eunmet += Qunmet_node * dt;
    8020             :         }
    8021     7114625 :         SourceInletTempSum += this->SourceInletTemp * dt;
    8022             :         // More bookkeeping for reporting variables
    8023     7114625 :         Eloss += Qloss * dt;
    8024     7114625 :         const Real64 Quse = (this->UseOutletStratNode > 0)
    8025     7114625 :                                 ? this->UseEffectiveness * this->UseMassFlowRate * Cp * (this->UseInletTemp - Tavg[this->UseOutletStratNode - 1])
    8026     7114625 :                                 : 0.0;
    8027     7114625 :         Euse += Quse * dt;
    8028     7114625 :         const Real64 Qsource = [&] {
    8029     9997725 :             if (this->HeatPumpNum > 0) {
    8030    10262433 :                 if (HPWHCondenserConfig == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterPumped) {
    8031     2426441 :                     return Qheatpump;
    8032             :                 } else {
    8033     3917996 :                     assert(HPWHCondenserConfig == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterWrapped);
    8034     3917996 :                     return 0.0;
    8035             :                 }
    8036             :             } else {
    8037      770188 :                 if (this->SourceOutletStratNode > 0) {
    8038     1056456 :                     return this->SourceEffectiveness * this->SourceMassFlowRate * Cp *
    8039     1056456 :                            (this->SourceInletTemp - Tavg[this->SourceOutletStratNode - 1]);
    8040             :                 } else {
    8041      241960 :                     return 0.0;
    8042             :                 }
    8043             :             }
    8044     7114625 :         }();
    8045     7114625 :         Esource += Qsource * dt;
    8046     7114625 :         if (this->HeaterOn1) Runtime1 += dt;
    8047     7114625 :         if (this->HeaterOn2) Runtime2 += dt;
    8048     7114625 :         if (this->HeaterOn1 || this->HeaterOn2) Runtime += dt;
    8049     7114625 :         Eheater1 += Qheater1 * dt;
    8050     7114625 :         Eheater2 += Qheater2 * dt;
    8051             : 
    8052             :         // Calculation for standard ratings
    8053     7114625 :         if (!this->FirstRecoveryDone) {
    8054             :             Real64 Qrecovery;
    8055     5853557 :             if (this->HeaterOn1 || this->HeaterOn2) {
    8056      108820 :                 Qrecovery = (Qheater1 + Qheater1) / this->Efficiency + this->OnCycParaLoad;
    8057             :             } else {
    8058     5744737 :                 Qrecovery = this->OffCycParaLoad;
    8059             :             }
    8060     5853557 :             this->FirstRecoveryFuel += Qrecovery * dt;
    8061     5853557 :             if (SetPointRecovered) this->FirstRecoveryDone = true;
    8062             :         }
    8063             :     } // end while TimeRemaining > 0.0
    8064             : 
    8065    10107085 :     for (auto &e : this->Node) {
    8066     8564766 :         e.TempAvg = e.TempSum / SecInTimeStep;
    8067     8564766 :         e.TempSum = 0.0;
    8068             :     }
    8069             : 
    8070     1542319 :     this->TankTemp = sum(this->Node, &StratifiedNodeData::Temp) / this->Nodes;
    8071     1542319 :     this->TankTempAvg = sum(this->Node, &StratifiedNodeData::TempAvg) / this->Nodes;
    8072             : 
    8073     1542319 :     if (!state.dataGlobal->WarmupFlag) {
    8074             :         // Warn for potential freezing when avg of final temp over all nodes is below 2°C (nearing 0°C)
    8075      252605 :         if (this->TankTemp < 2) {
    8076           0 :             if (this->FreezingErrorIndex == 0) {
    8077           0 :                 ShowWarningError(state,
    8078           0 :                                  format("{}: {} = '{}':  Temperature of tank < 2C indicates of possibility of freeze. Tank Temperature = {:.2R} C.",
    8079             :                                         RoutineName,
    8080             :                                         this->Type,
    8081             :                                         this->Name,
    8082           0 :                                         this->TankTemp));
    8083           0 :                 ShowContinueErrorTimeStamp(state, "");
    8084             :             }
    8085           0 :             ShowRecurringWarningErrorAtEnd(state,
    8086           0 :                                            this->Type + " = '" + this->Name + "':  Temperature of tank < 2C indicates of possibility of freeze",
    8087             :                                            this->FreezingErrorIndex,
    8088             :                                            this->TankTemp, // Report Max
    8089             :                                            this->TankTemp, // Report Min
    8090             :                                            _,              // Don't report Sum
    8091             :                                            "{C}",          // Max Unit
    8092             :                                            "{C}");         // Min Unit
    8093             :         }
    8094             :     }
    8095             : 
    8096     1542319 :     if (this->UseOutletStratNode > 0) {
    8097     1542319 :         this->UseOutletTemp = this->Node(this->UseOutletStratNode).TempAvg;
    8098             :         // Revised use outlet temperature to ensure energy balance. Assumes a constant CP. CR8341/CR8570
    8099     1542319 :         if (this->UseMassFlowRate > 0.0) {
    8100     1271610 :             this->UseOutletTemp = this->UseInletTemp * (1.0 - this->UseEffectiveness) + this->UseOutletTemp * this->UseEffectiveness;
    8101             :         }
    8102             :     }
    8103             : 
    8104     1542319 :     if (HPWHCondenserConfig == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterWrapped) {
    8105             :         // If we have a wrapped condenser HPWH, set the source outlet to the weighted average of the node
    8106             :         // temperatures the condenser sees
    8107      859481 :         Real64 WeightedAverageSourceOutletTemp(0.0);
    8108     3679063 :         for (int i = 1; i <= this->Nodes; ++i) {
    8109     2819582 :             WeightedAverageSourceOutletTemp += this->Node(i).TempAvg * this->Node(i).HPWHWrappedCondenserHeatingFrac;
    8110             :         }
    8111      859481 :         this->SourceOutletTemp = WeightedAverageSourceOutletTemp;
    8112      682838 :     } else if (this->SourceOutletStratNode > 0) {
    8113             :         // otherwise set it to the temperature of the source outlet node
    8114      601934 :         this->SourceOutletTemp = this->Node(this->SourceOutletStratNode).TempAvg;
    8115             :         // Output the average inlet temperature for the DataGlobals::TimeStep
    8116      601934 :         this->SourceInletTemp = SourceInletTempSum / SecInTimeStep;
    8117             :     }
    8118     1542319 :     if (HPWHCondenserConfig == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterPumped) {
    8119             :         // For pumped condensers, set the source inlet and outlets to match the delta T
    8120             :         // across the water side of the DX coil.
    8121      431285 :         HeatPumpWaterHeaterData const &HeatPump = state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum);
    8122      431285 :         DataLoopNode::NodeData const &HPWHCondWaterInletNode = state.dataLoopNodes->Node(HeatPump.CondWaterInletNode);
    8123      431285 :         DataLoopNode::NodeData const &HPWHCondWaterOutletNode = state.dataLoopNodes->Node(HeatPump.CondWaterOutletNode);
    8124      431285 :         Real64 const HPWHCondenserDeltaT = HPWHCondWaterOutletNode.Temp - HPWHCondWaterInletNode.Temp;
    8125      431285 :         this->SourceInletTemp = this->SourceOutletTemp + HPWHCondenserDeltaT;
    8126             :     }
    8127             : 
    8128             :     // Revised source outlet temperature to ensure energy balance. Assumes a constant CP. CR8341/CR8570
    8129     1542319 :     if (this->SourceOutletStratNode > 0) {
    8130      601934 :         if (this->SourceMassFlowRate > 0.0) {
    8131      276915 :             this->SourceOutletTemp = this->SourceInletTemp * (1.0 - this->SourceEffectiveness) + this->SourceOutletTemp * this->SourceEffectiveness;
    8132             :         }
    8133             :     }
    8134             : 
    8135     1542319 :     this->LossRate = Eloss / SecInTimeStep;
    8136     1542319 :     this->UseRate = Euse / SecInTimeStep;
    8137     1542319 :     Real64 WrappedCondenserHeatPumpRate = 0.0;
    8138     1542319 :     if ((this->HeatPumpNum > 0) && (HPWHCondenserConfig == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterPumped)) {
    8139      431285 :         this->SourceRate = Qheatpump;
    8140             :     } else {
    8141     1111034 :         this->SourceRate = Esource / SecInTimeStep;
    8142     1111034 :         WrappedCondenserHeatPumpRate = Qheatpump;
    8143             :     }
    8144             : 
    8145     1542319 :     this->OffCycParaFuelRate = this->OffCycParaLoad * (SecInTimeStep - Runtime) / SecInTimeStep;
    8146     1542319 :     this->OnCycParaFuelRate = this->OnCycParaLoad * Runtime / SecInTimeStep;
    8147     1542319 :     this->OffCycParaRateToTank = this->OffCycParaFuelRate * this->OffCycParaFracToTank;
    8148     1542319 :     this->OnCycParaRateToTank = this->OnCycParaFuelRate * this->OnCycParaFracToTank;
    8149     1542319 :     this->TotalDemandRate =
    8150     1542319 :         -this->UseRate - this->SourceRate - this->LossRate - this->OffCycParaRateToTank - this->OnCycParaRateToTank - WrappedCondenserHeatPumpRate;
    8151     1542319 :     this->HeaterRate1 = Eheater1 / SecInTimeStep;
    8152     1542319 :     this->HeaterRate2 = Eheater2 / SecInTimeStep;
    8153     1542319 :     this->HeaterRate = this->HeaterRate1 + this->HeaterRate2;
    8154             : 
    8155     1542319 :     this->UnmetRate = Eunmet / SecInTimeStep;
    8156     1542319 :     this->VentRate = Event / SecInTimeStep;
    8157     4626957 :     this->NetHeatTransferRate = this->UseRate + this->SourceRate + this->LossRate + this->OffCycParaRateToTank + this->OnCycParaRateToTank +
    8158     3084638 :                                 this->HeaterRate + this->VentRate + WrappedCondenserHeatPumpRate;
    8159             : 
    8160     1542319 :     this->CycleOnCount = CycleOnCount1_loc + CycleOnCount2_loc;
    8161     1542319 :     this->CycleOnCount1 = CycleOnCount1_loc;
    8162     1542319 :     this->CycleOnCount2 = CycleOnCount2_loc;
    8163             : 
    8164     1542319 :     this->RuntimeFraction = Runtime / SecInTimeStep;
    8165     1542319 :     this->RuntimeFraction1 = Runtime1 / SecInTimeStep;
    8166     1542319 :     this->RuntimeFraction2 = Runtime2 / SecInTimeStep;
    8167             : 
    8168     1542319 :     this->FuelRate = (Eheater1 + Eheater2) / this->Efficiency / SecInTimeStep;
    8169             : 
    8170             :     // Add water heater skin losses and venting losses to ambient zone, if specified
    8171     1542319 :     if (this->AmbientTempZone > 0) this->AmbientZoneGain = -this->LossRate * this->SkinLossFracToZone - this->VentRate;
    8172     1542319 : }
    8173             : 
    8174     1715396 : void WaterThermalTankData::CalcNodeMassFlows(InletPositionMode inletMode)
    8175             : {
    8176             : 
    8177             :     // SUBROUTINE INFORMATION:
    8178             :     //       AUTHOR         Peter Graham Ellis
    8179             :     //       DATE WRITTEN   January 2007
    8180             :     //       MODIFIED       na
    8181             :     //       RE-ENGINEERED  na
    8182             : 
    8183             :     // PURPOSE OF THIS SUBROUTINE:
    8184             :     // Determines mass flow rates between nodes according to the locations of the use- and source-side inlet and outlet
    8185             :     // nodes.
    8186             : 
    8187             :     // METHODOLOGY EMPLOYED:
    8188             :     // In 'Seeking' mode, nodes are searched between the user-specified inlet and outlet nodes to find the node closest
    8189             :     // in temperature to the inlet fluid temperature.  In 'Fixed' mode, the user-specified nodes are always used.
    8190             :     // Upward and downward flows are added to each node between an inlet and outlet.  Flows in both directions cancel out
    8191             :     // to leave only the net flow in one direction.
    8192             : 
    8193     1715396 :     int useInletStratNod = this->UseInletStratNode;
    8194     1715396 :     int useOutletStratNode = this->UseOutletStratNode;
    8195     1715396 :     int sourceInletStratNode = this->SourceInletStratNode;
    8196     1715396 :     int sourceOutletStratNode = this->SourceOutletStratNode;
    8197             : 
    8198     1715396 :     Real64 useMassFlowRate = this->UseMassFlowRate * this->UseEffectiveness;
    8199     1715396 :     Real64 sourceMassFlowRate = this->SourceMassFlowRate * this->SourceEffectiveness;
    8200             : 
    8201    11318624 :     for (auto &e : this->Node) {
    8202     9603228 :         e.UseMassFlowRate = 0.0;
    8203     9603228 :         e.SourceMassFlowRate = 0.0;
    8204     9603228 :         e.MassFlowFromUpper = 0.0;
    8205     9603228 :         e.MassFlowFromLower = 0.0;
    8206     9603228 :         e.MassFlowToUpper = 0.0;
    8207     9603228 :         e.MassFlowToLower = 0.0;
    8208             :     }
    8209             : 
    8210     1715396 :     if (inletMode == InletPositionMode::Seeking) {
    8211             :         // 'Seek' the node with the temperature closest to the inlet temperature
    8212             :         // Start at the user-specified inlet node and search to the user-specified outlet node
    8213             :         int Step;
    8214      346050 :         if (useMassFlowRate > 0.0) {
    8215      160952 :             if (useInletStratNod > useOutletStratNode) {
    8216           0 :                 Step = -1;
    8217             :             } else {
    8218      160952 :                 Step = 1;
    8219             :             }
    8220      160952 :             Real64 MinDeltaTemp = 1.0e6; // Some big number
    8221      160952 :             int const NodeNum_stop(floop_end(useInletStratNod, useOutletStratNode, Step));
    8222      552164 :             for (int NodeNum = useInletStratNod; NodeNum != NodeNum_stop; NodeNum += Step) {
    8223      508345 :                 Real64 DeltaTemp = std::abs(this->Node(NodeNum).Temp - this->UseInletTemp);
    8224      508345 :                 if (DeltaTemp < MinDeltaTemp) {
    8225      330644 :                     MinDeltaTemp = DeltaTemp;
    8226      330644 :                     useInletStratNod = NodeNum;
    8227      177701 :                 } else if (DeltaTemp > MinDeltaTemp) {
    8228      117133 :                     break;
    8229             :                 }
    8230             :             }
    8231             :         }
    8232             : 
    8233      346050 :         if (sourceMassFlowRate > 0.0) {
    8234       43024 :             if (sourceInletStratNode > sourceOutletStratNode) {
    8235       43024 :                 Step = -1;
    8236             :             } else {
    8237           0 :                 Step = 1;
    8238             :             }
    8239       43024 :             Real64 MinDeltaTemp = 1.0e6; // Some big number
    8240       43024 :             int const NodeNum_stop(floop_end(sourceInletStratNode, sourceOutletStratNode, Step));
    8241       86796 :             for (int NodeNum = sourceInletStratNode; NodeNum != NodeNum_stop; NodeNum += Step) {
    8242       86796 :                 Real64 DeltaTemp = std::abs(this->Node(NodeNum).Temp - this->SourceInletTemp);
    8243       86796 :                 if (DeltaTemp < MinDeltaTemp) {
    8244       43024 :                     MinDeltaTemp = DeltaTemp;
    8245       43024 :                     sourceInletStratNode = NodeNum;
    8246       43772 :                 } else if (DeltaTemp > MinDeltaTemp) {
    8247       43024 :                     break;
    8248             :                 }
    8249             :             }
    8250             :         }
    8251             :     }
    8252             : 
    8253     1715396 :     if (useInletStratNod > 0) this->Node(useInletStratNod).UseMassFlowRate = useMassFlowRate;
    8254     1715396 :     if (sourceInletStratNode > 0) this->Node(sourceInletStratNode).SourceMassFlowRate = sourceMassFlowRate;
    8255             : 
    8256     1715396 :     if (useMassFlowRate > 0.0) {
    8257     1352089 :         if (useOutletStratNode > useInletStratNod) {
    8258             :             // Use-side flow is down
    8259      768272 :             for (int NodeNum = useInletStratNod; NodeNum <= useOutletStratNode - 1; ++NodeNum) {
    8260      635068 :                 this->Node(NodeNum).MassFlowToLower += useMassFlowRate;
    8261             :             }
    8262      768272 :             for (int NodeNum = useInletStratNod + 1; NodeNum <= useOutletStratNode; ++NodeNum) {
    8263      635068 :                 this->Node(NodeNum).MassFlowFromUpper += useMassFlowRate;
    8264             :             }
    8265             : 
    8266     1218885 :         } else if (useOutletStratNode < useInletStratNod) {
    8267             :             // Use-side flow is up
    8268     5088968 :             for (int NodeNum = useOutletStratNode; NodeNum <= useInletStratNod - 1; ++NodeNum) {
    8269     4578137 :                 this->Node(NodeNum).MassFlowFromLower += useMassFlowRate;
    8270             :             }
    8271     5088968 :             for (int NodeNum = useOutletStratNode + 1; NodeNum <= useInletStratNod; ++NodeNum) {
    8272     4578137 :                 this->Node(NodeNum).MassFlowToUpper += useMassFlowRate;
    8273             :             }
    8274             : 
    8275             :         } else {
    8276             :             // Use-side flow is across the node; no flow to other nodes
    8277             :         }
    8278             :     }
    8279             : 
    8280     1715396 :     if (sourceMassFlowRate > 0.0) {
    8281      298427 :         if (sourceOutletStratNode > sourceInletStratNode) {
    8282             :             // Source-side flow is down
    8283      637438 :             for (int NodeNum = sourceInletStratNode; NodeNum <= sourceOutletStratNode - 1; ++NodeNum) {
    8284      542589 :                 this->Node(NodeNum).MassFlowToLower += sourceMassFlowRate;
    8285             :             }
    8286      637438 :             for (int NodeNum = sourceInletStratNode + 1; NodeNum <= sourceOutletStratNode; ++NodeNum) {
    8287      542589 :                 this->Node(NodeNum).MassFlowFromUpper += sourceMassFlowRate;
    8288             :             }
    8289             : 
    8290      203578 :         } else if (sourceOutletStratNode < sourceInletStratNode) {
    8291             :             // Source-side flow is up
    8292     1139320 :             for (int NodeNum = sourceOutletStratNode; NodeNum <= sourceInletStratNode - 1; ++NodeNum) {
    8293      935742 :                 this->Node(NodeNum).MassFlowFromLower += sourceMassFlowRate;
    8294             :             }
    8295     1139320 :             for (int NodeNum = sourceOutletStratNode + 1; NodeNum <= sourceInletStratNode; ++NodeNum) {
    8296      935742 :                 this->Node(NodeNum).MassFlowToUpper += sourceMassFlowRate;
    8297             :             }
    8298             : 
    8299             :         } else {
    8300             :             // Source-side flow is across the node; no flow to other nodes
    8301             :         }
    8302             :     }
    8303             : 
    8304             :     // Cancel out any up and down flows
    8305    11318624 :     for (int NodeNum = 1; NodeNum <= this->Nodes; ++NodeNum) {
    8306     9603228 :         this->Node(NodeNum).MassFlowFromUpper = max((this->Node(NodeNum).MassFlowFromUpper - this->Node(NodeNum).MassFlowToUpper), 0.0);
    8307     9603228 :         this->Node(NodeNum).MassFlowFromLower = max((this->Node(NodeNum).MassFlowFromLower - this->Node(NodeNum).MassFlowToLower), 0.0);
    8308             :     }
    8309     1715396 : }
    8310             : 
    8311       30050 : void WaterThermalTankData::CalcDesuperheaterWaterHeater(EnergyPlusData &state, bool const FirstHVACIteration)
    8312             : {
    8313             : 
    8314             :     // SUBROUTINE INFORMATION:
    8315             :     //       AUTHOR         Richard Raustad
    8316             :     //       DATE WRITTEN   July 2005
    8317             :     //       MODIFIED       na
    8318             :     //       RE-ENGINEERED  na
    8319             : 
    8320             :     // PURPOSE OF THIS SUBROUTINE:
    8321             :     // Simulates a refrigerant desuperheater to heat water
    8322             : 
    8323             :     // METHODOLOGY EMPLOYED:
    8324             :     // This model uses the rated heat reclaim recovery efficiency, recovery efficiency modifier curve,
    8325             :     // set point temperature, and dead band temperature difference to simulate the desuperheater coil
    8326             :     // and sets up inputs to the tank model associated with the desuperheater coil
    8327             : 
    8328       30050 :     int constexpr MaxIte(500); // Maximum number of iterations for RegulaFalsi
    8329             : 
    8330       30050 :     auto &DesupHtr = state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum);
    8331             : 
    8332       30050 :     int WaterInletNode = DesupHtr.WaterInletNode;
    8333       30050 :     int WaterOutletNode = DesupHtr.WaterOutletNode;
    8334             : 
    8335             :     // store first iteration tank temperature and desuperheater mode of operation
    8336       30050 :     if (FirstHVACIteration && !state.dataHVACGlobal->ShortenTimeStepSys && DesupHtr.FirstTimeThroughFlag) {
    8337             :         // Save conditions from end of previous system timestep
    8338             :         // Every iteration that does not advance time should reset to these values
    8339       13954 :         this->SavedTankTemp = this->TankTemp;
    8340       13954 :         this->SavedSourceOutletTemp = this->SourceOutletTemp;
    8341       13954 :         DesupHtr.SaveMode = DesupHtr.Mode;
    8342       13954 :         DesupHtr.FirstTimeThroughFlag = false;
    8343             :     }
    8344             : 
    8345       16096 :     else if (!FirstHVACIteration) {
    8346       15025 :         DesupHtr.FirstTimeThroughFlag = true;
    8347             :     }
    8348             : 
    8349             :     // initialize variables before invoking any RETURN statement
    8350       30050 :     this->SourceMassFlowRate = 0.0;
    8351             :     // reset tank inlet temp from previous time step
    8352       30050 :     this->SourceInletTemp = this->SavedSourceOutletTemp;
    8353       30050 :     DesupHtr.DesuperheaterPLR = 0.0;
    8354             : 
    8355       30050 :     state.dataLoopNodes->Node(WaterInletNode).MassFlowRate = 0.0;
    8356       30050 :     state.dataLoopNodes->Node(WaterOutletNode).MassFlowRate = 0.0;
    8357       30050 :     state.dataLoopNodes->Node(WaterOutletNode).Temp = this->SavedSourceOutletTemp;
    8358             : 
    8359       30050 :     DesupHtr.DesuperheaterPLR = 0.0;
    8360       30050 :     DesupHtr.OnCycParaFuelRate = 0.0;
    8361       30050 :     DesupHtr.OnCycParaFuelEnergy = 0.0;
    8362       30050 :     DesupHtr.OffCycParaFuelRate = 0.0;
    8363       30050 :     DesupHtr.OffCycParaFuelEnergy = 0.0;
    8364       30050 :     DesupHtr.HEffFTempOutput = 0.0;
    8365       30050 :     DesupHtr.HeaterRate = 0.0;
    8366       30050 :     DesupHtr.HeaterEnergy = 0.0;
    8367       30050 :     DesupHtr.PumpPower = 0.0;
    8368       30050 :     DesupHtr.PumpEnergy = 0.0;
    8369             : 
    8370             :     // simulate only the water heater tank if the desuperheater coil is scheduled off
    8371       30050 :     Real64 AvailSchedule = ScheduleManager::GetCurrentScheduleValue(state, DesupHtr.AvailSchedPtr);
    8372       30050 :     if (AvailSchedule == 0.0) {
    8373           0 :         DesupHtr.Mode = TankOperatingMode::Floating;
    8374           0 :         this->CalcWaterThermalTank(state);
    8375       18637 :         return;
    8376             :     }
    8377             : 
    8378             :     // simulate only the water heater tank if the lowest temperature available from the desuperheater coil
    8379             :     // is less than water inlet temperature if the reclaim source is a refrigeration condenser
    8380       30050 :     if (DesupHtr.ValidSourceType) {
    8381       30050 :         int SourceID = DesupHtr.ReclaimHeatingSourceIndexNum;
    8382       30050 :         if (DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::CondenserRefrigeration) {
    8383        4564 :             if (state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).AvailTemperature <= this->SourceInletTemp) {
    8384          24 :                 DesupHtr.Mode = TankOperatingMode::Floating;
    8385          24 :                 this->CalcWaterThermalTank(state);
    8386          72 :                 ShowRecurringWarningErrorAtEnd(state,
    8387          48 :                                                "WaterHeating:Desuperheater " + DesupHtr.Name +
    8388             :                                                    " - Waste heat source temperature was too low to be useful.",
    8389             :                                                DesupHtr.InsuffTemperatureWarn);
    8390          24 :                 return;
    8391             :             } // Temp too low
    8392             :         }     // desuperheater source is condenser_refrigeration
    8393             :     }         // validsourcetype
    8394             : 
    8395       30026 :     DesupHtr.OffCycParaFuelRate = DesupHtr.OffCycParaLoad;
    8396       30026 :     DesupHtr.OffCycParaFuelEnergy = DesupHtr.OffCycParaFuelRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    8397             : 
    8398             :     // check that water heater tank cut-in temp is greater than desuperheater cut-in temp
    8399       30026 :     Real64 desupHtrSetPointTemp = DesupHtr.SetPointTemp;
    8400       30026 :     Real64 DeadBandTempDiff = DesupHtr.DeadBandTempDiff;
    8401       30026 :     if ((desupHtrSetPointTemp - DeadBandTempDiff) <= this->SetPointTemp) {
    8402           4 :         if (!state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingSizing && !state.dataGlobal->KickOffSimulation) {
    8403           0 :             Real64 MinTemp = desupHtrSetPointTemp - DeadBandTempDiff;
    8404           0 :             ++DesupHtr.SetPointError;
    8405           0 :             if (DesupHtr.SetPointError < 5) {
    8406           0 :                 ShowWarningError(state,
    8407           0 :                                  DesupHtr.Type + " \"" + DesupHtr.Name +
    8408             :                                      "\":  Water heater tank set point temperature is greater than or equal to the cut-in temperature of the "
    8409             :                                      "desuperheater. Desuperheater will be disabled.");
    8410           0 :                 ShowContinueErrorTimeStamp(state, format(" ...Desuperheater cut-in temperature = {:.2R}", MinTemp));
    8411             :             } else {
    8412           0 :                 ShowRecurringWarningErrorAtEnd(state,
    8413           0 :                                                DesupHtr.Type + " \"" + DesupHtr.Name +
    8414             :                                                    "\":  Water heater tank set point temperature is greater than or equal to the cut-in "
    8415             :                                                    "temperature of the desuperheater. Desuperheater will be disabled warning continues...",
    8416             :                                                DesupHtr.SetPointErrIndex1,
    8417             :                                                MinTemp,
    8418             :                                                MinTemp);
    8419             :             }
    8420             :         }
    8421             : 
    8422             :         //   Simulate tank if desuperheater unavailable for water heating
    8423           4 :         this->CalcWaterThermalTank(state);
    8424           4 :         return;
    8425             :     }
    8426             : 
    8427       30022 :     Real64 Effic = DesupHtr.HeatReclaimRecoveryEff;
    8428             : 
    8429       30022 :     state.dataLoopNodes->Node(WaterInletNode).Temp = this->SavedSourceOutletTemp;
    8430       30022 :     DesupHtr.Mode = DesupHtr.SaveMode;
    8431             : 
    8432             :     Real64 HEffFTemp;
    8433       30022 :     if (DesupHtr.HEffFTemp > 0) {
    8434       30022 :         HEffFTemp = max(0.0, Curve::CurveValue(state, DesupHtr.HEffFTemp, this->SavedTankTemp, state.dataEnvrn->OutDryBulbTemp));
    8435             :     } else {
    8436           0 :         HEffFTemp = 1.0;
    8437             :     }
    8438             : 
    8439             :     // set limits on heat recovery efficiency
    8440       30022 :     if (DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::CondenserRefrigeration) {
    8441        4540 :         if ((HEffFTemp * Effic) > 0.9) HEffFTemp = 0.9 / Effic;
    8442             :     } else { // max is 0.3 for all other sources
    8443       25482 :         if ((HEffFTemp * Effic) > 0.3) HEffFTemp = 0.3 / Effic;
    8444             :     } // setting limits on heat recovery efficiency
    8445             : 
    8446             :     // Access the appropriate structure to find the average heating capacity of the desuperheater heating coil
    8447       30022 :     Real64 AverageWasteHeat = 0.0;
    8448       30022 :     if (DesupHtr.ValidSourceType) {
    8449       30022 :         int SourceID = DesupHtr.ReclaimHeatingSourceIndexNum;
    8450       30022 :         if (DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::CompressorRackRefrigeratedCase) {
    8451             :             // Refrigeration systems are solved outside the time step iteration, so the
    8452             :             //  appropriate decrement for other waste heat applications is handled differently
    8453           0 :             AverageWasteHeat = state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).AvailCapacity -
    8454           0 :                                state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).HVACDesuperheaterReclaimedHeatTotal;
    8455           0 :             DesupHtr.DXSysPLR = 1.0;
    8456       30022 :         } else if (DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::CondenserRefrigeration) {
    8457        9080 :             AverageWasteHeat = state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).AvailCapacity -
    8458        4540 :                                state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).HVACDesuperheaterReclaimedHeatTotal;
    8459        4540 :             DesupHtr.DXSysPLR = 1.0;
    8460       38796 :         } else if (DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::DXCooling ||
    8461       26628 :                    DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::DXMultiSpeed ||
    8462       13314 :                    DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::DXMultiMode) {
    8463       24336 :             AverageWasteHeat = state.dataHeatBal->HeatReclaimDXCoil(SourceID).AvailCapacity -
    8464       12168 :                                state.dataHeatBal->HeatReclaimDXCoil(SourceID).HVACDesuperheaterReclaimedHeatTotal;
    8465       12168 :             DesupHtr.DXSysPLR = state.dataDXCoils->DXCoil(SourceID).PartLoadRatio;
    8466       13314 :         } else if (DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::DXVariableCooling) {
    8467        7800 :             AverageWasteHeat = state.dataHeatBal->HeatReclaimVS_DXCoil(SourceID).AvailCapacity -
    8468        3900 :                                state.dataHeatBal->HeatReclaimVS_DXCoil(SourceID).HVACDesuperheaterReclaimedHeatTotal;
    8469        3900 :             DesupHtr.DXSysPLR = state.dataVariableSpeedCoils->VarSpeedCoil(SourceID).PartLoadRatio;
    8470        9414 :         } else if (DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::AirWaterHeatPumpEQ) {
    8471        6660 :             AverageWasteHeat = state.dataHeatBal->HeatReclaimSimple_WAHPCoil(SourceID).AvailCapacity -
    8472        3330 :                                state.dataHeatBal->HeatReclaimSimple_WAHPCoil(SourceID).HVACDesuperheaterReclaimedHeatTotal;
    8473        3330 :             DesupHtr.DXSysPLR = state.dataWaterToAirHeatPumpSimple->SimpleWatertoAirHP(SourceID).PartLoadRatio;
    8474        6084 :         } else if (DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::CoilCoolingDX) {
    8475        6084 :             AverageWasteHeat =
    8476        6084 :                 state.dataCoilCooingDX->coilCoolingDXs[DesupHtr.ReclaimHeatingSourceIndexNum].reclaimHeat.AvailCapacity -
    8477        6084 :                 state.dataCoilCooingDX->coilCoolingDXs[DesupHtr.ReclaimHeatingSourceIndexNum].reclaimHeat.HVACDesuperheaterReclaimedHeatTotal;
    8478        6084 :             DesupHtr.DXSysPLR = state.dataCoilCooingDX->coilCoolingDXs[DesupHtr.ReclaimHeatingSourceIndexNum].partLoadRatioReport;
    8479             :         }
    8480             :     } else {
    8481           0 :         AverageWasteHeat = 0.0;
    8482             :     }
    8483             : 
    8484             :     // simulate only water heater tank if reclaim heating source is off
    8485       30022 :     if (DesupHtr.DXSysPLR == 0.0) {
    8486       18609 :         this->CalcWaterThermalTank(state);
    8487       18609 :         return;
    8488             :     }
    8489             : 
    8490             :     // If the set point is higher than the maximum water temp, reset both the set point and the dead band temperature difference
    8491       11413 :     if (desupHtrSetPointTemp > DesupHtr.MaxInletWaterTemp) {
    8492       11413 :         Real64 CutInTemp = desupHtrSetPointTemp - DeadBandTempDiff;
    8493       11413 :         desupHtrSetPointTemp = DesupHtr.MaxInletWaterTemp;
    8494       11413 :         DeadBandTempDiff = max(0.0, (desupHtrSetPointTemp - CutInTemp));
    8495             :     }
    8496             : 
    8497             :     Real64 Acc; // Accuracy of result from RegulaFalsi
    8498       11413 :     if (DesupHtr.TankTypeNum == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
    8499         951 :         Acc = 0.001;
    8500             :     } else {
    8501       10462 :         Acc = 0.00001;
    8502             :     }
    8503             : 
    8504             :     // set the water-side mass flow rate
    8505       11413 :     Real64 CpWater = Psychrometrics::CPHW(state.dataLoopNodes->Node(WaterInletNode).Temp);
    8506       11413 :     Real64 MdotWater = DesupHtr.OperatingWaterFlowRate * Psychrometrics::RhoH2O(state.dataLoopNodes->Node(WaterInletNode).Temp);
    8507       11413 :     Real64 QHeatRate = 0.0;
    8508       11413 :     if (state.dataLoopNodes->Node(WaterInletNode).Temp <= DesupHtr.MaxInletWaterTemp + Acc) {
    8509       10217 :         QHeatRate = ((AverageWasteHeat * Effic * HEffFTemp) / DesupHtr.DXSysPLR) + (DesupHtr.PumpElecPower * DesupHtr.PumpFracToWater);
    8510             :     }
    8511             : 
    8512             :     // change to tanktypenum using parameters?
    8513       11413 :     Real64 partLoadRatio = 0.0;
    8514             :     Real64 NewTankTemp;
    8515             :     {
    8516       11413 :         auto const TankType(DesupHtr.TankTypeNum);
    8517             : 
    8518       11413 :         if (TankType == DataPlant::PlantEquipmentType::WtrHeaterMixed || TankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
    8519             : 
    8520       11413 :             DesupHtr.SaveWHMode = this->Mode;
    8521       11413 :             Real64 PreTankAvgTemp = this->TankTempAvg;
    8522       11413 :             Real64 NewTankAvgTemp = 0.0; // Initialization
    8523       11413 :             int max_count = 200;
    8524       11413 :             int count = 0;
    8525       11413 :             bool firstThrough = true;
    8526       11413 :             switch (DesupHtr.Mode) {
    8527       30917 :             case TankOperatingMode::Heating:
    8528             :                 // Calculate until consistency of desuperheater and tank source side energy transfer achieved
    8529       51325 :                 while ((std::abs(PreTankAvgTemp - NewTankAvgTemp) > DataHVACGlobals::SmallTempDiff || firstThrough) && count < max_count) {
    8530       20408 :                     count++;
    8531       20408 :                     firstThrough = false;
    8532       20408 :                     PreTankAvgTemp = this->TankTempAvg;
    8533       20408 :                     partLoadRatio = DesupHtr.DXSysPLR;
    8534       20408 :                     if (MdotWater > 0.0) {
    8535       20408 :                         state.dataLoopNodes->Node(WaterOutletNode).Temp = this->SourceOutletTemp + QHeatRate / (MdotWater * CpWater);
    8536             :                     } else {
    8537           0 :                         state.dataLoopNodes->Node(WaterOutletNode).Temp = this->SourceOutletTemp;
    8538             :                     }
    8539             : 
    8540             :                     //         set the full load outlet temperature on the water heater source inlet node (init has already been called)
    8541       20408 :                     this->SourceInletTemp = state.dataLoopNodes->Node(WaterOutletNode).Temp;
    8542             : 
    8543             :                     //         set the source mass flow rate for the tank
    8544       20408 :                     this->SourceMassFlowRate = MdotWater * partLoadRatio;
    8545             : 
    8546       20408 :                     this->MaxCapacity = DesupHtr.BackupElementCapacity;
    8547       20408 :                     this->MinCapacity = DesupHtr.BackupElementCapacity;
    8548       20408 :                     DesupHtr.DesuperheaterPLR = partLoadRatio;
    8549       20408 :                     DesupHtr.HeaterRate = QHeatRate * partLoadRatio;
    8550       20408 :                     this->CalcWaterThermalTank(state);
    8551       20408 :                     Real64 NewTankTemp = this->TankTemp;
    8552             : 
    8553       20408 :                     if (NewTankTemp > desupHtrSetPointTemp) {
    8554             :                         //           Only revert to floating mode if the tank temperature is higher than the cut out temperature
    8555        6856 :                         if (NewTankTemp > DesupHtr.SetPointTemp) {
    8556           0 :                             DesupHtr.Mode = TankOperatingMode::Floating;
    8557             :                         }
    8558             :                         int SolFla;
    8559       13712 :                         std::string IterNum;
    8560      137130 :                         auto f = [&state, this, desupHtrSetPointTemp, &DesupHtr, MdotWater](Real64 const HPPartLoadRatio) {
    8561       27426 :                             this->Mode = DesupHtr.SaveWHMode;
    8562       27426 :                             this->SourceMassFlowRate = MdotWater * HPPartLoadRatio;
    8563       27426 :                             this->CalcWaterThermalTank(state);
    8564       27426 :                             Real64 NewTankTemp = this->TankTemp;
    8565       27426 :                             Real64 PLRResidualWaterThermalTank = desupHtrSetPointTemp - NewTankTemp;
    8566       27426 :                             return PLRResidualWaterThermalTank;
    8567        6856 :                         };
    8568        6856 :                         General::SolveRoot(state, Acc, MaxIte, SolFla, partLoadRatio, f, 0.0, DesupHtr.DXSysPLR);
    8569        6856 :                         if (SolFla == -1) {
    8570           0 :                             IterNum = fmt::to_string(MaxIte);
    8571           0 :                             if (!state.dataGlobal->WarmupFlag) {
    8572           0 :                                 ++DesupHtr.IterLimitExceededNum1;
    8573           0 :                                 if (DesupHtr.IterLimitExceededNum1 == 1) {
    8574           0 :                                     ShowWarningError(state, DesupHtr.Type + " \"" + DesupHtr.Name + "\"");
    8575           0 :                                     ShowContinueError(state,
    8576           0 :                                                       format("Iteration limit exceeded calculating desuperheater unit part-load ratio, "
    8577             :                                                              "maximum iterations = {}. Part-load ratio returned = {:.3R}",
    8578             :                                                              IterNum,
    8579           0 :                                                              partLoadRatio));
    8580           0 :                                     ShowContinueErrorTimeStamp(state, "This error occurred in heating mode.");
    8581             :                                 } else {
    8582           0 :                                     ShowRecurringWarningErrorAtEnd(state,
    8583           0 :                                                                    DesupHtr.Type + " \"" + DesupHtr.Name +
    8584             :                                                                        "\":  Iteration limit exceeded in heating mode warning continues. "
    8585             :                                                                        "Part-load ratio statistics follow.",
    8586             :                                                                    DesupHtr.IterLimitErrIndex1,
    8587             :                                                                    partLoadRatio,
    8588             :                                                                    partLoadRatio);
    8589             :                                 }
    8590             :                             }
    8591        6856 :                         } else if (SolFla == -2) {
    8592           0 :                             partLoadRatio =
    8593           0 :                                 max(0.0, min(DesupHtr.DXSysPLR, (desupHtrSetPointTemp - this->SavedTankTemp) / (NewTankTemp - this->SavedTankTemp)));
    8594           0 :                             this->SourceMassFlowRate = MdotWater * partLoadRatio;
    8595           0 :                             this->CalcWaterThermalTank(state);
    8596           0 :                             if (!state.dataGlobal->WarmupFlag) {
    8597           0 :                                 ++DesupHtr.RegulaFalsiFailedNum1;
    8598           0 :                                 if (DesupHtr.RegulaFalsiFailedNum1 == 1) {
    8599           0 :                                     ShowWarningError(state, DesupHtr.Type + " \"" + DesupHtr.Name + "\"");
    8600           0 :                                     ShowContinueError(state,
    8601           0 :                                                       format("Desuperheater unit part-load ratio calculation failed: PLR limits of 0 to 1 "
    8602             :                                                              "exceeded. Part-load ratio used = {:.3R}",
    8603           0 :                                                              partLoadRatio));
    8604           0 :                                     ShowContinueError(state, "Please send this information to the EnergyPlus support group.");
    8605           0 :                                     ShowContinueErrorTimeStamp(state, "This error occurred in heating mode.");
    8606             :                                 } else {
    8607           0 :                                     ShowRecurringWarningErrorAtEnd(state,
    8608           0 :                                                                    DesupHtr.Type + " \"" + DesupHtr.Name +
    8609             :                                                                        "\":  Part-load ratio calculation failed in heating mode warning "
    8610             :                                                                        "continues. Part-load ratio statistics follow.",
    8611             :                                                                    DesupHtr.RegulaFalsiFailedIndex1,
    8612             :                                                                    partLoadRatio,
    8613             :                                                                    partLoadRatio);
    8614             :                                 }
    8615             :                             }
    8616             :                         }
    8617             :                     } else {
    8618       13552 :                         partLoadRatio = DesupHtr.DXSysPLR;
    8619             :                     }
    8620       20408 :                     NewTankAvgTemp = this->TankTempAvg;
    8621             :                 }
    8622       10509 :                 break;
    8623         904 :             case TankOperatingMode::Floating:
    8624         904 :                 if (MdotWater > 0.0) {
    8625         904 :                     state.dataLoopNodes->Node(WaterOutletNode).Temp =
    8626         904 :                         state.dataLoopNodes->Node(WaterInletNode).Temp + QHeatRate / (MdotWater * CpWater);
    8627             :                 } else {
    8628           0 :                     state.dataLoopNodes->Node(WaterOutletNode).Temp = state.dataLoopNodes->Node(WaterInletNode).Temp;
    8629             :                 }
    8630             :                 //         check tank temperature by setting source inlet mass flow rate to zero
    8631         904 :                 partLoadRatio = 0.0;
    8632             : 
    8633             :                 //         set the full load outlet temperature on the water heater source inlet node (init has already been called)
    8634         904 :                 this->SourceInletTemp = state.dataLoopNodes->Node(WaterOutletNode).Temp;
    8635             : 
    8636             :                 //         check tank temperature by setting source inlet mass flow rate to zero
    8637         904 :                 this->SourceMassFlowRate = 0.0;
    8638             : 
    8639             :                 //         disable the tank heater to find PLR of the HPWH
    8640         904 :                 this->MaxCapacity = 0.0;
    8641         904 :                 this->MinCapacity = 0.0;
    8642         904 :                 DesupHtr.DesuperheaterPLR = partLoadRatio;
    8643         904 :                 DesupHtr.HeaterRate = QHeatRate * partLoadRatio;
    8644         904 :                 this->CalcWaterThermalTank(state);
    8645         904 :                 NewTankTemp = this->TankTemp;
    8646             : 
    8647         904 :                 if (NewTankTemp <= (desupHtrSetPointTemp - DeadBandTempDiff)) {
    8648          44 :                     this->Mode = DesupHtr.SaveWHMode;
    8649          44 :                     if ((this->SavedTankTemp - NewTankTemp) != 0.0) {
    8650          44 :                         partLoadRatio =
    8651          44 :                             min(DesupHtr.DXSysPLR,
    8652          44 :                                 max(0.0, ((desupHtrSetPointTemp - DeadBandTempDiff) - NewTankTemp) / (this->SavedTankTemp - NewTankTemp)));
    8653             :                     } else {
    8654           0 :                         partLoadRatio = DesupHtr.DXSysPLR;
    8655             :                     }
    8656         358 :                     while ((std::abs(PreTankAvgTemp - NewTankAvgTemp) > DataHVACGlobals::SmallTempDiff || firstThrough) && count < max_count) {
    8657         157 :                         count++;
    8658         157 :                         firstThrough = false;
    8659         157 :                         PreTankAvgTemp = this->TankTempAvg;
    8660         157 :                         DesupHtr.Mode = TankOperatingMode::Heating;
    8661         157 :                         if (MdotWater > 0.0) {
    8662         157 :                             state.dataLoopNodes->Node(WaterOutletNode).Temp = this->SourceOutletTemp + QHeatRate / (MdotWater * CpWater);
    8663             :                         } else {
    8664           0 :                             state.dataLoopNodes->Node(WaterOutletNode).Temp = this->SourceOutletTemp;
    8665             :                         }
    8666             : 
    8667             :                         //           set the full load outlet temperature on the water heater source inlet node
    8668         157 :                         this->SourceInletTemp = state.dataLoopNodes->Node(WaterOutletNode).Temp;
    8669             : 
    8670             :                         //           set the source mass flow rate for the tank and enable backup heating element
    8671         157 :                         this->SourceMassFlowRate = MdotWater * partLoadRatio;
    8672         157 :                         this->MaxCapacity = DesupHtr.BackupElementCapacity;
    8673         157 :                         this->MinCapacity = DesupHtr.BackupElementCapacity;
    8674         157 :                         DesupHtr.DesuperheaterPLR = partLoadRatio;
    8675         157 :                         DesupHtr.HeaterRate = QHeatRate * partLoadRatio;
    8676         157 :                         this->CalcWaterThermalTank(state);
    8677         157 :                         NewTankTemp = this->TankTemp;
    8678             : 
    8679         157 :                         if (NewTankTemp > desupHtrSetPointTemp) {
    8680             :                             //           Only revert to floating mode if the tank temperature is higher than the cut-out temperature
    8681           0 :                             if (NewTankTemp > DesupHtr.SetPointTemp) {
    8682           0 :                                 DesupHtr.Mode = TankOperatingMode::Floating;
    8683             :                             }
    8684             :                             int SolFla;
    8685           0 :                             std::string IterNum;
    8686           0 :                             auto f = [&state, this, desupHtrSetPointTemp, &DesupHtr, MdotWater](Real64 const HPPartLoadRatio) {
    8687           0 :                                 this->Mode = DesupHtr.SaveWHMode;
    8688           0 :                                 this->SourceMassFlowRate = MdotWater * HPPartLoadRatio;
    8689           0 :                                 this->CalcWaterThermalTank(state);
    8690           0 :                                 Real64 NewTankTemp = this->TankTemp;
    8691           0 :                                 Real64 PLRResidualWaterThermalTank = desupHtrSetPointTemp - NewTankTemp;
    8692           0 :                                 return PLRResidualWaterThermalTank;
    8693           0 :                             };
    8694           0 :                             General::SolveRoot(state, Acc, MaxIte, SolFla, partLoadRatio, f, 0.0, DesupHtr.DXSysPLR);
    8695           0 :                             if (SolFla == -1) {
    8696           0 :                                 IterNum = fmt::to_string(MaxIte);
    8697           0 :                                 if (!state.dataGlobal->WarmupFlag) {
    8698           0 :                                     ++DesupHtr.IterLimitExceededNum2;
    8699           0 :                                     if (DesupHtr.IterLimitExceededNum2 == 1) {
    8700           0 :                                         ShowWarningError(state, DesupHtr.Type + " \"" + DesupHtr.Name + "\"");
    8701           0 :                                         ShowContinueError(state,
    8702           0 :                                                           format("Iteration limit exceeded calculating desuperheater unit part-load ratio, "
    8703             :                                                                  "maximum iterations = {}. Part-load ratio returned = {:.3R}",
    8704             :                                                                  IterNum,
    8705           0 :                                                                  partLoadRatio));
    8706           0 :                                         ShowContinueErrorTimeStamp(state, "This error occurred in float mode.");
    8707             :                                     } else {
    8708           0 :                                         ShowRecurringWarningErrorAtEnd(state,
    8709           0 :                                                                        DesupHtr.Type + " \"" + DesupHtr.Name +
    8710             :                                                                            "\":  Iteration limit exceeded in float mode warning continues. "
    8711             :                                                                            "Part-load ratio statistics follow.",
    8712             :                                                                        DesupHtr.IterLimitErrIndex2,
    8713             :                                                                        partLoadRatio,
    8714             :                                                                        partLoadRatio);
    8715             :                                     }
    8716             :                                 }
    8717           0 :                             } else if (SolFla == -2) {
    8718           0 :                                 partLoadRatio = max(
    8719           0 :                                     0.0, min(DesupHtr.DXSysPLR, (desupHtrSetPointTemp - this->SavedTankTemp) / (NewTankTemp - this->SavedTankTemp)));
    8720           0 :                                 if (!state.dataGlobal->WarmupFlag) {
    8721           0 :                                     ++DesupHtr.RegulaFalsiFailedNum2;
    8722           0 :                                     if (DesupHtr.RegulaFalsiFailedNum2 == 1) {
    8723           0 :                                         ShowWarningError(state, DesupHtr.Type + " \"" + DesupHtr.Name + "\"");
    8724           0 :                                         ShowContinueError(state,
    8725           0 :                                                           format("Desuperheater unit part-load ratio calculation failed: PLR limits of 0 to "
    8726             :                                                                  "1 exceeded. Part-load ratio used = {:.3R}",
    8727           0 :                                                                  partLoadRatio));
    8728           0 :                                         ShowContinueError(state, "Please send this information to the EnergyPlus support group.");
    8729           0 :                                         ShowContinueErrorTimeStamp(state, "This error occurred in float mode.");
    8730             :                                     } else {
    8731           0 :                                         ShowRecurringWarningErrorAtEnd(
    8732             :                                             state,
    8733           0 :                                             DesupHtr.Type + " \"" + DesupHtr.Name +
    8734             :                                                 "\": Part-load ratio calculation failed in float mode warning "
    8735             :                                                 "continues. Part-load ratio statistics follow.",
    8736           0 :                                             state.dataWaterThermalTanks->WaterHeaterDesuperheater(DesuperheaterNum).RegulaFalsiFailedIndex2,
    8737             :                                             partLoadRatio,
    8738             :                                             partLoadRatio);
    8739             :                                     }
    8740             :                                 }
    8741             :                             }
    8742             :                         }
    8743         157 :                         NewTankAvgTemp = this->TankTempAvg;
    8744             :                     }
    8745             :                 } else {
    8746         860 :                     this->MaxCapacity = DesupHtr.BackupElementCapacity;
    8747         860 :                     this->MinCapacity = DesupHtr.BackupElementCapacity;
    8748             :                 }
    8749         904 :                 break;
    8750           0 :             default:
    8751           0 :                 break;
    8752       11413 :             }
    8753             : 
    8754             :             //   should never get here, case is checked in GetWaterThermalTankInput
    8755             :         } else {
    8756           0 :             ShowFatalError(state,
    8757           0 :                            "Coil:WaterHeating:Desuperheater = " + state.dataWaterThermalTanks->WaterHeaterDesuperheater(DesuperheaterNum).Name +
    8758           0 :                                ":  invalid water heater tank type and name entered = " +
    8759           0 :                                state.dataWaterThermalTanks->WaterHeaterDesuperheater(DesuperheaterNum).TankType + ", " +
    8760           0 :                                state.dataWaterThermalTanks->WaterHeaterDesuperheater(DesuperheaterNum).TankName);
    8761             :         }
    8762             :     }
    8763             : 
    8764       11413 :     if (QHeatRate == 0) partLoadRatio = 0.0;
    8765             : 
    8766       11413 :     state.dataLoopNodes->Node(WaterOutletNode).MassFlowRate = MdotWater * partLoadRatio;
    8767       11413 :     DesupHtr.HEffFTempOutput = HEffFTemp;
    8768       11413 :     DesupHtr.HeaterRate = QHeatRate * partLoadRatio;
    8769       11413 :     this->SourceMassFlowRate = MdotWater * partLoadRatio;
    8770             : 
    8771       11413 :     if (partLoadRatio == 0) {
    8772        1196 :         this->SourceInletTemp = this->SourceOutletTemp;
    8773        1196 :         state.dataLoopNodes->Node(WaterOutletNode).Temp = this->SourceOutletTemp;
    8774        1196 :         DesupHtr.HEffFTempOutput = 0.0;
    8775        1196 :         DesupHtr.HeaterRate = 0.0;
    8776             :     }
    8777             : 
    8778       11413 :     DesupHtr.HeaterEnergy = DesupHtr.HeaterRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    8779       11413 :     DesupHtr.DesuperheaterPLR = partLoadRatio;
    8780       11413 :     DesupHtr.OnCycParaFuelRate = DesupHtr.OnCycParaLoad * partLoadRatio;
    8781       11413 :     DesupHtr.OnCycParaFuelEnergy = DesupHtr.OnCycParaFuelRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    8782       11413 :     DesupHtr.OffCycParaFuelRate = DesupHtr.OffCycParaLoad * (1 - partLoadRatio);
    8783       11413 :     DesupHtr.OffCycParaFuelEnergy = DesupHtr.OffCycParaFuelRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    8784       11413 :     DesupHtr.PumpPower = DesupHtr.PumpElecPower * (partLoadRatio);
    8785       11413 :     DesupHtr.PumpEnergy = DesupHtr.PumpPower * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    8786             : 
    8787             :     // Update used waste heat (just in case multiple users of waste heat use same source)
    8788       11413 :     if (DesupHtr.ValidSourceType) {
    8789       11413 :         int SourceID = DesupHtr.ReclaimHeatingSourceIndexNum;
    8790       11413 :         if (DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::CompressorRackRefrigeratedCase) {
    8791           0 :             state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).WaterHeatingDesuperheaterReclaimedHeat(DesuperheaterNum) = DesupHtr.HeaterRate;
    8792           0 :             state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal = 0.0;
    8793           0 :             for (auto &num : state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).WaterHeatingDesuperheaterReclaimedHeat)
    8794           0 :                 state.dataHeatBal->HeatReclaimRefrigeratedRack(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal += num;
    8795       11413 :         } else if (DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::CondenserRefrigeration) {
    8796        4540 :             state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).WaterHeatingDesuperheaterReclaimedHeat(DesuperheaterNum) = DesupHtr.HeaterRate;
    8797        4540 :             state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal = 0.0;
    8798        9080 :             for (auto &num : state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).WaterHeatingDesuperheaterReclaimedHeat)
    8799        4540 :                 state.dataHeatBal->HeatReclaimRefrigCondenser(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal += num;
    8800       11474 :         } else if (DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::DXCooling ||
    8801        9202 :                    DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::DXMultiSpeed ||
    8802        4601 :                    DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::DXMultiMode) {
    8803        2272 :             state.dataHeatBal->HeatReclaimDXCoil(SourceID).WaterHeatingDesuperheaterReclaimedHeat(DesuperheaterNum) = DesupHtr.HeaterRate;
    8804        2272 :             state.dataHeatBal->HeatReclaimDXCoil(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal = 0.0;
    8805        4544 :             for (auto &num : state.dataHeatBal->HeatReclaimDXCoil(SourceID).WaterHeatingDesuperheaterReclaimedHeat)
    8806        4544 :                 state.dataHeatBal->HeatReclaimDXCoil(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal += num;
    8807        4601 :         } else if (DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::DXVariableCooling) {
    8808        2514 :             state.dataHeatBal->HeatReclaimVS_DXCoil(SourceID).WaterHeatingDesuperheaterReclaimedHeat(DesuperheaterNum) = DesupHtr.HeaterRate;
    8809        2514 :             state.dataHeatBal->HeatReclaimVS_DXCoil(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal = 0.0;
    8810        5028 :             for (auto &num : state.dataHeatBal->HeatReclaimVS_DXCoil(SourceID).WaterHeatingDesuperheaterReclaimedHeat)
    8811        2514 :                 state.dataHeatBal->HeatReclaimVS_DXCoil(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal += num;
    8812        2087 :         } else if (DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::AirWaterHeatPumpEQ) {
    8813         951 :             state.dataHeatBal->HeatReclaimSimple_WAHPCoil(SourceID).WaterHeatingDesuperheaterReclaimedHeat(DesuperheaterNum) = DesupHtr.HeaterRate;
    8814         951 :             state.dataHeatBal->HeatReclaimSimple_WAHPCoil(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal = 0.0;
    8815        1902 :             for (auto &num : state.dataHeatBal->HeatReclaimSimple_WAHPCoil(SourceID).WaterHeatingDesuperheaterReclaimedHeat)
    8816         951 :                 state.dataHeatBal->HeatReclaimSimple_WAHPCoil(SourceID).WaterHeatingDesuperheaterReclaimedHeatTotal += num;
    8817        1136 :         } else if (DesupHtr.ReclaimHeatingSource == ReclaimHeatObjectType::CoilCoolingDX) {
    8818        1136 :             state.dataCoilCooingDX->coilCoolingDXs[DesupHtr.ReclaimHeatingSourceIndexNum].reclaimHeat.WaterHeatingDesuperheaterReclaimedHeat(
    8819        2272 :                 DesuperheaterNum) = DesupHtr.HeaterRate;
    8820        1136 :             state.dataCoilCooingDX->coilCoolingDXs[DesupHtr.ReclaimHeatingSourceIndexNum].reclaimHeat.WaterHeatingDesuperheaterReclaimedHeatTotal =
    8821             :                 0.0;
    8822        2272 :             for (auto &num :
    8823        1136 :                  state.dataCoilCooingDX->coilCoolingDXs[DesupHtr.ReclaimHeatingSourceIndexNum].reclaimHeat.WaterHeatingDesuperheaterReclaimedHeat)
    8824        1136 :                 state.dataCoilCooingDX->coilCoolingDXs[DesupHtr.ReclaimHeatingSourceIndexNum]
    8825        1136 :                     .reclaimHeat.WaterHeatingDesuperheaterReclaimedHeatTotal += num;
    8826             :         }
    8827             :     }
    8828             : }
    8829             : 
    8830      644606 : void WaterThermalTankData::CalcHeatPumpWaterHeater(EnergyPlusData &state, bool const FirstHVACIteration)
    8831             : {
    8832             : 
    8833             :     // SUBROUTINE INFORMATION:
    8834             :     //       AUTHOR         Richard Raustad
    8835             :     //       DATE WRITTEN   March 2005
    8836             :     //       MODIFIED       B. Griffith, Jan 2012 for stratified tank
    8837             :     //                        B. Shen 12/2014, add air-source variable-speed heat pump water heating
    8838             :     //       RE-ENGINEERED  na
    8839             : 
    8840             :     // PURPOSE OF THIS SUBROUTINE:
    8841             :     // Simulates a heat pump water heater
    8842             : 
    8843             :     // METHODOLOGY EMPLOYED:
    8844             :     // Simulate the water heater tank, DX coil, and fan to meet the water heating requirements.
    8845             : 
    8846      644606 :     int constexpr MaxIte(500);   // maximum number of iterations
    8847      644606 :     Real64 constexpr Acc(0.001); // Accuracy of result from RegulaFalsi
    8848             : 
    8849             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    8850             :     Real64 MdotWater;                                                                         // mass flow rate of condenser water, kg/s
    8851      644606 :     IntegratedHeatPump::IHPOperationMode IHPMode(IntegratedHeatPump::IHPOperationMode::Idle); // IHP working mode
    8852      644606 :     Real64 EMP1(0.0), EMP2(0.0), EMP3(0.0);
    8853             : 
    8854             :     // References to objects used in this function
    8855      644606 :     HeatPumpWaterHeaterData &HeatPump = state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum);
    8856             : 
    8857             :     // initialize local variables
    8858      644606 :     int AvailSchedule = ScheduleManager::GetCurrentScheduleValue(state, HeatPump.AvailSchedPtr);
    8859      644606 :     int HPAirInletNode = HeatPump.HeatPumpAirInletNode;
    8860      644606 :     int HPAirOutletNode = HeatPump.HeatPumpAirOutletNode;
    8861      644606 :     int OutdoorAirNode = HeatPump.OutsideAirNode;
    8862      644606 :     int ExhaustAirNode = HeatPump.ExhaustAirNode;
    8863      644606 :     int HPWaterInletNode = HeatPump.CondWaterInletNode;
    8864      644606 :     int HPWaterOutletNode = HeatPump.CondWaterOutletNode;
    8865      644606 :     int InletAirMixerNode = HeatPump.InletAirMixerNode;
    8866      644606 :     int OutletAirSplitterNode = HeatPump.OutletAirSplitterNode;
    8867      644606 :     int DXCoilAirInletNode = HeatPump.DXCoilAirInletNode;
    8868      644606 :     state.dataWaterThermalTanks->hpPartLoadRatio = 0.0;
    8869      644606 :     DataHVACGlobals::CompressorOperation CompressorOp = DataHVACGlobals::CompressorOperation::Off; // DX compressor operation; 1=on, 0=off
    8870      644606 :     HeatPump.OnCycParaFuelRate = 0.0;
    8871      644606 :     HeatPump.OnCycParaFuelEnergy = 0.0;
    8872      644606 :     HeatPump.OffCycParaFuelRate = 0.0;
    8873      644606 :     HeatPump.OffCycParaFuelEnergy = 0.0;
    8874      644606 :     state.dataLoopNodes->Node(HPWaterOutletNode) = state.dataLoopNodes->Node(HPWaterInletNode);
    8875      644606 :     int MaxSpeedNum = HeatPump.NumofSpeed; // speed number of variable speed HPWH coil
    8876             : 
    8877             :     // assign set point temperature (cut-out) and dead band temp diff (cut-in = cut-out minus dead band temp diff)
    8878      644606 :     Real64 HPSetPointTemp = HeatPump.SetPointTemp;
    8879      644606 :     Real64 DeadBandTempDiff = HeatPump.DeadBandTempDiff;
    8880      644606 :     Real64 RhoWater = Psychrometrics::RhoH2O(HPSetPointTemp); // initialize
    8881             : 
    8882             :     // store first iteration tank temperature and HP mode of operation
    8883             :     // this code can be called more than once with FirstHVACIteration = .TRUE., use FirstTimeThroughFlag to control save
    8884      644606 :     if (FirstHVACIteration && !state.dataHVACGlobal->ShortenTimeStepSys && HeatPump.FirstTimeThroughFlag) {
    8885       84350 :         this->SavedTankTemp = this->TankTemp;
    8886       84350 :         HeatPump.SaveMode = HeatPump.Mode;
    8887       84350 :         HeatPump.SaveWHMode = this->Mode;
    8888       84350 :         HeatPump.FirstTimeThroughFlag = false;
    8889             :     }
    8890             : 
    8891      644606 :     if (!FirstHVACIteration) HeatPump.FirstTimeThroughFlag = true;
    8892             : 
    8893             :     // check if HPWH is off for some reason and simulate HPWH air- and water-side mass flow rates of 0
    8894             :     // simulate only water heater tank if HP compressor is scheduled off
    8895             :     //   simulate only water heater tank if HP compressor cut-out temperature is lower than the tank's cut-in temperature
    8896             :     //    simulate only water heater tank if HP inlet air temperature is below minimum temperature for HP compressor operation
    8897             :     //    if the tank maximum temperature limit is less than the HPWH set point temp, disable HPWH
    8898     2578424 :     if (AvailSchedule == 0.0 || (HPSetPointTemp - DeadBandTempDiff) <= this->SetPointTemp ||
    8899     1136722 :         state.dataHVACGlobal->HPWHInletDBTemp < HeatPump.MinAirTempForHPOperation ||
    8900     1476348 :         state.dataHVACGlobal->HPWHInletDBTemp > HeatPump.MaxAirTempForHPOperation || HPSetPointTemp >= this->TankTempLimit ||
    8901      671512 :         (!HeatPump.AllowHeatingElementAndHeatPumpToRunAtSameTime && this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed &&
    8902     1291324 :          this->SavedMode == TankOperatingMode::Heating) ||
    8903      671512 :         (!HeatPump.AllowHeatingElementAndHeatPumpToRunAtSameTime &&
    8904      358792 :          this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified && (this->SavedHeaterOn1 || this->SavedHeaterOn2))) {
    8905             :         //   revert to float mode any time HPWH compressor is OFF
    8906      154602 :         HeatPump.Mode = TankOperatingMode::Floating;
    8907      154602 :         if (InletAirMixerNode > 0) {
    8908           0 :             state.dataLoopNodes->Node(InletAirMixerNode) = state.dataLoopNodes->Node(HPAirInletNode);
    8909             :         }
    8910             :         //   pass node info and simulate crankcase heater
    8911      154602 :         if (MaxSpeedNum > 0) {
    8912       32774 :             int VSCoilNum = HeatPump.DXCoilNum;
    8913             : 
    8914       32774 :             if (HeatPump.bIsIHP) {
    8915        5028 :                 VSCoilNum = state.dataIntegratedHP->IntegratedHeatPumps(VSCoilNum).SCWHCoilIndex;
    8916             :             }
    8917             :             // set the SCWH mode
    8918       32774 :             Real64 SpeedRatio = 1.0; // speed ratio for interpolating between two speed levels
    8919       32774 :             int SpeedNum = 1;
    8920       32774 :             if (HeatPump.FanPlacement == DataHVACGlobals::BlowThru) {
    8921       32774 :                 if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    8922       25398 :                     state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    8923             :                 } else {
    8924        7376 :                     Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    8925             :                 }
    8926       32774 :                 this->SetVSHPWHFlowRates(state, HeatPump, SpeedNum, SpeedRatio, RhoWater, MdotWater, FirstHVACIteration);
    8927       32774 :                 if (HeatPump.bIsIHP)
    8928       15084 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
    8929             :                                                               "",
    8930             :                                                               VSCoilNum,
    8931             :                                                               DataHVACGlobals::CycFanCycCoil,
    8932             :                                                               EMP1,
    8933             :                                                               EMP2,
    8934             :                                                               EMP3,
    8935             :                                                               DataHVACGlobals::CompressorOperation::On,
    8936        5028 :                                                               state.dataWaterThermalTanks->hpPartLoadRatio,
    8937             :                                                               SpeedNum,
    8938             :                                                               SpeedRatio,
    8939             :                                                               0.0,
    8940             :                                                               0.0,
    8941        5028 :                                                               1.0);
    8942             :                 else
    8943       55492 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
    8944             :                                                               HeatPump.DXCoilName,
    8945             :                                                               VSCoilNum,
    8946             :                                                               DataHVACGlobals::CycFanCycCoil,
    8947             :                                                               EMP1,
    8948             :                                                               EMP2,
    8949             :                                                               EMP3,
    8950             :                                                               DataHVACGlobals::CompressorOperation::On,
    8951       27746 :                                                               state.dataWaterThermalTanks->hpPartLoadRatio,
    8952             :                                                               SpeedNum,
    8953             :                                                               SpeedRatio,
    8954             :                                                               0.0,
    8955             :                                                               0.0,
    8956             :                                                               1.0);
    8957             :             } else {
    8958           0 :                 this->SetVSHPWHFlowRates(state, HeatPump, SpeedNum, SpeedRatio, RhoWater, MdotWater, FirstHVACIteration);
    8959           0 :                 if (HeatPump.bIsIHP)
    8960           0 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
    8961             :                                                               "",
    8962             :                                                               VSCoilNum,
    8963             :                                                               DataHVACGlobals::CycFanCycCoil,
    8964             :                                                               EMP1,
    8965             :                                                               EMP2,
    8966             :                                                               EMP3,
    8967             :                                                               DataHVACGlobals::CompressorOperation::On,
    8968           0 :                                                               state.dataWaterThermalTanks->hpPartLoadRatio,
    8969             :                                                               SpeedNum,
    8970             :                                                               SpeedRatio,
    8971             :                                                               0.0,
    8972             :                                                               0.0,
    8973           0 :                                                               1.0);
    8974             :                 else
    8975           0 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
    8976             :                                                               HeatPump.DXCoilName,
    8977             :                                                               VSCoilNum,
    8978             :                                                               DataHVACGlobals::CycFanCycCoil,
    8979             :                                                               EMP1,
    8980             :                                                               EMP2,
    8981             :                                                               EMP3,
    8982             :                                                               DataHVACGlobals::CompressorOperation::On,
    8983           0 :                                                               state.dataWaterThermalTanks->hpPartLoadRatio,
    8984             :                                                               SpeedNum,
    8985             :                                                               SpeedRatio,
    8986             :                                                               0.0,
    8987             :                                                               0.0,
    8988             :                                                               1.0);
    8989           0 :                 if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    8990           0 :                     state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    8991             :                 } else {
    8992           0 :                     Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    8993             :                 }
    8994             :             }
    8995             : 
    8996             :             // set the DWH mode
    8997       32774 :             if (HeatPump.bIsIHP) {
    8998        5028 :                 VSCoilNum = state.dataIntegratedHP->IntegratedHeatPumps(HeatPump.DXCoilNum).DWHCoilIndex;
    8999             : 
    9000        5028 :                 if (VSCoilNum > 0) // if DWH coil exists
    9001             :                 {
    9002        5028 :                     if (HeatPump.FanPlacement == DataHVACGlobals::BlowThru) {
    9003        5028 :                         if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9004           0 :                             state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9005             :                         } else {
    9006        5028 :                             Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9007             :                         }
    9008        5028 :                         this->SetVSHPWHFlowRates(state, HeatPump, SpeedNum, SpeedRatio, RhoWater, MdotWater, FirstHVACIteration);
    9009       15084 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
    9010             :                                                                   "",
    9011             :                                                                   VSCoilNum,
    9012             :                                                                   DataHVACGlobals::CycFanCycCoil,
    9013             :                                                                   EMP1,
    9014             :                                                                   EMP2,
    9015             :                                                                   EMP3,
    9016             :                                                                   DataHVACGlobals::CompressorOperation::On,
    9017        5028 :                                                                   state.dataWaterThermalTanks->hpPartLoadRatio,
    9018             :                                                                   SpeedNum,
    9019             :                                                                   SpeedRatio,
    9020             :                                                                   0.0,
    9021             :                                                                   0.0,
    9022        5028 :                                                                   1.0);
    9023             :                     } else {
    9024           0 :                         this->SetVSHPWHFlowRates(state, HeatPump, SpeedNum, SpeedRatio, RhoWater, MdotWater, FirstHVACIteration);
    9025           0 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
    9026             :                                                                   "",
    9027             :                                                                   VSCoilNum,
    9028             :                                                                   DataHVACGlobals::CycFanCycCoil,
    9029             :                                                                   EMP1,
    9030             :                                                                   EMP2,
    9031             :                                                                   EMP3,
    9032             :                                                                   DataHVACGlobals::CompressorOperation::On,
    9033           0 :                                                                   state.dataWaterThermalTanks->hpPartLoadRatio,
    9034             :                                                                   SpeedNum,
    9035             :                                                                   SpeedRatio,
    9036             :                                                                   0.0,
    9037             :                                                                   0.0,
    9038           0 :                                                                   1.0);
    9039           0 :                         if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9040           0 :                             state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9041             :                         } else {
    9042           0 :                             Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9043             :                         }
    9044             :                     }
    9045             :                 }
    9046             :             }
    9047             : 
    9048             :         } else {
    9049      121828 :             if (HeatPump.FanPlacement == DataHVACGlobals::BlowThru) {
    9050      119716 :                 if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9051       93922 :                     state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9052             :                 } else {
    9053       25794 :                     Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9054             :                 }
    9055      239432 :                 DXCoils::SimDXCoil(state,
    9056             :                                    HeatPump.DXCoilName,
    9057             :                                    CompressorOp,
    9058             :                                    FirstHVACIteration,
    9059             :                                    HeatPump.DXCoilNum,
    9060             :                                    DataHVACGlobals::CycFanCycCoil,
    9061      119716 :                                    state.dataWaterThermalTanks->hpPartLoadRatio);
    9062             :             } else {
    9063        4224 :                 DXCoils::SimDXCoil(state,
    9064             :                                    HeatPump.DXCoilName,
    9065             :                                    CompressorOp,
    9066             :                                    FirstHVACIteration,
    9067             :                                    HeatPump.DXCoilNum,
    9068             :                                    DataHVACGlobals::CycFanCycCoil,
    9069        2112 :                                    state.dataWaterThermalTanks->hpPartLoadRatio);
    9070        2112 :                 if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9071        2112 :                     state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9072             :                 } else {
    9073           0 :                     Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9074             :                 }
    9075             :             }
    9076             :         }
    9077             : 
    9078      154602 :         if (OutletAirSplitterNode > 0) {
    9079           0 :             state.dataLoopNodes->Node(HPAirOutletNode) = state.dataLoopNodes->Node(OutletAirSplitterNode);
    9080             :         }
    9081             : 
    9082             :         //   Simulate tank if HP compressor unavailable for water heating
    9083      154602 :         this->CalcWaterThermalTank(state);
    9084             : 
    9085             :         //   If HPWH compressor is available and unit is off for another reason, off-cycle parasitics are calculated
    9086      154602 :         if (AvailSchedule != 0) {
    9087      154602 :             HeatPump.OffCycParaFuelRate = HeatPump.OffCycParaLoad * (1.0 - state.dataWaterThermalTanks->hpPartLoadRatio);
    9088      154602 :             HeatPump.OffCycParaFuelEnergy = HeatPump.OffCycParaFuelRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    9089             :         }
    9090             : 
    9091             :         //   Warn if HPWH compressor cut-in temperature is less than the water heater tank's set point temp
    9092      154602 :         if (!state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingSizing && !state.dataGlobal->KickOffSimulation) {
    9093       13746 :             if ((HPSetPointTemp - DeadBandTempDiff) <= this->SetPointTemp) {
    9094           0 :                 Real64 HPMinTemp = HPSetPointTemp - DeadBandTempDiff;
    9095           0 :                 const auto HPMinTempChar = fmt::to_string(HPMinTemp);
    9096           0 :                 ++HeatPump.HPSetPointError;
    9097             :                 //  add logic for warmup, DataGlobals::KickOffSimulation and doing sizing here
    9098           0 :                 if (HeatPump.HPSetPointError == 1) {
    9099           0 :                     ShowWarningError(state,
    9100           0 :                                      HeatPump.Type + " \"" + HeatPump.Name +
    9101             :                                          ":  Water heater tank set point temperature is greater than or equal to the cut-in temperature of the heat "
    9102             :                                          "pump water heater. Heat Pump will be disabled and simulation continues.");
    9103           0 :                     ShowContinueErrorTimeStamp(state, " ...Heat Pump cut-in temperature=" + HPMinTempChar);
    9104             :                 } else {
    9105           0 :                     ShowRecurringWarningErrorAtEnd(state,
    9106           0 :                                                    HeatPump.Type + " \"" + HeatPump.Name +
    9107             :                                                        ":  Water heater tank set point temperature is greater than or equal to the cut-in "
    9108             :                                                        "temperature of the heat pump water heater. Heat Pump will be disabled error continues...",
    9109             :                                                    HeatPump.HPSetPointErrIndex1,
    9110             :                                                    HPMinTemp,
    9111             :                                                    HPMinTemp);
    9112             :                 }
    9113             :             }
    9114             :         }
    9115      309204 :         return;
    9116             :     }
    9117      490004 :     Real64 savedTankTemp = this->SavedTankTemp;
    9118      490004 :     HeatPump.Mode = HeatPump.SaveMode;
    9119             : 
    9120      490004 :     RhoWater = Psychrometrics::RhoH2O(savedTankTemp); // update water density using tank temp
    9121             : 
    9122             :     // set the heat pump air- and water-side mass flow rate
    9123      490004 :     MdotWater = HeatPump.OperatingWaterFlowRate * Psychrometrics::RhoH2O(savedTankTemp);
    9124             : 
    9125             :     // Select mode of operation (float mode or heat mode) from last iteration.
    9126             :     // Determine if heating will occur this iteration and get an estimate of the PLR
    9127      490004 :     if (HeatPump.Mode == TankOperatingMode::Heating) {
    9128             :         // HPWH was heating last iteration and will continue to heat until the set point is reached
    9129      161071 :         state.dataWaterThermalTanks->hpPartLoadRatio = 1.0;
    9130      161071 :         if (savedTankTemp > HPSetPointTemp) { // tank set point temp may have been reduced since last iteration and float mode may be needed
    9131          56 :             HeatPump.Mode = TankOperatingMode::Floating;
    9132          56 :             state.dataWaterThermalTanks->hpPartLoadRatio = 0.0;
    9133             :             // check to see if HP needs to operate
    9134             :             // set the condenser inlet node temperature and full mass flow rate prior to calling the HPWH DX coil
    9135          56 :             if (HeatPump.HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed) {
    9136          56 :                 state.dataLoopNodes->Node(HPWaterInletNode).Temp = savedTankTemp;
    9137          56 :                 state.dataLoopNodes->Node(HPWaterOutletNode).Temp = savedTankTemp;
    9138           0 :             } else if (HeatPump.HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
    9139           0 :                 state.dataLoopNodes->Node(HPWaterInletNode).Temp = this->SourceOutletTemp;
    9140           0 :                 state.dataLoopNodes->Node(HPWaterOutletNode).Temp = this->SourceInletTemp;
    9141             :             }
    9142          56 :             state.dataLoopNodes->Node(HPWaterInletNode).MassFlowRate = 0.0;
    9143          56 :             state.dataLoopNodes->Node(HPWaterOutletNode).MassFlowRate = 0.0;
    9144             : 
    9145             :             // Check tank temperature by setting source inlet mass flow rate to zero.
    9146          56 :             state.dataWaterThermalTanks->hpPartLoadRatio = 0.0;
    9147             : 
    9148             :             // Set the full load outlet temperature on the water heater source inlet node (init has already been called).
    9149          56 :             this->SourceInletTemp = state.dataLoopNodes->Node(HPWaterOutletNode).Temp;
    9150             : 
    9151             :             // Disable the tank's internal heating element to find PLR of the HPWH using floating temperatures.
    9152          56 :             this->MaxCapacity = 0.0;
    9153          56 :             this->MinCapacity = 0.0;
    9154          56 :             this->SourceMassFlowRate = 0.0; // disables heat pump for mixed tanks
    9155          56 :             Real64 SourceEffectivenessBackup = this->SourceEffectiveness;
    9156          56 :             this->SourceEffectiveness = 0.0; // disables heat pump for stratified tanks
    9157          56 :             this->CalcWaterThermalTank(state);
    9158          56 :             this->SourceEffectiveness = SourceEffectivenessBackup;
    9159          56 :             Real64 NewTankTemp = this->GetHPWHSensedTankTemp(state);
    9160             : 
    9161             :             // Reset the tank's internal heating element capacity.
    9162          56 :             this->MaxCapacity = HeatPump.BackupElementCapacity;
    9163          56 :             this->MinCapacity = HeatPump.BackupElementCapacity;
    9164             : 
    9165             :             // Check to see if the tank drifts below set point if no heating happens.
    9166          56 :             if (NewTankTemp <= (HPSetPointTemp - DeadBandTempDiff)) {
    9167             : 
    9168             :                 // HPWH is now in heating mode
    9169          36 :                 HeatPump.Mode = TankOperatingMode::Heating;
    9170             : 
    9171             :                 // Reset the water heater's mode (call above may have changed modes)
    9172          36 :                 this->Mode = HeatPump.SaveWHMode;
    9173             : 
    9174          36 :                 state.dataWaterThermalTanks->hpPartLoadRatio = 1.0;
    9175             :             }
    9176             :         } else { // or use side nodes may meet set point without need for heat pump compressor operation
    9177             :                  // check to see if HP needs to operate
    9178      161015 :             if (HeatPump.HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed) {
    9179       47670 :                 state.dataLoopNodes->Node(HPWaterInletNode).Temp = savedTankTemp;
    9180       47670 :                 state.dataLoopNodes->Node(HPWaterOutletNode).Temp = savedTankTemp;
    9181      113345 :             } else if (HeatPump.HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
    9182      113345 :                 state.dataLoopNodes->Node(HPWaterInletNode).Temp = this->SourceOutletTemp;
    9183      113345 :                 state.dataLoopNodes->Node(HPWaterOutletNode).Temp = this->SourceInletTemp;
    9184             :             }
    9185             :             // Check tank temperature by setting source inlet mass flow rate to zero.
    9186      161015 :             state.dataLoopNodes->Node(HPWaterInletNode).MassFlowRate = 0.0;
    9187      161015 :             state.dataLoopNodes->Node(HPWaterOutletNode).MassFlowRate = 0.0;
    9188             : 
    9189      161015 :             state.dataWaterThermalTanks->hpPartLoadRatio = 0.0;
    9190             : 
    9191             :             // Set the full load outlet temperature on the water heater source inlet node (init has already been called).
    9192      161015 :             this->SourceInletTemp = state.dataLoopNodes->Node(HPWaterOutletNode).Temp;
    9193             : 
    9194             :             // Disable the tank's internal heating element to find PLR of the HPWH using floating temperatures.
    9195      161015 :             this->MaxCapacity = 0.0;
    9196      161015 :             this->MinCapacity = 0.0;
    9197      161015 :             this->SourceMassFlowRate = 0.0; // disables heat pump for mixed tanks
    9198      161015 :             Real64 SourceEffectivenessBackup = this->SourceEffectiveness;
    9199      161015 :             this->SourceEffectiveness = 0.0; // disables heat pump for stratified tanks
    9200      161015 :             this->CalcWaterThermalTank(state);
    9201      161015 :             this->SourceEffectiveness = SourceEffectivenessBackup;
    9202      161015 :             Real64 NewTankTemp = this->GetHPWHSensedTankTemp(state);
    9203             : 
    9204             :             // Reset the tank's internal heating element capacity.
    9205      161015 :             this->MaxCapacity = HeatPump.BackupElementCapacity;
    9206      161015 :             this->MinCapacity = HeatPump.BackupElementCapacity;
    9207             : 
    9208             :             // Check to see if the tank meets set point if no heating happens.
    9209      161015 :             if (NewTankTemp > HPSetPointTemp) {
    9210             : 
    9211             :                 // HPWH is now in floating mode
    9212           0 :                 HeatPump.Mode = TankOperatingMode::Floating;
    9213             : 
    9214             :             } else {
    9215             : 
    9216             :                 // HPWH remains in heating mode
    9217      161015 :                 state.dataWaterThermalTanks->hpPartLoadRatio = 1.0;
    9218             :             }
    9219             : 
    9220             :             // Reset the water heater's mode (call above may have changed modes)
    9221      161015 :             this->Mode = HeatPump.SaveWHMode;
    9222             :         }
    9223             :     } else {
    9224      328933 :         assert(HeatPump.Mode == TankOperatingMode::Floating);
    9225             :         // HPWH was floating last iteration and will continue to float until the cut-in temperature is reached
    9226             : 
    9227             :         // set the condenser inlet node temperature and full mass flow rate prior to calling the HPWH DX coil
    9228      328933 :         if (HeatPump.HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed) {
    9229      165712 :             state.dataLoopNodes->Node(HPWaterInletNode).Temp = savedTankTemp;
    9230      165712 :             state.dataLoopNodes->Node(HPWaterOutletNode).Temp = savedTankTemp;
    9231      163221 :         } else if (HeatPump.HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
    9232      163221 :             state.dataLoopNodes->Node(HPWaterInletNode).Temp = this->SourceOutletTemp;
    9233      163221 :             state.dataLoopNodes->Node(HPWaterOutletNode).Temp = this->SourceInletTemp;
    9234             :         }
    9235      328933 :         state.dataLoopNodes->Node(HPWaterInletNode).MassFlowRate = 0.0;
    9236      328933 :         state.dataLoopNodes->Node(HPWaterOutletNode).MassFlowRate = 0.0;
    9237             : 
    9238             :         // Check tank temperature by setting source inlet mass flow rate to zero.
    9239      328933 :         state.dataWaterThermalTanks->hpPartLoadRatio = 0.0;
    9240             : 
    9241             :         // Set the full load outlet temperature on the water heater source inlet node (init has already been called).
    9242      328933 :         this->SourceInletTemp = state.dataLoopNodes->Node(HPWaterOutletNode).Temp;
    9243             : 
    9244             :         // Disable the tank's internal heating element to find PLR of the HPWH using floating temperatures.
    9245      328933 :         this->MaxCapacity = 0.0;
    9246      328933 :         this->MinCapacity = 0.0;
    9247      328933 :         this->SourceMassFlowRate = 0.0; // disables heat pump for mixed tanks
    9248      328933 :         Real64 SourceEffectivenessBackup = this->SourceEffectiveness;
    9249      328933 :         this->SourceEffectiveness = 0.0; // disables heat pump for stratified tanks
    9250      328933 :         this->CalcWaterThermalTank(state);
    9251      328933 :         this->SourceEffectiveness = SourceEffectivenessBackup;
    9252      328933 :         Real64 NewTankTemp = this->GetHPWHSensedTankTemp(state);
    9253             : 
    9254             :         // Reset the tank's internal heating element capacity.
    9255      328933 :         this->MaxCapacity = HeatPump.BackupElementCapacity;
    9256      328933 :         this->MinCapacity = HeatPump.BackupElementCapacity;
    9257             : 
    9258             :         // Check to see if the tank drifts below set point if no heating happens.
    9259      328933 :         if (NewTankTemp <= (HPSetPointTemp - DeadBandTempDiff)) {
    9260             : 
    9261             :             // HPWH is now in heating mode
    9262       72148 :             HeatPump.Mode = TankOperatingMode::Heating;
    9263             : 
    9264             :             // Reset the water heater's mode (call above may have changed modes)
    9265       72148 :             this->Mode = HeatPump.SaveWHMode;
    9266             : 
    9267       72148 :             state.dataWaterThermalTanks->hpPartLoadRatio = 1.0;
    9268             :         }
    9269             :     }
    9270             : 
    9271      490004 :     if (HeatPump.bIsIHP) // mark the water heating call, if existing
    9272             :     {
    9273        5070 :         if (state.dataIntegratedHP->IntegratedHeatPumps(HeatPump.DXCoilNum).CheckWHCall) {
    9274        2534 :             if (HeatPump.Mode == TankOperatingMode::Heating)
    9275        1258 :                 state.dataIntegratedHP->IntegratedHeatPumps(HeatPump.DXCoilNum).IsWHCallAvail = true;
    9276             :             else
    9277        1276 :                 state.dataIntegratedHP->IntegratedHeatPumps(HeatPump.DXCoilNum).IsWHCallAvail = false;
    9278             :         }
    9279             :     }
    9280             : 
    9281             :     // If the HPWH was in heating mode during the last DataGlobals::TimeStep or if it was determined that
    9282             :     // heating would be needed during this DataGlobals::TimeStep to maintain setpoint, do the heating calculation.
    9283      490004 :     int SpeedNum = 0;
    9284      490004 :     Real64 SpeedRatio = 0.0;
    9285      490004 :     if (HeatPump.Mode == TankOperatingMode::Heating) {
    9286             : 
    9287             :         // set up air flow on DX coil inlet node
    9288      233199 :         state.dataLoopNodes->Node(DXCoilAirInletNode).MassFlowRate =
    9289      233199 :             state.dataWaterThermalTanks->mdotAir * state.dataWaterThermalTanks->hpPartLoadRatio;
    9290             : 
    9291             :         // set the condenser inlet node mass flow rate prior to calling the DXCoils::CalcHPWHDXCoil
    9292      233199 :         state.dataLoopNodes->Node(HPWaterInletNode).MassFlowRate = MdotWater * state.dataWaterThermalTanks->hpPartLoadRatio;
    9293      233199 :         this->SourceMassFlowRate = MdotWater * state.dataWaterThermalTanks->hpPartLoadRatio;
    9294             : 
    9295             :         // Do the coil and tank calculations at full PLR to see if it overshoots setpoint.
    9296      233199 :         bool bIterSpeed = false;
    9297      233199 :         if (MaxSpeedNum > 0) { // lowest speed of VS HPWH coil
    9298       20583 :             SpeedRatio = 1.0;
    9299       20583 :             state.dataWaterThermalTanks->hpPartLoadRatio = 1.0;
    9300       20583 :             bIterSpeed = true; // prepare for iterating between speed levels
    9301       20583 :             SpeedNum = 1;
    9302       20583 :             this->SetVSHPWHFlowRates(state, HeatPump, SpeedNum, SpeedRatio, RhoWater, MdotWater, FirstHVACIteration);
    9303             : 
    9304       20583 :             if (HeatPump.bIsIHP) {
    9305        2517 :                 bIterSpeed = false; // don't iterate speed unless match conditions below
    9306        2517 :                 IHPMode = IntegratedHeatPump::GetCurWorkMode(state, HeatPump.DXCoilNum);
    9307             : 
    9308        2517 :                 if (state.dataIntegratedHP->IntegratedHeatPumps(HeatPump.DXCoilNum).CheckWHCall) {
    9309             :                     int VSCoilNum;
    9310        1258 :                     if (IntegratedHeatPump::IHPOperationMode::DedicatedWaterHtg == IHPMode) {
    9311          48 :                         VSCoilNum = state.dataIntegratedHP->IntegratedHeatPumps(HeatPump.DXCoilNum).DWHCoilIndex;
    9312          48 :                         state.dataIntegratedHP->IntegratedHeatPumps(HeatPump.DXCoilNum).CurMode =
    9313             :                             IntegratedHeatPump::IHPOperationMode::DedicatedWaterHtg;
    9314             :                     } else {
    9315        1210 :                         VSCoilNum = state.dataIntegratedHP->IntegratedHeatPumps(HeatPump.DXCoilNum).SCWHCoilIndex;
    9316        1210 :                         state.dataIntegratedHP->IntegratedHeatPumps(HeatPump.DXCoilNum).CurMode = IntegratedHeatPump::IHPOperationMode::SCWHMatchWH;
    9317             :                     }
    9318             : 
    9319        1258 :                     this->SetVSHPWHFlowRates(state, HeatPump, SpeedNum, SpeedRatio, RhoWater, MdotWater, FirstHVACIteration);
    9320             : 
    9321        3774 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
    9322             :                                                               "",
    9323             :                                                               VSCoilNum,
    9324             :                                                               DataHVACGlobals::CycFanCycCoil,
    9325             :                                                               EMP1,
    9326             :                                                               EMP2,
    9327             :                                                               EMP3,
    9328             :                                                               DataHVACGlobals::CompressorOperation::On,
    9329        1258 :                                                               state.dataWaterThermalTanks->hpPartLoadRatio,
    9330             :                                                               SpeedNum,
    9331             :                                                               SpeedRatio,
    9332             :                                                               0.0,
    9333             :                                                               0.0,
    9334        1258 :                                                               1.0);
    9335             : 
    9336        1258 :                     state.dataIntegratedHP->IntegratedHeatPumps(HeatPump.DXCoilNum).CurMode = IHPMode;
    9337        1258 :                     this->SetVSHPWHFlowRates(state, HeatPump, SpeedNum, SpeedRatio, RhoWater, MdotWater, FirstHVACIteration);
    9338             :                 } else {
    9339        1259 :                     SpeedNum = IntegratedHeatPump::GetLowSpeedNumIHP(state, HeatPump.DXCoilNum);
    9340             : 
    9341        1259 :                     this->SetVSHPWHFlowRates(state, HeatPump, SpeedNum, SpeedRatio, RhoWater, MdotWater, FirstHVACIteration);
    9342        2518 :                     IntegratedHeatPump::SimIHP(state,
    9343             :                                                HeatPump.DXCoilName,
    9344             :                                                HeatPump.DXCoilNum,
    9345             :                                                DataHVACGlobals::CycFanCycCoil,
    9346             :                                                EMP1,
    9347             :                                                EMP2,
    9348             :                                                EMP3,
    9349             :                                                DataHVACGlobals::CompressorOperation::On,
    9350        1259 :                                                state.dataWaterThermalTanks->hpPartLoadRatio,
    9351             :                                                SpeedNum,
    9352             :                                                SpeedRatio,
    9353             :                                                0.0,
    9354             :                                                0.0,
    9355             :                                                true,
    9356             :                                                false,
    9357             :                                                1.0);
    9358             : 
    9359        1259 :                     if ((IntegratedHeatPump::IHPOperationMode::SCWHMatchWH == IHPMode) ||
    9360             :                         (IntegratedHeatPump::IHPOperationMode::DedicatedWaterHtg == IHPMode)) {
    9361         112 :                         bIterSpeed = true;
    9362             :                     } else {
    9363        1147 :                         this->SourceMassFlowRate = state.dataIntegratedHP->IntegratedHeatPumps(HeatPump.DXCoilNum).TankSourceWaterMassFlowRate;
    9364        1147 :                         MdotWater = this->SourceMassFlowRate;
    9365             :                     }
    9366             : 
    9367        1259 :                     if (IntegratedHeatPump::IHPOperationMode::SHDWHElecHeatOff == IHPMode) // turn off heater element
    9368             :                     {
    9369           0 :                         this->MaxCapacity = 0.0;
    9370           0 :                         this->MinCapacity = 0.0;
    9371             :                     }
    9372             :                 }
    9373             :             } else {
    9374       36132 :                 VariableSpeedCoils::SimVariableSpeedCoils(state,
    9375             :                                                           HeatPump.DXCoilName,
    9376             :                                                           HeatPump.DXCoilNum,
    9377             :                                                           DataHVACGlobals::CycFanCycCoil,
    9378             :                                                           EMP1,
    9379             :                                                           EMP2,
    9380             :                                                           EMP3,
    9381             :                                                           DataHVACGlobals::CompressorOperation::On,
    9382       18066 :                                                           state.dataWaterThermalTanks->hpPartLoadRatio,
    9383             :                                                           SpeedNum,
    9384             :                                                           SpeedRatio,
    9385             :                                                           0.0,
    9386             :                                                           0.0,
    9387             :                                                           1.0);
    9388             :             }
    9389             : 
    9390       20583 :             this->CalcWaterThermalTank(state);
    9391             :         } else {
    9392      212616 :             this->ConvergeSingleSpeedHPWHCoilAndTank(state, state.dataWaterThermalTanks->hpPartLoadRatio);
    9393             :         }
    9394             : 
    9395      233199 :         Real64 NewTankTemp = this->GetHPWHSensedTankTemp(state);
    9396      233199 :         Real64 LowSpeedTankTemp = NewTankTemp;
    9397      233199 :         Real64 HPWHCondInletNodeLast = state.dataLoopNodes->Node(HPWaterInletNode).Temp;
    9398             : 
    9399      233199 :         if (NewTankTemp > HPSetPointTemp) {
    9400       14811 :             HeatPump.Mode = TankOperatingMode::Floating;
    9401       14811 :             TankOperatingMode tmpMode = HeatPump.SaveWHMode;
    9402       66889 :             auto f = [&state, this, HPSetPointTemp, tmpMode, MdotWater](Real64 const HPPartLoadRatio) {
    9403             :                 return this->PLRResidualHPWH(state, HPPartLoadRatio, HPSetPointTemp, tmpMode, MdotWater);
    9404       81700 :             };
    9405       14811 :             Real64 zeroResidual = 1.0;
    9406       14811 :             if (MaxSpeedNum > 0) {
    9407             :                 // square the solving, and avoid warning
    9408             :                 // due to very small capacity at lowest speed of VSHPWH coil
    9409        1039 :                 if (bIterSpeed)
    9410        1023 :                     zeroResidual = this->PLRResidualHPWH(state, 0.0, HPSetPointTemp, tmpMode, MdotWater);
    9411             :                 else
    9412          16 :                     zeroResidual = -1.0;
    9413             :             }
    9414             : 
    9415       14811 :             if (zeroResidual > 0.0) { // then iteration
    9416             :                 int SolFla;
    9417       14412 :                 General::SolveRoot(state, Acc, MaxIte, SolFla, state.dataWaterThermalTanks->hpPartLoadRatio, f, 0.0, 1.0);
    9418       14412 :                 if (SolFla == -1) {
    9419           0 :                     std::string IterNum;
    9420           0 :                     IterNum = fmt::to_string(MaxIte);
    9421           0 :                     if (!state.dataGlobal->WarmupFlag) {
    9422           0 :                         ++HeatPump.IterLimitExceededNum2;
    9423           0 :                         if (HeatPump.IterLimitExceededNum2 == 1) {
    9424           0 :                             ShowWarningError(state, HeatPump.Type + " \"" + HeatPump.Name + "\"");
    9425           0 :                             ShowContinueError(state,
    9426           0 :                                               format("Iteration limit exceeded calculating heat pump water heater compressor part-load ratio, "
    9427             :                                                      "maximum iterations = {}. Part-load ratio returned = {:.3R}",
    9428             :                                                      IterNum,
    9429           0 :                                                      state.dataWaterThermalTanks->hpPartLoadRatio));
    9430           0 :                             ShowContinueErrorTimeStamp(state, "This error occurred in float mode.");
    9431             :                         } else {
    9432           0 :                             ShowRecurringWarningErrorAtEnd(
    9433             :                                 state,
    9434           0 :                                 HeatPump.Type + " \"" + HeatPump.Name +
    9435             :                                     "\":  Iteration limit exceeded in float mode warning continues. Part-load ratio statistics follow.",
    9436             :                                 HeatPump.IterLimitErrIndex2,
    9437           0 :                                 state.dataWaterThermalTanks->hpPartLoadRatio,
    9438           0 :                                 state.dataWaterThermalTanks->hpPartLoadRatio);
    9439             :                         }
    9440             :                     }
    9441       14412 :                 } else if (SolFla == -2) {
    9442         304 :                     state.dataWaterThermalTanks->hpPartLoadRatio =
    9443         304 :                         max(0.0, min(1.0, (HPSetPointTemp - savedTankTemp) / (NewTankTemp - savedTankTemp)));
    9444         304 :                     if (!state.dataGlobal->WarmupFlag) {
    9445         152 :                         ++HeatPump.RegulaFalsiFailedNum2;
    9446         152 :                         if (HeatPump.RegulaFalsiFailedNum2 == 1) {
    9447           1 :                             ShowWarningError(state, HeatPump.Type + " \"" + HeatPump.Name + "\"");
    9448           3 :                             ShowContinueError(state,
    9449           3 :                                               format("Heat pump water heater compressor part-load ratio calculation failed: PLR limits of 0 to 1 "
    9450             :                                                      "exceeded. Part-load ratio used = {:.3R}",
    9451           2 :                                                      state.dataWaterThermalTanks->hpPartLoadRatio));
    9452           1 :                             ShowContinueError(state, "Please send this information to the EnergyPlus support group.");
    9453           1 :                             ShowContinueErrorTimeStamp(state, "This error occurred in float mode.");
    9454             :                         } else {
    9455         755 :                             ShowRecurringWarningErrorAtEnd(
    9456             :                                 state,
    9457         302 :                                 HeatPump.Type + " \"" + HeatPump.Name +
    9458             :                                     "\": Part-load ratio calculation failed in float mode warning continues. Part-load ratio statistics follow.",
    9459             :                                 HeatPump.RegulaFalsiFailedIndex2,
    9460         151 :                                 state.dataWaterThermalTanks->hpPartLoadRatio,
    9461         151 :                                 state.dataWaterThermalTanks->hpPartLoadRatio);
    9462             :                         }
    9463             :                     }
    9464             :                 }
    9465             :             } else {
    9466         399 :                 state.dataWaterThermalTanks->hpPartLoadRatio = 0.0;
    9467             :             }
    9468             : 
    9469             :             // Re-calculate the HPWH Coil to get the correct heat transfer rate.
    9470       14811 :             state.dataLoopNodes->Node(HPWaterInletNode).Temp = this->SourceOutletTemp;
    9471       14811 :             if (MaxSpeedNum > 0) {
    9472        1039 :                 SpeedRatio = 1.0;
    9473        1039 :                 SpeedNum = 1;
    9474             : 
    9475        1039 :                 this->SetVSHPWHFlowRates(state, HeatPump, SpeedNum, SpeedRatio, RhoWater, MdotWater, FirstHVACIteration);
    9476             : 
    9477        1039 :                 if (HeatPump.bIsIHP) {
    9478          32 :                     if (bIterSpeed) {
    9479          32 :                         IntegratedHeatPump::SimIHP(state,
    9480             :                                                    HeatPump.DXCoilName,
    9481             :                                                    HeatPump.DXCoilNum,
    9482             :                                                    DataHVACGlobals::CycFanCycCoil,
    9483             :                                                    EMP1,
    9484             :                                                    EMP2,
    9485             :                                                    EMP3,
    9486             :                                                    DataHVACGlobals::CompressorOperation::On,
    9487          16 :                                                    state.dataWaterThermalTanks->hpPartLoadRatio,
    9488             :                                                    SpeedNum,
    9489             :                                                    SpeedRatio,
    9490             :                                                    0.0,
    9491             :                                                    0.0,
    9492             :                                                    true,
    9493             :                                                    false,
    9494             :                                                    1.0);
    9495             :                     }
    9496             :                 } else {
    9497        2014 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
    9498             :                                                               HeatPump.DXCoilName,
    9499             :                                                               HeatPump.DXCoilNum,
    9500             :                                                               DataHVACGlobals::CycFanCycCoil,
    9501             :                                                               EMP1,
    9502             :                                                               EMP2,
    9503             :                                                               EMP3,
    9504             :                                                               DataHVACGlobals::CompressorOperation::On,
    9505        1007 :                                                               state.dataWaterThermalTanks->hpPartLoadRatio,
    9506             :                                                               SpeedNum,
    9507             :                                                               SpeedRatio,
    9508             :                                                               0.0,
    9509             :                                                               0.0,
    9510             :                                                               1.0);
    9511             :                 }
    9512             : 
    9513             :             } else {
    9514       13772 :                 DXCoils::CalcHPWHDXCoil(state, HeatPump.DXCoilNum, state.dataWaterThermalTanks->hpPartLoadRatio);
    9515             :             }
    9516      218388 :         } else if (bIterSpeed) {
    9517       43889 :             for (int loopIter = 1; loopIter <= 4; ++loopIter) {
    9518       43889 :                 HeatPump.Mode = TankOperatingMode::Heating; // modHeatMode is important for system convergence
    9519       43889 :                 state.dataWaterThermalTanks->hpPartLoadRatio = 1.0;
    9520       43889 :                 SpeedRatio = 1.0;
    9521       43889 :                 int LowSpeedNum = 2;
    9522       43889 :                 if (HeatPump.bIsIHP) {
    9523         272 :                     LowSpeedNum = IntegratedHeatPump::GetLowSpeedNumIHP(state, HeatPump.DXCoilNum);
    9524         272 :                     MaxSpeedNum = IntegratedHeatPump::GetMaxSpeedNumIHP(state, HeatPump.DXCoilNum);
    9525             :                 }
    9526             : 
    9527      356538 :                 for (int i = LowSpeedNum; i <= MaxSpeedNum; ++i) {
    9528      324425 :                     SpeedNum = i;
    9529      324425 :                     this->SetVSHPWHFlowRates(state, HeatPump, SpeedNum, SpeedRatio, RhoWater, MdotWater, FirstHVACIteration);
    9530      324425 :                     if (HeatPump.bIsIHP) {
    9531        5248 :                         IntegratedHeatPump::SimIHP(state,
    9532             :                                                    HeatPump.DXCoilName,
    9533             :                                                    HeatPump.DXCoilNum,
    9534             :                                                    DataHVACGlobals::CycFanCycCoil,
    9535             :                                                    EMP1,
    9536             :                                                    EMP2,
    9537             :                                                    EMP3,
    9538             :                                                    DataHVACGlobals::CompressorOperation::On,
    9539        2624 :                                                    state.dataWaterThermalTanks->hpPartLoadRatio,
    9540             :                                                    SpeedNum,
    9541             :                                                    SpeedRatio,
    9542             :                                                    0.0,
    9543             :                                                    0.0,
    9544             :                                                    true,
    9545             :                                                    false,
    9546             :                                                    1.0);
    9547             :                     } else {
    9548      643602 :                         VariableSpeedCoils::SimVariableSpeedCoils(state,
    9549             :                                                                   HeatPump.DXCoilName,
    9550             :                                                                   HeatPump.DXCoilNum,
    9551             :                                                                   DataHVACGlobals::CycFanCycCoil,
    9552             :                                                                   EMP1,
    9553             :                                                                   EMP2,
    9554             :                                                                   EMP3,
    9555             :                                                                   DataHVACGlobals::CompressorOperation::On,
    9556      321801 :                                                                   state.dataWaterThermalTanks->hpPartLoadRatio,
    9557             :                                                                   SpeedNum,
    9558             :                                                                   SpeedRatio,
    9559             :                                                                   0.0,
    9560             :                                                                   0.0,
    9561             :                                                                   1.0);
    9562             :                     }
    9563             : 
    9564             :                     // HPWH condenser water temperature difference
    9565      324425 :                     Real64 CondenserDeltaT = state.dataLoopNodes->Node(HPWaterOutletNode).Temp - state.dataLoopNodes->Node(HPWaterInletNode).Temp;
    9566             : 
    9567             :                     //           move the full load outlet temperature rate to the water heater structure variables
    9568             :                     //           (water heaters source inlet node temperature/mdot are set in Init, set it here after DXCoils::CalcHPWHDXCoil has
    9569             :                     //           been called)
    9570      324425 :                     this->SourceInletTemp = state.dataLoopNodes->Node(HPWaterInletNode).Temp + CondenserDeltaT;
    9571             :                     //           this CALL does not update node temps, must use WaterThermalTank variables
    9572             :                     // select tank type
    9573      324425 :                     if (HeatPump.HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed) {
    9574      317463 :                         this->CalcWaterThermalTankMixed(state);
    9575      317463 :                         NewTankTemp = this->TankTemp;
    9576        6962 :                     } else if (HeatPump.HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
    9577        6962 :                         this->CalcWaterThermalTankStratified(state);
    9578        6962 :                         NewTankTemp = this->FindStratifiedTankSensedTemp(state);
    9579             :                     }
    9580             : 
    9581      324425 :                     if (NewTankTemp > HPSetPointTemp) {
    9582       11776 :                         SpeedNum = i;
    9583       11776 :                         break;
    9584             :                     } else {
    9585      312649 :                         LowSpeedTankTemp = NewTankTemp;
    9586             :                     }
    9587             :                 }
    9588             : 
    9589       43889 :                 if (NewTankTemp > HPSetPointTemp) {
    9590             :                     int SolFla;
    9591       23552 :                     std::string IterNum;
    9592             :                     auto f = [&state, this, SpeedNum, HPWaterInletNode, HPWaterOutletNode, RhoWater, HPSetPointTemp, &HeatPump, FirstHVACIteration](
    9593      304120 :                                  Real64 const SpeedRatio) {
    9594      228090 :                         return this->PLRResidualIterSpeed(state,
    9595             :                                                           SpeedRatio,
    9596             :                                                           this->HeatPumpNum,
    9597             :                                                           SpeedNum,
    9598             :                                                           HPWaterInletNode,
    9599             :                                                           HPWaterOutletNode,
    9600             :                                                           RhoWater,
    9601             :                                                           HPSetPointTemp,
    9602             :                                                           HeatPump.SaveWHMode,
    9603             :                                                           FirstHVACIteration);
    9604       87806 :                     };
    9605       11776 :                     General::SolveRoot(state, Acc, MaxIte, SolFla, SpeedRatio, f, 1.0e-10, 1.0);
    9606             : 
    9607       11776 :                     if (SolFla == -1) {
    9608           0 :                         IterNum = fmt::to_string(MaxIte);
    9609           0 :                         if (!state.dataGlobal->WarmupFlag) {
    9610           0 :                             ++HeatPump.IterLimitExceededNum1;
    9611           0 :                             if (HeatPump.IterLimitExceededNum1 == 1) {
    9612           0 :                                 ShowWarningError(state, HeatPump.Type + " \"" + HeatPump.Name + "\"");
    9613           0 :                                 ShowContinueError(state,
    9614           0 :                                                   format("Iteration limit exceeded calculating heat pump water heater speed speed ratio ratio, "
    9615             :                                                          "maximum iterations = {}. speed ratio returned = {:.3R}",
    9616             :                                                          IterNum,
    9617           0 :                                                          SpeedRatio));
    9618           0 :                                 ShowContinueErrorTimeStamp(state, "This error occurred in heating mode.");
    9619             :                             } else {
    9620           0 :                                 ShowRecurringWarningErrorAtEnd(
    9621             :                                     state,
    9622           0 :                                     HeatPump.Type + " \"" + HeatPump.Name +
    9623             :                                         "\":  Iteration limit exceeded in heating mode warning continues. speed ratio statistics follow.",
    9624             :                                     HeatPump.IterLimitErrIndex1,
    9625             :                                     SpeedRatio,
    9626             :                                     SpeedRatio);
    9627             :                             }
    9628             :                         }
    9629       11776 :                     } else if (SolFla == -2) {
    9630           0 :                         SpeedRatio = max(0.0, min(1.0, (HPSetPointTemp - LowSpeedTankTemp) / (NewTankTemp - LowSpeedTankTemp)));
    9631           0 :                         if (!state.dataGlobal->WarmupFlag) {
    9632           0 :                             ++HeatPump.RegulaFalsiFailedNum1;
    9633           0 :                             if (HeatPump.RegulaFalsiFailedNum1 == 1) {
    9634           0 :                                 ShowWarningError(state, HeatPump.Type + " \"" + HeatPump.Name + "\"");
    9635           0 :                                 ShowContinueError(state,
    9636           0 :                                                   format("Heat pump water heater speed ratio calculation failed: speed ratio limits of 0 to 1 "
    9637             :                                                          "exceeded. speed ratio used = {:.3R}",
    9638           0 :                                                          SpeedRatio));
    9639           0 :                                 ShowContinueError(state, "Please send this information to the EnergyPlus support group.");
    9640           0 :                                 ShowContinueErrorTimeStamp(state, "This error occurred in heating mode.");
    9641             :                             } else {
    9642           0 :                                 ShowRecurringWarningErrorAtEnd(
    9643             :                                     state,
    9644           0 :                                     HeatPump.Type + " \"" + HeatPump.Name +
    9645             :                                         "\":  Speed ratio calculation failed in heating mode warning continues. Speed ratio statistics follow.",
    9646             :                                     HeatPump.RegulaFalsiFailedIndex1,
    9647             :                                     SpeedRatio,
    9648             :                                     SpeedRatio);
    9649             :                             }
    9650             :                         }
    9651             :                     }
    9652             :                 } else {
    9653       32113 :                     SpeedNum = MaxSpeedNum;
    9654       32113 :                     SpeedRatio = 1.0;
    9655             :                 }
    9656             : 
    9657       43889 :                 state.dataWaterThermalTanks->hpPartLoadRatio = 1.0;
    9658       43889 :                 this->SetVSHPWHFlowRates(state, HeatPump, SpeedNum, SpeedRatio, RhoWater, MdotWater, FirstHVACIteration);
    9659             : 
    9660       43889 :                 if (HeatPump.bIsIHP) {
    9661         544 :                     IntegratedHeatPump::SimIHP(state,
    9662             :                                                HeatPump.DXCoilName,
    9663             :                                                HeatPump.DXCoilNum,
    9664             :                                                DataHVACGlobals::CycFanCycCoil,
    9665             :                                                EMP1,
    9666             :                                                EMP2,
    9667             :                                                EMP3,
    9668             :                                                DataHVACGlobals::CompressorOperation::On,
    9669         272 :                                                state.dataWaterThermalTanks->hpPartLoadRatio,
    9670             :                                                SpeedNum,
    9671             :                                                SpeedRatio,
    9672             :                                                0.0,
    9673             :                                                0.0,
    9674             :                                                true,
    9675             :                                                false,
    9676             :                                                1.0);
    9677             :                 } else {
    9678       87234 :                     VariableSpeedCoils::SimVariableSpeedCoils(state,
    9679             :                                                               HeatPump.DXCoilName,
    9680             :                                                               HeatPump.DXCoilNum,
    9681             :                                                               DataHVACGlobals::CycFanCycCoil,
    9682             :                                                               EMP1,
    9683             :                                                               EMP2,
    9684             :                                                               EMP3,
    9685             :                                                               DataHVACGlobals::CompressorOperation::On,
    9686       43617 :                                                               state.dataWaterThermalTanks->hpPartLoadRatio,
    9687             :                                                               SpeedNum,
    9688             :                                                               SpeedRatio,
    9689             :                                                               0.0,
    9690             :                                                               0.0,
    9691             :                                                               1.0);
    9692             :                 }
    9693             : 
    9694             :                 // HPWH condenser water temperature difference
    9695       43889 :                 Real64 CondenserDeltaT = state.dataLoopNodes->Node(HPWaterOutletNode).Temp - state.dataLoopNodes->Node(HPWaterInletNode).Temp;
    9696             : 
    9697             :                 //           move the full load outlet temperature rate to the water heater structure variables
    9698             :                 //           (water heaters source inlet node temperature/mdot are set in Init, set it here after DXCoils::CalcHPWHDXCoil has been
    9699             :                 //           called)
    9700       43889 :                 this->SourceInletTemp = state.dataLoopNodes->Node(HPWaterInletNode).Temp + CondenserDeltaT;
    9701             :                 //           this CALL does not update node temps, must use WaterThermalTank variables
    9702             :                 // select tank type
    9703       43889 :                 if (HeatPump.HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed) {
    9704       40408 :                     this->CalcWaterThermalTankMixed(state);
    9705       40408 :                     NewTankTemp = this->TankTemp;
    9706        3481 :                 } else if (HeatPump.HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
    9707        3481 :                     this->CalcWaterThermalTankStratified(state);
    9708        3481 :                     NewTankTemp = this->FindStratifiedTankSensedTemp(state);
    9709             :                 }
    9710             :                 // update inlet temp
    9711       43889 :                 state.dataLoopNodes->Node(HPWaterInletNode).Temp = this->SourceOutletTemp;
    9712       43889 :                 if (std::abs(state.dataLoopNodes->Node(HPWaterInletNode).Temp - HPWHCondInletNodeLast) < DataHVACGlobals::SmallTempDiff) break;
    9713       26734 :                 HPWHCondInletNodeLast = state.dataLoopNodes->Node(HPWaterInletNode).Temp;
    9714             :             }
    9715             : 
    9716             :         } else {
    9717             :             // Set the PLR to 1 if we're not going to reach setpoint during this DataGlobals::TimeStep.
    9718      201233 :             state.dataWaterThermalTanks->hpPartLoadRatio = 1.0;
    9719             :         }
    9720             :     }
    9721             : 
    9722      490004 :     if (HeatPump.bIsIHP) {
    9723        5070 :         if (state.dataIntegratedHP->IntegratedHeatPumps(HeatPump.DXCoilNum).CheckWHCall) {
    9724        2534 :             IntegratedHeatPump::ClearCoils(state, HeatPump.DXCoilNum); // clear node info when checking the heating load
    9725             :         }
    9726             :     }
    9727             : 
    9728             :     // set air-side mass flow rate for final calculation
    9729      490004 :     if (InletAirMixerNode > 0) {
    9730       25611 :         state.dataLoopNodes->Node(InletAirMixerNode).MassFlowRate =
    9731       25611 :             state.dataWaterThermalTanks->mdotAir * state.dataWaterThermalTanks->hpPartLoadRatio;
    9732       51222 :         state.dataLoopNodes->Node(HPAirInletNode).MassFlowRate = state.dataWaterThermalTanks->mdotAir * state.dataWaterThermalTanks->hpPartLoadRatio *
    9733       25611 :                                                                  (1.0 - state.dataWaterThermalTanks->mixerInletAirSchedule);
    9734       25611 :         state.dataLoopNodes->Node(OutdoorAirNode).MassFlowRate =
    9735       25611 :             state.dataWaterThermalTanks->mdotAir * state.dataWaterThermalTanks->hpPartLoadRatio * state.dataWaterThermalTanks->mixerInletAirSchedule;
    9736             :         //   IF HPWH is off, pass zone node conditions through HPWH air-side
    9737       25611 :         if (state.dataWaterThermalTanks->hpPartLoadRatio == 0)
    9738       18404 :             state.dataLoopNodes->Node(InletAirMixerNode) = state.dataLoopNodes->Node(HPAirInletNode);
    9739             :     } else {
    9740      464393 :         if (OutdoorAirNode == 0) {
    9741      335997 :             state.dataLoopNodes->Node(HPAirInletNode).MassFlowRate =
    9742      335997 :                 state.dataWaterThermalTanks->mdotAir * state.dataWaterThermalTanks->hpPartLoadRatio;
    9743             :         } else {
    9744      128396 :             state.dataLoopNodes->Node(OutdoorAirNode).MassFlowRate =
    9745      128396 :                 state.dataWaterThermalTanks->mdotAir * state.dataWaterThermalTanks->hpPartLoadRatio;
    9746             :         }
    9747             :     }
    9748      490004 :     if (state.dataWaterThermalTanks->hpPartLoadRatio == 0) this->SourceInletTemp = this->SourceOutletTemp;
    9749             : 
    9750             :     // set water-side mass flow rate for final calculation
    9751      490004 :     state.dataLoopNodes->Node(HPWaterInletNode).MassFlowRate = MdotWater * state.dataWaterThermalTanks->hpPartLoadRatio;
    9752             : 
    9753      490004 :     if (MaxSpeedNum > 0) {
    9754             : 
    9755             :         // it is important to use mdotAir to reset the notes, otherwise, could fail to converge
    9756       42360 :         if (InletAirMixerNode > 0) {
    9757        5064 :             state.dataLoopNodes->Node(InletAirMixerNode).MassFlowRateMax = state.dataWaterThermalTanks->mdotAir;
    9758        5064 :             state.dataLoopNodes->Node(InletAirMixerNode).MassFlowRateMaxAvail = state.dataWaterThermalTanks->mdotAir;
    9759             :         } else {
    9760       37296 :             if (OutdoorAirNode == 0) {
    9761       10082 :                 state.dataLoopNodes->Node(HPAirInletNode).MassFlowRateMax = state.dataWaterThermalTanks->mdotAir;
    9762       10082 :                 state.dataLoopNodes->Node(HPAirInletNode).MassFlowRateMaxAvail = state.dataWaterThermalTanks->mdotAir;
    9763             :             } else {
    9764       27214 :                 state.dataLoopNodes->Node(OutdoorAirNode).MassFlowRateMax = state.dataWaterThermalTanks->mdotAir;
    9765       27214 :                 state.dataLoopNodes->Node(OutdoorAirNode).MassFlowRateMaxAvail = state.dataWaterThermalTanks->mdotAir;
    9766             :             }
    9767             :         }
    9768             : 
    9769             :         //   set the max mass flow rate for outdoor fans
    9770       42360 :         state.dataLoopNodes->Node(HeatPump.FanOutletNode).MassFlowRateMax = state.dataWaterThermalTanks->mdotAir;
    9771             : 
    9772       42360 :         if (HeatPump.bIsIHP) {
    9773             :             // pass node information using resulting PLR
    9774        5070 :             if (HeatPump.FanPlacement == DataHVACGlobals::BlowThru) {
    9775             :                 //   simulate fan and DX coil twice to pass PLF (OnOffFanPartLoadFraction) to fan
    9776        5070 :                 if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9777           0 :                     state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9778             :                 } else {
    9779        5070 :                     Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9780             :                 }
    9781       10140 :                 IntegratedHeatPump::SimIHP(state,
    9782             :                                            HeatPump.DXCoilName,
    9783             :                                            HeatPump.DXCoilNum,
    9784             :                                            DataHVACGlobals::CycFanCycCoil,
    9785             :                                            EMP1,
    9786             :                                            EMP2,
    9787             :                                            EMP3,
    9788             :                                            CompressorOp,
    9789        5070 :                                            state.dataWaterThermalTanks->hpPartLoadRatio,
    9790             :                                            SpeedNum,
    9791             :                                            SpeedRatio,
    9792             :                                            0.0,
    9793             :                                            0.0,
    9794             :                                            true,
    9795             :                                            false,
    9796             :                                            1.0);
    9797        5070 :                 if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9798           0 :                     state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9799             :                 } else {
    9800        5070 :                     Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9801             :                 }
    9802       10140 :                 IntegratedHeatPump::SimIHP(state,
    9803             :                                            HeatPump.DXCoilName,
    9804             :                                            HeatPump.DXCoilNum,
    9805             :                                            DataHVACGlobals::CycFanCycCoil,
    9806             :                                            EMP1,
    9807             :                                            EMP2,
    9808             :                                            EMP3,
    9809             :                                            CompressorOp,
    9810        5070 :                                            state.dataWaterThermalTanks->hpPartLoadRatio,
    9811             :                                            SpeedNum,
    9812             :                                            SpeedRatio,
    9813             :                                            0.0,
    9814             :                                            0.0,
    9815             :                                            true,
    9816             :                                            false,
    9817             :                                            1.0);
    9818             :             } else {
    9819             :                 //   simulate DX coil and fan twice to pass fan power (FanElecPower) to DX coil
    9820           0 :                 IntegratedHeatPump::SimIHP(state,
    9821             :                                            HeatPump.DXCoilName,
    9822             :                                            HeatPump.DXCoilNum,
    9823             :                                            DataHVACGlobals::CycFanCycCoil,
    9824             :                                            EMP1,
    9825             :                                            EMP2,
    9826             :                                            EMP3,
    9827             :                                            CompressorOp,
    9828           0 :                                            state.dataWaterThermalTanks->hpPartLoadRatio,
    9829             :                                            SpeedNum,
    9830             :                                            SpeedRatio,
    9831             :                                            0.0,
    9832             :                                            0.0,
    9833             :                                            true,
    9834             :                                            false,
    9835             :                                            1.0);
    9836           0 :                 if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9837           0 :                     state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9838             :                 } else {
    9839           0 :                     Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9840             :                 }
    9841           0 :                 IntegratedHeatPump::SimIHP(state,
    9842             :                                            HeatPump.DXCoilName,
    9843             :                                            HeatPump.DXCoilNum,
    9844             :                                            DataHVACGlobals::CycFanCycCoil,
    9845             :                                            EMP1,
    9846             :                                            EMP2,
    9847             :                                            EMP3,
    9848             :                                            CompressorOp,
    9849           0 :                                            state.dataWaterThermalTanks->hpPartLoadRatio,
    9850             :                                            SpeedNum,
    9851             :                                            SpeedRatio,
    9852             :                                            0.0,
    9853             :                                            0.0,
    9854             :                                            true,
    9855             :                                            false,
    9856             :                                            1.0);
    9857           0 :                 if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9858           0 :                     state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9859             :                 } else {
    9860           0 :                     Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9861             :                 }
    9862             :             }
    9863             :         } else {
    9864             :             // pass node information using resulting PLR
    9865       37290 :             if (HeatPump.FanPlacement == DataHVACGlobals::BlowThru) {
    9866             :                 //   simulate fan and DX coil twice to pass PLF (OnOffFanPartLoadFraction) to fan
    9867       27162 :                 if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9868       24812 :                     state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9869             :                 } else {
    9870        2350 :                     Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9871             :                 }
    9872       54324 :                 VariableSpeedCoils::SimVariableSpeedCoils(state,
    9873             :                                                           HeatPump.DXCoilName,
    9874             :                                                           HeatPump.DXCoilNum,
    9875             :                                                           DataHVACGlobals::CycFanCycCoil,
    9876             :                                                           EMP1,
    9877             :                                                           EMP2,
    9878             :                                                           EMP3,
    9879             :                                                           CompressorOp,
    9880       27162 :                                                           state.dataWaterThermalTanks->hpPartLoadRatio,
    9881             :                                                           SpeedNum,
    9882             :                                                           SpeedRatio,
    9883             :                                                           0.0,
    9884             :                                                           0.0,
    9885             :                                                           1.0);
    9886       27162 :                 if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9887       24812 :                     state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9888             :                 } else {
    9889        2350 :                     Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9890             :                 }
    9891       54324 :                 VariableSpeedCoils::SimVariableSpeedCoils(state,
    9892             :                                                           HeatPump.DXCoilName,
    9893             :                                                           HeatPump.DXCoilNum,
    9894             :                                                           DataHVACGlobals::CycFanCycCoil,
    9895             :                                                           EMP1,
    9896             :                                                           EMP2,
    9897             :                                                           EMP3,
    9898             :                                                           CompressorOp,
    9899       27162 :                                                           state.dataWaterThermalTanks->hpPartLoadRatio,
    9900             :                                                           SpeedNum,
    9901             :                                                           SpeedRatio,
    9902             :                                                           0.0,
    9903             :                                                           0.0,
    9904             :                                                           1.0);
    9905             :             } else {
    9906             :                 //   simulate DX coil and fan twice to pass fan power (FanElecPower) to DX coil
    9907       20256 :                 VariableSpeedCoils::SimVariableSpeedCoils(state,
    9908             :                                                           HeatPump.DXCoilName,
    9909             :                                                           HeatPump.DXCoilNum,
    9910             :                                                           DataHVACGlobals::CycFanCycCoil,
    9911             :                                                           EMP1,
    9912             :                                                           EMP2,
    9913             :                                                           EMP3,
    9914             :                                                           CompressorOp,
    9915       10128 :                                                           state.dataWaterThermalTanks->hpPartLoadRatio,
    9916             :                                                           SpeedNum,
    9917             :                                                           SpeedRatio,
    9918             :                                                           0.0,
    9919             :                                                           0.0,
    9920             :                                                           1.0);
    9921       10128 :                 if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9922       10128 :                     state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9923             :                 } else {
    9924           0 :                     Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9925             :                 }
    9926       20256 :                 VariableSpeedCoils::SimVariableSpeedCoils(state,
    9927             :                                                           HeatPump.DXCoilName,
    9928             :                                                           HeatPump.DXCoilNum,
    9929             :                                                           DataHVACGlobals::CycFanCycCoil,
    9930             :                                                           EMP1,
    9931             :                                                           EMP2,
    9932             :                                                           EMP3,
    9933             :                                                           CompressorOp,
    9934       10128 :                                                           state.dataWaterThermalTanks->hpPartLoadRatio,
    9935             :                                                           SpeedNum,
    9936             :                                                           SpeedRatio,
    9937             :                                                           0.0,
    9938             :                                                           0.0,
    9939             :                                                           1.0);
    9940       10128 :                 if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9941       10128 :                     state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9942             :                 } else {
    9943           0 :                     Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9944             :                 }
    9945             :             }
    9946             :         }
    9947             :     } else { // single speed
    9948             : 
    9949             :         // pass node information using resulting PLR
    9950      447644 :         if (HeatPump.FanPlacement == DataHVACGlobals::BlowThru) {
    9951             :             //   simulate fan and DX coil twice to pass PLF (OnOffFanPartLoadFraction) to fan
    9952       76246 :             if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9953       42190 :                 state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9954             :             } else {
    9955       34056 :                 Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9956             :             }
    9957      152492 :             DXCoils::SimDXCoil(state,
    9958             :                                HeatPump.DXCoilName,
    9959             :                                CompressorOp,
    9960             :                                FirstHVACIteration,
    9961             :                                HeatPump.DXCoilNum,
    9962             :                                DataHVACGlobals::CycFanCycCoil,
    9963       76246 :                                state.dataWaterThermalTanks->hpPartLoadRatio);
    9964       76246 :             if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9965       42190 :                 state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9966             :             } else {
    9967       34056 :                 Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9968             :             }
    9969      152492 :             DXCoils::SimDXCoil(state,
    9970             :                                HeatPump.DXCoilName,
    9971             :                                CompressorOp,
    9972             :                                FirstHVACIteration,
    9973             :                                HeatPump.DXCoilNum,
    9974             :                                DataHVACGlobals::CycFanCycCoil,
    9975       76246 :                                state.dataWaterThermalTanks->hpPartLoadRatio);
    9976             :         } else {
    9977             :             //   simulate DX coil and fan twice to pass fan power (FanElecPower) to DX coil
    9978      742796 :             DXCoils::SimDXCoil(state,
    9979             :                                HeatPump.DXCoilName,
    9980             :                                CompressorOp,
    9981             :                                FirstHVACIteration,
    9982             :                                HeatPump.DXCoilNum,
    9983             :                                DataHVACGlobals::CycFanCycCoil,
    9984      371398 :                                state.dataWaterThermalTanks->hpPartLoadRatio);
    9985      371398 :             if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9986      177640 :                 state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9987             :             } else {
    9988      193758 :                 Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
    9989             :             }
    9990      742796 :             DXCoils::SimDXCoil(state,
    9991             :                                HeatPump.DXCoilName,
    9992             :                                CompressorOp,
    9993             :                                FirstHVACIteration,
    9994             :                                HeatPump.DXCoilNum,
    9995             :                                DataHVACGlobals::CycFanCycCoil,
    9996      371398 :                                state.dataWaterThermalTanks->hpPartLoadRatio);
    9997      371398 :             if (HeatPump.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
    9998      177640 :                 state.dataHVACFan->fanObjs[HeatPump.FanNum]->simulate(state, _, _, _, _);
    9999             :             } else {
   10000      193758 :                 Fans::SimulateFanComponents(state, HeatPump.FanName, FirstHVACIteration, HeatPump.FanNum);
   10001             :             }
   10002             :         }
   10003             :     }
   10004             : 
   10005             :     // Call the tank one more time with the final PLR
   10006      490004 :     if (HeatPump.HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed) {
   10007      213438 :         this->CalcWaterThermalTankMixed(state);
   10008      276566 :     } else if (HeatPump.HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
   10009      276566 :         this->CalcWaterThermalTankStratified(state);
   10010             :     } else {
   10011           0 :         assert(0);
   10012             :     }
   10013             : 
   10014             :     // set HPWH outlet node equal to the outlet air splitter node conditions if outlet air splitter node exists
   10015      490004 :     if (OutletAirSplitterNode > 0) {
   10016       25611 :         state.dataLoopNodes->Node(HPAirOutletNode) = state.dataLoopNodes->Node(OutletAirSplitterNode);
   10017       25611 :         state.dataLoopNodes->Node(ExhaustAirNode) = state.dataLoopNodes->Node(OutletAirSplitterNode);
   10018             :     }
   10019             : 
   10020             :     // Check schedule to divert air-side cooling to outdoors.
   10021      490004 :     if (HeatPump.OutletAirSplitterSchPtr > 0) {
   10022       25611 :         Real64 OutletAirSplitterSch = ScheduleManager::GetCurrentScheduleValue(state, HeatPump.OutletAirSplitterSchPtr);
   10023       25611 :         state.dataLoopNodes->Node(HPAirOutletNode).MassFlowRate =
   10024       25611 :             state.dataWaterThermalTanks->mdotAir * state.dataWaterThermalTanks->hpPartLoadRatio * (1.0 - OutletAirSplitterSch);
   10025       25611 :         state.dataLoopNodes->Node(ExhaustAirNode).MassFlowRate =
   10026       25611 :             state.dataWaterThermalTanks->mdotAir * state.dataWaterThermalTanks->hpPartLoadRatio * OutletAirSplitterSch;
   10027             :     }
   10028             : 
   10029      490004 :     HeatPump.HeatingPLR = state.dataWaterThermalTanks->hpPartLoadRatio;
   10030      490004 :     HeatPump.OnCycParaFuelRate = HeatPump.OnCycParaLoad * state.dataWaterThermalTanks->hpPartLoadRatio;
   10031      490004 :     HeatPump.OnCycParaFuelEnergy = HeatPump.OnCycParaFuelRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
   10032      490004 :     HeatPump.OffCycParaFuelRate = HeatPump.OffCycParaLoad * (1.0 - state.dataWaterThermalTanks->hpPartLoadRatio);
   10033      490004 :     HeatPump.OffCycParaFuelEnergy = HeatPump.OffCycParaFuelRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
   10034      490004 :     if (HeatPump.HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed) {
   10035      213438 :         HeatPump.ControlTempAvg = this->TankTempAvg;
   10036      213438 :         HeatPump.ControlTempFinal = this->TankTemp;
   10037      276566 :     } else if (HeatPump.HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
   10038      276566 :         HeatPump.ControlTempAvg = this->FindStratifiedTankSensedTemp(state, true);
   10039      276566 :         HeatPump.ControlTempFinal = this->FindStratifiedTankSensedTemp(state);
   10040             :     } else {
   10041           0 :         assert(0);
   10042             :     }
   10043             : 
   10044      490004 :     switch (HeatPump.InletAirConfiguration) {
   10045             : 
   10046             :     //   no sensible capacity to zone for outdoor and scheduled HPWH
   10047      152534 :     case WTTAmbientTemp::OutsideAir:
   10048             :     case WTTAmbientTemp::Schedule: {
   10049      152534 :         HeatPump.HPWaterHeaterSensibleCapacity = 0.0;
   10050      152534 :         HeatPump.HPWaterHeaterLatentCapacity = 0.0;
   10051             : 
   10052             :         //   calculate sensible capacity to zone for inlet air configuration equals Zone Only or Zone And Outdoor Air configurations
   10053      152534 :         break;
   10054             :     }
   10055      337470 :     default:
   10056             : 
   10057      337470 :         Real64 CpAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(HPAirInletNode).HumRat);
   10058             : 
   10059             :         //     add parasitics to zone heat balance if parasitic heat load is to zone otherwise neglect parasitics
   10060      337470 :         if (HeatPump.ParasiticTempIndicator == WTTAmbientTemp::TempZone) {
   10061      204242 :             HeatPump.HPWaterHeaterSensibleCapacity =
   10062      408484 :                 (state.dataLoopNodes->Node(HPAirOutletNode).MassFlowRate * CpAir *
   10063      408484 :                  (state.dataLoopNodes->Node(HPAirOutletNode).Temp - state.dataLoopNodes->Node(HPAirInletNode).Temp)) +
   10064      408484 :                 HeatPump.OnCycParaFuelRate + HeatPump.OffCycParaFuelRate;
   10065             :         } else {
   10066      133228 :             HeatPump.HPWaterHeaterSensibleCapacity =
   10067      266456 :                 state.dataLoopNodes->Node(HPAirOutletNode).MassFlowRate * CpAir *
   10068      133228 :                 (state.dataLoopNodes->Node(HPAirOutletNode).Temp - state.dataLoopNodes->Node(HPAirInletNode).Temp);
   10069             :         }
   10070             : 
   10071      674940 :         HeatPump.HPWaterHeaterLatentCapacity = state.dataLoopNodes->Node(HPAirOutletNode).MassFlowRate *
   10072      337470 :                                                (state.dataLoopNodes->Node(HPAirOutletNode).HumRat - state.dataLoopNodes->Node(HPAirInletNode).HumRat);
   10073      337470 :         break;
   10074             :     }
   10075             : }
   10076             : 
   10077     1474867 : void WaterThermalTankData::CalcWaterThermalTank(EnergyPlusData &state)
   10078             : {
   10079     1474867 :     switch (this->WaterThermalTankType) {
   10080      560734 :     case DataPlant::PlantEquipmentType::WtrHeaterMixed:
   10081      560734 :         this->CalcWaterThermalTankMixed(state);
   10082      560734 :         break;
   10083      914133 :     case DataPlant::PlantEquipmentType::WtrHeaterStratified:
   10084      914133 :         this->CalcWaterThermalTankStratified(state);
   10085      914133 :         break;
   10086           0 :     default:
   10087           0 :         assert(false);
   10088             :     }
   10089     1474867 : }
   10090             : 
   10091      791115 : Real64 WaterThermalTankData::GetHPWHSensedTankTemp(EnergyPlusData &state)
   10092             : {
   10093      791115 :     switch (this->WaterThermalTankType) {
   10094      310157 :     case DataPlant::PlantEquipmentType::WtrHeaterMixed:
   10095      310157 :         return this->TankTemp;
   10096             :         break;
   10097      480958 :     case DataPlant::PlantEquipmentType::WtrHeaterStratified:
   10098      480958 :         return this->FindStratifiedTankSensedTemp(state);
   10099             :         break;
   10100           0 :     default:
   10101           0 :         assert(false);
   10102             :         return 0.0; // silence compiler
   10103             :     }
   10104             : }
   10105             : 
   10106      212616 : void WaterThermalTankData::ConvergeSingleSpeedHPWHCoilAndTank(EnergyPlusData &state, Real64 const partLoadRatio)
   10107             : {
   10108      212616 :     HeatPumpWaterHeaterData &HPWH = state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum);
   10109      212616 :     DXCoils::DXCoilData &Coil = state.dataDXCoils->DXCoil(HPWH.DXCoilNum);
   10110             : 
   10111      212616 :     Real64 PrevTankTemp = this->SourceOutletTemp;
   10112      742149 :     for (int i = 1; i <= 10; ++i) {
   10113             : 
   10114      742146 :         DXCoils::CalcHPWHDXCoil(state, HPWH.DXCoilNum, partLoadRatio);
   10115      742146 :         this->SourceInletTemp = state.dataLoopNodes->Node(HPWH.CondWaterOutletNode).Temp;
   10116             : 
   10117      742146 :         this->CalcWaterThermalTank(state);
   10118      742146 :         state.dataLoopNodes->Node(Coil.WaterInNode).Temp = this->SourceOutletTemp;
   10119             : 
   10120      742146 :         if (std::abs(this->SourceOutletTemp - PrevTankTemp) < DataHVACGlobals::SmallTempDiff) {
   10121      212613 :             break;
   10122             :         }
   10123             : 
   10124      529533 :         PrevTankTemp = this->SourceOutletTemp;
   10125             :     }
   10126      212616 : }
   10127             : 
   10128      508311 : void WaterThermalTankData::SetVSHPWHFlowRates(EnergyPlusData &state,
   10129             :                                               HeatPumpWaterHeaterData &HPWH, // heat pump coil
   10130             :                                               int const SpeedNum,            // upper speed number
   10131             :                                               Real64 const SpeedRatio,       // interpolation ration between upper and lower speed
   10132             :                                               Real64 const WaterDens,        // tank water density
   10133             :                                               Real64 &MdotWater,             // water flow rate
   10134             :                                               bool const FirstHVACIteration)
   10135             : {
   10136             :     // FUNCTION INFORMATION:
   10137             :     //       AUTHOR         B.Shen, ORNL, 12/2014
   10138             :     //       DATE WRITTEN   May 2005
   10139             :     //       MODIFIED
   10140             :     //       RE-ENGINEERED
   10141             : 
   10142             :     // PURPOSE OF THIS FUNCTION:
   10143             :     //  set water and air flow rates driven by the variable-speed HPWH coil
   10144             :     //  calculate resultant HPWH coil output
   10145             : 
   10146      508311 :     int SpeedLow = SpeedNum - 1;
   10147      508311 :     if (SpeedLow < 1) SpeedLow = 1;
   10148             : 
   10149      508311 :     int HPWaterInletNode = HPWH.CondWaterInletNode;
   10150      508311 :     int DXCoilAirInletNode = HPWH.DXCoilAirInletNode;
   10151      508311 :     if (HPWH.bIsIHP) {
   10152       19516 :         HPWH.OperatingWaterFlowRate = IntegratedHeatPump::GetWaterVolFlowRateIHP(state, HPWH.DXCoilNum, SpeedNum, SpeedRatio);
   10153       19516 :         state.dataWaterThermalTanks->mdotAir = IntegratedHeatPump::GetAirMassFlowRateIHP(state, HPWH.DXCoilNum, SpeedNum, SpeedRatio, true);
   10154       19516 :         HPWH.OperatingAirFlowRate = IntegratedHeatPump::GetAirVolFlowRateIHP(state, HPWH.DXCoilNum, SpeedNum, SpeedRatio, true);
   10155       19516 :         state.dataLoopNodes->Node(DXCoilAirInletNode).MassFlowRate = state.dataWaterThermalTanks->mdotAir;
   10156       19516 :         state.dataLoopNodes->Node(DXCoilAirInletNode).MassFlowRateMaxAvail = state.dataWaterThermalTanks->mdotAir;
   10157       19516 :         state.dataLoopNodes->Node(DXCoilAirInletNode).MassFlowRateMax = state.dataWaterThermalTanks->mdotAir;
   10158             :     } else {
   10159      488795 :         HPWH.OperatingWaterFlowRate = HPWH.HPWHWaterVolFlowRate(SpeedNum) * SpeedRatio + HPWH.HPWHWaterVolFlowRate(SpeedLow) * (1.0 - SpeedRatio);
   10160      488795 :         HPWH.OperatingAirFlowRate = HPWH.HPWHAirVolFlowRate(SpeedNum) * SpeedRatio + HPWH.HPWHAirVolFlowRate(SpeedLow) * (1.0 - SpeedRatio);
   10161      488795 :         state.dataWaterThermalTanks->mdotAir =
   10162      488795 :             HPWH.HPWHAirMassFlowRate(SpeedNum) * SpeedRatio + HPWH.HPWHAirMassFlowRate(SpeedLow) * (1.0 - SpeedRatio);
   10163             :     }
   10164             : 
   10165      508311 :     MdotWater = HPWH.OperatingWaterFlowRate * WaterDens;
   10166      508311 :     this->SourceMassFlowRate = MdotWater;
   10167             : 
   10168      508311 :     state.dataLoopNodes->Node(DXCoilAirInletNode).MassFlowRate = state.dataWaterThermalTanks->mdotAir;
   10169      508311 :     state.dataLoopNodes->Node(HPWaterInletNode).MassFlowRate = MdotWater;
   10170      508311 :     this->SourceMassFlowRate = MdotWater;
   10171             : 
   10172      508311 :     if (HPWH.InletAirMixerNode > 0) {
   10173       21698 :         state.dataLoopNodes->Node(HPWH.InletAirMixerNode).MassFlowRate = state.dataWaterThermalTanks->mdotAir;
   10174       21698 :         state.dataLoopNodes->Node(HPWH.InletAirMixerNode).MassFlowRateMaxAvail = state.dataWaterThermalTanks->mdotAir;
   10175             :     } else {
   10176      486613 :         if (HPWH.OutsideAirNode == 0) {
   10177       31241 :             state.dataLoopNodes->Node(HPWH.HeatPumpAirInletNode).MassFlowRate = state.dataWaterThermalTanks->mdotAir;
   10178       31241 :             state.dataLoopNodes->Node(HPWH.HeatPumpAirInletNode).MassFlowRateMaxAvail = state.dataWaterThermalTanks->mdotAir;
   10179             :         } else {
   10180      455372 :             state.dataLoopNodes->Node(HPWH.OutsideAirNode).MassFlowRate = state.dataWaterThermalTanks->mdotAir;
   10181      455372 :             state.dataLoopNodes->Node(HPWH.OutsideAirNode).MassFlowRateMaxAvail = state.dataWaterThermalTanks->mdotAir;
   10182             :         }
   10183             :     }
   10184             : 
   10185             :     // put fan component first, regardless placement, to calculate fan power
   10186             :     int FanInNode;
   10187      508311 :     if (HPWH.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
   10188      423368 :         FanInNode = state.dataHVACFan->fanObjs[HPWH.FanNum]->inletNodeNum;
   10189             :     } else {
   10190       84943 :         FanInNode = state.dataFans->Fan(HPWH.FanNum).InletNodeNum;
   10191             :     }
   10192             : 
   10193      508311 :     state.dataLoopNodes->Node(FanInNode).MassFlowRate = state.dataWaterThermalTanks->mdotAir;
   10194      508311 :     state.dataLoopNodes->Node(FanInNode).MassFlowRateMaxAvail = state.dataWaterThermalTanks->mdotAir;
   10195      508311 :     state.dataLoopNodes->Node(FanInNode).MassFlowRateMax = state.dataWaterThermalTanks->mdotAir;
   10196      508311 :     if (HPWH.FanType_Num != DataHVACGlobals::FanType_SystemModelObject) {
   10197       84943 :         state.dataFans->Fan(HPWH.FanNum).MassFlowRateMaxAvail = state.dataWaterThermalTanks->mdotAir;
   10198             :     } // system fan will use the inlet node max avail.
   10199             : 
   10200      508311 :     if (HPWH.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
   10201      423368 :         state.dataHVACFan->fanObjs[HPWH.FanNum]->simulate(state, _, _, _, _);
   10202             :     } else {
   10203       84943 :         Fans::SimulateFanComponents(state, HPWH.FanName, FirstHVACIteration, HPWH.FanNum);
   10204             :     }
   10205      508311 : }
   10206             : 
   10207       76030 : Real64 WaterThermalTankData::PLRResidualIterSpeed(EnergyPlusData &state,
   10208             :                                                   Real64 const SpeedRatio, // speed ratio between two speed levels
   10209             :                                                   int const HPNum,
   10210             :                                                   int const SpeedNum,
   10211             :                                                   int const HPWaterInletNode,
   10212             :                                                   int const HPWaterOutletNode,
   10213             :                                                   Real64 const RhoWater,
   10214             :                                                   Real64 const desTankTemp,
   10215             :                                                   TankOperatingMode const mode,
   10216             :                                                   bool const FirstHVACIteration)
   10217             : {
   10218             :     // FUNCTION INFORMATION:
   10219             :     //       AUTHOR         B.Shen, ORNL, 12/2014
   10220             :     //       MODIFIED
   10221             :     //       RE-ENGINEERED
   10222             : 
   10223             :     // PURPOSE OF THIS FUNCTION:
   10224             :     //  Calculates residual function (desired tank temp - actual tank temp), when iterating speed ration between two speed levels
   10225             :     //  HP water heater output depends on the speed ratio which is being varied to zero the residual.
   10226             : 
   10227             :     // METHODOLOGY EMPLOYED:
   10228             :     //  Calls residuals to get tank temperature at the given speed ratio between a lower and an upper speed levels
   10229             :     //  and calculates the residual as defined respectively for DataPlant::PlantEquipmentType::WtrHeaterMixed or
   10230             :     //  DataPlant::PlantEquipmentType::WtrHeaterStratified
   10231             : 
   10232       76030 :     Real64 EMP1(0.0), EMP2(0.0), EMP3(0.0); // place holder to calling variable-speed coil function
   10233       76030 :     this->Mode = mode;
   10234       76030 :     state.dataWaterThermalTanks->hpPartLoadRatio = 1.0;
   10235       76030 :     Real64 MdotWater = 0.0;
   10236             : 
   10237       76030 :     auto &HPWH = state.dataWaterThermalTanks->HPWaterHeater(HPNum);
   10238             : 
   10239       76030 :     this->SetVSHPWHFlowRates(state, HPWH, SpeedNum, SpeedRatio, RhoWater, MdotWater, FirstHVACIteration);
   10240             : 
   10241       76030 :     if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).bIsIHP) {
   10242         384 :         IntegratedHeatPump::SimIHP(state,
   10243          96 :                                    state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilName,
   10244          96 :                                    state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum,
   10245             :                                    DataHVACGlobals::CycFanCycCoil,
   10246             :                                    EMP1,
   10247             :                                    EMP2,
   10248             :                                    EMP3,
   10249             :                                    DataHVACGlobals::CompressorOperation::On,
   10250          96 :                                    state.dataWaterThermalTanks->hpPartLoadRatio,
   10251             :                                    SpeedNum,
   10252             :                                    SpeedRatio,
   10253             :                                    0.0,
   10254             :                                    0.0,
   10255             :                                    true,
   10256             :                                    false,
   10257             :                                    1.0);
   10258             :     } else {
   10259      303736 :         VariableSpeedCoils::SimVariableSpeedCoils(state,
   10260       75934 :                                                   state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilName,
   10261       75934 :                                                   state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum,
   10262             :                                                   DataHVACGlobals::CycFanCycCoil,
   10263             :                                                   EMP1,
   10264             :                                                   EMP2,
   10265             :                                                   EMP3,
   10266             :                                                   DataHVACGlobals::CompressorOperation::On,
   10267       75934 :                                                   state.dataWaterThermalTanks->hpPartLoadRatio,
   10268             :                                                   SpeedNum,
   10269             :                                                   SpeedRatio,
   10270             :                                                   0.0,
   10271             :                                                   0.0,
   10272             :                                                   1.0);
   10273             :     }
   10274             : 
   10275             :     Real64 CondenserDeltaT;
   10276       76030 :     CondenserDeltaT = state.dataLoopNodes->Node(HPWaterOutletNode).Temp - state.dataLoopNodes->Node(HPWaterInletNode).Temp;
   10277             : 
   10278             :     //           move the full load outlet temperature rate to the water heater structure variables
   10279             :     //           (water heaters source inlet node temperature/mdot are set in Init, set it here after DXCoils::CalcHPWHDXCoil has been called)
   10280       76030 :     this->SourceInletTemp = state.dataLoopNodes->Node(HPWaterInletNode).Temp + CondenserDeltaT;
   10281             : 
   10282             :     //           this CALL does not update node temps, must use WaterThermalTank variables
   10283             :     // select tank type
   10284       76030 :     Real64 NewTankTemp = 0.0;
   10285       76030 :     if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed) {
   10286       24885 :         this->CalcWaterThermalTankMixed(state);
   10287       24885 :         NewTankTemp = this->TankTemp;
   10288       51145 :     } else if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
   10289       51145 :         this->CalcWaterThermalTankStratified(state);
   10290       51145 :         NewTankTemp = this->FindStratifiedTankSensedTemp(state);
   10291             :     }
   10292             : 
   10293       76030 :     return desTankTemp - NewTankTemp;
   10294             : }
   10295             : 
   10296       67912 : Real64 WaterThermalTankData::PLRResidualHPWH(
   10297             :     EnergyPlusData &state, Real64 const HPPartLoadRatio, Real64 const desTankTemp, TankOperatingMode const mode, Real64 const mDotWater)
   10298             : {
   10299             :     // FUNCTION INFORMATION:
   10300             :     //       AUTHOR         B.Griffith,  Richard Raustad
   10301             :     //       DATE WRITTEN   Jan 2012
   10302             :     //       MODIFIED
   10303             :     //       RE-ENGINEERED  Noel Merket, Oct 2015
   10304             : 
   10305             :     // PURPOSE OF THIS FUNCTION:
   10306             :     //  Calculates residual function (desired tank temp - actual tank temp)
   10307             :     //  HP water heater output depends on the part load ratio which is being varied to zero the residual.
   10308             : 
   10309             :     // METHODOLOGY EMPLOYED:
   10310             :     //  Calls with CalcWaterThermalTankMixed or CalcWaterThermalTankStratified to get tank temperature at the given part load ratio (source water
   10311             :     //  mass flow rate) and calculates the residual as defined above
   10312             : 
   10313       67912 :     HeatPumpWaterHeaterData &HeatPump = state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum);
   10314       67912 :     bool const isVariableSpeed = (HeatPump.NumofSpeed > 0);
   10315       67912 :     this->Mode = mode;
   10316             :     // Apply the PLR
   10317       67912 :     if (this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed) {
   10318             :         // For a mixed tank, the PLR is applied to the source mass flow rate.
   10319       26534 :         this->SourceMassFlowRate = mDotWater * HPPartLoadRatio;
   10320       26534 :         this->CalcWaterThermalTankMixed(state);
   10321             :     } else {
   10322       41378 :         assert(this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified);
   10323             :         // For a stratified tank, the PLR is applied to the Coil.TotalHeatingEnergyRate
   10324             :         // whether that's a VarSpeedCoil or DXCoils::DXCoil.
   10325             :         // Here we create a pointer to the TotalHeatingEnergyRate for the appropriate coil type.
   10326             :         Real64 *CoilTotalHeatingEnergyRatePtr;
   10327       41378 :         if (isVariableSpeed) {
   10328         621 :             if (HeatPump.bIsIHP)
   10329           0 :                 CoilTotalHeatingEnergyRatePtr = &state.dataIntegratedHP->IntegratedHeatPumps(HeatPump.DXCoilNum).TotalWaterHeatingRate;
   10330             :             else
   10331         621 :                 CoilTotalHeatingEnergyRatePtr = &state.dataVariableSpeedCoils->VarSpeedCoil(HeatPump.DXCoilNum).TotalHeatingEnergyRate;
   10332             :         } else {
   10333       40757 :             CoilTotalHeatingEnergyRatePtr = &state.dataDXCoils->DXCoil(HeatPump.DXCoilNum).TotalHeatingEnergyRate;
   10334             :         }
   10335             :         // Copy the value of the total heating energy rate
   10336       41378 :         Real64 const CoilTotalHeatingEnergyRateBackup = *CoilTotalHeatingEnergyRatePtr;
   10337             :         // Apply the PLR
   10338       41378 :         *CoilTotalHeatingEnergyRatePtr *= HPPartLoadRatio;
   10339             :         // Tank Calculation
   10340       41378 :         this->CalcWaterThermalTankStratified(state);
   10341             :         // Restore the original value
   10342       41378 :         *CoilTotalHeatingEnergyRatePtr = CoilTotalHeatingEnergyRateBackup;
   10343             :     }
   10344       67912 :     Real64 NewTankTemp = this->GetHPWHSensedTankTemp(state);
   10345       67912 :     return desTankTemp - NewTankTemp;
   10346             : }
   10347             : 
   10348     1316276 : bool WaterThermalTankData::SourceHeatNeed(EnergyPlusData &state, Real64 const OutletTemp, Real64 const DeadBandTemp, Real64 const SetPointTemp_loc)
   10349             : {
   10350             :     // FUNCTION INFORMATION:
   10351             :     //       AUTHOR         Yueyue Zhou
   10352             :     //       DATE WRITTEN   May 2019
   10353             :     //       MODIFIED       na
   10354             :     //       RE-ENGINEERED  na
   10355             : 
   10356             :     // PURPOSE OF THIS FUNCTION:
   10357             :     // Determine by tank type, tank temperature and control mode if source side flow is needed
   10358             : 
   10359             :     // return value initialization
   10360     1316276 :     bool NeedsHeatOrCool = false;
   10361             : 
   10362     1316276 :     if (!this->IsChilledWaterTank) {
   10363      896980 :         if (this->SourceSideControlMode == SourceSideControl::IndirectHeatPrimarySetpoint) {
   10364      896980 :             if (OutletTemp < DeadBandTemp) {
   10365      125406 :                 NeedsHeatOrCool = true;
   10366      771574 :             } else if ((OutletTemp >= DeadBandTemp) && (OutletTemp < SetPointTemp_loc)) {
   10367             :                 // inside the deadband, use saved mode from water heater calcs
   10368      702830 :                 if (this->SavedMode == TankOperatingMode::Heating) {
   10369       87716 :                     NeedsHeatOrCool = true;
   10370      263699 :                 } else if (this->SavedMode == TankOperatingMode::Floating) {
   10371      263699 :                     NeedsHeatOrCool = false;
   10372             :                 }
   10373             : 
   10374      420159 :             } else if (OutletTemp >= SetPointTemp_loc) {
   10375      420159 :                 NeedsHeatOrCool = false;
   10376             :             }
   10377           0 :         } else if (this->SourceSideControlMode == SourceSideControl::IndirectHeatAltSetpoint) {
   10378             :             // get alternate setpoint
   10379           0 :             Real64 const AltSetpointTemp = ScheduleManager::GetCurrentScheduleValue(state, this->SourceSideAltSetpointSchedNum);
   10380           0 :             Real64 const AltDeadBandTemp = AltSetpointTemp - this->DeadBandDeltaTemp;
   10381           0 :             if (OutletTemp < AltDeadBandTemp) {
   10382           0 :                 NeedsHeatOrCool = true;
   10383           0 :             } else if ((OutletTemp >= AltDeadBandTemp) && (OutletTemp < AltSetpointTemp)) {
   10384             :                 // inside the deadband, use saved mode from water heater calcs
   10385           0 :                 if (this->SavedMode == TankOperatingMode::Heating) {
   10386           0 :                     NeedsHeatOrCool = true;
   10387           0 :                 } else if (this->SavedMode == TankOperatingMode::Floating) {
   10388           0 :                     NeedsHeatOrCool = false;
   10389             :                 }
   10390             : 
   10391           0 :             } else if (OutletTemp >= AltSetpointTemp) {
   10392           0 :                 NeedsHeatOrCool = false;
   10393             :             }
   10394           0 :         } else if (this->SourceSideControlMode == SourceSideControl::StorageTank) {
   10395           0 :             if (OutletTemp < this->TankTempLimit) {
   10396           0 :                 NeedsHeatOrCool = true;
   10397             :             } else {
   10398           0 :                 NeedsHeatOrCool = false;
   10399             :             }
   10400             :         }
   10401             :     } else { // is a chilled water tank so flip logic
   10402      419296 :         if (OutletTemp > DeadBandTemp) {
   10403       10744 :             NeedsHeatOrCool = true;
   10404      408552 :         } else if ((OutletTemp <= DeadBandTemp) && (OutletTemp > SetPointTemp_loc)) {
   10405             :             // inside the deadband, use saved mode from water thermal tank calcs (modes only for mixed)
   10406      603716 :             if (this->WaterThermalTankType == DataPlant::PlantEquipmentType::ChilledWaterTankMixed) {
   10407      276181 :                 if (this->SavedMode == TankOperatingMode::Cooling) {
   10408       36240 :                     NeedsHeatOrCool = true;
   10409      239941 :                 } else if (this->SavedMode == TankOperatingMode::Floating) {
   10410      239941 :                     NeedsHeatOrCool = false;
   10411             :                 }
   10412       25677 :             } else if (this->WaterThermalTankType == DataPlant::PlantEquipmentType::ChilledWaterTankStratified) {
   10413       25677 :                 NeedsHeatOrCool = true;
   10414             :             }
   10415             : 
   10416      106694 :         } else if (OutletTemp <= SetPointTemp_loc) {
   10417      106694 :             NeedsHeatOrCool = false;
   10418             :         }
   10419             :     }
   10420     1316276 :     return NeedsHeatOrCool;
   10421             : }
   10422             : 
   10423     7656984 : Real64 WaterThermalTankData::PlantMassFlowRatesFunc(EnergyPlusData &state,
   10424             :                                                     int const InNodeNum,
   10425             :                                                     bool const FirstHVACIteration,
   10426             :                                                     WaterHeaterSide const WaterThermalTankSide,
   10427             :                                                     const DataPlant::LoopSideLocation PlantLoopSide,
   10428             :                                                     [[maybe_unused]] bool const PlumbedInSeries,
   10429             :                                                     DataBranchAirLoopPlant::ControlType const BranchControlType,
   10430             :                                                     Real64 const OutletTemp,
   10431             :                                                     Real64 const DeadBandTemp,
   10432             :                                                     Real64 const SetPointTemp_loc)
   10433             : {
   10434             : 
   10435             :     // FUNCTION INFORMATION:
   10436             :     //       AUTHOR         Brent Griffith
   10437             :     //       DATE WRITTEN   October 2007
   10438             :     //       MODIFIED       na
   10439             :     //       RE-ENGINEERED  na
   10440             : 
   10441             :     // PURPOSE OF THIS FUNCTION:
   10442             :     // collect routines for setting flow rates for Water heaters
   10443             :     // with plant connections.
   10444             : 
   10445             :     // determine current mode.  there are three possible
   10446             :     //  1.  passing thru what was given to inlet node
   10447             :     //  2.  potentially making a flow request
   10448             :     //  3.  throttling flow in response to Plant's restrictions (MassFlowRateMaxAvail)
   10449             :     // init default mode changed to Unassigned
   10450     7656984 :     FlowMode CurrentMode = FlowMode::Invalid; // default
   10451             : 
   10452     7656984 :     if (PlantLoopSide == DataPlant::LoopSideLocation::Invalid) {
   10453      674706 :         CurrentMode = FlowMode::PassingFlowThru;
   10454     6982278 :     } else if (PlantLoopSide == DataPlant::LoopSideLocation::Supply) {
   10455             :         // If FlowLock is False (0), the tank sets the plant loop mdot
   10456             :         // If FlowLock is True (1),  the new resolved plant loop mdot is used
   10457     6431458 :         if (this->UseCurrentFlowLock == DataPlant::FlowLock::Unlocked) {
   10458     2685528 :             CurrentMode = FlowMode::PassingFlowThru;
   10459     2685528 :             if ((this->UseSideLoadRequested > 0.0) && (WaterThermalTankSide == WaterHeaterSide::Use)) {
   10460     2083360 :                 CurrentMode = FlowMode::MaybeRequestingFlow;
   10461             :             }
   10462             :         } else {
   10463     3745930 :             CurrentMode = FlowMode::PassingFlowThru;
   10464             :         }
   10465     6431458 :         if (WaterThermalTankSide == WaterHeaterSide::Source) {
   10466      765456 :             CurrentMode = FlowMode::MaybeRequestingFlow;
   10467             :         }
   10468      550820 :     } else if (PlantLoopSide == DataPlant::LoopSideLocation::Demand) {
   10469             : 
   10470             :         //  2.  Might be Requesting Flow.
   10471      550820 :         if (FirstHVACIteration) {
   10472      275168 :             if (BranchControlType == DataBranchAirLoopPlant::ControlType::Bypass) {
   10473           0 :                 CurrentMode = FlowMode::PassingFlowThru;
   10474             :             } else {
   10475      275168 :                 CurrentMode = FlowMode::MaybeRequestingFlow;
   10476             :             }
   10477             :         } else {
   10478      275652 :             if (BranchControlType == DataBranchAirLoopPlant::ControlType::Bypass) {
   10479           0 :                 CurrentMode = FlowMode::PassingFlowThru;
   10480             :             } else {
   10481      275652 :                 CurrentMode = FlowMode::ThrottlingFlow;
   10482             :             }
   10483             :         }
   10484             :     }
   10485             : 
   10486             :     // evaluate Availability schedule,
   10487     7656984 :     bool ScheduledAvail = true;
   10488     7656984 :     if (WaterThermalTankSide == WaterHeaterSide::Use) {
   10489     5666002 :         if (ScheduleManager::GetCurrentScheduleValue(state, this->UseSideAvailSchedNum) == 0.0) {
   10490           0 :             ScheduledAvail = false;
   10491             :         }
   10492     1990982 :     } else if (WaterThermalTankSide == WaterHeaterSide::Source) {
   10493     1990982 :         if (ScheduleManager::GetCurrentScheduleValue(state, this->SourceSideAvailSchedNum) == 0.0) {
   10494       58864 :             ScheduledAvail = false;
   10495             :         }
   10496             :     }
   10497             : 
   10498             :     // now act based on current mode
   10499     7656984 :     Real64 FlowResult = 0.0;
   10500     7656984 :     switch (CurrentMode) {
   10501             : 
   10502     4257348 :     case FlowMode::PassingFlowThru: {
   10503     4257348 :         if (!ScheduledAvail) {
   10504           0 :             FlowResult = 0.0;
   10505             :         } else {
   10506     4257348 :             FlowResult = state.dataLoopNodes->Node(InNodeNum).MassFlowRate;
   10507             :         }
   10508             : 
   10509     4257348 :         break;
   10510             :     }
   10511      275652 :     case FlowMode::ThrottlingFlow: {
   10512             :         // first determine what mass flow would be if it is to requested
   10513      275652 :         Real64 MassFlowRequest = 0.0;
   10514      275652 :         if (!ScheduledAvail) {
   10515       29432 :             MassFlowRequest = 0.0;
   10516             :         } else {
   10517      246220 :             if (WaterThermalTankSide == WaterHeaterSide::Use) {
   10518           0 :                 MassFlowRequest = this->PlantUseMassFlowRateMax;
   10519      246220 :             } else if (WaterThermalTankSide == WaterHeaterSide::Source) {
   10520      246220 :                 MassFlowRequest = this->PlantSourceMassFlowRateMax;
   10521             :             } else {
   10522           0 :                 assert(false);
   10523             :             }
   10524             :         }
   10525             : 
   10526             :         // next determine if tank temperature is such that source side flow might be requested
   10527      275652 :         bool NeedsHeatOrCool = this->SourceHeatNeed(state, OutletTemp, DeadBandTemp, SetPointTemp_loc);
   10528             : 
   10529      275652 :         if (MassFlowRequest > 0.0) {
   10530      246220 :             if (WaterThermalTankSide == WaterHeaterSide::Use) {
   10531           0 :                 FlowResult = MassFlowRequest;
   10532      246220 :             } else if (WaterThermalTankSide == WaterHeaterSide::Source) {
   10533      246220 :                 if (NeedsHeatOrCool) {
   10534       52600 :                     FlowResult = MassFlowRequest;
   10535             :                 } else {
   10536      193620 :                     FlowResult = 0.0;
   10537             :                 }
   10538             :             } else {
   10539           0 :                 assert(false);
   10540             :             }
   10541             :         } else {
   10542       29432 :             FlowResult = 0.0;
   10543             :         }
   10544             : 
   10545             :         // now throttle against MassFlowRateMaxAvail, MassFlowRateMinAvail, MassFlowRateMax, and MassFlowRateMin
   10546             :         // see notes about reverse dd compliance (specifically 5ZoneWaterSystems file)
   10547      275652 :         FlowResult = max(state.dataLoopNodes->Node(InNodeNum).MassFlowRateMinAvail, FlowResult); // okay for compliance (reverse dd)
   10548      275652 :         FlowResult = max(state.dataLoopNodes->Node(InNodeNum).MassFlowRateMin, FlowResult);      // okay for compliance (reverse dd)
   10549      275652 :         FlowResult = min(state.dataLoopNodes->Node(InNodeNum).MassFlowRateMaxAvail, FlowResult);
   10550             :         //=> following might take out of reverse dd compliance
   10551      275652 :         FlowResult = min(state.dataLoopNodes->Node(InNodeNum).MassFlowRateMax, FlowResult);
   10552             : 
   10553      275652 :         break;
   10554             :     }
   10555     3123984 :     case FlowMode::MaybeRequestingFlow: {
   10556             : 
   10557             :         // first determine what mass flow would be if it is to requested
   10558     3123984 :         Real64 MassFlowRequest = 0.0;
   10559     3123984 :         if (!ScheduledAvail) {
   10560       29432 :             MassFlowRequest = 0.0;
   10561             :         } else {
   10562     3094552 :             if (WaterThermalTankSide == WaterHeaterSide::Use) {
   10563     2083360 :                 if ((this->IsChilledWaterTank) && (this->UseSideLoadRequested > 0.0)) {
   10564       26764 :                     MassFlowRequest = this->PlantUseMassFlowRateMax;
   10565     2056596 :                 } else if ((this->IsChilledWaterTank) && (this->UseSideLoadRequested == 0.0)) {
   10566           0 :                     MassFlowRequest = 0.0;
   10567             :                 } else {
   10568     2056596 :                     MassFlowRequest = this->PlantUseMassFlowRateMax;
   10569             :                 }
   10570             : 
   10571     1011192 :             } else if (WaterThermalTankSide == WaterHeaterSide::Source) {
   10572     1011192 :                 MassFlowRequest = this->PlantSourceMassFlowRateMax;
   10573             :             }
   10574             :         }
   10575             : 
   10576     3123984 :         if (WaterThermalTankSide == WaterHeaterSide::Source) { // temperature dependent controls for indirect heating/cooling
   10577     1040624 :             bool NeedsHeatOrCool = this->SourceHeatNeed(state, OutletTemp, DeadBandTemp, SetPointTemp_loc);
   10578     1040624 :             if (MassFlowRequest > 0.0) {
   10579     1011174 :                 if (NeedsHeatOrCool) {
   10580      212816 :                     FlowResult = MassFlowRequest;
   10581             :                 } else {
   10582      798358 :                     FlowResult = 0.0;
   10583             :                 }
   10584             :             } else {
   10585       29450 :                 FlowResult = 0.0;
   10586             :             }
   10587             :         } else { // end source side, begin use side
   10588     2083360 :             if (MassFlowRequest > 0.0) {
   10589     2083360 :                 FlowResult = MassFlowRequest;
   10590             :             } else {
   10591           0 :                 FlowResult = 0.0;
   10592             :             }
   10593             :         }
   10594     3123984 :         break;
   10595             :     }
   10596           0 :     default:
   10597           0 :         break;
   10598             :     }
   10599             : 
   10600     7656984 :     if (FlowResult < DataHVACGlobals::VerySmallMassFlow) FlowResult = 0.0; // Catch underflow problems
   10601             : 
   10602     7656984 :     return FlowResult;
   10603             : }
   10604             : 
   10605         927 : void WaterThermalTankData::MinePlantStructForInfo(EnergyPlusData &state)
   10606             : {
   10607             : 
   10608             :     // SUBROUTINE INFORMATION:
   10609             :     //       AUTHOR         Brent Griffith
   10610             :     //       DATE WRITTEN   October 2007
   10611             :     //       MODIFIED       na
   10612             :     //       RE-ENGINEERED  na
   10613             : 
   10614             :     // PURPOSE OF THIS SUBROUTINE:
   10615             :     // get information from plant loop data structure
   10616             :     // check what we can learn from plant structure against user inputs
   10617             : 
   10618         927 :     bool ErrorsFound = false;
   10619             : 
   10620         927 :     if (allocated(state.dataPlnt->PlantLoop) && this->UseSidePlantLoc.loopNum > 0) {
   10621             : 
   10622             :         // check plant structure for useful data.
   10623             : 
   10624         854 :         int PlantLoopNum = this->UseSidePlantLoc.loopNum;
   10625         854 :         DataPlant::LoopSideLocation LoopSideNum = this->UseSidePlantLoc.loopSideNum;
   10626             : 
   10627         854 :         if ((this->UseDesignVolFlowRateWasAutoSized) && (this->UseSidePlantSizNum == 0)) {
   10628           0 :             ShowSevereError(state,
   10629           0 :                             "Water heater = " + this->Name + " for autosizing Use side flow rate, did not find Sizing:Plant object " +
   10630           0 :                                 state.dataPlnt->PlantLoop(PlantLoopNum).Name);
   10631           0 :             ErrorsFound = true;
   10632             :         }
   10633             :         // Is this wh Use side plumbed in series (default) or are there other branches in parallel?
   10634         854 :         if (state.dataPlnt->PlantLoop(PlantLoopNum).LoopSide(LoopSideNum).Splitter.Exists) {
   10635         854 :             if (any_eq(state.dataPlnt->PlantLoop(PlantLoopNum).LoopSide(LoopSideNum).Splitter.NodeNumOut,
   10636             :                        this->UseInletNode)) { // this wh is on the splitter
   10637         825 :                 if (state.dataPlnt->PlantLoop(PlantLoopNum).LoopSide(LoopSideNum).Splitter.TotalOutletNodes > 1) {
   10638         755 :                     this->UseSideSeries = false;
   10639             :                 }
   10640             :             }
   10641             :         }
   10642             :     }
   10643             : 
   10644         927 :     if (allocated(state.dataPlnt->PlantLoop) && this->SrcSidePlantLoc.loopNum > 0) {
   10645             :         // was user's input correct for plant loop name?
   10646         220 :         if ((this->SourceDesignVolFlowRateWasAutoSized) && (this->SourceSidePlantSizNum == 0) && (this->DesuperheaterNum == 0) &&
   10647           0 :             (this->HeatPumpNum == 0)) {
   10648           0 :             ShowSevereError(state,
   10649           0 :                             "Water heater = " + this->Name + "for autosizing Source side flow rate, did not find Sizing:Plant object " +
   10650           0 :                                 state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).Name);
   10651           0 :             ErrorsFound = true;
   10652             :         }
   10653             :         // Is this wh Source side plumbed in series (default) or are there other branches in parallel?
   10654         220 :         if (state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).LoopSide(this->SrcSidePlantLoc.loopSideNum).Splitter.Exists) {
   10655         220 :             if (any_eq(state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).LoopSide(this->SrcSidePlantLoc.loopSideNum).Splitter.NodeNumOut,
   10656             :                        this->SourceInletNode)) { // this wh is on the splitter
   10657         220 :                 if (state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).LoopSide(this->SrcSidePlantLoc.loopSideNum).Splitter.TotalOutletNodes >
   10658             :                     1) {
   10659          77 :                     this->SourceSideSeries = false;
   10660             :                 }
   10661             :             }
   10662             :         }
   10663             :     }
   10664             : 
   10665         927 :     if (ErrorsFound) {
   10666           0 :         ShowFatalError(state, "Preceding water heater input errors cause program termination");
   10667             :     }
   10668         927 : }
   10669             : 
   10670         731 : void WaterThermalTankData::SizeSupplySidePlantConnections(EnergyPlusData &state, Optional_int_const LoopNum)
   10671             : {
   10672             : 
   10673             :     // SUBROUTINE INFORMATION:
   10674             :     //       AUTHOR         Brent Griffith
   10675             :     //       DATE WRITTEN   October 2007
   10676             :     //       MODIFIED       na
   10677             :     //       RE-ENGINEERED  na
   10678             : 
   10679             :     // PURPOSE OF THIS SUBROUTINE:
   10680             :     // This subroutine is for sizing water heater plant connection flow rates
   10681             :     // on the supply that have not been specified in the input.
   10682             : 
   10683             :     // METHODOLOGY EMPLOYED:
   10684             :     // This routine is called later in the simulation than the sizing routine for the demand side
   10685             :     //  because the simulation needs to be further along before the needed data are available.
   10686             :     // For water heaters sides on Supply LoopSide, obtains hot water flow rate from the plant sizing array
   10687             :     //  (adapted approach from boiler sizing routines)
   10688             : 
   10689             :     static constexpr std::string_view RoutineName("SizeSupplySidePlantConnections");
   10690             : 
   10691         731 :     auto &PlantSizData(state.dataSize->PlantSizData);
   10692             : 
   10693         731 :     Real64 tmpUseDesignVolFlowRate = this->UseDesignVolFlowRate;
   10694         731 :     Real64 tmpSourceDesignVolFlowRate = this->SourceDesignVolFlowRate;
   10695             : 
   10696             :     int tmpLoopNum;
   10697         731 :     if (!present(LoopNum)) {
   10698           0 :         tmpLoopNum = this->SrcSidePlantLoc.loopNum;
   10699             :     } else {
   10700         731 :         tmpLoopNum = LoopNum;
   10701             :     }
   10702             : 
   10703         731 :     if ((this->UseInletNode > 0) && (tmpLoopNum == this->UseSidePlantLoc.loopNum)) {
   10704         631 :         if (this->UseDesignVolFlowRateWasAutoSized) {
   10705         601 :             int PltSizNum = this->UseSidePlantSizNum;
   10706         601 :             if (PltSizNum > 0) { // we have a Plant Sizing Object
   10707         601 :                 if (this->UseSidePlantLoc.loopSideNum == DataPlant::LoopSideLocation::Supply) {
   10708         601 :                     if (PlantSizData(PltSizNum).DesVolFlowRate >= DataHVACGlobals::SmallWaterVolFlow) {
   10709         484 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   10710         133 :                             this->UseDesignVolFlowRate = PlantSizData(PltSizNum).DesVolFlowRate;
   10711             :                         } else {
   10712         351 :                             tmpUseDesignVolFlowRate = PlantSizData(PltSizNum).DesVolFlowRate;
   10713             :                         }
   10714             :                     } else {
   10715         117 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   10716           0 :                             this->UseDesignVolFlowRate = 0.0;
   10717             :                         } else {
   10718         117 :                             tmpUseDesignVolFlowRate = 0.0;
   10719             :                         }
   10720             :                     }
   10721         601 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   10722         117 :                         BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Use Side Design Flow Rate [m3/s]", this->UseDesignVolFlowRate);
   10723             :                     }
   10724         601 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   10725          16 :                         BaseSizer::reportSizerOutput(
   10726           8 :                             state, this->Type, this->Name, "Initial Use Side Design Flow Rate [m3/s]", this->UseDesignVolFlowRate);
   10727             :                     }
   10728         601 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   10729         133 :                         PlantUtilities::RegisterPlantCompDesignFlow(state, this->UseInletNode, this->UseDesignVolFlowRate);
   10730             :                     } else {
   10731         468 :                         PlantUtilities::RegisterPlantCompDesignFlow(state, this->UseInletNode, tmpUseDesignVolFlowRate);
   10732             :                     }
   10733             : 
   10734        1202 :                     Real64 rho = FluidProperties::GetDensityGlycol(state,
   10735         601 :                                                                    state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
   10736             :                                                                    DataGlobalConstants::InitConvTemp,
   10737         601 :                                                                    state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
   10738         601 :                                                                    RoutineName);
   10739         601 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   10740         133 :                         this->PlantUseMassFlowRateMax = this->UseDesignVolFlowRate * rho;
   10741             :                     } else {
   10742         468 :                         this->PlantUseMassFlowRateMax = tmpUseDesignVolFlowRate * rho;
   10743             :                     }
   10744             :                 }
   10745             :             } else {
   10746             :                 // do nothing
   10747             :             } // plant sizing object
   10748             :         } else {
   10749          30 :             PlantUtilities::RegisterPlantCompDesignFlow(state, this->UseInletNode, this->UseDesignVolFlowRate);
   10750             :             Real64 rho;
   10751          30 :             if (this->UseSidePlantLoc.loopNum > 0) {
   10752          60 :                 rho = FluidProperties::GetDensityGlycol(state,
   10753          30 :                                                         state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
   10754             :                                                         DataGlobalConstants::InitConvTemp,
   10755          30 :                                                         state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
   10756             :                                                         RoutineName);
   10757             :             } else {
   10758           0 :                 rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, DataGlobalConstants::InitConvTemp, this->waterIndex, RoutineName);
   10759             :             }
   10760             : 
   10761          30 :             this->PlantUseMassFlowRateMax = this->UseDesignVolFlowRate * rho;
   10762             : 
   10763             :         } // autosizing needed.
   10764             :     }     // connected to plant
   10765             : 
   10766         731 :     if ((this->SourceInletNode > 0) && (tmpLoopNum == this->SrcSidePlantLoc.loopNum)) {
   10767         100 :         if (this->SourceDesignVolFlowRateWasAutoSized) {
   10768          50 :             int PltSizNum = this->SourceSidePlantSizNum;
   10769          50 :             if (PltSizNum > 0) {
   10770          50 :                 if (this->SrcSidePlantLoc.loopSideNum == DataPlant::LoopSideLocation::Supply) {
   10771          20 :                     if (PlantSizData(PltSizNum).DesVolFlowRate >= DataHVACGlobals::SmallWaterVolFlow) {
   10772          14 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   10773           4 :                             this->SourceDesignVolFlowRate = PlantSizData(PltSizNum).DesVolFlowRate;
   10774             :                         } else {
   10775          10 :                             tmpSourceDesignVolFlowRate = PlantSizData(PltSizNum).DesVolFlowRate;
   10776             :                         }
   10777             :                     } else {
   10778           6 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   10779           0 :                             this->SourceDesignVolFlowRate = 0.0;
   10780             :                         } else {
   10781           6 :                             tmpSourceDesignVolFlowRate = 0.0;
   10782             :                         }
   10783             :                     }
   10784          20 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   10785           8 :                         BaseSizer::reportSizerOutput(
   10786           4 :                             state, this->Type, this->Name, "Source Side Design Flow Rate [m3/s]", this->SourceDesignVolFlowRate);
   10787             :                     }
   10788          20 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   10789           0 :                         BaseSizer::reportSizerOutput(
   10790           0 :                             state, this->Type, this->Name, "Initial Source Side Design Flow Rate [m3/s]", this->SourceDesignVolFlowRate);
   10791             :                     }
   10792          20 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   10793           4 :                         PlantUtilities::RegisterPlantCompDesignFlow(state, this->SourceInletNode, this->SourceDesignVolFlowRate);
   10794             :                     } else {
   10795          16 :                         PlantUtilities::RegisterPlantCompDesignFlow(state, this->SourceInletNode, tmpSourceDesignVolFlowRate);
   10796             :                     }
   10797          40 :                     Real64 rho = FluidProperties::GetDensityGlycol(state,
   10798          20 :                                                                    state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidName,
   10799             :                                                                    DataGlobalConstants::InitConvTemp,
   10800          20 :                                                                    state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidIndex,
   10801          20 :                                                                    RoutineName);
   10802          20 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   10803           4 :                         this->PlantSourceMassFlowRateMax = this->SourceDesignVolFlowRate * rho;
   10804             :                     } else {
   10805          16 :                         this->PlantSourceMassFlowRateMax = tmpSourceDesignVolFlowRate * rho;
   10806             :                     }
   10807             :                 } // plant loop allocation
   10808             :             } else {
   10809             :                 // do nothing
   10810             :             } // plant sizing object
   10811             :         } else {
   10812          50 :             if (this->SrcSidePlantLoc.loopSideNum == DataPlant::LoopSideLocation::Supply) {
   10813          45 :                 PlantUtilities::RegisterPlantCompDesignFlow(state, this->SourceInletNode, this->SourceDesignVolFlowRate);
   10814             :                 Real64 rho;
   10815          45 :                 if (this->SrcSidePlantLoc.loopNum > 0) {
   10816          90 :                     rho = FluidProperties::GetDensityGlycol(state,
   10817          45 :                                                             state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidName,
   10818             :                                                             DataGlobalConstants::InitConvTemp,
   10819          45 :                                                             state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidIndex,
   10820             :                                                             RoutineName);
   10821             :                 } else {
   10822           0 :                     rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, DataGlobalConstants::InitConvTemp, this->waterIndex, RoutineName);
   10823             :                 }
   10824          45 :                 this->PlantSourceMassFlowRateMax = this->SourceDesignVolFlowRate * rho;
   10825             :             }
   10826             :         } // autosizing needed.
   10827             :     }     // connected to plant
   10828         731 : }
   10829             : 
   10830         731 : void WaterThermalTankData::SizeTankForDemandSide(EnergyPlusData &state)
   10831             : {
   10832             : 
   10833             :     // SUBROUTINE INFORMATION:
   10834             :     //       AUTHOR         Brent Griffith
   10835             :     //       DATE WRITTEN   February 2008
   10836             :     //       MODIFIED       na
   10837             :     //       RE-ENGINEERED  na
   10838             : 
   10839             :     // PURPOSE OF THIS SUBROUTINE:
   10840             :     // This subroutine is for sizing water heater tank volume and heater
   10841             :     //  as best we can at this point in simulation. (prior to demand side
   10842             :     //  sizing that needs volume).
   10843             : 
   10844             :     // METHODOLOGY EMPLOYED:
   10845             :     //  depending on the sizing design mode...
   10846             : 
   10847             :     // REFERENCES:
   10848             :     // BA benchmark report for residential design mode
   10849             : 
   10850             :     // SUBROUTINE PARAMETER DEFINITIONS:
   10851             :     static constexpr std::string_view RoutineName("SizeTankForDemandSide");
   10852         731 :     Real64 constexpr GalTocubicMeters(0.0037854);
   10853         731 :     Real64 constexpr kBtuPerHrToWatts(293.1);
   10854             : 
   10855         731 :     Real64 Tstart = 14.44;
   10856         731 :     Real64 Tfinish = 57.22;
   10857             : 
   10858         731 :     Real64 tmpTankVolume = this->Volume;
   10859         731 :     Real64 tmpMaxCapacity = this->MaxCapacity;
   10860             : 
   10861         731 :     switch (this->Sizing.DesignMode) {
   10862             : 
   10863         721 :     case SizingMode::Invalid:
   10864             :     case SizingMode::PeakDraw: {
   10865             : 
   10866         721 :         break;
   10867             :     }
   10868          10 :     case SizingMode::ResidentialMin: {
   10869             : 
   10870             :         // assume can propagate rules for gas to other fuels.
   10871          10 :         bool FuelTypeIsLikeGas = false;
   10872          10 :         switch (this->FuelType) {
   10873           0 :         case Fuel::NaturalGas:
   10874             :         case Fuel::Diesel:
   10875             :         case Fuel::Gasoline:
   10876             :         case Fuel::Coal:
   10877             :         case Fuel::FuelOilNo1:
   10878             :         case Fuel::FuelOilNo2:
   10879             :         case Fuel::Propane:
   10880             :         case Fuel::Steam:
   10881             :         case Fuel::OtherFuel1:
   10882             :         case Fuel::OtherFuel2:
   10883             :         case Fuel::DistrictHeating:
   10884           0 :             FuelTypeIsLikeGas = true;
   10885           0 :             break;
   10886          10 :         default: // FuelTypeIsLikeGas stays false
   10887          10 :             break;
   10888             :         }
   10889             : 
   10890          10 :         if (this->Sizing.NumberOfBedrooms == 1) {
   10891           0 :             if (this->FuelType == Fuel::Electricity) {
   10892           0 :                 if (this->VolumeWasAutoSized) tmpTankVolume = 20.0 * GalTocubicMeters;
   10893           0 :                 if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 2.5 * 1000.0; // 2.5 kW
   10894           0 :             } else if (FuelTypeIsLikeGas) {
   10895           0 :                 if (this->VolumeWasAutoSized) tmpTankVolume = 20.0 * GalTocubicMeters;
   10896           0 :                 if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 27.0 * kBtuPerHrToWatts; // 27kBtu/hr
   10897             :             }
   10898             : 
   10899          10 :         } else if (this->Sizing.NumberOfBedrooms == 2) {
   10900           0 :             if (this->Sizing.NumberOfBathrooms <= 1.5) {
   10901           0 :                 if (this->FuelType == Fuel::Electricity) {
   10902           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 30.0 * GalTocubicMeters;
   10903           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 3.5 * 1000.0; // 3.5 kW
   10904           0 :                 } else if (FuelTypeIsLikeGas) {
   10905           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 30.0 * GalTocubicMeters;
   10906           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 36.0 * kBtuPerHrToWatts; // 36 kBtu/hr
   10907             :                 }
   10908           0 :             } else if ((this->Sizing.NumberOfBathrooms > 1.5) && (this->Sizing.NumberOfBathrooms < 3.0)) {
   10909           0 :                 if (this->FuelType == Fuel::Electricity) {
   10910           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 40.0 * GalTocubicMeters;
   10911           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 4.5 * 1000.0; // 4.5 kW
   10912           0 :                 } else if (FuelTypeIsLikeGas) {
   10913           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 30.0 * GalTocubicMeters;
   10914           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 36.0 * kBtuPerHrToWatts; // 36 kBtu/hr
   10915             :                 }
   10916           0 :             } else if (this->Sizing.NumberOfBathrooms >= 3.0) {
   10917           0 :                 if (this->FuelType == Fuel::Electricity) {
   10918           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   10919           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   10920           0 :                 } else if (FuelTypeIsLikeGas) {
   10921           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 40.0 * GalTocubicMeters;
   10922           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 36.0 * kBtuPerHrToWatts; // 36 kBtu/hr
   10923             :                 }
   10924             :             }
   10925          10 :         } else if (this->Sizing.NumberOfBedrooms == 3) {
   10926          10 :             if (this->Sizing.NumberOfBathrooms <= 1.5) {
   10927           0 :                 if (this->FuelType == Fuel::Electricity) {
   10928           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 40.0 * GalTocubicMeters;
   10929           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 4.5 * 1000.0; // 4.5 kW
   10930           0 :                 } else if (FuelTypeIsLikeGas) {
   10931           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 30.0 * GalTocubicMeters;
   10932           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 36.0 * kBtuPerHrToWatts; // 36 kBtu/hr
   10933             :                 }
   10934          10 :             } else if ((this->Sizing.NumberOfBathrooms > 1.5) && (this->Sizing.NumberOfBathrooms < 3.0)) {
   10935           0 :                 if (this->FuelType == Fuel::Electricity) {
   10936           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   10937           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   10938           0 :                 } else if (FuelTypeIsLikeGas) {
   10939           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 40.0 * GalTocubicMeters;
   10940           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 36.0 * kBtuPerHrToWatts; // 36 kBtu/hr
   10941             :                 }
   10942          10 :             } else if (this->Sizing.NumberOfBathrooms >= 3.0) {
   10943          10 :                 if (this->FuelType == Fuel::Electricity) {
   10944          10 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   10945          10 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   10946           0 :                 } else if (FuelTypeIsLikeGas) {
   10947           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 40.0 * GalTocubicMeters;
   10948           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 38.0 * kBtuPerHrToWatts; // 38 kBtu/hr
   10949             :                 }
   10950             :             }
   10951           0 :         } else if (this->Sizing.NumberOfBedrooms == 4) {
   10952           0 :             if (this->Sizing.NumberOfBathrooms <= 1.5) {
   10953           0 :                 if (this->FuelType == Fuel::Electricity) {
   10954           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   10955           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   10956           0 :                 } else if (FuelTypeIsLikeGas) {
   10957           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 40.0 * GalTocubicMeters;
   10958           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 36.0 * kBtuPerHrToWatts; // 36 kBtu/hr
   10959             :                 }
   10960           0 :             } else if ((this->Sizing.NumberOfBathrooms > 1.5) && (this->Sizing.NumberOfBathrooms < 3.0)) {
   10961           0 :                 if (this->FuelType == Fuel::Electricity) {
   10962           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   10963           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   10964           0 :                 } else if (FuelTypeIsLikeGas) {
   10965           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 40.0 * GalTocubicMeters;
   10966           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 38.0 * kBtuPerHrToWatts; // 38 kBtu/hr
   10967             :                 }
   10968           0 :             } else if (this->Sizing.NumberOfBathrooms >= 3.0) {
   10969           0 :                 if (this->FuelType == Fuel::Electricity) {
   10970           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 66.0 * GalTocubicMeters;
   10971           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   10972           0 :                 } else if (FuelTypeIsLikeGas) {
   10973           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   10974           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 38.0 * kBtuPerHrToWatts; // 38 kBtu/hr
   10975             :                 }
   10976             :             }
   10977           0 :         } else if (this->Sizing.NumberOfBedrooms == 5) {
   10978           0 :             if (this->FuelType == Fuel::Electricity) {
   10979           0 :                 if (this->VolumeWasAutoSized) tmpTankVolume = 66.0 * GalTocubicMeters;
   10980           0 :                 if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   10981           0 :             } else if (FuelTypeIsLikeGas) {
   10982           0 :                 if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   10983           0 :                 if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 47.0 * kBtuPerHrToWatts; // 47 kBtu/hr
   10984             :             }
   10985           0 :         } else if (this->Sizing.NumberOfBedrooms >= 6) {
   10986           0 :             if (this->FuelType == Fuel::Electricity) {
   10987           0 :                 if (this->VolumeWasAutoSized) tmpTankVolume = 66.0 * GalTocubicMeters;
   10988           0 :                 if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   10989           0 :             } else if (FuelTypeIsLikeGas) {
   10990           0 :                 if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   10991           0 :                 if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 50.0 * kBtuPerHrToWatts; // 50 kBtu/hr
   10992             :             }
   10993             :         }
   10994             : 
   10995          10 :         if (this->VolumeWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   10996           0 :             this->Volume = tmpTankVolume;
   10997           0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   10998           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Volume [m3]", this->Volume);
   10999             :             }
   11000           0 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11001           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Initial Tank Volume [m3]", this->Volume);
   11002             :             }
   11003             :         }
   11004          10 :         if (this->MaxCapacityWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11005           2 :             this->MaxCapacity = tmpMaxCapacity;
   11006           2 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11007           2 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Maximum Heater Capacity [W]", this->MaxCapacity);
   11008             :             }
   11009           2 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11010           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Initial Maximum Heater Capacity [W]", this->MaxCapacity);
   11011             :             }
   11012             :         }
   11013          10 :         break;
   11014             :     }
   11015           0 :     case SizingMode::PerPerson: {
   11016             :         // how to get number of people?
   11017             : 
   11018           0 :         Real64 SumPeopleAllZones = sum(state.dataHeatBal->Zone, &DataHeatBalance::ZoneData::TotOccupants);
   11019           0 :         if (this->VolumeWasAutoSized) tmpTankVolume = this->Sizing.TankCapacityPerPerson * SumPeopleAllZones;
   11020             : 
   11021           0 :         if (this->MaxCapacityWasAutoSized) {
   11022             :             Real64 rho;
   11023             :             Real64 Cp;
   11024           0 :             if (this->UseSidePlantLoc.loopNum > 0) {
   11025           0 :                 rho = FluidProperties::GetDensityGlycol(state,
   11026           0 :                                                         state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
   11027           0 :                                                         ((Tfinish + Tstart) / 2.0),
   11028           0 :                                                         state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
   11029             :                                                         RoutineName);
   11030           0 :                 Cp = FluidProperties::GetSpecificHeatGlycol(state,
   11031           0 :                                                             state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
   11032           0 :                                                             ((Tfinish + Tstart) / 2.0),
   11033           0 :                                                             state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
   11034             :                                                             RoutineName);
   11035             :             } else {
   11036           0 :                 rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11037           0 :                 Cp = FluidProperties::GetSpecificHeatGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11038             :             }
   11039             : 
   11040           0 :             tmpMaxCapacity = SumPeopleAllZones * this->Sizing.RecoveryCapacityPerPerson * (Tfinish - Tstart) *
   11041           0 :                              (1.0 / DataGlobalConstants::SecInHour) * rho * Cp; // m3/hr/person | delta T  in K | 1 hr/ 3600 s | kg/m3 | J/Kg/k
   11042             :         }
   11043             : 
   11044           0 :         if (this->VolumeWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11045           0 :             this->Volume = tmpTankVolume;
   11046           0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11047           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Volume [m3]", this->Volume);
   11048             :             }
   11049           0 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11050           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Initial Tank Volume [m3]", this->Volume);
   11051             :             }
   11052             :         }
   11053           0 :         if (this->MaxCapacityWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11054           0 :             this->MaxCapacity = tmpMaxCapacity;
   11055           0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11056           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Maximum Heater Capacity [W]", this->MaxCapacity);
   11057             :             }
   11058           0 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11059           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Initial Maximum Heater Capacity [W]", this->MaxCapacity);
   11060             :             }
   11061             :         }
   11062           0 :         break;
   11063             :     }
   11064           0 :     case SizingMode::PerFloorArea: {
   11065             : 
   11066           0 :         Real64 SumFloorAreaAllZones = sum(state.dataHeatBal->Zone, &DataHeatBalance::ZoneData::FloorArea);
   11067           0 :         if (this->VolumeWasAutoSized) tmpTankVolume = this->Sizing.TankCapacityPerArea * SumFloorAreaAllZones;
   11068           0 :         if (this->MaxCapacityWasAutoSized) {
   11069             :             Real64 rho;
   11070             :             Real64 Cp;
   11071           0 :             if (this->UseSidePlantLoc.loopNum > 0) {
   11072           0 :                 rho = FluidProperties::GetDensityGlycol(state,
   11073           0 :                                                         state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
   11074           0 :                                                         ((Tfinish + Tstart) / 2.0),
   11075           0 :                                                         state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
   11076             :                                                         RoutineName);
   11077           0 :                 Cp = FluidProperties::GetSpecificHeatGlycol(state,
   11078           0 :                                                             state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
   11079           0 :                                                             ((Tfinish + Tstart) / 2.0),
   11080           0 :                                                             state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
   11081             :                                                             RoutineName);
   11082             :             } else {
   11083           0 :                 rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11084           0 :                 Cp = FluidProperties::GetSpecificHeatGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11085             :             }
   11086           0 :             tmpMaxCapacity = SumFloorAreaAllZones * this->Sizing.RecoveryCapacityPerArea * (Tfinish - Tstart) *
   11087           0 :                              (1.0 / DataGlobalConstants::SecInHour) * rho * Cp; // m2 | m3/hr/m2 | delta T  in K | 1 hr/ 3600 s | kg/m3 | J/Kg/k
   11088             :         }
   11089           0 :         if (this->VolumeWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11090           0 :             this->Volume = tmpTankVolume;
   11091           0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11092           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Volume [m3]", this->Volume);
   11093             :             }
   11094           0 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11095           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Initial Tank Volume [m3]", this->Volume);
   11096             :             }
   11097             :         }
   11098           0 :         if (this->MaxCapacityWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11099           0 :             this->MaxCapacity = tmpMaxCapacity;
   11100           0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11101           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Maximum Heater Capacity [W]", this->MaxCapacity);
   11102             :             }
   11103           0 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11104           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Initial Maximum Heater Capacity [W]", this->MaxCapacity);
   11105             :             }
   11106             :         }
   11107           0 :         break;
   11108             :     }
   11109           0 :     case SizingMode::PerUnit: {
   11110             : 
   11111           0 :         if (this->VolumeWasAutoSized) tmpTankVolume = this->Sizing.TankCapacityPerUnit * this->Sizing.NumberOfUnits;
   11112             : 
   11113           0 :         if (this->MaxCapacityWasAutoSized) {
   11114             :             Real64 rho;
   11115             :             Real64 Cp;
   11116           0 :             if (this->UseSidePlantLoc.loopNum > 0) {
   11117           0 :                 rho = FluidProperties::GetDensityGlycol(state,
   11118           0 :                                                         state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
   11119           0 :                                                         ((Tfinish + Tstart) / 2.0),
   11120           0 :                                                         state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
   11121             :                                                         RoutineName);
   11122           0 :                 Cp = FluidProperties::GetSpecificHeatGlycol(state,
   11123           0 :                                                             state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
   11124           0 :                                                             ((Tfinish + Tstart) / 2.0),
   11125           0 :                                                             state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
   11126             :                                                             RoutineName);
   11127             :             } else {
   11128           0 :                 rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11129           0 :                 Cp = FluidProperties::GetSpecificHeatGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11130             :             }
   11131           0 :             tmpMaxCapacity = this->Sizing.NumberOfUnits * this->Sizing.RecoveryCapacityPerUnit * (Tfinish - Tstart) *
   11132           0 :                              (1.0 / DataGlobalConstants::SecInHour) * rho * Cp; // m3/hr/ea | delta T  in K | 1 hr/ 3600 s | kg/m3 | J/Kg/k
   11133             :         }
   11134             : 
   11135           0 :         if (this->VolumeWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11136           0 :             this->Volume = tmpTankVolume;
   11137           0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11138           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Volume [m3]", this->Volume);
   11139             :             }
   11140           0 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11141           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Initial Tank Volume [m3]", this->Volume);
   11142             :             }
   11143             :         }
   11144           0 :         if (this->MaxCapacityWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11145           0 :             this->MaxCapacity = tmpMaxCapacity;
   11146           0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11147           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Maximum Heater Capacity [W]", this->MaxCapacity);
   11148             :             }
   11149           0 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11150           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Initial Maximum Heater Capacity [W]", this->MaxCapacity);
   11151             :             }
   11152             :         }
   11153           0 :         break;
   11154             :     }
   11155           0 :     case SizingMode::PerSolarColArea: {
   11156           0 :         break;
   11157             :     }
   11158           0 :     default:
   11159           0 :         break;
   11160             :     }
   11161             : 
   11162         731 :     if (this->MaxCapacityWasAutoSized) this->setBackupElementCapacity(state);
   11163             : 
   11164             :     // if stratified, might set height.
   11165         731 :     if ((this->VolumeWasAutoSized) && (this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) &&
   11166           0 :         state.dataPlnt->PlantFirstSizesOkayToFinalize) { // might set height
   11167           0 :         if ((this->HeightWasAutoSized) && (!this->VolumeWasAutoSized)) {
   11168           0 :             this->Height = std::pow((4.0 * this->Volume * pow_2(this->Sizing.HeightAspectRatio)) / DataGlobalConstants::Pi, 0.3333333333333333);
   11169           0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11170           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Height [m]", this->Height);
   11171             :             }
   11172           0 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11173           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Initial Tank Height [m]", this->Height);
   11174             :             }
   11175             :             // check if DataGlobalConstants::AutoCalculate() Use outlet and source inlet are still set to autosize by earlier
   11176           0 :             if (this->UseOutletHeightWasAutoSized) {
   11177           0 :                 this->UseOutletHeight = this->Height;
   11178             :             }
   11179           0 :             if (this->SourceInletHeightWasAutoSized) {
   11180           0 :                 this->SourceInletHeight = this->Height;
   11181             :             }
   11182             :         }
   11183             :     }
   11184         731 : }
   11185             : 
   11186         731 : void WaterThermalTankData::SizeTankForSupplySide(EnergyPlusData &state)
   11187             : {
   11188             : 
   11189             :     // SUBROUTINE INFORMATION:
   11190             :     //       AUTHOR         Brent Griffith
   11191             :     //       DATE WRITTEN   February 2008
   11192             :     //       MODIFIED       na
   11193             :     //       RE-ENGINEERED  na
   11194             : 
   11195             :     // PURPOSE OF THIS SUBROUTINE:
   11196             :     // This subroutine is for sizing water heater tank volume and heater
   11197             :     //   at a later point in the simulation when more of the plant is ready.
   11198             : 
   11199             :     // METHODOLOGY EMPLOYED:
   11200             :     //  depending on the sizing design mode...
   11201             : 
   11202             :     // REFERENCES:
   11203             :     // BA benchmark report for residential design mode
   11204             : 
   11205             :     static constexpr std::string_view RoutineName("SizeTankForSupplySide");
   11206             : 
   11207         731 :     Real64 Tstart = 14.44;
   11208         731 :     Real64 Tfinish = 57.22;
   11209             : 
   11210         731 :     Real64 tmpTankVolume = this->Volume;
   11211         731 :     Real64 tmpMaxCapacity = this->MaxCapacity;
   11212             : 
   11213         731 :     if (this->Sizing.DesignMode == SizingMode::PeakDraw) {
   11214          20 :         if (this->VolumeWasAutoSized)
   11215          20 :             tmpTankVolume = this->Sizing.TankDrawTime * this->UseDesignVolFlowRate * DataGlobalConstants::SecInHour; // hours | m3/s | (3600 s/1 hour)
   11216          20 :         if (this->VolumeWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11217           4 :             this->Volume = tmpTankVolume;
   11218           4 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11219           4 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Volume [m3]", this->Volume);
   11220             :             }
   11221           4 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11222           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Initial Tank Volume [m3]", this->Volume);
   11223             :             }
   11224             :         }
   11225          20 :         if (this->MaxCapacityWasAutoSized) {
   11226           0 :             if (this->Sizing.RecoveryTime > 0.0) {
   11227             :                 Real64 rho;
   11228             :                 Real64 Cp;
   11229           0 :                 if (this->SrcSidePlantLoc.loopNum > 0) {
   11230           0 :                     rho = FluidProperties::GetDensityGlycol(state,
   11231           0 :                                                             state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidName,
   11232           0 :                                                             ((Tfinish + Tstart) / 2.0),
   11233           0 :                                                             state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidIndex,
   11234             :                                                             RoutineName);
   11235           0 :                     Cp = FluidProperties::GetSpecificHeatGlycol(state,
   11236           0 :                                                                 state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidName,
   11237           0 :                                                                 ((Tfinish + Tstart) / 2.0),
   11238           0 :                                                                 state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidIndex,
   11239             :                                                                 RoutineName);
   11240             :                 } else {
   11241           0 :                     rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11242           0 :                     Cp = FluidProperties::GetSpecificHeatGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11243             :                 }
   11244           0 :                 tmpMaxCapacity = (this->Volume * rho * Cp * (Tfinish - Tstart)) /
   11245           0 :                                  (this->Sizing.RecoveryTime * DataGlobalConstants::SecInHour); // m3 | kg/m3 | J/Kg/K | K | seconds
   11246             :             } else {
   11247           0 :                 ShowFatalError(state,
   11248           0 :                                "SizeTankForSupplySide: Tank=\"" + this->Name +
   11249             :                                    "\", requested sizing for max capacity but entered Recovery Time is zero.");
   11250             :             }
   11251             :         }
   11252             : 
   11253          20 :         if (this->MaxCapacityWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11254           0 :             this->MaxCapacity = tmpMaxCapacity;
   11255           0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11256           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Maximum Heater Capacity [W]", this->MaxCapacity);
   11257             :             }
   11258           0 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11259           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Initial Maximum Heater Capacity [W]", this->MaxCapacity);
   11260             :             }
   11261             :         }
   11262         711 :     } else if (this->Sizing.DesignMode == SizingMode::PerSolarColArea) {
   11263             : 
   11264           0 :         this->Sizing.TotalSolarCollectorArea = 0.0;
   11265           0 :         for (int CollectorNum = 1; CollectorNum <= state.dataSolarCollectors->NumOfCollectors; ++CollectorNum) {
   11266           0 :             this->Sizing.TotalSolarCollectorArea += state.dataSurface->Surface(state.dataSolarCollectors->Collector(CollectorNum).Surface).Area;
   11267             :         }
   11268             : 
   11269           0 :         if (this->VolumeWasAutoSized) tmpTankVolume = this->Sizing.TotalSolarCollectorArea * this->Sizing.TankCapacityPerCollectorArea;
   11270           0 :         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 0.0;
   11271           0 :         if (this->VolumeWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11272           0 :             this->Volume = tmpTankVolume;
   11273           0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11274           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Volume [m3]", this->Volume);
   11275             :             }
   11276           0 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11277           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Initial Tank Volume [m3]", this->Volume);
   11278             :             }
   11279             :         }
   11280           0 :         if (this->MaxCapacityWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11281           0 :             this->MaxCapacity = tmpMaxCapacity;
   11282           0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11283           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Maximum Heater Capacity [W]", this->MaxCapacity);
   11284             :             }
   11285           0 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11286           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Initial Maximum Heater Capacity [W]", this->MaxCapacity);
   11287             :             }
   11288             :         }
   11289             :     }
   11290             : 
   11291         731 :     if (this->MaxCapacityWasAutoSized) this->setBackupElementCapacity(state);
   11292             : 
   11293         731 :     if ((this->VolumeWasAutoSized) && (this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) &&
   11294           0 :         state.dataPlnt->PlantFirstSizesOkayToFinalize) { // might set height
   11295           0 :         if ((this->HeightWasAutoSized) && (!this->VolumeWasAutoSized)) {
   11296           0 :             this->Height = std::pow((4.0 * this->Volume * pow_2(this->Sizing.HeightAspectRatio)) / DataGlobalConstants::Pi, 0.3333333333333333);
   11297           0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11298           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Height [m]", this->Height);
   11299             :             }
   11300           0 :             if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11301           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Initial Tank Height [m]", this->Height);
   11302             :             }
   11303             :         }
   11304             :     }
   11305         731 : }
   11306             : 
   11307         731 : void WaterThermalTankData::SizeDemandSidePlantConnections(EnergyPlusData &state)
   11308             : {
   11309             : 
   11310             :     // SUBROUTINE INFORMATION:
   11311             :     //       AUTHOR         Brent Griffith
   11312             :     //       DATE WRITTEN   October 2007
   11313             :     //       MODIFIED       na
   11314             :     //       RE-ENGINEERED  na
   11315             : 
   11316             :     // PURPOSE OF THIS SUBROUTINE:
   11317             :     // This subroutine is for sizing water heater plant connection flow rates
   11318             :     // on the demand side that have not been specified in the input.
   11319             : 
   11320             :     // METHODOLOGY EMPLOYED:
   11321             :     // For water heater sides on the Demand side, hot water flow rates are modeled entirely from user input data
   11322             :     // because the plant loop is not yet set up nor is plant sizing info populated.
   11323             :     // sizing is done by calculating an initial
   11324             :     //  recovery rate that if continued would reheat tank in user specified amount of time.
   11325             :     //  initial and final tank temperatures are 14.44 and reheat to 57.22 (values from CalcStandardRatings routine)
   11326             : 
   11327             :     static constexpr std::string_view RoutineName("SizeDemandSidePlantConnections");
   11328             : 
   11329         731 :     auto &PlantSizData(state.dataSize->PlantSizData);
   11330             : 
   11331         731 :     Real64 tankRecoverhours = this->SizingRecoveryTime;
   11332         731 :     bool ErrorsFound = false;
   11333         731 :     Real64 tmpUseDesignVolFlowRate = this->UseDesignVolFlowRate;
   11334         731 :     Real64 tmpSourceDesignVolFlowRate = this->SourceDesignVolFlowRate;
   11335             : 
   11336             :     Real64 Tstart;
   11337             :     Real64 Tfinish;
   11338         731 :     if (!this->IsChilledWaterTank) {
   11339         686 :         Tstart = 14.44;
   11340         686 :         Tfinish = 57.22;
   11341             :     } else {
   11342          45 :         Tstart = 14.44;
   11343          45 :         Tfinish = 9.0;
   11344             :     }
   11345             : 
   11346             :     // determine tank volume to use for sizing.
   11347         731 :     Real64 TankVolume = this->Volume;
   11348         731 :     if (this->VolumeWasAutoSized) {
   11349          20 :         TankVolume = this->Sizing.NominalVolForSizingDemandSideFlow;
   11350             :     }
   11351             : 
   11352         731 :     if (this->UseInletNode > 0) {
   11353         731 :         if (this->UseDesignVolFlowRateWasAutoSized) {
   11354         671 :             int PltSizNum = this->UseSidePlantSizNum;
   11355         671 :             if (PltSizNum > 0) { // we have a Plant Sizing Object
   11356         671 :                 if (this->UseSidePlantLoc.loopSideNum == DataPlant::LoopSideLocation::Demand) {
   11357             :                     // probably shouldn't come here as Use side is unlikley to be on demand side (?)
   11358             :                     // but going to treat component with symetry so if connections are reversed it'll still work
   11359             :                     // choose a flow rate that will allow the entire volume of the tank to go from 14.44 to 57.22 C
   11360             :                     // in user specified hours.
   11361             :                     //  using the plant inlet design temp for sizing.
   11362           0 :                     Real64 Tpdesign = PlantSizData(PltSizNum).ExitTemp;
   11363           0 :                     Real64 eff = this->UseEffectiveness;
   11364           0 :                     if ((Tpdesign >= 58.0) && (!this->IsChilledWaterTank)) {
   11365           0 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11366           0 :                             this->UseDesignVolFlowRate = -1.0 * (TankVolume / (tankRecoverhours * DataGlobalConstants::SecInHour * eff)) *
   11367           0 :                                                          std::log((Tpdesign - Tfinish) / (Tpdesign - Tstart));
   11368             :                         } else {
   11369           0 :                             tmpUseDesignVolFlowRate = -1.0 * (TankVolume / (tankRecoverhours * DataGlobalConstants::SecInHour * eff)) *
   11370           0 :                                                       std::log((Tpdesign - Tfinish) / (Tpdesign - Tstart));
   11371             :                         }
   11372           0 :                     } else if ((Tpdesign <= 8.0) && (this->IsChilledWaterTank)) {
   11373           0 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11374           0 :                             this->UseDesignVolFlowRate = -1.0 * (TankVolume / (tankRecoverhours * DataGlobalConstants::SecInHour * eff)) *
   11375           0 :                                                          std::log((Tpdesign - Tfinish) / (Tpdesign - Tstart));
   11376             :                         } else {
   11377           0 :                             tmpUseDesignVolFlowRate = -1.0 * (TankVolume / (tankRecoverhours * DataGlobalConstants::SecInHour * eff)) *
   11378           0 :                                                       std::log((Tpdesign - Tfinish) / (Tpdesign - Tstart));
   11379             :                         }
   11380             :                     } else {
   11381           0 :                         if (!this->IsChilledWaterTank) {
   11382             :                             // plant sizing object design temperature is set too low throw warning.
   11383           0 :                             ShowSevereError(state,
   11384             :                                             "Autosizing of Use side water heater design flow rate requires Sizing:Plant object to have an exit "
   11385             :                                             "temperature >= 58C");
   11386           0 :                             ShowContinueError(state, "Occurs for water heater object=" + this->Name);
   11387             :                         } else {
   11388             :                             // plant sizing object design temperature is set too hi throw warning.
   11389           0 :                             ShowSevereError(state,
   11390             :                                             "Autosizing of Use side chilled water tank design flow rate requires Sizing:Plant object to have an "
   11391             :                                             "exit temperature <= 8C");
   11392           0 :                             ShowContinueError(state, "Occurs for chilled water storage tank object=" + this->Name);
   11393             :                         }
   11394           0 :                         ErrorsFound = true;
   11395             :                     }
   11396           0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11397           0 :                         BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Use Side Design Flow Rate [m3/s]", this->UseDesignVolFlowRate);
   11398             :                     }
   11399           0 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11400           0 :                         BaseSizer::reportSizerOutput(
   11401           0 :                             state, this->Type, this->Name, "Initial Use Side Design Flow Rate [m3/s]", this->UseDesignVolFlowRate);
   11402             :                     }
   11403           0 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11404           0 :                         PlantUtilities::RegisterPlantCompDesignFlow(state, this->UseInletNode, this->UseDesignVolFlowRate);
   11405             :                     } else {
   11406           0 :                         PlantUtilities::RegisterPlantCompDesignFlow(state, this->UseInletNode, tmpUseDesignVolFlowRate);
   11407             :                     }
   11408           0 :                     Real64 rho = FluidProperties::GetDensityGlycol(state,
   11409           0 :                                                                    state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
   11410             :                                                                    DataGlobalConstants::InitConvTemp,
   11411           0 :                                                                    state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
   11412           0 :                                                                    RoutineName);
   11413           0 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11414           0 :                         this->PlantUseMassFlowRateMax = this->UseDesignVolFlowRate * rho;
   11415             :                     } else {
   11416           0 :                         this->PlantUseMassFlowRateMax = tmpUseDesignVolFlowRate * rho;
   11417             :                     }
   11418             :                 } // Demand side
   11419             :             } else {
   11420             :                 // do nothing
   11421             :             } // plant sizing object
   11422             : 
   11423             :         } else {
   11424             :             // not autosized - report flow to RegisterPlantCompDesignFlow for supply side component sizing
   11425          60 :             PlantUtilities::RegisterPlantCompDesignFlow(state, this->UseInletNode, this->UseDesignVolFlowRate);
   11426             :             Real64 rho;
   11427          60 :             if (this->UseSidePlantLoc.loopNum > 0) {
   11428         120 :                 rho = FluidProperties::GetDensityGlycol(state,
   11429          60 :                                                         state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidName,
   11430             :                                                         DataGlobalConstants::InitConvTemp,
   11431          60 :                                                         state.dataPlnt->PlantLoop(this->UseSidePlantLoc.loopNum).FluidIndex,
   11432             :                                                         RoutineName);
   11433             :             } else {
   11434           0 :                 rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, DataGlobalConstants::InitConvTemp, this->waterIndex, RoutineName);
   11435             :             }
   11436          60 :             this->PlantUseMassFlowRateMax = this->UseDesignVolFlowRate * rho;
   11437             :         } // autosizing needed.
   11438             :     }     // connected to plant
   11439             : 
   11440         731 :     if (this->SourceInletNode > 0) {
   11441         250 :         if (this->SourceDesignVolFlowRateWasAutoSized) {
   11442         115 :             int PltSizNum = this->SourceSidePlantSizNum;
   11443         115 :             if (PltSizNum > 0) {
   11444         100 :                 if (this->SrcSidePlantLoc.loopSideNum == DataPlant::LoopSideLocation::Demand) {
   11445             :                     //  choose a flow rate that will allow the entire volume of the tank to go from 14.44 to 57.22 C
   11446             :                     // in user specified hours.
   11447             :                     //  using the plant inlet design temp for sizing.
   11448          60 :                     Real64 Tpdesign = PlantSizData(PltSizNum).ExitTemp;
   11449          60 :                     Real64 eff = this->SourceEffectiveness;
   11450          60 :                     if ((Tpdesign >= 58.0) && (!this->IsChilledWaterTank)) {
   11451             : 
   11452          60 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11453          12 :                             this->SourceDesignVolFlowRate = -1.0 * (TankVolume / (tankRecoverhours * DataGlobalConstants::SecInHour * eff)) *
   11454           6 :                                                             std::log((Tpdesign - Tfinish) / (Tpdesign - Tstart));
   11455             :                         } else {
   11456          48 :                             tmpSourceDesignVolFlowRate = -1.0 * (TankVolume / (tankRecoverhours * DataGlobalConstants::SecInHour * eff)) *
   11457          24 :                                                          std::log((Tpdesign - Tfinish) / (Tpdesign - Tstart));
   11458             :                         }
   11459          30 :                     } else if ((Tpdesign <= 8.0) && (this->IsChilledWaterTank)) {
   11460          60 :                         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11461          12 :                             this->SourceDesignVolFlowRate = -1.0 * (TankVolume / (tankRecoverhours * DataGlobalConstants::SecInHour * eff)) *
   11462           6 :                                                             std::log((Tpdesign - Tfinish) / (Tpdesign - Tstart));
   11463             :                         } else {
   11464          48 :                             tmpSourceDesignVolFlowRate = -1.0 * (TankVolume / (tankRecoverhours * DataGlobalConstants::SecInHour * eff)) *
   11465          24 :                                                          std::log((Tpdesign - Tfinish) / (Tpdesign - Tstart));
   11466             :                         }
   11467             :                     } else {
   11468           0 :                         if (!this->IsChilledWaterTank) {
   11469             :                             // plant sizing object design temperature is set too low throw warning.
   11470           0 :                             ShowSevereError(state,
   11471             :                                             "Autosizing of Source side water heater design flow rate requires Sizing:Plant object to have an "
   11472             :                                             "exit temperature >= 58C");
   11473           0 :                             ShowContinueError(state, "Occurs for WaterHeater:Mixed object=" + this->Name);
   11474             :                         } else {
   11475             :                             // plant sizing object design temperature is set too hi throw warning.
   11476           0 :                             ShowSevereError(state,
   11477             :                                             "Autosizing of Source side chilled water tank design flow rate requires Sizing:Plant object to have "
   11478             :                                             "an exit temperature <= 8C");
   11479           0 :                             ShowContinueError(state, "Occurs for chilled water storage tank object=" + this->Name);
   11480             :                         }
   11481           0 :                         ErrorsFound = true;
   11482             :                     }
   11483          60 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
   11484          24 :                         BaseSizer::reportSizerOutput(
   11485          12 :                             state, this->Type, this->Name, "Source Side Design Flow Rate [m3/s]", this->SourceDesignVolFlowRate);
   11486             :                     }
   11487          60 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
   11488           0 :                         BaseSizer::reportSizerOutput(
   11489           0 :                             state, this->Type, this->Name, "Initial Source Side Design Flow Rate [m3/s]", this->SourceDesignVolFlowRate);
   11490             :                     }
   11491          60 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11492          12 :                         PlantUtilities::RegisterPlantCompDesignFlow(state, this->SourceInletNode, this->SourceDesignVolFlowRate);
   11493             :                     } else {
   11494          48 :                         PlantUtilities::RegisterPlantCompDesignFlow(state, this->SourceInletNode, tmpSourceDesignVolFlowRate);
   11495             :                     }
   11496         120 :                     Real64 rho = FluidProperties::GetDensityGlycol(state,
   11497          60 :                                                                    state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidName,
   11498             :                                                                    DataGlobalConstants::InitConvTemp,
   11499          60 :                                                                    state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidIndex,
   11500          60 :                                                                    RoutineName);
   11501          60 :                     if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
   11502          12 :                         this->PlantSourceMassFlowRateMax = this->SourceDesignVolFlowRate * rho;
   11503             :                     } else {
   11504          48 :                         this->PlantSourceMassFlowRateMax = tmpSourceDesignVolFlowRate * rho;
   11505             :                     }
   11506             :                 } // demand side
   11507             :             } else {
   11508             :                 // do nothing
   11509             :             } // plant sizing object
   11510             : 
   11511             :         } else {
   11512             :             // not autosized - report flow to RegisterPlantCompDesignFlow for supply side component sizing
   11513         135 :             PlantUtilities::RegisterPlantCompDesignFlow(state, this->SourceInletNode, this->SourceDesignVolFlowRate);
   11514             :             Real64 rho;
   11515         135 :             if (this->SrcSidePlantLoc.loopNum > 0) {
   11516         200 :                 rho = FluidProperties::GetDensityGlycol(state,
   11517         100 :                                                         state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidName,
   11518             :                                                         DataGlobalConstants::InitConvTemp,
   11519         100 :                                                         state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidIndex,
   11520             :                                                         RoutineName);
   11521             :             } else {
   11522          35 :                 rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, DataGlobalConstants::InitConvTemp, this->waterIndex, RoutineName);
   11523             :             }
   11524         135 :             this->PlantSourceMassFlowRateMax = this->SourceDesignVolFlowRate * rho;
   11525             :         } // autosizing needed.
   11526             :     }     // connected to plant
   11527             : 
   11528         731 :     if (ErrorsFound) {
   11529           0 :         ShowFatalError(state, "Preceding sizing errors cause program termination");
   11530             :     }
   11531         731 : }
   11532             : 
   11533          49 : void WaterThermalTankData::SizeStandAloneWaterHeater(EnergyPlusData &state)
   11534             : {
   11535             : 
   11536             :     // SUBROUTINE INFORMATION:
   11537             :     //       AUTHOR         B. Griffith
   11538             :     //       DATE WRITTEN   October 2013
   11539             :     //       MODIFIED       na
   11540             :     //       RE-ENGINEERED  na
   11541             : 
   11542             :     // PURPOSE OF THIS SUBROUTINE:
   11543             :     // allow autosizing of tank volume and heat capacity for stand alone tanks
   11544             : 
   11545             :     // METHODOLOGY EMPLOYED:
   11546             :     // same as for plant connected water heaters, only draws are scheduled.
   11547             : 
   11548             :     // SUBROUTINE PARAMETER DEFINITIONS:
   11549          49 :     Real64 constexpr GalTocubicMeters(0.0037854);
   11550          49 :     Real64 constexpr kBtuPerHrToWatts(293.1);
   11551             :     static constexpr std::string_view RoutineName("SizeStandAloneWaterHeater");
   11552             : 
   11553          49 :     Real64 Tstart = 14.44;
   11554          49 :     Real64 Tfinish = 57.22;
   11555          49 :     Real64 tmpTankVolume = this->Volume;
   11556          49 :     Real64 tmpMaxCapacity = this->MaxCapacity;
   11557             : 
   11558          49 :     if (this->VolumeWasAutoSized || this->MaxCapacityWasAutoSized) {
   11559             : 
   11560           0 :         switch (this->Sizing.DesignMode) {
   11561             : 
   11562           0 :         case SizingMode::PeakDraw: {
   11563             :             // get draw rate from maximum in schedule
   11564           0 :             Real64 rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, DataGlobalConstants::InitConvTemp, this->waterIndex, RoutineName);
   11565           0 :             Real64 DrawDesignVolFlowRate = ScheduleManager::GetScheduleMaxValue(state, this->FlowRateSchedule) * this->MassFlowRateMax / rho;
   11566             : 
   11567           0 :             if (this->VolumeWasAutoSized) {
   11568           0 :                 tmpTankVolume = this->Sizing.TankDrawTime * DrawDesignVolFlowRate * DataGlobalConstants::SecInHour; // hours | m3/s | (3600 s/1 hour)
   11569           0 :                 this->Volume = tmpTankVolume;
   11570           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Volume [m3]", this->Volume);
   11571             :             }
   11572           0 :             if (this->MaxCapacityWasAutoSized) {
   11573           0 :                 if (this->Sizing.RecoveryTime > 0.0) {
   11574           0 :                     rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11575             :                     Real64 Cp =
   11576           0 :                         FluidProperties::GetSpecificHeatGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11577             : 
   11578           0 :                     tmpMaxCapacity = (this->Volume * rho * Cp * (Tfinish - Tstart)) /
   11579           0 :                                      (this->Sizing.RecoveryTime * DataGlobalConstants::SecInHour); // m3 | kg/m3 | J/Kg/K | K | seconds
   11580             :                 } else {
   11581           0 :                     ShowFatalError(state,
   11582           0 :                                    "SizeStandAloneWaterHeater: Tank=\"" + this->Name +
   11583             :                                        "\", requested sizing for max capacity but entered Recovery Time is zero.");
   11584             :                 }
   11585           0 :                 this->MaxCapacity = tmpMaxCapacity;
   11586           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Maximum Heater Capacity [W]", this->MaxCapacity);
   11587             :             }
   11588             : 
   11589           0 :             break;
   11590             :         }
   11591           0 :         case SizingMode::ResidentialMin: {
   11592             :             // assume can propagate rules for gas to other fuels.
   11593           0 :             bool FuelTypeIsLikeGas = false;
   11594           0 :             switch (this->FuelType) {
   11595           0 :             case Fuel::NaturalGas:
   11596             :             case Fuel::Diesel:
   11597             :             case Fuel::Gasoline:
   11598             :             case Fuel::Coal:
   11599             :             case Fuel::FuelOilNo1:
   11600             :             case Fuel::FuelOilNo2:
   11601             :             case Fuel::Propane:
   11602             :             case Fuel::Steam:
   11603             :             case Fuel::OtherFuel1:
   11604             :             case Fuel::OtherFuel2:
   11605             :             case Fuel::DistrictHeating:
   11606           0 :                 FuelTypeIsLikeGas = true;
   11607           0 :                 break;
   11608           0 :             default: // FuelTypeIsLikeGas stays false
   11609           0 :                 break;
   11610             :             }
   11611             : 
   11612           0 :             if (this->Sizing.NumberOfBedrooms == 1) {
   11613           0 :                 if (this->FuelType == Fuel::Electricity) {
   11614           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 20.0 * GalTocubicMeters;
   11615           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 2.5 * 1000.0; // 2.5 kW
   11616           0 :                 } else if (FuelTypeIsLikeGas) {
   11617           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 20.0 * GalTocubicMeters;
   11618           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 27.0 * kBtuPerHrToWatts; // 27kBtu/hr
   11619             :                 }
   11620             : 
   11621           0 :             } else if (this->Sizing.NumberOfBedrooms == 2) {
   11622           0 :                 if (this->Sizing.NumberOfBathrooms <= 1.5) {
   11623           0 :                     if (this->FuelType == Fuel::Electricity) {
   11624           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 30.0 * GalTocubicMeters;
   11625           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 3.5 * 1000.0; // 3.5 kW
   11626           0 :                     } else if (FuelTypeIsLikeGas) {
   11627           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 30.0 * GalTocubicMeters;
   11628           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 36.0 * kBtuPerHrToWatts; // 36 kBtu/hr
   11629             :                     }
   11630           0 :                 } else if ((this->Sizing.NumberOfBathrooms > 1.5) && (this->Sizing.NumberOfBathrooms < 3.0)) {
   11631           0 :                     if (this->FuelType == Fuel::Electricity) {
   11632           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 40.0 * GalTocubicMeters;
   11633           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 4.5 * 1000.0; // 4.5 kW
   11634           0 :                     } else if (FuelTypeIsLikeGas) {
   11635           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 30.0 * GalTocubicMeters;
   11636           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 36.0 * kBtuPerHrToWatts; // 36 kBtu/hr
   11637             :                     }
   11638           0 :                 } else if (this->Sizing.NumberOfBathrooms >= 3.0) {
   11639           0 :                     if (this->FuelType == Fuel::Electricity) {
   11640           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   11641           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   11642           0 :                     } else if (FuelTypeIsLikeGas) {
   11643           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 40.0 * GalTocubicMeters;
   11644           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 36.0 * kBtuPerHrToWatts; // 36 kBtu/hr
   11645             :                     }
   11646             :                 }
   11647           0 :             } else if (this->Sizing.NumberOfBedrooms == 3) {
   11648           0 :                 if (this->Sizing.NumberOfBathrooms <= 1.5) {
   11649           0 :                     if (this->FuelType == Fuel::Electricity) {
   11650           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 40.0 * GalTocubicMeters;
   11651           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 4.5 * 1000.0; // 4.5 kW
   11652           0 :                     } else if (FuelTypeIsLikeGas) {
   11653           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 30.0 * GalTocubicMeters;
   11654           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 36.0 * kBtuPerHrToWatts; // 36 kBtu/hr
   11655             :                     }
   11656           0 :                 } else if ((this->Sizing.NumberOfBathrooms > 1.5) && (this->Sizing.NumberOfBathrooms < 3.0)) {
   11657           0 :                     if (this->FuelType == Fuel::Electricity) {
   11658           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   11659           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   11660           0 :                     } else if (FuelTypeIsLikeGas) {
   11661           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 40.0 * GalTocubicMeters;
   11662           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 36.0 * kBtuPerHrToWatts; // 36 kBtu/hr
   11663             :                     }
   11664           0 :                 } else if (this->Sizing.NumberOfBathrooms >= 3.0) {
   11665           0 :                     if (this->FuelType == Fuel::Electricity) {
   11666           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   11667           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   11668           0 :                     } else if (FuelTypeIsLikeGas) {
   11669           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 40.0 * GalTocubicMeters;
   11670           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 38.0 * kBtuPerHrToWatts; // 38 kBtu/hr
   11671             :                     }
   11672             :                 }
   11673           0 :             } else if (this->Sizing.NumberOfBedrooms == 4) {
   11674           0 :                 if (this->Sizing.NumberOfBathrooms <= 1.5) {
   11675           0 :                     if (this->FuelType == Fuel::Electricity) {
   11676           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   11677           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   11678           0 :                     } else if (FuelTypeIsLikeGas) {
   11679           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 40.0 * GalTocubicMeters;
   11680           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 36.0 * kBtuPerHrToWatts; // 36 kBtu/hr
   11681             :                     }
   11682           0 :                 } else if ((this->Sizing.NumberOfBathrooms > 1.5) && (this->Sizing.NumberOfBathrooms < 3.0)) {
   11683           0 :                     if (this->FuelType == Fuel::Electricity) {
   11684           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   11685           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   11686           0 :                     } else if (FuelTypeIsLikeGas) {
   11687           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 40.0 * GalTocubicMeters;
   11688           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 38.0 * kBtuPerHrToWatts; // 38 kBtu/hr
   11689             :                     }
   11690           0 :                 } else if (this->Sizing.NumberOfBathrooms >= 3.0) {
   11691           0 :                     if (this->FuelType == Fuel::Electricity) {
   11692           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 66.0 * GalTocubicMeters;
   11693           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   11694           0 :                     } else if (FuelTypeIsLikeGas) {
   11695           0 :                         if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   11696           0 :                         if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 38.0 * kBtuPerHrToWatts; // 38 kBtu/hr
   11697             :                     }
   11698             :                 }
   11699           0 :             } else if (this->Sizing.NumberOfBedrooms == 5) {
   11700           0 :                 if (this->FuelType == Fuel::Electricity) {
   11701           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 66.0 * GalTocubicMeters;
   11702           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   11703           0 :                 } else if (FuelTypeIsLikeGas) {
   11704           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   11705           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 47.0 * kBtuPerHrToWatts; // 47 kBtu/hr
   11706             :                 }
   11707           0 :             } else if (this->Sizing.NumberOfBedrooms >= 6) {
   11708           0 :                 if (this->FuelType == Fuel::Electricity) {
   11709           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 66.0 * GalTocubicMeters;
   11710           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 5.5 * 1000.0; // 5.5 kW
   11711           0 :                 } else if (FuelTypeIsLikeGas) {
   11712           0 :                     if (this->VolumeWasAutoSized) tmpTankVolume = 50.0 * GalTocubicMeters;
   11713           0 :                     if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 50.0 * kBtuPerHrToWatts; // 50 kBtu/hr
   11714             :                 }
   11715             :             }
   11716           0 :             if (this->VolumeWasAutoSized) {
   11717           0 :                 this->Volume = tmpTankVolume;
   11718           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Volume [m3]", this->Volume);
   11719             :             }
   11720           0 :             if (this->MaxCapacityWasAutoSized) {
   11721           0 :                 this->MaxCapacity = tmpMaxCapacity;
   11722           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Maximum Heater Capacity [W]", this->MaxCapacity);
   11723             :             }
   11724             : 
   11725           0 :             break;
   11726             :         }
   11727           0 :         case SizingMode::PerPerson: {
   11728             :             // how to get number of people?
   11729             : 
   11730           0 :             Real64 SumPeopleAllZones = sum(state.dataHeatBal->Zone, &DataHeatBalance::ZoneData::TotOccupants);
   11731           0 :             if (this->VolumeWasAutoSized) {
   11732           0 :                 tmpTankVolume = this->Sizing.TankCapacityPerPerson * SumPeopleAllZones;
   11733             :             }
   11734           0 :             if (this->MaxCapacityWasAutoSized) {
   11735           0 :                 Real64 rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11736           0 :                 Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11737           0 :                 tmpMaxCapacity = SumPeopleAllZones * this->Sizing.RecoveryCapacityPerPerson * (Tfinish - Tstart) *
   11738           0 :                                  (1.0 / DataGlobalConstants::SecInHour) * rho * Cp; // m3/hr/person | delta T  in K | 1 hr/ 3600 s | kg/m3 | J/Kg/k
   11739             :             }
   11740             : 
   11741           0 :             if (this->VolumeWasAutoSized) {
   11742           0 :                 this->Volume = tmpTankVolume;
   11743           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Volume [m3]", this->Volume);
   11744             :             }
   11745           0 :             if (this->MaxCapacityWasAutoSized) {
   11746           0 :                 this->MaxCapacity = tmpMaxCapacity;
   11747           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Maximum Heater Capacity [W]", this->MaxCapacity);
   11748             :             }
   11749             : 
   11750           0 :             break;
   11751             :         }
   11752           0 :         case SizingMode::PerFloorArea: {
   11753             : 
   11754           0 :             Real64 SumFloorAreaAllZones = sum(state.dataHeatBal->Zone, &DataHeatBalance::ZoneData::FloorArea);
   11755           0 :             if (this->VolumeWasAutoSized) {
   11756           0 :                 tmpTankVolume = this->Sizing.TankCapacityPerArea * SumFloorAreaAllZones;
   11757             :             }
   11758             : 
   11759           0 :             if (this->MaxCapacityWasAutoSized) {
   11760           0 :                 Real64 rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11761           0 :                 Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11762           0 :                 tmpMaxCapacity = SumFloorAreaAllZones * this->Sizing.RecoveryCapacityPerArea * (Tfinish - Tstart) *
   11763           0 :                                  (1.0 / DataGlobalConstants::SecInHour) * rho * Cp; // m2 | m3/hr/m2 | delta T  in K | 1 hr/ 3600 s | kg/m3 | J/Kg/k
   11764             :             }
   11765           0 :             if (this->VolumeWasAutoSized) {
   11766           0 :                 this->Volume = tmpTankVolume;
   11767           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Volume [m3]", this->Volume);
   11768             :             }
   11769           0 :             if (this->MaxCapacityWasAutoSized) {
   11770           0 :                 this->MaxCapacity = tmpMaxCapacity;
   11771           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Maximum Heater Capacity [W]", this->MaxCapacity);
   11772             :             }
   11773           0 :             break;
   11774             :         }
   11775           0 :         case SizingMode::PerUnit: {
   11776             : 
   11777           0 :             if (this->VolumeWasAutoSized) tmpTankVolume = this->Sizing.TankCapacityPerUnit * this->Sizing.NumberOfUnits;
   11778             : 
   11779           0 :             if (this->MaxCapacityWasAutoSized) {
   11780           0 :                 Real64 rho = FluidProperties::GetDensityGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11781           0 :                 Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state, fluidNameWater, ((Tfinish + Tstart) / 2.0), this->waterIndex, RoutineName);
   11782           0 :                 tmpMaxCapacity = this->Sizing.NumberOfUnits * this->Sizing.RecoveryCapacityPerUnit * (Tfinish - Tstart) *
   11783           0 :                                  (1.0 / DataGlobalConstants::SecInHour) * rho * Cp; // m3/hr/ea | delta T  in K | 1 hr/ 3600 s | kg/m3 | J/Kg/k
   11784             :             }
   11785             : 
   11786           0 :             if (this->VolumeWasAutoSized) {
   11787           0 :                 this->Volume = tmpTankVolume;
   11788           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Volume [m3]", this->Volume);
   11789             :             }
   11790           0 :             if (this->MaxCapacityWasAutoSized) {
   11791           0 :                 this->MaxCapacity = tmpMaxCapacity;
   11792           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Maximum Heater Capacity [W]", this->MaxCapacity);
   11793             :             }
   11794           0 :             break;
   11795             :         }
   11796           0 :         case SizingMode::PerSolarColArea: {
   11797           0 :             this->Sizing.TotalSolarCollectorArea = 0.0;
   11798           0 :             for (int CollectorNum = 1; CollectorNum <= state.dataSolarCollectors->NumOfCollectors; ++CollectorNum) {
   11799           0 :                 this->Sizing.TotalSolarCollectorArea += state.dataSurface->Surface(state.dataSolarCollectors->Collector(CollectorNum).Surface).Area;
   11800             :             }
   11801             : 
   11802           0 :             if (this->VolumeWasAutoSized) tmpTankVolume = this->Sizing.TotalSolarCollectorArea * this->Sizing.TankCapacityPerCollectorArea;
   11803           0 :             if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 0.0;
   11804           0 :             if (this->VolumeWasAutoSized) {
   11805           0 :                 this->Volume = tmpTankVolume;
   11806           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Volume [m3]", this->Volume);
   11807             :             }
   11808           0 :             if (this->MaxCapacityWasAutoSized) {
   11809           0 :                 this->MaxCapacity = tmpMaxCapacity;
   11810           0 :                 BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Maximum Heater Capacity [W]", this->MaxCapacity);
   11811             :             }
   11812           0 :             break;
   11813             :         }
   11814           0 :         default:
   11815           0 :             if (this->MaxCapacityWasAutoSized) this->setBackupElementCapacity(state);
   11816           0 :             break;
   11817             :         }
   11818             :     }
   11819          49 : }
   11820             : 
   11821     6113098 : void WaterThermalTankData::UpdateWaterThermalTank(EnergyPlusData &state)
   11822             : {
   11823             : 
   11824             :     // SUBROUTINE INFORMATION:
   11825             :     //       AUTHOR         Brandon Anderson
   11826             :     //       DATE WRITTEN   May 2000
   11827             :     //       MODIFIED       na
   11828             :     //                      Nov 2011, BAN; removed the use and source heat rate re-calculation for stratified tank
   11829             :     //                                     for energy conservation verification.
   11830             :     //       RE-ENGINEERED  Feb 2004, PGE
   11831             : 
   11832             :     // PURPOSE OF THIS SUBROUTINE:
   11833             :     // Updates the node variables with local variables.
   11834             : 
   11835     6113098 :     if (this->UseInletNode > 0 && this->UseOutletNode > 0) {
   11836     5666446 :         state.dataLoopNodes->Node(UseOutletNode) = state.dataLoopNodes->Node(this->UseInletNode); // this could wipe out setpoints on outlet node
   11837             : 
   11838     5666446 :         state.dataLoopNodes->Node(this->UseOutletNode).Temp = this->UseOutletTemp;
   11839             :     }
   11840             : 
   11841     6113098 :     if (this->SourceInletNode > 0 && this->SourceOutletNode > 0) {
   11842     1991072 :         state.dataLoopNodes->Node(this->SourceOutletNode) = state.dataLoopNodes->Node(this->SourceInletNode);
   11843             : 
   11844     1991072 :         state.dataLoopNodes->Node(this->SourceOutletNode).Temp = this->SourceOutletTemp;
   11845             :     }
   11846     6113098 : }
   11847             : 
   11848     6113098 : void WaterThermalTankData::ReportWaterThermalTank(EnergyPlusData &state)
   11849             : {
   11850             : 
   11851             :     // SUBROUTINE INFORMATION:
   11852             :     //       AUTHOR         Brandon Anderson
   11853             :     //       DATE WRITTEN   May 2000
   11854             :     //       MODIFIED       na
   11855             :     //       RE-ENGINEERED  Feb 2004, PGE
   11856             : 
   11857     6113098 :     Real64 SecInTimeStep = state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
   11858             : 
   11859     6113098 :     this->UnmetEnergy = this->UnmetRate * SecInTimeStep;
   11860     6113098 :     this->LossEnergy = this->LossRate * SecInTimeStep;
   11861     6113098 :     this->FlueLossEnergy = this->FlueLossRate * SecInTimeStep;
   11862     6113098 :     this->UseEnergy = this->UseRate * SecInTimeStep;
   11863     6113098 :     this->TotalDemandEnergy = this->TotalDemandRate * SecInTimeStep;
   11864     6113098 :     this->SourceEnergy = this->SourceRate * SecInTimeStep;
   11865     6113098 :     this->HeaterEnergy = this->HeaterRate * SecInTimeStep;
   11866     6113098 :     this->HeaterEnergy1 = this->HeaterRate1 * SecInTimeStep;
   11867     6113098 :     this->HeaterEnergy2 = this->HeaterRate2 * SecInTimeStep;
   11868     6113098 :     this->FuelEnergy = this->FuelRate * SecInTimeStep;
   11869     6113098 :     this->VentEnergy = this->VentRate * SecInTimeStep;
   11870     6113098 :     this->OffCycParaFuelEnergy = this->OffCycParaFuelRate * SecInTimeStep;
   11871     6113098 :     this->OffCycParaEnergyToTank = this->OffCycParaRateToTank * SecInTimeStep;
   11872     6113098 :     this->OnCycParaFuelEnergy = this->OnCycParaFuelRate * SecInTimeStep;
   11873     6113098 :     this->OnCycParaEnergyToTank = this->OnCycParaRateToTank * SecInTimeStep;
   11874     6113098 :     this->NetHeatTransferEnergy = this->NetHeatTransferRate * SecInTimeStep;
   11875     6113098 :     this->VolumeConsumed = this->VolFlowRate * SecInTimeStep;
   11876     6113098 : }
   11877             : 
   11878         331 : void WaterThermalTankData::CalcStandardRatings(EnergyPlusData &state)
   11879             : {
   11880             : 
   11881             :     // SUBROUTINE INFORMATION:
   11882             :     //       AUTHOR         Peter Graham Ellis
   11883             :     //       DATE WRITTEN   January 2005
   11884             :     //       MODIFIED       R. Raustad, July 2005 - added HPWH to ratings procedure
   11885             :     //       RE-ENGINEERED  na
   11886             : 
   11887             :     // PURPOSE OF THIS SUBROUTINE:
   11888             :     // Calculates the water heater standard ratings, such as Energy Factor and Recovery Efficiency.  Results are written
   11889             :     // to the EIO file.  Standard ratings are not calculated for storage-only tanks, i.e., MaxCapacity = 0, nor for Integrated Heat Pumps
   11890             : 
   11891             :     // METHODOLOGY EMPLOYED:
   11892             :     // Water heater inputs are set to the specified test conditions. For HPWHs, the heating capacity and COP are assumed
   11893             :     // to be the primary element in the water heater and are used during the rating procedure.  CalcWaterThermalTankMixed
   11894             :     // is iteratively called in a self-contained, 24 hour simulation of the standard test procedure.
   11895             : 
   11896             :     // REFERENCES:
   11897             :     // Title 10, Code of Federal Regulations, Part 430- Energy Conservation Program for Consumer Products, Appendix E to
   11898             :     // Subpart B- Uniform Test Procedure for Measuring the Energy Consumption of Water Heaters, January 1, 2004.
   11899             : 
   11900         331 :     if (this->AlreadyRated) { // bail we already did this one
   11901         145 :         return;
   11902             :     }
   11903             : 
   11904             :     bool FirstTimeFlag; // used during HPWH rating procedure
   11905         186 :     bool bIsVSCoil = false;
   11906             :     Real64 RecoveryEfficiency;
   11907             :     Real64 EnergyFactor;
   11908         186 :     Real64 RatedDXCoilTotalCapacity = 0.0;
   11909         186 :     if (this->MaxCapacity > 0.0 || this->HeatPumpNum > 0) {
   11910             :         // Set test conditions
   11911         181 :         this->AmbientTemp = 19.7222;   // 67.5 F
   11912         181 :         this->UseInletTemp = 14.4444;  // 58 F
   11913         181 :         this->SetPointTemp = 57.2222;  // 135 F
   11914         181 :         this->SetPointTemp2 = 57.2222; // 135 F
   11915         181 :         this->TankTemp = 57.2222;      // Initialize tank temperature
   11916         181 :         if (this->Nodes > 0)
   11917         144 :             for (auto &e : this->Node)
   11918         128 :                 e.Temp = 57.2222;
   11919             : 
   11920         181 :         Real64 TotalDrawMass = 0.243402 * Psychrometrics::RhoH2O(DataGlobalConstants::InitConvTemp); // 64.3 gal * rho
   11921         181 :         Real64 DrawMass = TotalDrawMass / 6.0;                                                       // 6 equal draws
   11922         181 :         Real64 SecInTimeStep = state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
   11923         181 :         Real64 DrawMassFlowRate = DrawMass / SecInTimeStep;
   11924         181 :         Real64 FuelEnergy_loc = 0.0;
   11925         181 :         FirstTimeFlag = true;
   11926             : 
   11927         181 :         int TimeStepPerHour = int(1.0 / state.dataHVACGlobal->TimeStepSys);
   11928             :         // Simulate 24 hour test
   11929       22549 :         for (int Step = 1; Step <= TimeStepPerHour * 24; ++Step) {
   11930             : 
   11931       44012 :             if (Step == 1 || Step == (1 + TimeStepPerHour) || Step == (1 + TimeStepPerHour * 2) || Step == (1 + TimeStepPerHour * 3) ||
   11932       43107 :                 Step == (1 + TimeStepPerHour * 4) || Step == (1 + TimeStepPerHour * 5)) { // Hour 1 | Hour 2 | Hour 3 | Hour 4 | Hour 5 | Hour 6
   11933             : 
   11934        1086 :                 this->UseMassFlowRate = DrawMassFlowRate;
   11935             :             } else {
   11936       21282 :                 this->UseMassFlowRate = 0.0;
   11937             :             }
   11938             : 
   11939       22368 :             this->SavedTankTemp = this->TankTemp;
   11940       22368 :             this->SavedMode = this->Mode;
   11941       22368 :             if (this->Nodes > 0) {
   11942       33552 :                 for (auto &e : this->Node)
   11943       30336 :                     e.SavedTemp = e.Temp;
   11944        3216 :                 this->SavedHeaterOn1 = this->HeaterOn1;
   11945        3216 :                 this->SavedHeaterOn2 = this->HeaterOn2;
   11946             :             }
   11947             : 
   11948       22368 :             if (this->HeatPumpNum == 0) {
   11949             : 
   11950       18576 :                 if (this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed) {
   11951       17952 :                     this->CalcWaterThermalTankMixed(state);
   11952             : 
   11953         624 :                 } else if (this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
   11954         624 :                     this->CalcWaterThermalTankStratified(state);
   11955             :                 }
   11956             : 
   11957             :             } else {
   11958             : 
   11959        3792 :                 int HPNum = this->HeatPumpNum;  // Convenience variable
   11960        3792 :                 Real64 AmbientHumRat = 0.00717; // Humidity ratio at 67.5 F / 50% RH
   11961             : 
   11962             :                 //       set the heat pump air- and water-side mass flow rate
   11963        3792 :                 Real64 MdotWater = state.dataWaterThermalTanks->HPWaterHeater(HPNum).OperatingWaterFlowRate * Psychrometrics::RhoH2O(this->TankTemp);
   11964        3792 :                 Real64 mdotAir = state.dataWaterThermalTanks->HPWaterHeater(HPNum).OperatingAirMassFlowRate;
   11965             : 
   11966             :                 // ?? why is HPWH condenser inlet node temp reset inside the for loop? shouldn't it chnage with the tank temp throughout these
   11967             :                 // iterations?
   11968        3792 :                 if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).HPWHType == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterPumped) {
   11969             :                     // set the condenser inlet node mass flow rate and temperature
   11970        2064 :                     state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).CondWaterInletNode).MassFlowRate = MdotWater;
   11971        2064 :                     state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).CondWaterInletNode).Temp = this->TankTemp;
   11972             :                 }
   11973             : 
   11974             :                 //       initialize temperatures for HPWH DX Coil heating capacity and COP curves
   11975        3792 :                 state.dataHVACGlobal->HPWHInletDBTemp = this->AmbientTemp;
   11976        3792 :                 state.dataHVACGlobal->HPWHInletWBTemp =
   11977        7584 :                     Psychrometrics::PsyTwbFnTdbWPb(state, state.dataHVACGlobal->HPWHInletDBTemp, AmbientHumRat, state.dataEnvrn->OutBaroPress);
   11978             : 
   11979             :                 //       set up full air flow on DX coil inlet node
   11980        3792 :                 if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).InletAirMixerNode > 0) {
   11981         288 :                     state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).InletAirMixerNode).MassFlowRate = mdotAir;
   11982         288 :                     state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).InletAirMixerNode).MassFlowRateMaxAvail = mdotAir;
   11983         288 :                     state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).InletAirMixerNode).Temp = this->AmbientTemp;
   11984         288 :                     state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).InletAirMixerNode).HumRat = AmbientHumRat;
   11985         288 :                     state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).InletAirMixerNode).Enthalpy =
   11986         288 :                         Psychrometrics::PsyHFnTdbW(this->AmbientTemp, AmbientHumRat);
   11987             :                 } else {
   11988        3504 :                     if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).OutsideAirNode == 0) {
   11989        1056 :                         state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).HeatPumpAirInletNode).MassFlowRate = mdotAir;
   11990        1056 :                         state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).HeatPumpAirInletNode).MassFlowRateMaxAvail =
   11991             :                             mdotAir;
   11992        1056 :                         state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).HeatPumpAirInletNode).Temp = this->AmbientTemp;
   11993        1056 :                         state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).HeatPumpAirInletNode).HumRat = AmbientHumRat;
   11994        1056 :                         state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).HeatPumpAirInletNode).Enthalpy =
   11995        1056 :                             Psychrometrics::PsyHFnTdbW(this->AmbientTemp, AmbientHumRat);
   11996             :                     } else {
   11997        2448 :                         state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).OutsideAirNode).MassFlowRate = mdotAir;
   11998        2448 :                         state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).OutsideAirNode).MassFlowRateMaxAvail = mdotAir;
   11999        2448 :                         state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).OutsideAirNode).Temp = this->AmbientTemp;
   12000        2448 :                         state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).OutsideAirNode).HumRat = AmbientHumRat;
   12001        2448 :                         state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).OutsideAirNode).Enthalpy =
   12002        2448 :                             Psychrometrics::PsyHFnTdbW(this->AmbientTemp, AmbientHumRat);
   12003             :                     }
   12004             :                 }
   12005             : 
   12006        3792 :                 state.dataHVACGlobal->HPWHCrankcaseDBTemp = this->AmbientTemp;
   12007             : 
   12008        7584 :                 if (UtilityRoutines::SameString(state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilType,
   12009       10752 :                                                 "Coil:WaterHeating:AirToWaterHeatPump:VariableSpeed") ||
   12010        3168 :                     (state.dataWaterThermalTanks->HPWaterHeater(HPNum).bIsIHP)) {
   12011         768 :                     bIsVSCoil = true;
   12012        1536 :                     std::string VSCoilName = state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilName;
   12013         768 :                     int VSCoilNum = state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum;
   12014         768 :                     if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).bIsIHP) {
   12015         144 :                         VSCoilNum =
   12016         144 :                             state.dataIntegratedHP->IntegratedHeatPumps(state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum).SCWHCoilIndex;
   12017         144 :                         VSCoilName =
   12018         144 :                             state.dataIntegratedHP->IntegratedHeatPumps(state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum).SCWHCoilName;
   12019             :                     }
   12020             : 
   12021         768 :                     Real64 RhoWater = Psychrometrics::RhoH2O(this->TankTemp);
   12022         768 :                     auto &HPWH = state.dataWaterThermalTanks->HPWaterHeater(HPNum);
   12023         768 :                     this->SetVSHPWHFlowRates(
   12024             :                         state,
   12025             :                         HPWH,
   12026         768 :                         state.dataVariableSpeedCoils->VarSpeedCoil(state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum).NormSpedLevel,
   12027             :                         1.0,
   12028             :                         RhoWater,
   12029             :                         MdotWater,
   12030             :                         true);
   12031             :                     //       simulate the HPWH coil/fan to find heating capacity
   12032         768 :                     Real64 EMP1 = 0.0;
   12033         768 :                     Real64 EMP2 = 0.0;
   12034         768 :                     Real64 EMP3 = 0.0;
   12035         768 :                     if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanPlacement == DataHVACGlobals::BlowThru) {
   12036             :                         //   simulate fan and DX coil twice
   12037         576 :                         if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
   12038         288 :                             state.dataHVACFan->fanObjs[state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum]->simulate(state, _, _, _, _);
   12039             :                         } else {
   12040         864 :                             Fans::SimulateFanComponents(state,
   12041         288 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanName,
   12042             :                                                         true,
   12043         288 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum);
   12044             :                         }
   12045        1152 :                         VariableSpeedCoils::SimVariableSpeedCoils(
   12046             :                             state,
   12047             :                             VSCoilName,
   12048             :                             VSCoilNum,
   12049             :                             DataHVACGlobals::CycFanCycCoil,
   12050             :                             EMP1,
   12051             :                             EMP2,
   12052             :                             EMP3,
   12053             :                             DataHVACGlobals::CompressorOperation::On,
   12054             :                             1.0,
   12055         576 :                             state.dataVariableSpeedCoils->VarSpeedCoil(state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum).NormSpedLevel,
   12056             :                             1.0,
   12057             :                             0.0,
   12058             :                             0.0,
   12059             :                             1.0);
   12060         576 :                         if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
   12061         288 :                             state.dataHVACFan->fanObjs[state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum]->simulate(state, _, _, _, _);
   12062             :                         } else {
   12063         864 :                             Fans::SimulateFanComponents(state,
   12064         288 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanName,
   12065             :                                                         true,
   12066         288 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum);
   12067             :                         }
   12068        1152 :                         VariableSpeedCoils::SimVariableSpeedCoils(
   12069             :                             state,
   12070             :                             VSCoilName,
   12071             :                             VSCoilNum,
   12072             :                             DataHVACGlobals::CycFanCycCoil,
   12073             :                             EMP1,
   12074             :                             EMP2,
   12075             :                             EMP3,
   12076             :                             DataHVACGlobals::CompressorOperation::On,
   12077             :                             1.0,
   12078         576 :                             state.dataVariableSpeedCoils->VarSpeedCoil(state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum).NormSpedLevel,
   12079             :                             1.0,
   12080             :                             0.0,
   12081             :                             0.0,
   12082             :                             1.0);
   12083             :                     } else {
   12084             :                         //   simulate DX coil and fan twice to pass fan power (FanElecPower) to DX coil
   12085         384 :                         VariableSpeedCoils::SimVariableSpeedCoils(
   12086             :                             state,
   12087             :                             VSCoilName,
   12088             :                             VSCoilNum,
   12089             :                             DataHVACGlobals::CycFanCycCoil,
   12090             :                             EMP1,
   12091             :                             EMP2,
   12092             :                             EMP3,
   12093             :                             DataHVACGlobals::CompressorOperation::On,
   12094             :                             1.0,
   12095         192 :                             state.dataVariableSpeedCoils->VarSpeedCoil(state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum).NormSpedLevel,
   12096             :                             1.0,
   12097             :                             0.0,
   12098             :                             0.0,
   12099             :                             1.0);
   12100         192 :                         if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
   12101         192 :                             state.dataHVACFan->fanObjs[state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum]->simulate(state, _, _, _, _);
   12102             :                         } else {
   12103           0 :                             Fans::SimulateFanComponents(state,
   12104           0 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanName,
   12105             :                                                         true,
   12106           0 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum);
   12107             :                         }
   12108         384 :                         VariableSpeedCoils::SimVariableSpeedCoils(
   12109             :                             state,
   12110             :                             VSCoilName,
   12111             :                             VSCoilNum,
   12112             :                             DataHVACGlobals::CycFanCycCoil,
   12113             :                             EMP1,
   12114             :                             EMP2,
   12115             :                             EMP3,
   12116             :                             DataHVACGlobals::CompressorOperation::On,
   12117             :                             1.0,
   12118         192 :                             state.dataVariableSpeedCoils->VarSpeedCoil(state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum).NormSpedLevel,
   12119             :                             1.0,
   12120             :                             0.0,
   12121             :                             0.0,
   12122             :                             1.0);
   12123         192 :                         if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
   12124         192 :                             state.dataHVACFan->fanObjs[state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum]->simulate(state, _, _, _, _);
   12125             :                         } else {
   12126           0 :                             Fans::SimulateFanComponents(state,
   12127           0 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanName,
   12128             :                                                         true,
   12129           0 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum);
   12130             :                         }
   12131             :                     }
   12132             : 
   12133         768 :                     this->MaxCapacity = state.dataVariableSpeedCoils->VSHPWHHeatingCapacity;
   12134         768 :                     this->MinCapacity = state.dataVariableSpeedCoils->VSHPWHHeatingCapacity;
   12135         768 :                     this->Efficiency = state.dataVariableSpeedCoils->VSHPWHHeatingCOP;
   12136             :                 } else {
   12137        3024 :                     bIsVSCoil = false;
   12138             :                     //       simulate the HPWH coil/fan to find heating capacity
   12139        3024 :                     if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanPlacement == DataHVACGlobals::BlowThru) {
   12140         720 :                         if (FirstTimeFlag) { // first time DXCoils::DXCoil is called, it's sized at the RatedCondenserWaterInlet temp, size and
   12141             :                                              // reset water inlet temp. If already sized, no harm.
   12142           7 :                             if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
   12143           4 :                                 state.dataHVACFan->fanObjs[state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum]->simulate(state, _, _, _, _);
   12144             :                             } else {
   12145           9 :                                 Fans::SimulateFanComponents(state,
   12146           3 :                                                             state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanName,
   12147             :                                                             true,
   12148           3 :                                                             state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum);
   12149             :                             }
   12150          21 :                             DXCoils::SimDXCoil(state,
   12151           7 :                                                state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilName,
   12152             :                                                DataHVACGlobals::CompressorOperation::On,
   12153             :                                                true,
   12154           7 :                                                state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum,
   12155             :                                                DataHVACGlobals::CycFanCycCoil,
   12156             :                                                1.0);
   12157           7 :                             state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).CondWaterInletNode).Temp = this->TankTemp;
   12158             :                         }
   12159             :                         // ?? should only need to call twice if PLR<1 since this might affect OnOffFanPartLoadFraction which impacts fan energy.
   12160             :                         // PLR=1 here.
   12161         720 :                         if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
   12162         432 :                             state.dataHVACFan->fanObjs[state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum]->simulate(state, _, _, _, _);
   12163             :                         } else {
   12164         864 :                             Fans::SimulateFanComponents(state,
   12165         288 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanName,
   12166             :                                                         true,
   12167         288 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum);
   12168             :                         }
   12169        2160 :                         DXCoils::SimDXCoil(state,
   12170         720 :                                            state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilName,
   12171             :                                            DataHVACGlobals::CompressorOperation::On,
   12172             :                                            true,
   12173         720 :                                            state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum,
   12174             :                                            DataHVACGlobals::CycFanCycCoil,
   12175             :                                            1.0);
   12176         720 :                         if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
   12177         432 :                             state.dataHVACFan->fanObjs[state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum]->simulate(state, _, _, _, _);
   12178             :                         } else {
   12179         864 :                             Fans::SimulateFanComponents(state,
   12180         288 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanName,
   12181             :                                                         true,
   12182         288 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum);
   12183             :                         }
   12184        2160 :                         DXCoils::SimDXCoil(state,
   12185         720 :                                            state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilName,
   12186             :                                            DataHVACGlobals::CompressorOperation::On,
   12187             :                                            true,
   12188         720 :                                            state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum,
   12189             :                                            DataHVACGlobals::CycFanCycCoil,
   12190             :                                            1.0);
   12191             :                     } else {
   12192        2304 :                         if (FirstTimeFlag) { // first time DXCoils::DXCoil is called, it's sized at the RatedCondenserWaterInlet temp, size and
   12193             :                                              // reset water inlet temp. If already sized, no harm.
   12194          27 :                             DXCoils::SimDXCoil(state,
   12195           9 :                                                state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilName,
   12196             :                                                DataHVACGlobals::CompressorOperation::On,
   12197             :                                                true,
   12198           9 :                                                state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum,
   12199             :                                                DataHVACGlobals::CycFanCycCoil,
   12200             :                                                1.0);
   12201           9 :                             state.dataLoopNodes->Node(state.dataWaterThermalTanks->HPWaterHeater(HPNum).CondWaterInletNode).Temp = this->TankTemp;
   12202             :                         }
   12203             :                         // ?? should only need to call twice if PLR<1 since this might affect OnOffFanPartLoadFraction which impacts fan energy.
   12204             :                         // PLR=1 here.
   12205        6912 :                         DXCoils::SimDXCoil(state,
   12206        2304 :                                            state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilName,
   12207             :                                            DataHVACGlobals::CompressorOperation::On,
   12208             :                                            true,
   12209        2304 :                                            state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum,
   12210             :                                            DataHVACGlobals::CycFanCycCoil,
   12211             :                                            1.0);
   12212        2304 :                         if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
   12213        1728 :                             state.dataHVACFan->fanObjs[state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum]->simulate(state, _, _, _, _);
   12214             :                         } else {
   12215        1728 :                             Fans::SimulateFanComponents(state,
   12216         576 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanName,
   12217             :                                                         true,
   12218         576 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum);
   12219             :                         }
   12220        6912 :                         DXCoils::SimDXCoil(state,
   12221        2304 :                                            state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilName,
   12222             :                                            DataHVACGlobals::CompressorOperation::On,
   12223             :                                            true,
   12224        2304 :                                            state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilNum,
   12225             :                                            DataHVACGlobals::CycFanCycCoil,
   12226             :                                            1.0);
   12227        2304 :                         if (state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
   12228        1728 :                             state.dataHVACFan->fanObjs[state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum]->simulate(state, _, _, _, _);
   12229             :                         } else {
   12230        1728 :                             Fans::SimulateFanComponents(state,
   12231         576 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanName,
   12232             :                                                         true,
   12233         576 :                                                         state.dataWaterThermalTanks->HPWaterHeater(HPNum).FanNum);
   12234             :                         }
   12235             :                     }
   12236             : 
   12237        3024 :                     this->MaxCapacity = state.dataDXCoils->HPWHHeatingCapacity;
   12238        3024 :                     this->MinCapacity = state.dataDXCoils->HPWHHeatingCapacity;
   12239        3024 :                     this->Efficiency = state.dataDXCoils->HPWHHeatingCOP;
   12240             :                 }
   12241             : 
   12242        3792 :                 if (FirstTimeFlag) {
   12243          23 :                     RatedDXCoilTotalCapacity = state.dataHVACGlobal->DXCoilTotalCapacity;
   12244          23 :                     FirstTimeFlag = false;
   12245             :                 }
   12246             : 
   12247             :                 //       Switch the HPWH info with the tank info and call CalcWaterThermalTankMixed to get Standard Rating
   12248             :                 //       (backup element is assumed to be disabled during the rating procedure)
   12249        3792 :                 this->SourceMassFlowRate = 0.0;
   12250        3792 :                 this->OnCycParaLoad = state.dataWaterThermalTanks->HPWaterHeater(HPNum).OnCycParaLoad;
   12251        3792 :                 this->OffCycParaLoad = state.dataWaterThermalTanks->HPWaterHeater(HPNum).OffCycParaLoad;
   12252        3792 :                 this->OffCycParaFracToTank = 0.0;
   12253        3792 :                 this->OnCycParaFracToTank = 0.0;
   12254        3792 :                 this->PLFCurve = state.dataWaterThermalTanks->HPWaterHeater(HPNum).DXCoilPLFFPLR;
   12255             : 
   12256        3792 :                 if (this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterMixed) {
   12257        1200 :                     if (this->Efficiency > 0.0) this->CalcWaterThermalTankMixed(state);
   12258             : 
   12259        2592 :                 } else if (this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
   12260        2592 :                     if (this->Efficiency > 0.0) this->CalcWaterThermalTankStratified(state);
   12261             :                 }
   12262             : 
   12263             :                 //       reset the water heater data to original values
   12264        3792 :                 this->MaxCapacity = state.dataWaterThermalTanks->HPWaterHeater(HPNum).BackupElementCapacity;
   12265        3792 :                 this->MinCapacity = state.dataWaterThermalTanks->HPWaterHeater(HPNum).BackupElementCapacity;
   12266        3792 :                 this->Efficiency = state.dataWaterThermalTanks->HPWaterHeater(HPNum).BackupElementEfficiency;
   12267        3792 :                 this->OnCycParaLoad = state.dataWaterThermalTanks->HPWaterHeater(HPNum).WHOnCycParaLoad;
   12268        3792 :                 this->OffCycParaLoad = state.dataWaterThermalTanks->HPWaterHeater(HPNum).WHOffCycParaLoad;
   12269        3792 :                 this->OnCycParaFracToTank = state.dataWaterThermalTanks->HPWaterHeater(HPNum).WHOnCycParaFracToTank;
   12270        3792 :                 this->OffCycParaFracToTank = state.dataWaterThermalTanks->HPWaterHeater(HPNum).WHOffCycParaFracToTank;
   12271        3792 :                 this->PLFCurve = state.dataWaterThermalTanks->HPWaterHeater(HPNum).WHPLFCurve;
   12272             :             }
   12273             : 
   12274       22368 :             FuelEnergy_loc += (this->FuelRate + this->OffCycParaFuelRate + this->OnCycParaFuelRate) * SecInTimeStep;
   12275             : 
   12276             :         } // Step
   12277             : 
   12278         181 :         if (this->FirstRecoveryDone && this->FirstRecoveryFuel > 0.0) {
   12279             :             // Calculate Recovery Efficiency based on energy used to recover from the first draw
   12280             :             // FirstRecoveryFuel is recorded inside the CalcWaterThermalTank subroutine
   12281         164 :             RecoveryEfficiency = DrawMass * Psychrometrics::CPHW(57.2222) * (57.2222 - 14.4444) / this->FirstRecoveryFuel;
   12282             : 
   12283             :             // Calculate Energy Factor based on total energy (including parasitics) used over entire test
   12284         164 :             EnergyFactor = TotalDrawMass * Psychrometrics::CPHW(57.2222) * (57.2222 - 14.4444) / FuelEnergy_loc;
   12285             : 
   12286             :         } else {
   12287          17 :             RecoveryEfficiency = 0.0;
   12288          17 :             EnergyFactor = 0.0;
   12289             :             // If this a regular tank, or an HPWH that's not an Integrated one
   12290          17 :             if ((this->HeatPumpNum == 0) || !state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).bIsIHP) {
   12291          48 :                 ShowWarningError(state,
   12292          32 :                                  "Water heater = " + this->Name +
   12293             :                                      ":  Recovery Efficiency and Energy Factor could not be calculated during the test for standard ratings");
   12294          16 :                 ShowContinueError(state, "Setpoint was never recovered and/or heater never turned on");
   12295             :             }
   12296         181 :         }
   12297             : 
   12298             :     } else {
   12299             : 
   12300             :         // Storage-only tank
   12301           5 :         RecoveryEfficiency = 0.0;
   12302           5 :         EnergyFactor = 0.0;
   12303             : 
   12304             :     } // WaterThermalTank(WaterThermalTankNum)%MaxCapacity > 0.0
   12305             : 
   12306             :     // create predefined report
   12307             :     // Store values for the input verification and summary report
   12308         372 :     std::string equipName;
   12309         186 :     if (this->HeatPumpNum == 0) {
   12310         163 :         equipName = this->Name;
   12311         163 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchSWHType, equipName, this->Type);
   12312         163 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchSWHVol, equipName, this->Volume);
   12313         163 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchSWHHeatIn, equipName, this->MaxCapacity);
   12314         163 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchSWHThEff, equipName, this->Efficiency);
   12315         163 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchSWHRecEff, equipName, RecoveryEfficiency);
   12316         163 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchSWHEnFac, equipName, EnergyFactor);
   12317             :     } else {
   12318          23 :         equipName = state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).Name;
   12319          46 :         OutputReportPredefined::PreDefTableEntry(
   12320          46 :             state, state.dataOutRptPredefined->pdchSWHType, equipName, state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).Type);
   12321          23 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchSWHVol, equipName, this->Volume);
   12322          23 :         if (bIsVSCoil) {
   12323          21 :             OutputReportPredefined::PreDefTableEntry(
   12324          14 :                 state, state.dataOutRptPredefined->pdchSWHHeatIn, equipName, state.dataVariableSpeedCoils->VSHPWHHeatingCapacity);
   12325             :         } else {
   12326          48 :             OutputReportPredefined::PreDefTableEntry(
   12327          32 :                 state, state.dataOutRptPredefined->pdchSWHHeatIn, equipName, state.dataDXCoils->HPWHHeatingCapacity);
   12328             :         }
   12329          23 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchSWHThEff, equipName, this->Efficiency);
   12330          23 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchSWHRecEff, equipName, RecoveryEfficiency);
   12331          23 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchSWHEnFac, equipName, EnergyFactor);
   12332             :     }
   12333             : 
   12334             :     // Write test results
   12335         186 :     if (this->HeatPumpNum == 0) {
   12336             :         Real64 MaxCapacity_loc;
   12337         163 :         if (this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) {
   12338           5 :             if (this->StratifiedControlMode == PriorityControlMode::MasterSlave) {
   12339           5 :                 MaxCapacity_loc = max(this->MaxCapacity, this->MaxCapacity2);
   12340             :             } else { // PrioritySimultaneous
   12341           0 :                 MaxCapacity_loc = this->MaxCapacity + this->MaxCapacity2;
   12342             :             }
   12343             :         } else { // WaterHeaterMixed
   12344         158 :             MaxCapacity_loc = this->MaxCapacity;
   12345             :         }
   12346             : 
   12347             :         static constexpr std::string_view Format_720("Water Heater Information,{},{},{:.4T},{:.1T},{:.3T},{:.4T}\n");
   12348         163 :         print(state.files.eio, Format_720, this->Type, this->Name, this->Volume, MaxCapacity_loc, RecoveryEfficiency, EnergyFactor);
   12349             :     } else {
   12350             :         static constexpr std::string_view Format_721("Heat Pump Water Heater Information,{},{},{:.4T},{:.1T},{:.3T},{:.4T},{:.0T}\n");
   12351          69 :         print(state.files.eio,
   12352             :               Format_721,
   12353          23 :               state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).Type,
   12354          23 :               state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).Name,
   12355             :               this->Volume,
   12356          23 :               state.dataDXCoils->HPWHHeatingCapacity,
   12357             :               RecoveryEfficiency,
   12358             :               EnergyFactor,
   12359             :               RatedDXCoilTotalCapacity);
   12360             :     }
   12361             : 
   12362         186 :     this->AlreadyRated = true;
   12363             : }
   12364             : 
   12365           9 : void WaterThermalTankData::ReportCWTankInits(EnergyPlusData &state)
   12366             : {
   12367             : 
   12368             :     // SUBROUTINE INFORMATION:
   12369             :     //       AUTHOR         B. Griffith
   12370             :     //       DATE WRITTEN   March 2009
   12371             :     //       MODIFIED       na
   12372             :     //       RE-ENGINEERED  na
   12373             : 
   12374             :     // PURPOSE OF THIS SUBROUTINE:
   12375             :     // send chilled water tank info to EIO
   12376             : 
   12377           9 :     if (this->myOneTimeInitFlag) {
   12378           0 :         this->setupOutputVars(state);
   12379           0 :         this->myOneTimeInitFlag = false;
   12380             :     }
   12381             : 
   12382           9 :     if (this->AlreadyReported) { // bail we already did this one
   12383           4 :         return;
   12384             :     }
   12385             : 
   12386             :     static constexpr std::string_view Format_728("Chilled Water Tank Information,{},{},{:.4T},{:.4T},{:.4T}\n");
   12387           5 :     print(state.files.eio, Format_728, this->Type, this->Name, this->Volume, this->UseDesignVolFlowRate, this->SourceDesignVolFlowRate);
   12388             : 
   12389           5 :     this->AlreadyReported = true;
   12390             : }
   12391             : 
   12392     1095678 : Real64 WaterThermalTankData::FindStratifiedTankSensedTemp(EnergyPlusData &state, bool UseAverage)
   12393             : {
   12394             : 
   12395             :     // FUNCTION INFORMATION:
   12396             :     //       AUTHOR         B. Griffith
   12397             :     //       DATE WRITTEN   March 2012
   12398             :     //       MODIFIED       na
   12399             :     //       RE-ENGINEERED  Noel Merket, April 2015
   12400             : 
   12401             :     // PURPOSE OF THIS FUNCTION:
   12402             :     // find tank temperature depending on how sensed
   12403             : 
   12404             :     // FUNCTION LOCAL VARIABLE DECLARATIONS:
   12405     1095678 :     HeatPumpWaterHeaterData const &HPWH = state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum);
   12406             :     Real64 ControlSensor1Temp;
   12407             :     Real64 ControlSensor2Temp;
   12408             : 
   12409     1095678 :     if (UseAverage) {
   12410      276566 :         ControlSensor1Temp = this->Node(HPWH.ControlSensor1Node).TempAvg;
   12411      276566 :         ControlSensor2Temp = this->Node(HPWH.ControlSensor2Node).TempAvg;
   12412             :     } else {
   12413      819112 :         ControlSensor1Temp = this->Node(HPWH.ControlSensor1Node).Temp;
   12414      819112 :         ControlSensor2Temp = this->Node(HPWH.ControlSensor2Node).Temp;
   12415             :     }
   12416             : 
   12417     1095678 :     Real64 SensedTemp = ControlSensor1Temp * HPWH.ControlSensor1Weight + ControlSensor2Temp * HPWH.ControlSensor2Weight;
   12418             : 
   12419     1095678 :     return SensedTemp;
   12420             : }
   12421             : 
   12422     6395474 : Real64 WaterThermalTankData::getDeadBandTemp()
   12423             : {
   12424     6395474 :     if (this->IsChilledWaterTank) {
   12425      315033 :         return (this->SetPointTemp + this->DeadBandDeltaTemp);
   12426             :     } else {
   12427     6080441 :         return (this->SetPointTemp - this->DeadBandDeltaTemp);
   12428             :     }
   12429             : }
   12430     5468492 : void WaterThermalTankData::oneTimeInit(EnergyPlusData &state)
   12431             : {
   12432     5468492 :     if (this->myOneTimeInitFlag) {
   12433         168 :         this->setupOutputVars(state);
   12434         168 :         this->myOneTimeInitFlag = false;
   12435             :     }
   12436     5468492 : }
   12437             : 
   12438          20 : void WaterThermalTankData::setBackupElementCapacity(EnergyPlusData &state)
   12439             : {
   12440             :     // Fix for #9001: The BackupElementCapacity was not being reset from the autosize value (-99999) which resulted in
   12441             :     // negative electric consumption.  Using a test for any negative numbers here instead of just -99999 for safety.
   12442             :     // Only reset the backup element capacity if a problem has been occured.
   12443          20 :     if (this->HeatPumpNum > 0) {
   12444          20 :         if (state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).HPWHType == DataPlant::PlantEquipmentType::HeatPumpWtrHeaterWrapped) return;
   12445           0 :         if (state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).BackupElementCapacity < 0.0) {
   12446           0 :             state.dataWaterThermalTanks->HPWaterHeater(this->HeatPumpNum).BackupElementCapacity = this->MaxCapacity;
   12447             :         }
   12448           0 :     } else if (this->DesuperheaterNum > 0) {
   12449           0 :         if (state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).BackupElementCapacity < 0.0) {
   12450           0 :             state.dataWaterThermalTanks->WaterHeaterDesuperheater(this->DesuperheaterNum).BackupElementCapacity = this->MaxCapacity;
   12451             :         }
   12452             :     }
   12453             : }
   12454             : 
   12455          16 : bool GetHeatPumpWaterHeaterNodeNumber(EnergyPlusData &state, int const NodeNumber)
   12456             : {
   12457             :     // PURPOSE OF THIS FUNCTION:
   12458             :     // Check if a node is used by a heat pump water heater
   12459             :     // and can be excluded from an airflow network.
   12460             : 
   12461             :     // Return value
   12462             :     bool HeatPumpWaterHeaterNodeException;
   12463             : 
   12464             :     int HeatPumpWaterHeaterIndex;
   12465             : 
   12466          16 :     if (state.dataWaterThermalTanks->getWaterThermalTankInputFlag) {
   12467           0 :         GetWaterThermalTankInput(state);
   12468           0 :         state.dataWaterThermalTanks->getWaterThermalTankInputFlag = false;
   12469             :     }
   12470             : 
   12471          16 :     HeatPumpWaterHeaterNodeException = false;
   12472             : 
   12473          26 :     for (HeatPumpWaterHeaterIndex = 1; HeatPumpWaterHeaterIndex <= state.dataWaterThermalTanks->numHeatPumpWaterHeater; ++HeatPumpWaterHeaterIndex) {
   12474             : 
   12475             :         // Get heat pump water heater data
   12476          16 :         HeatPumpWaterHeaterData &HPWH = state.dataWaterThermalTanks->HPWaterHeater(HeatPumpWaterHeaterIndex);
   12477             : 
   12478             :         // "Zone and outdoor air" configuration is expected break the conservation of mass
   12479          16 :         if (HPWH.InletAirConfiguration != WTTAmbientTemp::ZoneAndOA) {
   12480             : 
   12481             :             // Air outlet node
   12482          16 :             if (NodeNumber == HPWH.HeatPumpAirOutletNode) {
   12483           2 :                 HeatPumpWaterHeaterNodeException = true;
   12484           8 :                 break;
   12485             :             }
   12486             : 
   12487             :             // Air inlet node
   12488          14 :             if (NodeNumber == HPWH.HeatPumpAirInletNode) {
   12489           2 :                 HeatPumpWaterHeaterNodeException = true;
   12490           2 :                 break;
   12491             :             }
   12492             : 
   12493             :             // Get fan inlet node index
   12494          12 :             bool ErrorsFound{false};
   12495          12 :             int FanInletNodeIndex(0);
   12496          12 :             if (HPWH.FanType_Num == DataHVACGlobals::FanType_SystemModelObject) {
   12497           0 :                 FanInletNodeIndex = state.dataHVACFan->fanObjs[HPWH.FanNum]->inletNodeNum;
   12498             :             } else {
   12499          12 :                 FanInletNodeIndex = Fans::GetFanInletNode(state, HPWH.FanType, HPWH.FanName, ErrorsFound);
   12500          12 :                 if (ErrorsFound) {
   12501           0 :                     ShowWarningError(state, "Could not retrieve fan outlet node for this unit=\"" + HPWH.Name + "\".");
   12502           0 :                     ErrorsFound = true;
   12503             :                 }
   12504             :             }
   12505             : 
   12506             :             // Fan inlet node
   12507          12 :             if (NodeNumber == FanInletNodeIndex) {
   12508           2 :                 HeatPumpWaterHeaterNodeException = true;
   12509           2 :                 break;
   12510             :             }
   12511             : 
   12512             :             // Fan outlet node
   12513          10 :             if (NodeNumber == HPWH.FanOutletNode) {
   12514           0 :                 HeatPumpWaterHeaterNodeException = true;
   12515           0 :                 break;
   12516             :             }
   12517             : 
   12518             :             // Outside air node
   12519          10 :             if (NodeNumber == HPWH.OutsideAirNode) {
   12520           0 :                 HeatPumpWaterHeaterNodeException = true;
   12521           0 :                 break;
   12522             :             }
   12523             : 
   12524             :             // Exhaust air node
   12525          10 :             if (NodeNumber == HPWH.ExhaustAirNode) {
   12526           0 :                 HeatPumpWaterHeaterNodeException = true;
   12527           0 :                 break;
   12528             :             }
   12529             :         }
   12530             :     }
   12531             : 
   12532          16 :     return HeatPumpWaterHeaterNodeException;
   12533             : }
   12534             : 
   12535        2313 : } // namespace EnergyPlus::WaterThermalTanks

Generated by: LCOV version 1.13