LCOV - code coverage report
Current view: top level - EnergyPlus - WaterToAirHeatPump.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 59.3 % 1080 640
Test Date: 2025-05-22 16:09:37 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            1 :         if (state.dataWaterToAirHeatPump->initialQSource_calc == 0.0) state.dataWaterToAirHeatPump->initialQSource_calc = heatPump.CoolingCapacity;
    1287              : 
    1288              :         // Loop the calculation at least twice depending whether the latent degradation model
    1289              :         // is enabled. 1st iteration to calculate the QLatent(rated) at (TDB,TWB)indoorair=(26.7C,19.4C)
    1290              :         // and 2nd iteration to calculate the  QLatent(actual)
    1291              : 
    1292              :         // Calculate Part Load Factor and Runtime Fraction
    1293            1 :         Real64 PLF = 1.0; // part load factor as a function of PLR, RTF = PLR / PLF
    1294            1 :         if (heatPump.PLFCurveIndex > 0) {
    1295            1 :             PLF = Curve::CurveValue(state, heatPump.PLFCurveIndex, PartLoadRatio); // Calculate part-load factor
    1296              :         }
    1297            1 :         if (fanOp == HVAC::FanOp::Cycling) {
    1298            1 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = PLF;
    1299              :         }
    1300            1 :         heatPump.RunFrac = PartLoadRatio / PLF;
    1301              : 
    1302            1 :         QLatRated = 0.0;
    1303            1 :         QLatActual = 0.0;
    1304              :         // IF((RuntimeFrac .GE. 1.0) .OR. (Twet_rated .LE. 0.0) .OR. (Gamma_rated .LE. 0.0)) THEN
    1305              :         // Cycling fan does not required latent degradation model, only the constant fan case
    1306            1 :         if ((heatPump.RunFrac >= 1.0) || (heatPump.Twet_Rated <= 0.0) || (heatPump.Gamma_Rated <= 0.0) || (fanOp == HVAC::FanOp::Cycling)) {
    1307            1 :             LatDegradModelSimFlag = false;
    1308              :             // Set NumIteration4=1 so that latent model would quit after 1 simulation with the actual condition
    1309            1 :             NumIteration4 = 1;
    1310              :         } else {
    1311            0 :             LatDegradModelSimFlag = true;
    1312              :             // Set NumIteration4=0 so that latent model would simulate twice with rated and actual condition
    1313            0 :             NumIteration4 = 0;
    1314              :         }
    1315              : 
    1316              :         // Tuned Hoisted quantities out of nested loop that don't change
    1317            1 :         Real64 const LoadSideMassFlowRate_CpAir_inv(1.0 / (heatPump.InletAirMassFlowRate * CpAir));
    1318              :         Real64 const LoadSideEffec(1.0 -
    1319            1 :                                    std::exp(-heatPump.LoadSideOutsideUACoeff *
    1320            1 :                                             LoadSideMassFlowRate_CpAir_inv)); // Load Side Effectiveness based on Outside Heat Transfer Coefficient
    1321            1 :         Real64 const LoadSideEffec_MassFlowRate_inv(1.0 / (LoadSideEffec * heatPump.InletAirMassFlowRate));
    1322            1 :         ANTUWET = heatPump.LoadSideTotalUACoeff * LoadSideMassFlowRate_CpAir_inv;
    1323            1 :         EffectWET = 1.0 - std::exp(-ANTUWET);
    1324              : 
    1325              :         while (true) {
    1326            1 :             ++NumIteration4;
    1327            1 :             if (NumIteration4 == 1) {
    1328              :                 // Set indoor air conditions to the rated condition
    1329            0 :                 LoadSideInletDBTemp = state.dataWaterToAirHeatPump->LoadSideInletDBTemp_Init;
    1330            0 :                 LoadSideInletHumRat = state.dataWaterToAirHeatPump->LoadSideInletHumRat_Init;
    1331            0 :                 LoadSideAirInletEnth = state.dataWaterToAirHeatPump->LoadSideAirInletEnth_Init;
    1332              :             } else {
    1333              :                 // Set indoor air conditions to the actual condition
    1334            1 :                 LoadSideInletDBTemp = heatPump.InletAirDBTemp;
    1335            1 :                 LoadSideInletHumRat = heatPump.InletAirHumRat;
    1336            1 :                 LoadSideAirInletEnth = LoadSideAirInletEnth_Unit;
    1337              :             }
    1338              : 
    1339              :             // Outerloop: Calculate source side heat transfer
    1340            1 :             int NumIteration2 = 0;
    1341            1 :             Converged = false;
    1342            1 :             StillSimulatingFlag = true;
    1343            1 :             SourceResidual = 1.0;
    1344           17 :             while (StillSimulatingFlag) {
    1345           16 :                 if (Converged) StillSimulatingFlag = false;
    1346              : 
    1347           16 :                 ++NumIteration2;
    1348           16 :                 if (NumIteration2 == 1) RelaxParam = 0.5;
    1349              : 
    1350           16 :                 if (NumIteration2 > STOP2) {
    1351            0 :                     heatPump.SimFlag = false;
    1352            0 :                     return;
    1353              :                 }
    1354              : 
    1355              :                 // Innerloop: Calculate load side heat transfer
    1356           16 :                 NumIteration3 = 0;
    1357           16 :                 LoadResidual = 1.0;
    1358           59 :                 while (LoadResidual > ERR) {
    1359              : 
    1360           43 :                     ++NumIteration3;
    1361              : 
    1362           43 :                     if (NumIteration3 > STOP3) {
    1363            0 :                         heatPump.SimFlag = false;
    1364            0 :                         return;
    1365              :                     }
    1366              : 
    1367              :                     // Determine Effectiveness of Source Side
    1368           43 :                     CpFluid = state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum)
    1369           43 :                                   .glycol->getSpecificHeat(state, heatPump.InletWaterTemp, RoutineNameSourceSideInletTemp);
    1370              : 
    1371           43 :                     if (state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).glycol->Num == Fluid::GlycolNum_Water) {
    1372           43 :                         SourceSideEffect = 1.0 - std::exp(-heatPump.SourceSideUACoeff / (CpFluid * heatPump.InletWaterMassFlowRate));
    1373              :                     } else {
    1374            0 :                         DegradFactor = DegradF(state, state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).glycol, heatPump.InletWaterTemp);
    1375            0 :                         SourceSideEffect =
    1376            0 :                             1.0 / ((heatPump.SourceSideHTR1 * std::pow(SourceSideVolFlowRate, -0.8)) / DegradFactor + heatPump.SourceSideHTR2);
    1377              :                     }
    1378              : 
    1379              :                     // Determine Source Side Tempertaure (Condensing Temp in this case)
    1380           43 :                     SourceSideTemp = heatPump.InletWaterTemp + state.dataWaterToAirHeatPump->initialQSource_calc /
    1381           43 :                                                                    (SourceSideEffect * CpFluid * heatPump.InletWaterMassFlowRate);
    1382              : 
    1383              :                     // Compute the Effective Surface Temperature
    1384           43 :                     EffectiveSatEnth = LoadSideAirInletEnth - state.dataWaterToAirHeatPump->initialQLoadTotal_calc * LoadSideEffec_MassFlowRate_inv;
    1385              : 
    1386           43 :                     EffectiveSurfaceTemp = Psychrometrics::PsyTsatFnHPb(state, EffectiveSatEnth, PB, RoutineNameLoadSideSurfaceTemp);
    1387              : 
    1388           43 :                     QSensible = heatPump.InletAirMassFlowRate * CpAir * (LoadSideInletDBTemp - EffectiveSurfaceTemp) * LoadSideEffec;
    1389           43 :                     EvapSatEnth =
    1390           43 :                         LoadSideAirInletEnth - state.dataWaterToAirHeatPump->initialQLoadTotal_calc / (EffectWET * heatPump.InletAirMassFlowRate);
    1391              : 
    1392           43 :                     EvapTemp = Psychrometrics::PsyTsatFnHPb(state, EvapSatEnth, PB, RoutineNameLoadSideEvapTemp);
    1393              : 
    1394              :                     // Load Side Saturated Temperature (Evaporating Temp in this case)
    1395           43 :                     LoadSideTemp = EvapTemp;
    1396              : 
    1397              :                     // Determine the Load Side and Source Side Saturated Temp (evaporating and condensing pressures)
    1398           43 :                     SourceSidePressure = heatPump.refrig->getSatPressure(state, SourceSideTemp, RoutineNameSourceSideTemp);
    1399           43 :                     LoadSidePressure = heatPump.refrig->getSatPressure(state, LoadSideTemp, RoutineNameLoadSideTemp);
    1400              : 
    1401           43 :                     if (LoadSidePressure < heatPump.LowPressCutoff && !FirstHVACIteration) {
    1402            0 :                         if (!state.dataGlobal->WarmupFlag) {
    1403            0 :                             ShowRecurringWarningErrorAtEnd(
    1404              :                                 state,
    1405            0 :                                 format("WaterToAir Heat pump:cooling [{}] shut off on low pressure < {:.0R}", heatPump.Name, heatPump.LowPressCutoff),
    1406            0 :                                 heatPump.LowPressClgError,
    1407              :                                 LoadSidePressure,
    1408              :                                 LoadSidePressure,
    1409              :                                 _,
    1410              :                                 "[Pa]",
    1411              :                                 "[Pa]");
    1412              :                         }
    1413            0 :                         heatPump.SimFlag = false;
    1414            0 :                         return;
    1415              :                     }
    1416              : 
    1417           43 :                     if (SourceSidePressure > heatPump.HighPressCutoff && !FirstHVACIteration) {
    1418            0 :                         if (!state.dataGlobal->WarmupFlag) {
    1419            0 :                             ShowRecurringWarningErrorAtEnd(state,
    1420            0 :                                                            format("WaterToAir Heat pump:cooling [{}] shut off on high pressure > {:.0R}",
    1421            0 :                                                                   heatPump.Name,
    1422            0 :                                                                   heatPump.HighPressCutoff),
    1423            0 :                                                            heatPump.HighPressClgError,
    1424            0 :                                                            heatPump.InletWaterTemp,
    1425            0 :                                                            heatPump.InletWaterTemp,
    1426              :                                                            _,
    1427              :                                                            "SourceSideInletTemp[C]",
    1428              :                                                            "SourceSideInletTemp[C]");
    1429              :                         }
    1430            0 :                         heatPump.SimFlag = false;
    1431            0 :                         return;
    1432              :                     }
    1433              : 
    1434              :                     // Determine Suction Pressure & Discharge Pressure at Compressor Exit
    1435           43 :                     if (heatPump.compressorType == CompressorType::Reciprocating) { // RECIPROCATING
    1436            0 :                         SuctionPr = LoadSidePressure - heatPump.CompSucPressDrop;
    1437            0 :                         DischargePr = SourceSidePressure + heatPump.CompSucPressDrop;
    1438           43 :                     } else if (heatPump.compressorType == CompressorType::Rotary) { // ROTARY
    1439            0 :                         SuctionPr = LoadSidePressure;
    1440            0 :                         DischargePr = SourceSidePressure + heatPump.CompSucPressDrop;
    1441           43 :                     } else if (heatPump.compressorType == CompressorType::Scroll) { // SCROLL
    1442           43 :                         SuctionPr = LoadSidePressure;
    1443           43 :                         DischargePr = SourceSidePressure;
    1444              :                     }
    1445              : 
    1446              :                     // Determine the Load Side Outlet Enthalpy (Saturated Gas)
    1447           43 :                     Quality = 1.0;
    1448           43 :                     LoadSideOutletEnth = heatPump.refrig->getSatEnthalpy(state, LoadSideTemp, Quality, RoutineNameLoadSideTemp);
    1449              : 
    1450              :                     // Determine Source Side Outlet Enthalpy (Saturated Liquid)
    1451           43 :                     Quality = 0.0;
    1452           43 :                     SourceSideOutletEnth = heatPump.refrig->getSatEnthalpy(state, SourceSideTemp, Quality, RoutineNameSourceSideTemp);
    1453              :                     // Determine Superheated Temperature of the Load Side outlet/compressor Inlet
    1454           43 :                     CompressInletTemp = LoadSideTemp + heatPump.SuperheatTemp;
    1455              : 
    1456              :                     // Determine the Enthalpy of the Superheated Fluid at Load Side Outlet/Compressor Inlet
    1457           43 :                     SuperHeatEnth = heatPump.refrig->getSupHeatEnthalpy(state, CompressInletTemp, LoadSidePressure, RoutineNameCompressInletTemp);
    1458              : 
    1459              :                     // Determining the suction state of the fluid from inlet state involves interation
    1460              :                     // Method employed...
    1461              :                     // Determine the saturated temp at suction pressure, shoot out into the superheated region find the enthalpy
    1462              :                     // check that with the inlet enthalpy ( as suction loss is isenthalpic). Iterate till desired accuracy is reached
    1463           43 :                     if (!Converged) {
    1464           42 :                         CompSuctionSatTemp = heatPump.refrig->getSatTemperature(state, SuctionPr, RoutineNameSuctionPr);
    1465           42 :                         CompSuctionTemp1 = CompSuctionSatTemp;
    1466              : 
    1467              :                         // Shoot into the Superheated Region
    1468           42 :                         CompSuctionTemp2 = CompSuctionSatTemp + DegreeofSuperheat;
    1469              :                     }
    1470              : 
    1471          129 :                     auto f = [&state, &heatPump, SuctionPr, SuperHeatEnth](Real64 const CompSuctionTemp) {
    1472              :                         static constexpr std::string_view RoutineName("CalcWaterToAirHPHeating:CalcCompSuctionTemp");
    1473          129 :                         Real64 compSuctionEnth = heatPump.refrig->getSupHeatEnthalpy(state, CompSuctionTemp, SuctionPr, RoutineName);
    1474          129 :                         return (compSuctionEnth - SuperHeatEnth) / SuperHeatEnth;
    1475           43 :                     };
    1476              : 
    1477           86 :                     General::SolveRoot(
    1478           43 :                         state, ERR, STOP1, SolFlag, state.dataWaterToAirHeatPump->CompSuctionTemp, f, CompSuctionTemp1, CompSuctionTemp2);
    1479           43 :                     if (SolFlag == -1) {
    1480            0 :                         heatPump.SimFlag = false;
    1481            0 :                         return;
    1482              :                     }
    1483           43 :                     CompSuctionEnth = heatPump.refrig->getSupHeatEnthalpy(
    1484           43 :                         state, state.dataWaterToAirHeatPump->CompSuctionTemp, SuctionPr, RoutineNameCompSuctionTemp);
    1485           43 :                     CompSuctionDensity = heatPump.refrig->getSupHeatDensity(
    1486           43 :                         state, state.dataWaterToAirHeatPump->CompSuctionTemp, SuctionPr, RoutineNameCompSuctionTemp);
    1487              : 
    1488              :                     // Find Refrigerant Flow Rate
    1489           43 :                     switch (heatPump.compressorType) {
    1490            0 :                     case CompressorType::Reciprocating: {
    1491            0 :                         MassRef =
    1492            0 :                             heatPump.CompPistonDisp * CompSuctionDensity *
    1493            0 :                             (1.0 + heatPump.CompClearanceFactor - heatPump.CompClearanceFactor * std::pow(DischargePr / SuctionPr, 1.0 / gamma));
    1494            0 :                         break;
    1495              :                     }
    1496            0 :                     case CompressorType::Rotary: {
    1497            0 :                         MassRef = heatPump.CompPistonDisp * CompSuctionDensity;
    1498            0 :                         break;
    1499              :                     }
    1500           43 :                     case CompressorType::Scroll: {
    1501           43 :                         MassRef = heatPump.RefVolFlowRate * CompSuctionDensity - heatPump.LeakRateCoeff * (DischargePr / SuctionPr);
    1502           43 :                         break;
    1503              :                     }
    1504            0 :                     default:
    1505            0 :                         break;
    1506              :                     }
    1507           43 :                     MassRef = max(0.0, MassRef);
    1508              : 
    1509              :                     // Find the Load Side Heat Transfer
    1510           43 :                     QLoadTotal = MassRef * (LoadSideOutletEnth - SourceSideOutletEnth);
    1511           43 :                     LoadResidual = std::abs(QLoadTotal - state.dataWaterToAirHeatPump->initialQLoadTotal_calc) /
    1512           43 :                                    state.dataWaterToAirHeatPump->initialQLoadTotal_calc;
    1513           86 :                     state.dataWaterToAirHeatPump->initialQLoadTotal_calc +=
    1514           43 :                         RelaxParam * (QLoadTotal - state.dataWaterToAirHeatPump->initialQLoadTotal_calc);
    1515           43 :                     if (NumIteration3 > 8) RelaxParam = 0.3;
    1516              :                 }
    1517              : 
    1518              :                 // Determine the Power Consumption
    1519           16 :                 switch (heatPump.compressorType) {
    1520            0 :                 case CompressorType::Reciprocating:
    1521              :                 case CompressorType::Rotary: {
    1522            0 :                     Power = heatPump.PowerLosses + (1.0 / heatPump.LossFactor) * (MassRef * gamma / (gamma - 1.0) * SuctionPr / CompSuctionDensity *
    1523            0 :                                                                                   (std::pow(DischargePr / SuctionPr, (gamma - 1.0) / gamma) - 1.0));
    1524            0 :                     break;
    1525              :                 }
    1526           16 :                 case CompressorType::Scroll: {
    1527           16 :                     Power = heatPump.PowerLosses + (1.0 / heatPump.LossFactor) * (gamma / (gamma - 1.0)) * SuctionPr * heatPump.RefVolFlowRate *
    1528           16 :                                                        (((gamma - 1.0) / gamma) * ((DischargePr / SuctionPr) / heatPump.VolumeRatio) +
    1529           16 :                                                         ((1.0 / gamma) * std::pow(heatPump.VolumeRatio, gamma - 1.0)) - 1.0);
    1530           16 :                     break;
    1531              :                 }
    1532            0 :                 default:
    1533            0 :                     break;
    1534              :                 }
    1535              : 
    1536              :                 // Determine the Sourceside Heat Rate
    1537           16 :                 QSource = Power + QLoadTotal;
    1538           16 :                 SourceResidual =
    1539           16 :                     std::abs(QSource - state.dataWaterToAirHeatPump->initialQSource_calc) / state.dataWaterToAirHeatPump->initialQSource_calc;
    1540           16 :                 if (SourceResidual < ERR) Converged = true;
    1541           16 :                 state.dataWaterToAirHeatPump->initialQSource_calc += RelaxParam * (QSource - state.dataWaterToAirHeatPump->initialQSource_calc);
    1542           16 :                 if (NumIteration2 > 8) RelaxParam = 0.2;
    1543              :             }
    1544              : 
    1545            1 :             if (SuctionPr < heatPump.LowPressCutoff) {
    1546            0 :                 ShowWarningError(state, "Heat pump:cooling shut down on low pressure");
    1547            0 :                 heatPump.SimFlag = false;
    1548              :             }
    1549              : 
    1550            1 :             if (DischargePr > heatPump.HighPressCutoff && !FirstHVACIteration) {
    1551            0 :                 ShowWarningError(state, "Heat pump:cooling shut down on high pressure");
    1552            0 :                 heatPump.SimFlag = false;
    1553              :             }
    1554              : 
    1555            1 :             if (QSensible > QLoadTotal) {
    1556            1 :                 QSensible = QLoadTotal;
    1557              :             }
    1558              : 
    1559            1 :             if (LatDegradModelSimFlag) {
    1560            0 :                 if (NumIteration4 == 1) {
    1561            0 :                     QLatRated = QLoadTotal - QSensible;
    1562              : 
    1563            0 :                 } else if (NumIteration4 == 2) {
    1564            0 :                     QLatActual = QLoadTotal - QSensible;
    1565            0 :                     SHRss = QSensible / QLoadTotal;
    1566            0 :                     LoadSideInletWBTemp = Psychrometrics::PsyTwbFnTdbWPb(state, LoadSideInletDBTemp, LoadSideInletHumRat, PB);
    1567            0 :                     SHReff = CalcEffectiveSHR(
    1568              :                         state, HPNum, SHRss, fanOp, heatPump.RunFrac, QLatRated, QLatActual, LoadSideInletDBTemp, LoadSideInletWBTemp);
    1569              :                     //   Update sensible capacity based on effective SHR
    1570            0 :                     QSensible = QLoadTotal * SHReff;
    1571            0 :                     goto LOOPLatentDegradationModel_exit;
    1572              :                 }
    1573              :             } else {
    1574              : 
    1575            1 :                 SHReff = QSensible / QLoadTotal;
    1576            1 :                 goto LOOPLatentDegradationModel_exit;
    1577              :             }
    1578            0 :         }
    1579            1 :     LOOPLatentDegradationModel_exit:;
    1580              : 
    1581              :         // calculate coil outlet state variables
    1582            1 :         LoadSideAirOutletEnth = LoadSideAirInletEnth - QLoadTotal / heatPump.InletAirMassFlowRate;
    1583            1 :         LoadSideOutletDBTemp = LoadSideInletDBTemp - QSensible * LoadSideMassFlowRate_CpAir_inv;
    1584            1 :         LoadSideOutletHumRat = Psychrometrics::PsyWFnTdbH(state, LoadSideOutletDBTemp, LoadSideAirOutletEnth, RoutineNameLoadSideOutletEnthalpy);
    1585            1 :         SourceSideOutletTemp = heatPump.InletWaterTemp + QSource / (heatPump.InletWaterMassFlowRate * CpWater);
    1586              : 
    1587              :         // Actual outlet conditions are "average" for time step
    1588            1 :         if (fanOp == HVAC::FanOp::Continuous) {
    1589              :             // continuous fan, cycling compressor
    1590            0 :             heatPump.OutletAirEnthalpy = PartLoadRatio * LoadSideAirOutletEnth + (1.0 - PartLoadRatio) * LoadSideAirInletEnth;
    1591            0 :             heatPump.OutletAirHumRat = PartLoadRatio * LoadSideOutletHumRat + (1.0 - PartLoadRatio) * LoadSideInletHumRat;
    1592            0 :             heatPump.OutletAirDBTemp = Psychrometrics::PsyTdbFnHW(heatPump.OutletAirEnthalpy, heatPump.OutletAirHumRat);
    1593              :         } else {
    1594              :             // default to cycling fan, cycling compressor
    1595            1 :             heatPump.OutletAirEnthalpy = LoadSideAirOutletEnth;
    1596            1 :             heatPump.OutletAirHumRat = LoadSideOutletHumRat;
    1597            1 :             heatPump.OutletAirDBTemp = LoadSideOutletDBTemp;
    1598              :         }
    1599              : 
    1600              :         // scale heat transfer rates and power to run time
    1601            1 :         QLoadTotal *= PartLoadRatio;
    1602            1 :         QSensible *= PartLoadRatio;
    1603            1 :         Power *= heatPump.RunFrac;
    1604            1 :         QSource *= PartLoadRatio;
    1605              : 
    1606              :         // Update heat pump data structure
    1607            1 :         state.dataHVACGlobal->DXElecCoolingPower = Power;
    1608            1 :         heatPump.Power = Power;
    1609            1 :         heatPump.QLoadTotal = QLoadTotal;
    1610            1 :         heatPump.QSensible = QSensible;
    1611            1 :         heatPump.QLatent = QLoadTotal - QSensible;
    1612            1 :         heatPump.QSource = QSource;
    1613            1 :         heatPump.PartLoadRatio = PartLoadRatio;
    1614              : 
    1615              :         //  Air-side outlet conditions are already calculated above
    1616            1 :         heatPump.OutletAirMassFlowRate = heatPump.InletAirMassFlowRate;
    1617            1 :         heatPump.OutletWaterTemp = SourceSideOutletTemp;
    1618            1 :         heatPump.OutletWaterMassFlowRate = heatPump.InletWaterMassFlowRate;
    1619            1 :         heatPump.OutletWaterEnthalpy = heatPump.InletWaterEnthalpy + QSource / heatPump.InletWaterMassFlowRate;
    1620              :     }
    1621              : 
    1622            1 :     void CalcWatertoAirHPHeating(EnergyPlusData &state,
    1623              :                                  int const HPNum,                      // heat pump number
    1624              :                                  HVAC::FanOp const fanOp,              // fan/compressor cycling scheme indicator
    1625              :                                  bool const FirstHVACIteration,        // first iteration flag
    1626              :                                  [[maybe_unused]] bool const InitFlag, // first iteration flag
    1627              :                                  Real64 const SensDemand,
    1628              :                                  HVAC::CompressorOp const compressorOp,
    1629              :                                  Real64 const PartLoadRatio)
    1630              :     {
    1631              : 
    1632              :         // SUBROUTINE INFORMATION:
    1633              :         //       AUTHOR         Hui Jin
    1634              :         //       DATE WRITTEN   Oct 2000
    1635              :         //       MODIFIED       R. Raustad (Oct 2006) Revised iteration technique
    1636              : 
    1637              :         // PURPOSE OF THIS SUBROUTINE:
    1638              :         // Simulates a parameter estimation based water to air heat pump model
    1639              : 
    1640              :         // Using/Aliasing
    1641            1 :         auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
    1642              : 
    1643              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1644            1 :         Real64 constexpr CpWater(4210.0);         // Specific heat of water J/kg_C
    1645            1 :         Real64 constexpr DegreeofSuperheat(80.0); // Initial guess of degree of superheat
    1646            1 :         Real64 constexpr gamma(1.114);            // Expnasion Coefficient
    1647            1 :         Real64 RelaxParam(0.5);                   // Relaxation Parameter
    1648            1 :         Real64 constexpr ERR(0.01);               // Error Value
    1649            1 :         int constexpr STOP1(1000);                // Iteration stopper1
    1650            1 :         int constexpr STOP2(1000);                // Iteration stopper2
    1651            1 :         int constexpr STOP3(1000);                // Iteration stopper3
    1652              : 
    1653              :         static constexpr std::string_view RoutineNameSourceSideInletTemp("CalcWatertoAirHPHeating:SourceSideInletTemp");
    1654              :         static constexpr std::string_view RoutineNameSourceSideTemp("CalcWatertoAirHPHeating:SourceSideTemp");
    1655              :         static constexpr std::string_view RoutineNameLoadSideTemp("CalcWatertoAirHPHeating:LoadSideTemp");
    1656              :         static constexpr std::string_view RoutineNameLoadSideOutletEnthalpy("CalcWatertoAirHPHeating:LoadSideOutletEnthalpy");
    1657              :         static constexpr std::string_view RoutineNameCompressInletTemp("CalcWatertoAirHPHeating:CompressInletTemp");
    1658              :         static constexpr std::string_view RoutineNameSuctionPr("CalcWatertoAirHPHeating:SuctionPr");
    1659              :         static constexpr std::string_view RoutineNameCompSuctionTemp("CalcWatertoAirHPHeating:CompSuctionTemp");
    1660              : 
    1661              :         int NumIteration3; // Number of Iteration3
    1662              :         Real64 Quality;
    1663              :         Real64 SourceSideOutletTemp;  // Source Side Outlet Temperature [C]
    1664              :         Real64 SourceSideVolFlowRate; // Source Side Volumetric Flow Rate [m3/s]
    1665              :         Real64 CpFluid;               // Specific heat of source side fluid(J/kg)
    1666              :         Real64 LoadSideOutletDBTemp;  // Load Side Outlet Dry Bulb Temperature [C]
    1667              :         Real64 LoadSideOutletHumRat;  // Load Side Outlet Humidity Ratio [kg/kg]
    1668              :         Real64 LoadSideAirOutletEnth; // Load Side Outlet Enthalpy [J/kg]
    1669              :         Real64 CpAir;                 // Specific Heat of Air [J/kg_C]
    1670              :         Real64 DegradFactor;          // Degradation Factor [~]
    1671              :         Real64 QSource;               // Source Side Heat Transfer Rate [W]
    1672              :         Real64 QLoadTotal;            // Load Side Heat Transfer Rate [W]
    1673              :         Real64 Power;                 // Power Consumption [W]
    1674              : 
    1675              :         Real64 SourceSideEffect;     // Source Side Heat Exchanger Effectiveness
    1676              :         Real64 SourceSideTemp;       // Source Side Saturated Refrigerant Temperature [C]
    1677              :         Real64 LoadSideTemp;         // Load Side Saturated Refrigerant Temperature [C]
    1678              :         Real64 SourceSidePressure;   // Source Side Saturated Refrigerant Pressure [Pa]
    1679              :         Real64 LoadSidePressure;     // Load Side Saturated Refrigerant Pressure [Pa]
    1680              :         Real64 SuctionPr;            // Compressor Suction Pressure [Pa]
    1681              :         Real64 DischargePr;          // Compressor Discharge Pressure [Pa]
    1682              :         Real64 CompressInletTemp;    // Temperature of the Refrigerant Entering the Compressor [C]
    1683              :         Real64 MassRef;              // Mass Flow Rate of Refrigerant [kg/s]
    1684              :         Real64 SourceSideOutletEnth; // Enthalpy of Refrigerant leaving the Source Side Heat Exchanger [J/kg]
    1685              :         Real64 LoadSideOutletEnth;   // Enthalpy of Refrigerant leaving the Load Side Heat Exchanger [J/kg]
    1686              :         Real64 SuperHeatEnth;        // Enthalpy of the Superheated Refrigerant [J/kg]
    1687              :         Real64 CompSuctionTemp1;     // Guess of the Temperature of the Refrigerant Entering the
    1688              :         // Compressor #1 [C]
    1689              :         Real64 CompSuctionTemp2; // Guess of the Temperature of the Refrigerant Entering the
    1690              :         // Compressor #2 [C]
    1691              :         Real64 CompSuctionTemp;    // Temperature of the Refrigerant Entering the Compressor [C]
    1692              :         Real64 CompSuctionEnth;    // Enthalpy of the Refrigerant Entering the Compressor [J/kg]
    1693              :         Real64 CompSuctionDensity; // Density of the Refrigerant Entering the Compressorkg/m3
    1694              :         Real64 CompSuctionSatTemp; // Temperature of Saturated Refrigerant at Compressor Suction Pressure [C]
    1695              :         bool StillSimulatingFlag;  // Final Simulation Flag
    1696              :         bool Converged;            // Overall convergence Flag
    1697              :         int SolFlag;               // Solution flag returned from RegulaFalsi function
    1698              :         Real64 LoadResidual;       // loop convergence criteria
    1699              :         Real64 SourceResidual;     // loop convergence criteria
    1700              : 
    1701              :         //  LOAD LOCAL VARIABLES FROM DATA STRUCTURE (for code readability)
    1702              : 
    1703            1 :         CpAir = Psychrometrics::PsyCpAirFnW(heatPump.InletAirHumRat);
    1704            1 :         SourceSideVolFlowRate =
    1705            1 :             heatPump.InletWaterMassFlowRate /
    1706            1 :             state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).glycol->getDensity(state, heatPump.InletWaterTemp, RoutineNameSourceSideInletTemp);
    1707              : 
    1708              :         // If heat pump is not operating, return
    1709            1 :         if (SensDemand == 0.0 || heatPump.InletAirMassFlowRate <= 0.0 || heatPump.InletWaterMassFlowRate <= 0.0) {
    1710            0 :             heatPump.SimFlag = false;
    1711            0 :             return;
    1712              :         } else {
    1713            1 :             heatPump.SimFlag = true;
    1714              :         }
    1715              : 
    1716            1 :         if (compressorOp == HVAC::CompressorOp::Off) {
    1717            0 :             heatPump.SimFlag = false;
    1718            0 :             return;
    1719              :         }
    1720              : 
    1721            1 :         if (FirstHVACIteration) {
    1722            1 :             state.dataWaterToAirHeatPump->initialQLoad = heatPump.HeatingCapacity;
    1723            1 :             state.dataWaterToAirHeatPump->initialQSource = heatPump.HeatingCapacity;
    1724              :         }
    1725              : 
    1726            1 :         if (state.dataWaterToAirHeatPump->initialQLoad == 0.0) state.dataWaterToAirHeatPump->initialQLoad = heatPump.HeatingCapacity;
    1727            1 :         if (state.dataWaterToAirHeatPump->initialQSource == 0.0) state.dataWaterToAirHeatPump->initialQSource = heatPump.HeatingCapacity;
    1728              : 
    1729              :         // Tuned Hoisted quantities out of nested loop that don't change
    1730            1 :         Real64 const LoadSideMassFlowRate_CpAir_inv(1.0 / (heatPump.InletAirMassFlowRate * CpAir));
    1731              :         Real64 const LoadSideEffect(1.0 -
    1732            1 :                                     std::exp(-heatPump.LoadSideTotalUACoeff *
    1733            1 :                                              LoadSideMassFlowRate_CpAir_inv)); // Load Side Effectiveness based on Outside Heat Transfer Coefficient
    1734            1 :         Real64 const LoadSideEffect_CpAir_MassFlowRate_inv(1.0 / (LoadSideEffect * CpAir * heatPump.InletAirMassFlowRate));
    1735              : 
    1736              :         // Outerloop: calculate load side heat transfer
    1737            1 :         NumIteration3 = 0;
    1738            1 :         Converged = false;
    1739            1 :         StillSimulatingFlag = true;
    1740            1 :         LoadResidual = 1.0;
    1741           18 :         while (StillSimulatingFlag) {
    1742           17 :             if (Converged) StillSimulatingFlag = false;
    1743              : 
    1744           17 :             ++NumIteration3;
    1745           17 :             if (NumIteration3 == 1) RelaxParam = 0.5;
    1746              : 
    1747           17 :             if (NumIteration3 > STOP3) {
    1748            0 :                 heatPump.SimFlag = false;
    1749            0 :                 return;
    1750              :             }
    1751              : 
    1752              :             // Innerloop: calculate load side heat transfer
    1753           17 :             int NumIteration2 = 0;
    1754           17 :             SourceResidual = 1.0;
    1755           64 :             while (SourceResidual > ERR) {
    1756              : 
    1757           47 :                 ++NumIteration2;
    1758              : 
    1759           47 :                 if (NumIteration2 > STOP2) {
    1760            0 :                     heatPump.SimFlag = false;
    1761            0 :                     return;
    1762              :                 }
    1763              : 
    1764              :                 // Determine Effectiveness of Source Side
    1765           47 :                 CpFluid = state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum)
    1766           47 :                               .glycol->getSpecificHeat(state, heatPump.InletWaterTemp, RoutineNameSourceSideInletTemp);
    1767              : 
    1768           47 :                 if (state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).glycol->Num == Fluid::GlycolNum_Water) {
    1769           47 :                     SourceSideEffect = 1.0 - std::exp(-heatPump.SourceSideUACoeff / (CpFluid * heatPump.InletWaterMassFlowRate));
    1770              :                 } else {
    1771            0 :                     DegradFactor = DegradF(state, state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).glycol, heatPump.InletWaterTemp);
    1772            0 :                     SourceSideEffect =
    1773            0 :                         1.0 / ((heatPump.SourceSideHTR1 * std::pow(SourceSideVolFlowRate, -0.8)) / DegradFactor + heatPump.SourceSideHTR2);
    1774              :                 }
    1775              : 
    1776              :                 // Determine Source Side Tempertaure (Evap. Temp for this mode)
    1777           94 :                 SourceSideTemp = heatPump.InletWaterTemp -
    1778           47 :                                  state.dataWaterToAirHeatPump->initialQSource / (SourceSideEffect * CpFluid * heatPump.InletWaterMassFlowRate);
    1779              : 
    1780              :                 // Determine Load Side Tempertaure (Condensing Temp for this mode)
    1781           47 :                 LoadSideTemp = heatPump.InletAirDBTemp + state.dataWaterToAirHeatPump->initialQLoad * LoadSideEffect_CpAir_MassFlowRate_inv;
    1782              : 
    1783              :                 // Determine the Load Side and Source Side Saturated Temp (evaporating and condensing pressures)
    1784           47 :                 SourceSidePressure = heatPump.refrig->getSatPressure(state, SourceSideTemp, RoutineNameSourceSideTemp);
    1785           47 :                 LoadSidePressure = heatPump.refrig->getSatPressure(state, LoadSideTemp, RoutineNameLoadSideTemp);
    1786           47 :                 if (SourceSidePressure < heatPump.LowPressCutoff && !FirstHVACIteration) {
    1787            0 :                     if (!state.dataGlobal->WarmupFlag) {
    1788            0 :                         ShowRecurringWarningErrorAtEnd(
    1789              :                             state,
    1790            0 :                             format("WaterToAir Heat pump:heating [{}] shut off on low pressure < {:.0R}", heatPump.Name, heatPump.LowPressCutoff),
    1791            0 :                             heatPump.LowPressHtgError,
    1792              :                             SourceSidePressure,
    1793              :                             SourceSidePressure,
    1794              :                             _,
    1795              :                             "[Pa]",
    1796              :                             "[Pa]");
    1797              :                     }
    1798            0 :                     heatPump.SimFlag = false;
    1799            0 :                     return;
    1800              :                 }
    1801              : 
    1802           47 :                 if (LoadSidePressure > heatPump.HighPressCutoff && !FirstHVACIteration) {
    1803            0 :                     if (!state.dataGlobal->WarmupFlag) {
    1804            0 :                         ShowRecurringWarningErrorAtEnd(
    1805              :                             state,
    1806            0 :                             format("WaterToAir Heat pump:heating [{}] shut off on high pressure > {:.0R}", heatPump.Name, heatPump.HighPressCutoff),
    1807            0 :                             heatPump.HighPressHtgError,
    1808            0 :                             heatPump.InletWaterTemp,
    1809            0 :                             heatPump.InletWaterTemp,
    1810              :                             _,
    1811              :                             "SourceSideInletTemp[C]",
    1812              :                             "SourceSideInletTemp[C]");
    1813              :                     }
    1814              :                     //         CALL ShowWarningError(state, 'Heat pump:heating shut off on high pressure')
    1815              :                     //         WRITE(CErrCount,*) SourceSideInletTemp
    1816              :                     //         CErrCount=ADJUSTL(CErrCount)
    1817              :                     //         CALL ShowContinueError(state, 'Source side inlet temperature too low, T='//TRIM(CErrCount))
    1818              :                     //         CALL ShowContinueError(state, 'Heat pump heating demand not met by plant side')
    1819            0 :                     heatPump.SimFlag = false;
    1820            0 :                     return;
    1821              :                 }
    1822              : 
    1823              :                 // Determine Suction Pressure at Compressor Entrance & Discharge Pressure at Compressor Exit
    1824           47 :                 switch (heatPump.compressorType) {
    1825            0 :                 case CompressorType::Reciprocating: {
    1826            0 :                     SuctionPr = SourceSidePressure - heatPump.CompSucPressDrop;
    1827            0 :                     DischargePr = LoadSidePressure + heatPump.CompSucPressDrop;
    1828            0 :                     break;
    1829              :                 }
    1830            0 :                 case CompressorType::Rotary: {
    1831            0 :                     SuctionPr = SourceSidePressure;
    1832            0 :                     DischargePr = LoadSidePressure + heatPump.CompSucPressDrop;
    1833            0 :                     break;
    1834              :                 }
    1835           47 :                 case CompressorType::Scroll: {
    1836           47 :                     SuctionPr = SourceSidePressure;
    1837           47 :                     DischargePr = LoadSidePressure;
    1838           47 :                     break;
    1839              :                 }
    1840            0 :                 default:
    1841            0 :                     break;
    1842              :                 }
    1843              : 
    1844              :                 // Determine the Source Side Outlet Enthalpy
    1845              :                 // Quality of the refrigerant leaving the evaporator is saturated gas
    1846           47 :                 Quality = 1.0;
    1847           47 :                 SourceSideOutletEnth = heatPump.refrig->getSatEnthalpy(state, SourceSideTemp, Quality, RoutineNameSourceSideTemp);
    1848              : 
    1849              :                 // Determine Load Side Outlet Enthalpy
    1850              :                 // Quality of the refrigerant leaving the condenser is saturated liguid
    1851           47 :                 Quality = 0.0;
    1852           47 :                 LoadSideOutletEnth = heatPump.refrig->getSatEnthalpy(state, LoadSideTemp, Quality, RoutineNameLoadSideTemp);
    1853              : 
    1854              :                 // Determine Superheated Temperature of the Source Side outlet/compressor Inlet
    1855           47 :                 CompressInletTemp = SourceSideTemp + heatPump.SuperheatTemp;
    1856              : 
    1857              :                 // Determine the Enathalpy of the Superheated Fluid at Source Side Outlet/Compressor Inlet
    1858           47 :                 SuperHeatEnth = heatPump.refrig->getSupHeatEnthalpy(state, CompressInletTemp, SourceSidePressure, RoutineNameCompressInletTemp);
    1859              : 
    1860              :                 // Determining the suction state of the fluid from inlet state involves interation
    1861              :                 // Method employed...
    1862              :                 // Determine the saturated temp at suction pressure, shoot out into the superheated region find the enthalpy
    1863              :                 // check that with the inlet enthalpy ( as suction loss is isenthalpic). Iterate till desired accuracy is reached
    1864              : 
    1865           47 :                 if (!Converged) {
    1866           46 :                     CompSuctionSatTemp = heatPump.refrig->getSatTemperature(state, SuctionPr, RoutineNameSuctionPr);
    1867           46 :                     CompSuctionTemp1 = CompSuctionSatTemp;
    1868              : 
    1869              :                     // Shoot into the Superheated Region
    1870           46 :                     CompSuctionTemp2 = CompSuctionSatTemp + DegreeofSuperheat;
    1871              :                 }
    1872              : 
    1873          141 :                 auto f = [&state, &heatPump, SuctionPr, SuperHeatEnth](Real64 const CompSuctionTemp) {
    1874              :                     static constexpr std::string_view RoutineName("CalcWaterToAirHPHeating:CalcCompSuctionTemp");
    1875          141 :                     Real64 compSuctionEnth = heatPump.refrig->getSupHeatEnthalpy(state, CompSuctionTemp, SuctionPr, RoutineName);
    1876          141 :                     return (compSuctionEnth - SuperHeatEnth) / SuperHeatEnth;
    1877           47 :                 };
    1878              : 
    1879           47 :                 General::SolveRoot(state, ERR, STOP1, SolFlag, CompSuctionTemp, f, CompSuctionTemp1, CompSuctionTemp2);
    1880           47 :                 if (SolFlag == -1) {
    1881            0 :                     heatPump.SimFlag = false;
    1882            0 :                     return;
    1883              :                 }
    1884           47 :                 CompSuctionEnth = heatPump.refrig->getSupHeatEnthalpy(state, CompSuctionTemp, SuctionPr, RoutineNameCompSuctionTemp);
    1885           47 :                 CompSuctionDensity = heatPump.refrig->getSupHeatDensity(state, CompSuctionTemp, SuctionPr, RoutineNameCompSuctionTemp);
    1886              : 
    1887              :                 // Find Refrigerant Flow Rate
    1888           47 :                 switch (heatPump.compressorType) {
    1889            0 :                 case CompressorType::Reciprocating: {
    1890            0 :                     MassRef = heatPump.CompPistonDisp * CompSuctionDensity *
    1891            0 :                               (1 + heatPump.CompClearanceFactor - heatPump.CompClearanceFactor * std::pow(DischargePr / SuctionPr, 1 / gamma));
    1892            0 :                     break;
    1893              :                 }
    1894            0 :                 case CompressorType::Rotary: {
    1895            0 :                     MassRef = heatPump.CompPistonDisp * CompSuctionDensity;
    1896            0 :                     break;
    1897              :                 }
    1898           47 :                 case CompressorType::Scroll: {
    1899           47 :                     MassRef = heatPump.RefVolFlowRate * CompSuctionDensity - heatPump.LeakRateCoeff * (DischargePr / SuctionPr);
    1900           47 :                     break;
    1901              :                 }
    1902            0 :                 default:
    1903            0 :                     break;
    1904              :                 }
    1905           47 :                 MassRef = max(0.0, MassRef);
    1906              : 
    1907              :                 // Find the Source Side Heat Transfer
    1908           47 :                 QSource = MassRef * (SourceSideOutletEnth - LoadSideOutletEnth);
    1909           47 :                 SourceResidual = std::abs(QSource - state.dataWaterToAirHeatPump->initialQSource) / state.dataWaterToAirHeatPump->initialQSource;
    1910           47 :                 state.dataWaterToAirHeatPump->initialQSource += RelaxParam * (QSource - state.dataWaterToAirHeatPump->initialQSource);
    1911           47 :                 if (NumIteration2 > 8) RelaxParam = 0.3;
    1912              :             }
    1913              : 
    1914              :             // Determine the Power Consumption
    1915           17 :             switch (heatPump.compressorType) {
    1916            0 :             case CompressorType::Reciprocating:
    1917              :             case CompressorType::Rotary: {
    1918            0 :                 Power = heatPump.PowerLosses + (1 / heatPump.LossFactor) * (MassRef * gamma / (gamma - 1) * SuctionPr / CompSuctionDensity *
    1919            0 :                                                                             (std::pow(DischargePr / SuctionPr, (gamma - 1) / gamma) - 1));
    1920            0 :                 break;
    1921              :             }
    1922           17 :             case CompressorType::Scroll: {
    1923           17 :                 Power = heatPump.PowerLosses + (1 / heatPump.LossFactor) * (gamma / (gamma - 1)) * SuctionPr * heatPump.RefVolFlowRate *
    1924           17 :                                                    (((gamma - 1) / gamma) * ((DischargePr / SuctionPr) / heatPump.VolumeRatio) +
    1925           17 :                                                     ((1 / gamma) * std::pow(heatPump.VolumeRatio, gamma - 1)) - 1);
    1926           17 :                 break;
    1927              :             }
    1928            0 :             default:
    1929            0 :                 break;
    1930              :             }
    1931              : 
    1932              :             // Determine the Load Side Heat Rate
    1933           17 :             QLoadTotal = Power + QSource;
    1934           17 :             LoadResidual = std::abs(QLoadTotal - state.dataWaterToAirHeatPump->initialQLoad) / state.dataWaterToAirHeatPump->initialQLoad;
    1935           17 :             if (LoadResidual < ERR) Converged = true;
    1936           17 :             state.dataWaterToAirHeatPump->initialQLoad += RelaxParam * (QLoadTotal - state.dataWaterToAirHeatPump->initialQLoad);
    1937           17 :             if (NumIteration3 > 8) RelaxParam = 0.2;
    1938              :         }
    1939              : 
    1940            1 :         if (SuctionPr < heatPump.LowPressCutoff && !FirstHVACIteration) {
    1941            0 :             ShowWarningError(state, "Heat pump:heating shut down on low pressure");
    1942            0 :             heatPump.SimFlag = false;
    1943            0 :             return;
    1944              :         }
    1945              : 
    1946            1 :         if (DischargePr > heatPump.HighPressCutoff && !FirstHVACIteration) {
    1947            0 :             ShowWarningError(state, "Heat pump:heating shut down on high pressure");
    1948            0 :             heatPump.SimFlag = false;
    1949            0 :             return;
    1950              :         }
    1951              : 
    1952              :         // calculate coil outlet state variables
    1953            1 :         LoadSideAirOutletEnth = heatPump.InletAirEnthalpy + QLoadTotal / heatPump.InletAirMassFlowRate;
    1954            1 :         LoadSideOutletDBTemp = heatPump.InletAirDBTemp + QLoadTotal / (heatPump.InletAirMassFlowRate * CpAir);
    1955            1 :         LoadSideOutletHumRat = Psychrometrics::PsyWFnTdbH(state, LoadSideOutletDBTemp, LoadSideAirOutletEnth, RoutineNameLoadSideOutletEnthalpy);
    1956            1 :         SourceSideOutletTemp = heatPump.InletWaterTemp - QSource / (heatPump.InletWaterMassFlowRate * CpWater);
    1957              : 
    1958              :         // Calculate actual outlet conditions for the run time fraction
    1959              :         // Actual outlet conditions are "average" for time step
    1960            1 :         if (fanOp == HVAC::FanOp::Continuous) {
    1961              :             // continuous fan, cycling compressor
    1962            0 :             heatPump.OutletAirEnthalpy = PartLoadRatio * LoadSideAirOutletEnth + (1.0 - PartLoadRatio) * heatPump.InletAirEnthalpy;
    1963            0 :             heatPump.OutletAirHumRat = PartLoadRatio * LoadSideOutletHumRat + (1.0 - PartLoadRatio) * heatPump.InletAirHumRat;
    1964            0 :             heatPump.OutletAirDBTemp = Psychrometrics::PsyTdbFnHW(heatPump.OutletAirEnthalpy, heatPump.OutletAirHumRat);
    1965              :         } else {
    1966              :             // default to cycling fan, cycling compressor
    1967            1 :             heatPump.OutletAirEnthalpy = LoadSideAirOutletEnth;
    1968            1 :             heatPump.OutletAirHumRat = LoadSideOutletHumRat;
    1969            1 :             heatPump.OutletAirDBTemp = LoadSideOutletDBTemp;
    1970              :         }
    1971              : 
    1972              :         // Calculate Part Load Factor and Runtime Fraction
    1973            1 :         Real64 PLF = 1.0; // part load factor as a function of PLR, RTF = PLR / PLF
    1974            1 :         if (heatPump.PLFCurveIndex > 0) {
    1975            1 :             PLF = Curve::CurveValue(state, heatPump.PLFCurveIndex, PartLoadRatio); // Calculate part-load factor
    1976              :         }
    1977            1 :         if (fanOp == HVAC::FanOp::Cycling) {
    1978            1 :             state.dataHVACGlobal->OnOffFanPartLoadFraction = PLF;
    1979              :         }
    1980            1 :         heatPump.RunFrac = PartLoadRatio / PLF;
    1981              : 
    1982              :         // scale heat transfer rates and power to run time
    1983            1 :         QLoadTotal *= PartLoadRatio;
    1984            1 :         Power *= heatPump.RunFrac;
    1985            1 :         QSource *= PartLoadRatio;
    1986              : 
    1987              :         // Update heat pump data structure
    1988            1 :         state.dataHVACGlobal->DXElecHeatingPower = Power;
    1989            1 :         heatPump.Power = Power;
    1990            1 :         heatPump.QLoadTotal = QLoadTotal;
    1991            1 :         heatPump.QSensible = QLoadTotal;
    1992              : 
    1993            1 :         heatPump.QSource = QSource;
    1994            1 :         heatPump.PartLoadRatio = PartLoadRatio;
    1995            1 :         heatPump.OutletAirMassFlowRate = heatPump.InletAirMassFlowRate;
    1996            1 :         heatPump.OutletWaterTemp = SourceSideOutletTemp;
    1997            1 :         heatPump.OutletWaterMassFlowRate = heatPump.InletWaterMassFlowRate;
    1998            1 :         heatPump.OutletWaterEnthalpy = heatPump.InletWaterEnthalpy - QSource / heatPump.InletWaterMassFlowRate;
    1999              :     }
    2000              : 
    2001            0 :     void UpdateWatertoAirHP(EnergyPlusData &state, int const HPNum)
    2002              :     {
    2003              :         // SUBROUTINE INFORMATION:
    2004              :         //       AUTHOR         Hui Jin
    2005              :         //       DATE WRITTEN   Oct 2000
    2006              : 
    2007              :         // PURPOSE OF THIS SUBROUTINE:
    2008              :         // This subroutine updates the Water to Air Heat Pump outlet nodes.
    2009              : 
    2010              :         // METHODOLOGY EMPLOYED:
    2011              :         // Data is moved from the HP data structure to the HP outlet nodes.
    2012              : 
    2013              :         // Using/Aliasing
    2014            0 :         Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    2015            0 :         auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
    2016              : 
    2017              :         // WatertoAirHP(HPNum)%SimFlag=.FALSE.
    2018            0 :         if (!heatPump.SimFlag) {
    2019              :             // Heatpump is off; just pass through conditions
    2020            0 :             heatPump.Power = 0.0;
    2021            0 :             heatPump.Energy = 0.0;
    2022            0 :             heatPump.QLoadTotal = 0.0;
    2023            0 :             heatPump.QSensible = 0.0;
    2024            0 :             heatPump.QLatent = 0.0;
    2025            0 :             heatPump.QSource = 0.0;
    2026            0 :             heatPump.RunFrac = 0.0;
    2027            0 :             heatPump.PartLoadRatio = 0.0;
    2028            0 :             heatPump.OutletAirDBTemp = heatPump.InletAirDBTemp;
    2029            0 :             heatPump.OutletAirHumRat = heatPump.InletAirHumRat;
    2030            0 :             heatPump.OutletWaterTemp = heatPump.InletWaterTemp;
    2031            0 :             heatPump.OutletAirMassFlowRate = heatPump.InletAirMassFlowRate;
    2032            0 :             heatPump.OutletWaterMassFlowRate = heatPump.InletWaterMassFlowRate;
    2033            0 :             heatPump.OutletAirEnthalpy = heatPump.InletAirEnthalpy;
    2034            0 :             heatPump.OutletWaterEnthalpy = heatPump.InletWaterEnthalpy;
    2035              :         }
    2036              : 
    2037              :         // Set the outlet air nodes of the WatertoAirHP
    2038            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRate;
    2039            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).Temp = heatPump.OutletAirDBTemp;
    2040            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).HumRat = heatPump.OutletAirHumRat;
    2041            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).Enthalpy = heatPump.OutletAirEnthalpy;
    2042              : 
    2043              :         // Set the outlet nodes for properties that just pass through & not used
    2044            0 :         PlantUtilities::SafeCopyPlantNode(state, heatPump.WaterInletNodeNum, heatPump.WaterOutletNodeNum);
    2045              :         // Set the outlet water nodes for the heat pump
    2046            0 :         state.dataLoopNodes->Node(heatPump.WaterOutletNodeNum).Temp = heatPump.OutletWaterTemp;
    2047            0 :         state.dataLoopNodes->Node(heatPump.WaterOutletNodeNum).Enthalpy = heatPump.OutletWaterEnthalpy;
    2048              : 
    2049              :         // Set the outlet nodes for properties that just pass through & not used
    2050            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).Quality = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).Quality;
    2051            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).Press = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).Press;
    2052            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRateMin = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRateMin;
    2053            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRateMax;
    2054            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRateMinAvail =
    2055            0 :             state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRateMinAvail;
    2056            0 :         state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRateMaxAvail =
    2057            0 :             state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRateMaxAvail;
    2058              : 
    2059              :         // Pass through the load side mass flow rates
    2060            0 :         heatPump.InletAirMassFlowRate = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRate;
    2061            0 :         heatPump.OutletAirMassFlowRate = heatPump.InletAirMassFlowRate;
    2062              : 
    2063            0 :         heatPump.Energy = heatPump.Power * TimeStepSysSec;
    2064            0 :         heatPump.EnergyLoadTotal = heatPump.QLoadTotal * TimeStepSysSec;
    2065            0 :         heatPump.EnergySensible = heatPump.QSensible * TimeStepSysSec;
    2066            0 :         heatPump.EnergyLatent = heatPump.QLatent * TimeStepSysSec;
    2067            0 :         heatPump.EnergySource = heatPump.QSource * TimeStepSysSec;
    2068              : 
    2069            0 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2070            0 :             state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).CO2 = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).CO2;
    2071              :         }
    2072            0 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2073            0 :             state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).GenContam = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).GenContam;
    2074              :         }
    2075            0 :     }
    2076              : 
    2077              :     //        End of Update subroutines for the WatertoAirHP Module
    2078              :     // *****************************************************************************
    2079              : 
    2080            0 :     Real64 CalcEffectiveSHR(EnergyPlusData &state,
    2081              :                             int const HPNum,         // Index number for cooling coil
    2082              :                             Real64 const SHRss,      // Steady-state sensible heat ratio
    2083              :                             HVAC::FanOp const fanOp, // fan/compressor cycling scheme indicator
    2084              :                             Real64 const RTF,        // Compressor run-time fraction
    2085              :                             Real64 const QLatRated,  // Rated latent capacity
    2086              :                             Real64 const QLatActual, // Actual latent capacity
    2087              :                             Real64 const EnteringDB, // Entering air dry-bulb temperature
    2088              :                             Real64 const EnteringWB  // Entering air wet-bulb temperature
    2089              :     )
    2090              :     {
    2091              : 
    2092              :         // FUNCTION INFORMATION:
    2093              :         //    AUTHOR         Richard Raustad, FSEC
    2094              :         //    DATE WRITTEN   September 2003
    2095              :         //    MODIFIED       Kenneth Tang (Aug 2004) Added capability for simulating FanOp::Cycling
    2096              : 
    2097              :         // PURPOSE OF THIS FUNCTION:
    2098              :         //    Adjust sensible heat ratio to account for degradation of DX coil latent
    2099              :         //    capacity at part-load (cycling) conditions.
    2100              : 
    2101              :         // METHODOLOGY EMPLOYED:
    2102              :         //    With model parameters entered by the user, the part-load latent performance
    2103              :         //    of a DX cooling coil is determined for a constant air flow system with
    2104              :         //    a cooling coil that cycles on/off. The model calculates the time
    2105              :         //    required for condensate to begin falling from the cooling coil.
    2106              :         //    Runtimes greater than this are integrated to a "part-load" latent
    2107              :         //    capacity which is used to determine the "part-load" sensible heat ratio.
    2108              :         //    See reference below for additional details (linear decay model, Eq. 8b).
    2109              :         // REFERENCES:
    2110              :         //   "A Model to Predict the Latent Capacity of Air Conditioners and
    2111              :         //    Heat Pumps at Part-Load Conditions with Constant Fan Operation"
    2112              :         //    1996 ASHRAE Transactions, Volume 102, Part 1, Pp. 266 - 274,
    2113              :         //    Hugh I. Henderson, Jr., P.E., Kannan Rengarajan, P.E.
    2114              : 
    2115              :         // Using/Aliasing
    2116            0 :         auto const &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
    2117              : 
    2118              :         // Return value
    2119              :         Real64 SHReff; // Effective sensible heat ratio, includes degradation due to cycling effects
    2120              : 
    2121              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2122              :         Real64 Twet; // Nominal time for condensate to begin leaving the coil's condensate drain line
    2123              :         //   at the current operating conditions (sec)
    2124              :         Real64 Gamma; // Initial moisture evaporation rate divided by steady-state AC latent capacity
    2125              :         //   at the current operating conditions
    2126              :         Real64 Twet_max; // Maximum allowed value for Twet
    2127              :         // shut off after compressor cycle off  [s]
    2128              : 
    2129              :         Real64 Ton;     // Coil on time (sec)
    2130              :         Real64 Toff;    // Coil off time (sec)
    2131              :         Real64 Toffa;   // Actual coil off time (sec). Equations valid for Toff <= (2.0 * Twet/Gamma)
    2132              :         Real64 aa;      // Intermediate variable
    2133              :         Real64 To1;     // Intermediate variable (first guess at To). To = time to the start of moisture removal
    2134              :         Real64 To2;     // Intermediate variable (second guess at To). To = time to the start of moisture removal
    2135              :         Real64 Error;   // Error for iteration (DO) loop
    2136              :         Real64 LHRmult; // Latent Heat Ratio (LHR) multiplier. The effective latent heat ratio LHR = (1-SHRss)*LHRmult
    2137              : 
    2138              :         //  No moisture evaporation (latent degradation) occurs for runtime fraction of 1.0
    2139              :         //  All latent degradation model parameters cause divide by 0.0 if not greater than 0.0
    2140              :         //  Latent degradation model parameters initialize to 0.0 meaning no evaporation model used.
    2141            0 :         if ((RTF >= 1.0) || (QLatRated == 0.0) || (QLatActual == 0.0) || (heatPump.Twet_Rated <= 0.0) || (heatPump.Gamma_Rated <= 0.0) ||
    2142            0 :             (heatPump.MaxONOFFCyclesperHour <= 0.0) || (heatPump.LatentCapacityTimeConstant <= 0.0) || (RTF <= 0.0)) {
    2143            0 :             SHReff = SHRss;
    2144            0 :             return SHReff;
    2145              :         }
    2146              : 
    2147            0 :         Twet_max = 9999.0; // high limit for Twet
    2148              : 
    2149              :         //  Calculate the model parameters at the actual operating conditions
    2150            0 :         Twet = min(heatPump.Twet_Rated * QLatRated / (QLatActual + 1.e-10), Twet_max);
    2151            0 :         Gamma = heatPump.Gamma_Rated * QLatRated * (EnteringDB - EnteringWB) / ((26.7 - 19.4) * QLatActual + 1.e-10);
    2152              : 
    2153              :         //  Calculate the compressor on and off times using a conventional thermostat curve
    2154            0 :         Ton = 3600.0 / (4.0 * heatPump.MaxONOFFCyclesperHour * (1.0 - RTF)); // duration of cooling coil on-cycle (sec)
    2155              : 
    2156            0 :         if ((fanOp == HVAC::FanOp::Cycling) && (heatPump.FanDelayTime != 0.0)) {
    2157              :             //  For FanOp::Cycling, moisture is evaporated from the cooling coil back to the air stream
    2158              :             //  until the fan cycle off. Assume no evaporation from the coil after the fan shuts off.
    2159            0 :             Toff = heatPump.FanDelayTime;
    2160              :         } else {
    2161              :             //  For FanOp::Continuous, moisture is evaporated from the cooling coil back to the air stream
    2162              :             //  for the entire heat pump off-cycle.
    2163            0 :             Toff = 3600.0 / (4.0 * heatPump.MaxONOFFCyclesperHour * RTF); // duration of cooling coil off-cycle (sec)
    2164              :         }
    2165              : 
    2166              :         //  Cap Toff to meet the equation restriction
    2167            0 :         if (Gamma > 0.0) {
    2168            0 :             Toffa = min(Toff, 2.0 * Twet / Gamma);
    2169              :         } else {
    2170            0 :             Toffa = Toff;
    2171              :         }
    2172              : 
    2173              :         //  Use sucessive substitution to solve for To
    2174            0 :         aa = (Gamma * Toffa) - (0.25 / Twet) * pow_2(Gamma) * pow_2(Toffa);
    2175              : 
    2176            0 :         To1 = aa + heatPump.LatentCapacityTimeConstant;
    2177            0 :         Error = 1.0;
    2178            0 :         while (Error > 0.001) {
    2179            0 :             To2 = aa - heatPump.LatentCapacityTimeConstant * std::expm1(-To1 / heatPump.LatentCapacityTimeConstant);
    2180            0 :             Error = std::abs((To2 - To1) / To1);
    2181            0 :             To1 = To2;
    2182              :         }
    2183              : 
    2184              :         //  Adjust Sensible Heat Ratio (SHR) using Latent Heat Ratio (LHR) multiplier
    2185              :         //  Floating underflow errors occur when -Ton/LatentCapacityTimeConstant is a large negative number.
    2186              :         //  Cap lower limit at -700 to avoid the underflow errors.
    2187            0 :         aa = std::exp(max(-700.0, -Ton / heatPump.LatentCapacityTimeConstant));
    2188              :         //  Calculate latent heat ratio multiplier
    2189            0 :         LHRmult = max(((Ton - To2) / (Ton + heatPump.LatentCapacityTimeConstant * (aa - 1.0))), 0.0);
    2190              : 
    2191              :         //  Calculate part-load or "effective" sensible heat ratio
    2192            0 :         SHReff = 1.0 - (1.0 - SHRss) * LHRmult;
    2193              : 
    2194            0 :         if (SHReff < SHRss) SHReff = SHRss; // Effective SHR can be less than the steady-state SHR
    2195            0 :         if (SHReff > 1.0) SHReff = 1.0;     // Effective sensible heat ratio can't be greater than 1.0
    2196              : 
    2197            0 :         return SHReff;
    2198              :     }
    2199              : 
    2200            0 :     Real64 DegradF(EnergyPlusData &state,
    2201              :                    Fluid::GlycolProps *glycol,
    2202              :                    Real64 &Temp // Temperature of the fluid
    2203              :     )
    2204              :     {
    2205              :         // FUNCTION INFORMATION:
    2206              :         //    AUTHOR         Kenneth Tang
    2207              :         //    DATE WRITTEN   October 2004
    2208              : 
    2209              :         // PURPOSE OF THIS FUNCTION:
    2210              :         //    Calculate the degradation factor to predict the heat pump performance
    2211              :         //    when antifreeze is used.
    2212              :         // METHODOLOGY EMPLOYED:
    2213              :         //    Use FluidProperties to calculate the properties of water and glycol
    2214              :         //    at the given temperature. Then substitute the properties into the equation.
    2215              :         // REFERENCES:
    2216              :         //    Jin, H. 2002. Parameter Estimation Based Models of Water Source Heat Pumps. Phd Thesis.
    2217              :         //    Oklahoma State University.
    2218              : 
    2219              :         // Return value
    2220              :         Real64 DegradF;
    2221              : 
    2222              :         // FUNCTION PARAMETER DEFINITIONS:
    2223              :         static constexpr std::string_view CalledFrom("HVACWaterToAir:DegradF");
    2224              : 
    2225              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2226              :         Real64 VisWater;       // Viscosity of water [mPa-s]
    2227              :         Real64 DensityWater;   // Density of water [kg/m3]
    2228              :         Real64 CpWater;        // Specific heat of water [J/kg-K]
    2229              :         Real64 CondWater;      // Conductivity of water [W/m-K]
    2230              :         Real64 VisCoolant;     // Viscosity of water [mPa-s]
    2231              :         Real64 DensityCoolant; // Density of water [kg/m3]
    2232              :         Real64 CpCoolant;      // Specific heat of water [J/kg-K]
    2233              :         Real64 CondCoolant;    // Conductivity of water [W/m-K]
    2234              : 
    2235            0 :         auto *water = Fluid::GetWater(state);
    2236              : 
    2237            0 :         VisWater = water->getViscosity(state, Temp, CalledFrom);
    2238            0 :         DensityWater = water->getDensity(state, Temp, CalledFrom);
    2239            0 :         CpWater = water->getSpecificHeat(state, Temp, CalledFrom);
    2240            0 :         CondWater = water->getConductivity(state, Temp, CalledFrom);
    2241            0 :         VisCoolant = glycol->getViscosity(state, Temp, CalledFrom);
    2242            0 :         DensityCoolant = glycol->getDensity(state, Temp, CalledFrom);
    2243            0 :         CpCoolant = glycol->getSpecificHeat(state, Temp, CalledFrom);
    2244            0 :         CondCoolant = glycol->getConductivity(state, Temp, CalledFrom);
    2245              : 
    2246            0 :         DegradF = std::pow(VisCoolant / VisWater, -0.47) * std::pow(DensityCoolant / DensityWater, 0.8) * std::pow(CpCoolant / CpWater, 0.33) *
    2247            0 :                   std::pow(CondCoolant / CondWater, 0.67);
    2248              : 
    2249            0 :         return DegradF;
    2250              :     }
    2251              : 
    2252            0 :     int GetCoilIndex(EnergyPlusData &state,
    2253              :                      std::string const &CoilType, // must match coil types in this module
    2254              :                      std::string const &CoilName, // must match coil names for the coil type
    2255              :                      bool &ErrorsFound            // set to true if problem
    2256              :     )
    2257              :     {
    2258              : 
    2259              :         // FUNCTION INFORMATION:
    2260              :         //       AUTHOR         R. Raustad
    2261              :         //       DATE WRITTEN   August 2007
    2262              : 
    2263              :         // PURPOSE OF THIS FUNCTION:
    2264              :         // This function looks up the given coil and returns the index.  If
    2265              :         // incorrect coil type or name is given, ErrorsFound is returned as true and value is returned
    2266              :         // as zero.
    2267              : 
    2268              :         // Obtains and Allocates WatertoAirHP related parameters from input file
    2269            0 :         if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered
    2270            0 :             GetWatertoAirHPInput(state);
    2271            0 :             state.dataWaterToAirHeatPump->GetCoilsInputFlag = false;
    2272              :         }
    2273              : 
    2274            0 :         int IndexNum = Util::FindItemInList(CoilName, state.dataWaterToAirHeatPump->WatertoAirHP);
    2275              : 
    2276            0 :         if (IndexNum == 0) {
    2277            0 :             ShowSevereError(state, format("Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
    2278            0 :             ErrorsFound = true;
    2279              :         }
    2280              : 
    2281            0 :         return IndexNum;
    2282              :     }
    2283              : 
    2284            0 :     Real64 GetCoilCapacity(EnergyPlusData &state,
    2285              :                            std::string const &CoilType, // must match coil types in this module
    2286              :                            std::string const &CoilName, // must match coil names for the coil type
    2287              :                            bool &ErrorsFound            // set to true if problem
    2288              :     )
    2289              :     {
    2290              : 
    2291              :         // FUNCTION INFORMATION:
    2292              :         //       AUTHOR         Linda Lawrie
    2293              :         //       DATE WRITTEN   February 2006
    2294              : 
    2295              :         // PURPOSE OF THIS FUNCTION:
    2296              :         // This function looks up the coil capacity for the given coil and returns it.  If
    2297              :         // incorrect coil type or name is given, ErrorsFound is returned as true and capacity is returned
    2298              :         // as negative.
    2299              : 
    2300              :         // Return value
    2301              :         Real64 CoilCapacity; // returned capacity of matched coil
    2302              : 
    2303              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    2304              :         int WhichCoil;
    2305              : 
    2306              :         // Obtains and Allocates WatertoAirHP related parameters from input file
    2307            0 :         if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered
    2308            0 :             GetWatertoAirHPInput(state);
    2309            0 :             state.dataWaterToAirHeatPump->GetCoilsInputFlag = false;
    2310              :         }
    2311              : 
    2312            0 :         if (Util::SameString(CoilType, "COIL:HEATING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION") ||
    2313            0 :             Util::SameString(CoilType, "COIL:COOLING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION")) {
    2314            0 :             WhichCoil = Util::FindItemInList(CoilName, state.dataWaterToAirHeatPump->WatertoAirHP);
    2315            0 :             if (WhichCoil != 0) {
    2316            0 :                 if (Util::SameString(CoilType, "COIL:HEATING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION")) {
    2317            0 :                     CoilCapacity = state.dataWaterToAirHeatPump->WatertoAirHP(WhichCoil).HeatingCapacity;
    2318              :                 } else {
    2319            0 :                     CoilCapacity = state.dataWaterToAirHeatPump->WatertoAirHP(WhichCoil).CoolingCapacity;
    2320              :                 }
    2321              :             }
    2322              :         } else {
    2323            0 :             WhichCoil = 0;
    2324              :         }
    2325              : 
    2326            0 :         if (WhichCoil == 0) {
    2327            0 :             ShowSevereError(state, format("Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
    2328            0 :             ErrorsFound = true;
    2329            0 :             CoilCapacity = -1000.0;
    2330              :         }
    2331              : 
    2332            0 :         return CoilCapacity;
    2333              :     }
    2334              : 
    2335            0 :     int GetCoilInletNode(EnergyPlusData &state,
    2336              :                          std::string const &CoilType, // must match coil types in this module
    2337              :                          std::string const &CoilName, // must match coil names for the coil type
    2338              :                          bool &ErrorsFound            // set to true if problem
    2339              :     )
    2340              :     {
    2341              : 
    2342              :         // FUNCTION INFORMATION:
    2343              :         //       AUTHOR         Linda Lawrie
    2344              :         //       DATE WRITTEN   February 2006
    2345              : 
    2346              :         // PURPOSE OF THIS FUNCTION:
    2347              :         // This function looks up the given coil and returns the inlet node.  If
    2348              :         // incorrect coil type or name is given, ErrorsFound is returned as true and value is returned
    2349              :         // as zero.
    2350              : 
    2351              :         // Return value
    2352              :         int NodeNumber; // returned outlet node of matched coil
    2353              : 
    2354              :         // Obtains and Allocates WatertoAirHP related parameters from input file
    2355            0 :         if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered
    2356            0 :             GetWatertoAirHPInput(state);
    2357            0 :             state.dataWaterToAirHeatPump->GetCoilsInputFlag = false;
    2358              :         }
    2359              : 
    2360            0 :         int WhichCoil = Util::FindItemInList(CoilName, state.dataWaterToAirHeatPump->WatertoAirHP);
    2361            0 :         if (WhichCoil != 0) {
    2362            0 :             NodeNumber = state.dataWaterToAirHeatPump->WatertoAirHP(WhichCoil).AirInletNodeNum;
    2363              :         }
    2364              : 
    2365            0 :         if (WhichCoil == 0) {
    2366            0 :             ShowSevereError(state, format("Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
    2367            0 :             ErrorsFound = true;
    2368            0 :             NodeNumber = 0;
    2369              :         }
    2370              : 
    2371            0 :         return NodeNumber;
    2372              :     }
    2373              : 
    2374            0 :     int GetCoilOutletNode(EnergyPlusData &state,
    2375              :                           std::string const &CoilType, // must match coil types in this module
    2376              :                           std::string const &CoilName, // must match coil names for the coil type
    2377              :                           bool &ErrorsFound            // set to true if problem
    2378              :     )
    2379              :     {
    2380              : 
    2381              :         // FUNCTION INFORMATION:
    2382              :         //       AUTHOR         R. Raustad
    2383              :         //       DATE WRITTEN   July 2007
    2384              : 
    2385              :         // PURPOSE OF THIS FUNCTION:
    2386              :         // This function looks up the given coil and returns the outlet node.  If
    2387              :         // incorrect coil type or name is given, ErrorsFound is returned as true and value is returned
    2388              :         // as zero.
    2389              : 
    2390              :         // Return value
    2391              :         int NodeNumber; // returned outlet node of matched coil
    2392              : 
    2393              :         // Obtains and Allocates WatertoAirHP related parameters from input file
    2394            0 :         if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered
    2395            0 :             GetWatertoAirHPInput(state);
    2396            0 :             state.dataWaterToAirHeatPump->GetCoilsInputFlag = false;
    2397              :         }
    2398              : 
    2399            0 :         int WhichCoil = Util::FindItemInList(CoilName, state.dataWaterToAirHeatPump->WatertoAirHP);
    2400            0 :         if (WhichCoil != 0) {
    2401            0 :             NodeNumber = state.dataWaterToAirHeatPump->WatertoAirHP(WhichCoil).AirOutletNodeNum;
    2402              :         }
    2403              : 
    2404            0 :         if (WhichCoil == 0) {
    2405            0 :             ShowSevereError(state, format("Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
    2406            0 :             ErrorsFound = true;
    2407            0 :             NodeNumber = 0;
    2408              :         }
    2409              : 
    2410            0 :         return NodeNumber;
    2411              :     }
    2412              : 
    2413              : } // namespace WaterToAirHeatPump
    2414              : 
    2415              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1