LCOV - code coverage report
Current view: top level - EnergyPlus - HVACMultiSpeedHeatPump.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 1127 2217 50.8 %
Date: 2024-08-24 18:31:18 Functions: 17 19 89.5 %

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

Generated by: LCOV version 1.14