LCOV - code coverage report
Current view: top level - EnergyPlus - HVACMultiSpeedHeatPump.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 38.0 % 2200 835
Test Date: 2025-06-02 12:03:30 Functions: 57.9 % 19 11

            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              : #include <ObjexxFCL/Fmath.hh>
      54              : 
      55              : // EnergyPlus Headers
      56              : #include <AirflowNetwork/Solver.hpp>
      57              : #include <EnergyPlus/Autosizing/Base.hh>
      58              : #include <EnergyPlus/BranchNodeConnections.hh>
      59              : #include <EnergyPlus/DXCoils.hh>
      60              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      61              : #include <EnergyPlus/DataAirSystems.hh>
      62              : #include <EnergyPlus/DataEnvironment.hh>
      63              : #include <EnergyPlus/DataHVACGlobals.hh>
      64              : #include <EnergyPlus/DataLoopNode.hh>
      65              : #include <EnergyPlus/DataSizing.hh>
      66              : #include <EnergyPlus/DataZoneControls.hh>
      67              : #include <EnergyPlus/DataZoneEnergyDemands.hh>
      68              : #include <EnergyPlus/DataZoneEquipment.hh>
      69              : #include <EnergyPlus/EMSManager.hh>
      70              : #include <EnergyPlus/Fans.hh>
      71              : #include <EnergyPlus/FluidProperties.hh>
      72              : #include <EnergyPlus/General.hh>
      73              : #include <EnergyPlus/GeneralRoutines.hh>
      74              : #include <EnergyPlus/HVACMultiSpeedHeatPump.hh>
      75              : #include <EnergyPlus/HeatingCoils.hh>
      76              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      77              : #include <EnergyPlus/NodeInputManager.hh>
      78              : #include <EnergyPlus/OutputProcessor.hh>
      79              : #include <EnergyPlus/OutputReportPredefined.hh>
      80              : #include <EnergyPlus/Plant/DataPlant.hh>
      81              : #include <EnergyPlus/PlantUtilities.hh>
      82              : #include <EnergyPlus/Psychrometrics.hh>
      83              : #include <EnergyPlus/ScheduleManager.hh>
      84              : #include <EnergyPlus/SteamCoils.hh>
      85              : #include <EnergyPlus/UtilityRoutines.hh>
      86              : #include <EnergyPlus/WaterCoils.hh>
      87              : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      88              : 
      89              : namespace EnergyPlus {
      90              : 
      91              : namespace HVACMultiSpeedHeatPump {
      92              : 
      93              :     // Module containing the Multi Speed Heat Pump simulation routines
      94              : 
      95              :     // MODULE INFORMATION:
      96              :     //       AUTHOR         Lixing Gu, Florida Solar Energy Center
      97              :     //       DATE WRITTEN   June 2007
      98              :     //       MODIFIED       Bereket Nigusse, FSEC, June 2010 - deprecated supply air flow fraction through controlled
      99              :     //                      zone from the furnace object input field. Now, the flow fraction is calculated internally
     100              :     //                      Brent Griffith, NREL, Dec 2010 -- upgrade to new plant for heat recovery, general fluid props.
     101              :     //                      Bereket Nigusse, FSEC, Jan. 2012 -- added hot water and steam heating coil
     102              :     // PURPOSE OF THIS MODULE:
     103              :     // To encapsulate the data and algorithms required to simulate Multi Speed Heat Pump in
     104              :     // EnergyPlus.
     105              : 
     106              :     // Module currently models air-cooled or evap-cooled direct expansion systems
     107              :     // (split or packaged) with multiple speeds. Air-side performance is modeled to determine
     108              :     // coil discharge air conditions. The module also determines the DX unit's energy
     109              :     // usage. Neither the air-side performance nor the energy usage includes the effect
     110              :     // of supply air fan heat/energy usage. The supply air fan is modeled by other modules.
     111              : 
     112              :     // Curve Types
     113              :     enum class CurveType
     114              :     {
     115              :         Invalid = -1,
     116              :         Linear,      // Linear curve type
     117              :         BiLinear,    // Bi-linear curve type
     118              :         Quadratic,   // Quadratic curve type
     119              :         BiQuadratic, // Bi-quadratic curve type
     120              :         Cubic,       // Cubic curve type
     121              :         Num
     122              :     };
     123              : 
     124            0 :     void SimMSHeatPump(EnergyPlusData &state,
     125              :                        std::string_view CompName,     // Name of the unitary engine driven heat pump system
     126              :                        bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system time step
     127              :                        int const AirLoopNum,          // air loop index
     128              :                        int &CompIndex                 // Index to changeover-bypass VAV system
     129              :     )
     130              :     {
     131              : 
     132              :         // SUBROUTINE INFORMATION:
     133              :         //       AUTHOR         Lixing Gu, Florida Solar Energy Center
     134              :         //       DATE WRITTEN   June. 2007
     135              : 
     136              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     137              :         int MSHeatPumpNum;        // index of fan coil unit being simulated
     138              :         Real64 OnOffAirFlowRatio; // Ratio of compressor ON airflow to average airflow over timestep
     139              :         Real64 QZnLoad;           // Zone load required by all zones served by this air loop system
     140              :         Real64 QSensUnitOut;      // MSHP sensible capacity output [W]
     141              : 
     142              :         // First time SimMSHeatPump is called, get the input
     143            0 :         if (state.dataHVACMultiSpdHP->GetInputFlag) {
     144            0 :             GetMSHeatPumpInput(state);
     145            0 :             state.dataHVACMultiSpdHP->GetInputFlag = false; // Set GetInputFlag false so you don't get coil inputs again
     146              :         }
     147              : 
     148            0 :         if (CompIndex == 0) {
     149            0 :             MSHeatPumpNum = Util::FindItemInList(CompName, state.dataHVACMultiSpdHP->MSHeatPump);
     150            0 :             if (MSHeatPumpNum == 0) {
     151            0 :                 ShowFatalError(state, format("MultiSpeed Heat Pump is not found={}", CompName));
     152              :             }
     153            0 :             CompIndex = MSHeatPumpNum;
     154              :         } else {
     155            0 :             MSHeatPumpNum = CompIndex;
     156            0 :             if (MSHeatPumpNum > state.dataHVACMultiSpdHP->NumMSHeatPumps || MSHeatPumpNum < 1) {
     157            0 :                 ShowFatalError(state,
     158            0 :                                format("SimMSHeatPump: Invalid CompIndex passed={}, Number of MultiSpeed Heat Pumps={}, Heat Pump name={}",
     159              :                                       MSHeatPumpNum,
     160            0 :                                       state.dataHVACMultiSpdHP->NumMSHeatPumps,
     161              :                                       CompName));
     162              :             }
     163            0 :             if (state.dataHVACMultiSpdHP->CheckEquipName(MSHeatPumpNum)) {
     164            0 :                 if (CompName != state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).Name) {
     165            0 :                     ShowFatalError(state,
     166            0 :                                    format("SimMSHeatPump: Invalid CompIndex passed={}, Heat Pump name={}{}",
     167              :                                           MSHeatPumpNum,
     168              :                                           CompName,
     169            0 :                                           state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).Name));
     170              :                 }
     171            0 :                 state.dataHVACMultiSpdHP->CheckEquipName(MSHeatPumpNum) = false;
     172              :             }
     173              :         }
     174              : 
     175            0 :         OnOffAirFlowRatio = 0.0;
     176              : 
     177              :         // Initialize the engine driven heat pump
     178            0 :         InitMSHeatPump(state, MSHeatPumpNum, FirstHVACIteration, AirLoopNum, QZnLoad, OnOffAirFlowRatio);
     179              : 
     180            0 :         SimMSHP(state, MSHeatPumpNum, FirstHVACIteration, AirLoopNum, QSensUnitOut, QZnLoad, OnOffAirFlowRatio);
     181              : 
     182              :         // Update the unit outlet nodes
     183            0 :         UpdateMSHeatPump(state, MSHeatPumpNum);
     184              : 
     185              :         // Report the result of the simulation
     186            0 :         ReportMSHeatPump(state, MSHeatPumpNum);
     187            0 :     }
     188              : 
     189              :     //******************************************************************************
     190              : 
     191           12 :     void SimMSHP(EnergyPlusData &state,
     192              :                  int const MSHeatPumpNum,       // number of the current engine driven Heat Pump being simulated
     193              :                  bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
     194              :                  int const AirLoopNum,          // air loop index
     195              :                  Real64 &QSensUnitOut,          // cooling/heating delivered to zones [W]
     196              :                  Real64 const QZnReq,           // required zone load
     197              :                  Real64 &OnOffAirFlowRatio      // ratio of compressor ON airflow to AVERAGE airflow over timestep
     198              :     )
     199              :     {
     200              : 
     201              :         // SUBROUTINE INFORMATION:
     202              :         //       AUTHOR         Lixing Gu
     203              :         //       DATE WRITTEN   June 2007
     204              :         //       RE-ENGINEERED  Revised based on SimPTHP
     205              : 
     206              :         // PURPOSE OF THIS SUBROUTINE:
     207              :         // Simulate a multispeed heat pump; adjust its output to match the
     208              :         // required system load.
     209              : 
     210              :         // METHODOLOGY EMPLOYED:
     211              :         // Calls ControlMSHPOutput to obtain the desired unit output
     212              : 
     213              :         // Locals
     214              :         Real64 SupHeaterLoad;
     215              : 
     216              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     217              :         Real64 PartLoadFrac; // compressor part load fraction
     218              :         Real64 SpeedRatio;   // compressor speed ratio
     219              :         bool UnitOn;         // TRUE if unit is on
     220              :         int OutletNode;      // MSHP air outlet node
     221              :         int InletNode;       // MSHP air inlet node
     222              :         Real64 AirMassFlow;  // air mass flow rate [kg/s]
     223              :         HVAC::FanOp fanOp;   // operating mode (fan cycling or continuous; DX coil always cycles)
     224              :         int ZoneNum;         // Controlled zone number
     225              :         Real64 QTotUnitOut;
     226              :         int SpeedNum;                    // Speed number
     227              :         HVAC::CompressorOp compressorOp; // compressor operation; 1=on, 0=off
     228              :         Real64 SaveMassFlowRate;         // saved inlet air mass flow rate [kg/s]
     229              : 
     230              :         // zero the fan, DX coils, and supplemental electric heater electricity consumption
     231           12 :         state.dataHVACGlobal->DXElecHeatingPower = 0.0;
     232           12 :         state.dataHVACGlobal->DXElecCoolingPower = 0.0;
     233           12 :         state.dataHVACMultiSpdHP->SaveCompressorPLR = 0.0;
     234           12 :         state.dataHVACGlobal->ElecHeatingCoilPower = 0.0;
     235           12 :         state.dataHVACGlobal->SuppHeatingCoilPower = 0.0;
     236           12 :         state.dataHVACGlobal->DefrostElecPower = 0.0;
     237              : 
     238           12 :         auto &multiSpeedHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
     239              : 
     240              :         // initialize local variables
     241           12 :         UnitOn = true;
     242           12 :         OutletNode = multiSpeedHeatPump.AirOutletNodeNum;
     243           12 :         InletNode = multiSpeedHeatPump.AirInletNodeNum;
     244           12 :         AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
     245           12 :         fanOp = multiSpeedHeatPump.fanOp;
     246           12 :         ZoneNum = multiSpeedHeatPump.ControlZoneNum;
     247           12 :         compressorOp = HVAC::CompressorOp::On;
     248              : 
     249              :         // set the on/off flags
     250           12 :         if (multiSpeedHeatPump.fanOp == HVAC::FanOp::Cycling) {
     251              :             // cycling unit only runs if there is a cooling or heating load.
     252            0 :             if (std::abs(QZnReq) < HVAC::SmallLoad || AirMassFlow < HVAC::SmallMassFlow ||
     253            0 :                 state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
     254            0 :                 UnitOn = false;
     255              :             }
     256           12 :         } else if (multiSpeedHeatPump.fanOp == HVAC::FanOp::Continuous) {
     257              :             // continuous unit: fan runs if scheduled on; coil runs only if there is a cooling or heating load
     258           12 :             if (AirMassFlow < HVAC::SmallMassFlow) {
     259            0 :                 UnitOn = false;
     260              :             }
     261              :         }
     262              : 
     263           12 :         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
     264              : 
     265           12 :         SaveMassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate;
     266           12 :         if (multiSpeedHeatPump.EMSOverrideCoilSpeedNumOn) {
     267            4 :             Real64 SpeedVal = multiSpeedHeatPump.EMSOverrideCoilSpeedNumValue;
     268              : 
     269            4 :             if (!FirstHVACIteration && multiSpeedHeatPump.fanOp == HVAC::FanOp::Cycling && QZnReq < 0.0 &&
     270            0 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive) {
     271            0 :                 compressorOp = HVAC::CompressorOp::Off;
     272            0 :                 ControlMSHPOutputEMS(state,
     273              :                                      MSHeatPumpNum,
     274              :                                      FirstHVACIteration,
     275              :                                      compressorOp,
     276              :                                      fanOp,
     277              :                                      QZnReq,
     278              :                                      SpeedVal,
     279              :                                      SpeedNum,
     280              :                                      SpeedRatio,
     281              :                                      PartLoadFrac,
     282              :                                      OnOffAirFlowRatio,
     283              :                                      SupHeaterLoad);
     284            0 :                 if (ceil(SpeedVal) == multiSpeedHeatPump.NumOfSpeedCooling && SpeedRatio == 1.0) {
     285            0 :                     state.dataLoopNodes->Node(InletNode).MassFlowRate = SaveMassFlowRate;
     286            0 :                     compressorOp = HVAC::CompressorOp::On;
     287            0 :                     ControlMSHPOutputEMS(state,
     288              :                                          MSHeatPumpNum,
     289              :                                          FirstHVACIteration,
     290              :                                          compressorOp,
     291              :                                          fanOp,
     292              :                                          QZnReq,
     293              :                                          SpeedVal,
     294              :                                          SpeedNum,
     295              :                                          SpeedRatio,
     296              :                                          PartLoadFrac,
     297              :                                          OnOffAirFlowRatio,
     298              :                                          SupHeaterLoad);
     299              :                 }
     300              :             } else {
     301            4 :                 ControlMSHPOutputEMS(state,
     302              :                                      MSHeatPumpNum,
     303              :                                      FirstHVACIteration,
     304              :                                      compressorOp,
     305              :                                      fanOp,
     306              :                                      QZnReq,
     307              :                                      SpeedVal,
     308              :                                      SpeedNum,
     309              :                                      SpeedRatio,
     310              :                                      PartLoadFrac,
     311              :                                      OnOffAirFlowRatio,
     312              :                                      SupHeaterLoad);
     313              :             }
     314              :         } else {
     315            8 :             if (!FirstHVACIteration && multiSpeedHeatPump.fanOp == HVAC::FanOp::Cycling && QZnReq < 0.0 &&
     316            0 :                 state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive) {
     317              :                 // for cycling fan, cooling load, check whether furnace can meet load with compressor off
     318            0 :                 compressorOp = HVAC::CompressorOp::Off;
     319            0 :                 ControlMSHPOutput(state,
     320              :                                   MSHeatPumpNum,
     321              :                                   FirstHVACIteration,
     322              :                                   compressorOp,
     323              :                                   fanOp,
     324              :                                   QZnReq,
     325              :                                   ZoneNum,
     326              :                                   SpeedNum,
     327              :                                   SpeedRatio,
     328              :                                   PartLoadFrac,
     329              :                                   OnOffAirFlowRatio,
     330              :                                   SupHeaterLoad);
     331            0 :                 if (SpeedNum == multiSpeedHeatPump.NumOfSpeedCooling && SpeedRatio == 1.0) {
     332              :                     // compressor on (reset inlet air mass flow rate to starting value)
     333            0 :                     state.dataLoopNodes->Node(InletNode).MassFlowRate = SaveMassFlowRate;
     334            0 :                     compressorOp = HVAC::CompressorOp::On;
     335            0 :                     ControlMSHPOutput(state,
     336              :                                       MSHeatPumpNum,
     337              :                                       FirstHVACIteration,
     338              :                                       compressorOp,
     339              :                                       fanOp,
     340              :                                       QZnReq,
     341              :                                       ZoneNum,
     342              :                                       SpeedNum,
     343              :                                       SpeedRatio,
     344              :                                       PartLoadFrac,
     345              :                                       OnOffAirFlowRatio,
     346              :                                       SupHeaterLoad);
     347              :                 }
     348              :             } else {
     349              :                 // compressor on
     350            8 :                 ControlMSHPOutput(state,
     351              :                                   MSHeatPumpNum,
     352              :                                   FirstHVACIteration,
     353              :                                   compressorOp,
     354              :                                   fanOp,
     355              :                                   QZnReq,
     356              :                                   ZoneNum,
     357              :                                   SpeedNum,
     358              :                                   SpeedRatio,
     359              :                                   PartLoadFrac,
     360              :                                   OnOffAirFlowRatio,
     361              :                                   SupHeaterLoad);
     362              :             }
     363              :         }
     364              : 
     365           12 :         if (multiSpeedHeatPump.HeatCoilType != MultiSpeedHeatingCoil) {
     366            0 :             state.dataHVACMultiSpdHP->SaveCompressorPLR = PartLoadFrac;
     367              :         } else {
     368           12 :             if (SpeedNum > 1) {
     369            3 :                 state.dataHVACMultiSpdHP->SaveCompressorPLR = 1.0;
     370              :             }
     371              : 
     372           12 :             if (PartLoadFrac == 1.0 && state.dataHVACMultiSpdHP->SaveCompressorPLR < 1.0 && (!multiSpeedHeatPump.Staged)) {
     373            0 :                 PartLoadFrac = state.dataHVACMultiSpdHP->SaveCompressorPLR;
     374              :             }
     375              :         }
     376              : 
     377           12 :         CalcMSHeatPump(state,
     378              :                        MSHeatPumpNum,
     379              :                        FirstHVACIteration,
     380              :                        compressorOp,
     381              :                        SpeedNum,
     382              :                        SpeedRatio,
     383              :                        PartLoadFrac,
     384              :                        QSensUnitOut,
     385              :                        QZnReq,
     386              :                        OnOffAirFlowRatio,
     387              :                        SupHeaterLoad);
     388              : 
     389              :         // calculate delivered capacity
     390           12 :         AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
     391              : 
     392           12 :         QTotUnitOut = AirMassFlow * (state.dataLoopNodes->Node(OutletNode).Enthalpy -
     393           12 :                                      state.dataLoopNodes->Node(multiSpeedHeatPump.NodeNumOfControlledZone).Enthalpy);
     394              : 
     395              :         // report variables
     396           12 :         multiSpeedHeatPump.CompPartLoadRatio = state.dataHVACMultiSpdHP->SaveCompressorPLR;
     397           12 :         if (multiSpeedHeatPump.fanOp == HVAC::FanOp::Cycling) {
     398            0 :             if (SupHeaterLoad > 0.0) {
     399            0 :                 multiSpeedHeatPump.FanPartLoadRatio = 1.0;
     400              :             } else {
     401            0 :                 if (SpeedNum < 2) {
     402            0 :                     multiSpeedHeatPump.FanPartLoadRatio = PartLoadFrac;
     403              :                 } else {
     404            0 :                     multiSpeedHeatPump.FanPartLoadRatio = 1.0;
     405              :                 }
     406              :             }
     407              :         } else {
     408           12 :             if (UnitOn) {
     409           12 :                 multiSpeedHeatPump.FanPartLoadRatio = 1.0;
     410              :             } else {
     411            0 :                 if (SpeedNum < 2) {
     412            0 :                     multiSpeedHeatPump.FanPartLoadRatio = PartLoadFrac;
     413              :                 } else {
     414            0 :                     multiSpeedHeatPump.FanPartLoadRatio = 1.0;
     415              :                 }
     416              :             }
     417              :         }
     418              : 
     419           12 :         if (multiSpeedHeatPump.HeatCoolMode == ModeOfOperation::HeatingMode) {
     420            8 :             multiSpeedHeatPump.TotHeatEnergyRate = std::abs(max(0.0, QTotUnitOut));
     421            8 :             multiSpeedHeatPump.SensHeatEnergyRate = std::abs(max(0.0, QSensUnitOut));
     422            8 :             multiSpeedHeatPump.LatHeatEnergyRate = std::abs(max(0.0, (QTotUnitOut - QSensUnitOut)));
     423            8 :             multiSpeedHeatPump.TotCoolEnergyRate = 0.0;
     424            8 :             multiSpeedHeatPump.SensCoolEnergyRate = 0.0;
     425            8 :             multiSpeedHeatPump.LatCoolEnergyRate = 0.0;
     426              :         }
     427           12 :         if (multiSpeedHeatPump.HeatCoolMode == ModeOfOperation::CoolingMode) {
     428            4 :             multiSpeedHeatPump.TotCoolEnergyRate = std::abs(min(0.0, QTotUnitOut));
     429            4 :             multiSpeedHeatPump.SensCoolEnergyRate = std::abs(min(0.0, QSensUnitOut));
     430            4 :             multiSpeedHeatPump.LatCoolEnergyRate = std::abs(min(0.0, (QTotUnitOut - QSensUnitOut)));
     431            4 :             multiSpeedHeatPump.TotHeatEnergyRate = 0.0;
     432            4 :             multiSpeedHeatPump.SensHeatEnergyRate = 0.0;
     433            4 :             multiSpeedHeatPump.LatHeatEnergyRate = 0.0;
     434              :         }
     435              : 
     436           12 :         multiSpeedHeatPump.AuxElecPower = multiSpeedHeatPump.AuxOnCyclePower * state.dataHVACMultiSpdHP->SaveCompressorPLR +
     437           12 :                                           multiSpeedHeatPump.AuxOffCyclePower * (1.0 - state.dataHVACMultiSpdHP->SaveCompressorPLR);
     438           12 :         Real64 locFanElecPower = 0.0;
     439           12 :         locFanElecPower = state.dataFans->fans(multiSpeedHeatPump.FanNum)->totalPower;
     440           12 :         multiSpeedHeatPump.ElecPower = locFanElecPower + state.dataHVACGlobal->DXElecCoolingPower + state.dataHVACGlobal->DXElecHeatingPower +
     441           12 :                                        state.dataHVACGlobal->ElecHeatingCoilPower + state.dataHVACGlobal->SuppHeatingCoilPower +
     442           12 :                                        state.dataHVACGlobal->DefrostElecPower + multiSpeedHeatPump.AuxElecPower;
     443           12 :     }
     444              : 
     445              :     //******************************************************************************
     446              : 
     447            2 :     void GetMSHeatPumpInput(EnergyPlusData &state)
     448              :     {
     449              :         // SUBROUTINE INFORMATION:
     450              :         //       AUTHOR:          Lixing Gu, FSEC
     451              :         //       DATE WRITTEN:    July 2007
     452              : 
     453              :         // PURPOSE OF THIS SUBROUTINE:
     454              :         //  This routine will get the input required by the multispeed heat pump model
     455              : 
     456              :         using namespace OutputReportPredefined;
     457              : 
     458              :         // PARAMETERS
     459              :         static constexpr std::string_view RoutineName("GetMSHeatPumpInput: "); // include trailing blank space
     460              :         static constexpr std::string_view routineName = "GetMSHeatPumpInput";
     461              : 
     462              :         // LOCAL VARIABLES
     463              :         int NumAlphas;                 // Number of elements in the alpha array
     464              :         int NumNumbers;                // Number of Numbers for each GetObjectItem call
     465              :         int IOStatus;                  // Used in GetObjectItem
     466            2 :         bool ErrorsFound(false);       // True when input errors found
     467              :         bool IsNotOK;                  // Flag to verify name
     468              :         bool AirNodeFound;             // True when an air node is found
     469              :         bool AirLoopFound;             // True when an air loop is found
     470              :         int i;                         // Index to speeds
     471              :         int j;                         // Index to speeds
     472              :         bool Found;                    // Flag to find autosize
     473              :         bool LocalError;               // Local error flag
     474            2 :         Array1D_string Alphas;         // Alpha input items for object
     475            2 :         Array1D_string cAlphaFields;   // Alpha field names
     476            2 :         Array1D_string cNumericFields; // Numeric field names
     477            2 :         Array1D<Real64> Numbers;       // Numeric input items for object
     478            2 :         Array1D_bool lAlphaBlanks;     // Logical array, alpha field input BLANK = .TRUE.
     479            2 :         Array1D_bool lNumericBlanks;   // Logical array, numeric field input BLANK = .TRUE.
     480            2 :         int MaxNums(0);                // Maximum number of numeric input fields
     481            2 :         int MaxAlphas(0);              // Maximum number of alpha input fields
     482            2 :         int TotalArgs(0);              // Total number of alpha and numeric arguments (max) for a
     483              :         //  certain object in the input file
     484              :         bool errFlag;
     485              :         Real64 SteamDensity; // density of steam at 100C
     486              : 
     487            2 :         auto &MSHeatPump(state.dataHVACMultiSpdHP->MSHeatPump);
     488              : 
     489            2 :         if (MSHeatPump.allocated()) {
     490            0 :             return;
     491              :         }
     492              : 
     493            2 :         state.dataHVACMultiSpdHP->CurrentModuleObject =
     494            2 :             "AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed"; // Object type for getting and error messages
     495              : 
     496            4 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     497            2 :             state, state.dataHVACMultiSpdHP->CurrentModuleObject, TotalArgs, NumAlphas, NumNumbers);
     498            2 :         MaxNums = max(MaxNums, NumNumbers);
     499            2 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     500              : 
     501            2 :         Alphas.allocate(MaxAlphas);
     502            2 :         cAlphaFields.allocate(MaxAlphas);
     503            2 :         Numbers.dimension(MaxNums, 0.0);
     504            2 :         cNumericFields.allocate(MaxNums);
     505            2 :         lAlphaBlanks.dimension(MaxAlphas, true);
     506            2 :         lNumericBlanks.dimension(MaxNums, true);
     507              : 
     508            4 :         state.dataHVACMultiSpdHP->NumMSHeatPumps =
     509            2 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataHVACMultiSpdHP->CurrentModuleObject);
     510              : 
     511            2 :         if (state.dataHVACMultiSpdHP->NumMSHeatPumps <= 0) {
     512            0 :             ShowSevereError(state, format("No {} objects specified in input file.", state.dataHVACMultiSpdHP->CurrentModuleObject));
     513            0 :             ErrorsFound = true;
     514              :         }
     515              : 
     516              :         // ALLOCATE ARRAYS
     517            2 :         MSHeatPump.allocate(state.dataHVACMultiSpdHP->NumMSHeatPumps);
     518            2 :         state.dataHVACMultiSpdHP->MSHeatPumpReport.allocate(state.dataHVACMultiSpdHP->NumMSHeatPumps);
     519            2 :         state.dataHVACMultiSpdHP->CheckEquipName.dimension(state.dataHVACMultiSpdHP->NumMSHeatPumps, true);
     520              : 
     521              :         // Load arrays with reformulated electric EIR chiller data
     522            5 :         for (int MSHPNum = 1; MSHPNum <= state.dataHVACMultiSpdHP->NumMSHeatPumps; ++MSHPNum) {
     523            3 :             auto &thisMSHP = MSHeatPump(MSHPNum);
     524            3 :             int HeatingCoilInletNode = 0;
     525            3 :             int HeatingCoilOutletNode = 0;
     526            3 :             int CoolingCoilInletNode = 0;
     527            3 :             int CoolingCoilOutletNode = 0;
     528            3 :             int SuppHeatCoilInletNode = 0;
     529            3 :             int SuppHeatCoilOutletNode = 0;
     530              : 
     531            6 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     532            3 :                                                                      state.dataHVACMultiSpdHP->CurrentModuleObject,
     533              :                                                                      MSHPNum,
     534              :                                                                      Alphas,
     535              :                                                                      NumAlphas,
     536              :                                                                      Numbers,
     537              :                                                                      NumNumbers,
     538              :                                                                      IOStatus,
     539              :                                                                      lNumericBlanks,
     540              :                                                                      lAlphaBlanks,
     541              :                                                                      cAlphaFields,
     542              :                                                                      cNumericFields);
     543              : 
     544            3 :             thisMSHP.Name = Alphas(1);
     545              : 
     546            3 :             ErrorObjectHeader eoh{routineName, state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name};
     547              : 
     548            3 :             if (lAlphaBlanks(2)) {
     549            0 :                 thisMSHP.availSched = Sched::GetScheduleAlwaysOn(state);
     550            3 :             } else if ((thisMSHP.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
     551            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     552            0 :                 ErrorsFound = true;
     553              :             }
     554              : 
     555            3 :             thisMSHP.AirInletNodeName = Alphas(3);
     556            3 :             thisMSHP.AirOutletNodeName = Alphas(4);
     557            3 :             thisMSHP.AirInletNodeNum = GetOnlySingleNode(state,
     558            3 :                                                          Alphas(3),
     559              :                                                          ErrorsFound,
     560              :                                                          DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed,
     561            3 :                                                          Alphas(1),
     562              :                                                          DataLoopNode::NodeFluidType::Air,
     563              :                                                          DataLoopNode::ConnectionType::Inlet,
     564              :                                                          NodeInputManager::CompFluidStream::Primary,
     565              :                                                          DataLoopNode::ObjectIsParent);
     566              : 
     567            6 :             thisMSHP.AirOutletNodeNum = GetOnlySingleNode(state,
     568            3 :                                                           Alphas(4),
     569              :                                                           ErrorsFound,
     570              :                                                           DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed,
     571            3 :                                                           Alphas(1),
     572              :                                                           DataLoopNode::NodeFluidType::Air,
     573              :                                                           DataLoopNode::ConnectionType::Outlet,
     574              :                                                           NodeInputManager::CompFluidStream::Primary,
     575              :                                                           DataLoopNode::ObjectIsParent);
     576              : 
     577            3 :             BranchNodeConnections::TestCompSet(state, state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
     578              : 
     579              :             // Get the Controlling Zone or Location of the engine driven heat pump Thermostat
     580            3 :             thisMSHP.ControlZoneNum = Util::FindItemInList(Alphas(5), state.dataHeatBal->Zone);
     581            3 :             thisMSHP.ControlZoneName = Alphas(5);
     582            3 :             if (thisMSHP.ControlZoneNum == 0) {
     583            0 :                 ShowSevereError(state,
     584            0 :                                 format("{}, \"{}\" {} not found: {}",
     585            0 :                                        state.dataHVACMultiSpdHP->CurrentModuleObject,
     586            0 :                                        thisMSHP.Name,
     587              :                                        cAlphaFields(5),
     588            0 :                                        thisMSHP.ControlZoneName));
     589            0 :                 ErrorsFound = true;
     590              :             }
     591              : 
     592              :             // Get the node number for the zone with the thermostat
     593            3 :             if (thisMSHP.ControlZoneNum > 0) {
     594            3 :                 AirNodeFound = false;
     595            3 :                 AirLoopFound = false;
     596            3 :                 int ControlledZoneNum = thisMSHP.ControlZoneNum;
     597              :                 // Find the controlled zone number for the specified thermostat location
     598            3 :                 thisMSHP.NodeNumOfControlledZone = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
     599              :                 // Determine if furnace is on air loop served by the thermostat location specified
     600            3 :                 for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
     601            3 :                     int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
     602            3 :                     if (AirLoopNumber > 0) {
     603            3 :                         for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
     604            6 :                             for (int CompNum = 1;
     605            6 :                                  CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
     606              :                                  ++CompNum) {
     607            6 :                                 if (!Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
     608            9 :                                                       thisMSHP.Name) ||
     609            6 :                                     !Util::SameString(
     610            3 :                                         state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
     611            3 :                                         state.dataHVACMultiSpdHP->CurrentModuleObject)) {
     612            3 :                                     continue;
     613              :                                 }
     614            3 :                                 AirLoopFound = true;
     615            3 :                                 thisMSHP.AirLoopNumber = AirLoopNumber;
     616            3 :                                 break;
     617              :                             }
     618            3 :                             thisMSHP.ZoneInletNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode(zoneInNode);
     619            3 :                             if (AirLoopFound) {
     620            3 :                                 break;
     621              :                             }
     622              :                         }
     623            8 :                         for (int TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++TstatZoneNum) {
     624            5 :                             if (state.dataZoneCtrls->TempControlledZone(TstatZoneNum).ActualZoneNum != thisMSHP.ControlZoneNum) {
     625            2 :                                 continue;
     626              :                             }
     627            3 :                             AirNodeFound = true;
     628              :                         }
     629            3 :                         for (int TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++TstatZoneNum) {
     630            0 :                             if (state.dataZoneCtrls->ComfortControlledZone(TstatZoneNum).ActualZoneNum != thisMSHP.ControlZoneNum) {
     631            0 :                                 continue;
     632              :                             }
     633            0 :                             AirNodeFound = true;
     634              :                         }
     635            3 :                         for (int TstatZoneNum = 1; TstatZoneNum <= state.dataZoneTempPredictorCorrector->NumStageCtrZone; ++TstatZoneNum) {
     636            0 :                             if (state.dataZoneCtrls->StageControlledZone(TstatZoneNum).ActualZoneNum != thisMSHP.ControlZoneNum) {
     637            0 :                                 continue;
     638              :                             }
     639            0 :                             AirNodeFound = true;
     640              :                         }
     641              :                     }
     642            3 :                     if (AirLoopFound) {
     643            3 :                         break;
     644              :                     }
     645              :                 }
     646            3 :                 if (!AirNodeFound) {
     647            0 :                     ShowSevereError(state,
     648            0 :                                     format("Did not find Air Node ({}), {} = \"\"{}",
     649              :                                            cAlphaFields(5),
     650            0 :                                            state.dataHVACMultiSpdHP->CurrentModuleObject,
     651            0 :                                            thisMSHP.Name));
     652            0 :                     ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
     653            0 :                     ErrorsFound = true;
     654              :                 }
     655            3 :                 if (!AirLoopFound) {
     656            0 :                     ShowSevereError(
     657            0 :                         state, format("Did not find correct AirLoopHVAC for {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
     658            0 :                     ShowContinueError(state, format("The {} = {} is not served by this Primary Air Loop equipment.", cAlphaFields(5), Alphas(5)));
     659            0 :                     ErrorsFound = true;
     660              :                 }
     661              :             }
     662              : 
     663              :             // Get supply fan data
     664            3 :             thisMSHP.FanNum = Fans::GetFanIndex(state, Alphas(7));
     665            3 :             if (thisMSHP.FanNum == 0) {
     666            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(7), Alphas(7));
     667            0 :                 ErrorsFound = true;
     668              :             } else {
     669            3 :                 auto *fan = state.dataFans->fans(thisMSHP.FanNum);
     670            3 :                 thisMSHP.FanName = fan->Name;
     671            3 :                 thisMSHP.fanType = fan->type;
     672            3 :                 thisMSHP.FanInletNode = fan->inletNodeNum;
     673            3 :                 thisMSHP.FanOutletNode = fan->outletNodeNum;
     674            9 :                 BranchNodeConnections::SetUpCompSets(state,
     675            3 :                                                      state.dataHVACMultiSpdHP->CurrentModuleObject,
     676              :                                                      thisMSHP.Name,
     677            3 :                                                      HVAC::fanTypeNames[(int)thisMSHP.fanType],
     678              :                                                      thisMSHP.FanName,
     679              :                                                      "UNDEFINED",
     680              :                                                      "UNDEFINED");
     681              :             }
     682              : 
     683              :             // Get supply fan placement data
     684            3 :             thisMSHP.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(8)));
     685            3 :             assert(thisMSHP.fanPlace != HVAC::FanPlace::Invalid);
     686              : 
     687            3 :             if ((thisMSHP.fanOpModeSched = Sched::GetSchedule(state, Alphas(9))) == nullptr) {
     688            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(9), Alphas(9));
     689            0 :                 ErrorsFound = true;
     690              :             }
     691              : 
     692            3 :             if (thisMSHP.fanOpModeSched != nullptr && thisMSHP.fanType == HVAC::FanType::Constant) {
     693            0 :                 if (!thisMSHP.fanOpModeSched->checkMinMaxVals(state, Clusive::Ex, 0.0, Clusive::In, 1.0)) {
     694            0 :                     Sched::ShowSevereBadMinMax(state,
     695              :                                                eoh,
     696            0 :                                                cAlphaFields(9),
     697            0 :                                                Alphas(9),
     698              :                                                Clusive::Ex,
     699              :                                                0.0,
     700              :                                                Clusive::In,
     701              :                                                1.0,
     702              :                                                "Fan mode must be continuous (schedule values > 0) for Fan:ConstantVolume.");
     703            0 :                     ErrorsFound = true;
     704              :                 }
     705              :             }
     706              : 
     707            3 :             if (Util::SameString(Alphas(10), "Coil:Heating:DX:MultiSpeed")) {
     708            3 :                 thisMSHP.HeatCoilType = MultiSpeedHeatingCoil;
     709            3 :                 thisMSHP.HeatCoilNum = state.dataInputProcessing->inputProcessor->getObjectItemNum(state, "Coil:Heating:DX:MultiSpeed", Alphas(11));
     710            3 :                 thisMSHP.DXHeatCoilName = Alphas(11);
     711            3 :                 if (thisMSHP.HeatCoilNum <= 0) {
     712            0 :                     ShowSevereError(state, format("Configuration error in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     713            0 :                     ShowContinueError(state, format("{} \"{}\" not found.", cAlphaFields(11), Alphas(11)));
     714            0 :                     ShowContinueError(state, format("{} must be Coil:Heating:DX:MultiSpeed ", cAlphaFields(10)));
     715            0 :                     ShowFatalError(state,
     716            0 :                                    format("{}Errors found in getting {} input. Preceding condition(s) causes termination.",
     717              :                                           RoutineName,
     718            0 :                                           state.dataHVACMultiSpdHP->CurrentModuleObject));
     719            0 :                     ErrorsFound = true;
     720              :                 }
     721            3 :                 LocalError = false;
     722            3 :                 DXCoils::GetDXCoilIndex(state, thisMSHP.DXHeatCoilName, thisMSHP.DXHeatCoilIndex, LocalError, "Coil:Heating:DX:MultiSpeed");
     723            3 :                 if (LocalError) {
     724            0 :                     ShowSevereError(state, format("The index of {} is not found \"{}\"", cAlphaFields(11), Alphas(11)));
     725            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     726            0 :                     ErrorsFound = true;
     727            0 :                     LocalError = false;
     728              :                 }
     729            3 :                 HeatingCoilInletNode = DXCoils::GetCoilInletNode(state, Alphas(10), Alphas(11), LocalError);
     730            3 :                 if (LocalError) {
     731            0 :                     ShowSevereError(state, format("The inlet node number of {} is not found \"{}\"", cAlphaFields(11), Alphas(11)));
     732            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     733            0 :                     ErrorsFound = true;
     734            0 :                     LocalError = false;
     735              :                 }
     736            3 :                 HeatingCoilOutletNode = DXCoils::GetCoilOutletNode(state, Alphas(10), Alphas(11), LocalError);
     737            3 :                 if (LocalError) {
     738            0 :                     ShowSevereError(state, format("The outlet node number of {} is not found \"{}\"", cAlphaFields(11), Alphas(11)));
     739            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     740            0 :                     ErrorsFound = true;
     741            0 :                     LocalError = false;
     742              :                 }
     743            3 :                 thisMSHP.MinOATCompressorHeating = DXCoils::GetMinOATCompressor(state, thisMSHP.DXHeatCoilIndex, LocalError);
     744            3 :                 if (LocalError) {
     745            0 :                     ShowContinueError(state,
     746            0 :                                       format("...for heating coil. Occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     747            0 :                     LocalError = false;
     748              :                 }
     749            6 :                 BranchNodeConnections::SetUpCompSets(state,
     750            3 :                                                      state.dataHVACMultiSpdHP->CurrentModuleObject,
     751              :                                                      thisMSHP.Name,
     752              :                                                      "Coil:Heating:DX:MultiSpeed",
     753              :                                                      thisMSHP.DXHeatCoilName,
     754              :                                                      "UNDEFINED",
     755              :                                                      "UNDEFINED");
     756            0 :             } else if (Util::SameString(Alphas(10), "Coil:Heating:Electric:MultiStage") ||
     757            0 :                        Util::SameString(Alphas(10), "Coil:Heating:Gas:MultiStage")) {
     758              : 
     759            0 :                 if (Util::SameString(Alphas(10), "Coil:Heating:Electric:MultiStage")) {
     760            0 :                     thisMSHP.HeatCoilType = HVAC::Coil_HeatingElectric_MultiStage;
     761            0 :                     thisMSHP.HeatCoilNum =
     762            0 :                         state.dataInputProcessing->inputProcessor->getObjectItemNum(state, "Coil:Heating:Electric:MultiStage", Alphas(11));
     763            0 :                     if (thisMSHP.HeatCoilNum <= 0) {
     764            0 :                         ShowSevereError(state, format("Configuration error in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     765            0 :                         ShowContinueError(state, format("{} \"{}\" not found.", cAlphaFields(11), Alphas(11)));
     766            0 :                         ShowContinueError(state, format("{} must be Coil:Heating:Electric:MultiStage ", cAlphaFields(10)));
     767            0 :                         ShowFatalError(state,
     768            0 :                                        format("{}Errors found in getting {} input. Preceding condition(s) causes termination.",
     769              :                                               RoutineName,
     770            0 :                                               state.dataHVACMultiSpdHP->CurrentModuleObject));
     771            0 :                         ErrorsFound = true;
     772              :                     }
     773              :                 } else {
     774            0 :                     thisMSHP.HeatCoilType = HVAC::Coil_HeatingGas_MultiStage;
     775            0 :                     thisMSHP.HeatCoilNum =
     776            0 :                         state.dataInputProcessing->inputProcessor->getObjectItemNum(state, "Coil:Heating:Gas:MultiStage", Alphas(11));
     777            0 :                     if (thisMSHP.HeatCoilNum <= 0) {
     778            0 :                         ShowSevereError(state, format("Configuration error in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     779            0 :                         ShowContinueError(state, format("{} \"{}\" not found.", cAlphaFields(11), Alphas(11)));
     780            0 :                         ShowContinueError(state, format("{} must be Coil:Heating:Gas:MultiStage ", cAlphaFields(10)));
     781            0 :                         ShowFatalError(state,
     782            0 :                                        format("{}Errors found in getting {} input. Preceding condition(s) causes termination.",
     783              :                                               RoutineName,
     784            0 :                                               state.dataHVACMultiSpdHP->CurrentModuleObject));
     785            0 :                         ErrorsFound = true;
     786              :                     }
     787              :                 }
     788            0 :                 thisMSHP.HeatCoilName = Alphas(11);
     789            0 :                 LocalError = false;
     790            0 :                 if (Util::SameString(Alphas(10), "Coil:Heating:Electric:MultiStage")) {
     791            0 :                     HeatingCoils::GetCoilIndex(state, thisMSHP.HeatCoilName, thisMSHP.HeatCoilIndex, LocalError);
     792              :                 } else {
     793            0 :                     HeatingCoils::GetCoilIndex(state, thisMSHP.HeatCoilName, thisMSHP.HeatCoilIndex, LocalError);
     794              :                 }
     795            0 :                 if (LocalError) {
     796            0 :                     ShowSevereError(state, format("The index of {} is not found \"{}\"", cAlphaFields(11), Alphas(11)));
     797            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     798            0 :                     ErrorsFound = true;
     799            0 :                     LocalError = false;
     800              :                 }
     801            0 :                 HeatingCoilInletNode = HeatingCoils::GetCoilInletNode(state, Alphas(10), Alphas(11), LocalError);
     802            0 :                 if (LocalError) {
     803            0 :                     ShowSevereError(state, format("The inlet node number of {} is not found \"{}\"", cAlphaFields(11), Alphas(11)));
     804            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     805            0 :                     ErrorsFound = true;
     806            0 :                     LocalError = false;
     807              :                 }
     808            0 :                 HeatingCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, Alphas(10), Alphas(11), LocalError);
     809            0 :                 if (LocalError) {
     810            0 :                     ShowSevereError(state, format("The outlet node number of {} is not found \"{}\"", cAlphaFields(11), Alphas(11)));
     811            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     812            0 :                     ErrorsFound = true;
     813            0 :                     LocalError = false;
     814              :                 }
     815            0 :                 if (Util::SameString(Alphas(10), "Coil:Heating:Electric:MultiStage")) {
     816            0 :                     BranchNodeConnections::SetUpCompSets(state,
     817            0 :                                                          state.dataHVACMultiSpdHP->CurrentModuleObject,
     818              :                                                          thisMSHP.Name,
     819              :                                                          "Coil:Heating:Electric:MultiStage",
     820              :                                                          thisMSHP.HeatCoilName,
     821              :                                                          "UNDEFINED",
     822              :                                                          "UNDEFINED");
     823              :                 } else {
     824            0 :                     BranchNodeConnections::SetUpCompSets(state,
     825            0 :                                                          state.dataHVACMultiSpdHP->CurrentModuleObject,
     826              :                                                          thisMSHP.Name,
     827              :                                                          "Coil:Heating:Gas:MultiStage",
     828              :                                                          thisMSHP.HeatCoilName,
     829              :                                                          "UNDEFINED",
     830              :                                                          "UNDEFINED");
     831              :                 }
     832            0 :             } else if (Util::SameString(Alphas(10), "Coil:Heating:Water")) {
     833            0 :                 thisMSHP.HeatCoilType = HVAC::Coil_HeatingWater;
     834            0 :                 ValidateComponent(state, Alphas(10), Alphas(11), IsNotOK, state.dataHVACMultiSpdHP->CurrentModuleObject);
     835            0 :                 if (IsNotOK) {
     836            0 :                     ShowContinueError(state, format("...occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     837            0 :                     ErrorsFound = true;
     838              :                 } else { // mine data from heating coil object
     839              : 
     840            0 :                     thisMSHP.HeatCoilName = Alphas(11);
     841              :                     // Get the Heating Coil water Inlet or control Node number
     842            0 :                     errFlag = false;
     843            0 :                     thisMSHP.CoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", thisMSHP.HeatCoilName, errFlag);
     844            0 :                     if (errFlag) {
     845            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
     846            0 :                         ErrorsFound = true;
     847              :                     }
     848              : 
     849              :                     // Get the ReHeat Coil hot water max volume flow rate
     850            0 :                     errFlag = false;
     851            0 :                     thisMSHP.MaxCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisMSHP.HeatCoilName, errFlag);
     852            0 :                     if (errFlag) {
     853            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
     854            0 :                         ErrorsFound = true;
     855              :                     }
     856              : 
     857              :                     // Get the supplemental Heating Coil Inlet Node
     858            0 :                     errFlag = false;
     859            0 :                     HeatingCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", thisMSHP.HeatCoilName, errFlag);
     860            0 :                     thisMSHP.CoilAirInletNode = HeatingCoilInletNode;
     861            0 :                     if (errFlag) {
     862            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
     863            0 :                         ErrorsFound = true;
     864              :                     }
     865              : 
     866              :                     // Get the supplemental Heating Coil Outlet Node
     867            0 :                     errFlag = false;
     868            0 :                     HeatingCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", thisMSHP.HeatCoilName, errFlag);
     869            0 :                     if (errFlag) {
     870            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
     871            0 :                         ErrorsFound = true;
     872              :                     }
     873            0 :                     BranchNodeConnections::SetUpCompSets(state,
     874            0 :                                                          state.dataHVACMultiSpdHP->CurrentModuleObject,
     875              :                                                          thisMSHP.Name,
     876              :                                                          "Coil:Heating:Water",
     877              :                                                          thisMSHP.HeatCoilName,
     878            0 :                                                          state.dataLoopNodes->NodeID(HeatingCoilInletNode),
     879            0 :                                                          state.dataLoopNodes->NodeID(HeatingCoilOutletNode));
     880              :                 }
     881            0 :             } else if (Util::SameString(Alphas(10), "Coil:Heating:Steam")) {
     882            0 :                 thisMSHP.HeatCoilType = HVAC::Coil_HeatingSteam;
     883            0 :                 ValidateComponent(state, Alphas(10), Alphas(11), IsNotOK, state.dataHVACMultiSpdHP->CurrentModuleObject);
     884            0 :                 if (IsNotOK) {
     885            0 :                     ShowContinueError(state, format("...occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
     886            0 :                     ErrorsFound = true;
     887              :                 } else { // mine data from heating coil object
     888              : 
     889            0 :                     thisMSHP.HeatCoilName = Alphas(11);
     890            0 :                     errFlag = false;
     891            0 :                     thisMSHP.HeatCoilNum = SteamCoils::GetSteamCoilIndex(state, Alphas(10), thisMSHP.HeatCoilName, errFlag);
     892            0 :                     if (thisMSHP.HeatCoilNum == 0) {
     893            0 :                         ShowSevereError(
     894              :                             state,
     895            0 :                             format("{} illegal {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, cAlphaFields(10), thisMSHP.HeatCoilName));
     896            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
     897            0 :                         ErrorsFound = true;
     898              :                     }
     899              : 
     900              :                     // Get the supplemental Heating Coil steam inlet node number
     901            0 :                     errFlag = false;
     902            0 :                     thisMSHP.CoilControlNode = SteamCoils::GetCoilAirOutletNode(state, "Coil:Heating:Steam", thisMSHP.HeatCoilName, errFlag);
     903            0 :                     if (errFlag) {
     904            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
     905            0 :                         ErrorsFound = true;
     906              :                     }
     907              : 
     908              :                     // Get the supplemental Heating Coil steam max volume flow rate
     909            0 :                     thisMSHP.MaxCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisMSHP.HeatCoilNum, errFlag);
     910            0 :                     if (thisMSHP.MaxCoilFluidFlow > 0.0) {
     911            0 :                         SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataHVACMultiSpdHP->TempSteamIn, 1.0, routineName);
     912            0 :                         thisMSHP.MaxCoilFluidFlow *= SteamDensity;
     913              :                     }
     914              : 
     915              :                     // Get the supplemental Heating Coil Inlet Node
     916            0 :                     errFlag = false;
     917            0 :                     HeatingCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisMSHP.HeatCoilNum, thisMSHP.HeatCoilName, errFlag);
     918            0 :                     thisMSHP.CoilAirInletNode = HeatingCoilInletNode;
     919            0 :                     if (errFlag) {
     920            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
     921            0 :                         ErrorsFound = true;
     922              :                     }
     923              : 
     924              :                     // Get the supplemental Heating Coil Outlet Node
     925            0 :                     errFlag = false;
     926            0 :                     HeatingCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisMSHP.HeatCoilNum, thisMSHP.HeatCoilName, errFlag);
     927            0 :                     if (errFlag) {
     928            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
     929            0 :                         ErrorsFound = true;
     930              :                     }
     931              : 
     932            0 :                     BranchNodeConnections::SetUpCompSets(state,
     933            0 :                                                          state.dataHVACMultiSpdHP->CurrentModuleObject,
     934              :                                                          thisMSHP.Name,
     935              :                                                          "Coil:Heating:Steam",
     936              :                                                          thisMSHP.HeatCoilName,
     937            0 :                                                          state.dataLoopNodes->NodeID(HeatingCoilInletNode),
     938            0 :                                                          state.dataLoopNodes->NodeID(HeatingCoilOutletNode));
     939              :                 }
     940              :             } else {
     941            0 :                 ShowSevereError(state,
     942            0 :                                 format("The allowed {} are Coil:Heating:DX:MultiSpeed, Coil:Heating:Electric:MultiStage, and "
     943              :                                        "Coil:Heating:Gas:MultiStage  in {} \"{}\"",
     944              :                                        cAlphaFields(10),
     945            0 :                                        state.dataHVACMultiSpdHP->CurrentModuleObject,
     946              :                                        Alphas(1)));
     947            0 :                 ShowContinueError(state, format("The entered {} = \"{}\".", cAlphaFields(10), Alphas(10)));
     948            0 :                 ErrorsFound = true;
     949              :             }
     950              : 
     951              :             // thisMSHP.MinOATCompressor = Numbers(1); // deprecated, now uses coil MinOAT inputs
     952              : 
     953            3 :             if (Util::SameString(Alphas(12), "Coil:Cooling:DX:MultiSpeed")) {
     954            3 :                 thisMSHP.CoolCoilType = MultiSpeedCoolingCoil;
     955            3 :                 thisMSHP.DXCoolCoilName = Alphas(13);
     956            3 :                 if (state.dataInputProcessing->inputProcessor->getObjectItemNum(state, "Coil:Cooling:DX:MultiSpeed", Alphas(13)) <= 0) {
     957            0 :                     ShowSevereError(state, format("Configuration error in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     958            0 :                     ShowContinueError(state, format("{} \"{}\" not found.", cAlphaFields(13), Alphas(13)));
     959            0 :                     ShowContinueError(state, format("{} must be Coil:Cooling:DX:MultiSpeed ", cAlphaFields(12)));
     960            0 :                     ShowFatalError(state,
     961            0 :                                    format("{}Errors found in getting {} input. Preceding condition(s) causes termination.",
     962              :                                           RoutineName,
     963            0 :                                           state.dataHVACMultiSpdHP->CurrentModuleObject));
     964            0 :                     ErrorsFound = true;
     965              :                 }
     966            3 :                 LocalError = false;
     967            3 :                 DXCoils::GetDXCoilIndex(state, thisMSHP.DXCoolCoilName, thisMSHP.DXCoolCoilIndex, LocalError, "Coil:Cooling:DX:MultiSpeed");
     968            3 :                 if (LocalError) {
     969            0 :                     ShowSevereError(state, format("The index of {} is not found \"{}\"", cAlphaFields(13), Alphas(13)));
     970            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     971            0 :                     ErrorsFound = true;
     972            0 :                     LocalError = false;
     973              :                 }
     974            3 :                 CoolingCoilInletNode = DXCoils::GetCoilInletNode(state, Alphas(12), Alphas(13), LocalError);
     975            3 :                 if (LocalError) {
     976            0 :                     ShowSevereError(state, format("The inlet node number of {} is not found \"{}\"", cAlphaFields(13), Alphas(13)));
     977            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     978            0 :                     ErrorsFound = true;
     979            0 :                     LocalError = false;
     980              :                 }
     981            3 :                 CoolingCoilOutletNode = DXCoils::GetCoilOutletNode(state, Alphas(12), Alphas(13), LocalError);
     982            3 :                 if (LocalError) {
     983            0 :                     ShowSevereError(state, format("The outlet node number of {} is not found \"{}\"", cAlphaFields(13), Alphas(13)));
     984            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     985            0 :                     ErrorsFound = true;
     986            0 :                     LocalError = false;
     987              :                 }
     988            3 :                 thisMSHP.MinOATCompressorCooling = DXCoils::GetMinOATCompressor(state, thisMSHP.DXCoolCoilIndex, LocalError);
     989            3 :                 if (LocalError) {
     990            0 :                     ShowContinueError(state,
     991            0 :                                       format("...for cooling coil. Occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
     992            0 :                     LocalError = false;
     993              :                 }
     994              :             } else {
     995            0 :                 ShowSevereError(state,
     996            0 :                                 format("The allowed {} is Coil:Cooling:DX:MultiSpeed in {} \"{}\"",
     997              :                                        cAlphaFields(12),
     998            0 :                                        state.dataHVACMultiSpdHP->CurrentModuleObject,
     999              :                                        Alphas(1)));
    1000            0 :                 ShowContinueError(state, format("The entered {} = \"{}\".", cAlphaFields(12), Alphas(12)));
    1001            0 :                 ErrorsFound = true;
    1002              :             }
    1003            6 :             BranchNodeConnections::SetUpCompSets(state,
    1004            3 :                                                  state.dataHVACMultiSpdHP->CurrentModuleObject,
    1005              :                                                  thisMSHP.Name,
    1006              :                                                  "Coil:Cooling:DX:MultiSpeed",
    1007              :                                                  thisMSHP.DXCoolCoilName,
    1008              :                                                  "UNDEFINED",
    1009              :                                                  "UNDEFINED");
    1010              : 
    1011              :             // Get supplemental heating coil data
    1012            3 :             thisMSHP.SuppHeatCoilName = Alphas(15);
    1013            3 :             if (Util::SameString(Alphas(14), "Coil:Heating:Fuel")) {
    1014            0 :                 thisMSHP.SuppHeatCoilType = SuppHeatingCoilGas;
    1015            0 :                 errFlag = false;
    1016            0 :                 thisMSHP.SuppHeatCoilNum = HeatingCoils::GetHeatingCoilIndex(state, "Coil:Heating:Fuel", Alphas(15), errFlag);
    1017            0 :                 if (thisMSHP.SuppHeatCoilNum <= 0 || errFlag) {
    1018            0 :                     ShowContinueError(state, format("Configuration error in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
    1019            0 :                     ShowContinueError(state, format("{} of type Coil:Heating:Fuel \"{}\" not found.", cAlphaFields(15), Alphas(15)));
    1020            0 :                     ErrorsFound = true;
    1021              :                 }
    1022              : 
    1023              :                 // Get the Supplemental Heating Coil Node Numbers
    1024            0 :                 LocalError = false;
    1025            0 :                 SuppHeatCoilInletNode = HeatingCoils::GetCoilInletNode(state, Alphas(14), Alphas(15), LocalError);
    1026            0 :                 if (LocalError) {
    1027            0 :                     ShowSevereError(state, format("The inlet node number of {} is not found \"{}\"", cAlphaFields(15), Alphas(15)));
    1028            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
    1029            0 :                     ErrorsFound = true;
    1030            0 :                     LocalError = false;
    1031              :                 }
    1032            0 :                 SuppHeatCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, Alphas(14), Alphas(15), LocalError);
    1033            0 :                 if (LocalError) {
    1034            0 :                     ShowSevereError(state, format("The outlet node number of {} is not found \"{}\"", cAlphaFields(15), Alphas(15)));
    1035            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
    1036            0 :                     ErrorsFound = true;
    1037            0 :                     LocalError = false;
    1038              :                 }
    1039              : 
    1040              :                 // Get supplemental heating coil capacity to see if it is autosize
    1041            0 :                 thisMSHP.DesignSuppHeatingCapacity = HeatingCoils::GetCoilCapacity(state, Alphas(14), Alphas(15), LocalError);
    1042            0 :                 if (LocalError) {
    1043            0 :                     ShowSevereError(state, format("The capacity {} is not found \"{}\"", cAlphaFields(15), Alphas(15)));
    1044            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
    1045            0 :                     ErrorsFound = true;
    1046            0 :                     LocalError = false;
    1047              :                 }
    1048            0 :                 BranchNodeConnections::SetUpCompSets(state,
    1049            0 :                                                      state.dataHVACMultiSpdHP->CurrentModuleObject,
    1050              :                                                      thisMSHP.Name,
    1051              :                                                      "Coil:Heating:Fuel",
    1052              :                                                      thisMSHP.SuppHeatCoilName,
    1053              :                                                      "UNDEFINED",
    1054              :                                                      "UNDEFINED");
    1055              :             }
    1056            3 :             if (Util::SameString(Alphas(14), "Coil:Heating:Electric")) {
    1057            3 :                 thisMSHP.SuppHeatCoilType = SuppHeatingCoilElec;
    1058            3 :                 errFlag = false;
    1059            6 :                 thisMSHP.SuppHeatCoilNum = HeatingCoils::GetHeatingCoilIndex(state, "Coil:Heating:Electric", Alphas(15), errFlag);
    1060            3 :                 if (thisMSHP.SuppHeatCoilNum <= 0 || errFlag) {
    1061            0 :                     ShowContinueError(state, format("Configuration error in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
    1062            0 :                     ShowContinueError(state, format("{} of type Coil:Heating:Electric \"{}\" not found.", cAlphaFields(15), Alphas(15)));
    1063            0 :                     ErrorsFound = true;
    1064              :                 }
    1065              : 
    1066              :                 // Get the Supplemental Heating Coil Node Numbers
    1067            3 :                 LocalError = false;
    1068            3 :                 SuppHeatCoilInletNode = HeatingCoils::GetCoilInletNode(state, Alphas(14), Alphas(15), LocalError);
    1069            3 :                 if (LocalError) {
    1070            0 :                     ShowSevereError(state, format("The inlet node number of {} is not found \"{}\"", cAlphaFields(15), Alphas(15)));
    1071            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
    1072            0 :                     ErrorsFound = true;
    1073            0 :                     LocalError = false;
    1074              :                 }
    1075            3 :                 SuppHeatCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, Alphas(14), Alphas(15), LocalError);
    1076            3 :                 if (LocalError) {
    1077            0 :                     ShowSevereError(state, format("The outlet node number of {} is not found \"{}\"", cAlphaFields(15), Alphas(15)));
    1078            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
    1079            0 :                     ErrorsFound = true;
    1080            0 :                     LocalError = false;
    1081              :                 }
    1082              : 
    1083              :                 // Get supplemental heating coil capacity to see if it is autosize
    1084            3 :                 thisMSHP.DesignSuppHeatingCapacity = HeatingCoils::GetCoilCapacity(state, Alphas(14), Alphas(15), LocalError);
    1085            3 :                 if (LocalError) {
    1086            0 :                     ShowSevereError(state, format("The capacity {} is not found \"{}\"", cAlphaFields(15), Alphas(15)));
    1087            0 :                     ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
    1088            0 :                     ErrorsFound = true;
    1089            0 :                     LocalError = false;
    1090              :                 }
    1091              : 
    1092            6 :                 BranchNodeConnections::SetUpCompSets(state,
    1093            3 :                                                      state.dataHVACMultiSpdHP->CurrentModuleObject,
    1094              :                                                      thisMSHP.Name,
    1095              :                                                      "Coil:Heating:Electric",
    1096              :                                                      thisMSHP.SuppHeatCoilName,
    1097              :                                                      "UNDEFINED",
    1098              :                                                      "UNDEFINED");
    1099              :             }
    1100              : 
    1101            3 :             if (Util::SameString(Alphas(14), "Coil:Heating:Water")) {
    1102            0 :                 thisMSHP.SuppHeatCoilType = HVAC::Coil_HeatingWater;
    1103            0 :                 ValidateComponent(state, Alphas(14), thisMSHP.SuppHeatCoilName, IsNotOK, state.dataHVACMultiSpdHP->CurrentModuleObject);
    1104            0 :                 if (IsNotOK) {
    1105            0 :                     ShowContinueError(state, format("...occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
    1106            0 :                     ErrorsFound = true;
    1107              :                 } else { // mine data from heating coil object
    1108              : 
    1109              :                     // Get the Heating Coil water Inlet or control Node number
    1110            0 :                     errFlag = false;
    1111            0 :                     thisMSHP.SuppCoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", thisMSHP.SuppHeatCoilName, errFlag);
    1112            0 :                     if (errFlag) {
    1113            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1114            0 :                         ErrorsFound = true;
    1115              :                     }
    1116              : 
    1117              :                     // Get the ReHeat Coil hot water max volume flow rate
    1118            0 :                     errFlag = false;
    1119            0 :                     thisMSHP.MaxSuppCoilFluidFlow =
    1120            0 :                         WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisMSHP.SuppHeatCoilName, errFlag);
    1121            0 :                     if (errFlag) {
    1122            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1123            0 :                         ErrorsFound = true;
    1124              :                     }
    1125              : 
    1126              :                     // Get the Supplemental Heating Coil Inlet Node
    1127            0 :                     errFlag = false;
    1128            0 :                     SuppHeatCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", thisMSHP.SuppHeatCoilName, errFlag);
    1129            0 :                     thisMSHP.SuppCoilAirInletNode = SuppHeatCoilInletNode;
    1130            0 :                     if (errFlag) {
    1131            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1132            0 :                         ErrorsFound = true;
    1133              :                     }
    1134              : 
    1135              :                     // Get the Supplemental Heating Coil Outlet Node
    1136            0 :                     errFlag = false;
    1137            0 :                     SuppHeatCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", thisMSHP.SuppHeatCoilName, errFlag);
    1138            0 :                     thisMSHP.SuppCoilAirOutletNode = SuppHeatCoilOutletNode;
    1139            0 :                     if (errFlag) {
    1140            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1141            0 :                         ErrorsFound = true;
    1142              :                     }
    1143            0 :                     BranchNodeConnections::SetUpCompSets(state,
    1144            0 :                                                          state.dataHVACMultiSpdHP->CurrentModuleObject,
    1145              :                                                          thisMSHP.Name,
    1146              :                                                          "Coil:Heating:Water",
    1147              :                                                          thisMSHP.SuppHeatCoilName,
    1148            0 :                                                          state.dataLoopNodes->NodeID(SuppHeatCoilInletNode),
    1149            0 :                                                          state.dataLoopNodes->NodeID(SuppHeatCoilOutletNode));
    1150              :                 }
    1151              :             }
    1152            3 :             if (Util::SameString(Alphas(14), "Coil:Heating:Steam")) {
    1153            0 :                 thisMSHP.SuppHeatCoilType = HVAC::Coil_HeatingSteam;
    1154            0 :                 ValidateComponent(state, Alphas(14), thisMSHP.SuppHeatCoilName, IsNotOK, state.dataHVACMultiSpdHP->CurrentModuleObject);
    1155            0 :                 if (IsNotOK) {
    1156            0 :                     ShowContinueError(state, format("...occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1157            0 :                     ErrorsFound = true;
    1158              :                 } else { // mine data from heating coil object
    1159              : 
    1160            0 :                     errFlag = false;
    1161            0 :                     thisMSHP.SuppHeatCoilNum = SteamCoils::GetSteamCoilIndex(state, Alphas(14), thisMSHP.SuppHeatCoilName, errFlag);
    1162            0 :                     if (thisMSHP.SuppHeatCoilNum == 0) {
    1163            0 :                         ShowSevereError(
    1164              :                             state,
    1165            0 :                             format("{} illegal {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, cAlphaFields(14), thisMSHP.SuppHeatCoilName));
    1166            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1167            0 :                         ErrorsFound = true;
    1168              :                     }
    1169              : 
    1170              :                     // Get the Supplemental Heating Coil steam inlet node number
    1171            0 :                     errFlag = false;
    1172            0 :                     thisMSHP.SuppCoilControlNode = SteamCoils::GetCoilAirOutletNode(state, "Coil:Heating:Steam", thisMSHP.SuppHeatCoilName, errFlag);
    1173            0 :                     if (errFlag) {
    1174            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1175            0 :                         ErrorsFound = true;
    1176              :                     }
    1177              : 
    1178              :                     // Get the Supplemental Heating Coil steam max volume flow rate
    1179            0 :                     thisMSHP.MaxSuppCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisMSHP.SuppHeatCoilNum, errFlag);
    1180            0 :                     if (thisMSHP.MaxSuppCoilFluidFlow > 0.0) {
    1181            0 :                         SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataHVACMultiSpdHP->TempSteamIn, 1.0, routineName);
    1182            0 :                         thisMSHP.MaxSuppCoilFluidFlow *= SteamDensity;
    1183              :                     }
    1184              : 
    1185              :                     // Get the Supplemental Heating Coil Inlet Node
    1186            0 :                     errFlag = false;
    1187            0 :                     SuppHeatCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisMSHP.SuppHeatCoilNum, thisMSHP.SuppHeatCoilName, errFlag);
    1188            0 :                     thisMSHP.SuppCoilAirInletNode = SuppHeatCoilInletNode;
    1189            0 :                     if (errFlag) {
    1190            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1191            0 :                         ErrorsFound = true;
    1192              :                     }
    1193              : 
    1194              :                     // Get the Supplemental Heating Coil Outlet Node
    1195            0 :                     errFlag = false;
    1196            0 :                     SuppHeatCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisMSHP.SuppHeatCoilNum, thisMSHP.SuppHeatCoilName, errFlag);
    1197            0 :                     thisMSHP.SuppCoilAirOutletNode = SuppHeatCoilOutletNode;
    1198            0 :                     if (errFlag) {
    1199            0 :                         ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1200            0 :                         ErrorsFound = true;
    1201              :                     }
    1202              : 
    1203            0 :                     BranchNodeConnections::SetUpCompSets(state,
    1204            0 :                                                          state.dataHVACMultiSpdHP->CurrentModuleObject,
    1205              :                                                          thisMSHP.Name,
    1206              :                                                          "Coil:Heating:Steam",
    1207              :                                                          thisMSHP.SuppHeatCoilName,
    1208            0 :                                                          state.dataLoopNodes->NodeID(SuppHeatCoilInletNode),
    1209            0 :                                                          state.dataLoopNodes->NodeID(SuppHeatCoilOutletNode));
    1210              :                 }
    1211              :             }
    1212              : 
    1213            3 :             if (thisMSHP.SuppHeatCoilType == 0) {
    1214            0 :                 ShowSevereError(state,
    1215            0 :                                 format("{}, \"{}\", {} is not allowed = {}",
    1216            0 :                                        state.dataHVACMultiSpdHP->CurrentModuleObject,
    1217            0 :                                        thisMSHP.Name,
    1218              :                                        cAlphaFields(14),
    1219              :                                        Alphas(14)));
    1220            0 :                 ShowContinueError(state, "Valid choices are Coil:Heating:Fuel,Coil:Heating:Electric,Coil:Heating:Steam,or Coil:Heating:Water");
    1221            0 :                 ErrorsFound = true;
    1222              :             }
    1223              : 
    1224            3 :             thisMSHP.SuppMaxAirTemp = Numbers(2);
    1225            3 :             thisMSHP.SuppMaxOATemp = Numbers(3);
    1226            3 :             if (thisMSHP.SuppMaxOATemp > 21.0) {
    1227            0 :                 ShowSevereError(
    1228              :                     state,
    1229            0 :                     format("{}, \"{}\", {} is greater than 21.0", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name, cNumericFields(3)));
    1230            0 :                 ShowContinueError(state, format("The input value is {:.2R}", Numbers(3)));
    1231            0 :                 ErrorsFound = true;
    1232              :             }
    1233            6 :             OutputReportPredefined::PreDefTableEntry(
    1234            3 :                 state, state.dataOutRptPredefined->pdchDXHeatCoilSuppHiT, thisMSHP.DXHeatCoilName, thisMSHP.SuppMaxOATemp);
    1235              : 
    1236            3 :             thisMSHP.AuxOnCyclePower = Numbers(4);
    1237            3 :             thisMSHP.AuxOffCyclePower = Numbers(5);
    1238            3 :             if (thisMSHP.AuxOnCyclePower < 0.0) {
    1239            0 :                 ShowSevereError(state,
    1240            0 :                                 format("{}, \"{}\", A negative value for {} is not allowed ",
    1241            0 :                                        state.dataHVACMultiSpdHP->CurrentModuleObject,
    1242            0 :                                        thisMSHP.Name,
    1243              :                                        cNumericFields(4)));
    1244            0 :                 ErrorsFound = true;
    1245              :             }
    1246            3 :             if (thisMSHP.AuxOffCyclePower < 0.0) {
    1247            0 :                 ShowSevereError(state,
    1248            0 :                                 format("{}, \"{}\", A negative value for {} is not allowed ",
    1249            0 :                                        state.dataHVACMultiSpdHP->CurrentModuleObject,
    1250            0 :                                        thisMSHP.Name,
    1251              :                                        cNumericFields(5)));
    1252            0 :                 ErrorsFound = true;
    1253              :             }
    1254              : 
    1255              :             // Heat recovery
    1256            3 :             thisMSHP.DesignHeatRecFlowRate = Numbers(6);
    1257            3 :             if (thisMSHP.DesignHeatRecFlowRate > 0.0) {
    1258            0 :                 thisMSHP.HeatRecActive = true;
    1259            0 :                 thisMSHP.DesignHeatRecMassFlowRate = Psychrometrics::RhoH2O(Constant::HWInitConvTemp) * thisMSHP.DesignHeatRecFlowRate;
    1260            0 :                 thisMSHP.HeatRecInletNodeNum = GetOnlySingleNode(state,
    1261            0 :                                                                  Alphas(16),
    1262              :                                                                  ErrorsFound,
    1263              :                                                                  DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed,
    1264            0 :                                                                  Alphas(1),
    1265              :                                                                  DataLoopNode::NodeFluidType::Water,
    1266              :                                                                  DataLoopNode::ConnectionType::Inlet,
    1267              :                                                                  NodeInputManager::CompFluidStream::Tertiary,
    1268              :                                                                  DataLoopNode::ObjectIsNotParent);
    1269            0 :                 if (thisMSHP.HeatRecInletNodeNum == 0) {
    1270            0 :                     ShowSevereError(
    1271            0 :                         state, format("{}, \"{}\", Missing {}.", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name, cAlphaFields(16)));
    1272            0 :                     ErrorsFound = true;
    1273              :                 }
    1274            0 :                 thisMSHP.HeatRecOutletNodeNum = GetOnlySingleNode(state,
    1275            0 :                                                                   Alphas(17),
    1276              :                                                                   ErrorsFound,
    1277              :                                                                   DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed,
    1278            0 :                                                                   Alphas(1),
    1279              :                                                                   DataLoopNode::NodeFluidType::Water,
    1280              :                                                                   DataLoopNode::ConnectionType::Outlet,
    1281              :                                                                   NodeInputManager::CompFluidStream::Tertiary,
    1282              :                                                                   DataLoopNode::ObjectIsNotParent);
    1283            0 :                 if (thisMSHP.HeatRecOutletNodeNum == 0) {
    1284            0 :                     ShowSevereError(
    1285            0 :                         state, format("{}, \"{}\", Missing {}.", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name, cAlphaFields(17)));
    1286            0 :                     ErrorsFound = true;
    1287              :                 }
    1288            0 :                 BranchNodeConnections::TestCompSet(
    1289            0 :                     state, state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1), Alphas(16), Alphas(17), "MSHP Heat Recovery Nodes");
    1290            0 :                 DXCoils::SetMSHPDXCoilHeatRecoveryFlag(state, thisMSHP.DXCoolCoilIndex);
    1291            0 :                 if (thisMSHP.DXHeatCoilIndex > 0) {
    1292            0 :                     DXCoils::SetMSHPDXCoilHeatRecoveryFlag(state, thisMSHP.DXHeatCoilIndex);
    1293              :                 }
    1294              :             } else {
    1295            3 :                 thisMSHP.HeatRecActive = false;
    1296            3 :                 thisMSHP.DesignHeatRecMassFlowRate = 0.0;
    1297            3 :                 thisMSHP.HeatRecInletNodeNum = 0;
    1298            3 :                 thisMSHP.HeatRecOutletNodeNum = 0;
    1299            3 :                 if (!lAlphaBlanks(16) || !lAlphaBlanks(17)) {
    1300            0 :                     ShowWarningError(state,
    1301            0 :                                      format("Since {} = 0.0, heat recovery is inactive for {} = {}",
    1302              :                                             cNumericFields(6),
    1303            0 :                                             state.dataHVACMultiSpdHP->CurrentModuleObject,
    1304              :                                             Alphas(1)));
    1305            0 :                     ShowContinueError(state, format("However, {} or {} was specified.", cAlphaFields(16), cAlphaFields(17)));
    1306              :                 }
    1307              :             }
    1308            3 :             thisMSHP.MaxHeatRecOutletTemp = Numbers(7);
    1309            3 :             if (thisMSHP.MaxHeatRecOutletTemp < 0.0) {
    1310            0 :                 ShowSevereError(state,
    1311            0 :                                 format("{}, \"{}\", The value for {} is below 0.0",
    1312            0 :                                        state.dataHVACMultiSpdHP->CurrentModuleObject,
    1313            0 :                                        thisMSHP.Name,
    1314              :                                        cNumericFields(7)));
    1315            0 :                 ErrorsFound = true;
    1316              :             }
    1317            3 :             if (thisMSHP.MaxHeatRecOutletTemp > 100.0) {
    1318            0 :                 ShowSevereError(state,
    1319            0 :                                 format("{}, \"{}\", The value for {} is above 100.0",
    1320            0 :                                        state.dataHVACMultiSpdHP->CurrentModuleObject,
    1321            0 :                                        thisMSHP.Name,
    1322              :                                        cNumericFields(7)));
    1323            0 :                 ErrorsFound = true;
    1324              :             }
    1325              : 
    1326            3 :             thisMSHP.IdleVolumeAirRate = Numbers(8);
    1327            3 :             if (thisMSHP.IdleVolumeAirRate < 0.0 && thisMSHP.IdleVolumeAirRate != DataSizing::AutoSize) {
    1328            0 :                 ShowSevereError(
    1329              :                     state,
    1330            0 :                     format(
    1331            0 :                         "{}, \"{}\", {} cannot be less than zero.", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name, cNumericFields(8)));
    1332            0 :                 ErrorsFound = true;
    1333              :             }
    1334              : 
    1335              :             //     AirFlowControl only valid if fan opmode = FanOp::Continuous
    1336            3 :             if (thisMSHP.IdleVolumeAirRate == 0.0) {
    1337            0 :                 thisMSHP.AirFlowControl = AirflowControl::UseCompressorOnFlow;
    1338              :             } else {
    1339            3 :                 thisMSHP.AirFlowControl = AirflowControl::UseCompressorOffFlow;
    1340              :             }
    1341              : 
    1342              :             //   Initialize last mode of compressor operation
    1343            3 :             thisMSHP.LastMode = ModeOfOperation::HeatingMode;
    1344              : 
    1345            3 :             thisMSHP.NumOfSpeedHeating = Numbers(9);
    1346            3 :             if (thisMSHP.NumOfSpeedHeating < 2 || thisMSHP.NumOfSpeedHeating > 4) {
    1347            0 :                 if (thisMSHP.HeatCoilType == MultiSpeedHeatingCoil) {
    1348            0 :                     ShowSevereError(state,
    1349            0 :                                     format("{}, The maximum {} is 4, and the minimum number is 2",
    1350            0 :                                            state.dataHVACMultiSpdHP->CurrentModuleObject,
    1351              :                                            cNumericFields(9)));
    1352            0 :                     ShowContinueError(state, format("The input value is {:.0R}", Numbers(9)));
    1353            0 :                     ErrorsFound = true;
    1354              :                 }
    1355              :             }
    1356            3 :             thisMSHP.NumOfSpeedCooling = Numbers(10);
    1357            3 :             if (thisMSHP.NumOfSpeedCooling < 2 || thisMSHP.NumOfSpeedCooling > 4) {
    1358            0 :                 ShowSevereError(state,
    1359            0 :                                 format("{}, The maximum {} is 4, and the minimum number is 2",
    1360            0 :                                        state.dataHVACMultiSpdHP->CurrentModuleObject,
    1361              :                                        cNumericFields(10)));
    1362            0 :                 ShowContinueError(state, format("The input value is {:.0R}", Numbers(10)));
    1363            0 :                 ErrorsFound = true;
    1364              :             }
    1365              : 
    1366              :             // Generate a dynamic array for heating
    1367            3 :             if (thisMSHP.NumOfSpeedHeating > 0) {
    1368            3 :                 thisMSHP.HeatMassFlowRate.allocate(thisMSHP.NumOfSpeedHeating);
    1369            3 :                 thisMSHP.HeatVolumeFlowRate.allocate(thisMSHP.NumOfSpeedHeating);
    1370            3 :                 thisMSHP.HeatingSpeedRatio.allocate(thisMSHP.NumOfSpeedHeating);
    1371            3 :                 thisMSHP.HeatingSpeedRatio = 1.0;
    1372            9 :                 for (i = 1; i <= thisMSHP.NumOfSpeedHeating; ++i) {
    1373            6 :                     thisMSHP.HeatVolumeFlowRate(i) = Numbers(10 + i);
    1374            6 :                     if (thisMSHP.HeatCoilType == MultiSpeedHeatingCoil) {
    1375            6 :                         if (thisMSHP.HeatVolumeFlowRate(i) <= 0.0 && thisMSHP.HeatVolumeFlowRate(i) != DataSizing::AutoSize) {
    1376            0 :                             ShowSevereError(state,
    1377            0 :                                             format("{}, \"{}\", {} must be greater than zero.",
    1378            0 :                                                    state.dataHVACMultiSpdHP->CurrentModuleObject,
    1379            0 :                                                    thisMSHP.Name,
    1380              :                                                    cNumericFields(10 + i)));
    1381            0 :                             ErrorsFound = true;
    1382              :                         }
    1383              :                     }
    1384              :                 }
    1385              :                 // Ensure flow rate at high speed should be greater or equal to the flow rate at low speed
    1386            6 :                 for (i = 2; i <= thisMSHP.NumOfSpeedHeating; ++i) {
    1387            3 :                     if (thisMSHP.HeatVolumeFlowRate(i) == DataSizing::AutoSize) {
    1388            0 :                         continue;
    1389              :                     }
    1390            3 :                     Found = false;
    1391            3 :                     for (j = i - 1; j >= 1; --j) {
    1392            3 :                         if (thisMSHP.HeatVolumeFlowRate(i) != DataSizing::AutoSize) {
    1393            3 :                             Found = true;
    1394            3 :                             break;
    1395              :                         }
    1396              :                     }
    1397            3 :                     if (Found) {
    1398            3 :                         if (thisMSHP.HeatVolumeFlowRate(i) < thisMSHP.HeatVolumeFlowRate(j)) {
    1399            0 :                             ShowSevereError(
    1400              :                                 state,
    1401            0 :                                 format("{}, \"{}\", {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name, cNumericFields(10 + i)));
    1402            0 :                             ShowContinueError(state, format(" cannot be less than {}", cNumericFields(10 + j)));
    1403            0 :                             ErrorsFound = true;
    1404              :                         }
    1405              :                     }
    1406              :                 }
    1407              :             }
    1408              : 
    1409            3 :             if (state.dataGlobal->DoCoilDirectSolutions) {
    1410            0 :                 int MaxNumber = std::max(thisMSHP.NumOfSpeedCooling, thisMSHP.NumOfSpeedHeating);
    1411            0 :                 thisMSHP.FullOutput.allocate(MaxNumber);
    1412            0 :                 DXCoils::DisableLatentDegradation(state, thisMSHP.DXCoolCoilIndex);
    1413              :             }
    1414              :             // Generate a dynamic array for cooling
    1415            3 :             if (thisMSHP.NumOfSpeedCooling > 0) {
    1416            3 :                 thisMSHP.CoolMassFlowRate.allocate(thisMSHP.NumOfSpeedCooling);
    1417            3 :                 thisMSHP.CoolVolumeFlowRate.allocate(thisMSHP.NumOfSpeedCooling);
    1418            3 :                 thisMSHP.CoolingSpeedRatio.allocate(thisMSHP.NumOfSpeedCooling);
    1419            3 :                 thisMSHP.CoolingSpeedRatio = 1.0;
    1420            9 :                 for (i = 1; i <= thisMSHP.NumOfSpeedCooling; ++i) {
    1421            6 :                     thisMSHP.CoolVolumeFlowRate(i) = Numbers(14 + i);
    1422            6 :                     if (thisMSHP.CoolVolumeFlowRate(i) <= 0.0 && thisMSHP.CoolVolumeFlowRate(i) != DataSizing::AutoSize) {
    1423            0 :                         ShowSevereError(state,
    1424            0 :                                         format("{}, \"{}\", {} must be greater than zero.",
    1425            0 :                                                state.dataHVACMultiSpdHP->CurrentModuleObject,
    1426            0 :                                                thisMSHP.Name,
    1427              :                                                cNumericFields(14 + i)));
    1428            0 :                         ErrorsFound = true;
    1429              :                     }
    1430              :                 }
    1431              :                 // Ensure flow rate at high speed should be greater or equal to the flow rate at low speed
    1432            6 :                 for (i = 2; i <= thisMSHP.NumOfSpeedCooling; ++i) {
    1433            3 :                     if (thisMSHP.CoolVolumeFlowRate(i) == DataSizing::AutoSize) {
    1434            0 :                         continue;
    1435              :                     }
    1436            3 :                     Found = false;
    1437            3 :                     for (j = i - 1; j >= 1; --j) {
    1438            3 :                         if (thisMSHP.CoolVolumeFlowRate(i) != DataSizing::AutoSize) {
    1439            3 :                             Found = true;
    1440            3 :                             break;
    1441              :                         }
    1442              :                     }
    1443            3 :                     if (Found) {
    1444            3 :                         if (thisMSHP.CoolVolumeFlowRate(i) < thisMSHP.CoolVolumeFlowRate(j)) {
    1445            0 :                             ShowSevereError(
    1446              :                                 state,
    1447            0 :                                 format("{}, \"{}\", {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name, cNumericFields(14 + i)));
    1448            0 :                             ShowContinueError(state, format(" cannot be less than {}", cNumericFields(14 + j)));
    1449            0 :                             ErrorsFound = true;
    1450              :                         }
    1451              :                     }
    1452              :                 }
    1453              :             }
    1454              : 
    1455              :             // Check node integrity
    1456            3 :             if (thisMSHP.fanPlace == HVAC::FanPlace::BlowThru) {
    1457            3 :                 if (thisMSHP.FanInletNode != thisMSHP.AirInletNodeNum) {
    1458            0 :                     ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1459            0 :                     ShowContinueError(
    1460            0 :                         state, format("When a blow through fan is specified, the fan inlet node name must be the same as the {}", cAlphaFields(3)));
    1461            0 :                     ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(thisMSHP.FanInletNode)));
    1462            0 :                     ShowContinueError(state, format("...{} = {}", cAlphaFields(3), state.dataLoopNodes->NodeID(thisMSHP.AirInletNodeNum)));
    1463            0 :                     ErrorsFound = true;
    1464              :                 }
    1465            3 :                 if (thisMSHP.FanOutletNode != CoolingCoilInletNode) {
    1466            0 :                     ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1467            0 :                     ShowContinueError(
    1468              :                         state,
    1469              :                         "When a blow through fan is specified, the fan outlet node name must be the same as the cooling coil inlet node name.");
    1470            0 :                     ShowContinueError(state, format("...Fan outlet node name         = {}", state.dataLoopNodes->NodeID(thisMSHP.FanOutletNode)));
    1471            0 :                     ShowContinueError(state, format("...Cooling coil inlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    1472            0 :                     ErrorsFound = true;
    1473              :                 }
    1474            3 :                 if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    1475            0 :                     ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1476            0 :                     ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
    1477            0 :                     ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    1478            0 :                     ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    1479            0 :                     ErrorsFound = true;
    1480              :                 }
    1481            3 :                 if (HeatingCoilOutletNode != SuppHeatCoilInletNode) {
    1482            0 :                     ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1483            0 :                     ShowContinueError(state,
    1484              :                                       "When a blow through fan is specified, the heating coil outlet node name must be the same as the reheat coil "
    1485              :                                       "inlet node name.");
    1486            0 :                     ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    1487            0 :                     ShowContinueError(state, format("...Reheat coil inlet node name   = {}", state.dataLoopNodes->NodeID(SuppHeatCoilInletNode)));
    1488            0 :                     ErrorsFound = true;
    1489              :                 }
    1490            3 :                 if (SuppHeatCoilOutletNode != thisMSHP.AirOutletNodeNum) {
    1491            0 :                     ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1492            0 :                     ShowContinueError(state, format("The supplemental heating coil outlet node name must be the same as the {}", cAlphaFields(4)));
    1493            0 :                     ShowContinueError(
    1494            0 :                         state, format("...Supplemental heating coil outlet node name   = {}", state.dataLoopNodes->NodeID(SuppHeatCoilOutletNode)));
    1495            0 :                     ShowContinueError(state, format("...{} = {}", cAlphaFields(4), state.dataLoopNodes->NodeID(thisMSHP.AirOutletNodeNum)));
    1496            0 :                     ErrorsFound = true;
    1497              :                 }
    1498              :             } else {
    1499            0 :                 if (CoolingCoilInletNode != thisMSHP.AirInletNodeNum) {
    1500            0 :                     ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1501            0 :                     ShowContinueError(
    1502              :                         state,
    1503            0 :                         format("When a draw through fan is specified, the cooling coil inlet node name must be the same as the {}", cAlphaFields(3)));
    1504            0 :                     ShowContinueError(state, format("...Cooling coil inlet node name  = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
    1505            0 :                     ShowContinueError(state, format("...{} = {}", cAlphaFields(3), state.dataLoopNodes->NodeID(thisMSHP.AirInletNodeNum)));
    1506            0 :                     ErrorsFound = true;
    1507              :                 }
    1508            0 :                 if (CoolingCoilOutletNode != HeatingCoilInletNode) {
    1509            0 :                     ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1510            0 :                     ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
    1511            0 :                     ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
    1512            0 :                     ShowContinueError(state, format("...Heating coil inlet node name  = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
    1513            0 :                     ErrorsFound = true;
    1514              :                 }
    1515            0 :                 if (HeatingCoilOutletNode != thisMSHP.FanInletNode) {
    1516            0 :                     ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1517            0 :                     ShowContinueError(
    1518              :                         state,
    1519              :                         "When a draw through fan is specified, the heating coil outlet node name must be the same as the fan inlet node name.");
    1520            0 :                     ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
    1521            0 :                     ShowContinueError(state, format("...Fan inlet node name           = {}", state.dataLoopNodes->NodeID(thisMSHP.FanInletNode)));
    1522            0 :                     ErrorsFound = true;
    1523              :                 }
    1524            0 :                 if (thisMSHP.FanOutletNode != SuppHeatCoilInletNode) {
    1525            0 :                     ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1526            0 :                     ShowContinueError(
    1527              :                         state, "When a draw through fan is specified, the fan outlet node name must be the same as the reheat coil inlet node name.");
    1528            0 :                     ShowContinueError(state, format("...Fan outlet node name        = {}", state.dataLoopNodes->NodeID(thisMSHP.FanOutletNode)));
    1529            0 :                     ShowContinueError(state, format("...Reheat coil inlet node name = {}", state.dataLoopNodes->NodeID(SuppHeatCoilInletNode)));
    1530            0 :                     ErrorsFound = true;
    1531              :                 }
    1532            0 :                 if (SuppHeatCoilOutletNode != thisMSHP.AirOutletNodeNum) {
    1533            0 :                     ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1534            0 :                     ShowContinueError(state, format("The reheat coil outlet node name must be the same as the {}", cAlphaFields(4)));
    1535            0 :                     ShowContinueError(state, format("...Reheat coil outlet node name   = {}", state.dataLoopNodes->NodeID(SuppHeatCoilOutletNode)));
    1536            0 :                     ShowContinueError(state, format("...{} = {}", cAlphaFields(4), state.dataLoopNodes->NodeID(thisMSHP.AirOutletNodeNum)));
    1537            0 :                     ErrorsFound = true;
    1538              :                 }
    1539              :             }
    1540              : 
    1541              :             // Ensure the numbers of speeds defined in the parent object are equal to the numbers defined in coil objects
    1542            3 :             if (thisMSHP.HeatCoilType == MultiSpeedHeatingCoil) {
    1543            3 :                 i = DXCoils::GetDXCoilNumberOfSpeeds(state, Alphas(10), Alphas(11), ErrorsFound);
    1544            3 :                 if (thisMSHP.NumOfSpeedHeating != i) {
    1545            0 :                     ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1546            0 :                     ShowContinueError(
    1547            0 :                         state, format("The {} is not equal to the number defined in {} = {}", cNumericFields(9), cAlphaFields(11), Alphas(11)));
    1548            0 :                     ErrorsFound = true;
    1549              :                 }
    1550            0 :             } else if (thisMSHP.HeatCoilType == HVAC::Coil_HeatingElectric_MultiStage || thisMSHP.HeatCoilType == HVAC::Coil_HeatingGas_MultiStage) {
    1551            0 :                 i = HeatingCoils::GetHeatingCoilNumberOfStages(state, Alphas(10), Alphas(11), ErrorsFound);
    1552            0 :                 if (thisMSHP.NumOfSpeedHeating != i) {
    1553            0 :                     ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1554            0 :                     ShowContinueError(
    1555            0 :                         state, format("The {} is not equal to the number defined in {} = {}", cNumericFields(9), cAlphaFields(11), Alphas(11)));
    1556            0 :                     ErrorsFound = true;
    1557              :                 }
    1558              :             }
    1559            3 :             i = DXCoils::GetDXCoilNumberOfSpeeds(state, Alphas(12), Alphas(13), ErrorsFound);
    1560            3 :             if (thisMSHP.NumOfSpeedCooling != i) {
    1561            0 :                 ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
    1562            0 :                 ShowContinueError(state,
    1563            0 :                                   format("The {} is not equal to the number defined in {} = {}", cNumericFields(10), cAlphaFields(13), Alphas(13)));
    1564            0 :                 ErrorsFound = true;
    1565              :             }
    1566              :         }
    1567              : 
    1568            2 :         if (ErrorsFound) {
    1569            0 :             ShowFatalError(state,
    1570            0 :                            format("{}Errors found in getting {} input.  Preceding condition(s) causes termination.",
    1571              :                                   RoutineName,
    1572            0 :                                   state.dataHVACMultiSpdHP->CurrentModuleObject));
    1573              :         }
    1574              :         // End of multispeed heat pump
    1575              : 
    1576            2 :         int MSHPNum = 0;
    1577            5 :         for (auto &thisMSHeatPump : state.dataHVACMultiSpdHP->MSHeatPump) {
    1578            3 :             auto &thisMSHPReport = state.dataHVACMultiSpdHP->MSHeatPumpReport(++MSHPNum);
    1579              :             // Setup Report Variables for MSHP Equipment
    1580            6 :             SetupOutputVariable(state,
    1581              :                                 "Unitary System Ancillary Electricity Rate",
    1582              :                                 Constant::Units::W,
    1583            3 :                                 thisMSHeatPump.AuxElecPower,
    1584              :                                 OutputProcessor::TimeStepType::System,
    1585              :                                 OutputProcessor::StoreType::Average,
    1586            3 :                                 thisMSHeatPump.Name);
    1587            6 :             SetupOutputVariable(state,
    1588              :                                 "Unitary System Cooling Ancillary Electricity Energy",
    1589              :                                 Constant::Units::J,
    1590            3 :                                 thisMSHPReport.AuxElecCoolConsumption,
    1591              :                                 OutputProcessor::TimeStepType::System,
    1592              :                                 OutputProcessor::StoreType::Sum,
    1593            3 :                                 thisMSHeatPump.Name,
    1594              :                                 Constant::eResource::Electricity,
    1595              :                                 OutputProcessor::Group::HVAC,
    1596              :                                 OutputProcessor::EndUseCat::Cooling);
    1597            6 :             SetupOutputVariable(state,
    1598              :                                 "Unitary System Heating Ancillary Electricity Energy",
    1599              :                                 Constant::Units::J,
    1600            3 :                                 thisMSHPReport.AuxElecHeatConsumption,
    1601              :                                 OutputProcessor::TimeStepType::System,
    1602              :                                 OutputProcessor::StoreType::Sum,
    1603            3 :                                 thisMSHeatPump.Name,
    1604              :                                 Constant::eResource::Electricity,
    1605              :                                 OutputProcessor::Group::HVAC,
    1606              :                                 OutputProcessor::EndUseCat::Heating);
    1607            6 :             SetupOutputVariable(state,
    1608              :                                 "Unitary System Fan Part Load Ratio",
    1609              :                                 Constant::Units::None,
    1610            3 :                                 thisMSHeatPump.FanPartLoadRatio,
    1611              :                                 OutputProcessor::TimeStepType::System,
    1612              :                                 OutputProcessor::StoreType::Average,
    1613            3 :                                 thisMSHeatPump.Name);
    1614            6 :             SetupOutputVariable(state,
    1615              :                                 "Unitary System Compressor Part Load Ratio",
    1616              :                                 Constant::Units::None,
    1617            3 :                                 thisMSHeatPump.CompPartLoadRatio,
    1618              :                                 OutputProcessor::TimeStepType::System,
    1619              :                                 OutputProcessor::StoreType::Average,
    1620            3 :                                 thisMSHeatPump.Name);
    1621            6 :             SetupOutputVariable(state,
    1622              :                                 "Unitary System Electricity Rate",
    1623              :                                 Constant::Units::W,
    1624            3 :                                 thisMSHeatPump.ElecPower,
    1625              :                                 OutputProcessor::TimeStepType::System,
    1626              :                                 OutputProcessor::StoreType::Average,
    1627            3 :                                 thisMSHeatPump.Name);
    1628            6 :             SetupOutputVariable(state,
    1629              :                                 "Unitary System Electricity Energy",
    1630              :                                 Constant::Units::J,
    1631            3 :                                 thisMSHPReport.ElecPowerConsumption,
    1632              :                                 OutputProcessor::TimeStepType::System,
    1633              :                                 OutputProcessor::StoreType::Sum,
    1634            3 :                                 thisMSHeatPump.Name);
    1635            6 :             SetupOutputVariable(state,
    1636              :                                 "Unitary System DX Coil Cycling Ratio",
    1637              :                                 Constant::Units::None,
    1638            3 :                                 thisMSHPReport.CycRatio,
    1639              :                                 OutputProcessor::TimeStepType::System,
    1640              :                                 OutputProcessor::StoreType::Average,
    1641            3 :                                 thisMSHeatPump.Name);
    1642            6 :             SetupOutputVariable(state,
    1643              :                                 "Unitary System DX Coil Speed Ratio",
    1644              :                                 Constant::Units::None,
    1645            3 :                                 thisMSHPReport.SpeedRatio,
    1646              :                                 OutputProcessor::TimeStepType::System,
    1647              :                                 OutputProcessor::StoreType::Average,
    1648            3 :                                 thisMSHeatPump.Name);
    1649            3 :             SetupOutputVariable(state,
    1650              :                                 "Unitary System DX Coil Speed Level",
    1651              :                                 Constant::Units::None,
    1652            3 :                                 thisMSHPReport.SpeedNum,
    1653              :                                 OutputProcessor::TimeStepType::System,
    1654              :                                 OutputProcessor::StoreType::Average,
    1655            3 :                                 thisMSHeatPump.Name);
    1656            6 :             SetupOutputVariable(state,
    1657              :                                 "Unitary System Total Cooling Rate",
    1658              :                                 Constant::Units::W,
    1659            3 :                                 thisMSHeatPump.TotCoolEnergyRate,
    1660              :                                 OutputProcessor::TimeStepType::System,
    1661              :                                 OutputProcessor::StoreType::Average,
    1662            3 :                                 thisMSHeatPump.Name);
    1663            6 :             SetupOutputVariable(state,
    1664              :                                 "Unitary System Total Heating Rate",
    1665              :                                 Constant::Units::W,
    1666            3 :                                 thisMSHeatPump.TotHeatEnergyRate,
    1667              :                                 OutputProcessor::TimeStepType::System,
    1668              :                                 OutputProcessor::StoreType::Average,
    1669            3 :                                 thisMSHeatPump.Name);
    1670            6 :             SetupOutputVariable(state,
    1671              :                                 "Unitary System Sensible Cooling Rate",
    1672              :                                 Constant::Units::W,
    1673            3 :                                 thisMSHeatPump.SensCoolEnergyRate,
    1674              :                                 OutputProcessor::TimeStepType::System,
    1675              :                                 OutputProcessor::StoreType::Average,
    1676            3 :                                 thisMSHeatPump.Name);
    1677            6 :             SetupOutputVariable(state,
    1678              :                                 "Unitary System Sensible Heating Rate",
    1679              :                                 Constant::Units::W,
    1680            3 :                                 thisMSHeatPump.SensHeatEnergyRate,
    1681              :                                 OutputProcessor::TimeStepType::System,
    1682              :                                 OutputProcessor::StoreType::Average,
    1683            3 :                                 thisMSHeatPump.Name);
    1684            6 :             SetupOutputVariable(state,
    1685              :                                 "Unitary System Latent Cooling Rate",
    1686              :                                 Constant::Units::W,
    1687            3 :                                 thisMSHeatPump.LatCoolEnergyRate,
    1688              :                                 OutputProcessor::TimeStepType::System,
    1689              :                                 OutputProcessor::StoreType::Average,
    1690            3 :                                 thisMSHeatPump.Name);
    1691            6 :             SetupOutputVariable(state,
    1692              :                                 "Unitary System Latent Heating Rate",
    1693              :                                 Constant::Units::W,
    1694            3 :                                 thisMSHeatPump.LatHeatEnergyRate,
    1695              :                                 OutputProcessor::TimeStepType::System,
    1696              :                                 OutputProcessor::StoreType::Average,
    1697            3 :                                 thisMSHeatPump.Name);
    1698            3 :             if (thisMSHeatPump.HeatRecActive) {
    1699            0 :                 SetupOutputVariable(state,
    1700              :                                     "Unitary System Heat Recovery Rate",
    1701              :                                     Constant::Units::W,
    1702            0 :                                     thisMSHeatPump.HeatRecoveryRate,
    1703              :                                     OutputProcessor::TimeStepType::System,
    1704              :                                     OutputProcessor::StoreType::Average,
    1705            0 :                                     thisMSHeatPump.Name);
    1706            0 :                 SetupOutputVariable(state,
    1707              :                                     "Unitary System Heat Recovery Inlet Temperature",
    1708              :                                     Constant::Units::C,
    1709            0 :                                     thisMSHeatPump.HeatRecoveryInletTemp,
    1710              :                                     OutputProcessor::TimeStepType::System,
    1711              :                                     OutputProcessor::StoreType::Average,
    1712            0 :                                     thisMSHeatPump.Name);
    1713            0 :                 SetupOutputVariable(state,
    1714              :                                     "Unitary System Heat Recovery Outlet Temperature",
    1715              :                                     Constant::Units::C,
    1716            0 :                                     thisMSHeatPump.HeatRecoveryOutletTemp,
    1717              :                                     OutputProcessor::TimeStepType::System,
    1718              :                                     OutputProcessor::StoreType::Average,
    1719            0 :                                     thisMSHeatPump.Name);
    1720            0 :                 SetupOutputVariable(state,
    1721              :                                     "Unitary System Heat Recovery Fluid Mass Flow Rate",
    1722              :                                     Constant::Units::kg_s,
    1723            0 :                                     thisMSHeatPump.HeatRecoveryMassFlowRate,
    1724              :                                     OutputProcessor::TimeStepType::System,
    1725              :                                     OutputProcessor::StoreType::Average,
    1726            0 :                                     thisMSHeatPump.Name);
    1727            0 :                 SetupOutputVariable(state,
    1728              :                                     "Unitary System Heat Recovery Energy",
    1729              :                                     Constant::Units::J,
    1730            0 :                                     thisMSHPReport.HeatRecoveryEnergy,
    1731              :                                     OutputProcessor::TimeStepType::System,
    1732              :                                     OutputProcessor::StoreType::Sum,
    1733            0 :                                     thisMSHeatPump.Name);
    1734              :             }
    1735              :         }
    1736            2 :         if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    1737            0 :             for (auto &thisCoil : state.dataHVACMultiSpdHP->MSHeatPump) {
    1738            0 :                 SetupEMSActuator(state,
    1739              :                                  "Coil Speed Control",
    1740              :                                  thisCoil.Name,
    1741              :                                  "Unitary System DX Coil Speed Value",
    1742              :                                  "[]",
    1743            0 :                                  thisCoil.EMSOverrideCoilSpeedNumOn,
    1744            0 :                                  thisCoil.EMSOverrideCoilSpeedNumValue);
    1745              :             }
    1746              :         }
    1747            2 :     }
    1748              : 
    1749              :     //******************************************************************************
    1750              : 
    1751            2 :     void InitMSHeatPump(EnergyPlusData &state,
    1752              :                         int const MSHeatPumpNum,       // Engine driven heat pump number
    1753              :                         bool const FirstHVACIteration, // TRUE if first HVAC iteration
    1754              :                         int const AirLoopNum,          // air loop index
    1755              :                         Real64 &QZnReq,                // Heating/Cooling load for all served zones
    1756              :                         Real64 &OnOffAirFlowRatio      // Ratio of compressor ON airflow to average airflow over timestep
    1757              :     )
    1758              :     {
    1759              : 
    1760              :         // SUBROUTINE INFORMATION:
    1761              :         //       AUTHOR:          Lixing Gu, FSEC
    1762              :         //       DATE WRITTEN:    July 2007
    1763              :         //       MODIFIED         Bereket Nigusse, June 2010 - added a procedure to calculate supply air flow fraction
    1764              :         //                        through controlled zone
    1765              : 
    1766              :         // PURPOSE OF THIS SUBROUTINE:
    1767              :         // This subroutine is for initializations of the multispeed heat pump (MSHP) components.
    1768              : 
    1769              :         // METHODOLOGY EMPLOYED:
    1770              :         // Uses the status flags to trigger initializations. The MSHP system is simulated with no load (coils off) to
    1771              :         // determine the outlet temperature. A setpoint temperature is calculated on FirstHVACIteration = TRUE.
    1772              :         // Once the setpoint is calculated, the inlet mass flow rate on FirstHVACIteration = FALSE is used to
    1773              :         // determine the bypass fraction. The simulation converges quickly on mass flow rate. If the zone
    1774              :         // temperatures float in the deadband, additional iterations are required to converge on mass flow rate.
    1775              : 
    1776              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1777              :         static constexpr std::string_view RoutineName("InitMSHeatPump");
    1778              :         Real64 RhoAir; // Air density at InNode
    1779              : 
    1780              :         Real64 QSensUnitOut; // Output of MSHP system with coils off
    1781              :         Real64 PartLoadFrac; // Part-load ratio
    1782              :         int ZoneNum;
    1783              :         int i;                // Index to speed
    1784              :         Real64 DeltaMassRate; // Difference of mass flow rate between inlet node and system outlet node
    1785              : 
    1786            2 :         int NumAirLoopZones(0);                           // number of zone inlet nodes in an air loop
    1787            2 :         Real64 SumOfMassFlowRateMax(0.0);                 // the sum of mass flow rates at inlet to zones in an airloop
    1788            2 :         Real64 CntrlZoneTerminalUnitMassFlowRateMax(0.0); // Maximum mass flow rate through controlled zone terminal unit
    1789              :         Real64 rho;                                       // local fluid density
    1790              :         Real64 MdotHR;                                    // local temporary for heat recovery fluid mass flow rate (kg/s)
    1791              :         Real64 ZoneLoadToCoolSPSequenced;
    1792              :         Real64 ZoneLoadToHeatSPSequenced;
    1793              : 
    1794            2 :         bool ErrorsFound(false);        // flag returned from mining call
    1795            2 :         Real64 mdot(0.0);               // local temporary for mass flow rate (kg/s)
    1796            2 :         Real64 SteamDensity(0.0);       // density of steam at 100C, used for steam heating coils
    1797            2 :         Real64 CoilMaxVolFlowRate(0.0); // coil fluid maximum volume flow rate
    1798            2 :         Real64 QActual(0.0);            // coil actual capacity
    1799              : 
    1800            2 :         auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump;
    1801              : 
    1802            2 :         int InNode = MSHeatPump(MSHeatPumpNum).AirInletNodeNum;
    1803            2 :         int OutNode = MSHeatPump(MSHeatPumpNum).AirOutletNodeNum;
    1804            2 :         int NumOfSpeedCooling = MSHeatPump(MSHeatPumpNum).NumOfSpeedCooling;
    1805            2 :         int NumOfSpeedHeating = MSHeatPump(MSHeatPumpNum).NumOfSpeedHeating;
    1806              : 
    1807            2 :         ++state.dataHVACMultiSpdHP->AirLoopPass;
    1808            2 :         if (state.dataHVACMultiSpdHP->AirLoopPass > 2) {
    1809            0 :             state.dataHVACMultiSpdHP->AirLoopPass = 1;
    1810              :         }
    1811              : 
    1812            2 :         if (MSHeatPump(MSHeatPumpNum).MyPlantScantFlag && allocated(state.dataPlnt->PlantLoop)) {
    1813              :             bool errFlag;
    1814            0 :             if (MSHeatPump(MSHeatPumpNum).HeatRecActive) {
    1815            0 :                 errFlag = false;
    1816            0 :                 PlantUtilities::ScanPlantLoopsForObject(state,
    1817            0 :                                                         MSHeatPump(MSHeatPumpNum).Name,
    1818              :                                                         DataPlant::PlantEquipmentType::MultiSpeedHeatPumpRecovery,
    1819            0 :                                                         MSHeatPump(MSHeatPumpNum).HRPlantLoc,
    1820              :                                                         errFlag,
    1821              :                                                         _,
    1822              :                                                         _,
    1823              :                                                         _,
    1824              :                                                         _,
    1825              :                                                         _);
    1826            0 :                 if (errFlag) {
    1827            0 :                     ShowFatalError(state, "InitMSHeatPump: Program terminated for previous conditions.");
    1828              :                 }
    1829              : 
    1830            0 :                 MSHeatPump(MSHeatPumpNum).MyPlantScantFlag = false;
    1831              :             } else {
    1832            0 :                 MSHeatPump(MSHeatPumpNum).MyPlantScantFlag = false;
    1833              :             }
    1834            0 :             if (MSHeatPump(MSHeatPumpNum).HeatCoilType == HVAC::Coil_HeatingWater) {
    1835            0 :                 errFlag = false;
    1836            0 :                 PlantUtilities::ScanPlantLoopsForObject(state,
    1837            0 :                                                         MSHeatPump(MSHeatPumpNum).HeatCoilName,
    1838              :                                                         DataPlant::PlantEquipmentType::CoilWaterSimpleHeating,
    1839            0 :                                                         MSHeatPump(MSHeatPumpNum).plantLoc,
    1840              :                                                         errFlag,
    1841              :                                                         _,
    1842              :                                                         _,
    1843              :                                                         _,
    1844              :                                                         _,
    1845              :                                                         _);
    1846            0 :                 if (errFlag) {
    1847            0 :                     ShowFatalError(state, "InitMSHeatPump: Program terminated for previous conditions.");
    1848              :                 }
    1849            0 :                 MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow =
    1850            0 :                     WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", MSHeatPump(MSHeatPumpNum).HeatCoilName, ErrorsFound);
    1851              : 
    1852            0 :                 if (MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow > 0.0) {
    1853            0 :                     rho = state.dataPlnt->PlantLoop(MSHeatPump(MSHeatPumpNum).plantLoc.loopNum)
    1854            0 :                               .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    1855            0 :                     MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow =
    1856            0 :                         WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", MSHeatPump(MSHeatPumpNum).HeatCoilName, ErrorsFound) * rho;
    1857              :                 }
    1858              :                 // fill outlet node for coil
    1859            0 :                 MSHeatPump(MSHeatPumpNum).CoilOutletNode =
    1860            0 :                     DataPlant::CompData::getPlantComponent(state, MSHeatPump(MSHeatPumpNum).plantLoc).NodeNumOut;
    1861            0 :                 MSHeatPump(MSHeatPumpNum).MyPlantScantFlag = false;
    1862              : 
    1863            0 :             } else if (MSHeatPump(MSHeatPumpNum).HeatCoilType == HVAC::Coil_HeatingSteam) {
    1864            0 :                 errFlag = false;
    1865            0 :                 PlantUtilities::ScanPlantLoopsForObject(state,
    1866            0 :                                                         MSHeatPump(MSHeatPumpNum).HeatCoilName,
    1867              :                                                         DataPlant::PlantEquipmentType::CoilSteamAirHeating,
    1868            0 :                                                         MSHeatPump(MSHeatPumpNum).plantLoc,
    1869              :                                                         errFlag,
    1870              :                                                         _,
    1871              :                                                         _,
    1872              :                                                         _,
    1873              :                                                         _,
    1874              :                                                         _);
    1875            0 :                 if (errFlag) {
    1876            0 :                     ShowFatalError(state, "InitMSHeatPump: Program terminated for previous conditions.");
    1877              :                 }
    1878            0 :                 MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow =
    1879            0 :                     SteamCoils::GetCoilMaxSteamFlowRate(state, MSHeatPump(MSHeatPumpNum).HeatCoilNum, ErrorsFound);
    1880            0 :                 if (MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow > 0.0) {
    1881            0 :                     SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataHVACMultiSpdHP->TempSteamIn, 1.0, RoutineName);
    1882            0 :                     MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow *= SteamDensity;
    1883              :                 }
    1884              : 
    1885              :                 // fill outlet node for coil
    1886            0 :                 MSHeatPump(MSHeatPumpNum).CoilOutletNode =
    1887            0 :                     DataPlant::CompData::getPlantComponent(state, MSHeatPump(MSHeatPumpNum).plantLoc).NodeNumOut;
    1888            0 :                 MSHeatPump(MSHeatPumpNum).MyPlantScantFlag = false;
    1889              :             }
    1890            0 :             if (MSHeatPump(MSHeatPumpNum).SuppHeatCoilType == HVAC::Coil_HeatingWater) {
    1891            0 :                 errFlag = false;
    1892            0 :                 PlantUtilities::ScanPlantLoopsForObject(state,
    1893            0 :                                                         MSHeatPump(MSHeatPumpNum).SuppHeatCoilName,
    1894              :                                                         DataPlant::PlantEquipmentType::CoilWaterSimpleHeating,
    1895            0 :                                                         MSHeatPump(MSHeatPumpNum).SuppPlantLoc,
    1896              :                                                         errFlag,
    1897              :                                                         _,
    1898              :                                                         _,
    1899              :                                                         _,
    1900              :                                                         _,
    1901              :                                                         _);
    1902            0 :                 if (errFlag) {
    1903            0 :                     ShowFatalError(state, "InitMSHeatPump: Program terminated for previous conditions.");
    1904              :                 }
    1905            0 :                 MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow =
    1906            0 :                     WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", MSHeatPump(MSHeatPumpNum).SuppHeatCoilName, ErrorsFound);
    1907              : 
    1908            0 :                 if (MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow > 0.0) {
    1909            0 :                     rho = state.dataPlnt->PlantLoop(MSHeatPump(MSHeatPumpNum).SuppPlantLoc.loopNum)
    1910            0 :                               .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    1911            0 :                     MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow =
    1912            0 :                         WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", MSHeatPump(MSHeatPumpNum).SuppHeatCoilName, ErrorsFound) *
    1913              :                         rho;
    1914              :                 }
    1915              :                 // fill outlet node for coil
    1916            0 :                 MSHeatPump(MSHeatPumpNum).SuppCoilOutletNode =
    1917            0 :                     DataPlant::CompData::getPlantComponent(state, MSHeatPump(MSHeatPumpNum).SuppPlantLoc).NodeNumOut;
    1918            0 :                 MSHeatPump(MSHeatPumpNum).MyPlantScantFlag = false;
    1919              : 
    1920            0 :             } else if (MSHeatPump(MSHeatPumpNum).SuppHeatCoilType == HVAC::Coil_HeatingSteam) {
    1921            0 :                 errFlag = false;
    1922            0 :                 PlantUtilities::ScanPlantLoopsForObject(state,
    1923            0 :                                                         MSHeatPump(MSHeatPumpNum).SuppHeatCoilName,
    1924              :                                                         DataPlant::PlantEquipmentType::CoilSteamAirHeating,
    1925            0 :                                                         MSHeatPump(MSHeatPumpNum).SuppPlantLoc,
    1926              :                                                         errFlag,
    1927              :                                                         _,
    1928              :                                                         _,
    1929              :                                                         _,
    1930              :                                                         _,
    1931              :                                                         _);
    1932            0 :                 if (errFlag) {
    1933            0 :                     ShowFatalError(state, "InitMSHeatPump: Program terminated for previous conditions.");
    1934              :                 }
    1935            0 :                 MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow =
    1936            0 :                     SteamCoils::GetCoilMaxSteamFlowRate(state, MSHeatPump(MSHeatPumpNum).SuppHeatCoilNum, ErrorsFound);
    1937            0 :                 if (MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow > 0.0) {
    1938            0 :                     SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataHVACMultiSpdHP->TempSteamIn, 1.0, RoutineName);
    1939            0 :                     MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow *= SteamDensity;
    1940              :                 }
    1941              : 
    1942              :                 // fill outlet node for coil
    1943            0 :                 MSHeatPump(MSHeatPumpNum).SuppCoilOutletNode =
    1944            0 :                     DataPlant::CompData::getPlantComponent(state, MSHeatPump(MSHeatPumpNum).SuppPlantLoc).NodeNumOut;
    1945            0 :                 MSHeatPump(MSHeatPumpNum).MyPlantScantFlag = false;
    1946              :             }
    1947            2 :         } else if (MSHeatPump(MSHeatPumpNum).MyPlantScantFlag && !state.dataGlobal->AnyPlantInModel) {
    1948            2 :             MSHeatPump(MSHeatPumpNum).MyPlantScantFlag = false;
    1949              :         }
    1950              : 
    1951            2 :         if (!state.dataGlobal->SysSizingCalc && MSHeatPump(MSHeatPumpNum).MySizeFlag) {
    1952            0 :             MSHeatPump(MSHeatPumpNum).FanVolFlow = state.dataFans->fans(MSHeatPump(MSHeatPumpNum).FanNum)->maxAirFlowRate;
    1953            0 :             SizeMSHeatPump(state, MSHeatPumpNum);
    1954            0 :             MSHeatPump(MSHeatPumpNum).FlowFraction = 1.0;
    1955            0 :             MSHeatPump(MSHeatPumpNum).MySizeFlag = false;
    1956              :             // Pass the fan cycling schedule index up to the air loop. Set the air loop unitary system flag.
    1957            0 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).cycFanSched = MSHeatPump(MSHeatPumpNum).fanOpModeSched;
    1958            0 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).UnitarySys = true;
    1959            0 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).UnitarySysSimulating =
    1960              :                 false; // affects child coil sizing by allowing coil to size itself instead of parent telling coil what size to use
    1961            0 :             state.dataAirLoop->AirLoopControlInfo(AirLoopNum).fanOp = MSHeatPump(MSHeatPumpNum).fanOp;
    1962              :         }
    1963              : 
    1964            2 :         if (allocated(state.dataZoneEquip->ZoneEquipConfig) && MSHeatPump(MSHeatPumpNum).MyCheckFlag) {
    1965            2 :             int zoneNum = MSHeatPump(MSHeatPumpNum).ControlZoneNum;
    1966            2 :             int zoneInlet = MSHeatPump(MSHeatPumpNum).ZoneInletNode;
    1967              :             // setup furnace zone equipment sequence information based on finding matching air terminal
    1968            2 :             if (state.dataZoneEquip->ZoneEquipConfig(zoneNum).EquipListIndex > 0) {
    1969            2 :                 int coolingPriority = 0;
    1970            2 :                 int heatingPriority = 0;
    1971            2 :                 state.dataZoneEquip->ZoneEquipList(state.dataZoneEquip->ZoneEquipConfig(zoneNum).EquipListIndex)
    1972            2 :                     .getPrioritiesForInletNode(state, zoneInlet, coolingPriority, heatingPriority);
    1973            2 :                 MSHeatPump(MSHeatPumpNum).ZoneSequenceCoolingNum = coolingPriority;
    1974            2 :                 MSHeatPump(MSHeatPumpNum).ZoneSequenceHeatingNum = heatingPriority;
    1975              :             }
    1976            2 :             MSHeatPump(MSHeatPumpNum).MyCheckFlag = false;
    1977            2 :             if (MSHeatPump(MSHeatPumpNum).ZoneSequenceCoolingNum == 0 || MSHeatPump(MSHeatPumpNum).ZoneSequenceHeatingNum == 0) {
    1978            0 :                 ShowSevereError(state,
    1979            0 :                                 format("AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed, \"{}\": Airloop air terminal in the zone equipment list for "
    1980              :                                        "zone = {} not found or is not allowed Zone Equipment Cooling or Heating Sequence = 0.",
    1981            0 :                                        MSHeatPump(MSHeatPumpNum).Name,
    1982            0 :                                        MSHeatPump(MSHeatPumpNum).ControlZoneName));
    1983            0 :                 ShowFatalError(state,
    1984              :                                "Subroutine InitMSHeatPump: Errors found in getting AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed input.  Preceding "
    1985              :                                "condition(s) causes termination.");
    1986              :             }
    1987              :         }
    1988              : 
    1989              :         // Find the number of zones (zone Inlet Nodes) attached to an air loop from the air loop number
    1990            2 :         NumAirLoopZones =
    1991            2 :             state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesCooled + state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesHeated;
    1992            2 :         if (allocated(state.dataAirLoop->AirToZoneNodeInfo) && MSHeatPump(MSHeatPumpNum).MyFlowFracFlag) {
    1993            1 :             state.dataHVACMultiSpdHP->FlowFracFlagReady = true;
    1994            2 :             for (int ZoneInSysIndex = 1; ZoneInSysIndex <= NumAirLoopZones; ++ZoneInSysIndex) {
    1995              :                 // zone inlet nodes for cooling
    1996            1 :                 if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesCooled > 0) {
    1997            1 :                     if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitCoolInletNodes(ZoneInSysIndex) == -999) {
    1998              :                         // the data structure for the zones inlet nodes has not been filled
    1999            0 :                         state.dataHVACMultiSpdHP->FlowFracFlagReady = false;
    2000              :                     }
    2001              :                 }
    2002              :                 // zone inlet nodes for heating
    2003            1 :                 if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesHeated > 0) {
    2004            0 :                     if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitHeatInletNodes(ZoneInSysIndex) == -999) {
    2005              :                         // the data structure for the zones inlet nodes has not been filled
    2006            0 :                         state.dataHVACMultiSpdHP->FlowFracFlagReady = false;
    2007              :                     }
    2008              :                 }
    2009              :             }
    2010              :         }
    2011            2 :         if (allocated(state.dataAirLoop->AirToZoneNodeInfo) && state.dataHVACMultiSpdHP->FlowFracFlagReady) {
    2012            1 :             SumOfMassFlowRateMax = 0.0; // initialize the sum of the maximum flows
    2013            2 :             for (int ZoneInSysIndex = 1; ZoneInSysIndex <= NumAirLoopZones; ++ZoneInSysIndex) {
    2014            1 :                 int ZoneInletNodeNum = state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitCoolInletNodes(ZoneInSysIndex);
    2015            1 :                 SumOfMassFlowRateMax += state.dataLoopNodes->Node(ZoneInletNodeNum).MassFlowRateMax;
    2016            1 :                 if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).CoolCtrlZoneNums(ZoneInSysIndex) == MSHeatPump(MSHeatPumpNum).ControlZoneNum) {
    2017            1 :                     CntrlZoneTerminalUnitMassFlowRateMax = state.dataLoopNodes->Node(ZoneInletNodeNum).MassFlowRateMax;
    2018              :                 }
    2019              :             }
    2020            1 :             if (SumOfMassFlowRateMax != 0.0 && MSHeatPump(MSHeatPumpNum).MyFlowFracFlag) {
    2021            1 :                 if (CntrlZoneTerminalUnitMassFlowRateMax >= HVAC::SmallAirVolFlow) {
    2022            0 :                     MSHeatPump(MSHeatPumpNum).FlowFraction = CntrlZoneTerminalUnitMassFlowRateMax / SumOfMassFlowRateMax;
    2023              :                 } else {
    2024            1 :                     ShowSevereError(state, format("{} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump(MSHeatPumpNum).Name));
    2025            3 :                     ShowContinueError(state, " The Fraction of Supply Air Flow That Goes Through the Controlling Zone is set to 1.");
    2026              :                 }
    2027            2 :                 BaseSizer::reportSizerOutput(state,
    2028            1 :                                              state.dataHVACMultiSpdHP->CurrentModuleObject,
    2029            1 :                                              MSHeatPump(MSHeatPumpNum).Name,
    2030              :                                              "Fraction of Supply Air Flow That Goes Through the Controlling Zone",
    2031            1 :                                              MSHeatPump(MSHeatPumpNum).FlowFraction);
    2032            1 :                 MSHeatPump(MSHeatPumpNum).MyFlowFracFlag = false;
    2033              :             }
    2034              :         }
    2035              : 
    2036              :         // Do the Begin Environment initializations
    2037            2 :         if (state.dataGlobal->BeginEnvrnFlag && MSHeatPump(MSHeatPumpNum).MyEnvrnFlag) {
    2038            1 :             RhoAir = state.dataEnvrn->StdRhoAir;
    2039              :             // set the mass flow rates from the input volume flow rates
    2040            3 :             for (i = 1; i <= NumOfSpeedCooling; ++i) {
    2041            2 :                 MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(i) = RhoAir * MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(i);
    2042              :             }
    2043            3 :             for (i = 1; i <= NumOfSpeedHeating; ++i) {
    2044            2 :                 MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(i) = RhoAir * MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(i);
    2045              :             }
    2046            1 :             MSHeatPump(MSHeatPumpNum).IdleMassFlowRate = RhoAir * MSHeatPump(MSHeatPumpNum).IdleVolumeAirRate;
    2047              :             // set the node max and min mass flow rates
    2048            1 :             state.dataLoopNodes->Node(InNode).MassFlowRateMax =
    2049            1 :                 max(MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(NumOfSpeedCooling), MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(NumOfSpeedHeating));
    2050            1 :             state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail =
    2051            1 :                 max(MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(NumOfSpeedCooling), MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(NumOfSpeedHeating));
    2052            1 :             state.dataLoopNodes->Node(InNode).MassFlowRateMin = 0.0;
    2053            1 :             state.dataLoopNodes->Node(InNode).MassFlowRateMinAvail = 0.0;
    2054            1 :             state.dataLoopNodes->Node(OutNode) = state.dataLoopNodes->Node(InNode);
    2055            1 :             MSHeatPump(MSHeatPumpNum).LoadLoss = 0.0;
    2056              : 
    2057            1 :             if ((MSHeatPump(MSHeatPumpNum).HeatRecActive) && (!MSHeatPump(MSHeatPumpNum).MyPlantScantFlag)) {
    2058              : 
    2059            0 :                 rho = state.dataPlnt->PlantLoop(MSHeatPump(MSHeatPumpNum).HRPlantLoc.loopNum)
    2060            0 :                           .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    2061              : 
    2062            0 :                 MSHeatPump(MSHeatPumpNum).DesignHeatRecMassFlowRate = MSHeatPump(MSHeatPumpNum).DesignHeatRecFlowRate * rho;
    2063              : 
    2064            0 :                 PlantUtilities::InitComponentNodes(state,
    2065              :                                                    0.0,
    2066            0 :                                                    MSHeatPump(MSHeatPumpNum).DesignHeatRecMassFlowRate,
    2067            0 :                                                    MSHeatPump(MSHeatPumpNum).HeatRecInletNodeNum,
    2068            0 :                                                    MSHeatPump(MSHeatPumpNum).HeatRecOutletNodeNum);
    2069              :             }
    2070            1 :             if (MSHeatPump(MSHeatPumpNum).CoilControlNode > 0) {
    2071            0 :                 if (MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow == DataSizing::AutoSize) {
    2072            0 :                     if (MSHeatPump(MSHeatPumpNum).HeatCoilType == HVAC::Coil_HeatingWater) {
    2073            0 :                         WaterCoils::SimulateWaterCoilComponents(
    2074            0 :                             state, MSHeatPump(MSHeatPumpNum).HeatCoilName, FirstHVACIteration, MSHeatPump(MSHeatPumpNum).HeatCoilNum);
    2075              : 
    2076              :                         CoilMaxVolFlowRate =
    2077            0 :                             WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", MSHeatPump(MSHeatPumpNum).HeatCoilName, ErrorsFound);
    2078            0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    2079            0 :                             rho = state.dataPlnt->PlantLoop(MSHeatPump(MSHeatPumpNum).plantLoc.loopNum)
    2080            0 :                                       .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    2081            0 :                             MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow = CoilMaxVolFlowRate * rho;
    2082              :                         }
    2083            0 :                         PlantUtilities::InitComponentNodes(state,
    2084              :                                                            0.0,
    2085            0 :                                                            MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow,
    2086            0 :                                                            MSHeatPump(MSHeatPumpNum).CoilControlNode,
    2087            0 :                                                            MSHeatPump(MSHeatPumpNum).CoilOutletNode);
    2088              :                     }
    2089            0 :                     if (MSHeatPump(MSHeatPumpNum).HeatCoilType == HVAC::Coil_HeatingSteam) {
    2090              : 
    2091            0 :                         SteamCoils::SimulateSteamCoilComponents(state,
    2092            0 :                                                                 MSHeatPump(MSHeatPumpNum).HeatCoilName,
    2093              :                                                                 FirstHVACIteration,
    2094            0 :                                                                 MSHeatPump(MSHeatPumpNum).HeatCoilNum,
    2095            0 :                                                                 1.0,
    2096              :                                                                 QActual); // QCoilReq, simulate any load > 0 to get max capacity of steam coil
    2097            0 :                         CoilMaxVolFlowRate = SteamCoils::GetCoilMaxSteamFlowRate(state, MSHeatPump(MSHeatPumpNum).HeatCoilNum, ErrorsFound);
    2098              : 
    2099            0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    2100            0 :                             SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataHVACMultiSpdHP->TempSteamIn, 1.0, RoutineName);
    2101            0 :                             MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow = CoilMaxVolFlowRate * SteamDensity;
    2102              :                         }
    2103            0 :                         PlantUtilities::InitComponentNodes(state,
    2104              :                                                            0.0,
    2105            0 :                                                            MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow,
    2106            0 :                                                            MSHeatPump(MSHeatPumpNum).CoilControlNode,
    2107            0 :                                                            MSHeatPump(MSHeatPumpNum).CoilOutletNode);
    2108              :                     }
    2109              :                 }
    2110              :             }
    2111            1 :             if (MSHeatPump(MSHeatPumpNum).SuppCoilControlNode > 0) {
    2112            0 :                 if (MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow == DataSizing::AutoSize) {
    2113            0 :                     if (MSHeatPump(MSHeatPumpNum).SuppHeatCoilType == HVAC::Coil_HeatingWater) {
    2114            0 :                         WaterCoils::SimulateWaterCoilComponents(
    2115            0 :                             state, MSHeatPump(MSHeatPumpNum).SuppHeatCoilName, FirstHVACIteration, MSHeatPump(MSHeatPumpNum).SuppHeatCoilNum);
    2116              : 
    2117              :                         CoilMaxVolFlowRate =
    2118            0 :                             WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", MSHeatPump(MSHeatPumpNum).SuppHeatCoilName, ErrorsFound);
    2119            0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    2120            0 :                             rho = state.dataPlnt->PlantLoop(MSHeatPump(MSHeatPumpNum).SuppPlantLoc.loopNum)
    2121            0 :                                       .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    2122            0 :                             MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow = CoilMaxVolFlowRate * rho;
    2123              :                         }
    2124            0 :                         PlantUtilities::InitComponentNodes(state,
    2125              :                                                            0.0,
    2126            0 :                                                            MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow,
    2127            0 :                                                            MSHeatPump(MSHeatPumpNum).SuppCoilControlNode,
    2128            0 :                                                            MSHeatPump(MSHeatPumpNum).SuppCoilOutletNode);
    2129              :                     }
    2130            0 :                     if (MSHeatPump(MSHeatPumpNum).SuppHeatCoilType == HVAC::Coil_HeatingSteam) {
    2131              : 
    2132            0 :                         SteamCoils::SimulateSteamCoilComponents(state,
    2133            0 :                                                                 MSHeatPump(MSHeatPumpNum).SuppHeatCoilName,
    2134              :                                                                 FirstHVACIteration,
    2135            0 :                                                                 MSHeatPump(MSHeatPumpNum).SuppHeatCoilNum,
    2136            0 :                                                                 1.0,
    2137              :                                                                 QActual); // QCoilReq, simulate any load > 0 to get max capacity of steam coil
    2138            0 :                         CoilMaxVolFlowRate = SteamCoils::GetCoilMaxSteamFlowRate(state, MSHeatPump(MSHeatPumpNum).SuppHeatCoilNum, ErrorsFound);
    2139              : 
    2140            0 :                         if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
    2141            0 :                             SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataHVACMultiSpdHP->TempSteamIn, 1.0, RoutineName);
    2142            0 :                             MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow = CoilMaxVolFlowRate * SteamDensity;
    2143              :                         }
    2144            0 :                         PlantUtilities::InitComponentNodes(state,
    2145              :                                                            0.0,
    2146            0 :                                                            MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow,
    2147            0 :                                                            MSHeatPump(MSHeatPumpNum).SuppCoilControlNode,
    2148            0 :                                                            MSHeatPump(MSHeatPumpNum).SuppCoilOutletNode);
    2149              :                     }
    2150              :                 }
    2151              :             }
    2152            1 :             MSHeatPump(MSHeatPumpNum).MyEnvrnFlag = false;
    2153              :         } // end one time inits
    2154              : 
    2155            2 :         if (!state.dataGlobal->BeginEnvrnFlag) {
    2156            1 :             MSHeatPump(MSHeatPumpNum).MyEnvrnFlag = true;
    2157              :         }
    2158              : 
    2159              :         // IF MSHP system was not autosized and the fan is autosized, check that fan volumetric flow rate is greater than MSHP flow rates
    2160            2 :         if (!state.dataGlobal->DoingSizing && MSHeatPump(MSHeatPumpNum).CheckFanFlow) {
    2161            2 :             state.dataHVACMultiSpdHP->CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed";
    2162            2 :             MSHeatPump(MSHeatPumpNum).FanVolFlow = state.dataFans->fans(MSHeatPump(MSHeatPumpNum).FanNum)->maxAirFlowRate;
    2163            2 :             if (MSHeatPump(MSHeatPumpNum).FanVolFlow != DataSizing::AutoSize) {
    2164              :                 //     Check fan versus system supply air flow rates
    2165            2 :                 if (MSHeatPump(MSHeatPumpNum).FanVolFlow < MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(NumOfSpeedCooling)) {
    2166            0 :                     ShowWarningError(state,
    2167            0 :                                      format("{} - air flow rate = {:.7T} in fan object {} is less than the MSHP system air flow rate when cooling is "
    2168              :                                             "required ({:.7T}).",
    2169            0 :                                             state.dataHVACMultiSpdHP->CurrentModuleObject,
    2170            0 :                                             MSHeatPump(MSHeatPumpNum).FanVolFlow,
    2171            0 :                                             MSHeatPump(MSHeatPumpNum).FanName,
    2172            0 :                                             MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(NumOfSpeedCooling)));
    2173            0 :                     ShowContinueError(
    2174              :                         state, " The MSHP system flow rate when cooling is required is reset to the fan flow rate and the simulation continues.");
    2175            0 :                     ShowContinueError(state,
    2176            0 :                                       format(" Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump(MSHeatPumpNum).Name));
    2177            0 :                     MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(NumOfSpeedCooling) = MSHeatPump(MSHeatPumpNum).FanVolFlow;
    2178              :                     // Check flow rates in other speeds and ensure flow rates are not above the max flow rate
    2179            0 :                     for (i = NumOfSpeedCooling - 1; i >= 1; --i) {
    2180            0 :                         if (MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(i) > MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(i + 1)) {
    2181            0 :                             ShowContinueError(state,
    2182            0 :                                               format(" The MSHP system flow rate when cooling is required is reset to the flow rate at higher speed "
    2183              :                                                      "and the simulation continues at Speed{}.",
    2184              :                                                      i));
    2185            0 :                             ShowContinueError(
    2186            0 :                                 state, format(" Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump(MSHeatPumpNum).Name));
    2187            0 :                             MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(i) = MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(i + 1);
    2188              :                         }
    2189              :                     }
    2190              :                 }
    2191            2 :                 if (MSHeatPump(MSHeatPumpNum).FanVolFlow < MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(NumOfSpeedHeating)) {
    2192            0 :                     ShowWarningError(state,
    2193            0 :                                      format("{} - air flow rate = {:.7T} in fan object {} is less than the MSHP system air flow rate when heating is "
    2194              :                                             "required ({:.7T}).",
    2195            0 :                                             state.dataHVACMultiSpdHP->CurrentModuleObject,
    2196            0 :                                             MSHeatPump(MSHeatPumpNum).FanVolFlow,
    2197            0 :                                             MSHeatPump(MSHeatPumpNum).FanName,
    2198            0 :                                             MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(NumOfSpeedHeating)));
    2199            0 :                     ShowContinueError(
    2200              :                         state, " The MSHP system flow rate when heating is required is reset to the fan flow rate and the simulation continues.");
    2201            0 :                     ShowContinueError(state,
    2202            0 :                                       format(" Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump(MSHeatPumpNum).Name));
    2203            0 :                     MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(NumOfSpeedHeating) = MSHeatPump(MSHeatPumpNum).FanVolFlow;
    2204            0 :                     for (i = NumOfSpeedHeating - 1; i >= 1; --i) {
    2205            0 :                         if (MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(i) > MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(i + 1)) {
    2206            0 :                             ShowContinueError(state,
    2207            0 :                                               format(" The MSHP system flow rate when heating is required is reset to the flow rate at higher speed "
    2208              :                                                      "and the simulation continues at Speed{}.",
    2209              :                                                      i));
    2210            0 :                             ShowContinueError(
    2211              :                                 state,
    2212            0 :                                 format(" Occurs in {} system = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump(MSHeatPumpNum).Name));
    2213            0 :                             MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(i) = MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(i + 1);
    2214              :                         }
    2215              :                     }
    2216              :                 }
    2217            2 :                 if (MSHeatPump(MSHeatPumpNum).FanVolFlow < MSHeatPump(MSHeatPumpNum).IdleVolumeAirRate &&
    2218            0 :                     MSHeatPump(MSHeatPumpNum).IdleVolumeAirRate != 0.0) {
    2219            0 :                     ShowWarningError(state,
    2220            0 :                                      format("{} - air flow rate = {:.7T} in fan object {} is less than the MSHP system air flow rate when no heating "
    2221              :                                             "or cooling is needed ({:.7T}).",
    2222            0 :                                             state.dataHVACMultiSpdHP->CurrentModuleObject,
    2223            0 :                                             MSHeatPump(MSHeatPumpNum).FanVolFlow,
    2224            0 :                                             MSHeatPump(MSHeatPumpNum).FanName,
    2225            0 :                                             MSHeatPump(MSHeatPumpNum).IdleVolumeAirRate));
    2226            0 :                     ShowContinueError(state,
    2227              :                                       " The MSHP system flow rate when no heating or cooling is needed is reset to the fan flow rate and the "
    2228              :                                       "simulation continues.");
    2229            0 :                     ShowContinueError(state,
    2230            0 :                                       format(" Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump(MSHeatPumpNum).Name));
    2231            0 :                     MSHeatPump(MSHeatPumpNum).IdleVolumeAirRate = MSHeatPump(MSHeatPumpNum).FanVolFlow;
    2232              :                 }
    2233            2 :                 RhoAir = state.dataEnvrn->StdRhoAir;
    2234              :                 // set the mass flow rates from the reset volume flow rates
    2235            6 :                 for (i = 1; i <= NumOfSpeedCooling; ++i) {
    2236            4 :                     MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(i) = RhoAir * MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(i);
    2237            4 :                     if (MSHeatPump(MSHeatPumpNum).FanVolFlow > 0.0) {
    2238            4 :                         MSHeatPump(MSHeatPumpNum).CoolingSpeedRatio(i) =
    2239            4 :                             MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(i) / MSHeatPump(MSHeatPumpNum).FanVolFlow;
    2240              :                     }
    2241              :                 }
    2242            6 :                 for (i = 1; i <= NumOfSpeedHeating; ++i) {
    2243            4 :                     MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(i) = RhoAir * MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(i);
    2244            4 :                     if (MSHeatPump(MSHeatPumpNum).FanVolFlow > 0.0) {
    2245            4 :                         MSHeatPump(MSHeatPumpNum).HeatingSpeedRatio(i) =
    2246            4 :                             MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(i) / MSHeatPump(MSHeatPumpNum).FanVolFlow;
    2247              :                     }
    2248              :                 }
    2249            2 :                 MSHeatPump(MSHeatPumpNum).IdleMassFlowRate = RhoAir * MSHeatPump(MSHeatPumpNum).IdleVolumeAirRate;
    2250            2 :                 if (MSHeatPump(MSHeatPumpNum).FanVolFlow > 0.0) {
    2251            2 :                     MSHeatPump(MSHeatPumpNum).IdleSpeedRatio = MSHeatPump(MSHeatPumpNum).IdleVolumeAirRate / MSHeatPump(MSHeatPumpNum).FanVolFlow;
    2252              :                 }
    2253              :                 // set the node max and min mass flow rates based on reset volume flow rates
    2254            2 :                 state.dataLoopNodes->Node(InNode).MassFlowRateMax =
    2255            2 :                     max(MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(NumOfSpeedCooling), MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(NumOfSpeedHeating));
    2256            2 :                 state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail =
    2257            2 :                     max(MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(NumOfSpeedCooling), MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(NumOfSpeedHeating));
    2258            2 :                 state.dataLoopNodes->Node(InNode).MassFlowRateMin = 0.0;
    2259            2 :                 state.dataLoopNodes->Node(InNode).MassFlowRateMinAvail = 0.0;
    2260            2 :                 state.dataLoopNodes->Node(OutNode) = state.dataLoopNodes->Node(InNode);
    2261            2 :                 MSHeatPump(MSHeatPumpNum).CheckFanFlow = false;
    2262              :             }
    2263              :         }
    2264              : 
    2265            2 :         if (MSHeatPump(MSHeatPumpNum).fanOpModeSched != nullptr) {
    2266            2 :             MSHeatPump(MSHeatPumpNum).fanOp =
    2267            2 :                 (MSHeatPump(MSHeatPumpNum).fanOpModeSched->getCurrentVal() == 0.0) ? HVAC::FanOp::Cycling : HVAC::FanOp::Continuous;
    2268              :         }
    2269              : 
    2270              :         // Calculate air distribution losses
    2271            2 :         if (!FirstHVACIteration && state.dataHVACMultiSpdHP->AirLoopPass == 1) {
    2272            0 :             int ZoneInNode = MSHeatPump(MSHeatPumpNum).ZoneInletNode;
    2273            0 :             DeltaMassRate = state.dataLoopNodes->Node(OutNode).MassFlowRate -
    2274            0 :                             state.dataLoopNodes->Node(ZoneInNode).MassFlowRate / MSHeatPump(MSHeatPumpNum).FlowFraction;
    2275            0 :             if (DeltaMassRate < 0.0) {
    2276            0 :                 DeltaMassRate = 0.0;
    2277              :             }
    2278            0 :             Real64 MassFlowRate(0.0);        // parent mass flow rate
    2279            0 :             Real64 LatentOutput(0.0);        // latent output rate
    2280            0 :             Real64 TotalOutput(0.0);         // total output rate
    2281            0 :             Real64 SensibleOutputDelta(0.0); // delta sensible output rate
    2282            0 :             Real64 LatentOutputDelta(0.0);   // delta latent output rate
    2283            0 :             Real64 TotalOutputDelta(0.0);    // delta total output rate
    2284            0 :             MassFlowRate = state.dataLoopNodes->Node(ZoneInNode).MassFlowRate / MSHeatPump(MSHeatPumpNum).FlowFraction;
    2285            0 :             Real64 MinHumRat = state.dataLoopNodes->Node(ZoneInNode).HumRat;
    2286            0 :             if (state.dataLoopNodes->Node(OutNode).Temp < state.dataLoopNodes->Node(MSHeatPump(MSHeatPumpNum).NodeNumOfControlledZone).Temp) {
    2287            0 :                 MinHumRat = state.dataLoopNodes->Node(OutNode).HumRat;
    2288              :             }
    2289            0 :             CalcZoneSensibleLatentOutput(MassFlowRate,
    2290            0 :                                          state.dataLoopNodes->Node(OutNode).Temp,
    2291              :                                          MinHumRat,
    2292            0 :                                          state.dataLoopNodes->Node(ZoneInNode).Temp,
    2293              :                                          MinHumRat,
    2294            0 :                                          MSHeatPump(MSHeatPumpNum).LoadLoss,
    2295              :                                          LatentOutput,
    2296              :                                          TotalOutput);
    2297            0 :             CalcZoneSensibleLatentOutput(DeltaMassRate,
    2298            0 :                                          state.dataLoopNodes->Node(OutNode).Temp,
    2299              :                                          MinHumRat,
    2300            0 :                                          state.dataLoopNodes->Node(MSHeatPump(MSHeatPumpNum).NodeNumOfControlledZone).Temp,
    2301              :                                          MinHumRat,
    2302              :                                          SensibleOutputDelta,
    2303              :                                          LatentOutputDelta,
    2304              :                                          TotalOutputDelta);
    2305            0 :             MSHeatPump(MSHeatPumpNum).LoadLoss = MSHeatPump(MSHeatPumpNum).LoadLoss + SensibleOutputDelta;
    2306            0 :             if (std::abs(MSHeatPump(MSHeatPumpNum).LoadLoss) < 1.0e-6) {
    2307            0 :                 MSHeatPump(MSHeatPumpNum).LoadLoss = 0.0;
    2308              :             }
    2309              :         }
    2310              : 
    2311              :         // Returns load only for zones requesting cooling (heating). If in deadband, Qzoneload = 0.
    2312            2 :         ZoneNum = MSHeatPump(MSHeatPumpNum).ControlZoneNum;
    2313            2 :         if ((MSHeatPump(MSHeatPumpNum).ZoneSequenceCoolingNum > 0) && (MSHeatPump(MSHeatPumpNum).ZoneSequenceHeatingNum > 0)) {
    2314            2 :             ZoneLoadToCoolSPSequenced = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(MSHeatPump(MSHeatPumpNum).ControlZoneNum)
    2315            2 :                                             .SequencedOutputRequiredToCoolingSP(MSHeatPump(MSHeatPumpNum).ZoneSequenceCoolingNum);
    2316            2 :             ZoneLoadToHeatSPSequenced = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(MSHeatPump(MSHeatPumpNum).ControlZoneNum)
    2317            2 :                                             .SequencedOutputRequiredToHeatingSP(MSHeatPump(MSHeatPumpNum).ZoneSequenceHeatingNum);
    2318            2 :             if (ZoneLoadToHeatSPSequenced > HVAC::SmallLoad && ZoneLoadToCoolSPSequenced > HVAC::SmallLoad) {
    2319            1 :                 QZnReq = ZoneLoadToHeatSPSequenced;
    2320            1 :             } else if (ZoneLoadToHeatSPSequenced < (-1.0 * HVAC::SmallLoad) && ZoneLoadToCoolSPSequenced < (-1.0 * HVAC::SmallLoad)) {
    2321            1 :                 QZnReq = ZoneLoadToCoolSPSequenced;
    2322            0 :             } else if (ZoneLoadToHeatSPSequenced <= (-1.0 * HVAC::SmallLoad) && ZoneLoadToCoolSPSequenced >= HVAC::SmallLoad) {
    2323            0 :                 QZnReq = 0.0;
    2324              :             } else {
    2325            0 :                 QZnReq = 0.0; // Autodesk:Init Case added to prevent use of uninitialized value (occurred in MultiSpeedACFurnace example)
    2326              :             }
    2327            2 :             QZnReq /= MSHeatPump(MSHeatPumpNum).FlowFraction;
    2328              :         } else {
    2329            0 :             QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputRequired / MSHeatPump(MSHeatPumpNum).FlowFraction;
    2330              :         }
    2331            2 :         if (state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
    2332            0 :             QZnReq = 0.0;
    2333              :         }
    2334              : 
    2335            2 :         if (QZnReq > HVAC::SmallLoad) {
    2336            1 :             MSHeatPump(MSHeatPumpNum).HeatCoolMode = ModeOfOperation::HeatingMode;
    2337            1 :         } else if (QZnReq < (-1.0 * HVAC::SmallLoad)) {
    2338            1 :             MSHeatPump(MSHeatPumpNum).HeatCoolMode = ModeOfOperation::CoolingMode;
    2339              :         } else {
    2340            0 :             MSHeatPump(MSHeatPumpNum).HeatCoolMode = ModeOfOperation::Invalid;
    2341              :         }
    2342              : 
    2343              :         // Determine the staged status
    2344            2 :         if (allocated(state.dataZoneCtrls->StageZoneLogic)) {
    2345            0 :             if (state.dataZoneCtrls->StageZoneLogic(ZoneNum)) {
    2346            0 :                 MSHeatPump(MSHeatPumpNum).Staged = true;
    2347            0 :                 MSHeatPump(MSHeatPumpNum).StageNum = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).StageNum;
    2348              :             } else {
    2349            0 :                 if (MSHeatPump(MSHeatPumpNum).MyStagedFlag) {
    2350            0 :                     ShowWarningError(state,
    2351              :                                      "ZoneControl:Thermostat:StagedDualSetpoint is found, but is not applied to this "
    2352              :                                      "AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed object = ");
    2353            0 :                     ShowContinueError(state, format("{}. Please make correction. Simulation continues...", MSHeatPump(MSHeatPumpNum).Name));
    2354            0 :                     MSHeatPump(MSHeatPumpNum).MyStagedFlag = false;
    2355              :                 }
    2356              :             }
    2357              :         }
    2358              :         // Set the inlet node mass flow rate
    2359            2 :         if (MSHeatPump(MSHeatPumpNum).fanOp == HVAC::FanOp::Continuous) {
    2360              :             // constant fan mode
    2361            2 :             if (QZnReq > HVAC::SmallLoad && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
    2362            1 :                 state.dataHVACMultiSpdHP->CompOnMassFlow = MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(1);
    2363            1 :                 state.dataHVACMultiSpdHP->CompOnFlowRatio = MSHeatPump(MSHeatPumpNum).HeatingSpeedRatio(1);
    2364            1 :                 MSHeatPump(MSHeatPumpNum).LastMode = ModeOfOperation::HeatingMode;
    2365            1 :             } else if (QZnReq < (-1.0 * HVAC::SmallLoad) && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
    2366            1 :                 state.dataHVACMultiSpdHP->CompOnMassFlow = MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(1);
    2367            1 :                 state.dataHVACMultiSpdHP->CompOnFlowRatio = MSHeatPump(MSHeatPumpNum).CoolingSpeedRatio(1);
    2368            1 :                 MSHeatPump(MSHeatPumpNum).LastMode = ModeOfOperation::CoolingMode;
    2369              :             } else {
    2370            0 :                 state.dataHVACMultiSpdHP->CompOnMassFlow = MSHeatPump(MSHeatPumpNum).IdleMassFlowRate;
    2371            0 :                 state.dataHVACMultiSpdHP->CompOnFlowRatio = MSHeatPump(MSHeatPumpNum).IdleSpeedRatio;
    2372              :             }
    2373            2 :             state.dataHVACMultiSpdHP->CompOffMassFlow = MSHeatPump(MSHeatPumpNum).IdleMassFlowRate;
    2374            2 :             state.dataHVACMultiSpdHP->CompOffFlowRatio = MSHeatPump(MSHeatPumpNum).IdleSpeedRatio;
    2375              :         } else {
    2376              :             // cycling fan mode
    2377            0 :             if (QZnReq > HVAC::SmallLoad && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
    2378            0 :                 state.dataHVACMultiSpdHP->CompOnMassFlow = MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(1);
    2379            0 :                 state.dataHVACMultiSpdHP->CompOnFlowRatio = MSHeatPump(MSHeatPumpNum).HeatingSpeedRatio(1);
    2380            0 :             } else if (QZnReq < (-1.0 * HVAC::SmallLoad) && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
    2381            0 :                 state.dataHVACMultiSpdHP->CompOnMassFlow = MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(1);
    2382            0 :                 state.dataHVACMultiSpdHP->CompOnFlowRatio = MSHeatPump(MSHeatPumpNum).CoolingSpeedRatio(1);
    2383              :             } else {
    2384            0 :                 state.dataHVACMultiSpdHP->CompOnMassFlow = 0.0;
    2385            0 :                 state.dataHVACMultiSpdHP->CompOnFlowRatio = 0.0;
    2386              :             }
    2387            0 :             state.dataHVACMultiSpdHP->CompOffMassFlow = 0.0;
    2388            0 :             state.dataHVACMultiSpdHP->CompOffFlowRatio = 0.0;
    2389              :         }
    2390              : 
    2391              :         // Set the inlet node mass flow rate
    2392            2 :         if (MSHeatPump(MSHeatPumpNum).availSched->getCurrentVal() > 0.0 && state.dataHVACMultiSpdHP->CompOnMassFlow != 0.0) {
    2393            2 :             OnOffAirFlowRatio = 1.0;
    2394            2 :             if (FirstHVACIteration) {
    2395            2 :                 state.dataLoopNodes->Node(MSHeatPump(MSHeatPumpNum).AirInletNodeNum).MassFlowRate = state.dataHVACMultiSpdHP->CompOnMassFlow;
    2396            2 :                 PartLoadFrac = 0.0;
    2397              :             } else {
    2398            0 :                 if (MSHeatPump(MSHeatPumpNum).HeatCoolMode != ModeOfOperation::Invalid) {
    2399            0 :                     PartLoadFrac = 1.0;
    2400              :                 } else {
    2401            0 :                     PartLoadFrac = 0.0;
    2402              :                 }
    2403              :             }
    2404              :         } else {
    2405            0 :             PartLoadFrac = 0.0;
    2406            0 :             state.dataLoopNodes->Node(InNode).MassFlowRate = 0.0;
    2407            0 :             state.dataLoopNodes->Node(OutNode).MassFlowRate = 0.0;
    2408            0 :             state.dataLoopNodes->Node(OutNode).MassFlowRateMaxAvail = 0.0;
    2409            0 :             OnOffAirFlowRatio = 1.0;
    2410              :         }
    2411              : 
    2412              :         // Check availability of DX coils
    2413            2 :         if (MSHeatPump(MSHeatPumpNum).availSched->getCurrentVal() > 0.0) {
    2414            2 :             if (MSHeatPump(MSHeatPumpNum).HeatCoolMode == ModeOfOperation::CoolingMode) {
    2415            2 :                 auto *coilAvailSched = DXCoils::GetDXCoilAvailSched( // TODO: Why isn't this stored on the struct?
    2416              :                     state,
    2417              :                     "Coil:Cooling:DX:MultiSpeed",
    2418            1 :                     MSHeatPump(MSHeatPumpNum).DXCoolCoilName,
    2419              :                     ErrorsFound,
    2420            1 :                     MSHeatPump(MSHeatPumpNum).DXCoolCoilIndex);
    2421            1 :                 if (ErrorsFound) {
    2422            0 :                     ShowFatalError(state, "InitMSHeatPump, The previous error causes termination.");
    2423              :                 }
    2424            1 :                 if (coilAvailSched->getCurrentVal() == 0.0) {
    2425            0 :                     if (MSHeatPump(MSHeatPumpNum).CoolCountAvail == 0) {
    2426            0 :                         ++MSHeatPump(MSHeatPumpNum).CoolCountAvail;
    2427            0 :                         ShowWarningError(
    2428              :                             state,
    2429            0 :                             format("{} is ready to perform cooling, but its DX cooling coil = {} is not available at Available Schedule = {}.",
    2430            0 :                                    MSHeatPump(MSHeatPumpNum).Name,
    2431            0 :                                    MSHeatPump(MSHeatPumpNum).DXCoolCoilName,
    2432            0 :                                    coilAvailSched->Name));
    2433            0 :                         ShowContinueErrorTimeStamp(state, format("Availability schedule returned={:.1R}", coilAvailSched->getCurrentVal()));
    2434              :                     } else {
    2435            0 :                         ++MSHeatPump(MSHeatPumpNum).CoolCountAvail;
    2436            0 :                         ShowRecurringWarningErrorAtEnd(state,
    2437            0 :                                                        MSHeatPump(MSHeatPumpNum).Name + ": Cooling coil is still not available ...",
    2438            0 :                                                        MSHeatPump(MSHeatPumpNum).CoolIndexAvail,
    2439            0 :                                                        coilAvailSched->getCurrentVal(),
    2440            0 :                                                        coilAvailSched->getCurrentVal());
    2441              :                     }
    2442              :                 }
    2443              :             }
    2444            3 :             if (MSHeatPump(MSHeatPumpNum).HeatCoolMode == ModeOfOperation::HeatingMode &&
    2445            1 :                 MSHeatPump(MSHeatPumpNum).HeatCoilType == MultiSpeedHeatingCoil) {
    2446            2 :                 auto *coilAvailSched = DXCoils::GetDXCoilAvailSched(state,
    2447              :                                                                     "Coil:Heating:DX:MultiSpeed",
    2448            1 :                                                                     MSHeatPump(MSHeatPumpNum).DXHeatCoilName,
    2449              :                                                                     ErrorsFound,
    2450            1 :                                                                     MSHeatPump(MSHeatPumpNum).DXHeatCoilIndex);
    2451            1 :                 if (ErrorsFound) {
    2452            0 :                     ShowFatalError(state, "InitMSHeatPump, The previous error causes termination.");
    2453              :                 }
    2454            1 :                 if (coilAvailSched->getCurrentVal() == 0.0) {
    2455            0 :                     if (MSHeatPump(MSHeatPumpNum).HeatCountAvail == 0) {
    2456            0 :                         ++MSHeatPump(MSHeatPumpNum).HeatCountAvail;
    2457            0 :                         ShowWarningError(
    2458              :                             state,
    2459            0 :                             format("{} is ready to perform heating, but its DX heating coil = {} is not available at Available Schedule = {}.",
    2460            0 :                                    MSHeatPump(MSHeatPumpNum).Name,
    2461            0 :                                    MSHeatPump(MSHeatPumpNum).DXCoolCoilName,
    2462            0 :                                    coilAvailSched->Name));
    2463            0 :                         ShowContinueErrorTimeStamp(state, format("Availability schedule returned={:.1R}", coilAvailSched->getCurrentVal()));
    2464              :                     } else {
    2465            0 :                         ++MSHeatPump(MSHeatPumpNum).HeatCountAvail;
    2466            0 :                         ShowRecurringWarningErrorAtEnd(state,
    2467            0 :                                                        MSHeatPump(MSHeatPumpNum).Name + ": Heating coil is still not available ...",
    2468            0 :                                                        MSHeatPump(MSHeatPumpNum).HeatIndexAvail,
    2469            0 :                                                        coilAvailSched->getCurrentVal(),
    2470            0 :                                                        coilAvailSched->getCurrentVal());
    2471              :                     }
    2472              :                 }
    2473              :             }
    2474              :         }
    2475              : 
    2476            2 :         state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).CycRatio = 0.0;
    2477            2 :         state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedRatio = 0.0;
    2478            2 :         state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedNum = 0;
    2479              : 
    2480            2 :         CalcMSHeatPump(state,
    2481              :                        MSHeatPumpNum,
    2482              :                        FirstHVACIteration,
    2483              :                        HVAC::CompressorOp::On,
    2484              :                        1,
    2485              :                        0.0,
    2486              :                        PartLoadFrac,
    2487              :                        QSensUnitOut,
    2488              :                        QZnReq,
    2489              :                        OnOffAirFlowRatio,
    2490            2 :                        state.dataHVACMultiSpdHP->SupHeaterLoad);
    2491              : 
    2492            2 :         auto &e = MSHeatPump(MSHeatPumpNum);
    2493              :         {
    2494            2 :             e.TotHeatEnergyRate = 0.0;
    2495            2 :             e.SensHeatEnergyRate = 0.0;
    2496            2 :             e.LatHeatEnergyRate = 0.0;
    2497            2 :             e.TotCoolEnergyRate = 0.0;
    2498            2 :             e.SensCoolEnergyRate = 0.0;
    2499            2 :             e.LatCoolEnergyRate = 0.0;
    2500              :         }
    2501              :         // If unit is scheduled OFF, setpoint is equal to inlet node temperature.
    2502              :         //!!LKL Discrepancy with < 0
    2503            2 :         if (MSHeatPump(MSHeatPumpNum).availSched->getCurrentVal() == 0.0) {
    2504            0 :             state.dataLoopNodes->Node(OutNode).Temp = state.dataLoopNodes->Node(InNode).Temp;
    2505            0 :             return;
    2506              :         }
    2507              : 
    2508            4 :         if ((MSHeatPump(MSHeatPumpNum).HeatCoolMode == ModeOfOperation::Invalid && MSHeatPump(MSHeatPumpNum).fanOp == HVAC::FanOp::Cycling) ||
    2509            2 :             state.dataHVACMultiSpdHP->CompOnMassFlow == 0.0) {
    2510            0 :             QZnReq = 0.0;
    2511            0 :             PartLoadFrac = 0.0;
    2512            0 :             state.dataLoopNodes->Node(InNode).MassFlowRate = 0.0;
    2513            0 :             state.dataLoopNodes->Node(OutNode).MassFlowRateMaxAvail = 0.0;
    2514              :         }
    2515            2 :         MSHeatPump(MSHeatPumpNum).LoadMet = 0.0;
    2516            2 :         SetAverageAirFlow(state, MSHeatPumpNum, PartLoadFrac, OnOffAirFlowRatio);
    2517              : 
    2518              :         // Init maximum available Heat Recovery flow rate
    2519            2 :         if ((MSHeatPump(MSHeatPumpNum).HeatRecActive) && (!MSHeatPump(MSHeatPumpNum).MyPlantScantFlag)) {
    2520            0 :             if (PartLoadFrac > 0.0) {
    2521            0 :                 if (FirstHVACIteration) {
    2522            0 :                     MdotHR = MSHeatPump(MSHeatPumpNum).DesignHeatRecMassFlowRate;
    2523              :                 } else {
    2524            0 :                     if (MSHeatPump(MSHeatPumpNum).HeatRecoveryMassFlowRate > 0.0) {
    2525            0 :                         MdotHR = MSHeatPump(MSHeatPumpNum).HeatRecoveryMassFlowRate;
    2526              :                     } else {
    2527            0 :                         MdotHR = MSHeatPump(MSHeatPumpNum).DesignHeatRecMassFlowRate;
    2528              :                     }
    2529              :                 }
    2530              :             } else {
    2531            0 :                 MdotHR = 0.0;
    2532              :             }
    2533              : 
    2534            0 :             PlantUtilities::SetComponentFlowRate(state,
    2535              :                                                  MdotHR,
    2536            0 :                                                  MSHeatPump(MSHeatPumpNum).HeatRecInletNodeNum,
    2537            0 :                                                  MSHeatPump(MSHeatPumpNum).HeatRecOutletNodeNum,
    2538            0 :                                                  MSHeatPump(MSHeatPumpNum).HRPlantLoc);
    2539              :         }
    2540              : 
    2541              :         // get operating capacity of water and steam coil
    2542            2 :         if (FirstHVACIteration) {
    2543            2 :             if (MSHeatPump(MSHeatPumpNum).HeatCoilType == HVAC::Coil_HeatingWater) {
    2544              :                 //     set air-side and steam-side mass flow rates
    2545            0 :                 state.dataLoopNodes->Node(MSHeatPump(MSHeatPumpNum).CoilAirInletNode).MassFlowRate = state.dataHVACMultiSpdHP->CompOnMassFlow;
    2546            0 :                 mdot = MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow;
    2547            0 :                 PlantUtilities::SetComponentFlowRate(state,
    2548              :                                                      mdot,
    2549            0 :                                                      MSHeatPump(MSHeatPumpNum).CoilControlNode,
    2550            0 :                                                      MSHeatPump(MSHeatPumpNum).CoilOutletNode,
    2551            0 :                                                      MSHeatPump(MSHeatPumpNum).plantLoc);
    2552              :                 //     simulate water coil to find operating capacity
    2553            0 :                 WaterCoils::SimulateWaterCoilComponents(
    2554            0 :                     state, MSHeatPump(MSHeatPumpNum).HeatCoilName, FirstHVACIteration, MSHeatPump(MSHeatPumpNum).HeatCoilNum, QActual);
    2555              :             } // from IF(MSHeatPump(MSHeatPumpNum)%HeatCoilType == Coil_HeatingWater) THEN
    2556              : 
    2557            2 :             if (MSHeatPump(MSHeatPumpNum).HeatCoilType == HVAC::Coil_HeatingSteam) {
    2558              : 
    2559              :                 //     set air-side and steam-side mass flow rates
    2560            0 :                 state.dataLoopNodes->Node(MSHeatPump(MSHeatPumpNum).CoilAirInletNode).MassFlowRate = state.dataHVACMultiSpdHP->CompOnMassFlow;
    2561            0 :                 mdot = MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow;
    2562            0 :                 PlantUtilities::SetComponentFlowRate(state,
    2563              :                                                      mdot,
    2564            0 :                                                      MSHeatPump(MSHeatPumpNum).CoilControlNode,
    2565            0 :                                                      MSHeatPump(MSHeatPumpNum).CoilOutletNode,
    2566            0 :                                                      MSHeatPump(MSHeatPumpNum).plantLoc);
    2567              : 
    2568              :                 //     simulate steam coil to find operating capacity
    2569            0 :                 SteamCoils::SimulateSteamCoilComponents(state,
    2570            0 :                                                         MSHeatPump(MSHeatPumpNum).HeatCoilName,
    2571              :                                                         FirstHVACIteration,
    2572            0 :                                                         MSHeatPump(MSHeatPumpNum).HeatCoilNum,
    2573            0 :                                                         1.0,
    2574              :                                                         QActual); // QCoilReq, simulate any load > 0 to get max capacity of steam coil
    2575              : 
    2576              :             } // from IF(MSHeatPump(MSHeatPumpNum)%HeatCoilType == Coil_HeatingSteam) THEN
    2577            2 :             if (MSHeatPump(MSHeatPumpNum).SuppHeatCoilType == HVAC::Coil_HeatingWater) {
    2578              :                 //     set air-side and steam-side mass flow rates
    2579            0 :                 state.dataLoopNodes->Node(MSHeatPump(MSHeatPumpNum).SuppCoilAirInletNode).MassFlowRate = state.dataHVACMultiSpdHP->CompOnMassFlow;
    2580            0 :                 mdot = MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow;
    2581            0 :                 PlantUtilities::SetComponentFlowRate(state,
    2582              :                                                      mdot,
    2583            0 :                                                      MSHeatPump(MSHeatPumpNum).SuppCoilControlNode,
    2584            0 :                                                      MSHeatPump(MSHeatPumpNum).SuppCoilOutletNode,
    2585            0 :                                                      MSHeatPump(MSHeatPumpNum).SuppPlantLoc);
    2586              :                 //     simulate water coil to find operating capacity
    2587            0 :                 WaterCoils::SimulateWaterCoilComponents(
    2588            0 :                     state, MSHeatPump(MSHeatPumpNum).SuppHeatCoilName, FirstHVACIteration, MSHeatPump(MSHeatPumpNum).SuppHeatCoilNum, QActual);
    2589            0 :                 MSHeatPump(MSHeatPumpNum).DesignSuppHeatingCapacity = QActual;
    2590              : 
    2591              :             } // from IF(MSHeatPump(MSHeatPumpNum)%SuppHeatCoilType == Coil_HeatingWater) THEN
    2592              : 
    2593            2 :             if (MSHeatPump(MSHeatPumpNum).SuppHeatCoilType == HVAC::Coil_HeatingSteam) {
    2594              : 
    2595              :                 //     set air-side and steam-side mass flow rates
    2596            0 :                 state.dataLoopNodes->Node(MSHeatPump(MSHeatPumpNum).SuppCoilAirInletNode).MassFlowRate = state.dataHVACMultiSpdHP->CompOnMassFlow;
    2597            0 :                 mdot = MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow;
    2598            0 :                 PlantUtilities::SetComponentFlowRate(state,
    2599              :                                                      mdot,
    2600            0 :                                                      MSHeatPump(MSHeatPumpNum).SuppCoilControlNode,
    2601            0 :                                                      MSHeatPump(MSHeatPumpNum).SuppCoilOutletNode,
    2602            0 :                                                      MSHeatPump(MSHeatPumpNum).SuppPlantLoc);
    2603              : 
    2604              :                 //     simulate steam coil to find operating capacity
    2605            0 :                 SteamCoils::SimulateSteamCoilComponents(state,
    2606            0 :                                                         MSHeatPump(MSHeatPumpNum).SuppHeatCoilName,
    2607              :                                                         FirstHVACIteration,
    2608            0 :                                                         MSHeatPump(MSHeatPumpNum).SuppHeatCoilNum,
    2609            0 :                                                         1.0,
    2610              :                                                         QActual); // QCoilReq, simulate any load > 0 to get max capacity of steam coil
    2611            0 :                 MSHeatPump(MSHeatPumpNum).DesignSuppHeatingCapacity =
    2612            0 :                     SteamCoils::GetCoilCapacity(state, "Coil:Heating:Steam", MSHeatPump(MSHeatPumpNum).SuppHeatCoilName, ErrorsFound);
    2613              : 
    2614              :             } // from IF(MSHeatPump(MSHeatPumpNum)%SuppHeatCoilType == Coil_HeatingSteam) THEN
    2615              :         } // from IF( FirstHVACIteration ) THEN
    2616              :     }
    2617              : 
    2618              :     //******************************************************************************
    2619              : 
    2620            0 :     void SizeMSHeatPump(EnergyPlusData &state, int const MSHeatPumpNum) // Engine driven heat pump number
    2621              :     {
    2622              :         // SUBROUTINE INFORMATION:
    2623              :         //       AUTHOR:          Lixing Gu, FSEC
    2624              :         //       DATE WRITTEN:    June 2007
    2625              : 
    2626              :         // PURPOSE OF THIS SUBROUTINE:
    2627              :         // This subroutine is for sizing multispeed heat pump airflow rates and flow fraction.
    2628              : 
    2629              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2630              :         int NumOfSpeedCooling; // Number of speeds for cooling
    2631              :         int NumOfSpeedHeating; // Number of speeds for heating
    2632              :         int i;                 // Index to speed
    2633              : 
    2634            0 :         auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
    2635            0 :         if (state.dataSize->CurSysNum > 0 && state.dataSize->CurOASysNum == 0) {
    2636            0 :             state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanNum = MSHeatPump.FanNum;
    2637            0 :             state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanType = MSHeatPump.fanType;
    2638            0 :             state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanPlace = MSHeatPump.fanPlace;
    2639              :         }
    2640              : 
    2641            0 :         NumOfSpeedCooling = MSHeatPump.NumOfSpeedCooling;
    2642            0 :         NumOfSpeedHeating = MSHeatPump.NumOfSpeedHeating;
    2643              : 
    2644            0 :         for (i = NumOfSpeedCooling; i >= 1; --i) {
    2645              : 
    2646            0 :             if (MSHeatPump.CoolVolumeFlowRate(i) == DataSizing::AutoSize) {
    2647            0 :                 if (state.dataSize->CurSysNum > 0) {
    2648            0 :                     if (i == NumOfSpeedCooling) {
    2649            0 :                         CheckSysSizing(state, state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump.Name);
    2650            0 :                         MSHeatPump.CoolVolumeFlowRate(i) = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    2651            0 :                         if (MSHeatPump.FanVolFlow < MSHeatPump.CoolVolumeFlowRate(i) && MSHeatPump.FanVolFlow != DataSizing::AutoSize) {
    2652            0 :                             MSHeatPump.CoolVolumeFlowRate(i) = MSHeatPump.FanVolFlow;
    2653            0 :                             ShowWarningError(state, format("{} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump.Name));
    2654            0 :                             ShowContinueError(state,
    2655              :                                               "The supply air flow rate at high speed is less than the autosized value for the supply air flow rate "
    2656              :                                               "in cooling mode. Consider autosizing the fan for this simulation.");
    2657            0 :                             ShowContinueError(
    2658              :                                 state,
    2659              :                                 "The air flow rate at high speed in cooling mode is reset to the supply air flow rate and the simulation continues.");
    2660              :                         }
    2661              :                     } else {
    2662            0 :                         MSHeatPump.CoolVolumeFlowRate(i) = MSHeatPump.CoolVolumeFlowRate(NumOfSpeedCooling) * i / NumOfSpeedCooling;
    2663              :                     }
    2664            0 :                     if (MSHeatPump.CoolVolumeFlowRate(i) < HVAC::SmallAirVolFlow) {
    2665            0 :                         MSHeatPump.CoolVolumeFlowRate = 0.0;
    2666              :                     }
    2667              :                     // Ensure the flow rate at lower speed has to be less or equal to the flow rate at higher speed
    2668            0 :                     if (i != NumOfSpeedCooling) {
    2669            0 :                         if (MSHeatPump.CoolVolumeFlowRate(i) > MSHeatPump.CoolVolumeFlowRate(i + 1)) {
    2670            0 :                             MSHeatPump.CoolVolumeFlowRate(i) = MSHeatPump.CoolVolumeFlowRate(i + 1);
    2671              :                         }
    2672              :                     }
    2673            0 :                     BaseSizer::reportSizerOutput(state,
    2674            0 :                                                  state.dataHVACMultiSpdHP->CurrentModuleObject,
    2675              :                                                  MSHeatPump.Name,
    2676            0 :                                                  format("Speed {} Supply Air Flow Rate During Cooling Operation [m3/s]", i),
    2677            0 :                                                  MSHeatPump.CoolVolumeFlowRate(i));
    2678              :                 }
    2679              :             }
    2680              :         }
    2681              : 
    2682            0 :         for (i = NumOfSpeedHeating; i >= 1; --i) {
    2683            0 :             if (MSHeatPump.HeatVolumeFlowRate(i) == DataSizing::AutoSize) {
    2684            0 :                 if (state.dataSize->CurSysNum > 0) {
    2685            0 :                     if (i == NumOfSpeedHeating) {
    2686            0 :                         CheckSysSizing(state, state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump.Name);
    2687            0 :                         MSHeatPump.HeatVolumeFlowRate(i) = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    2688            0 :                         if (MSHeatPump.FanVolFlow < MSHeatPump.HeatVolumeFlowRate(i) && MSHeatPump.FanVolFlow != DataSizing::AutoSize) {
    2689            0 :                             MSHeatPump.HeatVolumeFlowRate(i) = MSHeatPump.FanVolFlow;
    2690            0 :                             ShowWarningError(state, format("{} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump.Name));
    2691            0 :                             ShowContinueError(state,
    2692              :                                               "The supply air flow rate at high speed is less than the autosized value for the maximum air flow rate "
    2693              :                                               "in heating mode. Consider autosizing the fan for this simulation.");
    2694            0 :                             ShowContinueError(state,
    2695              :                                               "The maximum air flow rate at high speed in heating mode is reset to the supply air flow rate and the "
    2696              :                                               "simulation continues.");
    2697              :                         }
    2698              :                     } else {
    2699            0 :                         MSHeatPump.HeatVolumeFlowRate(i) = MSHeatPump.HeatVolumeFlowRate(NumOfSpeedHeating) * i / NumOfSpeedHeating;
    2700              :                     }
    2701            0 :                     if (MSHeatPump.HeatVolumeFlowRate(i) < HVAC::SmallAirVolFlow) {
    2702            0 :                         MSHeatPump.HeatVolumeFlowRate(i) = 0.0;
    2703              :                     }
    2704              :                     // Ensure the flow rate at lower speed has to be less or equal to the flow rate at higher speed
    2705            0 :                     if (i != NumOfSpeedHeating) {
    2706            0 :                         if (MSHeatPump.HeatVolumeFlowRate(i) > MSHeatPump.HeatVolumeFlowRate(i + 1)) {
    2707            0 :                             MSHeatPump.HeatVolumeFlowRate(i) = MSHeatPump.HeatVolumeFlowRate(i + 1);
    2708              :                         }
    2709              :                     }
    2710            0 :                     BaseSizer::reportSizerOutput(state,
    2711            0 :                                                  state.dataHVACMultiSpdHP->CurrentModuleObject,
    2712              :                                                  MSHeatPump.Name,
    2713            0 :                                                  format("Speed{}Supply Air Flow Rate During Heating Operation [m3/s]", i),
    2714            0 :                                                  MSHeatPump.HeatVolumeFlowRate(i));
    2715              :                 }
    2716              :             }
    2717              :         }
    2718              : 
    2719            0 :         if (MSHeatPump.IdleVolumeAirRate == DataSizing::AutoSize) {
    2720            0 :             if (state.dataSize->CurSysNum > 0) {
    2721            0 :                 CheckSysSizing(state, state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump.Name);
    2722            0 :                 MSHeatPump.IdleVolumeAirRate = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
    2723            0 :                 if (MSHeatPump.FanVolFlow < MSHeatPump.IdleVolumeAirRate && MSHeatPump.FanVolFlow != DataSizing::AutoSize) {
    2724            0 :                     MSHeatPump.IdleVolumeAirRate = MSHeatPump.FanVolFlow;
    2725            0 :                     ShowWarningError(state, format("{} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump.Name));
    2726            0 :                     ShowContinueError(state,
    2727              :                                       "The supply air flow rate is less than the autosized value for the maximum air flow rate when no heating or "
    2728              :                                       "cooling is needed. Consider autosizing the fan for this simulation.");
    2729            0 :                     ShowContinueError(state,
    2730              :                                       "The maximum air flow rate when no heating or cooling is needed is reset to the supply air flow rate and the "
    2731              :                                       "simulation continues.");
    2732              :                 }
    2733            0 :                 if (MSHeatPump.IdleVolumeAirRate < HVAC::SmallAirVolFlow) {
    2734            0 :                     MSHeatPump.IdleVolumeAirRate = 0.0;
    2735              :                 }
    2736              : 
    2737            0 :                 BaseSizer::reportSizerOutput(state,
    2738            0 :                                              state.dataHVACMultiSpdHP->CurrentModuleObject,
    2739              :                                              MSHeatPump.Name,
    2740              :                                              "Supply Air Flow Rate When No Cooling or Heating is Needed [m3/s]",
    2741              :                                              MSHeatPump.IdleVolumeAirRate);
    2742              :             }
    2743              :         }
    2744              : 
    2745            0 :         if (MSHeatPump.SuppMaxAirTemp == DataSizing::AutoSize) {
    2746            0 :             if (state.dataSize->CurSysNum > 0) {
    2747            0 :                 if (MSHeatPump.SuppHeatCoilType == 1) { // Gas
    2748            0 :                     CheckZoneSizing(state, "Coil:Heating:Fuel", MSHeatPump.Name);
    2749              :                 } else {
    2750            0 :                     CheckZoneSizing(state, "Coil:Heating:Electric", MSHeatPump.Name);
    2751              :                 }
    2752            0 :                 MSHeatPump.SuppMaxAirTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatSupTemp;
    2753            0 :                 BaseSizer::reportSizerOutput(state,
    2754            0 :                                              state.dataHVACMultiSpdHP->CurrentModuleObject,
    2755              :                                              MSHeatPump.Name,
    2756              :                                              "Maximum Supply Air Temperature from Supplemental Heater [C]",
    2757              :                                              MSHeatPump.SuppMaxAirTemp);
    2758              :             }
    2759              :         }
    2760              : 
    2761            0 :         if (MSHeatPump.DesignSuppHeatingCapacity == DataSizing::AutoSize) {
    2762            0 :             if (state.dataSize->CurSysNum > 0) {
    2763            0 :                 if (MSHeatPump.SuppHeatCoilType == 1) { // Gas
    2764            0 :                     CheckSysSizing(state, "Coil:Heating:Fuel", MSHeatPump.Name);
    2765              :                 } else {
    2766            0 :                     CheckSysSizing(state, "Coil:Heating:Electric", MSHeatPump.Name);
    2767              :                 }
    2768            0 :                 MSHeatPump.DesignSuppHeatingCapacity = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatCap;
    2769              :             } else {
    2770            0 :                 MSHeatPump.DesignSuppHeatingCapacity = 0.0;
    2771              :             }
    2772            0 :             BaseSizer::reportSizerOutput(state,
    2773            0 :                                          state.dataHVACMultiSpdHP->CurrentModuleObject,
    2774              :                                          MSHeatPump.Name,
    2775              :                                          "Supplemental Heating Coil Nominal Capacity [W]",
    2776              :                                          MSHeatPump.DesignSuppHeatingCapacity);
    2777              :         }
    2778            0 :         state.dataSize->SuppHeatCap = MSHeatPump.DesignSuppHeatingCapacity;
    2779              : 
    2780            0 :         if (MSHeatPump.HeatRecActive) {
    2781            0 :             PlantUtilities::RegisterPlantCompDesignFlow(state, MSHeatPump.HeatRecInletNodeNum, MSHeatPump.DesignHeatRecFlowRate);
    2782              :         }
    2783            0 :     }
    2784              : 
    2785              :     //******************************************************************************
    2786              : 
    2787            4 :     void ControlMSHPOutputEMS(EnergyPlusData &state,
    2788              :                               int const MSHeatPumpNum,               // Unit index of engine driven heat pump
    2789              :                               bool const FirstHVACIteration,         // flag for 1st HVAC iteration in the time step
    2790              :                               HVAC::CompressorOp const compressorOp, // compressor operation; 1=on, 0=off
    2791              :                               HVAC::FanOp const fanOp,               // operating mode: FanOp::Cycling | FanOp::Continuous
    2792              :                               Real64 const QZnReq,                   // cooling or heating output needed by zone [W]
    2793              :                               Real64 const SpeedVal,                 // continuous speed value
    2794              :                               int &SpeedNum,                         // discrete speed level
    2795              :                               Real64 &SpeedRatio,                    // unit speed ratio for DX coils
    2796              :                               Real64 &PartLoadFrac,                  // unit part load fraction
    2797              :                               Real64 &OnOffAirFlowRatio,             // ratio of compressor ON airflow to AVERAGE airflow over timestep
    2798              :                               Real64 &SupHeaterLoad                  // Supplemental heater load [W]
    2799              : 
    2800              :     )
    2801              :     {
    2802            4 :         OnOffAirFlowRatio = 0.0;
    2803            4 :         SupHeaterLoad = 0.0;
    2804              : 
    2805            4 :         auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
    2806              : 
    2807              :         // Get EMS output
    2808            4 :         SpeedNum = ceil(SpeedVal);
    2809            4 :         bool useMaxedSpeed = false;
    2810            4 :         std::string useMaxedSpeedCoilName;
    2811            4 :         if (MSHeatPump.HeatCoolMode == ModeOfOperation::HeatingMode) {
    2812            4 :             if (SpeedNum > MSHeatPump.NumOfSpeedHeating) {
    2813            1 :                 SpeedNum = MSHeatPump.NumOfSpeedHeating;
    2814            1 :                 useMaxedSpeed = true;
    2815            1 :                 useMaxedSpeedCoilName = MSHeatPump.DXHeatCoilName;
    2816              :             }
    2817            0 :         } else if (MSHeatPump.HeatCoolMode == ModeOfOperation::CoolingMode) {
    2818            0 :             if (SpeedNum > MSHeatPump.NumOfSpeedCooling) {
    2819            0 :                 SpeedNum = MSHeatPump.NumOfSpeedCooling;
    2820            0 :                 useMaxedSpeed = true;
    2821            0 :                 useMaxedSpeedCoilName = MSHeatPump.DXCoolCoilName;
    2822              :             }
    2823              :         }
    2824            4 :         if (useMaxedSpeed) {
    2825            1 :             MSHeatPump.CoilSpeedErrIndex++;
    2826            8 :             ShowRecurringWarningErrorAtEnd(state,
    2827            2 :                                            "Wrong coil speed EMS override value, for unit=\"" + useMaxedSpeedCoilName +
    2828              :                                                "\". Exceeding maximum coil speed level. Speed level is set to the maximum coil speed level allowed.",
    2829            1 :                                            MSHeatPump.CoilSpeedErrIndex,
    2830              :                                            SpeedVal,
    2831              :                                            SpeedVal,
    2832              :                                            _,
    2833              :                                            "",
    2834              :                                            "");
    2835              :         }
    2836              :         // Calculate TempOutput
    2837            4 :         Real64 TempOutput = 0.0; // unit output when iteration limit exceeded [W]
    2838              : 
    2839            4 :         if (SpeedNum == 1) {
    2840            2 :             SpeedRatio = 0.0;
    2841            2 :             if (useMaxedSpeed || floor(SpeedVal) == SpeedVal) {
    2842            1 :                 PartLoadFrac = 1;
    2843              :             } else {
    2844            1 :                 PartLoadFrac = SpeedVal - floor(SpeedVal);
    2845              :             }
    2846            2 :             CalcMSHeatPump(state,
    2847              :                            MSHeatPumpNum,
    2848              :                            FirstHVACIteration,
    2849              :                            compressorOp,
    2850              :                            SpeedNum,
    2851              :                            SpeedRatio,
    2852              :                            PartLoadFrac,
    2853              :                            TempOutput,
    2854              :                            QZnReq,
    2855              :                            OnOffAirFlowRatio,
    2856              :                            SupHeaterLoad);
    2857              :         } else {
    2858            2 :             PartLoadFrac = 0.0;
    2859            2 :             if (useMaxedSpeed || floor(SpeedVal) == SpeedVal) {
    2860            1 :                 SpeedRatio = 1;
    2861              :             } else {
    2862            1 :                 SpeedRatio = SpeedVal - floor(SpeedVal);
    2863              :             }
    2864            2 :             CalcMSHeatPump(state,
    2865              :                            MSHeatPumpNum,
    2866              :                            FirstHVACIteration,
    2867              :                            compressorOp,
    2868              :                            SpeedNum,
    2869              :                            SpeedRatio,
    2870              :                            PartLoadFrac,
    2871              :                            TempOutput,
    2872              :                            QZnReq,
    2873              :                            OnOffAirFlowRatio,
    2874              :                            SupHeaterLoad);
    2875              :         }
    2876              : 
    2877            4 :         ControlMSHPSupHeater(state,
    2878              :                              MSHeatPumpNum,
    2879              :                              FirstHVACIteration,
    2880              :                              compressorOp,
    2881              :                              fanOp,
    2882              :                              QZnReq,
    2883              :                              TempOutput,
    2884              :                              SpeedNum,
    2885              :                              SpeedRatio,
    2886              :                              PartLoadFrac,
    2887              :                              OnOffAirFlowRatio,
    2888              :                              SupHeaterLoad);
    2889            4 :         state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).CycRatio = PartLoadFrac;
    2890            4 :         state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedRatio = SpeedRatio;
    2891            4 :         state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedNum = SpeedNum;
    2892            4 :     }
    2893              : 
    2894            4 :     void ControlMSHPSupHeater(EnergyPlusData &state,
    2895              :                               int const MSHeatPumpNum,               // Unit index of engine driven heat pump
    2896              :                               bool const FirstHVACIteration,         // flag for 1st HVAC iteration in the time step
    2897              :                               HVAC::CompressorOp const compressorOp, // compressor operation; 1=on, 0=off
    2898              :                               HVAC::FanOp const fanOp,               // operating mode: FanOp::Cycling | FanOp::Continuous
    2899              :                               Real64 const QZnReq,                   // cooling or heating output needed by zone [W]
    2900              :                               int const EMSOutput,                   // unit full output when compressor is operating [W]
    2901              :                               int const SpeedNum,                    // Speed number
    2902              :                               Real64 SpeedRatio,                     // unit speed ratio for DX coils
    2903              :                               Real64 PartLoadFrac,                   // unit part load fraction
    2904              :                               Real64 OnOffAirFlowRatio,              // ratio of compressor ON airflow to AVERAGE airflow over timestep
    2905              :                               Real64 &SupHeaterLoad                  // Supplemental heater load [W]
    2906              : 
    2907              :     )
    2908              :     {
    2909              :         // if the DX heating coil cannot meet the load, trim with supplemental heater
    2910              :         // occurs with constant fan mode when compressor is on or off
    2911              :         // occurs with cycling fan mode when compressor PLR is equal to 1
    2912            4 :         auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
    2913              : 
    2914            4 :         if ((QZnReq > HVAC::SmallLoad && QZnReq > EMSOutput)) {
    2915              :             Real64 TempOutput;
    2916            3 :             if (state.dataEnvrn->OutDryBulbTemp <= MSHeatPump.SuppMaxAirTemp) {
    2917            3 :                 SupHeaterLoad = QZnReq - EMSOutput;
    2918              :             } else {
    2919            0 :                 SupHeaterLoad = 0.0;
    2920              :             }
    2921            3 :             CalcMSHeatPump(state,
    2922              :                            MSHeatPumpNum,
    2923              :                            FirstHVACIteration,
    2924              :                            compressorOp,
    2925              :                            SpeedNum,
    2926              :                            SpeedRatio,
    2927              :                            PartLoadFrac,
    2928              :                            TempOutput,
    2929              :                            QZnReq,
    2930              :                            OnOffAirFlowRatio,
    2931              :                            SupHeaterLoad);
    2932              :         }
    2933              : 
    2934              :         // check the outlet of the supplemental heater to be lower than the maximum supplemental heater supply air temperature
    2935            4 :         if (state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).Temp > MSHeatPump.SuppMaxAirTemp && SupHeaterLoad > 0.0) {
    2936              : 
    2937              :             //   If the supply air temperature is to high, turn off the supplemental heater to recalculate the outlet temperature
    2938            0 :             SupHeaterLoad = 0.0;
    2939              :             Real64 QCoilActual; // coil load actually delivered returned to calling component
    2940            0 :             CalcNonDXHeatingCoils(state, MSHeatPumpNum, FirstHVACIteration, SupHeaterLoad, fanOp, QCoilActual);
    2941              : 
    2942              :             //   If the outlet temperature is below the maximum supplemental heater supply air temperature, reduce the load passed to
    2943              :             //   the supplemental heater, otherwise leave the supplemental heater off. If the supplemental heater is to be turned on,
    2944              :             //   use the outlet conditions when the supplemental heater was off (CALL above) as the inlet conditions for the calculation
    2945              :             //   of supplemental heater load to just meet the maximum supply air temperature from the supplemental heater.
    2946            0 :             if (state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).Temp < MSHeatPump.SuppMaxAirTemp) {
    2947            0 :                 Real64 CpAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).HumRat);
    2948            0 :                 SupHeaterLoad = state.dataLoopNodes->Node(MSHeatPump.AirInletNodeNum).MassFlowRate * CpAir *
    2949            0 :                                 (MSHeatPump.SuppMaxAirTemp - state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).Temp);
    2950              : 
    2951              :             } else {
    2952            0 :                 SupHeaterLoad = 0.0;
    2953              :             }
    2954              :         }
    2955            4 :     }
    2956              : 
    2957            8 :     void ControlMSHPOutput(EnergyPlusData &state,
    2958              :                            int const MSHeatPumpNum,               // Unit index of engine driven heat pump
    2959              :                            bool const FirstHVACIteration,         // flag for 1st HVAC iteration in the time step
    2960              :                            HVAC::CompressorOp const compressorOp, // compressor operation; 1=on, 0=off
    2961              :                            HVAC::FanOp const fanOp,               // operating mode: FanOp::Cycling | FanOp::Continuous
    2962              :                            Real64 const QZnReq,                   // cooling or heating output needed by zone [W]
    2963              :                            int const ZoneNum [[maybe_unused]],    // Index to zone number
    2964              :                            int &SpeedNum,                         // Speed number
    2965              :                            Real64 &SpeedRatio,                    // unit speed ratio for DX coils
    2966              :                            Real64 &PartLoadFrac,                  // unit part load fraction
    2967              :                            Real64 &OnOffAirFlowRatio,             // ratio of compressor ON airflow to AVERAGE airflow over timestep
    2968              :                            Real64 &SupHeaterLoad                  // Supplemental heater load [W]
    2969              :     )
    2970              :     {
    2971              : 
    2972              :         // SUBROUTINE INFORMATION:
    2973              :         //       AUTHOR         Lixing Gu
    2974              :         //       DATE WRITTEN   June 2007
    2975              :         //       RE-ENGINEERED  Revised for multispeed heat pump use based on ControlPTHPOutput
    2976              : 
    2977              :         // PURPOSE OF THIS SUBROUTINE:
    2978              :         // Determine the part load fraction at low speed, and speed ratio at high speed for this time step.
    2979              : 
    2980              :         // METHODOLOGY EMPLOYED:
    2981              :         // Use RegulaFalsi technique to iterate on part-load ratio until convergence is achieved.
    2982              : 
    2983              :         // SUBROUTINE PARAMETER DEFINITIONS:
    2984            8 :         int constexpr MaxIte(500); // maximum number of iterations
    2985              : 
    2986              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2987              :         Real64 FullOutput;         // unit full output when compressor is operating [W]
    2988              :         Real64 LowOutput;          // unit full output at low speed [W]
    2989              :         Real64 TempOutput;         // unit output when iteration limit exceeded [W]
    2990              :         Real64 NoCompOutput;       // output when no active compressor [W]
    2991              :         Real64 ErrorToler;         // error tolerance
    2992              :         int SolFla;                // Flag of RegulaFalsi solver
    2993              :         Real64 CpAir;              // air specific heat
    2994              :         Real64 OutsideDryBulbTemp; // Outside air temperature at external node height
    2995              :         Real64 QCoilActual;        // coil load actually delivered returned to calling component
    2996              :         int i;                     // Speed index
    2997              : 
    2998            8 :         SupHeaterLoad = 0.0;
    2999            8 :         PartLoadFrac = 0.0;
    3000            8 :         SpeedRatio = 0.0;
    3001            8 :         SpeedNum = 1;
    3002              : 
    3003            8 :         OutsideDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
    3004              : 
    3005            8 :         auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
    3006              : 
    3007              :         //!!LKL Discrepancy with < 0
    3008            8 :         if (MSHeatPump.availSched->getCurrentVal() == 0.0) {
    3009            1 :             return;
    3010              :         }
    3011              : 
    3012              :         // Get result when DX coil is off
    3013            8 :         CalcMSHeatPump(state,
    3014              :                        MSHeatPumpNum,
    3015              :                        FirstHVACIteration,
    3016              :                        compressorOp,
    3017              :                        SpeedNum,
    3018              :                        SpeedRatio,
    3019              :                        PartLoadFrac,
    3020              :                        NoCompOutput,
    3021              :                        QZnReq,
    3022              :                        OnOffAirFlowRatio,
    3023              :                        SupHeaterLoad);
    3024              : 
    3025              :         // If cooling and NoCompOutput < QZnReq, the coil needs to be off
    3026              :         // If heating and NoCompOutput > QZnReq, the coil needs to be off
    3027           16 :         if ((QZnReq < (-1.0 * HVAC::SmallLoad) && NoCompOutput < QZnReq) || (QZnReq > HVAC::SmallLoad && NoCompOutput > QZnReq) ||
    3028            8 :             std::abs(QZnReq) <= HVAC::SmallLoad) {
    3029            1 :             return;
    3030              :         }
    3031              : 
    3032              :         // Get full load result
    3033            7 :         PartLoadFrac = 1.0;
    3034            7 :         SpeedRatio = 1.0;
    3035            7 :         if (MSHeatPump.HeatCoolMode == ModeOfOperation::HeatingMode) {
    3036            3 :             SpeedNum = MSHeatPump.NumOfSpeedHeating;
    3037            3 :             if (MSHeatPump.Staged && std::abs(MSHeatPump.StageNum) < SpeedNum) {
    3038            0 :                 SpeedNum = std::abs(MSHeatPump.StageNum);
    3039            0 :                 if (SpeedNum == 1) {
    3040            0 :                     SpeedRatio = 0.0;
    3041              :                 }
    3042              :             }
    3043              :         }
    3044            7 :         if (MSHeatPump.HeatCoolMode == ModeOfOperation::CoolingMode) {
    3045            4 :             SpeedNum = MSHeatPump.NumOfSpeedCooling;
    3046            4 :             if (MSHeatPump.Staged && std::abs(MSHeatPump.StageNum) < SpeedNum) {
    3047            0 :                 SpeedNum = std::abs(MSHeatPump.StageNum);
    3048            0 :                 if (SpeedNum == 1) {
    3049            0 :                     SpeedRatio = 0.0;
    3050              :                 }
    3051              :             }
    3052              :         }
    3053              : 
    3054            7 :         CalcMSHeatPump(state,
    3055              :                        MSHeatPumpNum,
    3056              :                        FirstHVACIteration,
    3057              :                        compressorOp,
    3058              :                        SpeedNum,
    3059              :                        SpeedRatio,
    3060              :                        PartLoadFrac,
    3061              :                        FullOutput,
    3062              :                        QZnReq,
    3063              :                        OnOffAirFlowRatio,
    3064              :                        SupHeaterLoad);
    3065              : 
    3066            7 :         if (QZnReq < (-1.0 * HVAC::SmallLoad)) {
    3067              :             // Since we are cooling, we expect FullOutput to be < 0 and FullOutput < NoCompOutput
    3068              :             // Check that this is the case; if not set PartLoadFrac = 0.0 (off) and return
    3069            4 :             if (FullOutput >= 0.0 || FullOutput >= NoCompOutput) {
    3070            0 :                 PartLoadFrac = 0.0;
    3071            0 :                 SpeedRatio = 0.0;
    3072            0 :                 SpeedNum = 0;
    3073            0 :                 return;
    3074              :             }
    3075              :             //  ! If the QZnReq <= FullOutput the unit needs to run full out
    3076            4 :             if (QZnReq <= FullOutput) {
    3077            0 :                 PartLoadFrac = 1.0;
    3078            0 :                 SpeedRatio = 1.0;
    3079            0 :                 if (MSHeatPump.Staged && SpeedNum == 1) {
    3080            0 :                     SpeedRatio = 0.0;
    3081              :                 }
    3082            0 :                 state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).CycRatio = PartLoadFrac;
    3083            0 :                 state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedRatio = SpeedRatio;
    3084            0 :                 state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedNum = SpeedNum;
    3085            0 :                 return;
    3086              :             }
    3087            4 :             ErrorToler = 0.001; // Error tolerance for convergence from input deck
    3088              :         } else {
    3089              :             // Since we are heating, we expect FullOutput to be > 0 and FullOutput > NoCompOutput
    3090              :             // Check that this is the case; if not set PartLoadFrac = 0.0 (off)
    3091            3 :             if (FullOutput <= 0.0 || FullOutput <= NoCompOutput) {
    3092            0 :                 PartLoadFrac = 0.0;
    3093            0 :                 SpeedRatio = 0.0;
    3094              :                 // may need supplemental heating so don't return in heating mode
    3095              :             }
    3096            3 :             if (QZnReq >= FullOutput) {
    3097            1 :                 PartLoadFrac = 1.0;
    3098            1 :                 SpeedRatio = 1.0;
    3099              :                 // may need supplemental heating so don't return in heating mode
    3100              :             }
    3101            3 :             ErrorToler = 0.001; // Error tolerance for convergence from input deck
    3102              :         }
    3103              : 
    3104              :         // Direct solution
    3105            7 :         if (state.dataGlobal->DoCoilDirectSolutions && !MSHeatPump.Staged) {
    3106            3 :             Real64 TempOutput0 = 0.0;
    3107            3 :             MSHeatPump.FullOutput = 0.0;
    3108              : 
    3109              :             // heating
    3110            3 :             if (QZnReq > HVAC::SmallLoad && QZnReq < FullOutput) {
    3111            1 :                 CalcMSHeatPump(
    3112              :                     state, MSHeatPumpNum, FirstHVACIteration, compressorOp, 1, 0.0, 0.0, TempOutput0, QZnReq, OnOffAirFlowRatio, SupHeaterLoad);
    3113              : 
    3114            1 :                 for (int k = 1; k <= MSHeatPump.NumOfSpeedHeating; ++k) {
    3115            1 :                     if (k == 1) {
    3116            1 :                         CalcMSHeatPump(state,
    3117              :                                        MSHeatPumpNum,
    3118              :                                        FirstHVACIteration,
    3119              :                                        compressorOp,
    3120              :                                        k,
    3121              :                                        0.0,
    3122              :                                        1.0,
    3123            1 :                                        MSHeatPump.FullOutput(k),
    3124              :                                        QZnReq,
    3125              :                                        OnOffAirFlowRatio,
    3126              :                                        SupHeaterLoad);
    3127            1 :                         if (QZnReq <= MSHeatPump.FullOutput(k)) {
    3128            1 :                             SpeedNum = k;
    3129            1 :                             PartLoadFrac = (QZnReq - TempOutput0) / (MSHeatPump.FullOutput(k) - TempOutput0);
    3130            1 :                             CalcMSHeatPump(state,
    3131              :                                            MSHeatPumpNum,
    3132              :                                            FirstHVACIteration,
    3133              :                                            compressorOp,
    3134              :                                            k,
    3135              :                                            0.0,
    3136              :                                            PartLoadFrac,
    3137              :                                            TempOutput,
    3138              :                                            QZnReq,
    3139              :                                            OnOffAirFlowRatio,
    3140              :                                            SupHeaterLoad);
    3141            1 :                             break;
    3142              :                         }
    3143              :                     } else {
    3144            0 :                         CalcMSHeatPump(state,
    3145              :                                        MSHeatPumpNum,
    3146              :                                        FirstHVACIteration,
    3147              :                                        compressorOp,
    3148              :                                        k,
    3149              :                                        1.0,
    3150              :                                        1.0,
    3151            0 :                                        MSHeatPump.FullOutput(k),
    3152              :                                        QZnReq,
    3153              :                                        OnOffAirFlowRatio,
    3154              :                                        SupHeaterLoad);
    3155            0 :                         if (QZnReq <= MSHeatPump.FullOutput(k)) {
    3156            0 :                             SpeedNum = k;
    3157            0 :                             PartLoadFrac = 1.0;
    3158            0 :                             SpeedRatio = (QZnReq - MSHeatPump.FullOutput(k - 1)) / (MSHeatPump.FullOutput(k) - MSHeatPump.FullOutput(k - 1));
    3159            0 :                             CalcMSHeatPump(state,
    3160              :                                            MSHeatPumpNum,
    3161              :                                            FirstHVACIteration,
    3162              :                                            compressorOp,
    3163              :                                            k,
    3164              :                                            SpeedRatio,
    3165              :                                            1.0,
    3166              :                                            TempOutput,
    3167              :                                            QZnReq,
    3168              :                                            OnOffAirFlowRatio,
    3169              :                                            SupHeaterLoad);
    3170            0 :                             break;
    3171              :                         }
    3172              :                     }
    3173              :                 }
    3174              :             }
    3175              : 
    3176              :             // Cooling
    3177            3 :             if (QZnReq < (-1.0 * HVAC::SmallLoad) && QZnReq > FullOutput) {
    3178            2 :                 CalcMSHeatPump(
    3179              :                     state, MSHeatPumpNum, FirstHVACIteration, compressorOp, 1, 0.0, 0.0, TempOutput0, QZnReq, OnOffAirFlowRatio, SupHeaterLoad);
    3180            2 :                 for (int k = 1; k <= MSHeatPump.NumOfSpeedCooling; ++k) {
    3181            2 :                     if (k == 1) {
    3182            2 :                         CalcMSHeatPump(state,
    3183              :                                        MSHeatPumpNum,
    3184              :                                        FirstHVACIteration,
    3185              :                                        compressorOp,
    3186              :                                        k,
    3187              :                                        0.0,
    3188              :                                        1.0,
    3189            2 :                                        MSHeatPump.FullOutput(k),
    3190              :                                        QZnReq,
    3191              :                                        OnOffAirFlowRatio,
    3192              :                                        SupHeaterLoad);
    3193            2 :                         if (QZnReq >= MSHeatPump.FullOutput(k)) {
    3194            2 :                             SpeedNum = k;
    3195            2 :                             PartLoadFrac = (QZnReq - TempOutput0) / (MSHeatPump.FullOutput(k) - TempOutput0);
    3196            2 :                             CalcMSHeatPump(state,
    3197              :                                            MSHeatPumpNum,
    3198              :                                            FirstHVACIteration,
    3199              :                                            compressorOp,
    3200              :                                            k,
    3201              :                                            0.0,
    3202              :                                            PartLoadFrac,
    3203              :                                            TempOutput,
    3204              :                                            QZnReq,
    3205              :                                            OnOffAirFlowRatio,
    3206              :                                            SupHeaterLoad);
    3207            2 :                             break;
    3208              :                         }
    3209              :                     } else {
    3210            0 :                         CalcMSHeatPump(state,
    3211              :                                        MSHeatPumpNum,
    3212              :                                        FirstHVACIteration,
    3213              :                                        compressorOp,
    3214              :                                        k,
    3215              :                                        1.0,
    3216              :                                        1.0,
    3217            0 :                                        MSHeatPump.FullOutput(k),
    3218              :                                        QZnReq,
    3219              :                                        OnOffAirFlowRatio,
    3220              :                                        SupHeaterLoad);
    3221            0 :                         if (QZnReq >= MSHeatPump.FullOutput(k)) {
    3222            0 :                             SpeedNum = k;
    3223            0 :                             PartLoadFrac = 1.0;
    3224            0 :                             SpeedRatio = (QZnReq - MSHeatPump.FullOutput(k - 1)) / (MSHeatPump.FullOutput(k) - MSHeatPump.FullOutput(k - 1));
    3225            0 :                             CalcMSHeatPump(state,
    3226              :                                            MSHeatPumpNum,
    3227              :                                            FirstHVACIteration,
    3228              :                                            compressorOp,
    3229              :                                            k,
    3230              :                                            SpeedRatio,
    3231              :                                            1.0,
    3232              :                                            TempOutput,
    3233              :                                            QZnReq,
    3234              :                                            OnOffAirFlowRatio,
    3235              :                                            SupHeaterLoad);
    3236            0 :                             break;
    3237              :                         }
    3238              :                     }
    3239              :                 }
    3240              :             }
    3241              :         } else {
    3242              :             // Calculate the part load fraction
    3243            4 :             if (((QZnReq > HVAC::SmallLoad && QZnReq < FullOutput) || (QZnReq < (-1.0 * HVAC::SmallLoad) && QZnReq > FullOutput)) &&
    3244            3 :                 (!MSHeatPump.Staged)) {
    3245              :                 // Check whether the low speed coil can meet the load or not
    3246            3 :                 CalcMSHeatPump(
    3247              :                     state, MSHeatPumpNum, FirstHVACIteration, compressorOp, 1, 0.0, 1.0, LowOutput, QZnReq, OnOffAirFlowRatio, SupHeaterLoad);
    3248            3 :                 if ((QZnReq > 0.0 && QZnReq <= LowOutput) || (QZnReq < 0.0 && QZnReq >= LowOutput)) {
    3249            3 :                     SpeedRatio = 0.0;
    3250            3 :                     SpeedNum = 1;
    3251           12 :                     auto f = [&state, MSHeatPumpNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp](
    3252              :                                  Real64 const PartLoadFrac) {
    3253              :                         //  Calculates residual function ((ActualOutput - QZnReq)/QZnReq); MSHP output depends on PLR which is being varied to zero
    3254              :                         //  the residual.
    3255              :                         Real64 ActualOutput; // delivered capacity of MSHP
    3256            9 :                         Real64 tmpAirFlowRatio = OnOffAirFlowRatio;
    3257            9 :                         Real64 tmpHeaterLoad = SupHeaterLoad;
    3258            9 :                         CalcMSHeatPump(state,
    3259              :                                        MSHeatPumpNum,
    3260              :                                        FirstHVACIteration,
    3261              :                                        compressorOp,
    3262              :                                        1,
    3263              :                                        0.0,
    3264              :                                        PartLoadFrac,
    3265              :                                        ActualOutput,
    3266              :                                        QZnReq,
    3267              :                                        tmpAirFlowRatio,
    3268              :                                        tmpHeaterLoad);
    3269            9 :                         return (ActualOutput - QZnReq) / QZnReq;
    3270            3 :                     };
    3271            3 :                     General::SolveRoot(state, ErrorToler, MaxIte, SolFla, PartLoadFrac, f, 0.0, 1.0);
    3272            3 :                     if (SolFla == -1) {
    3273            0 :                         if (!state.dataGlobal->WarmupFlag) {
    3274            0 :                             if (state.dataHVACMultiSpdHP->ErrCountCyc == 0) {
    3275            0 :                                 ++state.dataHVACMultiSpdHP->ErrCountCyc; // TODO: Why is the error count shared among all heat pump units?
    3276            0 :                                 ShowWarningError(state,
    3277            0 :                                                  format("Iteration limit exceeded calculating DX unit cycling ratio, for unit={}", MSHeatPump.Name));
    3278            0 :                                 ShowContinueErrorTimeStamp(state, format("Cycling ratio returned={:.2R}", PartLoadFrac));
    3279              :                             } else {
    3280            0 :                                 ++state.dataHVACMultiSpdHP->ErrCountCyc;
    3281            0 :                                 ShowRecurringWarningErrorAtEnd(
    3282              :                                     state,
    3283            0 :                                     MSHeatPump.Name + "\": Iteration limit warning exceeding calculating DX unit cycling ratio  continues...",
    3284            0 :                                     MSHeatPump.ErrIndexCyc,
    3285              :                                     PartLoadFrac,
    3286              :                                     PartLoadFrac);
    3287              :                             }
    3288              :                         }
    3289            3 :                     } else if (SolFla == -2) {
    3290            0 :                         ShowFatalError(
    3291              :                             state,
    3292            0 :                             format("DX unit cycling ratio calculation failed: cycling limits exceeded, for unit={}", MSHeatPump.DXCoolCoilName));
    3293              :                     }
    3294            3 :                 } else {
    3295              :                     // Check to see which speed to meet the load
    3296            0 :                     PartLoadFrac = 1.0;
    3297            0 :                     SpeedRatio = 1.0;
    3298            0 :                     if (QZnReq < (-1.0 * HVAC::SmallLoad)) { // Cooling
    3299            0 :                         for (i = 2; i <= MSHeatPump.NumOfSpeedCooling; ++i) {
    3300            0 :                             CalcMSHeatPump(state,
    3301              :                                            MSHeatPumpNum,
    3302              :                                            FirstHVACIteration,
    3303              :                                            compressorOp,
    3304              :                                            i,
    3305              :                                            SpeedRatio,
    3306              :                                            PartLoadFrac,
    3307              :                                            TempOutput,
    3308              :                                            QZnReq,
    3309              :                                            OnOffAirFlowRatio,
    3310              :                                            SupHeaterLoad);
    3311            0 :                             if (QZnReq >= TempOutput) {
    3312            0 :                                 SpeedNum = i;
    3313            0 :                                 break;
    3314              :                             }
    3315              :                         }
    3316              :                     } else {
    3317            0 :                         for (i = 2; i <= MSHeatPump.NumOfSpeedHeating; ++i) {
    3318            0 :                             CalcMSHeatPump(state,
    3319              :                                            MSHeatPumpNum,
    3320              :                                            FirstHVACIteration,
    3321              :                                            compressorOp,
    3322              :                                            i,
    3323              :                                            SpeedRatio,
    3324              :                                            PartLoadFrac,
    3325              :                                            TempOutput,
    3326              :                                            QZnReq,
    3327              :                                            OnOffAirFlowRatio,
    3328              :                                            SupHeaterLoad);
    3329            0 :                             if (QZnReq <= TempOutput) {
    3330            0 :                                 SpeedNum = i;
    3331            0 :                                 break;
    3332              :                             }
    3333              :                         }
    3334              :                     }
    3335            0 :                     auto f = [&state, OnOffAirFlowRatio, SupHeaterLoad, MSHeatPumpNum, FirstHVACIteration, compressorOp, SpeedNum, QZnReq](
    3336              :                                  Real64 const SpeedRatio) {
    3337              :                         //  Calculates residual function ((ActualOutput - QZnReq)/QZnReq) MSHP output depends on PLR which is being varied to zero the
    3338              :                         //  residual.
    3339            0 :                         Real64 localAirFlowRatio = OnOffAirFlowRatio;
    3340            0 :                         Real64 localHeaterLoad = SupHeaterLoad;
    3341              :                         Real64 ActualOutput;
    3342            0 :                         CalcMSHeatPump(state,
    3343              :                                        MSHeatPumpNum,
    3344              :                                        FirstHVACIteration,
    3345              :                                        compressorOp,
    3346              :                                        SpeedNum,
    3347              :                                        SpeedRatio,
    3348              :                                        1.0,
    3349              :                                        ActualOutput,
    3350              :                                        QZnReq,
    3351              :                                        localAirFlowRatio,
    3352              :                                        localHeaterLoad);
    3353            0 :                         return (ActualOutput - QZnReq) / QZnReq;
    3354            0 :                     };
    3355            0 :                     General::SolveRoot(state, ErrorToler, MaxIte, SolFla, SpeedRatio, f, 0.0, 1.0);
    3356            0 :                     if (SolFla == -1) {
    3357            0 :                         if (!state.dataGlobal->WarmupFlag) {
    3358            0 :                             if (state.dataHVACMultiSpdHP->ErrCountVar == 0) {
    3359            0 :                                 ++state.dataHVACMultiSpdHP->ErrCountVar;
    3360            0 :                                 ShowWarningError(state,
    3361            0 :                                                  format("Iteration limit exceeded calculating DX unit speed ratio, for unit={}", MSHeatPump.Name));
    3362            0 :                                 ShowContinueErrorTimeStamp(state, format("Speed ratio returned=[{:.2R}], Speed number ={}", SpeedRatio, SpeedNum));
    3363              :                             } else {
    3364            0 :                                 ++state.dataHVACMultiSpdHP->ErrCountVar;
    3365            0 :                                 ShowRecurringWarningErrorAtEnd(
    3366              :                                     state,
    3367            0 :                                     MSHeatPump.Name + "\": Iteration limit warning exceeding calculating DX unit speed ratio continues...",
    3368            0 :                                     MSHeatPump.ErrIndexVar,
    3369              :                                     SpeedRatio,
    3370              :                                     SpeedRatio);
    3371              :                             }
    3372              :                         }
    3373            0 :                     } else if (SolFla == -2) {
    3374            0 :                         ShowFatalError(
    3375              :                             state,
    3376            0 :                             format("DX unit compressor speed calculation failed: speed limits exceeded, for unit={}", MSHeatPump.DXCoolCoilName));
    3377              :                     }
    3378              :                 }
    3379            3 :             } else {
    3380              :                 // Staged thermostat performance
    3381            1 :                 if (MSHeatPump.StageNum != 0) {
    3382            0 :                     SpeedNum = std::abs(MSHeatPump.StageNum);
    3383            0 :                     if (SpeedNum == 1) {
    3384            0 :                         CalcMSHeatPump(
    3385              :                             state, MSHeatPumpNum, FirstHVACIteration, compressorOp, 1, 0.0, 1.0, LowOutput, QZnReq, OnOffAirFlowRatio, SupHeaterLoad);
    3386            0 :                         SpeedRatio = 0.0;
    3387            0 :                         if ((QZnReq > 0.0 && QZnReq <= LowOutput) || (QZnReq < 0.0 && QZnReq >= LowOutput)) {
    3388            0 :                             auto f = [&state, MSHeatPumpNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp](
    3389              :                                          Real64 const PartLoadFrac) {
    3390              :                                 //  Calculates residual function ((ActualOutput - QZnReq)/QZnReq); MSHP output depends on PLR which is being varied to
    3391              :                                 //  zero the residual.
    3392              :                                 Real64 ActualOutput; // delivered capacity of MSHP
    3393            0 :                                 Real64 tmpAirFlowRatio = OnOffAirFlowRatio;
    3394            0 :                                 Real64 tmpHeaterLoad = SupHeaterLoad;
    3395            0 :                                 CalcMSHeatPump(state,
    3396              :                                                MSHeatPumpNum,
    3397              :                                                FirstHVACIteration,
    3398              :                                                compressorOp,
    3399              :                                                1,
    3400              :                                                0.0,
    3401              :                                                PartLoadFrac,
    3402              :                                                ActualOutput,
    3403              :                                                QZnReq,
    3404              :                                                tmpAirFlowRatio,
    3405              :                                                tmpHeaterLoad);
    3406            0 :                                 return (ActualOutput - QZnReq) / QZnReq;
    3407            0 :                             };
    3408            0 :                             General::SolveRoot(state, ErrorToler, MaxIte, SolFla, PartLoadFrac, f, 0.0, 1.0);
    3409            0 :                             if (SolFla == -1) {
    3410            0 :                                 if (!state.dataGlobal->WarmupFlag) {
    3411            0 :                                     if (state.dataHVACMultiSpdHP->ErrCountCyc == 0) {
    3412            0 :                                         ++state.dataHVACMultiSpdHP->ErrCountCyc;
    3413            0 :                                         ShowWarningError(
    3414              :                                             state,
    3415            0 :                                             format("Iteration limit exceeded calculating DX unit cycling ratio, for unit={}", MSHeatPump.Name));
    3416            0 :                                         ShowContinueErrorTimeStamp(state, format("Cycling ratio returned={:.2R}", PartLoadFrac));
    3417              :                                     } else {
    3418            0 :                                         ++state.dataHVACMultiSpdHP->ErrCountCyc;
    3419            0 :                                         ShowRecurringWarningErrorAtEnd(
    3420              :                                             state,
    3421            0 :                                             MSHeatPump.Name + "\": Iteration limit warning exceeding calculating DX unit cycling ratio  continues...",
    3422            0 :                                             MSHeatPump.ErrIndexCyc,
    3423              :                                             PartLoadFrac,
    3424              :                                             PartLoadFrac);
    3425              :                                     }
    3426              :                                 }
    3427            0 :                             } else if (SolFla == -2) {
    3428            0 :                                 ShowFatalError(state,
    3429            0 :                                                format("DX unit cycling ratio calculation failed: cycling limits exceeded, for unit={}",
    3430            0 :                                                       MSHeatPump.DXCoolCoilName));
    3431              :                             }
    3432            0 :                         } else {
    3433            0 :                             FullOutput = LowOutput;
    3434            0 :                             PartLoadFrac = 1.0;
    3435              :                         }
    3436              :                     } else {
    3437            0 :                         if (MSHeatPump.StageNum < 0) {
    3438            0 :                             SpeedNum = min(MSHeatPump.NumOfSpeedCooling, std::abs(MSHeatPump.StageNum));
    3439              :                         } else {
    3440            0 :                             SpeedNum = min(MSHeatPump.NumOfSpeedHeating, std::abs(MSHeatPump.StageNum));
    3441              :                         }
    3442            0 :                         CalcMSHeatPump(state,
    3443              :                                        MSHeatPumpNum,
    3444              :                                        FirstHVACIteration,
    3445              :                                        compressorOp,
    3446              :                                        SpeedNum,
    3447              :                                        0.0,
    3448              :                                        1.0,
    3449              :                                        LowOutput,
    3450              :                                        QZnReq,
    3451              :                                        OnOffAirFlowRatio,
    3452              :                                        SupHeaterLoad);
    3453            0 :                         if ((QZnReq > 0.0 && QZnReq >= LowOutput) || (QZnReq < 0.0 && QZnReq <= LowOutput)) {
    3454            0 :                             CalcMSHeatPump(state,
    3455              :                                            MSHeatPumpNum,
    3456              :                                            FirstHVACIteration,
    3457              :                                            compressorOp,
    3458              :                                            SpeedNum,
    3459              :                                            1.0,
    3460              :                                            1.0,
    3461              :                                            FullOutput,
    3462              :                                            QZnReq,
    3463              :                                            OnOffAirFlowRatio,
    3464              :                                            SupHeaterLoad);
    3465            0 :                             if ((QZnReq > 0.0 && QZnReq <= FullOutput) || (QZnReq < 0.0 && QZnReq >= FullOutput)) {
    3466              :                                 auto f = // (AUTO_OK_LAMBDA)
    3467            0 :                                     [&state, OnOffAirFlowRatio, SupHeaterLoad, MSHeatPumpNum, FirstHVACIteration, compressorOp, SpeedNum, QZnReq](
    3468              :                                         Real64 const SpeedRatio) {
    3469              :                                         //  Calculates residual function ((ActualOutput - QZnReq)/QZnReq) MSHP output depends on PLR which is being
    3470              :                                         //  varied to zero the residual.
    3471            0 :                                         Real64 localAirFlowRatio = OnOffAirFlowRatio;
    3472            0 :                                         Real64 localHeaterLoad = SupHeaterLoad;
    3473              :                                         Real64 ActualOutput;
    3474            0 :                                         CalcMSHeatPump(state,
    3475              :                                                        MSHeatPumpNum,
    3476              :                                                        FirstHVACIteration,
    3477              :                                                        compressorOp,
    3478              :                                                        SpeedNum,
    3479              :                                                        SpeedRatio,
    3480              :                                                        1.0,
    3481              :                                                        ActualOutput,
    3482              :                                                        QZnReq,
    3483              :                                                        localAirFlowRatio,
    3484              :                                                        localHeaterLoad);
    3485            0 :                                         return (ActualOutput - QZnReq) / QZnReq;
    3486            0 :                                     };
    3487            0 :                                 General::SolveRoot(state, ErrorToler, MaxIte, SolFla, SpeedRatio, f, 0.0, 1.0);
    3488            0 :                                 if (SolFla == -1) {
    3489            0 :                                     if (!state.dataGlobal->WarmupFlag) {
    3490            0 :                                         if (state.dataHVACMultiSpdHP->ErrCountVar == 0) {
    3491            0 :                                             ++state.dataHVACMultiSpdHP->ErrCountVar;
    3492            0 :                                             ShowWarningError(
    3493              :                                                 state,
    3494            0 :                                                 format("Iteration limit exceeded calculating DX unit speed ratio, for unit={}", MSHeatPump.Name));
    3495            0 :                                             ShowContinueErrorTimeStamp(
    3496            0 :                                                 state, format("Speed ratio returned=[{:.2R}], Speed number ={}", SpeedRatio, SpeedNum));
    3497              :                                         } else {
    3498            0 :                                             ++state.dataHVACMultiSpdHP->ErrCountVar;
    3499            0 :                                             ShowRecurringWarningErrorAtEnd(
    3500              :                                                 state,
    3501            0 :                                                 MSHeatPump.Name +
    3502              :                                                     "\": Iteration limit warning exceeding calculating DX unit speed ratio continues...",
    3503            0 :                                                 MSHeatPump.ErrIndexVar,
    3504              :                                                 SpeedRatio,
    3505              :                                                 SpeedRatio);
    3506              :                                         }
    3507              :                                     }
    3508            0 :                                 } else if (SolFla == -2) {
    3509            0 :                                     ShowFatalError(state,
    3510            0 :                                                    format("DX unit compressor speed calculation failed: speed limits exceeded, for unit={}",
    3511            0 :                                                           MSHeatPump.DXCoolCoilName));
    3512              :                                 }
    3513            0 :                             } else {
    3514            0 :                                 SpeedRatio = 1.0;
    3515              :                             }
    3516            0 :                         } else { // lowOutput provides a larger capacity than needed
    3517            0 :                             SpeedRatio = 0.0;
    3518              :                         }
    3519              :                     }
    3520              :                 }
    3521              :             }
    3522              :         }
    3523              : 
    3524              :         // if the DX heating coil cannot meet the load, trim with supplemental heater
    3525              :         // occurs with constant fan mode when compressor is on or off
    3526              :         // occurs with cycling fan mode when compressor PLR is equal to 1
    3527            7 :         if ((QZnReq > HVAC::SmallLoad && QZnReq > FullOutput)) {
    3528            1 :             PartLoadFrac = 1.0;
    3529            1 :             SpeedRatio = 1.0;
    3530            1 :             if (MSHeatPump.Staged && SpeedNum == 1) {
    3531            0 :                 SpeedRatio = 0.0;
    3532              :             }
    3533            1 :             if (OutsideDryBulbTemp <= MSHeatPump.SuppMaxAirTemp) {
    3534            1 :                 SupHeaterLoad = QZnReq - FullOutput;
    3535              :             } else {
    3536            0 :                 SupHeaterLoad = 0.0;
    3537              :             }
    3538            1 :             CalcMSHeatPump(state,
    3539              :                            MSHeatPumpNum,
    3540              :                            FirstHVACIteration,
    3541              :                            compressorOp,
    3542              :                            SpeedNum,
    3543              :                            SpeedRatio,
    3544              :                            PartLoadFrac,
    3545              :                            TempOutput,
    3546              :                            QZnReq,
    3547              :                            OnOffAirFlowRatio,
    3548              :                            SupHeaterLoad);
    3549              :         }
    3550              : 
    3551              :         // check the outlet of the supplemental heater to be lower than the maximum supplemental heater supply air temperature
    3552            7 :         if (state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).Temp > MSHeatPump.SuppMaxAirTemp && SupHeaterLoad > 0.0) {
    3553              : 
    3554              :             //   If the supply air temperature is to high, turn off the supplemental heater to recalculate the outlet temperature
    3555            0 :             SupHeaterLoad = 0.0;
    3556            0 :             CalcNonDXHeatingCoils(state, MSHeatPumpNum, FirstHVACIteration, SupHeaterLoad, fanOp, QCoilActual);
    3557              : 
    3558              :             //   If the outlet temperature is below the maximum supplemental heater supply air temperature, reduce the load passed to
    3559              :             //   the supplemental heater, otherwise leave the supplemental heater off. If the supplemental heater is to be turned on,
    3560              :             //   use the outlet conditions when the supplemental heater was off (CALL above) as the inlet conditions for the calculation
    3561              :             //   of supplemental heater load to just meet the maximum supply air temperature from the supplemental heater.
    3562            0 :             if (state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).Temp < MSHeatPump.SuppMaxAirTemp) {
    3563            0 :                 CpAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).HumRat);
    3564            0 :                 SupHeaterLoad = state.dataLoopNodes->Node(MSHeatPump.AirInletNodeNum).MassFlowRate * CpAir *
    3565            0 :                                 (MSHeatPump.SuppMaxAirTemp - state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).Temp);
    3566              : 
    3567              :             } else {
    3568            0 :                 SupHeaterLoad = 0.0;
    3569              :             }
    3570              :         }
    3571              : 
    3572            7 :         state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).CycRatio = PartLoadFrac;
    3573            7 :         state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedRatio = SpeedRatio;
    3574            7 :         state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedNum = SpeedNum;
    3575              :     }
    3576              : 
    3577              :     //******************************************************************************
    3578              : 
    3579           58 :     void CalcMSHeatPump(EnergyPlusData &state,
    3580              :                         int const MSHeatPumpNum,               // Engine driven heat pump number
    3581              :                         bool const FirstHVACIteration,         // Flag for 1st HVAC iteration
    3582              :                         HVAC::CompressorOp const compressorOp, // Compressor on/off; 1=on, 0=off
    3583              :                         int const SpeedNum,                    // Speed number
    3584              :                         Real64 const SpeedRatio,               // Compressor speed ratio
    3585              :                         Real64 const PartLoadFrac,             // Compressor part load fraction
    3586              :                         Real64 &LoadMet,                       // Load met by unit (W)
    3587              :                         Real64 const QZnReq,                   // Zone load (W)
    3588              :                         Real64 &OnOffAirFlowRatio,             // Ratio of compressor ON airflow to AVERAGE airflow over timestep
    3589              :                         Real64 &SupHeaterLoad                  // supplemental heater load (W)
    3590              :     )
    3591              :     {
    3592              :         // SUBROUTINE INFORMATION:
    3593              :         //       AUTHOR:          Lixing Gu, FSEC
    3594              :         //       DATE WRITTEN:    June 2007
    3595              : 
    3596              :         // PURPOSE OF THIS SUBROUTINE:
    3597              :         //  This routine will calculates MSHP performance based on given system load
    3598              : 
    3599              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3600              :         int OutletNode;            // MSHP air outlet node
    3601              :         int InletNode;             // MSHP air inlet node
    3602              :         Real64 OutsideDryBulbTemp; // Outdoor dry bulb temperature [C]
    3603              :         Real64 AirMassFlow;        // Air mass flow rate [kg/s]
    3604              :         Real64 SavePartloadRatio;
    3605              :         Real64 SaveSpeedRatio;
    3606              :         Real64 QCoilActual;  // coil load actually delivered returned to calling component
    3607              :         Real64 MinWaterFlow; // minimum water flow rate
    3608              :         Real64 ErrorToler;   // supplemental heating coil convergence tolerance
    3609              : 
    3610           58 :         auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
    3611              : 
    3612           58 :         OutletNode = MSHeatPump.AirOutletNodeNum;
    3613           58 :         InletNode = MSHeatPump.AirInletNodeNum;
    3614           58 :         if (MSHeatPump.DXHeatCoilIndex > 0) {
    3615           58 :             if (state.dataDXCoils->DXCoil(MSHeatPump.DXHeatCoilIndex).IsSecondaryDXCoilInZone) {
    3616            0 :                 OutsideDryBulbTemp =
    3617            0 :                     state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataDXCoils->DXCoil(MSHeatPump.DXHeatCoilIndex).SecZonePtr).ZT;
    3618              :             } else {
    3619           58 :                 OutsideDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
    3620              :             }
    3621            0 :         } else if (MSHeatPump.DXCoolCoilIndex > 0) {
    3622            0 :             if (state.dataDXCoils->DXCoil(MSHeatPump.DXCoolCoilIndex).IsSecondaryDXCoilInZone) {
    3623            0 :                 OutsideDryBulbTemp =
    3624            0 :                     state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataDXCoils->DXCoil(MSHeatPump.DXCoolCoilIndex).SecZonePtr).ZT;
    3625              :             } else {
    3626            0 :                 OutsideDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
    3627              :             }
    3628              :         } else {
    3629            0 :             OutsideDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
    3630              :         }
    3631              : 
    3632           58 :         state.dataHVACMultiSpdHP->SaveCompressorPLR = 0.0;
    3633           58 :         SavePartloadRatio = 0.0;
    3634           58 :         MinWaterFlow = 0.0;
    3635           58 :         ErrorToler = 0.001;
    3636              :         // Set inlet air mass flow rate based on PLR and compressor on/off air flow rates
    3637           58 :         SetAverageAirFlow(state, MSHeatPumpNum, PartLoadFrac, OnOffAirFlowRatio, SpeedNum, SpeedRatio);
    3638              : 
    3639           58 :         AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
    3640              :         // if blow through, simulate fan then coils
    3641           58 :         if (MSHeatPump.fanPlace == HVAC::FanPlace::BlowThru) {
    3642           58 :             state.dataFans->fans(MSHeatPump.FanNum)->simulate(state, FirstHVACIteration, state.dataHVACMultiSpdHP->FanSpeedRatio);
    3643           58 :             if (QZnReq < (-1.0 * HVAC::SmallLoad)) {
    3644           27 :                 if (OutsideDryBulbTemp > MSHeatPump.MinOATCompressorCooling) {
    3645           81 :                     DXCoils::SimDXCoilMultiSpeed(state,
    3646              :                                                  MSHeatPump.DXCoolCoilName,
    3647              :                                                  SpeedRatio,
    3648              :                                                  PartLoadFrac,
    3649           27 :                                                  MSHeatPump.DXCoolCoilIndex,
    3650              :                                                  SpeedNum,
    3651           27 :                                                  MSHeatPump.fanOp,
    3652              :                                                  compressorOp);
    3653           27 :                     SavePartloadRatio = PartLoadFrac;
    3654           27 :                     SaveSpeedRatio = SpeedRatio;
    3655              :                 } else {
    3656            0 :                     DXCoils::SimDXCoilMultiSpeed(
    3657            0 :                         state, MSHeatPump.DXCoolCoilName, 0.0, 0.0, MSHeatPump.DXCoolCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
    3658              :                 }
    3659           27 :                 state.dataHVACMultiSpdHP->SaveCompressorPLR = state.dataDXCoils->DXCoilPartLoadRatio(MSHeatPump.DXCoolCoilIndex);
    3660              :             } else {
    3661           93 :                 DXCoils::SimDXCoilMultiSpeed(
    3662           62 :                     state, MSHeatPump.DXCoolCoilName, 0.0, 0.0, MSHeatPump.DXCoolCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
    3663              :             }
    3664           58 :             if (MSHeatPump.HeatCoilType == MultiSpeedHeatingCoil) {
    3665           58 :                 if (QZnReq > HVAC::SmallLoad) {
    3666           29 :                     if (OutsideDryBulbTemp > MSHeatPump.MinOATCompressorHeating) {
    3667           87 :                         DXCoils::SimDXCoilMultiSpeed(state,
    3668              :                                                      MSHeatPump.DXHeatCoilName,
    3669              :                                                      SpeedRatio,
    3670              :                                                      PartLoadFrac,
    3671           29 :                                                      MSHeatPump.DXHeatCoilIndex,
    3672              :                                                      SpeedNum,
    3673           29 :                                                      MSHeatPump.fanOp,
    3674              :                                                      compressorOp);
    3675           29 :                         SavePartloadRatio = PartLoadFrac;
    3676           29 :                         SaveSpeedRatio = SpeedRatio;
    3677              :                     } else {
    3678            0 :                         DXCoils::SimDXCoilMultiSpeed(
    3679            0 :                             state, MSHeatPump.DXHeatCoilName, 0.0, 0.0, MSHeatPump.DXHeatCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
    3680              :                     }
    3681           29 :                     state.dataHVACMultiSpdHP->SaveCompressorPLR = state.dataDXCoils->DXCoilPartLoadRatio(MSHeatPump.DXHeatCoilIndex);
    3682              :                 } else {
    3683           87 :                     DXCoils::SimDXCoilMultiSpeed(
    3684           58 :                         state, MSHeatPump.DXHeatCoilName, 0.0, 0.0, MSHeatPump.DXHeatCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
    3685              :                 }
    3686            0 :             } else if (MSHeatPump.HeatCoilType == HVAC::Coil_HeatingElectric_MultiStage ||
    3687            0 :                        MSHeatPump.HeatCoilType == HVAC::Coil_HeatingGas_MultiStage) {
    3688            0 :                 if (QZnReq > HVAC::SmallLoad) {
    3689            0 :                     HeatingCoils::SimulateHeatingCoilComponents(
    3690            0 :                         state, MSHeatPump.HeatCoilName, FirstHVACIteration, _, 0, _, _, MSHeatPump.fanOp, PartLoadFrac, SpeedNum, SpeedRatio);
    3691              :                 } else {
    3692            0 :                     HeatingCoils::SimulateHeatingCoilComponents(
    3693            0 :                         state, MSHeatPump.HeatCoilName, FirstHVACIteration, _, 0, _, _, MSHeatPump.fanOp, 0.0, SpeedNum, 0.0);
    3694              :                 }
    3695              :             } else {
    3696            0 :                 CalcNonDXHeatingCoils(state, MSHeatPumpNum, FirstHVACIteration, QZnReq, MSHeatPump.fanOp, QCoilActual, PartLoadFrac);
    3697              :             }
    3698              :             // Call twice to ensure the fan outlet conditions are updated
    3699           58 :             state.dataFans->fans(MSHeatPump.FanNum)->simulate(state, FirstHVACIteration, state.dataHVACMultiSpdHP->FanSpeedRatio);
    3700           58 :             if (QZnReq < (-1.0 * HVAC::SmallLoad)) {
    3701           27 :                 if (OutsideDryBulbTemp > MSHeatPump.MinOATCompressorCooling) {
    3702           81 :                     DXCoils::SimDXCoilMultiSpeed(state,
    3703              :                                                  MSHeatPump.DXCoolCoilName,
    3704              :                                                  SpeedRatio,
    3705              :                                                  PartLoadFrac,
    3706           27 :                                                  MSHeatPump.DXCoolCoilIndex,
    3707              :                                                  SpeedNum,
    3708           27 :                                                  MSHeatPump.fanOp,
    3709              :                                                  compressorOp);
    3710           27 :                     SavePartloadRatio = PartLoadFrac;
    3711           27 :                     SaveSpeedRatio = SpeedRatio;
    3712              :                 } else {
    3713            0 :                     DXCoils::SimDXCoilMultiSpeed(
    3714            0 :                         state, MSHeatPump.DXCoolCoilName, 0.0, 0.0, MSHeatPump.DXCoolCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
    3715              :                 }
    3716           27 :                 state.dataHVACMultiSpdHP->SaveCompressorPLR = state.dataDXCoils->DXCoilPartLoadRatio(MSHeatPump.DXCoolCoilIndex);
    3717              :             } else {
    3718           93 :                 DXCoils::SimDXCoilMultiSpeed(
    3719           62 :                     state, MSHeatPump.DXCoolCoilName, 0.0, 0.0, MSHeatPump.DXCoolCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
    3720              :             }
    3721           58 :             if (MSHeatPump.HeatCoilType == MultiSpeedHeatingCoil) {
    3722           58 :                 if (QZnReq > HVAC::SmallLoad) {
    3723           29 :                     if (OutsideDryBulbTemp > MSHeatPump.MinOATCompressorHeating) {
    3724           87 :                         DXCoils::SimDXCoilMultiSpeed(state,
    3725              :                                                      MSHeatPump.DXHeatCoilName,
    3726              :                                                      SpeedRatio,
    3727              :                                                      PartLoadFrac,
    3728           29 :                                                      MSHeatPump.DXHeatCoilIndex,
    3729              :                                                      SpeedNum,
    3730           29 :                                                      MSHeatPump.fanOp,
    3731              :                                                      compressorOp);
    3732           29 :                         SavePartloadRatio = PartLoadFrac;
    3733           29 :                         SaveSpeedRatio = SpeedRatio;
    3734              :                     } else {
    3735            0 :                         DXCoils::SimDXCoilMultiSpeed(
    3736            0 :                             state, MSHeatPump.DXHeatCoilName, 0.0, 0.0, MSHeatPump.DXHeatCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
    3737              :                     }
    3738           29 :                     state.dataHVACMultiSpdHP->SaveCompressorPLR = state.dataDXCoils->DXCoilPartLoadRatio(MSHeatPump.DXHeatCoilIndex);
    3739              :                 } else {
    3740           87 :                     DXCoils::SimDXCoilMultiSpeed(
    3741           58 :                         state, MSHeatPump.DXHeatCoilName, 0.0, 0.0, MSHeatPump.DXHeatCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
    3742              :                 }
    3743            0 :             } else if (MSHeatPump.HeatCoilType == HVAC::Coil_HeatingElectric_MultiStage ||
    3744            0 :                        MSHeatPump.HeatCoilType == HVAC::Coil_HeatingGas_MultiStage) {
    3745            0 :                 if (QZnReq > HVAC::SmallLoad) {
    3746            0 :                     HeatingCoils::SimulateHeatingCoilComponents(
    3747            0 :                         state, MSHeatPump.HeatCoilName, FirstHVACIteration, _, 0, _, _, MSHeatPump.fanOp, PartLoadFrac, SpeedNum, SpeedRatio);
    3748              :                 } else {
    3749            0 :                     HeatingCoils::SimulateHeatingCoilComponents(
    3750            0 :                         state, MSHeatPump.HeatCoilName, FirstHVACIteration, _, 0, _, _, MSHeatPump.fanOp, 0.0, SpeedNum, 0.0);
    3751              :                 }
    3752              :             } else {
    3753            0 :                 CalcNonDXHeatingCoils(state, MSHeatPumpNum, FirstHVACIteration, QZnReq, MSHeatPump.fanOp, QCoilActual, PartLoadFrac);
    3754              :             }
    3755              :             //  Simulate supplemental heating coil for blow through fan
    3756           58 :             if (MSHeatPump.SuppHeatCoilNum > 0) {
    3757           58 :                 CalcNonDXHeatingCoils(state, MSHeatPumpNum, FirstHVACIteration, SupHeaterLoad, MSHeatPump.fanOp, QCoilActual);
    3758              :             }
    3759              :         } else { // otherwise simulate DX coils then fan then supplemental heater
    3760            0 :             if (QZnReq < (-1.0 * HVAC::SmallLoad)) {
    3761            0 :                 if (OutsideDryBulbTemp > MSHeatPump.MinOATCompressorCooling) {
    3762            0 :                     DXCoils::SimDXCoilMultiSpeed(state,
    3763              :                                                  MSHeatPump.DXCoolCoilName,
    3764              :                                                  SpeedRatio,
    3765              :                                                  PartLoadFrac,
    3766            0 :                                                  MSHeatPump.DXCoolCoilIndex,
    3767              :                                                  SpeedNum,
    3768            0 :                                                  MSHeatPump.fanOp,
    3769              :                                                  compressorOp);
    3770            0 :                     SavePartloadRatio = PartLoadFrac;
    3771            0 :                     SaveSpeedRatio = SpeedRatio;
    3772              :                 } else {
    3773            0 :                     DXCoils::SimDXCoilMultiSpeed(
    3774            0 :                         state, MSHeatPump.DXCoolCoilName, 0.0, 0.0, MSHeatPump.DXCoolCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
    3775              :                 }
    3776            0 :                 state.dataHVACMultiSpdHP->SaveCompressorPLR = state.dataDXCoils->DXCoilPartLoadRatio(MSHeatPump.DXCoolCoilIndex);
    3777              :             } else {
    3778            0 :                 DXCoils::SimDXCoilMultiSpeed(
    3779            0 :                     state, MSHeatPump.DXCoolCoilName, 0.0, 0.0, MSHeatPump.DXCoolCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
    3780              :             }
    3781            0 :             if (MSHeatPump.HeatCoilType == MultiSpeedHeatingCoil) {
    3782            0 :                 if (QZnReq > HVAC::SmallLoad) {
    3783            0 :                     if (OutsideDryBulbTemp > MSHeatPump.MinOATCompressorHeating) {
    3784            0 :                         DXCoils::SimDXCoilMultiSpeed(state,
    3785              :                                                      MSHeatPump.DXHeatCoilName,
    3786              :                                                      SpeedRatio,
    3787              :                                                      PartLoadFrac,
    3788            0 :                                                      MSHeatPump.DXHeatCoilIndex,
    3789              :                                                      SpeedNum,
    3790            0 :                                                      MSHeatPump.fanOp,
    3791              :                                                      compressorOp);
    3792            0 :                         SavePartloadRatio = PartLoadFrac;
    3793            0 :                         SaveSpeedRatio = SpeedRatio;
    3794              :                     } else {
    3795            0 :                         DXCoils::SimDXCoilMultiSpeed(
    3796            0 :                             state, MSHeatPump.DXHeatCoilName, 0.0, 0.0, MSHeatPump.DXHeatCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
    3797              :                     }
    3798            0 :                     state.dataHVACMultiSpdHP->SaveCompressorPLR = state.dataDXCoils->DXCoilPartLoadRatio(MSHeatPump.DXHeatCoilIndex);
    3799              :                 } else {
    3800            0 :                     DXCoils::SimDXCoilMultiSpeed(
    3801            0 :                         state, MSHeatPump.DXHeatCoilName, 0.0, 0.0, MSHeatPump.DXHeatCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
    3802              :                 }
    3803            0 :             } else if (MSHeatPump.HeatCoilType == HVAC::Coil_HeatingElectric_MultiStage ||
    3804            0 :                        MSHeatPump.HeatCoilType == HVAC::Coil_HeatingGas_MultiStage) {
    3805            0 :                 if (QZnReq > HVAC::SmallLoad) {
    3806            0 :                     HeatingCoils::SimulateHeatingCoilComponents(
    3807            0 :                         state, MSHeatPump.HeatCoilName, FirstHVACIteration, _, 0, _, _, MSHeatPump.fanOp, PartLoadFrac, SpeedNum, SpeedRatio);
    3808              :                 } else {
    3809            0 :                     HeatingCoils::SimulateHeatingCoilComponents(
    3810            0 :                         state, MSHeatPump.HeatCoilName, FirstHVACIteration, _, 0, _, _, MSHeatPump.fanOp, 0.0, SpeedNum, 0.0);
    3811              :                 }
    3812              :             } else {
    3813            0 :                 CalcNonDXHeatingCoils(state, MSHeatPumpNum, FirstHVACIteration, QZnReq, MSHeatPump.fanOp, QCoilActual, PartLoadFrac);
    3814              :             }
    3815            0 :             state.dataFans->fans(MSHeatPump.FanNum)->simulate(state, FirstHVACIteration, state.dataHVACMultiSpdHP->FanSpeedRatio);
    3816              :             //  Simulate supplemental heating coil for draw through fan
    3817            0 :             if (MSHeatPump.SuppHeatCoilNum > 0) {
    3818            0 :                 CalcNonDXHeatingCoils(state, MSHeatPumpNum, FirstHVACIteration, SupHeaterLoad, MSHeatPump.fanOp, QCoilActual);
    3819              :             }
    3820              :         }
    3821              : 
    3822              :         // calculate sensible load met
    3823           58 :         Real64 SensibleOutput(0.0); // sensible output rate
    3824              :         // calculate sensible load met using delta enthalpy at a constant (minimum) humidity ratio)
    3825           58 :         Real64 MinHumRat = state.dataLoopNodes->Node(MSHeatPump.NodeNumOfControlledZone).HumRat;
    3826           58 :         if (state.dataLoopNodes->Node(OutletNode).Temp < state.dataLoopNodes->Node(MSHeatPump.NodeNumOfControlledZone).Temp) {
    3827           22 :             MinHumRat = state.dataLoopNodes->Node(OutletNode).HumRat;
    3828              :         }
    3829           58 :         SensibleOutput = AirMassFlow * Psychrometrics::PsyDeltaHSenFnTdb2W2Tdb1W1(state.dataLoopNodes->Node(OutletNode).Temp,
    3830              :                                                                                   MinHumRat,
    3831           58 :                                                                                   state.dataLoopNodes->Node(MSHeatPump.NodeNumOfControlledZone).Temp,
    3832              :                                                                                   MinHumRat);
    3833           58 :         LoadMet = SensibleOutput - MSHeatPump.LoadLoss;
    3834              : 
    3835           58 :         MSHeatPump.LoadMet = LoadMet;
    3836           58 :     }
    3837              : 
    3838            0 :     void UpdateMSHeatPump(EnergyPlusData &state, int const MSHeatPumpNum) // Engine driven heat pump number
    3839              :     {
    3840              :         // SUBROUTINE INFORMATION:
    3841              :         //       AUTHOR:          Lixing Gu, FSEC
    3842              :         //       DATE WRITTEN:    June 2007
    3843              : 
    3844              :         // PURPOSE OF THIS SUBROUTINE:
    3845              :         //  This routine will update MSHP performance and calculate heat recovery rate and crankcase heater power
    3846              : 
    3847              :         // Calculate heat recovery
    3848            0 :         if (state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatRecActive) {
    3849            0 :             MSHPHeatRecovery(state, MSHeatPumpNum);
    3850              :         }
    3851              : 
    3852            0 :         if (state.afn->distribution_simulated) {
    3853            0 :             state.dataAirLoop->AirLoopAFNInfo(state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).AirLoopNumber).LoopSystemOnMassFlowrate =
    3854            0 :                 state.dataHVACMultiSpdHP->CompOnMassFlow;
    3855            0 :             state.dataAirLoop->AirLoopAFNInfo(state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).AirLoopNumber).LoopSystemOffMassFlowrate =
    3856            0 :                 state.dataHVACMultiSpdHP->CompOffMassFlow;
    3857            0 :             state.dataAirLoop->AirLoopAFNInfo(state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).AirLoopNumber).LoopFanOperationMode =
    3858            0 :                 state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).fanOp;
    3859            0 :             state.dataAirLoop->AirLoopAFNInfo(state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).AirLoopNumber).LoopOnOffFanPartLoadRatio =
    3860            0 :                 state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).FanPartLoadRatio;
    3861            0 :             state.dataAirLoop->AirLoopAFNInfo(state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).AirLoopNumber).LoopCompCycRatio =
    3862            0 :                 state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).CycRatio;
    3863              :         }
    3864            0 :     }
    3865              : 
    3866              :     //******************************************************************************
    3867              : 
    3868            0 :     void ReportMSHeatPump(EnergyPlusData &state, int const MSHeatPumpNum) // Engine driven heat pump number
    3869              :     {
    3870              :         // SUBROUTINE INFORMATION:
    3871              :         //       AUTHOR:          Lixing Gu, FSEC
    3872              :         //       DATE WRITTEN:    June 2007
    3873              : 
    3874              :         // PURPOSE OF THIS SUBROUTINE:
    3875              :         //  This routine will write values to output variables in MSHP
    3876              : 
    3877            0 :         Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    3878              : 
    3879            0 :         auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
    3880            0 :         auto &MSHeatPumpReport = state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum);
    3881              : 
    3882            0 :         MSHeatPumpReport.ElecPowerConsumption = MSHeatPump.ElecPower * TimeStepSysSec; // + &
    3883            0 :         MSHeatPumpReport.HeatRecoveryEnergy = MSHeatPump.HeatRecoveryRate * TimeStepSysSec;
    3884              : 
    3885            0 :         MSHeatPumpReport.AuxElecHeatConsumption = 0.0;
    3886            0 :         MSHeatPumpReport.AuxElecCoolConsumption = 0.0;
    3887              : 
    3888            0 :         MSHeatPump.AuxElecPower = MSHeatPump.AuxOnCyclePower * state.dataHVACMultiSpdHP->SaveCompressorPLR +
    3889            0 :                                   MSHeatPump.AuxOffCyclePower * (1.0 - state.dataHVACMultiSpdHP->SaveCompressorPLR);
    3890            0 :         if (MSHeatPump.HeatCoolMode == ModeOfOperation::CoolingMode) {
    3891            0 :             MSHeatPumpReport.AuxElecCoolConsumption = MSHeatPump.AuxOnCyclePower * state.dataHVACMultiSpdHP->SaveCompressorPLR * TimeStepSysSec;
    3892              :         }
    3893            0 :         if (MSHeatPump.HeatCoolMode == ModeOfOperation::HeatingMode) {
    3894            0 :             MSHeatPumpReport.AuxElecHeatConsumption = MSHeatPump.AuxOnCyclePower * state.dataHVACMultiSpdHP->SaveCompressorPLR * TimeStepSysSec;
    3895              :         }
    3896            0 :         if (MSHeatPump.LastMode == ModeOfOperation::HeatingMode) {
    3897            0 :             MSHeatPumpReport.AuxElecHeatConsumption +=
    3898            0 :                 MSHeatPump.AuxOffCyclePower * (1.0 - state.dataHVACMultiSpdHP->SaveCompressorPLR) * TimeStepSysSec;
    3899              :         } else {
    3900            0 :             MSHeatPumpReport.AuxElecCoolConsumption +=
    3901            0 :                 MSHeatPump.AuxOffCyclePower * (1.0 - state.dataHVACMultiSpdHP->SaveCompressorPLR) * TimeStepSysSec;
    3902              :         }
    3903              : 
    3904            0 :         if (MSHeatPump.FirstPass) {
    3905            0 :             if (!state.dataGlobal->SysSizingCalc) {
    3906            0 :                 DataSizing::resetHVACSizingGlobals(state, state.dataSize->CurZoneEqNum, state.dataSize->CurSysNum, MSHeatPump.FirstPass);
    3907              :             }
    3908              :         }
    3909              : 
    3910              :         // reset to 1 in case blow through fan configuration (fan resets to 1, but for blow thru fans coil sets back down < 1)
    3911            0 :         state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
    3912            0 :     }
    3913              : 
    3914            3 :     void MSHPHeatRecovery(EnergyPlusData &state, int const MSHeatPumpNum) // Number of the current electric MSHP being simulated
    3915              :     {
    3916              :         // SUBROUTINE INFORMATION:
    3917              :         //       AUTHOR:          Lixing Gu
    3918              :         //       DATE WRITTEN:    June 2007
    3919              :         //       RE-ENGINEERED    Revised to calculate MSHP heat recovery rate based on EIR Chiller heat recovery subroutine
    3920              :         // PURPOSE OF THIS SUBROUTINE:
    3921              :         //  Calculate the heat recovered from MSHP
    3922              : 
    3923              :         // SUBROUTINE PARAMETER DEFINITIONS:
    3924              :         static constexpr std::string_view RoutineName("MSHPHeatRecovery");
    3925              : 
    3926              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3927              :         Real64 HeatRecOutletTemp; // Heat reclaim outlet temp [C]
    3928              : 
    3929            3 :         auto &mshp = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
    3930              :         // Begin routine
    3931            3 :         int HeatRecInNode = mshp.HeatRecInletNodeNum;
    3932            3 :         int HeatRecOutNode = mshp.HeatRecOutletNodeNum;
    3933              : 
    3934              :         // Inlet node to the heat recovery heat exchanger
    3935            3 :         Real64 HeatRecInletTemp = state.dataLoopNodes->Node(HeatRecInNode).Temp;
    3936              : 
    3937              :         // Set heat recovery mass flow rates
    3938            3 :         Real64 HeatRecMassFlowRate = state.dataLoopNodes->Node(HeatRecInNode).MassFlowRate;
    3939              : 
    3940            3 :         Real64 QHeatRec = state.dataHVACGlobal->MSHPWasteHeat;
    3941              : 
    3942            3 :         if (HeatRecMassFlowRate > 0.0) {
    3943              :             // Heat reclaim water inlet specific heat [J/kg-K]
    3944            2 :             Real64 CpHeatRec = state.dataPlnt->PlantLoop(mshp.HRPlantLoc.loopNum).glycol->getSpecificHeat(state, HeatRecInletTemp, RoutineName);
    3945              : 
    3946            2 :             HeatRecOutletTemp = QHeatRec / (HeatRecMassFlowRate * CpHeatRec) + HeatRecInletTemp;
    3947            2 :             if (HeatRecOutletTemp > mshp.MaxHeatRecOutletTemp) {
    3948            1 :                 HeatRecOutletTemp = max(HeatRecInletTemp, mshp.MaxHeatRecOutletTemp);
    3949            1 :                 QHeatRec = HeatRecMassFlowRate * CpHeatRec * (HeatRecOutletTemp - HeatRecInletTemp);
    3950              :             }
    3951              :         } else {
    3952            1 :             HeatRecOutletTemp = HeatRecInletTemp;
    3953            1 :             QHeatRec = 0.0;
    3954              :         }
    3955              : 
    3956            3 :         PlantUtilities::SafeCopyPlantNode(state, HeatRecInNode, HeatRecOutNode);
    3957              :         // changed outputs
    3958            3 :         state.dataLoopNodes->Node(HeatRecOutNode).Temp = HeatRecOutletTemp;
    3959              : 
    3960            3 :         mshp.HeatRecoveryRate = QHeatRec;
    3961            3 :         mshp.HeatRecoveryInletTemp = HeatRecInletTemp;
    3962            3 :         mshp.HeatRecoveryOutletTemp = HeatRecOutletTemp;
    3963            3 :         mshp.HeatRecoveryMassFlowRate = HeatRecMassFlowRate;
    3964            3 :     }
    3965              : 
    3966           60 :     void SetAverageAirFlow(EnergyPlusData &state,
    3967              :                            int const MSHeatPumpNum,                     // Unit index
    3968              :                            Real64 const PartLoadRatio,                  // unit part load ratio
    3969              :                            Real64 &OnOffAirFlowRatio,                   // ratio of compressor ON airflow to average airflow over timestep
    3970              :                            ObjexxFCL::Optional_int_const SpeedNum,      // Speed number
    3971              :                            ObjexxFCL::Optional<Real64 const> SpeedRatio // Speed ratio
    3972              :     )
    3973              :     {
    3974              : 
    3975              :         // SUBROUTINE INFORMATION:
    3976              :         //       AUTHOR         Lixing
    3977              :         //       DATE WRITTEN   June 2007
    3978              :         //       RE-ENGINEERED  Resived to meet requirements of multispeed heat pump based on the same subroutine
    3979              :         //                      in PTHP module
    3980              : 
    3981              :         // PURPOSE OF THIS SUBROUTINE:
    3982              :         // Set the average air mass flow rates using the part load fraction of the heat pump for this time step
    3983              :         // Set OnOffAirFlowRatio to be used by DX coils
    3984              : 
    3985              :         // Using/Aliasing
    3986           60 :         auto &MSHPMassFlowRateHigh = state.dataHVACGlobal->MSHPMassFlowRateHigh;
    3987           60 :         auto &MSHPMassFlowRateLow = state.dataHVACGlobal->MSHPMassFlowRateLow;
    3988              : 
    3989              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3990              :         int InletNode;              // inlet node number for PTHPNum
    3991              :         Real64 AverageUnitMassFlow; // average supply air mass flow rate over time step
    3992              : 
    3993           60 :         MSHPMassFlowRateLow = 0.0;  // Mass flow rate at low speed
    3994           60 :         MSHPMassFlowRateHigh = 0.0; // Mass flow rate at high speed
    3995              : 
    3996          120 :         if (!state.dataZoneEnergyDemand->CurDeadBandOrSetback(state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).ControlZoneNum) &&
    3997           60 :             present(SpeedNum)) {
    3998           58 :             if (state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatCoolMode == ModeOfOperation::HeatingMode) {
    3999           31 :                 if (SpeedNum == 1) {
    4000           21 :                     state.dataHVACMultiSpdHP->CompOnMassFlow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(SpeedNum);
    4001           21 :                     state.dataHVACMultiSpdHP->CompOnFlowRatio = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatingSpeedRatio(SpeedNum);
    4002           21 :                     MSHPMassFlowRateLow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(1);
    4003           21 :                     MSHPMassFlowRateHigh = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(1);
    4004           10 :                 } else if (SpeedNum > 1) {
    4005           20 :                     state.dataHVACMultiSpdHP->CompOnMassFlow =
    4006           10 :                         SpeedRatio * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(SpeedNum) +
    4007           10 :                         (1.0 - SpeedRatio) * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(SpeedNum - 1);
    4008           20 :                     state.dataHVACMultiSpdHP->CompOnFlowRatio =
    4009           10 :                         SpeedRatio * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatingSpeedRatio(SpeedNum) +
    4010           10 :                         (1.0 - SpeedRatio) * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatingSpeedRatio(SpeedNum - 1);
    4011           10 :                     MSHPMassFlowRateLow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(SpeedNum - 1);
    4012           10 :                     MSHPMassFlowRateHigh = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(SpeedNum);
    4013              :                 }
    4014           27 :             } else if (state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatCoolMode == ModeOfOperation::CoolingMode) {
    4015           27 :                 if (SpeedNum == 1) {
    4016           23 :                     state.dataHVACMultiSpdHP->CompOnMassFlow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(SpeedNum);
    4017           23 :                     state.dataHVACMultiSpdHP->CompOnFlowRatio = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolingSpeedRatio(SpeedNum);
    4018           23 :                     MSHPMassFlowRateLow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(1);
    4019           23 :                     MSHPMassFlowRateHigh = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(1);
    4020            4 :                 } else if (SpeedNum > 1) {
    4021            8 :                     state.dataHVACMultiSpdHP->CompOnMassFlow =
    4022            4 :                         SpeedRatio * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(SpeedNum) +
    4023            4 :                         (1.0 - SpeedRatio) * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(SpeedNum - 1);
    4024            8 :                     state.dataHVACMultiSpdHP->CompOnFlowRatio =
    4025            4 :                         SpeedRatio * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolingSpeedRatio(SpeedNum) +
    4026            4 :                         (1.0 - SpeedRatio) * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolingSpeedRatio(SpeedNum - 1);
    4027            4 :                     MSHPMassFlowRateLow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(SpeedNum - 1);
    4028            4 :                     MSHPMassFlowRateHigh = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(SpeedNum);
    4029              :                 }
    4030              :             }
    4031              :         }
    4032           60 :         InletNode = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).AirInletNodeNum;
    4033              : 
    4034              :         // Set up fan flow rate during compressor off time
    4035           60 :         if (state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).fanOp == HVAC::FanOp::Continuous && present(SpeedNum)) {
    4036           58 :             if (state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).AirFlowControl == AirflowControl::UseCompressorOnFlow &&
    4037            0 :                 state.dataHVACMultiSpdHP->CompOnMassFlow > 0.0) {
    4038            0 :                 if (state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).LastMode == ModeOfOperation::HeatingMode) {
    4039            0 :                     state.dataHVACMultiSpdHP->CompOffMassFlow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(SpeedNum);
    4040            0 :                     state.dataHVACMultiSpdHP->CompOffFlowRatio = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatingSpeedRatio(SpeedNum);
    4041              :                 } else {
    4042            0 :                     state.dataHVACMultiSpdHP->CompOffMassFlow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(SpeedNum);
    4043            0 :                     state.dataHVACMultiSpdHP->CompOffFlowRatio = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolingSpeedRatio(SpeedNum);
    4044              :                 }
    4045              :             }
    4046              :         }
    4047              : 
    4048           60 :         if (present(SpeedNum)) {
    4049           58 :             if (SpeedNum > 1) {
    4050           14 :                 AverageUnitMassFlow = state.dataHVACMultiSpdHP->CompOnMassFlow;
    4051           14 :                 state.dataHVACMultiSpdHP->FanSpeedRatio = state.dataHVACMultiSpdHP->CompOnFlowRatio;
    4052              :             } else {
    4053           44 :                 AverageUnitMassFlow =
    4054           44 :                     (PartLoadRatio * state.dataHVACMultiSpdHP->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataHVACMultiSpdHP->CompOffMassFlow);
    4055           44 :                 if (state.dataHVACMultiSpdHP->CompOffFlowRatio > 0.0) {
    4056           88 :                     state.dataHVACMultiSpdHP->FanSpeedRatio = (PartLoadRatio * state.dataHVACMultiSpdHP->CompOnFlowRatio) +
    4057           44 :                                                               ((1 - PartLoadRatio) * state.dataHVACMultiSpdHP->CompOffFlowRatio);
    4058              :                 } else {
    4059            0 :                     state.dataHVACMultiSpdHP->FanSpeedRatio = state.dataHVACMultiSpdHP->CompOnFlowRatio;
    4060              :                 }
    4061              :             }
    4062              :         } else {
    4063            2 :             AverageUnitMassFlow =
    4064            2 :                 (PartLoadRatio * state.dataHVACMultiSpdHP->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataHVACMultiSpdHP->CompOffMassFlow);
    4065            2 :             if (state.dataHVACMultiSpdHP->CompOffFlowRatio > 0.0) {
    4066            2 :                 state.dataHVACMultiSpdHP->FanSpeedRatio =
    4067            2 :                     (PartLoadRatio * state.dataHVACMultiSpdHP->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataHVACMultiSpdHP->CompOffFlowRatio);
    4068              :             } else {
    4069            0 :                 state.dataHVACMultiSpdHP->FanSpeedRatio = state.dataHVACMultiSpdHP->CompOnFlowRatio;
    4070              :             }
    4071              :         }
    4072              : 
    4073              :         //!!LKL Discrepancy with > 0
    4074           60 :         if (state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).availSched->getCurrentVal() == 0.0) {
    4075            0 :             state.dataLoopNodes->Node(InletNode).MassFlowRate = 0.0;
    4076            0 :             OnOffAirFlowRatio = 0.0;
    4077              :         } else {
    4078           60 :             state.dataLoopNodes->Node(InletNode).MassFlowRate = AverageUnitMassFlow;
    4079           60 :             state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = AverageUnitMassFlow;
    4080           60 :             if (AverageUnitMassFlow > 0.0) {
    4081           60 :                 OnOffAirFlowRatio = state.dataHVACMultiSpdHP->CompOnMassFlow / AverageUnitMassFlow;
    4082              :             } else {
    4083            0 :                 OnOffAirFlowRatio = 0.0;
    4084              :             }
    4085              :         }
    4086           60 :     }
    4087              : 
    4088           58 :     void CalcNonDXHeatingCoils(EnergyPlusData &state,
    4089              :                                int const MSHeatPumpNum,       // multispeed heatpump index
    4090              :                                bool const FirstHVACIteration, // flag for first HVAC iteration in the time step
    4091              :                                Real64 const HeatingLoad,      // supplemental coil load to be met by unit (watts)
    4092              :                                HVAC::FanOp const fanOp,       // fan operation mode
    4093              :                                Real64 &HeatCoilLoadmet,       // Heating Load Met
    4094              :                                ObjexxFCL::Optional<Real64 const> PartLoadFrac)
    4095              :     {
    4096              : 
    4097              :         // SUBROUTINE INFORMATION:
    4098              :         //       AUTHOR         Bereket Nigusse, FSEC/UCF
    4099              :         //       DATE WRITTEN   January 2012
    4100              : 
    4101              :         // PURPOSE OF THIS SUBROUTINE:
    4102              :         // This subroutine simulates the four non dx heating coil types: Gas, Electric, hot water and steam.
    4103              : 
    4104              :         // METHODOLOGY EMPLOYED:
    4105              :         // Simply calls the different heating coil component.  The hot water flow rate matching the coil load
    4106              :         // is calculated iteratively.
    4107              : 
    4108              :         // Locals
    4109              :         static constexpr std::string_view CurrentModuleObject("AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed");
    4110              : 
    4111              :         // SUBROUTINE PARAMETER DEFINITIONS:
    4112           58 :         Real64 constexpr ErrTolerance(0.001); // convergence limit for hotwater coil
    4113           58 :         int constexpr SolveMaxIter(50);
    4114              : 
    4115              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4116              :         Real64 QCoilActual;     // actual heating load met
    4117              :         Real64 mdot;            // heating coil steam or hot water mass flow rate
    4118              :         Real64 MinWaterFlow;    // coil minimum hot water mass flow rate, kg/s
    4119              :         Real64 MaxHotWaterFlow; // coil maximum hot water mass flow rate, kg/s
    4120              :         Real64 HotWaterMdot;    // actual hot water mass flow rate
    4121              : 
    4122              :         int HeatCoilType;
    4123              :         int HeatCoilNum;
    4124              :         Real64 MaxCoilFluidFlow;
    4125              :         Real64 SteamCoilHeatingLoad;
    4126              :         int CoilControlNode;
    4127              :         int CoilOutletNode;
    4128           58 :         PlantLocation plantLoc{};
    4129              : 
    4130           58 :         QCoilActual = 0.0;
    4131              : 
    4132           58 :         auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
    4133              : 
    4134           58 :         if (present(PartLoadFrac)) {
    4135            0 :             HeatCoilType = MSHeatPump.HeatCoilType;
    4136            0 :             state.dataHVACMultiSpdHP->HeatCoilName = MSHeatPump.HeatCoilName;
    4137            0 :             HeatCoilNum = MSHeatPump.HeatCoilNum;
    4138            0 :             MaxCoilFluidFlow = MSHeatPump.MaxCoilFluidFlow;
    4139            0 :             CoilControlNode = MSHeatPump.CoilControlNode;
    4140            0 :             CoilOutletNode = MSHeatPump.CoilOutletNode;
    4141            0 :             plantLoc = MSHeatPump.plantLoc;
    4142              :         } else {
    4143           58 :             HeatCoilType = MSHeatPump.SuppHeatCoilType;
    4144           58 :             state.dataHVACMultiSpdHP->HeatCoilName = MSHeatPump.SuppHeatCoilName;
    4145           58 :             HeatCoilNum = MSHeatPump.SuppHeatCoilNum;
    4146           58 :             MaxCoilFluidFlow = MSHeatPump.MaxSuppCoilFluidFlow;
    4147           58 :             CoilControlNode = MSHeatPump.SuppCoilControlNode;
    4148           58 :             CoilOutletNode = MSHeatPump.SuppCoilOutletNode;
    4149           58 :             plantLoc = MSHeatPump.SuppPlantLoc;
    4150              :         }
    4151              : 
    4152           58 :         MSHeatPump.HotWaterPlantLoc = plantLoc;
    4153           58 :         MSHeatPump.HotWaterCoilControlNode = CoilControlNode;
    4154           58 :         MSHeatPump.HotWaterCoilOutletNode = CoilOutletNode;
    4155           58 :         MSHeatPump.HotWaterCoilName = state.dataHVACMultiSpdHP->HeatCoilName;
    4156           58 :         MSHeatPump.HotWaterCoilNum = HeatCoilNum;
    4157              : 
    4158           58 :         if (HeatingLoad > HVAC::SmallLoad) {
    4159              : 
    4160            6 :             switch (HeatCoilType) {
    4161            6 :             case SuppHeatingCoilGas:
    4162              :             case SuppHeatingCoilElec: {
    4163           24 :                 HeatingCoils::SimulateHeatingCoilComponents(
    4164           18 :                     state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatingLoad, HeatCoilNum, QCoilActual, true, fanOp);
    4165            6 :             } break;
    4166            0 :             case HVAC::Coil_HeatingWater: {
    4167            0 :                 if (present(PartLoadFrac)) {
    4168            0 :                     MaxHotWaterFlow = MaxCoilFluidFlow * PartLoadFrac;
    4169            0 :                     PlantUtilities::SetComponentFlowRate(state, MaxHotWaterFlow, CoilControlNode, CoilOutletNode, plantLoc);
    4170            0 :                     WaterCoils::SimulateWaterCoilComponents(
    4171            0 :                         state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatCoilNum, QCoilActual, fanOp);
    4172              :                 } else {
    4173            0 :                     MaxHotWaterFlow = MaxCoilFluidFlow;
    4174            0 :                     PlantUtilities::SetComponentFlowRate(state, MaxHotWaterFlow, CoilControlNode, CoilOutletNode, plantLoc);
    4175            0 :                     WaterCoils::SimulateWaterCoilComponents(
    4176            0 :                         state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatCoilNum, QCoilActual, fanOp);
    4177            0 :                     if (QCoilActual > (HeatingLoad + HVAC::SmallLoad)) {
    4178              :                         // control water flow to obtain output matching HeatingLoad
    4179            0 :                         int SolFlag = 0;
    4180            0 :                         MinWaterFlow = 0.0;
    4181            0 :                         auto f = [&state, MSHeatPumpNum, FirstHVACIteration, HeatingLoad](Real64 const HWFlow) {
    4182              :                             // Calculates residual function (QCoilActual - SupHeatCoilLoad) / SupHeatCoilLoad
    4183              :                             // coil actual output depends on the hot water flow rate which is varied to minimize the residual.
    4184            0 :                             Real64 targetHeatingCoilLoad = HeatingLoad;
    4185            0 :                             Real64 calcHeatingCoilLoad = targetHeatingCoilLoad;
    4186            0 :                             Real64 mdot = HWFlow;
    4187            0 :                             auto &hp = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
    4188            0 :                             PlantUtilities::SetComponentFlowRate(
    4189            0 :                                 state, mdot, hp.HotWaterCoilControlNode, hp.HotWaterCoilOutletNode, hp.HotWaterPlantLoc);
    4190              :                             // simulate the hot water supplemental heating coil
    4191            0 :                             WaterCoils::SimulateWaterCoilComponents(
    4192            0 :                                 state, hp.HotWaterCoilName, FirstHVACIteration, hp.HotWaterCoilNum, calcHeatingCoilLoad, hp.fanOp);
    4193            0 :                             if (targetHeatingCoilLoad != 0.0) {
    4194            0 :                                 return (calcHeatingCoilLoad - targetHeatingCoilLoad) / targetHeatingCoilLoad;
    4195              :                             } else { // Autodesk:Return Condition added to assure return value is set
    4196            0 :                                 return 0.0;
    4197              :                             }
    4198            0 :                         };
    4199            0 :                         General::SolveRoot(state, ErrTolerance, SolveMaxIter, SolFlag, HotWaterMdot, f, MinWaterFlow, MaxHotWaterFlow);
    4200            0 :                         if (SolFlag == -1) {
    4201            0 :                             if (MSHeatPump.HotWaterCoilMaxIterIndex == 0) {
    4202            0 :                                 ShowWarningMessage(state,
    4203            0 :                                                    format("CalcNonDXHeatingCoils: Hot water coil control failed for {}=\"{}\"",
    4204              :                                                           CurrentModuleObject,
    4205            0 :                                                           MSHeatPump.Name));
    4206            0 :                                 ShowContinueErrorTimeStamp(state, "");
    4207            0 :                                 ShowContinueError(state,
    4208            0 :                                                   format("  Iteration limit [{}] exceeded in calculating hot water mass flow rate", SolveMaxIter));
    4209              :                             }
    4210            0 :                             ShowRecurringWarningErrorAtEnd(
    4211              :                                 state,
    4212            0 :                                 format("CalcNonDXHeatingCoils: Hot water coil control failed (iteration limit [{}]) for {}=\"{}",
    4213              :                                        SolveMaxIter,
    4214              :                                        CurrentModuleObject,
    4215            0 :                                        MSHeatPump.Name),
    4216            0 :                                 MSHeatPump.HotWaterCoilMaxIterIndex);
    4217            0 :                         } else if (SolFlag == -2) {
    4218            0 :                             if (MSHeatPump.HotWaterCoilMaxIterIndex2 == 0) {
    4219            0 :                                 ShowWarningMessage(state,
    4220            0 :                                                    format("CalcNonDXHeatingCoils: Hot water coil control failed (maximum flow limits) for {}=\"{}\"",
    4221              :                                                           CurrentModuleObject,
    4222            0 :                                                           MSHeatPump.Name));
    4223            0 :                                 ShowContinueErrorTimeStamp(state, "");
    4224            0 :                                 ShowContinueError(state, "...Bad hot water maximum flow rate limits");
    4225            0 :                                 ShowContinueError(state, format("...Given minimum water flow rate={:.3R} kg/s", MinWaterFlow));
    4226            0 :                                 ShowContinueError(state, format("...Given maximum water flow rate={:.3R} kg/s", MaxHotWaterFlow));
    4227              :                             }
    4228            0 :                             ShowRecurringWarningErrorAtEnd(state,
    4229            0 :                                                            "CalcNonDXHeatingCoils: Hot water coil control failed (flow limits) for " +
    4230            0 :                                                                std::string{CurrentModuleObject} + "=\"" + MSHeatPump.Name + "\"",
    4231            0 :                                                            MSHeatPump.HotWaterCoilMaxIterIndex2,
    4232              :                                                            MaxHotWaterFlow,
    4233              :                                                            MinWaterFlow,
    4234              :                                                            _,
    4235              :                                                            "[kg/s]",
    4236              :                                                            "[kg/s]");
    4237              :                         }
    4238              :                         // simulate hot water supplemental heating coil
    4239            0 :                         WaterCoils::SimulateWaterCoilComponents(
    4240            0 :                             state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatCoilNum, QCoilActual, fanOp);
    4241              :                     }
    4242              :                 }
    4243            0 :             } break;
    4244            0 :             case HVAC::Coil_HeatingSteam: {
    4245            0 :                 if (present(PartLoadFrac)) {
    4246            0 :                     mdot = MSHeatPump.MaxCoilFluidFlow * PartLoadFrac;
    4247            0 :                     SteamCoilHeatingLoad = HeatingLoad * PartLoadFrac;
    4248              :                 } else {
    4249            0 :                     mdot = MSHeatPump.MaxCoilFluidFlow;
    4250            0 :                     SteamCoilHeatingLoad = HeatingLoad;
    4251              :                 }
    4252            0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, CoilControlNode, CoilOutletNode, plantLoc);
    4253              :                 // simulate steam supplemental heating coil
    4254            0 :                 SteamCoils::SimulateSteamCoilComponents(
    4255            0 :                     state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatCoilNum, SteamCoilHeatingLoad, QCoilActual, fanOp);
    4256            0 :             } break;
    4257            0 :             default:
    4258            0 :                 break;
    4259              :             }
    4260              : 
    4261              :         } else { // end of IF (HeatingLoad > SmallLoad) THEN
    4262              : 
    4263           52 :             switch (HeatCoilType) {
    4264           52 :             case SuppHeatingCoilGas:
    4265              :             case SuppHeatingCoilElec: {
    4266          208 :                 HeatingCoils::SimulateHeatingCoilComponents(
    4267          156 :                     state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatingLoad, HeatCoilNum, QCoilActual, true, fanOp);
    4268           52 :             } break;
    4269            0 :             case HVAC::Coil_HeatingWater: {
    4270            0 :                 mdot = 0.0;
    4271            0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, CoilControlNode, CoilOutletNode, plantLoc);
    4272            0 :                 WaterCoils::SimulateWaterCoilComponents(
    4273            0 :                     state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatCoilNum, QCoilActual, fanOp);
    4274            0 :             } break;
    4275            0 :             case HVAC::Coil_HeatingSteam: {
    4276            0 :                 mdot = 0.0;
    4277            0 :                 PlantUtilities::SetComponentFlowRate(state, mdot, CoilControlNode, CoilOutletNode, plantLoc);
    4278              :                 // simulate the steam supplemental heating coil
    4279            0 :                 SteamCoils::SimulateSteamCoilComponents(
    4280            0 :                     state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatCoilNum, HeatingLoad, QCoilActual, fanOp);
    4281            0 :             } break;
    4282            0 :             default:
    4283            0 :                 break;
    4284              :             }
    4285              :         }
    4286           58 :         HeatCoilLoadmet = QCoilActual;
    4287           58 :     }
    4288              : 
    4289              : } // namespace HVACMultiSpeedHeatPump
    4290              : 
    4291              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1