LCOV - code coverage report
Current view: top level - EnergyPlus - WaterToAirHeatPump.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 59.4 % 1095 650
Test Date: 2025-06-02 12:03:30 Functions: 42.9 % 14 6

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <cmath>
      50              : 
      51              : // ObjexxFCL Headers
      52              : #include <ObjexxFCL/Array.functions.hh>
      53              : 
      54              : // EnergyPlus Headers
      55              : #include <EnergyPlus/BranchNodeConnections.hh>
      56              : #include <EnergyPlus/CurveManager.hh>
      57              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      58              : #include <EnergyPlus/DataContaminantBalance.hh>
      59              : #include <EnergyPlus/DataHVACGlobals.hh>
      60              : #include <EnergyPlus/DataLoopNode.hh>
      61              : #include <EnergyPlus/FluidProperties.hh>
      62              : #include <EnergyPlus/General.hh>
      63              : #include <EnergyPlus/GlobalNames.hh>
      64              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      65              : #include <EnergyPlus/NodeInputManager.hh>
      66              : #include <EnergyPlus/OutputProcessor.hh>
      67              : #include <EnergyPlus/OutputReportPredefined.hh>
      68              : #include <EnergyPlus/Plant/DataPlant.hh>
      69              : #include <EnergyPlus/PlantUtilities.hh>
      70              : #include <EnergyPlus/Psychrometrics.hh>
      71              : #include <EnergyPlus/UtilityRoutines.hh>
      72              : #include <EnergyPlus/WaterToAirHeatPump.hh>
      73              : 
      74              : namespace EnergyPlus {
      75              : 
      76              : namespace WaterToAirHeatPump {
      77              :     // Module containing the Water to Air Heat Pump simulation routines
      78              : 
      79              :     // MODULE INFORMATION:
      80              :     //       AUTHOR         Hui Jin
      81              :     //       DATE WRITTEN   Oct 2000
      82              :     //       MODIFIED       Dan Fisher, Kenneth Tang (Jan 2004)
      83              :     //                      Brent Griffith, plant upgrades, fluid props
      84              : 
      85              :     // PURPOSE OF THIS MODULE:
      86              :     // To encapsulate the data and algorithms required to
      87              :     // manage the Water to Air Heat Pump Component
      88              : 
      89              :     // METHODOLOGY EMPLOYED:
      90              : 
      91              :     // REFERENCES:
      92              :     // Jin, H. 2002. Parameter Estimation Based Models of Water Source Heat Pumps. Phd Thesis.
      93              :     // Oklahoma State University.
      94              : 
      95            0 :     void SimWatertoAirHP(EnergyPlusData &state,
      96              :                          std::string_view CompName,     // component name
      97              :                          int &CompIndex,                // Index for Component name
      98              :                          Real64 const DesignAirflow,    // design air flow rate
      99              :                          HVAC::FanOp const fanOp,       // cycling scheme--either continuous fan/cycling compressor or
     100              :                          bool const FirstHVACIteration, // first iteration flag
     101              :                          bool const InitFlag,           // initialization flag used to suppress property routine errors
     102              :                          Real64 const SensLoad,         // sensible load
     103              :                          Real64 const LatentLoad,       // latent load
     104              :                          HVAC::CompressorOp const compressorOp,
     105              :                          Real64 const PartLoadRatio)
     106              :     {
     107              : 
     108              :         // SUBROUTINE INFORMATION:
     109              :         //       AUTHOR         Hui Jin
     110              :         //       DATE WRITTEN   Oct 2000
     111              :         //       MODIFIED       Dan Fisher, Kenneth Tang (Jan 2004)
     112              : 
     113              :         // PURPOSE OF THIS SUBROUTINE:
     114              :         // This subroutine manages Water to Air Heat Pump component simulation.
     115              : 
     116              :         // shut off after compressor cycle off  [s]
     117              :         // cycling fan/cycling compressor
     118              : 
     119              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     120              :         int HPNum; // The WatertoAirHP that you are currently loading input into
     121              : 
     122              :         // Obtains and Allocates WatertoAirHP related parameters from input file
     123            0 :         if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered
     124            0 :             GetWatertoAirHPInput(state);
     125            0 :             state.dataWaterToAirHeatPump->GetCoilsInputFlag = false;
     126              :         }
     127              : 
     128            0 :         if (CompIndex == 0) {
     129            0 :             HPNum = Util::FindItemInList(CompName, state.dataWaterToAirHeatPump->WatertoAirHP);
     130            0 :             if (HPNum == 0) {
     131            0 :                 ShowFatalError(state, format("WaterToAir HP not found={}", CompName));
     132              :             }
     133            0 :             CompIndex = HPNum;
     134              :         } else {
     135            0 :             HPNum = CompIndex;
     136            0 :             if (HPNum > state.dataWaterToAirHeatPump->NumWatertoAirHPs || HPNum < 1) {
     137            0 :                 ShowFatalError(state,
     138            0 :                                format("SimWatertoAirHP: Invalid CompIndex passed={}, Number of Water to Air HPs={}, WaterToAir HP name={}",
     139              :                                       HPNum,
     140            0 :                                       state.dataWaterToAirHeatPump->NumWatertoAirHPs,
     141              :                                       CompName));
     142              :             }
     143            0 :             if (state.dataWaterToAirHeatPump->CheckEquipName(HPNum)) {
     144            0 :                 if (!CompName.empty() && CompName != state.dataWaterToAirHeatPump->WatertoAirHP(HPNum).Name) {
     145            0 :                     ShowFatalError(
     146              :                         state,
     147            0 :                         format("SimWatertoAirHP: Invalid CompIndex passed={}, WaterToAir HP name={}, stored WaterToAir HP Name for that index={}",
     148              :                                HPNum,
     149              :                                CompName,
     150            0 :                                state.dataWaterToAirHeatPump->WatertoAirHP(HPNum).Name));
     151              :                 }
     152            0 :                 state.dataWaterToAirHeatPump->CheckEquipName(HPNum) = false;
     153              :             }
     154              :         }
     155              :         // Calculate the Correct Water to Air HP Model with the current HPNum
     156              : 
     157            0 :         if (state.dataWaterToAirHeatPump->WatertoAirHP(HPNum).WAHPType == DataPlant::PlantEquipmentType::CoilWAHPCoolingParamEst) {
     158            0 :             InitWatertoAirHP(state, HPNum, InitFlag, SensLoad, LatentLoad, DesignAirflow, PartLoadRatio);
     159            0 :             CalcWatertoAirHPCooling(state, HPNum, fanOp, FirstHVACIteration, InitFlag, SensLoad, compressorOp, PartLoadRatio);
     160              : 
     161            0 :             UpdateWatertoAirHP(state, HPNum);
     162              : 
     163            0 :         } else if (state.dataWaterToAirHeatPump->WatertoAirHP(HPNum).WAHPType == DataPlant::PlantEquipmentType::CoilWAHPHeatingParamEst) {
     164            0 :             InitWatertoAirHP(state, HPNum, InitFlag, SensLoad, LatentLoad, DesignAirflow, PartLoadRatio);
     165            0 :             CalcWatertoAirHPHeating(state, HPNum, fanOp, FirstHVACIteration, InitFlag, SensLoad, compressorOp, PartLoadRatio);
     166              : 
     167            0 :             UpdateWatertoAirHP(state, HPNum);
     168              : 
     169              :         } else {
     170            0 :             ShowFatalError(state, "SimWatertoAirHP: AirtoAir heatpump not in either HEATING or COOLING");
     171              :         }
     172            0 :     }
     173              : 
     174              :     // Get Input Section of the Module
     175              :     //******************************************************************************
     176              : 
     177            1 :     void GetWatertoAirHPInput(EnergyPlusData &state)
     178              :     {
     179              : 
     180              :         // SUBROUTINE INFORMATION:
     181              :         //       AUTHOR         Hui Jin
     182              :         //       DATE WRITTEN   Oct 2000
     183              :         //       MODIFIED       Dan Fisher, Kenneth Tang (Jan 2004)
     184              : 
     185              :         // PURPOSE OF THIS SUBROUTINE:
     186              :         // Obtains input data for HPs and stores it in HP data structures
     187              : 
     188              :         // METHODOLOGY EMPLOYED:
     189              :         // Uses "Get" routines to read in data.
     190              : 
     191              :         // SUBROUTINE PARAMETER DEFINITIONS:
     192              :         static constexpr std::string_view RoutineName("GetWatertoAirHPInput: "); // include trailing blank space
     193              :         static constexpr std::string_view routineName = "GetWatertoAirHPInput";
     194              : 
     195              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     196              :         int HPNum; // The Water to Air HP that you are currently loading input into
     197              :         int NumCool;
     198              :         int NumHeat;
     199              :         int WatertoAirHPNum;
     200              :         int NumAlphas;
     201              :         int NumParams;
     202              :         int NumNums;
     203            1 :         int MaxNums(0);   // Maximum number of numeric input fields
     204            1 :         int MaxAlphas(0); // Maximum number of alpha input fields
     205              :         int IOStat;
     206            1 :         bool ErrorsFound(false);         // If errors detected in input
     207            1 :         std::string CurrentModuleObject; // for ease in getting objects
     208            1 :         Array1D_string AlphArray;        // Alpha input items for object
     209            1 :         Array1D_string cAlphaFields;     // Alpha field names
     210            1 :         Array1D_string cNumericFields;   // Numeric field names
     211            1 :         Array1D<Real64> NumArray;        // Numeric input items for object
     212            1 :         Array1D_bool lAlphaBlanks;       // Logical array, alpha field input BLANK = .TRUE.
     213            1 :         Array1D_bool lNumericBlanks;     // Logical array, numeric field input BLANK = .TRUE.
     214              : 
     215            1 :         constexpr std::array<std::string_view, static_cast<int>(CompressorType::Num)> CompressTypeNamesUC{"RECIPROCATING", "ROTARY", "SCROLL"};
     216              : 
     217            1 :         NumCool = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Cooling:WaterToAirHeatPump:ParameterEstimation");
     218            1 :         NumHeat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Heating:WaterToAirHeatPump:ParameterEstimation");
     219            1 :         state.dataWaterToAirHeatPump->NumWatertoAirHPs = NumCool + NumHeat;
     220            1 :         HPNum = 0;
     221              : 
     222            1 :         if (state.dataWaterToAirHeatPump->NumWatertoAirHPs <= 0) {
     223            0 :             ShowSevereError(state, "No Equipment found in SimWatertoAirHP");
     224            0 :             ErrorsFound = true;
     225              :         }
     226              : 
     227              :         // Allocate Arrays
     228            1 :         if (state.dataWaterToAirHeatPump->NumWatertoAirHPs > 0) {
     229            1 :             state.dataWaterToAirHeatPump->WatertoAirHP.allocate(state.dataWaterToAirHeatPump->NumWatertoAirHPs);
     230            1 :             state.dataWaterToAirHeatPump->CheckEquipName.dimension(state.dataWaterToAirHeatPump->NumWatertoAirHPs, true);
     231              :         }
     232              : 
     233            1 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     234              :             state, "Coil:Cooling:WaterToAirHeatPump:ParameterEstimation", NumParams, NumAlphas, NumNums);
     235            1 :         MaxNums = max(MaxNums, NumNums);
     236            1 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     237            1 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     238              :             state, "Coil:Heating:WaterToAirHeatPump:ParameterEstimation", NumParams, NumAlphas, NumNums);
     239            1 :         MaxNums = max(MaxNums, NumNums);
     240            1 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     241            1 :         AlphArray.allocate(MaxAlphas);
     242            1 :         cAlphaFields.allocate(MaxAlphas);
     243            1 :         lAlphaBlanks.dimension(MaxAlphas, true);
     244            1 :         cNumericFields.allocate(MaxNums);
     245            1 :         lNumericBlanks.dimension(MaxNums, true);
     246            1 :         NumArray.dimension(MaxNums, 0.0);
     247              : 
     248              :         // Get the data for detailed cooling Heat Pump
     249            1 :         CurrentModuleObject = "Coil:Cooling:WaterToAirHeatPump:ParameterEstimation";
     250              : 
     251            2 :         for (WatertoAirHPNum = 1; WatertoAirHPNum <= NumCool; ++WatertoAirHPNum) {
     252              : 
     253            1 :             ++HPNum;
     254              : 
     255            1 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     256              :                                                                      CurrentModuleObject,
     257              :                                                                      HPNum,
     258              :                                                                      AlphArray,
     259              :                                                                      NumAlphas,
     260              :                                                                      NumArray,
     261              :                                                                      NumNums,
     262              :                                                                      IOStat,
     263              :                                                                      lNumericBlanks,
     264              :                                                                      lAlphaBlanks,
     265              :                                                                      cAlphaFields,
     266              :                                                                      cNumericFields);
     267              : 
     268            1 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, AlphArray(1)};
     269              :             // ErrorsFound will be set to True if problem was found, left untouched otherwise
     270            1 :             GlobalNames::VerifyUniqueCoilName(state, CurrentModuleObject, AlphArray(1), ErrorsFound, CurrentModuleObject + " Name");
     271              : 
     272            1 :             auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
     273              : 
     274            1 :             heatPump.Name = AlphArray(1);
     275            1 :             heatPump.WatertoAirHPType = "COOLING";
     276            1 :             heatPump.WAHPType = DataPlant::PlantEquipmentType::CoilWAHPCoolingParamEst;
     277            1 :             heatPump.Refrigerant = AlphArray(3);
     278            1 :             if (heatPump.Refrigerant.empty()) {
     279            0 :                 ShowSevereEmptyField(state, eoh, cAlphaFields(3));
     280            0 :                 ErrorsFound = true;
     281            1 :             } else if ((heatPump.refrig = Fluid::GetRefrig(state, heatPump.Refrigerant)) == nullptr) {
     282            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(3), AlphArray(3));
     283            0 :                 ErrorsFound = true;
     284              :             }
     285            1 :             heatPump.DesignWaterVolFlowRate = NumArray(1);
     286            1 :             heatPump.CoolingCapacity = NumArray(2);
     287            1 :             heatPump.Twet_Rated = NumArray(3);
     288            1 :             heatPump.Gamma_Rated = NumArray(4);
     289              : 
     290            1 :             heatPump.HighPressCutoff = NumArray(5);
     291            1 :             heatPump.LowPressCutoff = NumArray(6);
     292              : 
     293            1 :             heatPump.WaterInletNodeNum = GetOnlySingleNode(state,
     294            1 :                                                            AlphArray(4),
     295              :                                                            ErrorsFound,
     296              :                                                            DataLoopNode::ConnectionObjectType::CoilCoolingWaterToAirHeatPumpParameterEstimation,
     297            1 :                                                            AlphArray(1),
     298              :                                                            DataLoopNode::NodeFluidType::Water,
     299              :                                                            DataLoopNode::ConnectionType::Inlet,
     300              :                                                            NodeInputManager::CompFluidStream::Secondary,
     301              :                                                            DataLoopNode::ObjectIsNotParent);
     302            1 :             heatPump.WaterOutletNodeNum = GetOnlySingleNode(state,
     303            1 :                                                             AlphArray(5),
     304              :                                                             ErrorsFound,
     305              :                                                             DataLoopNode::ConnectionObjectType::CoilCoolingWaterToAirHeatPumpParameterEstimation,
     306            1 :                                                             AlphArray(1),
     307              :                                                             DataLoopNode::NodeFluidType::Water,
     308              :                                                             DataLoopNode::ConnectionType::Outlet,
     309              :                                                             NodeInputManager::CompFluidStream::Secondary,
     310              :                                                             DataLoopNode::ObjectIsNotParent);
     311            1 :             heatPump.AirInletNodeNum = GetOnlySingleNode(state,
     312            1 :                                                          AlphArray(6),
     313              :                                                          ErrorsFound,
     314              :                                                          DataLoopNode::ConnectionObjectType::CoilCoolingWaterToAirHeatPumpParameterEstimation,
     315            1 :                                                          AlphArray(1),
     316              :                                                          DataLoopNode::NodeFluidType::Air,
     317              :                                                          DataLoopNode::ConnectionType::Inlet,
     318              :                                                          NodeInputManager::CompFluidStream::Primary,
     319              :                                                          DataLoopNode::ObjectIsNotParent);
     320            1 :             heatPump.AirOutletNodeNum = GetOnlySingleNode(state,
     321            1 :                                                           AlphArray(7),
     322              :                                                           ErrorsFound,
     323              :                                                           DataLoopNode::ConnectionObjectType::CoilCoolingWaterToAirHeatPumpParameterEstimation,
     324            1 :                                                           AlphArray(1),
     325              :                                                           DataLoopNode::NodeFluidType::Air,
     326              :                                                           DataLoopNode::ConnectionType::Outlet,
     327              :                                                           NodeInputManager::CompFluidStream::Primary,
     328              :                                                           DataLoopNode::ObjectIsNotParent);
     329              : 
     330              :             // 2010-01-13 ESL: Jason Glazer noted that these were out of order previously, but they are good now
     331            1 :             heatPump.LoadSideTotalUACoeff = NumArray(7);
     332            1 :             heatPump.LoadSideOutsideUACoeff = NumArray(8);
     333              : 
     334            1 :             if ((heatPump.LoadSideOutsideUACoeff < Constant::rTinyValue) || (heatPump.LoadSideTotalUACoeff < Constant::rTinyValue)) {
     335            0 :                 ShowSevereError(state, format("Input problem for {}={}", CurrentModuleObject, heatPump.Name));
     336            0 :                 ShowContinueError(state, " One or both load side UA values entered are below tolerance, likely zero or blank.");
     337            0 :                 ShowContinueError(state, " Verify inputs, as the parameter syntax for this object went through a change with");
     338            0 :                 ShowContinueError(state, "  the release of EnergyPlus version 5.");
     339            0 :                 ErrorsFound = true;
     340              :             }
     341              : 
     342            1 :             heatPump.SuperheatTemp = NumArray(9);
     343            1 :             heatPump.PowerLosses = NumArray(10);
     344            1 :             heatPump.LossFactor = NumArray(11);
     345              : 
     346            1 :             heatPump.compressorType = static_cast<CompressorType>(getEnumValue(CompressTypeNamesUC, Util::makeUPPER(AlphArray(2))));
     347              : 
     348            1 :             switch (heatPump.compressorType) {
     349            0 :             case CompressorType::Reciprocating: {
     350            0 :                 heatPump.CompPistonDisp = NumArray(12);
     351            0 :                 heatPump.CompSucPressDrop = NumArray(13);
     352            0 :                 heatPump.CompClearanceFactor = NumArray(14);
     353            0 :                 break;
     354              :             }
     355            0 :             case CompressorType::Rotary: {
     356            0 :                 heatPump.CompPistonDisp = NumArray(12);
     357            0 :                 heatPump.CompSucPressDrop = NumArray(13);
     358            0 :                 break;
     359              :             }
     360            1 :             case CompressorType::Scroll: {
     361            1 :                 heatPump.RefVolFlowRate = NumArray(15);
     362            1 :                 heatPump.VolumeRatio = NumArray(16);
     363            1 :                 heatPump.LeakRateCoeff = NumArray(17);
     364            1 :                 break;
     365              :             }
     366            0 :             default: {
     367            0 :                 ShowSevereError(
     368              :                     state,
     369            0 :                     format("{}Invalid {} ({}) entered. {}={}", RoutineName, cAlphaFields(2), AlphArray(2), CurrentModuleObject, heatPump.Name));
     370            0 :                 ErrorsFound = true;
     371            0 :                 break;
     372              :             }
     373              :             }
     374              : 
     375            1 :             heatPump.SourceSideUACoeff = NumArray(18);
     376            1 :             heatPump.SourceSideHTR1 = NumArray(19);
     377            1 :             heatPump.SourceSideHTR2 = NumArray(20);
     378            1 :             heatPump.PLFCurveIndex = Curve::GetCurveIndex(state, AlphArray(8)); // convert curve name to number
     379              : 
     380            1 :             if (heatPump.PLFCurveIndex == 0) {
     381            0 :                 if (lAlphaBlanks(8)) {
     382            0 :                     ShowSevereError(state, format("{}{}=\"{}\", missing", RoutineName, CurrentModuleObject, heatPump.Name));
     383            0 :                     ShowContinueError(state, format("...required {} is blank.", cAlphaFields(8)));
     384              :                 } else {
     385            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, CurrentModuleObject, heatPump.Name));
     386            0 :                     ShowContinueError(state, format("...not found {}=\"{}\".", cAlphaFields(8), AlphArray(8)));
     387              :                 }
     388            0 :                 ErrorsFound = true;
     389              :             } else {
     390              :                 // Verify Curve Object, only legal types are Quadratic or Cubic
     391            2 :                 ErrorsFound |= Curve::CheckCurveDims(state,
     392              :                                                      heatPump.PLFCurveIndex, // Curve index
     393              :                                                      {1},                    // Valid dimensions
     394              :                                                      RoutineName,            // Routine name
     395              :                                                      CurrentModuleObject,    // Object Type
     396              :                                                      heatPump.Name,          // Object Name
     397            1 :                                                      cAlphaFields(8));       // Field Name
     398              : 
     399            1 :                 if (!ErrorsFound) {
     400              :                     //     Test PLF curve minimum and maximum. Cap if less than 0.7 or greater than 1.0.
     401            1 :                     Real64 MinCurveVal = 999.0;
     402            1 :                     Real64 MaxCurveVal = -999.0;
     403            1 :                     Real64 CurveInput = 0.0;
     404            1 :                     Real64 MinCurvePLR{0.0};
     405            1 :                     Real64 MaxCurvePLR{0.0};
     406              : 
     407          101 :                     while (CurveInput <= 1.0) {
     408          100 :                         Real64 CurveVal = Curve::CurveValue(state, heatPump.PLFCurveIndex, CurveInput);
     409          100 :                         if (CurveVal < MinCurveVal) {
     410            1 :                             MinCurveVal = CurveVal;
     411            1 :                             MinCurvePLR = CurveInput;
     412              :                         }
     413          100 :                         if (CurveVal > MaxCurveVal) {
     414           20 :                             MaxCurveVal = CurveVal;
     415           20 :                             MaxCurvePLR = CurveInput;
     416              :                         }
     417          100 :                         CurveInput += 0.01;
     418              :                     }
     419            1 :                     if (MinCurveVal < 0.7) {
     420            0 :                         ShowWarningError(state, format("{}{}=\"{}\", invalid", RoutineName, CurrentModuleObject, heatPump.Name));
     421            0 :                         ShowContinueError(state, format("...{}=\"{}\" has out of range values.", cAlphaFields(8), AlphArray(8)));
     422            0 :                         ShowContinueError(state,
     423            0 :                                           format("...Curve minimum must be >= 0.7, curve min at PLR = {:.2T} is {:.3T}", MinCurvePLR, MinCurveVal));
     424            0 :                         ShowContinueError(state, "...Setting curve minimum to 0.7 and simulation continues.");
     425            0 :                         Curve::SetCurveOutputMinValue(state, heatPump.PLFCurveIndex, ErrorsFound, 0.7);
     426              :                     }
     427              : 
     428            1 :                     if (MaxCurveVal > 1.0) {
     429            0 :                         ShowWarningError(state, format("{}{}=\"{}\", invalid", RoutineName, CurrentModuleObject, heatPump.Name));
     430            0 :                         ShowContinueError(state, format("...{} = {} has out of range value.", cAlphaFields(8), AlphArray(8)));
     431            0 :                         ShowContinueError(state,
     432            0 :                                           format("...Curve maximum must be <= 1.0, curve max at PLR = {:.2T} is {:.3T}", MaxCurvePLR, MaxCurveVal));
     433            0 :                         ShowContinueError(state, "...Setting curve maximum to 1.0 and simulation continues.");
     434            0 :                         Curve::SetCurveOutputMaxValue(state, heatPump.PLFCurveIndex, ErrorsFound, 1.0);
     435              :                     }
     436              :                 }
     437              :             }
     438              : 
     439            1 :             heatPump.MaxONOFFCyclesperHour = NumArray(21);
     440            1 :             heatPump.LatentCapacityTimeConstant = NumArray(22);
     441            1 :             heatPump.FanDelayTime = NumArray(23);
     442              : 
     443            2 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(4), AlphArray(5), "Water Nodes");
     444            1 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(6), AlphArray(7), "Air Nodes");
     445              : 
     446              :             // Setup Report variables for the detailed cooling Heat Pump
     447              :             // CurrentModuleObject = "Coil:Cooling:WaterToAirHeatPump:ParameterEstimation"
     448            2 :             SetupOutputVariable(state,
     449              :                                 "Cooling Coil Electricity Energy",
     450              :                                 Constant::Units::J,
     451            1 :                                 heatPump.Energy,
     452              :                                 OutputProcessor::TimeStepType::System,
     453              :                                 OutputProcessor::StoreType::Sum,
     454            1 :                                 heatPump.Name,
     455              :                                 Constant::eResource::Electricity,
     456              :                                 OutputProcessor::Group::HVAC,
     457              :                                 OutputProcessor::EndUseCat::Cooling);
     458            2 :             SetupOutputVariable(state,
     459              :                                 "Cooling Coil Total Cooling Energy",
     460              :                                 Constant::Units::J,
     461            1 :                                 heatPump.EnergyLoadTotal,
     462              :                                 OutputProcessor::TimeStepType::System,
     463              :                                 OutputProcessor::StoreType::Sum,
     464            1 :                                 heatPump.Name,
     465              :                                 Constant::eResource::EnergyTransfer,
     466              :                                 OutputProcessor::Group::HVAC,
     467              :                                 OutputProcessor::EndUseCat::CoolingCoils);
     468            2 :             SetupOutputVariable(state,
     469              :                                 "Cooling Coil Sensible Cooling Energy",
     470              :                                 Constant::Units::J,
     471            1 :                                 heatPump.EnergySensible,
     472              :                                 OutputProcessor::TimeStepType::System,
     473              :                                 OutputProcessor::StoreType::Sum,
     474            1 :                                 heatPump.Name);
     475            2 :             SetupOutputVariable(state,
     476              :                                 "Cooling Coil Latent Cooling Energy",
     477              :                                 Constant::Units::J,
     478            1 :                                 heatPump.EnergyLatent,
     479              :                                 OutputProcessor::TimeStepType::System,
     480              :                                 OutputProcessor::StoreType::Sum,
     481            1 :                                 heatPump.Name);
     482            2 :             SetupOutputVariable(state,
     483              :                                 "Cooling Coil Source Side Heat Transfer Energy",
     484              :                                 Constant::Units::J,
     485            1 :                                 heatPump.EnergySource,
     486              :                                 OutputProcessor::TimeStepType::System,
     487              :                                 OutputProcessor::StoreType::Sum,
     488            1 :                                 heatPump.Name,
     489              :                                 Constant::eResource::PlantLoopCoolingDemand,
     490              :                                 OutputProcessor::Group::HVAC,
     491              :                                 OutputProcessor::EndUseCat::CoolingCoils);
     492              : 
     493              :             // save the design source side flow rate for use by plant loop sizing algorithms
     494            1 :             PlantUtilities::RegisterPlantCompDesignFlow(state, heatPump.WaterInletNodeNum, 0.5 * heatPump.DesignWaterVolFlowRate);
     495              : 
     496              :             // create predefined report entries
     497            1 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilType, heatPump.Name, CurrentModuleObject);
     498            1 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilTotCap, heatPump.Name, heatPump.CoolingCapacity);
     499            1 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilSensCap, heatPump.Name, "-");
     500            1 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilLatCap, heatPump.Name, "-");
     501            1 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilSHR, heatPump.Name, "-");
     502            1 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilNomEff, heatPump.Name, "-");
     503              :         }
     504              : 
     505            1 :         CurrentModuleObject = "Coil:Heating:WaterToAirHeatPump:ParameterEstimation";
     506              : 
     507            2 :         for (WatertoAirHPNum = 1; WatertoAirHPNum <= NumHeat; ++WatertoAirHPNum) {
     508              : 
     509            1 :             ++HPNum;
     510              : 
     511            1 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     512              :                                                                      CurrentModuleObject,
     513              :                                                                      WatertoAirHPNum,
     514              :                                                                      AlphArray,
     515              :                                                                      NumAlphas,
     516              :                                                                      NumArray,
     517              :                                                                      NumNums,
     518              :                                                                      IOStat,
     519              :                                                                      lNumericBlanks,
     520              :                                                                      lAlphaBlanks,
     521              :                                                                      cAlphaFields,
     522              :                                                                      cNumericFields);
     523              : 
     524            1 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, AlphArray(1)};
     525              : 
     526              :             // ErrorsFound will be set to True if problem was found, left untouched otherwise
     527            1 :             GlobalNames::VerifyUniqueCoilName(state, CurrentModuleObject, AlphArray(1), ErrorsFound, CurrentModuleObject + " Name");
     528            1 :             auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
     529              : 
     530            1 :             heatPump.Name = AlphArray(1);
     531            1 :             heatPump.WatertoAirHPType = "HEATING";
     532            1 :             heatPump.WAHPType = DataPlant::PlantEquipmentType::CoilWAHPHeatingParamEst;
     533            1 :             heatPump.Refrigerant = AlphArray(3);
     534            1 :             if (heatPump.Refrigerant.empty()) {
     535            0 :                 ShowSevereEmptyField(state, eoh, cAlphaFields(3));
     536            0 :                 ErrorsFound = true;
     537            1 :             } else if ((heatPump.refrig = Fluid::GetRefrig(state, heatPump.Refrigerant)) == nullptr) {
     538            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(3), AlphArray(3));
     539            0 :                 ErrorsFound = true;
     540              :             }
     541            1 :             heatPump.DesignWaterVolFlowRate = NumArray(1);
     542            1 :             heatPump.HeatingCapacity = NumArray(2);
     543              : 
     544            1 :             heatPump.HighPressCutoff = NumArray(3);
     545            1 :             heatPump.LowPressCutoff = NumArray(4);
     546              : 
     547            1 :             heatPump.WaterInletNodeNum = GetOnlySingleNode(state,
     548            1 :                                                            AlphArray(4),
     549              :                                                            ErrorsFound,
     550              :                                                            DataLoopNode::ConnectionObjectType::CoilHeatingWaterToAirHeatPumpParameterEstimation,
     551            1 :                                                            AlphArray(1),
     552              :                                                            DataLoopNode::NodeFluidType::Water,
     553              :                                                            DataLoopNode::ConnectionType::Inlet,
     554              :                                                            NodeInputManager::CompFluidStream::Secondary,
     555              :                                                            DataLoopNode::ObjectIsNotParent);
     556            1 :             heatPump.WaterOutletNodeNum = GetOnlySingleNode(state,
     557            1 :                                                             AlphArray(5),
     558              :                                                             ErrorsFound,
     559              :                                                             DataLoopNode::ConnectionObjectType::CoilHeatingWaterToAirHeatPumpParameterEstimation,
     560            1 :                                                             AlphArray(1),
     561              :                                                             DataLoopNode::NodeFluidType::Water,
     562              :                                                             DataLoopNode::ConnectionType::Outlet,
     563              :                                                             NodeInputManager::CompFluidStream::Secondary,
     564              :                                                             DataLoopNode::ObjectIsNotParent);
     565            1 :             heatPump.AirInletNodeNum = GetOnlySingleNode(state,
     566            1 :                                                          AlphArray(6),
     567              :                                                          ErrorsFound,
     568              :                                                          DataLoopNode::ConnectionObjectType::CoilHeatingWaterToAirHeatPumpParameterEstimation,
     569            1 :                                                          AlphArray(1),
     570              :                                                          DataLoopNode::NodeFluidType::Air,
     571              :                                                          DataLoopNode::ConnectionType::Inlet,
     572              :                                                          NodeInputManager::CompFluidStream::Primary,
     573              :                                                          DataLoopNode::ObjectIsNotParent);
     574            1 :             heatPump.AirOutletNodeNum = GetOnlySingleNode(state,
     575            1 :                                                           AlphArray(7),
     576              :                                                           ErrorsFound,
     577              :                                                           DataLoopNode::ConnectionObjectType::CoilHeatingWaterToAirHeatPumpParameterEstimation,
     578            1 :                                                           AlphArray(1),
     579              :                                                           DataLoopNode::NodeFluidType::Air,
     580              :                                                           DataLoopNode::ConnectionType::Outlet,
     581              :                                                           NodeInputManager::CompFluidStream::Primary,
     582              :                                                           DataLoopNode::ObjectIsNotParent);
     583              : 
     584            1 :             heatPump.LoadSideTotalUACoeff = NumArray(5);
     585            1 :             if (heatPump.LoadSideTotalUACoeff < Constant::rTinyValue) {
     586            0 :                 ShowSevereError(state, format("Input problem for {}={}", CurrentModuleObject, heatPump.Name));
     587            0 :                 ShowContinueError(state, " Load side UA value is less than tolerance, likely zero or blank.");
     588            0 :                 ShowContinueError(state, " Verify inputs, as the parameter syntax for this object went through a change with");
     589            0 :                 ShowContinueError(state, "  the release of EnergyPlus version 5.");
     590            0 :                 ErrorsFound = true;
     591              :             }
     592              : 
     593            1 :             heatPump.SuperheatTemp = NumArray(6);
     594            1 :             heatPump.PowerLosses = NumArray(7);
     595            1 :             heatPump.LossFactor = NumArray(8);
     596              : 
     597            1 :             heatPump.compressorType = static_cast<CompressorType>(getEnumValue(CompressTypeNamesUC, Util::makeUPPER(AlphArray(2))));
     598              : 
     599            1 :             switch (heatPump.compressorType) {
     600            0 :             case CompressorType::Reciprocating: {
     601            0 :                 heatPump.CompPistonDisp = NumArray(9);
     602            0 :                 heatPump.CompSucPressDrop = NumArray(10);
     603            0 :                 heatPump.CompClearanceFactor = NumArray(11);
     604            0 :                 break;
     605              :             }
     606            0 :             case CompressorType::Rotary: {
     607            0 :                 heatPump.CompPistonDisp = NumArray(9);
     608            0 :                 heatPump.CompSucPressDrop = NumArray(10);
     609            0 :                 break;
     610              :             }
     611            1 :             case CompressorType::Scroll: {
     612            1 :                 heatPump.RefVolFlowRate = NumArray(12);
     613            1 :                 heatPump.VolumeRatio = NumArray(13);
     614            1 :                 heatPump.LeakRateCoeff = NumArray(14);
     615            1 :                 break;
     616              :             }
     617            0 :             default: {
     618            0 :                 ShowSevereError(
     619              :                     state,
     620            0 :                     format("{}Invalid {} ({}) entered. {}={}", RoutineName, cAlphaFields(2), AlphArray(2), CurrentModuleObject, heatPump.Name));
     621            0 :                 ErrorsFound = true;
     622            0 :                 break;
     623              :             }
     624              :             }
     625              : 
     626            1 :             heatPump.SourceSideUACoeff = NumArray(15);
     627            1 :             heatPump.SourceSideHTR1 = NumArray(16);
     628            1 :             heatPump.SourceSideHTR2 = NumArray(17);
     629              : 
     630            1 :             heatPump.PLFCurveIndex = Curve::GetCurveIndex(state, AlphArray(8)); // convert curve name to number
     631              : 
     632            1 :             if (heatPump.PLFCurveIndex == 0) {
     633            0 :                 if (lAlphaBlanks(8)) {
     634            0 :                     ShowSevereError(state, format("{}{}=\"{}\", missing", RoutineName, CurrentModuleObject, heatPump.Name));
     635            0 :                     ShowContinueError(state, format("...required {} is blank.", cAlphaFields(8)));
     636              :                 } else {
     637            0 :                     ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, CurrentModuleObject, heatPump.Name));
     638            0 :                     ShowContinueError(state, format("...not found {}=\"{}\".", cAlphaFields(8), AlphArray(8)));
     639              :                 }
     640            0 :                 ErrorsFound = true;
     641              :             } else {
     642              :                 // Verify Curve Object, only legal types are Quadratic or Cubic
     643            2 :                 ErrorsFound |= Curve::CheckCurveDims(state,
     644              :                                                      heatPump.PLFCurveIndex, // Curve index
     645              :                                                      {1},                    // Valid dimensions
     646              :                                                      RoutineName,            // Routine name
     647              :                                                      CurrentModuleObject,    // Object Type
     648              :                                                      heatPump.Name,          // Object Name
     649            1 :                                                      cAlphaFields(8));       // Field Name
     650              : 
     651            1 :                 if (!ErrorsFound) {
     652              :                     //     Test PLF curve minimum and maximum. Cap if less than 0.7 or greater than 1.0.
     653            1 :                     Real64 MinCurveVal = 999.0;
     654            1 :                     Real64 MaxCurveVal = -999.0;
     655            1 :                     Real64 CurveInput = 0.0;
     656            1 :                     Real64 MinCurvePLR{0.0};
     657            1 :                     Real64 MaxCurvePLR{0.0};
     658              : 
     659          101 :                     while (CurveInput <= 1.0) {
     660          100 :                         Real64 CurveVal = Curve::CurveValue(state, heatPump.PLFCurveIndex, CurveInput);
     661          100 :                         if (CurveVal < MinCurveVal) {
     662            1 :                             MinCurveVal = CurveVal;
     663            1 :                             MinCurvePLR = CurveInput;
     664              :                         }
     665          100 :                         if (CurveVal > MaxCurveVal) {
     666           20 :                             MaxCurveVal = CurveVal;
     667           20 :                             MaxCurvePLR = CurveInput;
     668              :                         }
     669          100 :                         CurveInput += 0.01;
     670              :                     }
     671            1 :                     if (MinCurveVal < 0.7) {
     672            0 :                         ShowWarningError(state, format("{}{}=\"{}\", invalid", RoutineName, CurrentModuleObject, heatPump.Name));
     673            0 :                         ShowContinueError(state, format("...{}=\"{}\" has out of range values.", cAlphaFields(9), AlphArray(9)));
     674            0 :                         ShowContinueError(state,
     675            0 :                                           format("...Curve minimum must be >= 0.7, curve min at PLR = {:.2T} is {:.3T}", MinCurvePLR, MinCurveVal));
     676            0 :                         ShowContinueError(state, "...Setting curve minimum to 0.7 and simulation continues.");
     677            0 :                         Curve::SetCurveOutputMinValue(state, heatPump.PLFCurveIndex, ErrorsFound, 0.7);
     678              :                     }
     679              : 
     680            1 :                     if (MaxCurveVal > 1.0) {
     681            0 :                         ShowWarningError(state, format("{}{}=\"{}\", invalid", RoutineName, CurrentModuleObject, heatPump.Name));
     682            0 :                         ShowContinueError(state, format("...{} = {} has out of range value.", cAlphaFields(9), AlphArray(9)));
     683            0 :                         ShowContinueError(state,
     684            0 :                                           format("...Curve maximum must be <= 1.0, curve max at PLR = {:.2T} is {:.3T}", MaxCurvePLR, MaxCurveVal));
     685            0 :                         ShowContinueError(state, "...Setting curve maximum to 1.0 and simulation continues.");
     686            0 :                         Curve::SetCurveOutputMaxValue(state, heatPump.PLFCurveIndex, ErrorsFound, 1.0);
     687              :                     }
     688              :                 }
     689              :             }
     690              : 
     691            2 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(4), AlphArray(5), "Water Nodes");
     692            1 :             BranchNodeConnections::TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(6), AlphArray(7), "Air Nodes");
     693              : 
     694              :             // CurrentModuleObject = "Coil:Heating:WaterToAirHeatPump:ParameterEstimation"
     695            2 :             SetupOutputVariable(state,
     696              :                                 "Heating Coil Electricity Energy",
     697              :                                 Constant::Units::J,
     698            1 :                                 heatPump.Energy,
     699              :                                 OutputProcessor::TimeStepType::System,
     700              :                                 OutputProcessor::StoreType::Sum,
     701            1 :                                 heatPump.Name,
     702              :                                 Constant::eResource::Electricity,
     703              :                                 OutputProcessor::Group::HVAC,
     704              :                                 OutputProcessor::EndUseCat::Heating);
     705            2 :             SetupOutputVariable(state,
     706              :                                 "Heating Coil Heating Energy",
     707              :                                 Constant::Units::J,
     708            1 :                                 heatPump.EnergyLoadTotal,
     709              :                                 OutputProcessor::TimeStepType::System,
     710              :                                 OutputProcessor::StoreType::Sum,
     711            1 :                                 heatPump.Name,
     712              :                                 Constant::eResource::EnergyTransfer,
     713              :                                 OutputProcessor::Group::HVAC,
     714              :                                 OutputProcessor::EndUseCat::HeatingCoils);
     715            2 :             SetupOutputVariable(state,
     716              :                                 "Heating Coil Source Side Heat Transfer Energy",
     717              :                                 Constant::Units::J,
     718            1 :                                 heatPump.EnergySource,
     719              :                                 OutputProcessor::TimeStepType::System,
     720              :                                 OutputProcessor::StoreType::Sum,
     721            1 :                                 heatPump.Name,
     722              :                                 Constant::eResource::PlantLoopHeatingDemand,
     723              :                                 OutputProcessor::Group::HVAC,
     724              :                                 OutputProcessor::EndUseCat::HeatingCoils);
     725              : 
     726              :             // save the design source side flow rate for use by plant loop sizing algorithms
     727            1 :             PlantUtilities::RegisterPlantCompDesignFlow(state, heatPump.WaterInletNodeNum, 0.5 * heatPump.DesignWaterVolFlowRate);
     728              : 
     729              :             // create predefined report entries
     730            1 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilType, heatPump.Name, CurrentModuleObject);
     731            1 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilNomCap, heatPump.Name, heatPump.HeatingCapacity);
     732            1 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilNomEff, heatPump.Name, "-");
     733              :         }
     734              : 
     735            1 :         AlphArray.deallocate();
     736            1 :         cAlphaFields.deallocate();
     737            1 :         lAlphaBlanks.deallocate();
     738            1 :         cNumericFields.deallocate();
     739            1 :         lNumericBlanks.deallocate();
     740            1 :         NumArray.deallocate();
     741              : 
     742            1 :         if (ErrorsFound) {
     743            0 :             ShowFatalError(state, format("{}Errors found getting input. Program terminates.", RoutineName));
     744              :         }
     745              : 
     746            3 :         for (HPNum = 1; HPNum <= state.dataWaterToAirHeatPump->NumWatertoAirHPs; ++HPNum) {
     747              : 
     748            2 :             auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
     749            2 :             if (heatPump.WAHPType == DataPlant::PlantEquipmentType::CoilWAHPCoolingParamEst) {
     750              :                 // COOLING COIL: Setup Report variables for the Heat Pump
     751            2 :                 SetupOutputVariable(state,
     752              :                                     "Cooling Coil Electricity Rate",
     753              :                                     Constant::Units::W,
     754            1 :                                     heatPump.Power,
     755              :                                     OutputProcessor::TimeStepType::System,
     756              :                                     OutputProcessor::StoreType::Average,
     757            1 :                                     heatPump.Name);
     758              : 
     759            2 :                 SetupOutputVariable(state,
     760              :                                     "Cooling Coil Total Cooling Rate",
     761              :                                     Constant::Units::W,
     762            1 :                                     heatPump.QLoadTotal,
     763              :                                     OutputProcessor::TimeStepType::System,
     764              :                                     OutputProcessor::StoreType::Average,
     765            1 :                                     heatPump.Name);
     766              : 
     767            2 :                 SetupOutputVariable(state,
     768              :                                     "Cooling Coil Sensible Cooling Rate",
     769              :                                     Constant::Units::W,
     770            1 :                                     heatPump.QSensible,
     771              :                                     OutputProcessor::TimeStepType::System,
     772              :                                     OutputProcessor::StoreType::Average,
     773            1 :                                     heatPump.Name);
     774              : 
     775            2 :                 SetupOutputVariable(state,
     776              :                                     "Cooling Coil Latent Cooling Rate",
     777              :                                     Constant::Units::W,
     778            1 :                                     heatPump.QLatent,
     779              :                                     OutputProcessor::TimeStepType::System,
     780              :                                     OutputProcessor::StoreType::Average,
     781            1 :                                     heatPump.Name);
     782              : 
     783            2 :                 SetupOutputVariable(state,
     784              :                                     "Cooling Coil Source Side Heat Transfer Rate",
     785              :                                     Constant::Units::W,
     786            1 :                                     heatPump.QSource,
     787              :                                     OutputProcessor::TimeStepType::System,
     788              :                                     OutputProcessor::StoreType::Average,
     789            1 :                                     heatPump.Name);
     790              : 
     791            2 :                 SetupOutputVariable(state,
     792              :                                     "Cooling Coil Part Load Ratio",
     793              :                                     Constant::Units::None,
     794            1 :                                     heatPump.PartLoadRatio,
     795              :                                     OutputProcessor::TimeStepType::System,
     796              :                                     OutputProcessor::StoreType::Average,
     797            1 :                                     heatPump.Name);
     798            2 :                 SetupOutputVariable(state,
     799              :                                     "Cooling Coil Runtime Fraction",
     800              :                                     Constant::Units::None,
     801            1 :                                     heatPump.RunFrac,
     802              :                                     OutputProcessor::TimeStepType::System,
     803              :                                     OutputProcessor::StoreType::Average,
     804            1 :                                     heatPump.Name);
     805              : 
     806            2 :                 SetupOutputVariable(state,
     807              :                                     "Cooling Coil Air Mass Flow Rate",
     808              :                                     Constant::Units::kg_s,
     809            1 :                                     heatPump.OutletAirMassFlowRate,
     810              :                                     OutputProcessor::TimeStepType::System,
     811              :                                     OutputProcessor::StoreType::Average,
     812            1 :                                     heatPump.Name);
     813            2 :                 SetupOutputVariable(state,
     814              :                                     "Cooling Coil Air Inlet Temperature",
     815              :                                     Constant::Units::C,
     816            1 :                                     heatPump.InletAirDBTemp,
     817              :                                     OutputProcessor::TimeStepType::System,
     818              :                                     OutputProcessor::StoreType::Average,
     819            1 :                                     heatPump.Name);
     820            2 :                 SetupOutputVariable(state,
     821              :                                     "Cooling Coil Air Inlet Humidity Ratio",
     822              :                                     Constant::Units::kgWater_kgDryAir,
     823            1 :                                     heatPump.InletAirHumRat,
     824              :                                     OutputProcessor::TimeStepType::System,
     825              :                                     OutputProcessor::StoreType::Average,
     826            1 :                                     heatPump.Name);
     827            2 :                 SetupOutputVariable(state,
     828              :                                     "Cooling Coil Air Outlet Temperature",
     829              :                                     Constant::Units::C,
     830            1 :                                     heatPump.OutletAirDBTemp,
     831              :                                     OutputProcessor::TimeStepType::System,
     832              :                                     OutputProcessor::StoreType::Average,
     833            1 :                                     heatPump.Name);
     834            2 :                 SetupOutputVariable(state,
     835              :                                     "Cooling Coil Air Outlet Humidity Ratio",
     836              :                                     Constant::Units::kgWater_kgDryAir,
     837            1 :                                     heatPump.OutletAirHumRat,
     838              :                                     OutputProcessor::TimeStepType::System,
     839              :                                     OutputProcessor::StoreType::Average,
     840            1 :                                     heatPump.Name);
     841              : 
     842            2 :                 SetupOutputVariable(state,
     843              :                                     "Cooling Coil Source Side Mass Flow Rate",
     844              :                                     Constant::Units::kg_s,
     845            1 :                                     heatPump.OutletWaterMassFlowRate,
     846              :                                     OutputProcessor::TimeStepType::System,
     847              :                                     OutputProcessor::StoreType::Average,
     848            1 :                                     heatPump.Name);
     849            2 :                 SetupOutputVariable(state,
     850              :                                     "Cooling Coil Source Side Inlet Temperature",
     851              :                                     Constant::Units::C,
     852            1 :                                     heatPump.InletWaterTemp,
     853              :                                     OutputProcessor::TimeStepType::System,
     854              :                                     OutputProcessor::StoreType::Average,
     855            1 :                                     heatPump.Name);
     856            2 :                 SetupOutputVariable(state,
     857              :                                     "Cooling Coil Source Side Outlet Temperature",
     858              :                                     Constant::Units::C,
     859            1 :                                     heatPump.OutletWaterTemp,
     860              :                                     OutputProcessor::TimeStepType::System,
     861              :                                     OutputProcessor::StoreType::Average,
     862            1 :                                     heatPump.Name);
     863            1 :             } else if (heatPump.WAHPType == DataPlant::PlantEquipmentType::CoilWAHPHeatingParamEst) {
     864              :                 // HEATING COIL Setup Report variables for the Heat Pump
     865            2 :                 SetupOutputVariable(state,
     866              :                                     "Heating Coil Electricity Rate",
     867              :                                     Constant::Units::W,
     868            1 :                                     heatPump.Power,
     869              :                                     OutputProcessor::TimeStepType::System,
     870              :                                     OutputProcessor::StoreType::Average,
     871            1 :                                     heatPump.Name);
     872              : 
     873            2 :                 SetupOutputVariable(state,
     874              :                                     "Heating Coil Heating Rate",
     875              :                                     Constant::Units::W,
     876            1 :                                     heatPump.QLoadTotal,
     877              :                                     OutputProcessor::TimeStepType::System,
     878              :                                     OutputProcessor::StoreType::Average,
     879            1 :                                     heatPump.Name);
     880              : 
     881            2 :                 SetupOutputVariable(state,
     882              :                                     "Heating Coil Sensible Heating Rate",
     883              :                                     Constant::Units::W,
     884            1 :                                     heatPump.QSensible,
     885              :                                     OutputProcessor::TimeStepType::System,
     886              :                                     OutputProcessor::StoreType::Average,
     887            1 :                                     heatPump.Name);
     888              : 
     889            2 :                 SetupOutputVariable(state,
     890              :                                     "Heating Coil Source Side Heat Transfer Rate",
     891              :                                     Constant::Units::W,
     892            1 :                                     heatPump.QSource,
     893              :                                     OutputProcessor::TimeStepType::System,
     894              :                                     OutputProcessor::StoreType::Average,
     895            1 :                                     heatPump.Name);
     896              : 
     897            2 :                 SetupOutputVariable(state,
     898              :                                     "Heating Coil Part Load Ratio",
     899              :                                     Constant::Units::None,
     900            1 :                                     heatPump.PartLoadRatio,
     901              :                                     OutputProcessor::TimeStepType::System,
     902              :                                     OutputProcessor::StoreType::Average,
     903            1 :                                     heatPump.Name);
     904            2 :                 SetupOutputVariable(state,
     905              :                                     "Heating Coil Runtime Fraction",
     906              :                                     Constant::Units::None,
     907            1 :                                     heatPump.RunFrac,
     908              :                                     OutputProcessor::TimeStepType::System,
     909              :                                     OutputProcessor::StoreType::Average,
     910            1 :                                     heatPump.Name);
     911              : 
     912            2 :                 SetupOutputVariable(state,
     913              :                                     "Heating Coil Air Mass Flow Rate",
     914              :                                     Constant::Units::kg_s,
     915            1 :                                     heatPump.OutletAirMassFlowRate,
     916              :                                     OutputProcessor::TimeStepType::System,
     917              :                                     OutputProcessor::StoreType::Average,
     918            1 :                                     heatPump.Name);
     919            2 :                 SetupOutputVariable(state,
     920              :                                     "Heating Coil Air Inlet Temperature",
     921              :                                     Constant::Units::C,
     922            1 :                                     heatPump.InletAirDBTemp,
     923              :                                     OutputProcessor::TimeStepType::System,
     924              :                                     OutputProcessor::StoreType::Average,
     925            1 :                                     heatPump.Name);
     926            2 :                 SetupOutputVariable(state,
     927              :                                     "Heating Coil Air Inlet Humidity Ratio",
     928              :                                     Constant::Units::kgWater_kgDryAir,
     929            1 :                                     heatPump.InletAirHumRat,
     930              :                                     OutputProcessor::TimeStepType::System,
     931              :                                     OutputProcessor::StoreType::Average,
     932            1 :                                     heatPump.Name);
     933            2 :                 SetupOutputVariable(state,
     934              :                                     "Heating Coil Air Outlet Temperature",
     935              :                                     Constant::Units::C,
     936            1 :                                     heatPump.OutletAirDBTemp,
     937              :                                     OutputProcessor::TimeStepType::System,
     938              :                                     OutputProcessor::StoreType::Average,
     939            1 :                                     heatPump.Name);
     940            2 :                 SetupOutputVariable(state,
     941              :                                     "Heating Coil Air Outlet Humidity Ratio",
     942              :                                     Constant::Units::kgWater_kgDryAir,
     943            1 :                                     heatPump.OutletAirHumRat,
     944              :                                     OutputProcessor::TimeStepType::System,
     945              :                                     OutputProcessor::StoreType::Average,
     946            1 :                                     heatPump.Name);
     947              : 
     948            2 :                 SetupOutputVariable(state,
     949              :                                     "Heating Coil Source Side Mass Flow Rate",
     950              :                                     Constant::Units::kg_s,
     951            1 :                                     heatPump.OutletWaterMassFlowRate,
     952              :                                     OutputProcessor::TimeStepType::System,
     953              :                                     OutputProcessor::StoreType::Average,
     954            1 :                                     heatPump.Name);
     955            2 :                 SetupOutputVariable(state,
     956              :                                     "Heating Coil Source Side Inlet Temperature",
     957              :                                     Constant::Units::C,
     958            1 :                                     heatPump.InletWaterTemp,
     959              :                                     OutputProcessor::TimeStepType::System,
     960              :                                     OutputProcessor::StoreType::Average,
     961            1 :                                     heatPump.Name);
     962            2 :                 SetupOutputVariable(state,
     963              :                                     "Heating Coil Source Side Outlet Temperature",
     964              :                                     Constant::Units::C,
     965            1 :                                     heatPump.OutletWaterTemp,
     966              :                                     OutputProcessor::TimeStepType::System,
     967              :                                     OutputProcessor::StoreType::Average,
     968            1 :                                     heatPump.Name);
     969              :             }
     970              :         }
     971            1 :     }
     972              : 
     973            2 :     void InitWatertoAirHP(EnergyPlusData &state,
     974              :                           int const HPNum, // index to main heat pump data structure
     975              :                           bool const InitFlag,
     976              :                           Real64 const SensLoad,
     977              :                           Real64 const LatentLoad,
     978              :                           Real64 const DesignAirFlow,
     979              :                           Real64 const PartLoadRatio)
     980              :     {
     981              : 
     982              :         // SUBROUTINE INFORMATION:
     983              :         //       AUTHOR         Hui Jin
     984              :         //       DATE WRITTEN   Oct 2000
     985              :         //       MODIFIED       Dan Fisher, Kenneth Tang (Jan 2004)
     986              :         //                      Brent Griffith, Sept 2010, plant upgrades, general fluid properties
     987              : 
     988              :         // PURPOSE OF THIS SUBROUTINE:
     989              :         // This subroutine is for initializations of the Water to Air HP Components.
     990              : 
     991              :         // METHODOLOGY EMPLOYED:
     992              :         // Uses the status flags to trigger initializations.
     993              : 
     994              :         // Using/Aliasing
     995            2 :         auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
     996              : 
     997              :         static constexpr std::string_view RoutineName("InitWatertoAirHP");
     998            2 :         int WaterInletNode = heatPump.WaterInletNodeNum;
     999              : 
    1000            2 :         if (state.dataWaterToAirHeatPump->MyOneTimeFlag) {
    1001            1 :             state.dataWaterToAirHeatPump->MyEnvrnFlag.allocate(state.dataWaterToAirHeatPump->NumWatertoAirHPs);
    1002            1 :             state.dataWaterToAirHeatPump->MyPlantScanFlag.allocate(state.dataWaterToAirHeatPump->NumWatertoAirHPs);
    1003            1 :             state.dataWaterToAirHeatPump->MyEnvrnFlag = true;
    1004            1 :             state.dataWaterToAirHeatPump->MyPlantScanFlag = true;
    1005            1 :             state.dataWaterToAirHeatPump->MyOneTimeFlag = false;
    1006              :         }
    1007              : 
    1008            2 :         if (state.dataWaterToAirHeatPump->MyPlantScanFlag(HPNum) && allocated(state.dataPlnt->PlantLoop)) {
    1009            2 :             bool errFlag = false;
    1010            2 :             PlantUtilities::ScanPlantLoopsForObject(state, heatPump.Name, heatPump.WAHPType, heatPump.plantLoc, errFlag, _, _, _, _, _);
    1011              : 
    1012            2 :             if (state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).FluidName == "WATER") {
    1013            2 :                 if (heatPump.SourceSideUACoeff < Constant::rTinyValue) {
    1014            0 :                     ShowSevereError(state, format("Input problem for water to air heat pump, \"{}\".", heatPump.Name));
    1015            0 :                     ShowContinueError(state, " Source side UA value is less than tolerance, likely zero or blank.");
    1016            0 :                     ShowContinueError(state, " Verify inputs, as the parameter syntax for this object went through a change with");
    1017            0 :                     ShowContinueError(state, "  the release of EnergyPlus version 5.");
    1018            0 :                     errFlag = true;
    1019              :                 }
    1020              :             } else {
    1021            0 :                 if ((heatPump.SourceSideHTR1 < Constant::rTinyValue) || (heatPump.SourceSideHTR2 < Constant::rTinyValue)) {
    1022            0 :                     ShowSevereError(state, format("Input problem for water to air heat pump, \"{}\".", heatPump.Name));
    1023            0 :                     ShowContinueError(state, " A source side heat transfer resistance value is less than tolerance, likely zero or blank.");
    1024            0 :                     ShowContinueError(state, " Verify inputs, as the parameter syntax for this object went through a change with");
    1025            0 :                     ShowContinueError(state, "  the release of EnergyPlus version 5.");
    1026            0 :                     errFlag = true;
    1027              :                 }
    1028              :             }
    1029              : 
    1030            2 :             if (errFlag) {
    1031            0 :                 ShowFatalError(state, "InitWatertoAirHP: Program terminated for previous conditions.");
    1032              :             }
    1033              : 
    1034            2 :             state.dataWaterToAirHeatPump->MyPlantScanFlag(HPNum) = false;
    1035              :         }
    1036              : 
    1037              :         // Do the Begin Environment initializations
    1038            2 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataWaterToAirHeatPump->MyEnvrnFlag(HPNum) &&
    1039            0 :             !state.dataWaterToAirHeatPump->MyPlantScanFlag(HPNum)) {
    1040              : 
    1041              :             // Initialize all report variables to a known state at beginning of simulation
    1042            0 :             heatPump.Power = 0.0;
    1043            0 :             heatPump.Energy = 0.0;
    1044            0 :             heatPump.QLoadTotal = 0.0;
    1045            0 :             heatPump.QSensible = 0.0;
    1046            0 :             heatPump.QLatent = 0.0;
    1047            0 :             heatPump.QSource = 0.0;
    1048            0 :             heatPump.EnergyLoadTotal = 0.0;
    1049            0 :             heatPump.EnergySensible = 0.0;
    1050            0 :             heatPump.EnergyLatent = 0.0;
    1051            0 :             heatPump.EnergySource = 0.0;
    1052            0 :             heatPump.RunFrac = 0.0;
    1053            0 :             heatPump.PartLoadRatio = 0.0;
    1054            0 :             heatPump.OutletAirDBTemp = 0.0;
    1055            0 :             heatPump.OutletAirHumRat = 0.0;
    1056            0 :             heatPump.InletAirDBTemp = 0.0;
    1057            0 :             heatPump.InletAirHumRat = 0.0;
    1058            0 :             heatPump.OutletWaterTemp = 0.0;
    1059            0 :             heatPump.InletWaterTemp = 0.0;
    1060            0 :             heatPump.InletAirMassFlowRate = 0.0;
    1061            0 :             heatPump.InletWaterMassFlowRate = 0.0;
    1062            0 :             heatPump.OutletAirEnthalpy = 0.0;
    1063            0 :             heatPump.OutletWaterEnthalpy = 0.0;
    1064              : 
    1065              :             // The rest of the one time initializations
    1066            0 :             Real64 rho = state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).glycol->getDensity(state, Constant::InitConvTemp, RoutineName);
    1067            0 :             Real64 Cp = state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).glycol->getSpecificHeat(state, Constant::InitConvTemp, RoutineName);
    1068              : 
    1069            0 :             heatPump.DesignWaterMassFlowRate = rho * heatPump.DesignWaterVolFlowRate;
    1070              : 
    1071            0 :             int PlantOutletNode = DataPlant::CompData::getPlantComponent(state, heatPump.plantLoc).NodeNumOut;
    1072            0 :             PlantUtilities::InitComponentNodes(state, 0.0, heatPump.DesignWaterMassFlowRate, WaterInletNode, PlantOutletNode);
    1073              : 
    1074            0 :             state.dataLoopNodes->Node(WaterInletNode).Temp = 5.0;
    1075            0 :             state.dataLoopNodes->Node(WaterInletNode).Enthalpy = Cp * state.dataLoopNodes->Node(WaterInletNode).Temp;
    1076            0 :             state.dataLoopNodes->Node(WaterInletNode).Quality = 0.0;
    1077            0 :             state.dataLoopNodes->Node(WaterInletNode).Press = 0.0;
    1078            0 :             state.dataLoopNodes->Node(WaterInletNode).HumRat = 0.0;
    1079              : 
    1080            0 :             state.dataLoopNodes->Node(PlantOutletNode).Temp = 5.0;
    1081            0 :             state.dataLoopNodes->Node(PlantOutletNode).Enthalpy = Cp * state.dataLoopNodes->Node(WaterInletNode).Temp;
    1082            0 :             state.dataLoopNodes->Node(PlantOutletNode).Quality = 0.0;
    1083            0 :             state.dataLoopNodes->Node(PlantOutletNode).Press = 0.0;
    1084            0 :             state.dataLoopNodes->Node(PlantOutletNode).HumRat = 0.0;
    1085              : 
    1086            0 :             heatPump.SimFlag = true;
    1087              : 
    1088            0 :             state.dataWaterToAirHeatPump->MyEnvrnFlag(HPNum) = false;
    1089              :         } // End If for the Begin Environment initializations
    1090              : 
    1091            2 :         if (!state.dataGlobal->BeginEnvrnFlag) {
    1092            2 :             state.dataWaterToAirHeatPump->MyEnvrnFlag(HPNum) = true;
    1093              :         }
    1094              : 
    1095              :         // Do the following initializations (every time step): This should be the info from
    1096              :         // the previous components outlets or the node data in this section.
    1097              :         // First set the conditions for the air into the heat pump model
    1098              : 
    1099              :         // Set water and air inlet nodes
    1100            2 :         int AirInletNode = heatPump.AirInletNodeNum;
    1101              : 
    1102            2 :         if (((SensLoad != 0.0 || LatentLoad != 0.0) || (SensLoad == 0.0 && InitFlag)) && state.dataLoopNodes->Node(AirInletNode).MassFlowRate > 0.0 &&
    1103              :             PartLoadRatio > 0.0) {
    1104              :             // set the water side flow rate to the design flow rate unless constrained by
    1105              :             // the demand side manager (MIN/MAX available). now done by call to setcomponentFlowRate
    1106            2 :             heatPump.InletWaterMassFlowRate = heatPump.DesignWaterMassFlowRate;
    1107            2 :             heatPump.InletAirMassFlowRate = DesignAirFlow; // This is required instead of the node temperature
    1108              :             // because the air loop operates handles part load for
    1109              :             // cycling equipment by modulating the air flow rate
    1110              :             // the heat pump model requires an accurate (i.e. full load
    1111              :             // flow rate for accurate simulation.
    1112              :         } else { // heat pump is off
    1113            0 :             heatPump.InletWaterMassFlowRate = 0.0;
    1114              : 
    1115            0 :             heatPump.InletAirMassFlowRate = 0.0;
    1116              :         }
    1117              :         // constrain water flow provided by plant
    1118            2 :         PlantUtilities::SetComponentFlowRate(
    1119            2 :             state, heatPump.InletWaterMassFlowRate, heatPump.WaterInletNodeNum, heatPump.WaterOutletNodeNum, heatPump.plantLoc);
    1120              : 
    1121            2 :         heatPump.InletWaterTemp = state.dataLoopNodes->Node(WaterInletNode).Temp;
    1122              :         //  IF (WatertoAirHP(HPNum)%InletWaterTemp < 0.0) THEN  ! Debug trap
    1123              :         //    Temptemp         = Node(WaterInletNode)%Temp
    1124              :         //  ENDIF
    1125            2 :         heatPump.InletWaterEnthalpy = state.dataLoopNodes->Node(WaterInletNode).Enthalpy;
    1126              : 
    1127            2 :         heatPump.InletAirDBTemp = state.dataLoopNodes->Node(AirInletNode).Temp;
    1128            2 :         heatPump.InletAirHumRat = state.dataLoopNodes->Node(AirInletNode).HumRat;
    1129            2 :         heatPump.InletAirEnthalpy = state.dataLoopNodes->Node(AirInletNode).Enthalpy;
    1130              : 
    1131            2 :         heatPump.Power = 0.0;
    1132            2 :         heatPump.Energy = 0.0;
    1133            2 :         heatPump.QLoadTotal = 0.0;
    1134            2 :         heatPump.QSensible = 0.0;
    1135            2 :         heatPump.QLatent = 0.0;
    1136            2 :         heatPump.QSource = 0.0;
    1137            2 :         heatPump.EnergyLoadTotal = 0.0;
    1138            2 :         heatPump.EnergySensible = 0.0;
    1139            2 :         heatPump.EnergyLatent = 0.0;
    1140            2 :         heatPump.EnergySource = 0.0;
    1141            2 :         heatPump.RunFrac = 0.0;
    1142            2 :         heatPump.OutletAirDBTemp = 0.0;
    1143            2 :         heatPump.OutletAirHumRat = 0.0;
    1144            2 :         heatPump.OutletWaterTemp = 0.0;
    1145            2 :         heatPump.OutletAirEnthalpy = 0.0;
    1146            2 :         heatPump.OutletWaterEnthalpy = 0.0;
    1147            2 :     }
    1148              : 
    1149            1 :     void CalcWatertoAirHPCooling(EnergyPlusData &state,
    1150              :                                  int const HPNum,                      // heat pump number
    1151              :                                  HVAC::FanOp const fanOp,              // fan/compressor cycling scheme indicator
    1152              :                                  bool const FirstHVACIteration,        // first iteration flag
    1153              :                                  [[maybe_unused]] bool const InitFlag, // suppress property errors if true
    1154              :                                  Real64 const SensDemand,
    1155              :                                  HVAC::CompressorOp const compressorOp,
    1156              :                                  Real64 const PartLoadRatio)
    1157              :     {
    1158              : 
    1159              :         // SUBROUTINE INFORMATION:
    1160              :         //       AUTHOR         Hui Jin
    1161              :         //       DATE WRITTEN   Oct 2000
    1162              :         //       MODIFIED       Dan Fisher, Kenneth Tang (Jan 2004), R. Raustad (Oct 2006) Revised iteration technique
    1163              : 
    1164              :         // PURPOSE OF THIS SUBROUTINE:
    1165              :         // Simulates a parameter estimation based water to air heat pump model
    1166              : 
    1167              :         // Using/Aliasing
    1168            1 :         auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
    1169              : 
    1170              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1171            1 :         constexpr Real64 CpWater(4210.0);         // Specific heat of water J/kg_C
    1172            1 :         constexpr Real64 DegreeofSuperheat(80.0); // Initial guess of degree of superheat
    1173            1 :         constexpr Real64 gamma(1.114);            // Expansion Coefficient
    1174            1 :         constexpr Real64 ERR(0.01);               // Error Value
    1175            1 :         constexpr Real64 PB(1.013e5);             // Barometric Pressure (Pa)
    1176              : 
    1177            1 :         constexpr int STOP1(1000); // Iteration stopper1
    1178            1 :         constexpr int STOP2(1000); // Iteration stopper2
    1179            1 :         constexpr int STOP3(1000); // Iteration stopper3
    1180              : 
    1181              :         static constexpr std::string_view RoutineNameSourceSideInletTemp("CalcWatertoAirHPCooling:SourceSideInletTemp");
    1182              :         static constexpr std::string_view RoutineNameSourceSideTemp("CalcWatertoAirHPCooling:SourceSideTemp");
    1183              :         static constexpr std::string_view RoutineNameLoadSideTemp("CalcWatertoAirHPCooling:LoadSideTemp");
    1184              :         static constexpr std::string_view RoutineNameLoadSideSurfaceTemp("CalcWatertoAirHPCooling:LoadSideSurfaceTemp");
    1185              :         static constexpr std::string_view RoutineNameLoadSideEvapTemp("CalcWatertoAirHPCooling:LoadSideEvapTemp");
    1186              :         static constexpr std::string_view RoutineNameLoadSideOutletEnthalpy("CalcWatertoAirHPCooling:LoadSideOutletEnthalpy");
    1187              :         static constexpr std::string_view RoutineNameCompressInletTemp("CalcWatertoAirHPCooling:CompressInletTemp");
    1188              :         static constexpr std::string_view RoutineNameSuctionPr("CalcWatertoAirHPCooling:SuctionPr");
    1189              :         static constexpr std::string_view RoutineNameCompSuctionTemp("CalcWatertoAirHPCooling:CompSuctionTemp");
    1190              : 
    1191              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1192              :         int NumIteration3;                // Number of Iteration3
    1193              :         int NumIteration4;                // Number of Iteration4 (use of latent degradation model ONLY)
    1194              :         Real64 Quality;                   // Quality of Refrigerant
    1195              :         Real64 SourceSideOutletTemp;      // Source Side Outlet Temperature [C]
    1196              :         Real64 SourceSideVolFlowRate;     // Source Side Volumetric Flow Rate [m3/s]
    1197              :         Real64 DegradFactor;              // Degradation Factor [~]
    1198              :         Real64 CpFluid;                   // Specific heat of source side fluid(J/kg)
    1199              :         Real64 LoadSideInletWBTemp;       // Wet-bulb temperature of indoor inlet air [C]
    1200              :         Real64 LoadSideInletDBTemp;       // Load Side Inlet Dry Bulb Temp [C]
    1201              :         Real64 LoadSideInletHumRat;       // Load Side Inlet Humidity Ratio [kg/kg]
    1202              :         Real64 LoadSideOutletDBTemp;      // Load Side Outlet Dry Bulb Temperature [C]
    1203              :         Real64 LoadSideOutletHumRat;      // Load Side Outlet Humidity Ratio [kg/kg]
    1204              :         Real64 LoadSideAirInletEnth;      // Load Side Inlet Enthalpy [J/kg]
    1205              :         Real64 LoadSideAirOutletEnth;     // Load Side Outlet Enthalpy [J/kg]
    1206              :         Real64 EffectiveSurfaceTemp;      // Effective Surface Temperature [C]
    1207              :         Real64 EffectiveSatEnth;          // Saturated Enthalpy of Air Corresponding to the Effective Surface Temperature [J/kg]
    1208              :         Real64 QSource;                   // Source Side Heat Transfer Rate [W]
    1209              :         Real64 QLoadTotal;                // Load Side Total Heat Transfer Rate [W]
    1210              :         Real64 QSensible;                 // Load Side Sensible Heat Transfer Rate [W]
    1211              :         Real64 Power;                     // Power Consumption [W]
    1212              :         Real64 EvapTemp;                  // Evaporating Temperature [C]
    1213              :         Real64 ANTUWET;                   // Number of Transfer Unit for Wet Condition
    1214              :         Real64 EffectWET;                 // Load Side Heat Exchanger Effectiveness
    1215              :         Real64 EvapSatEnth;               // Saturated Enthalpy of Air Corresponding to the Evaporating Temperature [J/kg]
    1216              :         Real64 SourceSideEffect;          // Source Side Heat Exchanger Effectiveness
    1217              :         Real64 SourceSideTemp;            // Source Side Saturated Refrigerant Temperature [C]
    1218              :         Real64 LoadSideTemp;              // Load Side Saturated Refrigerant Temperature [C]
    1219              :         Real64 SourceSidePressure;        // Source Side Saturated Refrigerant Pressure [Pa]
    1220              :         Real64 LoadSidePressure;          // Load Side Saturated Refrigerant Pressure [Pa]
    1221              :         Real64 SuctionPr;                 // Compressor Suction Pressure [Pa]
    1222              :         Real64 DischargePr;               // Compressor Discharge Pressure [Pa]
    1223              :         Real64 CompressInletTemp;         // Temperature of the Refrigerant Entering the Compressor [C]
    1224              :         Real64 MassRef;                   // Mass Flow Rate of Refrigerant [kg/s]
    1225              :         Real64 SourceSideOutletEnth;      // Enthalpy of Refrigerant leaving the Source Side Heat Exchanger [J/kg]
    1226              :         Real64 LoadSideOutletEnth;        // Enthalpy of Refrigerant leaving the Load Side Heat Exchanger [J/kg]
    1227              :         Real64 CpAir;                     // Specific Heat of Air [J/kg_C]
    1228              :         Real64 SuperHeatEnth;             // Enthalpy of the Superheated Refrigerant [J/kg]
    1229              :         Real64 CompSuctionTemp1;          // Guess of the Temperature of the Refrigerant Entering the Compressor #1 [C]
    1230              :         Real64 CompSuctionTemp2;          // Guess of the Temperature of the Refrigerant Entering the Compressor #2 [C]
    1231              :         Real64 CompSuctionEnth;           // Enthalpy of the Refrigerant Entering the Compressor [J/kg]
    1232              :         Real64 CompSuctionDensity;        // Density of the Refrigerant Entering the Compressor [kg/m3]
    1233              :         Real64 CompSuctionSatTemp;        // Temperature of Saturated Refrigerant at Compressor Suction Pressure [C]
    1234              :         bool LatDegradModelSimFlag;       // Latent degradation model simulation flag
    1235              :         bool StillSimulatingFlag;         // Final Simulation Flag
    1236              :         bool Converged;                   // overall convergence Flag
    1237              :         Real64 QLatRated;                 // Qlatent at rated conditions of indoor(TDB,TWB)=(26.7C,19.4C)
    1238              :         Real64 QLatActual;                // Qlatent at actual operating conditions
    1239              :         Real64 SHRss;                     // Sensible heat ratio at steady state
    1240              :         Real64 SHReff;                    // Effective sensible heat ratio at part-load condition
    1241              :         int SolFlag;                      // Solution flag returned from RegulaFalsi function
    1242              :         Real64 LoadSideAirInletEnth_Unit; // calc conditions for unit
    1243              :         Real64 LoadResidual;              // loop convergence criteria
    1244              :         Real64 SourceResidual;            // loop convergence criteria
    1245            1 :         Real64 RelaxParam(0.5);           // Relaxation Parameter
    1246              : 
    1247            1 :         if (state.dataWaterToAirHeatPump->firstTime) {
    1248              :             // Set indoor air conditions to the rated condition
    1249            1 :             state.dataWaterToAirHeatPump->LoadSideInletDBTemp_Init = 26.7;
    1250            1 :             state.dataWaterToAirHeatPump->LoadSideInletHumRat_Init = 0.0111;
    1251            1 :             state.dataWaterToAirHeatPump->LoadSideAirInletEnth_Init = Psychrometrics::PsyHFnTdbW(
    1252            1 :                 state.dataWaterToAirHeatPump->LoadSideInletDBTemp_Init, state.dataWaterToAirHeatPump->LoadSideInletHumRat_Init);
    1253            1 :             state.dataWaterToAirHeatPump->firstTime = false;
    1254              :         }
    1255              : 
    1256              :         //  SET LOCAL VARIABLES FROM DATA STRUCTURE (for code readability)
    1257              :         // Set indoor air conditions to the actual condition
    1258            1 :         CpAir = Psychrometrics::PsyCpAirFnW(heatPump.InletAirHumRat);
    1259            1 :         LoadSideAirInletEnth_Unit = Psychrometrics::PsyHFnTdbW(heatPump.InletAirDBTemp, heatPump.InletAirHumRat);
    1260            1 :         SourceSideVolFlowRate =
    1261            1 :             heatPump.InletWaterMassFlowRate /
    1262            1 :             state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).glycol->getDensity(state, heatPump.InletWaterTemp, RoutineNameSourceSideInletTemp);
    1263              : 
    1264            1 :         StillSimulatingFlag = true;
    1265              : 
    1266              :         // If heat pump is not operating, return
    1267            1 :         if (SensDemand == 0.0 || heatPump.InletAirMassFlowRate <= 0.0 || heatPump.InletWaterMassFlowRate <= 0.0) {
    1268            0 :             heatPump.SimFlag = false;
    1269            0 :             return;
    1270              :         } else {
    1271            1 :             heatPump.SimFlag = true;
    1272              :         }
    1273              : 
    1274            1 :         if (compressorOp == HVAC::CompressorOp::Off) {
    1275            0 :             heatPump.SimFlag = false;
    1276            0 :             return;
    1277              :         }
    1278              : 
    1279            1 :         if (FirstHVACIteration) {
    1280            1 :             state.dataWaterToAirHeatPump->initialQSource_calc = heatPump.CoolingCapacity;
    1281            1 :             state.dataWaterToAirHeatPump->initialQLoadTotal_calc = heatPump.CoolingCapacity;
    1282              :         }
    1283              : 
    1284            1 :         if (state.dataWaterToAirHeatPump->initialQLoadTotal_calc == 0.0) {
    1285            0 :             state.dataWaterToAirHeatPump->initialQLoadTotal_calc = heatPump.CoolingCapacity;
    1286              :         }
    1287            1 :         if (state.dataWaterToAirHeatPump->initialQSource_calc == 0.0) {
    1288            0 :             state.dataWaterToAirHeatPump->initialQSource_calc = heatPump.CoolingCapacity;
    1289              :         }
    1290              : 
    1291              :         // Loop the calculation at least twice depending whether the latent degradation model
    1292              :         // is enabled. 1st iteration to calculate the QLatent(rated) at (TDB,TWB)indoorair=(26.7C,19.4C)
    1293              :         // and 2nd iteration to calculate the  QLatent(actual)
    1294              : 
    1295              :         // Calculate Part Load Factor and Runtime Fraction
    1296            1 :         Real64 PLF = 1.0; // part load factor as a function of PLR, RTF = PLR / PLF
    1297            1 :         if (heatPump.PLFCurveIndex > 0) {
    1298            1 :             PLF = Curve::CurveValue(state, heatPump.PLFCurveIndex, PartLoadRatio); // Calculate part-load factor
    1299              :         }
    1300            1 :         if (fanOp == HVAC::FanOp::Cycling) {
    1301            1 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = PLF;
    1302              :         }
    1303            1 :         heatPump.RunFrac = PartLoadRatio / PLF;
    1304              : 
    1305            1 :         QLatRated = 0.0;
    1306            1 :         QLatActual = 0.0;
    1307              :         // IF((RuntimeFrac .GE. 1.0) .OR. (Twet_rated .LE. 0.0) .OR. (Gamma_rated .LE. 0.0)) THEN
    1308              :         // Cycling fan does not required latent degradation model, only the constant fan case
    1309            1 :         if ((heatPump.RunFrac >= 1.0) || (heatPump.Twet_Rated <= 0.0) || (heatPump.Gamma_Rated <= 0.0) || (fanOp == HVAC::FanOp::Cycling)) {
    1310            1 :             LatDegradModelSimFlag = false;
    1311              :             // Set NumIteration4=1 so that latent model would quit after 1 simulation with the actual condition
    1312            1 :             NumIteration4 = 1;
    1313              :         } else {
    1314            0 :             LatDegradModelSimFlag = true;
    1315              :             // Set NumIteration4=0 so that latent model would simulate twice with rated and actual condition
    1316            0 :             NumIteration4 = 0;
    1317              :         }
    1318              : 
    1319              :         // Tuned Hoisted quantities out of nested loop that don't change
    1320            1 :         Real64 const LoadSideMassFlowRate_CpAir_inv(1.0 / (heatPump.InletAirMassFlowRate * CpAir));
    1321              :         Real64 const LoadSideEffec(1.0 -
    1322            1 :                                    std::exp(-heatPump.LoadSideOutsideUACoeff *
    1323            1 :                                             LoadSideMassFlowRate_CpAir_inv)); // Load Side Effectiveness based on Outside Heat Transfer Coefficient
    1324            1 :         Real64 const LoadSideEffec_MassFlowRate_inv(1.0 / (LoadSideEffec * heatPump.InletAirMassFlowRate));
    1325            1 :         ANTUWET = heatPump.LoadSideTotalUACoeff * LoadSideMassFlowRate_CpAir_inv;
    1326            1 :         EffectWET = 1.0 - std::exp(-ANTUWET);
    1327              : 
    1328              :         while (true) {
    1329            1 :             ++NumIteration4;
    1330            1 :             if (NumIteration4 == 1) {
    1331              :                 // Set indoor air conditions to the rated condition
    1332            0 :                 LoadSideInletDBTemp = state.dataWaterToAirHeatPump->LoadSideInletDBTemp_Init;
    1333            0 :                 LoadSideInletHumRat = state.dataWaterToAirHeatPump->LoadSideInletHumRat_Init;
    1334            0 :                 LoadSideAirInletEnth = state.dataWaterToAirHeatPump->LoadSideAirInletEnth_Init;
    1335              :             } else {
    1336              :                 // Set indoor air conditions to the actual condition
    1337            1 :                 LoadSideInletDBTemp = heatPump.InletAirDBTemp;
    1338            1 :                 LoadSideInletHumRat = heatPump.InletAirHumRat;
    1339            1 :                 LoadSideAirInletEnth = LoadSideAirInletEnth_Unit;
    1340              :             }
    1341              : 
    1342              :             // Outerloop: Calculate source side heat transfer
    1343            1 :             int NumIteration2 = 0;
    1344            1 :             Converged = false;
    1345            1 :             StillSimulatingFlag = true;
    1346            1 :             SourceResidual = 1.0;
    1347           17 :             while (StillSimulatingFlag) {
    1348           16 :                 if (Converged) {
    1349            1 :                     StillSimulatingFlag = false;
    1350              :                 }
    1351              : 
    1352           16 :                 ++NumIteration2;
    1353           16 :                 if (NumIteration2 == 1) {
    1354            1 :                     RelaxParam = 0.5;
    1355              :                 }
    1356              : 
    1357           16 :                 if (NumIteration2 > STOP2) {
    1358            0 :                     heatPump.SimFlag = false;
    1359            0 :                     return;
    1360              :                 }
    1361              : 
    1362              :                 // Innerloop: Calculate load side heat transfer
    1363           16 :                 NumIteration3 = 0;
    1364           16 :                 LoadResidual = 1.0;
    1365           59 :                 while (LoadResidual > ERR) {
    1366              : 
    1367           43 :                     ++NumIteration3;
    1368              : 
    1369           43 :                     if (NumIteration3 > STOP3) {
    1370            0 :                         heatPump.SimFlag = false;
    1371            0 :                         return;
    1372              :                     }
    1373              : 
    1374              :                     // Determine Effectiveness of Source Side
    1375           43 :                     CpFluid = state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum)
    1376           43 :                                   .glycol->getSpecificHeat(state, heatPump.InletWaterTemp, RoutineNameSourceSideInletTemp);
    1377              : 
    1378           43 :                     if (state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).glycol->Num == Fluid::GlycolNum_Water) {
    1379           43 :                         SourceSideEffect = 1.0 - std::exp(-heatPump.SourceSideUACoeff / (CpFluid * heatPump.InletWaterMassFlowRate));
    1380              :                     } else {
    1381            0 :                         DegradFactor = DegradF(state, state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).glycol, heatPump.InletWaterTemp);
    1382            0 :                         SourceSideEffect =
    1383            0 :                             1.0 / ((heatPump.SourceSideHTR1 * std::pow(SourceSideVolFlowRate, -0.8)) / DegradFactor + heatPump.SourceSideHTR2);
    1384              :                     }
    1385              : 
    1386              :                     // Determine Source Side Tempertaure (Condensing Temp in this case)
    1387           43 :                     SourceSideTemp = heatPump.InletWaterTemp + state.dataWaterToAirHeatPump->initialQSource_calc /
    1388           43 :                                                                    (SourceSideEffect * CpFluid * heatPump.InletWaterMassFlowRate);
    1389              : 
    1390              :                     // Compute the Effective Surface Temperature
    1391           43 :                     EffectiveSatEnth = LoadSideAirInletEnth - state.dataWaterToAirHeatPump->initialQLoadTotal_calc * LoadSideEffec_MassFlowRate_inv;
    1392              : 
    1393           43 :                     EffectiveSurfaceTemp = Psychrometrics::PsyTsatFnHPb(state, EffectiveSatEnth, PB, RoutineNameLoadSideSurfaceTemp);
    1394              : 
    1395           43 :                     QSensible = heatPump.InletAirMassFlowRate * CpAir * (LoadSideInletDBTemp - EffectiveSurfaceTemp) * LoadSideEffec;
    1396           43 :                     EvapSatEnth =
    1397           43 :                         LoadSideAirInletEnth - state.dataWaterToAirHeatPump->initialQLoadTotal_calc / (EffectWET * heatPump.InletAirMassFlowRate);
    1398              : 
    1399           43 :                     EvapTemp = Psychrometrics::PsyTsatFnHPb(state, EvapSatEnth, PB, RoutineNameLoadSideEvapTemp);
    1400              : 
    1401              :                     // Load Side Saturated Temperature (Evaporating Temp in this case)
    1402           43 :                     LoadSideTemp = EvapTemp;
    1403              : 
    1404              :                     // Determine the Load Side and Source Side Saturated Temp (evaporating and condensing pressures)
    1405           43 :                     SourceSidePressure = heatPump.refrig->getSatPressure(state, SourceSideTemp, RoutineNameSourceSideTemp);
    1406           43 :                     LoadSidePressure = heatPump.refrig->getSatPressure(state, LoadSideTemp, RoutineNameLoadSideTemp);
    1407              : 
    1408           43 :                     if (LoadSidePressure < heatPump.LowPressCutoff && !FirstHVACIteration) {
    1409            0 :                         if (!state.dataGlobal->WarmupFlag) {
    1410            0 :                             ShowRecurringWarningErrorAtEnd(
    1411              :                                 state,
    1412            0 :                                 format("WaterToAir Heat pump:cooling [{}] shut off on low pressure < {:.0R}", heatPump.Name, heatPump.LowPressCutoff),
    1413            0 :                                 heatPump.LowPressClgError,
    1414              :                                 LoadSidePressure,
    1415              :                                 LoadSidePressure,
    1416              :                                 _,
    1417              :                                 "[Pa]",
    1418              :                                 "[Pa]");
    1419              :                         }
    1420            0 :                         heatPump.SimFlag = false;
    1421            0 :                         return;
    1422              :                     }
    1423              : 
    1424           43 :                     if (SourceSidePressure > heatPump.HighPressCutoff && !FirstHVACIteration) {
    1425            0 :                         if (!state.dataGlobal->WarmupFlag) {
    1426            0 :                             ShowRecurringWarningErrorAtEnd(state,
    1427            0 :                                                            format("WaterToAir Heat pump:cooling [{}] shut off on high pressure > {:.0R}",
    1428            0 :                                                                   heatPump.Name,
    1429            0 :                                                                   heatPump.HighPressCutoff),
    1430            0 :                                                            heatPump.HighPressClgError,
    1431            0 :                                                            heatPump.InletWaterTemp,
    1432            0 :                                                            heatPump.InletWaterTemp,
    1433              :                                                            _,
    1434              :                                                            "SourceSideInletTemp[C]",
    1435              :                                                            "SourceSideInletTemp[C]");
    1436              :                         }
    1437            0 :                         heatPump.SimFlag = false;
    1438            0 :                         return;
    1439              :                     }
    1440              : 
    1441              :                     // Determine Suction Pressure & Discharge Pressure at Compressor Exit
    1442           43 :                     if (heatPump.compressorType == CompressorType::Reciprocating) { // RECIPROCATING
    1443            0 :                         SuctionPr = LoadSidePressure - heatPump.CompSucPressDrop;
    1444            0 :                         DischargePr = SourceSidePressure + heatPump.CompSucPressDrop;
    1445           43 :                     } else if (heatPump.compressorType == CompressorType::Rotary) { // ROTARY
    1446            0 :                         SuctionPr = LoadSidePressure;
    1447            0 :                         DischargePr = SourceSidePressure + heatPump.CompSucPressDrop;
    1448           43 :                     } else if (heatPump.compressorType == CompressorType::Scroll) { // SCROLL
    1449           43 :                         SuctionPr = LoadSidePressure;
    1450           43 :                         DischargePr = SourceSidePressure;
    1451              :                     }
    1452              : 
    1453              :                     // Determine the Load Side Outlet Enthalpy (Saturated Gas)
    1454           43 :                     Quality = 1.0;
    1455           43 :                     LoadSideOutletEnth = heatPump.refrig->getSatEnthalpy(state, LoadSideTemp, Quality, RoutineNameLoadSideTemp);
    1456              : 
    1457              :                     // Determine Source Side Outlet Enthalpy (Saturated Liquid)
    1458           43 :                     Quality = 0.0;
    1459           43 :                     SourceSideOutletEnth = heatPump.refrig->getSatEnthalpy(state, SourceSideTemp, Quality, RoutineNameSourceSideTemp);
    1460              :                     // Determine Superheated Temperature of the Load Side outlet/compressor Inlet
    1461           43 :                     CompressInletTemp = LoadSideTemp + heatPump.SuperheatTemp;
    1462              : 
    1463              :                     // Determine the Enthalpy of the Superheated Fluid at Load Side Outlet/Compressor Inlet
    1464           43 :                     SuperHeatEnth = heatPump.refrig->getSupHeatEnthalpy(state, CompressInletTemp, LoadSidePressure, RoutineNameCompressInletTemp);
    1465              : 
    1466              :                     // Determining the suction state of the fluid from inlet state involves interation
    1467              :                     // Method employed...
    1468              :                     // Determine the saturated temp at suction pressure, shoot out into the superheated region find the enthalpy
    1469              :                     // check that with the inlet enthalpy ( as suction loss is isenthalpic). Iterate till desired accuracy is reached
    1470           43 :                     if (!Converged) {
    1471           42 :                         CompSuctionSatTemp = heatPump.refrig->getSatTemperature(state, SuctionPr, RoutineNameSuctionPr);
    1472           42 :                         CompSuctionTemp1 = CompSuctionSatTemp;
    1473              : 
    1474              :                         // Shoot into the Superheated Region
    1475           42 :                         CompSuctionTemp2 = CompSuctionSatTemp + DegreeofSuperheat;
    1476              :                     }
    1477              : 
    1478          129 :                     auto f = [&state, &heatPump, SuctionPr, SuperHeatEnth](Real64 const CompSuctionTemp) {
    1479              :                         static constexpr std::string_view RoutineName("CalcWaterToAirHPHeating:CalcCompSuctionTemp");
    1480          129 :                         Real64 compSuctionEnth = heatPump.refrig->getSupHeatEnthalpy(state, CompSuctionTemp, SuctionPr, RoutineName);
    1481          129 :                         return (compSuctionEnth - SuperHeatEnth) / SuperHeatEnth;
    1482           43 :                     };
    1483              : 
    1484           86 :                     General::SolveRoot(
    1485           43 :                         state, ERR, STOP1, SolFlag, state.dataWaterToAirHeatPump->CompSuctionTemp, f, CompSuctionTemp1, CompSuctionTemp2);
    1486           43 :                     if (SolFlag == -1) {
    1487            0 :                         heatPump.SimFlag = false;
    1488            0 :                         return;
    1489              :                     }
    1490           43 :                     CompSuctionEnth = heatPump.refrig->getSupHeatEnthalpy(
    1491           43 :                         state, state.dataWaterToAirHeatPump->CompSuctionTemp, SuctionPr, RoutineNameCompSuctionTemp);
    1492           43 :                     CompSuctionDensity = heatPump.refrig->getSupHeatDensity(
    1493           43 :                         state, state.dataWaterToAirHeatPump->CompSuctionTemp, SuctionPr, RoutineNameCompSuctionTemp);
    1494              : 
    1495              :                     // Find Refrigerant Flow Rate
    1496           43 :                     switch (heatPump.compressorType) {
    1497            0 :                     case CompressorType::Reciprocating: {
    1498            0 :                         MassRef =
    1499            0 :                             heatPump.CompPistonDisp * CompSuctionDensity *
    1500            0 :                             (1.0 + heatPump.CompClearanceFactor - heatPump.CompClearanceFactor * std::pow(DischargePr / SuctionPr, 1.0 / gamma));
    1501            0 :                         break;
    1502              :                     }
    1503            0 :                     case CompressorType::Rotary: {
    1504            0 :                         MassRef = heatPump.CompPistonDisp * CompSuctionDensity;
    1505            0 :                         break;
    1506              :                     }
    1507           43 :                     case CompressorType::Scroll: {
    1508           43 :                         MassRef = heatPump.RefVolFlowRate * CompSuctionDensity - heatPump.LeakRateCoeff * (DischargePr / SuctionPr);
    1509           43 :                         break;
    1510              :                     }
    1511            0 :                     default:
    1512            0 :                         break;
    1513              :                     }
    1514           43 :                     MassRef = max(0.0, MassRef);
    1515              : 
    1516              :                     // Find the Load Side Heat Transfer
    1517           43 :                     QLoadTotal = MassRef * (LoadSideOutletEnth - SourceSideOutletEnth);
    1518           43 :                     LoadResidual = std::abs(QLoadTotal - state.dataWaterToAirHeatPump->initialQLoadTotal_calc) /
    1519           43 :                                    state.dataWaterToAirHeatPump->initialQLoadTotal_calc;
    1520           86 :                     state.dataWaterToAirHeatPump->initialQLoadTotal_calc +=
    1521           43 :                         RelaxParam * (QLoadTotal - state.dataWaterToAirHeatPump->initialQLoadTotal_calc);
    1522           43 :                     if (NumIteration3 > 8) {
    1523            4 :                         RelaxParam = 0.3;
    1524              :                     }
    1525              :                 }
    1526              : 
    1527              :                 // Determine the Power Consumption
    1528           16 :                 switch (heatPump.compressorType) {
    1529            0 :                 case CompressorType::Reciprocating:
    1530              :                 case CompressorType::Rotary: {
    1531            0 :                     Power = heatPump.PowerLosses + (1.0 / heatPump.LossFactor) * (MassRef * gamma / (gamma - 1.0) * SuctionPr / CompSuctionDensity *
    1532            0 :                                                                                   (std::pow(DischargePr / SuctionPr, (gamma - 1.0) / gamma) - 1.0));
    1533            0 :                     break;
    1534              :                 }
    1535           16 :                 case CompressorType::Scroll: {
    1536           16 :                     Power = heatPump.PowerLosses + (1.0 / heatPump.LossFactor) * (gamma / (gamma - 1.0)) * SuctionPr * heatPump.RefVolFlowRate *
    1537           16 :                                                        (((gamma - 1.0) / gamma) * ((DischargePr / SuctionPr) / heatPump.VolumeRatio) +
    1538           16 :                                                         ((1.0 / gamma) * std::pow(heatPump.VolumeRatio, gamma - 1.0)) - 1.0);
    1539           16 :                     break;
    1540              :                 }
    1541            0 :                 default:
    1542            0 :                     break;
    1543              :                 }
    1544              : 
    1545              :                 // Determine the Sourceside Heat Rate
    1546           16 :                 QSource = Power + QLoadTotal;
    1547           16 :                 SourceResidual =
    1548           16 :                     std::abs(QSource - state.dataWaterToAirHeatPump->initialQSource_calc) / state.dataWaterToAirHeatPump->initialQSource_calc;
    1549           16 :                 if (SourceResidual < ERR) {
    1550            2 :                     Converged = true;
    1551              :                 }
    1552           16 :                 state.dataWaterToAirHeatPump->initialQSource_calc += RelaxParam * (QSource - state.dataWaterToAirHeatPump->initialQSource_calc);
    1553           16 :                 if (NumIteration2 > 8) {
    1554            8 :                     RelaxParam = 0.2;
    1555              :                 }
    1556              :             }
    1557              : 
    1558            1 :             if (SuctionPr < heatPump.LowPressCutoff) {
    1559            0 :                 ShowWarningError(state, "Heat pump:cooling shut down on low pressure");
    1560            0 :                 heatPump.SimFlag = false;
    1561              :             }
    1562              : 
    1563            1 :             if (DischargePr > heatPump.HighPressCutoff && !FirstHVACIteration) {
    1564            0 :                 ShowWarningError(state, "Heat pump:cooling shut down on high pressure");
    1565            0 :                 heatPump.SimFlag = false;
    1566              :             }
    1567              : 
    1568            1 :             if (QSensible > QLoadTotal) {
    1569            1 :                 QSensible = QLoadTotal;
    1570              :             }
    1571              : 
    1572            1 :             if (LatDegradModelSimFlag) {
    1573            0 :                 if (NumIteration4 == 1) {
    1574            0 :                     QLatRated = QLoadTotal - QSensible;
    1575              : 
    1576            0 :                 } else if (NumIteration4 == 2) {
    1577            0 :                     QLatActual = QLoadTotal - QSensible;
    1578            0 :                     SHRss = QSensible / QLoadTotal;
    1579            0 :                     LoadSideInletWBTemp = Psychrometrics::PsyTwbFnTdbWPb(state, LoadSideInletDBTemp, LoadSideInletHumRat, PB);
    1580            0 :                     SHReff = CalcEffectiveSHR(
    1581              :                         state, HPNum, SHRss, fanOp, heatPump.RunFrac, QLatRated, QLatActual, LoadSideInletDBTemp, LoadSideInletWBTemp);
    1582              :                     //   Update sensible capacity based on effective SHR
    1583            0 :                     QSensible = QLoadTotal * SHReff;
    1584            0 :                     goto LOOPLatentDegradationModel_exit;
    1585              :                 }
    1586              :             } else {
    1587              : 
    1588            1 :                 SHReff = QSensible / QLoadTotal;
    1589            1 :                 goto LOOPLatentDegradationModel_exit;
    1590              :             }
    1591            0 :         }
    1592            1 :     LOOPLatentDegradationModel_exit:;
    1593              : 
    1594              :         // calculate coil outlet state variables
    1595            1 :         LoadSideAirOutletEnth = LoadSideAirInletEnth - QLoadTotal / heatPump.InletAirMassFlowRate;
    1596            1 :         LoadSideOutletDBTemp = LoadSideInletDBTemp - QSensible * LoadSideMassFlowRate_CpAir_inv;
    1597            1 :         LoadSideOutletHumRat = Psychrometrics::PsyWFnTdbH(state, LoadSideOutletDBTemp, LoadSideAirOutletEnth, RoutineNameLoadSideOutletEnthalpy);
    1598            1 :         SourceSideOutletTemp = heatPump.InletWaterTemp + QSource / (heatPump.InletWaterMassFlowRate * CpWater);
    1599              : 
    1600              :         // Actual outlet conditions are "average" for time step
    1601            1 :         if (fanOp == HVAC::FanOp::Continuous) {
    1602              :             // continuous fan, cycling compressor
    1603            0 :             heatPump.OutletAirEnthalpy = PartLoadRatio * LoadSideAirOutletEnth + (1.0 - PartLoadRatio) * LoadSideAirInletEnth;
    1604            0 :             heatPump.OutletAirHumRat = PartLoadRatio * LoadSideOutletHumRat + (1.0 - PartLoadRatio) * LoadSideInletHumRat;
    1605            0 :             heatPump.OutletAirDBTemp = Psychrometrics::PsyTdbFnHW(heatPump.OutletAirEnthalpy, heatPump.OutletAirHumRat);
    1606              :         } else {
    1607              :             // default to cycling fan, cycling compressor
    1608            1 :             heatPump.OutletAirEnthalpy = LoadSideAirOutletEnth;
    1609            1 :             heatPump.OutletAirHumRat = LoadSideOutletHumRat;
    1610            1 :             heatPump.OutletAirDBTemp = LoadSideOutletDBTemp;
    1611              :         }
    1612              : 
    1613              :         // scale heat transfer rates and power to run time
    1614            1 :         QLoadTotal *= PartLoadRatio;
    1615            1 :         QSensible *= PartLoadRatio;
    1616            1 :         Power *= heatPump.RunFrac;
    1617            1 :         QSource *= PartLoadRatio;
    1618              : 
    1619              :         // Update heat pump data structure
    1620            1 :         state.dataHVACGlobal->DXElecCoolingPower = Power;
    1621            1 :         heatPump.Power = Power;
    1622            1 :         heatPump.QLoadTotal = QLoadTotal;
    1623            1 :         heatPump.QSensible = QSensible;
    1624            1 :         heatPump.QLatent = QLoadTotal - QSensible;
    1625            1 :         heatPump.QSource = QSource;
    1626            1 :         heatPump.PartLoadRatio = PartLoadRatio;
    1627              : 
    1628              :         //  Air-side outlet conditions are already calculated above
    1629            1 :         heatPump.OutletAirMassFlowRate = heatPump.InletAirMassFlowRate;
    1630            1 :         heatPump.OutletWaterTemp = SourceSideOutletTemp;
    1631            1 :         heatPump.OutletWaterMassFlowRate = heatPump.InletWaterMassFlowRate;
    1632            1 :         heatPump.OutletWaterEnthalpy = heatPump.InletWaterEnthalpy + QSource / heatPump.InletWaterMassFlowRate;
    1633              :     }
    1634              : 
    1635            1 :     void CalcWatertoAirHPHeating(EnergyPlusData &state,
    1636              :                                  int const HPNum,                      // heat pump number
    1637              :                                  HVAC::FanOp const fanOp,              // fan/compressor cycling scheme indicator
    1638              :                                  bool const FirstHVACIteration,        // first iteration flag
    1639              :                                  [[maybe_unused]] bool const InitFlag, // first iteration flag
    1640              :                                  Real64 const SensDemand,
    1641              :                                  HVAC::CompressorOp const compressorOp,
    1642              :                                  Real64 const PartLoadRatio)
    1643              :     {
    1644              : 
    1645              :         // SUBROUTINE INFORMATION:
    1646              :         //       AUTHOR         Hui Jin
    1647              :         //       DATE WRITTEN   Oct 2000
    1648              :         //       MODIFIED       R. Raustad (Oct 2006) Revised iteration technique
    1649              : 
    1650              :         // PURPOSE OF THIS SUBROUTINE:
    1651              :         // Simulates a parameter estimation based water to air heat pump model
    1652              : 
    1653              :         // Using/Aliasing
    1654            1 :         auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
    1655              : 
    1656              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1657            1 :         Real64 constexpr CpWater(4210.0);         // Specific heat of water J/kg_C
    1658            1 :         Real64 constexpr DegreeofSuperheat(80.0); // Initial guess of degree of superheat
    1659            1 :         Real64 constexpr gamma(1.114);            // Expnasion Coefficient
    1660            1 :         Real64 RelaxParam(0.5);                   // Relaxation Parameter
    1661            1 :         Real64 constexpr ERR(0.01);               // Error Value
    1662            1 :         int constexpr STOP1(1000);                // Iteration stopper1
    1663            1 :         int constexpr STOP2(1000);                // Iteration stopper2
    1664            1 :         int constexpr STOP3(1000);                // Iteration stopper3
    1665              : 
    1666              :         static constexpr std::string_view RoutineNameSourceSideInletTemp("CalcWatertoAirHPHeating:SourceSideInletTemp");
    1667              :         static constexpr std::string_view RoutineNameSourceSideTemp("CalcWatertoAirHPHeating:SourceSideTemp");
    1668              :         static constexpr std::string_view RoutineNameLoadSideTemp("CalcWatertoAirHPHeating:LoadSideTemp");
    1669              :         static constexpr std::string_view RoutineNameLoadSideOutletEnthalpy("CalcWatertoAirHPHeating:LoadSideOutletEnthalpy");
    1670              :         static constexpr std::string_view RoutineNameCompressInletTemp("CalcWatertoAirHPHeating:CompressInletTemp");
    1671              :         static constexpr std::string_view RoutineNameSuctionPr("CalcWatertoAirHPHeating:SuctionPr");
    1672              :         static constexpr std::string_view RoutineNameCompSuctionTemp("CalcWatertoAirHPHeating:CompSuctionTemp");
    1673              : 
    1674              :         int NumIteration3; // Number of Iteration3
    1675              :         Real64 Quality;
    1676              :         Real64 SourceSideOutletTemp;  // Source Side Outlet Temperature [C]
    1677              :         Real64 SourceSideVolFlowRate; // Source Side Volumetric Flow Rate [m3/s]
    1678              :         Real64 CpFluid;               // Specific heat of source side fluid(J/kg)
    1679              :         Real64 LoadSideOutletDBTemp;  // Load Side Outlet Dry Bulb Temperature [C]
    1680              :         Real64 LoadSideOutletHumRat;  // Load Side Outlet Humidity Ratio [kg/kg]
    1681              :         Real64 LoadSideAirOutletEnth; // Load Side Outlet Enthalpy [J/kg]
    1682              :         Real64 CpAir;                 // Specific Heat of Air [J/kg_C]
    1683              :         Real64 DegradFactor;          // Degradation Factor [~]
    1684              :         Real64 QSource;               // Source Side Heat Transfer Rate [W]
    1685              :         Real64 QLoadTotal;            // Load Side Heat Transfer Rate [W]
    1686              :         Real64 Power;                 // Power Consumption [W]
    1687              : 
    1688              :         Real64 SourceSideEffect;     // Source Side Heat Exchanger Effectiveness
    1689              :         Real64 SourceSideTemp;       // Source Side Saturated Refrigerant Temperature [C]
    1690              :         Real64 LoadSideTemp;         // Load Side Saturated Refrigerant Temperature [C]
    1691              :         Real64 SourceSidePressure;   // Source Side Saturated Refrigerant Pressure [Pa]
    1692              :         Real64 LoadSidePressure;     // Load Side Saturated Refrigerant Pressure [Pa]
    1693              :         Real64 SuctionPr;            // Compressor Suction Pressure [Pa]
    1694              :         Real64 DischargePr;          // Compressor Discharge Pressure [Pa]
    1695              :         Real64 CompressInletTemp;    // Temperature of the Refrigerant Entering the Compressor [C]
    1696              :         Real64 MassRef;              // Mass Flow Rate of Refrigerant [kg/s]
    1697              :         Real64 SourceSideOutletEnth; // Enthalpy of Refrigerant leaving the Source Side Heat Exchanger [J/kg]
    1698              :         Real64 LoadSideOutletEnth;   // Enthalpy of Refrigerant leaving the Load Side Heat Exchanger [J/kg]
    1699              :         Real64 SuperHeatEnth;        // Enthalpy of the Superheated Refrigerant [J/kg]
    1700              :         Real64 CompSuctionTemp1;     // Guess of the Temperature of the Refrigerant Entering the
    1701              :         // Compressor #1 [C]
    1702              :         Real64 CompSuctionTemp2; // Guess of the Temperature of the Refrigerant Entering the
    1703              :         // Compressor #2 [C]
    1704              :         Real64 CompSuctionTemp;    // Temperature of the Refrigerant Entering the Compressor [C]
    1705              :         Real64 CompSuctionEnth;    // Enthalpy of the Refrigerant Entering the Compressor [J/kg]
    1706              :         Real64 CompSuctionDensity; // Density of the Refrigerant Entering the Compressorkg/m3
    1707              :         Real64 CompSuctionSatTemp; // Temperature of Saturated Refrigerant at Compressor Suction Pressure [C]
    1708              :         bool StillSimulatingFlag;  // Final Simulation Flag
    1709              :         bool Converged;            // Overall convergence Flag
    1710              :         int SolFlag;               // Solution flag returned from RegulaFalsi function
    1711              :         Real64 LoadResidual;       // loop convergence criteria
    1712              :         Real64 SourceResidual;     // loop convergence criteria
    1713              : 
    1714              :         //  LOAD LOCAL VARIABLES FROM DATA STRUCTURE (for code readability)
    1715              : 
    1716            1 :         CpAir = Psychrometrics::PsyCpAirFnW(heatPump.InletAirHumRat);
    1717            1 :         SourceSideVolFlowRate =
    1718            1 :             heatPump.InletWaterMassFlowRate /
    1719            1 :             state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).glycol->getDensity(state, heatPump.InletWaterTemp, RoutineNameSourceSideInletTemp);
    1720              : 
    1721              :         // If heat pump is not operating, return
    1722            1 :         if (SensDemand == 0.0 || heatPump.InletAirMassFlowRate <= 0.0 || heatPump.InletWaterMassFlowRate <= 0.0) {
    1723            0 :             heatPump.SimFlag = false;
    1724            0 :             return;
    1725              :         } else {
    1726            1 :             heatPump.SimFlag = true;
    1727              :         }
    1728              : 
    1729            1 :         if (compressorOp == HVAC::CompressorOp::Off) {
    1730            0 :             heatPump.SimFlag = false;
    1731            0 :             return;
    1732              :         }
    1733              : 
    1734            1 :         if (FirstHVACIteration) {
    1735            1 :             state.dataWaterToAirHeatPump->initialQLoad = heatPump.HeatingCapacity;
    1736            1 :             state.dataWaterToAirHeatPump->initialQSource = heatPump.HeatingCapacity;
    1737              :         }
    1738              : 
    1739            1 :         if (state.dataWaterToAirHeatPump->initialQLoad == 0.0) {
    1740            0 :             state.dataWaterToAirHeatPump->initialQLoad = heatPump.HeatingCapacity;
    1741              :         }
    1742            1 :         if (state.dataWaterToAirHeatPump->initialQSource == 0.0) {
    1743            0 :             state.dataWaterToAirHeatPump->initialQSource = heatPump.HeatingCapacity;
    1744              :         }
    1745              : 
    1746              :         // Tuned Hoisted quantities out of nested loop that don't change
    1747            1 :         Real64 const LoadSideMassFlowRate_CpAir_inv(1.0 / (heatPump.InletAirMassFlowRate * CpAir));
    1748              :         Real64 const LoadSideEffect(1.0 -
    1749            1 :                                     std::exp(-heatPump.LoadSideTotalUACoeff *
    1750            1 :                                              LoadSideMassFlowRate_CpAir_inv)); // Load Side Effectiveness based on Outside Heat Transfer Coefficient
    1751            1 :         Real64 const LoadSideEffect_CpAir_MassFlowRate_inv(1.0 / (LoadSideEffect * CpAir * heatPump.InletAirMassFlowRate));
    1752              : 
    1753              :         // Outerloop: calculate load side heat transfer
    1754            1 :         NumIteration3 = 0;
    1755            1 :         Converged = false;
    1756            1 :         StillSimulatingFlag = true;
    1757            1 :         LoadResidual = 1.0;
    1758           18 :         while (StillSimulatingFlag) {
    1759           17 :             if (Converged) {
    1760            1 :                 StillSimulatingFlag = false;
    1761              :             }
    1762              : 
    1763           17 :             ++NumIteration3;
    1764           17 :             if (NumIteration3 == 1) {
    1765            1 :                 RelaxParam = 0.5;
    1766              :             }
    1767              : 
    1768           17 :             if (NumIteration3 > STOP3) {
    1769            0 :                 heatPump.SimFlag = false;
    1770            0 :                 return;
    1771              :             }
    1772              : 
    1773              :             // Innerloop: calculate load side heat transfer
    1774           17 :             int NumIteration2 = 0;
    1775           17 :             SourceResidual = 1.0;
    1776           64 :             while (SourceResidual > ERR) {
    1777              : 
    1778           47 :                 ++NumIteration2;
    1779              : 
    1780           47 :                 if (NumIteration2 > STOP2) {
    1781            0 :                     heatPump.SimFlag = false;
    1782            0 :                     return;
    1783              :                 }
    1784              : 
    1785              :                 // Determine Effectiveness of Source Side
    1786           47 :                 CpFluid = state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum)
    1787           47 :                               .glycol->getSpecificHeat(state, heatPump.InletWaterTemp, RoutineNameSourceSideInletTemp);
    1788              : 
    1789           47 :                 if (state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).glycol->Num == Fluid::GlycolNum_Water) {
    1790           47 :                     SourceSideEffect = 1.0 - std::exp(-heatPump.SourceSideUACoeff / (CpFluid * heatPump.InletWaterMassFlowRate));
    1791              :                 } else {
    1792            0 :                     DegradFactor = DegradF(state, state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).glycol, heatPump.InletWaterTemp);
    1793            0 :                     SourceSideEffect =
    1794            0 :                         1.0 / ((heatPump.SourceSideHTR1 * std::pow(SourceSideVolFlowRate, -0.8)) / DegradFactor + heatPump.SourceSideHTR2);
    1795              :                 }
    1796              : 
    1797              :                 // Determine Source Side Tempertaure (Evap. Temp for this mode)
    1798           94 :                 SourceSideTemp = heatPump.InletWaterTemp -
    1799           47 :                                  state.dataWaterToAirHeatPump->initialQSource / (SourceSideEffect * CpFluid * heatPump.InletWaterMassFlowRate);
    1800              : 
    1801              :                 // Determine Load Side Tempertaure (Condensing Temp for this mode)
    1802           47 :                 LoadSideTemp = heatPump.InletAirDBTemp + state.dataWaterToAirHeatPump->initialQLoad * LoadSideEffect_CpAir_MassFlowRate_inv;
    1803              : 
    1804              :                 // Determine the Load Side and Source Side Saturated Temp (evaporating and condensing pressures)
    1805           47 :                 SourceSidePressure = heatPump.refrig->getSatPressure(state, SourceSideTemp, RoutineNameSourceSideTemp);
    1806           47 :                 LoadSidePressure = heatPump.refrig->getSatPressure(state, LoadSideTemp, RoutineNameLoadSideTemp);
    1807           47 :                 if (SourceSidePressure < heatPump.LowPressCutoff && !FirstHVACIteration) {
    1808            0 :                     if (!state.dataGlobal->WarmupFlag) {
    1809            0 :                         ShowRecurringWarningErrorAtEnd(
    1810              :                             state,
    1811            0 :                             format("WaterToAir Heat pump:heating [{}] shut off on low pressure < {:.0R}", heatPump.Name, heatPump.LowPressCutoff),
    1812            0 :                             heatPump.LowPressHtgError,
    1813              :                             SourceSidePressure,
    1814              :                             SourceSidePressure,
    1815              :                             _,
    1816              :                             "[Pa]",
    1817              :                             "[Pa]");
    1818              :                     }
    1819            0 :                     heatPump.SimFlag = false;
    1820            0 :                     return;
    1821              :                 }
    1822              : 
    1823           47 :                 if (LoadSidePressure > heatPump.HighPressCutoff && !FirstHVACIteration) {
    1824            0 :                     if (!state.dataGlobal->WarmupFlag) {
    1825            0 :                         ShowRecurringWarningErrorAtEnd(
    1826              :                             state,
    1827            0 :                             format("WaterToAir Heat pump:heating [{}] shut off on high pressure > {:.0R}", heatPump.Name, heatPump.HighPressCutoff),
    1828            0 :                             heatPump.HighPressHtgError,
    1829            0 :                             heatPump.InletWaterTemp,
    1830            0 :                             heatPump.InletWaterTemp,
    1831              :                             _,
    1832              :                             "SourceSideInletTemp[C]",
    1833              :                             "SourceSideInletTemp[C]");
    1834              :                     }
    1835              :                     //         CALL ShowWarningError(state, 'Heat pump:heating shut off on high pressure')
    1836              :                     //         WRITE(CErrCount,*) SourceSideInletTemp
    1837              :                     //         CErrCount=ADJUSTL(CErrCount)
    1838              :                     //         CALL ShowContinueError(state, 'Source side inlet temperature too low, T='//TRIM(CErrCount))
    1839              :                     //         CALL ShowContinueError(state, 'Heat pump heating demand not met by plant side')
    1840            0 :                     heatPump.SimFlag = false;
    1841            0 :                     return;
    1842              :                 }
    1843              : 
    1844              :                 // Determine Suction Pressure at Compressor Entrance & Discharge Pressure at Compressor Exit
    1845           47 :                 switch (heatPump.compressorType) {
    1846            0 :                 case CompressorType::Reciprocating: {
    1847            0 :                     SuctionPr = SourceSidePressure - heatPump.CompSucPressDrop;
    1848            0 :                     DischargePr = LoadSidePressure + heatPump.CompSucPressDrop;
    1849            0 :                     break;
    1850              :                 }
    1851            0 :                 case CompressorType::Rotary: {
    1852            0 :                     SuctionPr = SourceSidePressure;
    1853            0 :                     DischargePr = LoadSidePressure + heatPump.CompSucPressDrop;
    1854            0 :                     break;
    1855              :                 }
    1856           47 :                 case CompressorType::Scroll: {
    1857           47 :                     SuctionPr = SourceSidePressure;
    1858           47 :                     DischargePr = LoadSidePressure;
    1859           47 :                     break;
    1860              :                 }
    1861            0 :                 default:
    1862            0 :                     break;
    1863              :                 }
    1864              : 
    1865              :                 // Determine the Source Side Outlet Enthalpy
    1866              :                 // Quality of the refrigerant leaving the evaporator is saturated gas
    1867           47 :                 Quality = 1.0;
    1868           47 :                 SourceSideOutletEnth = heatPump.refrig->getSatEnthalpy(state, SourceSideTemp, Quality, RoutineNameSourceSideTemp);
    1869              : 
    1870              :                 // Determine Load Side Outlet Enthalpy
    1871              :                 // Quality of the refrigerant leaving the condenser is saturated liguid
    1872           47 :                 Quality = 0.0;
    1873           47 :                 LoadSideOutletEnth = heatPump.refrig->getSatEnthalpy(state, LoadSideTemp, Quality, RoutineNameLoadSideTemp);
    1874              : 
    1875              :                 // Determine Superheated Temperature of the Source Side outlet/compressor Inlet
    1876           47 :                 CompressInletTemp = SourceSideTemp + heatPump.SuperheatTemp;
    1877              : 
    1878              :                 // Determine the Enathalpy of the Superheated Fluid at Source Side Outlet/Compressor Inlet
    1879           47 :                 SuperHeatEnth = heatPump.refrig->getSupHeatEnthalpy(state, CompressInletTemp, SourceSidePressure, RoutineNameCompressInletTemp);
    1880              : 
    1881              :                 // Determining the suction state of the fluid from inlet state involves interation
    1882              :                 // Method employed...
    1883              :                 // Determine the saturated temp at suction pressure, shoot out into the superheated region find the enthalpy
    1884              :                 // check that with the inlet enthalpy ( as suction loss is isenthalpic). Iterate till desired accuracy is reached
    1885              : 
    1886           47 :                 if (!Converged) {
    1887           46 :                     CompSuctionSatTemp = heatPump.refrig->getSatTemperature(state, SuctionPr, RoutineNameSuctionPr);
    1888           46 :                     CompSuctionTemp1 = CompSuctionSatTemp;
    1889              : 
    1890              :                     // Shoot into the Superheated Region
    1891           46 :                     CompSuctionTemp2 = CompSuctionSatTemp + DegreeofSuperheat;
    1892              :                 }
    1893              : 
    1894          141 :                 auto f = [&state, &heatPump, SuctionPr, SuperHeatEnth](Real64 const CompSuctionTemp) {
    1895              :                     static constexpr std::string_view RoutineName("CalcWaterToAirHPHeating:CalcCompSuctionTemp");
    1896          141 :                     Real64 compSuctionEnth = heatPump.refrig->getSupHeatEnthalpy(state, CompSuctionTemp, SuctionPr, RoutineName);
    1897          141 :                     return (compSuctionEnth - SuperHeatEnth) / SuperHeatEnth;
    1898           47 :                 };
    1899              : 
    1900           47 :                 General::SolveRoot(state, ERR, STOP1, SolFlag, CompSuctionTemp, f, CompSuctionTemp1, CompSuctionTemp2);
    1901           47 :                 if (SolFlag == -1) {
    1902            0 :                     heatPump.SimFlag = false;
    1903            0 :                     return;
    1904              :                 }
    1905           47 :                 CompSuctionEnth = heatPump.refrig->getSupHeatEnthalpy(state, CompSuctionTemp, SuctionPr, RoutineNameCompSuctionTemp);
    1906           47 :                 CompSuctionDensity = heatPump.refrig->getSupHeatDensity(state, CompSuctionTemp, SuctionPr, RoutineNameCompSuctionTemp);
    1907              : 
    1908              :                 // Find Refrigerant Flow Rate
    1909           47 :                 switch (heatPump.compressorType) {
    1910            0 :                 case CompressorType::Reciprocating: {
    1911            0 :                     MassRef = heatPump.CompPistonDisp * CompSuctionDensity *
    1912            0 :                               (1 + heatPump.CompClearanceFactor - heatPump.CompClearanceFactor * std::pow(DischargePr / SuctionPr, 1 / gamma));
    1913            0 :                     break;
    1914              :                 }
    1915            0 :                 case CompressorType::Rotary: {
    1916            0 :                     MassRef = heatPump.CompPistonDisp * CompSuctionDensity;
    1917            0 :                     break;
    1918              :                 }
    1919           47 :                 case CompressorType::Scroll: {
    1920           47 :                     MassRef = heatPump.RefVolFlowRate * CompSuctionDensity - heatPump.LeakRateCoeff * (DischargePr / SuctionPr);
    1921           47 :                     break;
    1922              :                 }
    1923            0 :                 default:
    1924            0 :                     break;
    1925              :                 }
    1926           47 :                 MassRef = max(0.0, MassRef);
    1927              : 
    1928              :                 // Find the Source Side Heat Transfer
    1929           47 :                 QSource = MassRef * (SourceSideOutletEnth - LoadSideOutletEnth);
    1930           47 :                 SourceResidual = std::abs(QSource - state.dataWaterToAirHeatPump->initialQSource) / state.dataWaterToAirHeatPump->initialQSource;
    1931           47 :                 state.dataWaterToAirHeatPump->initialQSource += RelaxParam * (QSource - state.dataWaterToAirHeatPump->initialQSource);
    1932           47 :                 if (NumIteration2 > 8) {
    1933           10 :                     RelaxParam = 0.3;
    1934              :                 }
    1935              :             }
    1936              : 
    1937              :             // Determine the Power Consumption
    1938           17 :             switch (heatPump.compressorType) {
    1939            0 :             case CompressorType::Reciprocating:
    1940              :             case CompressorType::Rotary: {
    1941            0 :                 Power = heatPump.PowerLosses + (1 / heatPump.LossFactor) * (MassRef * gamma / (gamma - 1) * SuctionPr / CompSuctionDensity *
    1942            0 :                                                                             (std::pow(DischargePr / SuctionPr, (gamma - 1) / gamma) - 1));
    1943            0 :                 break;
    1944              :             }
    1945           17 :             case CompressorType::Scroll: {
    1946           17 :                 Power = heatPump.PowerLosses + (1 / heatPump.LossFactor) * (gamma / (gamma - 1)) * SuctionPr * heatPump.RefVolFlowRate *
    1947           17 :                                                    (((gamma - 1) / gamma) * ((DischargePr / SuctionPr) / heatPump.VolumeRatio) +
    1948           17 :                                                     ((1 / gamma) * std::pow(heatPump.VolumeRatio, gamma - 1)) - 1);
    1949           17 :                 break;
    1950              :             }
    1951            0 :             default:
    1952            0 :                 break;
    1953              :             }
    1954              : 
    1955              :             // Determine the Load Side Heat Rate
    1956           17 :             QLoadTotal = Power + QSource;
    1957           17 :             LoadResidual = std::abs(QLoadTotal - state.dataWaterToAirHeatPump->initialQLoad) / state.dataWaterToAirHeatPump->initialQLoad;
    1958           17 :             if (LoadResidual < ERR) {
    1959            2 :                 Converged = true;
    1960              :             }
    1961           17 :             state.dataWaterToAirHeatPump->initialQLoad += RelaxParam * (QLoadTotal - state.dataWaterToAirHeatPump->initialQLoad);
    1962           17 :             if (NumIteration3 > 8) {
    1963            9 :                 RelaxParam = 0.2;
    1964              :             }
    1965              :         }
    1966              : 
    1967            1 :         if (SuctionPr < heatPump.LowPressCutoff && !FirstHVACIteration) {
    1968            0 :             ShowWarningError(state, "Heat pump:heating shut down on low pressure");
    1969            0 :             heatPump.SimFlag = false;
    1970            0 :             return;
    1971              :         }
    1972              : 
    1973            1 :         if (DischargePr > heatPump.HighPressCutoff && !FirstHVACIteration) {
    1974            0 :             ShowWarningError(state, "Heat pump:heating shut down on high pressure");
    1975            0 :             heatPump.SimFlag = false;
    1976            0 :             return;
    1977              :         }
    1978              : 
    1979              :         // calculate coil outlet state variables
    1980            1 :         LoadSideAirOutletEnth = heatPump.InletAirEnthalpy + QLoadTotal / heatPump.InletAirMassFlowRate;
    1981            1 :         LoadSideOutletDBTemp = heatPump.InletAirDBTemp + QLoadTotal / (heatPump.InletAirMassFlowRate * CpAir);
    1982            1 :         LoadSideOutletHumRat = Psychrometrics::PsyWFnTdbH(state, LoadSideOutletDBTemp, LoadSideAirOutletEnth, RoutineNameLoadSideOutletEnthalpy);
    1983            1 :         SourceSideOutletTemp = heatPump.InletWaterTemp - QSource / (heatPump.InletWaterMassFlowRate * CpWater);
    1984              : 
    1985              :         // Calculate actual outlet conditions for the run time fraction
    1986              :         // Actual outlet conditions are "average" for time step
    1987            1 :         if (fanOp == HVAC::FanOp::Continuous) {
    1988              :             // continuous fan, cycling compressor
    1989            0 :             heatPump.OutletAirEnthalpy = PartLoadRatio * LoadSideAirOutletEnth + (1.0 - PartLoadRatio) * heatPump.InletAirEnthalpy;
    1990            0 :             heatPump.OutletAirHumRat = PartLoadRatio * LoadSideOutletHumRat + (1.0 - PartLoadRatio) * heatPump.InletAirHumRat;
    1991            0 :             heatPump.OutletAirDBTemp = Psychrometrics::PsyTdbFnHW(heatPump.OutletAirEnthalpy, heatPump.OutletAirHumRat);
    1992              :         } else {
    1993              :             // default to cycling fan, cycling compressor
    1994            1 :             heatPump.OutletAirEnthalpy = LoadSideAirOutletEnth;
    1995            1 :             heatPump.OutletAirHumRat = LoadSideOutletHumRat;
    1996            1 :             heatPump.OutletAirDBTemp = LoadSideOutletDBTemp;
    1997              :         }
    1998              : 
    1999              :         // Calculate Part Load Factor and Runtime Fraction
    2000            1 :         Real64 PLF = 1.0; // part load factor as a function of PLR, RTF = PLR / PLF
    2001            1 :         if (heatPump.PLFCurveIndex > 0) {
    2002            1 :             PLF = Curve::CurveValue(state, heatPump.PLFCurveIndex, PartLoadRatio); // Calculate part-load factor
    2003              :         }
    2004            1 :         if (fanOp == HVAC::FanOp::Cycling) {
    2005            1 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = PLF;
    2006              :         }
    2007            1 :         heatPump.RunFrac = PartLoadRatio / PLF;
    2008              : 
    2009              :         // scale heat transfer rates and power to run time
    2010            1 :         QLoadTotal *= PartLoadRatio;
    2011            1 :         Power *= heatPump.RunFrac;
    2012            1 :         QSource *= PartLoadRatio;
    2013              : 
    2014              :         // Update heat pump data structure
    2015            1 :         state.dataHVACGlobal->DXElecHeatingPower = Power;
    2016            1 :         heatPump.Power = Power;
    2017            1 :         heatPump.QLoadTotal = QLoadTotal;
    2018            1 :         heatPump.QSensible = QLoadTotal;
    2019              : 
    2020            1 :         heatPump.QSource = QSource;
    2021            1 :         heatPump.PartLoadRatio = PartLoadRatio;
    2022            1 :         heatPump.OutletAirMassFlowRate = heatPump.InletAirMassFlowRate;
    2023            1 :         heatPump.OutletWaterTemp = SourceSideOutletTemp;
    2024            1 :         heatPump.OutletWaterMassFlowRate = heatPump.InletWaterMassFlowRate;
    2025            1 :         heatPump.OutletWaterEnthalpy = heatPump.InletWaterEnthalpy - QSource / heatPump.InletWaterMassFlowRate;
    2026              :     }
    2027              : 
    2028            0 :     void UpdateWatertoAirHP(EnergyPlusData &state, int const HPNum)
    2029              :     {
    2030              :         // SUBROUTINE INFORMATION:
    2031              :         //       AUTHOR         Hui Jin
    2032              :         //       DATE WRITTEN   Oct 2000
    2033              : 
    2034              :         // PURPOSE OF THIS SUBROUTINE:
    2035              :         // This subroutine updates the Water to Air Heat Pump outlet nodes.
    2036              : 
    2037              :         // METHODOLOGY EMPLOYED:
    2038              :         // Data is moved from the HP data structure to the HP outlet nodes.
    2039              : 
    2040              :         // Using/Aliasing
    2041            0 :         Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    2042            0 :         auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
    2043              : 
    2044              :         // WatertoAirHP(HPNum)%SimFlag=.FALSE.
    2045            0 :         if (!heatPump.SimFlag) {
    2046              :             // Heatpump is off; just pass through conditions
    2047            0 :             heatPump.Power = 0.0;
    2048            0 :             heatPump.Energy = 0.0;
    2049            0 :             heatPump.QLoadTotal = 0.0;
    2050            0 :             heatPump.QSensible = 0.0;
    2051            0 :             heatPump.QLatent = 0.0;
    2052            0 :             heatPump.QSource = 0.0;
    2053            0 :             heatPump.RunFrac = 0.0;
    2054            0 :             heatPump.PartLoadRatio = 0.0;
    2055            0 :             heatPump.OutletAirDBTemp = heatPump.InletAirDBTemp;
    2056            0 :             heatPump.OutletAirHumRat = heatPump.InletAirHumRat;
    2057            0 :             heatPump.OutletWaterTemp = heatPump.InletWaterTemp;
    2058            0 :             heatPump.OutletAirMassFlowRate = heatPump.InletAirMassFlowRate;
    2059            0 :             heatPump.OutletWaterMassFlowRate = heatPump.InletWaterMassFlowRate;
    2060            0 :             heatPump.OutletAirEnthalpy = heatPump.InletAirEnthalpy;
    2061            0 :             heatPump.OutletWaterEnthalpy = heatPump.InletWaterEnthalpy;
    2062              :         }
    2063              : 
    2064              :         // Set the outlet air nodes of the WatertoAirHP
    2065            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRate;
    2066            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).Temp = heatPump.OutletAirDBTemp;
    2067            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).HumRat = heatPump.OutletAirHumRat;
    2068            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).Enthalpy = heatPump.OutletAirEnthalpy;
    2069              : 
    2070              :         // Set the outlet nodes for properties that just pass through & not used
    2071            0 :         PlantUtilities::SafeCopyPlantNode(state, heatPump.WaterInletNodeNum, heatPump.WaterOutletNodeNum);
    2072              :         // Set the outlet water nodes for the heat pump
    2073            0 :         state.dataLoopNodes->Node(heatPump.WaterOutletNodeNum).Temp = heatPump.OutletWaterTemp;
    2074            0 :         state.dataLoopNodes->Node(heatPump.WaterOutletNodeNum).Enthalpy = heatPump.OutletWaterEnthalpy;
    2075              : 
    2076              :         // Set the outlet nodes for properties that just pass through & not used
    2077            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).Quality = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).Quality;
    2078            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).Press = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).Press;
    2079            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRateMin = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRateMin;
    2080            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRateMax;
    2081            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRateMinAvail =
    2082            0 :             state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRateMinAvail;
    2083            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRateMaxAvail =
    2084            0 :             state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRateMaxAvail;
    2085              : 
    2086              :         // Pass through the load side mass flow rates
    2087            0 :         heatPump.InletAirMassFlowRate = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRate;
    2088            0 :         heatPump.OutletAirMassFlowRate = heatPump.InletAirMassFlowRate;
    2089              : 
    2090            0 :         heatPump.Energy = heatPump.Power * TimeStepSysSec;
    2091            0 :         heatPump.EnergyLoadTotal = heatPump.QLoadTotal * TimeStepSysSec;
    2092            0 :         heatPump.EnergySensible = heatPump.QSensible * TimeStepSysSec;
    2093            0 :         heatPump.EnergyLatent = heatPump.QLatent * TimeStepSysSec;
    2094            0 :         heatPump.EnergySource = heatPump.QSource * TimeStepSysSec;
    2095              : 
    2096            0 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2097            0 :             state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).CO2 = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).CO2;
    2098              :         }
    2099            0 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2100            0 :             state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).GenContam = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).GenContam;
    2101              :         }
    2102            0 :     }
    2103              : 
    2104              :     //        End of Update subroutines for the WatertoAirHP Module
    2105              :     // *****************************************************************************
    2106              : 
    2107            0 :     Real64 CalcEffectiveSHR(EnergyPlusData &state,
    2108              :                             int const HPNum,         // Index number for cooling coil
    2109              :                             Real64 const SHRss,      // Steady-state sensible heat ratio
    2110              :                             HVAC::FanOp const fanOp, // fan/compressor cycling scheme indicator
    2111              :                             Real64 const RTF,        // Compressor run-time fraction
    2112              :                             Real64 const QLatRated,  // Rated latent capacity
    2113              :                             Real64 const QLatActual, // Actual latent capacity
    2114              :                             Real64 const EnteringDB, // Entering air dry-bulb temperature
    2115              :                             Real64 const EnteringWB  // Entering air wet-bulb temperature
    2116              :     )
    2117              :     {
    2118              : 
    2119              :         // FUNCTION INFORMATION:
    2120              :         //    AUTHOR         Richard Raustad, FSEC
    2121              :         //    DATE WRITTEN   September 2003
    2122              :         //    MODIFIED       Kenneth Tang (Aug 2004) Added capability for simulating FanOp::Cycling
    2123              : 
    2124              :         // PURPOSE OF THIS FUNCTION:
    2125              :         //    Adjust sensible heat ratio to account for degradation of DX coil latent
    2126              :         //    capacity at part-load (cycling) conditions.
    2127              : 
    2128              :         // METHODOLOGY EMPLOYED:
    2129              :         //    With model parameters entered by the user, the part-load latent performance
    2130              :         //    of a DX cooling coil is determined for a constant air flow system with
    2131              :         //    a cooling coil that cycles on/off. The model calculates the time
    2132              :         //    required for condensate to begin falling from the cooling coil.
    2133              :         //    Runtimes greater than this are integrated to a "part-load" latent
    2134              :         //    capacity which is used to determine the "part-load" sensible heat ratio.
    2135              :         //    See reference below for additional details (linear decay model, Eq. 8b).
    2136              :         // REFERENCES:
    2137              :         //   "A Model to Predict the Latent Capacity of Air Conditioners and
    2138              :         //    Heat Pumps at Part-Load Conditions with Constant Fan Operation"
    2139              :         //    1996 ASHRAE Transactions, Volume 102, Part 1, Pp. 266 - 274,
    2140              :         //    Hugh I. Henderson, Jr., P.E., Kannan Rengarajan, P.E.
    2141              : 
    2142              :         // Using/Aliasing
    2143            0 :         auto const &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
    2144              : 
    2145              :         // Return value
    2146              :         Real64 SHReff; // Effective sensible heat ratio, includes degradation due to cycling effects
    2147              : 
    2148              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2149              :         Real64 Twet; // Nominal time for condensate to begin leaving the coil's condensate drain line
    2150              :         //   at the current operating conditions (sec)
    2151              :         Real64 Gamma; // Initial moisture evaporation rate divided by steady-state AC latent capacity
    2152              :         //   at the current operating conditions
    2153              :         Real64 Twet_max; // Maximum allowed value for Twet
    2154              :         // shut off after compressor cycle off  [s]
    2155              : 
    2156              :         Real64 Ton;     // Coil on time (sec)
    2157              :         Real64 Toff;    // Coil off time (sec)
    2158              :         Real64 Toffa;   // Actual coil off time (sec). Equations valid for Toff <= (2.0 * Twet/Gamma)
    2159              :         Real64 aa;      // Intermediate variable
    2160              :         Real64 To1;     // Intermediate variable (first guess at To). To = time to the start of moisture removal
    2161              :         Real64 To2;     // Intermediate variable (second guess at To). To = time to the start of moisture removal
    2162              :         Real64 Error;   // Error for iteration (DO) loop
    2163              :         Real64 LHRmult; // Latent Heat Ratio (LHR) multiplier. The effective latent heat ratio LHR = (1-SHRss)*LHRmult
    2164              : 
    2165              :         //  No moisture evaporation (latent degradation) occurs for runtime fraction of 1.0
    2166              :         //  All latent degradation model parameters cause divide by 0.0 if not greater than 0.0
    2167              :         //  Latent degradation model parameters initialize to 0.0 meaning no evaporation model used.
    2168            0 :         if ((RTF >= 1.0) || (QLatRated == 0.0) || (QLatActual == 0.0) || (heatPump.Twet_Rated <= 0.0) || (heatPump.Gamma_Rated <= 0.0) ||
    2169            0 :             (heatPump.MaxONOFFCyclesperHour <= 0.0) || (heatPump.LatentCapacityTimeConstant <= 0.0) || (RTF <= 0.0)) {
    2170            0 :             SHReff = SHRss;
    2171            0 :             return SHReff;
    2172              :         }
    2173              : 
    2174            0 :         Twet_max = 9999.0; // high limit for Twet
    2175              : 
    2176              :         //  Calculate the model parameters at the actual operating conditions
    2177            0 :         Twet = min(heatPump.Twet_Rated * QLatRated / (QLatActual + 1.e-10), Twet_max);
    2178            0 :         Gamma = heatPump.Gamma_Rated * QLatRated * (EnteringDB - EnteringWB) / ((26.7 - 19.4) * QLatActual + 1.e-10);
    2179              : 
    2180              :         //  Calculate the compressor on and off times using a conventional thermostat curve
    2181            0 :         Ton = 3600.0 / (4.0 * heatPump.MaxONOFFCyclesperHour * (1.0 - RTF)); // duration of cooling coil on-cycle (sec)
    2182              : 
    2183            0 :         if ((fanOp == HVAC::FanOp::Cycling) && (heatPump.FanDelayTime != 0.0)) {
    2184              :             //  For FanOp::Cycling, moisture is evaporated from the cooling coil back to the air stream
    2185              :             //  until the fan cycle off. Assume no evaporation from the coil after the fan shuts off.
    2186            0 :             Toff = heatPump.FanDelayTime;
    2187              :         } else {
    2188              :             //  For FanOp::Continuous, moisture is evaporated from the cooling coil back to the air stream
    2189              :             //  for the entire heat pump off-cycle.
    2190            0 :             Toff = 3600.0 / (4.0 * heatPump.MaxONOFFCyclesperHour * RTF); // duration of cooling coil off-cycle (sec)
    2191              :         }
    2192              : 
    2193              :         //  Cap Toff to meet the equation restriction
    2194            0 :         if (Gamma > 0.0) {
    2195            0 :             Toffa = min(Toff, 2.0 * Twet / Gamma);
    2196              :         } else {
    2197            0 :             Toffa = Toff;
    2198              :         }
    2199              : 
    2200              :         //  Use sucessive substitution to solve for To
    2201            0 :         aa = (Gamma * Toffa) - (0.25 / Twet) * pow_2(Gamma) * pow_2(Toffa);
    2202              : 
    2203            0 :         To1 = aa + heatPump.LatentCapacityTimeConstant;
    2204            0 :         Error = 1.0;
    2205            0 :         while (Error > 0.001) {
    2206            0 :             To2 = aa - heatPump.LatentCapacityTimeConstant * std::expm1(-To1 / heatPump.LatentCapacityTimeConstant);
    2207            0 :             Error = std::abs((To2 - To1) / To1);
    2208            0 :             To1 = To2;
    2209              :         }
    2210              : 
    2211              :         //  Adjust Sensible Heat Ratio (SHR) using Latent Heat Ratio (LHR) multiplier
    2212              :         //  Floating underflow errors occur when -Ton/LatentCapacityTimeConstant is a large negative number.
    2213              :         //  Cap lower limit at -700 to avoid the underflow errors.
    2214            0 :         aa = std::exp(max(-700.0, -Ton / heatPump.LatentCapacityTimeConstant));
    2215              :         //  Calculate latent heat ratio multiplier
    2216            0 :         LHRmult = max(((Ton - To2) / (Ton + heatPump.LatentCapacityTimeConstant * (aa - 1.0))), 0.0);
    2217              : 
    2218              :         //  Calculate part-load or "effective" sensible heat ratio
    2219            0 :         SHReff = 1.0 - (1.0 - SHRss) * LHRmult;
    2220              : 
    2221            0 :         if (SHReff < SHRss) {
    2222            0 :             SHReff = SHRss; // Effective SHR can be less than the steady-state SHR
    2223              :         }
    2224            0 :         if (SHReff > 1.0) {
    2225            0 :             SHReff = 1.0; // Effective sensible heat ratio can't be greater than 1.0
    2226              :         }
    2227              : 
    2228            0 :         return SHReff;
    2229              :     }
    2230              : 
    2231            0 :     Real64 DegradF(EnergyPlusData &state,
    2232              :                    Fluid::GlycolProps *glycol,
    2233              :                    Real64 &Temp // Temperature of the fluid
    2234              :     )
    2235              :     {
    2236              :         // FUNCTION INFORMATION:
    2237              :         //    AUTHOR         Kenneth Tang
    2238              :         //    DATE WRITTEN   October 2004
    2239              : 
    2240              :         // PURPOSE OF THIS FUNCTION:
    2241              :         //    Calculate the degradation factor to predict the heat pump performance
    2242              :         //    when antifreeze is used.
    2243              :         // METHODOLOGY EMPLOYED:
    2244              :         //    Use FluidProperties to calculate the properties of water and glycol
    2245              :         //    at the given temperature. Then substitute the properties into the equation.
    2246              :         // REFERENCES:
    2247              :         //    Jin, H. 2002. Parameter Estimation Based Models of Water Source Heat Pumps. Phd Thesis.
    2248              :         //    Oklahoma State University.
    2249              : 
    2250              :         // Return value
    2251              :         Real64 DegradF;
    2252              : 
    2253              :         // FUNCTION PARAMETER DEFINITIONS:
    2254              :         static constexpr std::string_view CalledFrom("HVACWaterToAir:DegradF");
    2255              : 
    2256              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2257              :         Real64 VisWater;       // Viscosity of water [mPa-s]
    2258              :         Real64 DensityWater;   // Density of water [kg/m3]
    2259              :         Real64 CpWater;        // Specific heat of water [J/kg-K]
    2260              :         Real64 CondWater;      // Conductivity of water [W/m-K]
    2261              :         Real64 VisCoolant;     // Viscosity of water [mPa-s]
    2262              :         Real64 DensityCoolant; // Density of water [kg/m3]
    2263              :         Real64 CpCoolant;      // Specific heat of water [J/kg-K]
    2264              :         Real64 CondCoolant;    // Conductivity of water [W/m-K]
    2265              : 
    2266            0 :         auto *water = Fluid::GetWater(state);
    2267              : 
    2268            0 :         VisWater = water->getViscosity(state, Temp, CalledFrom);
    2269            0 :         DensityWater = water->getDensity(state, Temp, CalledFrom);
    2270            0 :         CpWater = water->getSpecificHeat(state, Temp, CalledFrom);
    2271            0 :         CondWater = water->getConductivity(state, Temp, CalledFrom);
    2272            0 :         VisCoolant = glycol->getViscosity(state, Temp, CalledFrom);
    2273            0 :         DensityCoolant = glycol->getDensity(state, Temp, CalledFrom);
    2274            0 :         CpCoolant = glycol->getSpecificHeat(state, Temp, CalledFrom);
    2275            0 :         CondCoolant = glycol->getConductivity(state, Temp, CalledFrom);
    2276              : 
    2277            0 :         DegradF = std::pow(VisCoolant / VisWater, -0.47) * std::pow(DensityCoolant / DensityWater, 0.8) * std::pow(CpCoolant / CpWater, 0.33) *
    2278            0 :                   std::pow(CondCoolant / CondWater, 0.67);
    2279              : 
    2280            0 :         return DegradF;
    2281              :     }
    2282              : 
    2283            0 :     int GetCoilIndex(EnergyPlusData &state,
    2284              :                      std::string const &CoilType, // must match coil types in this module
    2285              :                      std::string const &CoilName, // must match coil names for the coil type
    2286              :                      bool &ErrorsFound            // set to true if problem
    2287              :     )
    2288              :     {
    2289              : 
    2290              :         // FUNCTION INFORMATION:
    2291              :         //       AUTHOR         R. Raustad
    2292              :         //       DATE WRITTEN   August 2007
    2293              : 
    2294              :         // PURPOSE OF THIS FUNCTION:
    2295              :         // This function looks up the given coil and returns the index.  If
    2296              :         // incorrect coil type or name is given, ErrorsFound is returned as true and value is returned
    2297              :         // as zero.
    2298              : 
    2299              :         // Obtains and Allocates WatertoAirHP related parameters from input file
    2300            0 :         if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered
    2301            0 :             GetWatertoAirHPInput(state);
    2302            0 :             state.dataWaterToAirHeatPump->GetCoilsInputFlag = false;
    2303              :         }
    2304              : 
    2305            0 :         int IndexNum = Util::FindItemInList(CoilName, state.dataWaterToAirHeatPump->WatertoAirHP);
    2306              : 
    2307            0 :         if (IndexNum == 0) {
    2308            0 :             ShowSevereError(state, format("Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
    2309            0 :             ErrorsFound = true;
    2310              :         }
    2311              : 
    2312            0 :         return IndexNum;
    2313              :     }
    2314              : 
    2315            0 :     Real64 GetCoilCapacity(EnergyPlusData &state,
    2316              :                            std::string const &CoilType, // must match coil types in this module
    2317              :                            std::string const &CoilName, // must match coil names for the coil type
    2318              :                            bool &ErrorsFound            // set to true if problem
    2319              :     )
    2320              :     {
    2321              : 
    2322              :         // FUNCTION INFORMATION:
    2323              :         //       AUTHOR         Linda Lawrie
    2324              :         //       DATE WRITTEN   February 2006
    2325              : 
    2326              :         // PURPOSE OF THIS FUNCTION:
    2327              :         // This function looks up the coil capacity for the given coil and returns it.  If
    2328              :         // incorrect coil type or name is given, ErrorsFound is returned as true and capacity is returned
    2329              :         // as negative.
    2330              : 
    2331              :         // Return value
    2332              :         Real64 CoilCapacity; // returned capacity of matched coil
    2333              : 
    2334              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2335              :         int WhichCoil;
    2336              : 
    2337              :         // Obtains and Allocates WatertoAirHP related parameters from input file
    2338            0 :         if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered
    2339            0 :             GetWatertoAirHPInput(state);
    2340            0 :             state.dataWaterToAirHeatPump->GetCoilsInputFlag = false;
    2341              :         }
    2342              : 
    2343            0 :         if (Util::SameString(CoilType, "COIL:HEATING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION") ||
    2344            0 :             Util::SameString(CoilType, "COIL:COOLING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION")) {
    2345            0 :             WhichCoil = Util::FindItemInList(CoilName, state.dataWaterToAirHeatPump->WatertoAirHP);
    2346            0 :             if (WhichCoil != 0) {
    2347            0 :                 if (Util::SameString(CoilType, "COIL:HEATING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION")) {
    2348            0 :                     CoilCapacity = state.dataWaterToAirHeatPump->WatertoAirHP(WhichCoil).HeatingCapacity;
    2349              :                 } else {
    2350            0 :                     CoilCapacity = state.dataWaterToAirHeatPump->WatertoAirHP(WhichCoil).CoolingCapacity;
    2351              :                 }
    2352              :             }
    2353              :         } else {
    2354            0 :             WhichCoil = 0;
    2355              :         }
    2356              : 
    2357            0 :         if (WhichCoil == 0) {
    2358            0 :             ShowSevereError(state, format("Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
    2359            0 :             ErrorsFound = true;
    2360            0 :             CoilCapacity = -1000.0;
    2361              :         }
    2362              : 
    2363            0 :         return CoilCapacity;
    2364              :     }
    2365              : 
    2366            0 :     int GetCoilInletNode(EnergyPlusData &state,
    2367              :                          std::string const &CoilType, // must match coil types in this module
    2368              :                          std::string const &CoilName, // must match coil names for the coil type
    2369              :                          bool &ErrorsFound            // set to true if problem
    2370              :     )
    2371              :     {
    2372              : 
    2373              :         // FUNCTION INFORMATION:
    2374              :         //       AUTHOR         Linda Lawrie
    2375              :         //       DATE WRITTEN   February 2006
    2376              : 
    2377              :         // PURPOSE OF THIS FUNCTION:
    2378              :         // This function looks up the given coil and returns the inlet node.  If
    2379              :         // incorrect coil type or name is given, ErrorsFound is returned as true and value is returned
    2380              :         // as zero.
    2381              : 
    2382              :         // Return value
    2383              :         int NodeNumber; // returned outlet node of matched coil
    2384              : 
    2385              :         // Obtains and Allocates WatertoAirHP related parameters from input file
    2386            0 :         if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered
    2387            0 :             GetWatertoAirHPInput(state);
    2388            0 :             state.dataWaterToAirHeatPump->GetCoilsInputFlag = false;
    2389              :         }
    2390              : 
    2391            0 :         int WhichCoil = Util::FindItemInList(CoilName, state.dataWaterToAirHeatPump->WatertoAirHP);
    2392            0 :         if (WhichCoil != 0) {
    2393            0 :             NodeNumber = state.dataWaterToAirHeatPump->WatertoAirHP(WhichCoil).AirInletNodeNum;
    2394              :         }
    2395              : 
    2396            0 :         if (WhichCoil == 0) {
    2397            0 :             ShowSevereError(state, format("Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
    2398            0 :             ErrorsFound = true;
    2399            0 :             NodeNumber = 0;
    2400              :         }
    2401              : 
    2402            0 :         return NodeNumber;
    2403              :     }
    2404              : 
    2405            0 :     int GetCoilOutletNode(EnergyPlusData &state,
    2406              :                           std::string const &CoilType, // must match coil types in this module
    2407              :                           std::string const &CoilName, // must match coil names for the coil type
    2408              :                           bool &ErrorsFound            // set to true if problem
    2409              :     )
    2410              :     {
    2411              : 
    2412              :         // FUNCTION INFORMATION:
    2413              :         //       AUTHOR         R. Raustad
    2414              :         //       DATE WRITTEN   July 2007
    2415              : 
    2416              :         // PURPOSE OF THIS FUNCTION:
    2417              :         // This function looks up the given coil and returns the outlet node.  If
    2418              :         // incorrect coil type or name is given, ErrorsFound is returned as true and value is returned
    2419              :         // as zero.
    2420              : 
    2421              :         // Return value
    2422              :         int NodeNumber; // returned outlet node of matched coil
    2423              : 
    2424              :         // Obtains and Allocates WatertoAirHP related parameters from input file
    2425            0 :         if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered
    2426            0 :             GetWatertoAirHPInput(state);
    2427            0 :             state.dataWaterToAirHeatPump->GetCoilsInputFlag = false;
    2428              :         }
    2429              : 
    2430            0 :         int WhichCoil = Util::FindItemInList(CoilName, state.dataWaterToAirHeatPump->WatertoAirHP);
    2431            0 :         if (WhichCoil != 0) {
    2432            0 :             NodeNumber = state.dataWaterToAirHeatPump->WatertoAirHP(WhichCoil).AirOutletNodeNum;
    2433              :         }
    2434              : 
    2435            0 :         if (WhichCoil == 0) {
    2436            0 :             ShowSevereError(state, format("Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
    2437            0 :             ErrorsFound = true;
    2438            0 :             NodeNumber = 0;
    2439              :         }
    2440              : 
    2441            0 :         return NodeNumber;
    2442              :     }
    2443              : 
    2444              : } // namespace WaterToAirHeatPump
    2445              : 
    2446              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1