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

Generated by: LCOV version 2.0-1